Merge branch '1.9.x'
diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000..249a851
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,22 @@
+# 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
+#
+#     https://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.
+
+github:
+  description: "Apache Ant is a Java-based build tool."
+  homepage: https://ant.apache.org/
+  labels:
+    - java
+    - build
+    - apache
diff --git a/.gitignore b/.gitignore
index 80d1425..2ad4e31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 *.snap
 .ant.properties
 .classpath
+.DS_Store
 .project
 .settings
 bin
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 79f94be..236b6dc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,7 +6,7 @@
 hear from you.
 
 Ant's primary code repository is the
-[git repository at Apache](https://git-wip-us.apache.org/repos/asf/ant.git)
+[git repository at Apache](https://gitbox.apache.org/repos/asf/ant.git)
 and we've also got a [github mirror](https://github.com/apache/ant/).
 
 There are two ways you can contribute, you can either use the
@@ -15,19 +15,32 @@
 use github issues, so if you are reporting a bug, please raise a
 [Bugzilla issue](https://issues.apache.org/bugzilla/).
 
-Before reporting a bug, please also review http://ant.apache.org/problems.html
+Before reporting a bug, please also review https://ant.apache.org/problems.html
 
-If you're planning to implement a new feature please discuss you're
+If you're planning to implement a new feature please discuss your
 changes on the
-[dev list](http://ant.apache.org/mail.html#Developer%20List:%20dev@ant.apache.org)
+[dev list](https://ant.apache.org/mail.html#Developer%20List:%20dev@ant.apache.org)
 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.
@@ -52,4 +65,4 @@
 + Alternatively push your changes to a topic branch in your fork of the repository.
   + Submit a pull request to the repository in the apache organization.
 
-[cla]:http://www.apache.org/licenses/#clas
+[cla]:https://www.apache.org/licenses/#clas
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index c51db08..708f503 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -2,9 +2,14 @@
 
 Adam Blinkinsop
 Adam Bryzak
+Adam Murdoch
+Adam Retter
 Adam Sotona
 Adrian Nistor
+Adrien Grand
 Aleksandr Ishutin
+Aleksei Zotov
+Alex
 Alex Rosen
 Alexander Grund
 Alexei Yudichev
@@ -28,17 +33,22 @@
 Antoine Baudoux
 Antoine Levy-Lambert
 Anton Mazkovoi
+Arcadius Ahouansou
 Arjan Veenstra
 Arnaud Vandyck
 Arnout J. Kuiper
+Arturo Bernal
+Arun Jamwal
 Aslak Hellesôy
 Atsuhiko Yamanaka
 Avik Sengupta
 Balazs Fejes 2
+barney2k7
 Bart Vanhaute
-Benjamin Burgess
+Basil Crow
 Ben Galbraith
 Ben Gertzfield
+Benjamin Burgess
 Benoit Moussaud
 Bernd Dutkowski
 Bernhard Rosenkraenzer
@@ -50,6 +60,7 @@
 Brian Repko
 Bruce Atherton
 Cedomir Igaly
+Charles Duffy
 Charles Hudak
 Charlie Hubbard
 Chris Hegarty
@@ -66,9 +77,11 @@
 Clement OUDOT
 Clive Brettingham-Moore
 Conor MacNeill
+Costin Manolache
 Craeg Strong
 Craig Cottingham
 Craig R. McClanahan
+Craig Pell
 Craig Richardson
 Craig Ryan
 Craig Sandvik
@@ -87,6 +100,7 @@
 Danno Ferrin
 Danny Yates
 Dante Briones
+Darrell DeBoer
 Davanum Srinivas
 Dave Brondsema
 Dave Brosius
@@ -107,10 +121,11 @@
 dIon Gillard
 Dmitry A. Kuminov
 Dominique Devienne
-Donal Quinlan
 Don Brown
 Don Ferguson
 Don Jeffery
+Donal Quinlan
+Donald Leslie
 Drew Sudell
 Earl Hood
 Edison Guo
@@ -118,7 +133,9 @@
 Edwin Woudt
 Eli Tucker
 Emmanuel Bourg
+Eugène Adell
 Eric Barboni
+Eric Delaunay
 Eric Olsen
 Eric Pugh
 Erik Costlow
@@ -130,9 +147,10 @@
 Frank Harnack
 Frank Somers
 Frank Zeyda
-Frantisek Kucera
-Frederic Bothamy
+František Kučera
+Frédéric Bothamy
 Frederic Lavigne
+Gal Shachor
 Gary S. Weaver
 Gautam Guliani
 Gene-Sung Chung
@@ -145,6 +163,7 @@
 Gilles Scokart
 Glenn McAllister
 Glenn Twiggs
+Gösen
 Greg Nelson
 Greg Roodt
 Greg Schueler
@@ -152,6 +171,7 @@
 Günther Kögel
 Harish Prabandham
 Haroon Rafique
+Helder Pereira
 Hiroaki Nakamura
 Holger Engels
 Holger Joest
@@ -163,9 +183,12 @@
 Issa Gorissen
 Ivan Ivanov
 J Bleijenbergh
+JC Mann
 Jack J. Woehr
+Jacobus Martinus Kruithof
 Jaikiran Pai
 James Duncan Davidson
+James Todd
 Jan Cumps
 Jan Matèrne
 Jan Mynarik
@@ -177,8 +200,6 @@
 Jay Dickon Glanville
 Jay Peck
 Jay van der Meer
-JC Mann
-J D Glanville
 Jean-Francois Brousseau
 Jean-Louis Boudart
 Jeff Gettle
@@ -193,21 +214,24 @@
 Jesse Stockall
 Jim Allers
 Jimmy Casey
-Joerg Wassmer
 Joel Tucci
+Joerg Wassmer
 Joey Richey
 Johann Herunter
 John Elion
 John Sisson
 Jon Dickinson
-Jon S. Stevens
 Jon Skeet
+Jon S. Stevens
+Jonathan K. Schneider
 Jose Alberto Fernandez
 Joseph Walton
 Josh Lucas
 Juerg Wanner
 Julian Simpson
+Julien Lepiller
 Justin Vallon
+Justyna Horwat
 Karl Jansen
 Keiron Liddle
 Keith Visco
@@ -215,7 +239,7 @@
 Kevin Greiner
 Kevin Jackson
 Kevin Ross
-Kevin Z Grey
+Kevin Z. Grey
 Kim Hansen
 Kirk Wylie
 Kristian Rosenvold
@@ -232,12 +256,15 @@
 Maarten Coene
 Magesh Umasankar
 Maneesh Sahu
+Marc Guillemot
+Marc Strapetz
 Marcel Schutte
-Marcus Börger
+Marcus Börger
 Mario Frasca 
 Mariusz Nowostawski
 Mark A. Ziesemer
 Mark DeLaFranier
+Mark Harmer
 Mark Hecker
 Mark Niggemann
 Mark R. Diggory
@@ -261,9 +288,12 @@
 Matthew Hawthorne
 Matthew Inger
 Matthew Kuperus Heun
+Matthew Warman
 Matthew Watson
 Matthew Yanos
 Matthias Bhend
+Matthias Gutheil
+Matthias Johann Vill
 Michael Bayne
 Michael Clarke
 Michael Davey
@@ -271,32 +301,37 @@
 Michael McCallum
 Michael Montuori
 Michael Newcomb
-Micheal Nygard
+Michael Nygard
 Michael Saunders
+Michael Seele
+Mickaël Guessant
 Miha
 Mike Davis
 Mike Roberts
 Mike Williams
+Mikolaj Izdebski
 Miroslav Zaťko
-mnowostawski
 Mounir El Hajj
 Nathan Beyer
 Nick Chalko
-Nick Fortescue
 Nick Crossley
+Nick Davis
+Nick Fortescue
+Nick King
 Nick Pellow
-Nicola Ken Barozzi
 Nico Seessle
+Nicola Ken Barozzi
+Nicolas Lalevée
 Nigel Magnay
 Oliver Merkel
 Oliver Rossmueller
-Ondra Medek
+Olivier Parent
 Omer Shapira
-Oystein Gisnas
+Ondra Medek
 Patrick Altaie
 Patrick C. Beard
 Patrick Chanezon
-Patrick G. Heck (Gus Heck)
+Patrick Gus Heck
 Patrick Martin
 Paul Austin
 Paul Christmann
@@ -305,7 +340,7 @@
 Paulo Gaspar
 Pavan Bayyapu
 Pavel Jisl
-Pawel Zuzelski
+Paweł Zuzelski
 Peter B. West
 Peter Donald
 Peter Doornbosch
@@ -318,13 +353,13 @@
 Phillip Wells
 Pierre Delisle
 Pierre Dittgen
-riasol
-R Handerson
+Preston Bannister
 Ralf Hergert
 Rami Ojares
 Randy Watler
 Raphael Pierquin
 Ray Waldin
+Razzi Abuissa
 Reinhard Pointner
 Remie Bolte
 René Krell
@@ -332,8 +367,11 @@
 Richard Evans
 Richard Steele
 Rick Beton
+Rob Oxspring
+Rob van Oostrum
+Rob Riasol
 Robbie Gibson
-Robert Anderson
+Robert H. Anderson
 Robert Clark
 Robert Flaherty
 Robert Shaw
@@ -343,8 +381,6 @@
 Robin Green
 Robin Power
 Robin Verduijn
-Rob Oxspring
-Rob van Oostrum
 Rodrigo Schmidt
 Roger Vaughn
 Roman Ivashin
@@ -354,24 +390,27 @@
 Ryan Bennitt
 Sam Ruby
 Sandra Metz
+Santosh R. Dhariwal
 Scott Carlson
 Scott Ellsworth
 Scott Johnson
 Scott M. Stirling
 Sean Egan
 Sean P. Kane
+Sebastian Kantha
 Sebastien Arod
 Shiraz Kanga
-Sebastian Kantha
+Simeon Fitch
 Simon Law
+Simon Legner
 Simone Bordet
 Stefan Bodewig
 Stefan Heimann
 Stefano Mazzocchi
-Stephan Strittmatter
-Stephane Bailliez
 stephan
 Stephan Michels
+Stephan Strittmatter
+Stephane Bailliez
 Stephen Chin
 Stephen Goetze
 Steve Cohen
@@ -385,6 +424,7 @@
 TAMURA Kent
 Taoufik Romdhane
 Tariq Master
+Taylor Smock
 Thomas Aglassinger
 Thomas Butz
 Thomas Christen
@@ -398,6 +438,7 @@
 Tim Whittington
 Timoteo Ohara
 Timothy Gerard Endres
+TJ Rothwell
 Tom Ball
 Tom Brus
 Tom Cunningham
@@ -406,18 +447,22 @@
 Tom May
 Tomasz Bech
 Tomáš Zezula
+Tony Gravagno
 Trejkaz Xaoza
 Ulrich Schmidt
 Uwe Schindler
 Valentino Miazzo
 Victor Toni
+Ville Skyttä
 Vimil Saju
 Vincent Legoll
 Vincent Privat
 Vitold Sedyshev
+Vladislav Bauer
 Volker Leidl
 Waldek Herka
 Wang Weijun
+Wenjing Wang
 Will Wang
 William Bernardet
 William Ferguson
@@ -429,8 +474,10 @@
 Wolfgang Werner
 Xavier Hanin
 Xavier Witdouck
+Xia Li
 Yohann Roussel
 Yuji Yamano
 Yves Martin
 Zach Garner
 Zdenek Wagner
+Øystein Gisnås
diff --git a/INSTALL b/INSTALL
index 83c1167..289e5b8 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,2 +1,2 @@
-For installation instructions see the manual in the docs subdirectory
-or online at <http://ant.apache.org/manual/index.html>.
+For installation instructions see the manual by opening manual/index.html
+or see it online at <https://ant.apache.org/manual/index.html>.
diff --git a/LICENSE b/LICENSE
index cdf6ff8..5cfe309 100644
--- a/LICENSE
+++ b/LICENSE
@@ -193,7 +193,7 @@
  *   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
+ *       https://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,
@@ -203,7 +203,7 @@
  */
 
 W3C® SOFTWARE NOTICE AND LICENSE
-http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+https://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
 
 This work (and included software, documentation such as READMEs, or other
 related items) is being provided by the copyright holders under the following
diff --git a/NOTICE b/NOTICE
index 0895151..298879d 100644
--- a/NOTICE
+++ b/NOTICE
@@ -2,7 +2,7 @@
 Copyright 1999-2022 The Apache Software Foundation
 
 This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
+The Apache Software Foundation (https://www.apache.org/).
 
 The <sync> task is based on code Copyright (c) 2002, Landmark
 Graphics Corp that has been kindly donated to the Apache Software
diff --git a/README b/README
index 9510941..cff7e89 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 
-                                 A     N     T
+                                 Apache Ant
  
 
   What is it? 
@@ -46,16 +46,19 @@
   ------------------
 
   Details of the latest version can be found on the Apache Ant
-  Project web site <http://ant.apache.org/>.
+  Project web site <https://ant.apache.org/>.
 
 
   Documentation
   -------------
 
-  Documentation is available in HTML format, in the docs/ directory.
+  Documentation is available in HTML format, in the manual/ directory.
   For information about building and installing Ant, see
-  docs/manual/index.html
-
+  manual/install.html
+  The manual for the latest release of Ant is available online at
+  <https://ant.apache.org/manual/index.html>.
+  The latest version of the manual is available online at
+  <https://rawgit.com/apache/ant/master/manual/index.html>.
 
   Licensing
   ---------
@@ -69,7 +72,7 @@
   encryption software.  BEFORE using any encryption software, please 
   check your country's laws, regulations and policies concerning the
   import, possession, or use, and re-export of encryption software, to 
-  see if this is permitted.  See <http://www.wassenaar.org/> for more
+  see if this is permitted.  See <https://www.wassenaar.org/> for more
   information.
 
   The U.S. Government Department of Commerce, Bureau of Industry and
@@ -88,10 +91,10 @@
   For the SSH family of tasks (<sshexec> and <scp>) Ant requires the
   JSch <http://www.jcraft.com/jsch/index.html> library as well as the
   Java Cryptography extensions
-  <http://java.sun.com/javase/technologies/security/>.  Ant does not
+  <https://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html>.  Ant does not
   include these libraries itself, but is designed to use them.
 
   Thanks for using Ant.
 
                                           The Apache Ant Project
-                                         <http://ant.apache.org/>
+                                         <https://ant.apache.org/>
diff --git a/ReleaseInstructions b/ReleaseInstructions
index ff494b6..c16245e 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
@@ -42,6 +43,10 @@
     the right year and commit and push the change upstream, before
     starting any release process.
 
+    There are certain features that require JDK 9+ version to be used
+    while releasing Ant 1.10.x from master branch. Make sure JAVA_HOME
+    points to a JDK installation which is minimally Java 9.
+
     You will need to have the snapcraft CLI tool installed in order to
     create and publish snap archives. See
     https://docs.snapcraft.io/snapcraft-overview
@@ -51,9 +56,9 @@
 3.  We don't want tags for failed votes to end up on our 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
@@ -68,7 +73,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.
 
@@ -81,6 +86,14 @@
 6.  Next bootstrap, build and run the tests.
 
     $ ./bootstrap.sh
+
+    Make sure the log messages doesn't contain the message:
+
+    "Java 9+ features won't be available in the distribution"
+
+    If it does, then it's a sign that JAVA_HOME isn't pointing to a JDK 9+ version.
+    Fix JAVA_HOME to point to a valid JDK 9+ version and redo the release steps.
+
     $ ./build.sh
     $ ./build.sh test
     # if you've got maven installed
@@ -95,11 +108,12 @@
     $ ./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 commit -m "Prepare for RC1 of version 1.10.0 of Ant" ./
+    $ git tag -s -m "Tagging RC1 for version 1.10.0 of Ant" ANT_1.10.0_RC1
     $ git push --tags
 
 9.  Ensure that the GPG key you use is inside the KEYS file in Ant's
@@ -143,7 +157,7 @@
 
     b. Using gpg
 
-    $ for i in distribution/*/*.zip distribution/*/*.gz distribution/*/*.bz2; do gpg --use-agent --detach-sign --armor $i; done
+    $ for i in distribution/*/*.zip distribution/*/*.gz distribution/*/*.bz2 distribution/*/*.xz; do gpg --use-agent --detach-sign --armor $i; done
     $ for i in java-repository/org/apache/ant/ant*/*/*.jar java-repository/org/apache/ant/ant*/*/*.pom; do gpg --use-agent --detach-sign --armor $i; done
 
 11. Convert the part of the WHATSNEW file covering the changes
@@ -157,12 +171,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 contents of RELEASE-NOTES-1.9.7.html also into README.html
+    Copy the contents of RELEASE-NOTES-1.10.0.html also into 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
@@ -201,9 +215,9 @@
 
       $ snapcraft clean
       $ snapcraft snap
-      $ snapcraft upload --release=1.9/candidate ant_*.snap
+      $ snapcraft upload --release=candidate ant_*.snap
 
-    This will publish the new release snap to the 1.9 track on the
+    This will publish the new release snap to the latest track on the
     candidate risk level. It will be moved to stable, once the vote
     has passed.
 
@@ -220,9 +234,13 @@
 16. If the vote fails, address the problems and recreate the next RC
     build.
 
-17. Once the vote has passed, tag the last RC created with the final tag
+17. Once the vote has passed, tag the last RC created with the final tag.
+    It is important to tag the release under the "rel/" path since the
+    Apache infrastructure for .git provides certain protections for tags
+    under the "rel/" path. Releases need such protections as per Apache
+    release guidelines.
 
-    $ 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
 
 18. The distrib artifacts should be published the apache dist. It is
@@ -250,36 +268,40 @@
     https://reporter.apache.org/addrelease.html?ant
 
 20. 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.
 
 21. Add a new release tag to doap_Ant.rdf in Ant's site.
 
-22. checkout the 1.9.x branch, merge the tag but don't push the
+22. checkout the master branch, merge the tag but don't push the
     commit
 
-    $ git checkout 1.9.x
-    $ git merge rel/1.9.7
+    [if a release of Ant 1.9.x happened at the same time, deal with
+    the 1.9.x tag on the 1.9.x branch first and merge the 1.9.x branch
+    to master before proceeding here]
+
+    $ 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.
 
@@ -295,22 +317,20 @@
     $ git commit -a --amend
     $ git push
 
-22. checkout the master branch, merge the 1.9.x branch
-
-    $ git checkout master
-    $ git merge 1.9.x
-    $ git push
-
-24. copy the candidate snaps to stable. First figure out the revision
+23. copy the candidate snaps to stable. First figure out the revision
 
     $ snapcraft status ant
-    $ snapcraft release ant REVISION 1.9/stable
+    $ snapcraft release ant REVISION latest/stable
+    $ snapcraft release ant REVISION 1.10/stable
 
-    where REVISION is the revision you want to promote
+    where REVISION is the revision you want to promote (keep in mind that the
+    REVISION isn't the version you are releasing. snapcraft uses its own separate integer
+    value for the REVISION and this value is listed as the output of the previous
+    "snapcraft status ant" command)
 
-25. wait a few hours for the mirrors to catch up
+24. wait a few hours for the mirrors to catch up
 
-26. Update the ant.apache.org site :
+25. Update the ant.apache.org site :
 
     The website is managed here: https://svn.apache.org/repos/asf/ant/site/ant/
 
@@ -318,6 +338,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)
@@ -332,17 +356,20 @@
     Commit the modified/generated files in the 'production' folder, it will go
     live on ant.apache.org in a matter on seconds.
 
-27. At this point in time, the release is done and announcements are made.
+26. 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.
 
-28. You can now reacquaint yourself with your family and friends.
+27. You can now reacquaint yourself with your family and friends.
 
-29. After a few days "svn rm" the older release artifacts and release
+28. 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
 
 https://www.apache.org/dev/#releases
@@ -359,7 +386,7 @@
    * ivy.xml in release subdirectory
    * WHATSNEW
    * src/etc/testcases/taskdefs/conditions/antversion.xml
-   * snap/snapcraft.yml
+   * snap/snapcraft.yaml
 
 cover.html, credits.html, POM files, antversion.xml should be 
 adjusted for the [newversion] right after the build and tagging 
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..c420962
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,3 @@
+# Security Policy
+
+Please see https://ant.apache.org/security.html
diff --git a/STATUS b/STATUS
index 874396d..8b6b710 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
@@ -17,7 +17,7 @@
     Repositories:       ant.git
 
 PMC Members
- see http://ant.apache.org/contributors.html
+ see https://ant.apache.org/contributors.html
 
 Committers:
- see http://ant.apache.org/contributors.html
+ see https://ant.apache.org/contributors.html
diff --git a/WHATSNEW b/WHATSNEW
index 487149a..8990ec2 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -1,8 +1,8 @@
-Changes from Ant 1.9.16 TO Ant 1.9.17
-=====================================
+Changes from Ant 1.10.12 TO Ant 1.10.13
+=======================================
 
 Changes that could break older environments:
---------------------------------------------
+-------------------------------------------
 
  * <get> has a new attribute authenticateOnRedirect that can be used to
    prevent Ant from sending the configured credentials when following a
@@ -13,65 +13,361 @@
 Fixed bugs:
 -----------
 
- * Made sure setting build.compiler to the fully qualified classname
-   that corresponds to extJavac or modern has the same effect as using
-   the shorter alias names.
-   Bugzilla Report 65539
+ * the PropertyEnumerator change introduced in 1.10.9 proved to be not
+   fully backwards compatible when combined with certain custom
+   PropertyHelper implementations - for example when using AntXtras.
+   Bugzilla Report 65799
+
+ * legacy-xml reporter of the junitlauncher task now escapes ]]> when writing CDATA.
+   Bugzilla Report 65833
 
  * <scp> may leak connections when trying to preserve the last modified
    timestamps of files transferred recursively from a server.
    Bugzilla Report 66001
 
- * Building Ant from source could result in the javadocs target failing if the
-   optional dependencies were missing. This has now been fixed.
-   Bugzilla Report 63438
-
+ * tstamp task would in certain cases parse the SOURCE_DATE_EPOCH environment variable
+   value to an incorrect date. This has now been fixed.
+   Github Pull Request #186
 
 Other changes:
 --------------
 
+ * added an implementation of the MIME Mail sender based on the
+   repackaged Jakarta Mail package rather than javax Mail.
+   Github Pull Request #161
+
+ * The "listener" element in the junitlauncher task now supports
+   an "extension" attribute to control the filename extension
+   of the generated output file from the listener.
+   Github Pull Request #168
+
+ * <ftp> now supports FTPs.
+   Github Pull Request #170
+
+ * DirectoryScanner avoids listing directory contents when it known it
+   will never use the information retrieved. This may improve
+   performance in some special cases.
+   Bugzilla Report 66048
+
+Changes from Ant 1.10.11 TO Ant 1.10.12
+=======================================
+
+Fixed bugs:
+-----------
+
+ * The http condition would follow redirects even when "followRedirects" attribute
+   was set to "false". This has now been fixed.
+   Bugzilla Report 65489
+
+ * Made sure setting build.compiler to the fully qualified classname
+   that corresponds to extJavac or modern has the same effect as using
+   the shorter alias names.
+   Bugzilla Report 65539
+
+ * Prevent potential deadlocks in org.apache.tools.ant.IntrospectionHelper.
+   Bugzilla Report 65424
+
+Other changes:
+--------------
+
+ * The implementation of AntClassLoader#findResources() has been changed to optimize
+   it for potential performance issues, as those noted at
+   https://issues.jenkins.io/browse/JENKINS-22310?focusedCommentId=197405&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-197405
+   Github Pull Request #151
+
+ * AntClassLoader now implements the ClassLoader#findResource(String) method.
+   Github Pull Request #150
+
+ * Ant tries to avoid file name canonicalization when possible.
+   Bugzilla Report 65499
+
+ * javadoc task will now look for warning messages in the STDERR stream too
+   when "failonwarning" is set to true to account for changes in JDK 17+
+
  * The tar task now preserves symlinks of nested tarfilesets.
    Github Pull Request #142
 
-Changes from Ant 1.9.15 TO Ant 1.9.16
-=====================================
+Changes from Ant 1.10.10 TO Ant 1.10.11
+=======================================
+
+Fixed bugs:
+-----------
+
+ * a race condition could lead to NullPointerExceptions when running
+   tasks in parallel.
+   Bugzilla Report 65316
+
+ * fixed potential OutOfMemory errors when reading broken archives
+   using the tar or zip formats or formats derived from zip.
 
 Other changes:
 --------------
 
+ * org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask now
+   has a new protected createExecuteWatchdog() method for allowing it to be overriden.
+   Github Pull Request #147
+
  * Upgraded AntUnit to 1.4.1.
 
+
+Changes from Ant 1.10.9 TO Ant 1.10.10
+======================================
+
 Fixed bugs:
 -----------
 
+ * SCP (with sftp=true) task would fail if fetching file located in root directory
+   Bugzilla Report 64742
+
+ * javac task would fail if the arguments file it (internally) created didn't quote
+   the # character. This has now been fixed.
+   Bugzilla Reports 64912, 64790
+
+ * made sure LegacyXmlResultFormatter encodes characters illegal in
+   XML the same way JUnit5's built-in formatter would.
+   Bugzilla Report 65030
+
+ * LegacyXmlResultFormatter no longer double-encodes <>& in system-err
+   and system-out
+   Bugzilla Report 63436
+
+ * Fixes a bug in junitlauncher task's legacy-xml formatter, where the testcase
+   representing a @Parameterized JUnit4 test wasn't being reported in the XML.
+   Bugzilla Report 64952
+
  * Fixes a bug where the ant-testutil-sources.jar that gets published to Maven
    central repository didn't contain any source files.
    Bugzilla Report 65110
 
- * fixed potential OutOfMemory errors when reading broken archives
-   using the tar or zip formats or formats derived from zip.
+ * The <http> condition didn't follow redirects from http to https.
+   Bugzilla Report 65105
 
-Changes from Ant 1.9.14 TO Ant 1.9.15
-=====================================
+ * ZipOutputStream now overrides write(int) in order to make sure
+   single byte writes get the same treatment as array writes.
+   Github Pull Request #145
+
+ * Fixes a potential deadlock in junitlauncher task when using legacy-xml
+   reporter.
+   Bugzilla Report 64733
 
 Other changes:
 --------------
 
+ * javaversion condition now has a new "atmost" attribute. See the javaversion
+   manual for more details
+
+ * The "listener" nested element of the "junitlauncher" task now has a new
+   "useLegacyReportingName" attribute which can be used to control the test
+   identifiers names that get reported by the listener. See the junitlauncher
+   manual for more details.
+   Note that this change also introduces a new "setUseLegacyReportingName" method
+   on the org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter
+   interface. This will break backward compatibility with any of your custom
+   result formatters which implemented this interface and such implementations
+   are now expected to implement this new method.
+
+ * a new attribute preserveduplicates allows <resourcelist> to return
+   the same resource multiple times when set to true.
+   Bugzilla Report 64854
+
+ * a new attribute filterbeforeconcat in <concat> can be used to
+   decide whether the filterchain should be applied to the
+   concatenated content (the default) or each nested resource
+   individually before concatenating them.
+   Bugzilla Report 64855
+
+ * the ssh tasks now share a new nested element additionalConfig that
+   can be used to set config values for the jsch Session used by the
+   task.
+   Bugzilla Report 65089
+
+ * added new discardOutput and discardError properties to redirector
+   and the exec, apply and java tasks which can be used to completely
+   discard any (error) output. This is a platform independent
+   alternative to directiong output to any kind of null device.
+
+ * junitlauncher now prints a more useful and instantaneous summary of
+   tests being run, closely matching the junit task's summary.
+   Bugzilla Report 64836
+
+Changes from Ant 1.10.8 TO Ant 1.10.9
+=====================================
+
+Fixed bugs:
+-----------
+
+ * the ftp task could throw a NullPointerException if an error occured
+   Bugzilla Report 64438
+
+ * propertyset now also sees in-scope local properties
+   Bugzilla Report 50179
+
+ * replaced our version of ReaderInputStream with the battle-tested
+   version of Apache Commons IO as our version had problems with
+   surrogate pairs (and likely other edge cases as well).
+   Bugzilla Report 40455
+
+ * <fixcrlf> will no longer remove the temporary file it just created
+   before writing to it.
+
+ * <sshexec> and <scp> didn't deal with wildcard hostnames in ssh
+   config files properly.
+   Bugzilla Report 64530
+
+Other changes:
+--------------
+
+ * Ant will no longer log a warning if it doesn't find tools.jar
+   Bugzilla Report 63577
+
+ * the <jar> task accepts now a nested <indexjarsmapper> element
+   that can be used to perform custom filename transformations
+   for the <indexjars> archives.
+   Github Pull Request #134
+
+ * added a new PropertyEnumerator interface that extensions can
+   provide if they are managing properties unknown to the Ant project.
+
+ * added some special code to support GraalVM JavaScript as
+   javax.script scripting engine for JavaScript. In particular we
+   relax some security settings of GraalVM so that scripts can access
+   Ant objects.
+
+   Also Ant enables Nashorn compatibility mode by default, you can
+   disable that by setting the magic Ant property
+   ant.disable.graal.nashorn.compat to true.
+
+   See the script task manual for additional details.
+
+ * If the magic property ant.tmpdir hasn't been set and Ant can
+   control the permissions of directories it creates it will create an
+   owner-owned temporary directory unaccessible to others as default
+   tempdir as soon as a temporary file is created for the first time,
+
+Changes from Ant 1.10.7 TO Ant 1.10.8
+=====================================
+
+Fixed bugs:
+-----------
+
+ * "legacy-xml" formatter of junitlauncher task wasn't writing out
+   the stacktrace for failures. This is now fixed.
+   Bugzilla Report 63827
+
+ * sshexec failed to write output to a file if the file didn't exist
+
+ * Fixes a regression in javac task involving command line argument
+   files.
+   Bugzilla Report 63874
+
+ * sshexec, sshsession and scp now support a new sshConfig parameter.
+   It specified the SSH configuration file (typically ${user.home}/.ssh/config)
+   defining the username and keyfile to be used per host.
+
+ * "legacy-xml" formatter of junitlauncher task wasn't writing out
+   exceptions that happen in @BeforeAll method of a test. This is now fixed.
+   Bugzilla Report 63850
+
+ * Building Ant from source could result in the javadocs target failing if the
+   optional dependencies were missing. This has now been fixed.
+   Bugzilla Report 63438
+
+ * Fixes a potential ConcurrentModificationException in XMLLogger.
+   Bugzilla Report 63921
+
+ * Fixes a bug in junitlauncher task in forked mode, where if a listener element
+   was used as a sibling element for either the test or testclasses element,
+   then the forked mode launch would fail.
+   Bugzilla Report 63958
+
+ * Fixes an issue in AntStructure where an incorrect DTD was being generated.
+   Github Pull Request #116
+
+ * Fixes an incorrect variable name usage in junit-frames-xalan1.xsl.
+   Github Pull Request #117
+
+Other changes:
+--------------
+
+ * org.apache.tools.mail.MailMessage will now send a fully qualified
+   domain name in its HELO message.
+   Github Pull Request #101
+
  * The runant.py script should now work with Python 3.
    Github Pull Request #96
 
+ * tstamp task now honors SOURCE_DATE_EPOCH environment variable for
+   reproducible builds (https://reproducible-builds.org/specs/source-date-epoch/#idm55)
+   Bugzilla Report 62617
+
  * rmic has been removed from Java 15. The task will now throw an
    exception if you try to use it while running Java 15 or newer.
 
  * a new property ant.tmpdir provides improved control over the
    location Ant uses to create temporary files
 
-Changes from Ant 1.9.13 TO Ant 1.9.14
+Changes from Ant 1.10.6 TO Ant 1.10.7
+=====================================
+
+Fixed bugs:
+-----------
+
+ * FTP still tries checking or entering directories after a timeout
+   Bugzilla Report 63454
+
+ * junitlauncher - does not detect failure in @BeforeAll
+   Bugzilla Report 63479
+
+ * Error using ant-1.10.6 with jdk8
+   Bugzilla Report 63457
+
+ * FTP task no longer duplicates a check for a file being a symlink.
+   Bugzilla Report 63259
+
+ * junitlauncher task, when used in fork mode with "<testclasses>",
+   used to create the wrong number of listeners per test class. This
+   has now been fixed.
+   Bugzilla Report 63446
+
+ * The "legacy-xml" junitlauncher task's listener would not include
+   @ParameterizedTest testcases in its XML report file. This has now
+   been fixed.
+   Bugzilla Report 63680
+
+Other changes:
+--------------
+
+ * FTP task timeout improvements.
+   Bugzilla Reports 63252 and 47414
+
+ * junitlauncher task now supports selecting test classes for execution,
+   based on the JUnit 5 tags, through the new "includeTags" and
+   "excludeTags" attributes.
+
+ * prefer https over http when building ant itself, and in the ant 
+   documentation and sources
+
+ * changed the references and Maven coordinates of JavaMail dependency
+   to Jakarta Mail and thus javax.mail to jakarta.mail - and upgraded
+   the dependency to 1.6.3.
+
+Changes from Ant 1.10.5 TO Ant 1.10.6
 =====================================
 
 Changes that could break older environments:
 -------------------------------------------
 
+ * image task no longer works on Java 9+ because internal classes
+   supporting Java Advanced Imaging are removed; imageio task (based on
+   ImageIO and AWT) is provided as a replacement.
+
+ * junitlauncher task has changed the class names and package names of
+   the task as well as some of the supporting classes of that task. If
+   any code depended on these class or package names, they will have to
+   be updated to reference these newly named classes. This however,
+   doesn't impact build scripts if their reference to junitlauncher task
+   was merely through the use of the <junitlauncher> element.
+
  * ClearCase#runS has been augmented by a two arg-version and the
    one-arg version will no longer be called. This may affect
    subclasses that have overridden runS.
@@ -83,6 +379,10 @@
    mail task.
    Bugzilla Report 62621
 
+ * Fixes an issue in junitreport task, which used to throw a
+   java.net.MalformedURLException when saxon was used on Windows OS.
+   Bugzilla Report 62594
+
  * augment task now throws a BuildException (as noted in its manual)
    instead of a IllegalStateException in the absence of the "id" attribute.
    Bugzilla Report 62655
@@ -91,10 +391,29 @@
    an incorrect compression level for a zip entry. This is now fixed.
    Bugzilla Report 62686
 
+ * sync task, in some cases on case insensitive file systems, would consider
+   a file in a destination directory to be orphaned and would delete it.
+   This task has now been fixed to infer the case sensitivity of the filesystem
+   of the destination directory.
+   Bugzilla Report 62890
+
+ * Fixes a potential java.util.ConcurrentModificationException in
+   org.apache.tools.ant.Project#getCopyOfReferences.
+   Github Pull Request #81
+
  * cccheckout would ignore an error of the "ls checkout" command even
    if failOnError was set to false.
    Bugzilla Report 63071
 
+ * The isreachable condition could in some cases return true even if the
+   actual address could potentially be unreachable. This is now fixed
+   and the resolved address is actually checked for reachability.
+
+ * Fixes an issue where scp transfer completion tracking wasn't being
+   triggered for 100% completion.
+   Github Pull Request #91
+
+
 Other changes:
 --------------
  * generatekey task now supports SubjectAlternativeName during key
@@ -103,6 +422,9 @@
  * the <modified> selector has a new built-in algorithm 'lastmodified'
    which computes a value based upon the lastmodified time of the file.
 
+ * junitlauncher task now supports running tests in a forked JVM. More
+   details available in the junitlauncher task manual.
+
  * signjar and verifyjar now support the -providerName, -providerClass
    and -providerArg command line options of keytool via new attributes.
    Bugzilla Report 65234
@@ -114,16 +436,38 @@
  * added several attributes to <javadoc> that support modules.
    Bugzilla Report 62424
 
+ * properties used or set by BuildFileTask/BuildFileRule are documented
+   in MagicTestNames. A new magic property, ant.test.basedir.ignore, is
+   introduced for cases where Ant projects set up for test purposes
+   must ignore basedir set externally by test harness.
+
+ * a new CharSet type is provided for encoding or charset attributes in
+   tasks that must deal with different character encodings in files,
+   file names and other string resources.
+
+ * org.apache.tools.ant.AntClassLoader is now multi-release jar aware.
+   Starting Java 9, jar files can be packaged as multi-release jars,
+   AntClassLoader now recognizes such multi-release jar files while
+   loading resources at runtime in Java 9+ runtime environments.
+   Bugzilla Report 62952
+
+ * Added jmod and link tasks, to support jmod and jlink tools of JDK 9+.
+   Github Pull Request #80
+
  * Jsch library dependency has now been upgraded to 0.1.55. Jsch is
    the library behind the sshexec and scp Ant tasks.
    Github Pull Request #84
 
+ * The "http" condition, now has a "readTimeout" attribute which can be
+   used to control the amount of time to wait for the read to complete.
+   Bugzilla Report 63193
+
  * ftp task manual has been updated to mention that the remote listing of
    files honours the followsymlinks attribute.
    Bugzilla Report 63226
 
 
-Changes from Ant 1.9.12 TO Ant 1.9.13
+Changes from Ant 1.10.4 TO Ant 1.10.5
 =====================================
 
 Fixed bugs:
@@ -140,7 +484,12 @@
    root.
    Bugzilla Report 62502
 
-Changes from Ant 1.9.11 TO Ant 1.9.12
+Other changes:
+--------------
+ * Java task now accepts a "sourcefile" attribute to allow single file
+   source program execution, a feature that is introduced in Java 11.
+
+Changes from Ant 1.10.3 TO Ant 1.10.4
 =====================================
 
 Changes that could break older environments:
@@ -170,6 +519,15 @@
  * The junit task when used with includeantruntime="no" was incorrectly
    printing a warning about multiple versions of ant detected in path
 
+ * <cab> died with a NullPointerException since Ant 1.10.2.
+   Bugzilla Report 62335
+
+ * The <depend> task would fail with
+   "java.lang.ClassFormatError: Invalid Constant Pool entry Type 19" while
+   parsing a module-info.class. The task is compatible with
+   Java bytecode version 53 now.
+   Bug reported by Simon IJskes https://issues.apache.org/jira/browse/NETBEANS-781
+
  * Default and SecureInputHandler will now raise an error when then
    end of the input stream (usually System.in or System.console) are
    reached before a valid input has been read.
@@ -181,6 +539,9 @@
 Other changes:
 --------------
 
+ * AntAssert is deprecated, assertThat from JUnit 4.4+, Hamcrest matchers and/or
+   ExpectedException rule provide equivalent functionality
+
  * PumpStreamHandler now explicitly verifies the streams for output
    and error are not null and will throw an exception if they
    are. This way creating a PumpStreamHandler will fail early as
@@ -193,6 +554,11 @@
    availableProcessors, freeMemory, maxMemory and totalMemory methods
    of the Java Runtime class.
 
+ * linecontains filter now has a new "matchAny" attribute which when
+   set to "true" allows any (instead of all) of the user-specified
+   strings to be present in the line.
+   Bugzilla Report 62313
+
  * <resourcelist> has a new basedir attribute that can be used to
    resolve relative names and provides a root for the FileResources
    generated.
@@ -203,7 +569,15 @@
    can be used to specify the file's encoding.
    Bugzilla Report 62379
 
-Changes from Ant 1.9.10 TO Ant 1.9.11
+ * New file selectors, posixGroup and posixPermissions, are available.
+   The new selectors and related ownedBy selector have "followSymlinks"
+   attribute that defaults to "true" for consistency.
+   Bugzilla Report 22370
+
+ * The junitlauncher task now has a "printSummary" attribute which when
+   set to "true" will print the test execution summary to System.out.
+
+Changes from Ant 1.10.2 TO Ant 1.10.3
 =====================================
 
 Changes that could break older environments:
@@ -215,12 +589,23 @@
    and no longer throws an exception.
    ant-dev list https://www.mail-archive.com/dev@ant.apache.org/msg46634.html
 
+ * Reverted the signature change of various clone method
+   implementation in Ant's data-types introduced with 1.10.2 as they
+   broke subclasses of said data-types which tried to override clone.
+
 Fixed bugs:
 -----------
 
+ * Fixed NullPointerException in ChainedMapper
+   Bugzilla Report 62086
+
  * Fixed NullPointerException when a mappedresource is used in pathconvert
    Bugzilla Report 62076
 
+ * Fixed an issue where a string, when used as a resource collection, within
+   tokens, would be replaced by property values
+   Bugzilla Report 62147
+
  * Added a workaround for a bug in the jarsigner tool to <verifyjar>
    which requires the -storepass command line argument when verifying
    signatures using -strict together with a PKCS12 keystore. Unlike
@@ -234,16 +619,48 @@
 Other changes:
 --------------
 
+ * Allow Saxon to be used for junitreport XSL transformation
+   Github Pull Request #57
+
  * when running on Java 11+ rmic will fail early if iiop or idl are
-   requested. Java11 removes support for CORBA and the switches have
+   requested. Java 11 removes support for CORBA and the switches have
    been removed from the rmic tool.
 
-Changes from Ant 1.9.9 TO Ant 1.9.10
-====================================
+ * A new junitlauncher task which support JUnit 5 test framework.
+   Bugzilla Report 61796
+
+Changes from Ant 1.10.1 TO Ant 1.10.2
+=====================================
+
+Changes that could break older environments:
+-------------------------------------------
+
+ * updated the dependency of BCEL to 6.2.
+   Bugzilla Report 61196
+
+ * delete task previously would silently accept wildcard (*)
+   value for the "file" attribute. That's no longer the case
+   and an exception could get thrown by the underlying filesystem
+   for such use. Usage like:
+
+   <delete file="/foo/bar/*.something"/>
+
+   should instead be changed to use resource collections like:
+
+   <delete>
+   	 <fileset dir="/foo/bar/" includes="*.something"/>
+   </delete>
+
+ * Commons Net 3.6 is binary-code, but not source compatible;
+   see change list of Commons Net 3.0 for details
 
  * The Log4jListener is marked as deprecated as the required log4j library
    (in version 1.x) is not maintained any more.
 
+ * Image task is marked as deprecated as the required JAI library is not
+   maintained any more and internal APIs that JAI depended on are no longer
+   available in Java 9.
+
 Fixed bugs:
 -----------
 
@@ -251,6 +668,9 @@
    value.
    Bugzilla Report 60767
 
+ * bootstrapping Ant on Windows failed
+   Bugzilla Report 61027
+
  * Fixed the issue where the SCP based tasks would try to change
    the permissions on the parent directory of a transferred file,
    instead of changing it on the transferred file itself.
@@ -261,6 +681,11 @@
    the same source file (symlinked back to itself).
    Bugzilla Report 60644
 
+ * Fixed the issue where symlink creation with "overwrite=false",
+   on existing symlink whose target was a directory, would end
+   up creating a new symlink under the target directory.
+   Bugzilla Report 58683
+
  * Improvement to the Zip task for reduced memory usage in certain
    cases. Thanks to Glen Lewis for reporting the issue and
    suggesting the fix.
@@ -282,9 +707,23 @@
    values always get quoted.
    Github Pull Request #32
 
+ * Added <encoding> attributes to various script related tasks and a
+   compiled attribute to scriptdef.
+   Github Pull Request #30
+
+ * Added support for jarsigner's -tsadigestalg to <signjar>.
+   Bugzilla Report 60665
+
  * added "regexp" attribute to <linecontainsregexp>
    Bugzilla Report 60968
 
+ * reduced GC pressure by replacing all usage of FileInputStream and
+   FileOutputStream.
+
+ * Task can now also use attribute setters that expect a
+   java.nio.file.Path argument.
+   Bugzilla Report 61042
+
  * added a new magic property ant.tstamp.now that can be used to
    override the current time/date used by <tstamp>.
    Bugzilla Report 61079
@@ -314,20 +753,21 @@
 
  * Updated Maven Ant Tasks, Jakarta Regexp and JUnit 4 to the latest
    stable version (2.1.3, 1.4, and 4.12 respectively); updated
-   Java Mail API, JRuby and Jython to the latest Java 5 compatible
-   version (1.5.6, 1.6.8 and 2.5.3, respectively); added resolve targets
-   for Ivy and AntUnit to facilitate releases and updates, respectively.
+   JRuby to the latest Java 5 compatible version (1.6.8); added
+   resolve target for AntUnit to facilitate updates.
    Github Pull Request #50
 
-* Updated Commons Net to the latest Java 5 compatible version (2.2).
+ * Updated Java Mail API, Jython, Rhino and Commons Net to the latest
+   stable version (1.6.0, 2.7.0, 1.7.7.2 and 3.6, respectively).
+   Github Pull Request #53
 
-Changes from Ant 1.9.8 TO Ant 1.9.9
-===================================
+Changes from Ant 1.10.0 TO Ant 1.10.1
+=====================================
 
 Fixed bugs:
 -----------
 
- * Ant 1.9.8 made Path#systemClasspath final which broke the Eclipse
+ * Ant 1.10.0 made Path#systemClasspath final which broke the Eclipse
    integration.
    Bugzilla Report 60582
 
@@ -337,17 +777,36 @@
    newlines present in command line arguments.
    Bugzilla Report 60562
 
-Changes from Ant 1.9.7 TO Ant 1.9.8
-===================================
+Other changes:
+--------------
+
+ * new tasks <xz> and <unxz> and resource <xzresource> for XZ
+   compression. Also the compression attribute of <tar>/<untar> now
+   accepts "xz" as valid value.
+   The tasks and type are contained in the new ant-xz.jar and require
+   the library XZ for Java to be on the CLASSPATH.
+   Bugzilla Report 60350
+
+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 builtin 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.
 
@@ -355,6 +814,9 @@
    be used when running on Java 9 since this option has been removed.
    Bugzilla Report 59906
 
+ * <javah> will default to the "forking" implementation on Java8
+   as well.
+
 Fixed bugs:
 -----------
 
@@ -402,6 +864,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
@@ -439,6 +906,9 @@
  * it is now possible to use references to Ant types and classloaders
    built around Ant <path>s as values for TraX factory attributes.
 
+ * AntClassLoader and its subclasses register themselves as parallel
+   capable.
+
  * <junitreport> now enables the feature
    http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions
    when run on Java 9 so the redirect extension function can be used
diff --git a/ant.properties.sample b/ant.properties.sample
index 1930ca7..3126fcc 100644
--- a/ant.properties.sample
+++ b/ant.properties.sample
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/bootstrap.bat b/bootstrap.bat
index be2ec0b..1d79958 100755
--- a/bootstrap.bat
+++ b/bootstrap.bat
@@ -10,7 +10,7 @@
 REM  (the "License"); you may not use this file except in compliance with
 REM  the License.  You may obtain a copy of the License at
 REM
-REM      http://www.apache.org/licenses/LICENSE-2.0
+REM      https://www.apache.org/licenses/LICENSE-2.0
 REM
 REM  Unless required by applicable law or agreed to in writing, software
 REM  distributed under the License is distributed on an "AS IS" BASIS,
@@ -34,10 +34,8 @@
 echo.
 echo ... Bootstrapping Ant Distribution
 
-if     "%OS%" == "Windows_NT" if exist bootstrap\nul rmdir/s/q bootstrap
-if not "%OS%" == "Windows_NT" if exist bootstrap\nul deltree/y bootstrap
-if     "%OS%" == "Windows_NT" if exist build\nul rmdir/s/q build
-if not "%OS%" == "Windows_NT" if exist build\nul deltree/y build
+if exist bootstrap\nul rmdir/s/q bootstrap
+if exist build\nul rmdir/s/q build
 
 SET LOCALCLASSPATH=
 for %%i in (lib\optional\*.jar) do call src\script\lcp.bat %%i
@@ -55,16 +53,25 @@
 echo CLASSPATH=%CLASSPATH%
 echo ANT_HOME=%ANT_HOME%
 
-if     "%OS%" == "Windows_NT" if exist %CLASSDIR%\nul rmdir/s/q %CLASSDIR%
-if not "%OS%" == "Windows_NT" if exist %CLASSDIR%\nul deltree/y %CLASSDIR%
+if exist %CLASSDIR%\nul rmdir/s/q %CLASSDIR%
 
 if not exist build\nul mkdir build
 if not exist build\classes\nul mkdir build\classes
 
+rem Check if javac tool supports the --release param
+SET JAVAC_RELEASE_VERSION=""
+echo "public class JavacVersionCheck {}" > %CLASSDIR%\JavacVersionCheck.java
+"%JAVAC%" --release 8 -d %CLASSDIR% %CLASSDIR%\JavacVersionCheck.java >nul 2>&1
+IF %ERRORLEVEL% EQU 0 SET JAVAC_RELEASE_VERSION="--release 8"
+DEL %CLASSDIR%\JavacVersionCheck.java %CLASSDIR%\JavacVersionCheck.class >nul 2>&1
 echo.
-echo ... Compiling Ant Classes
-
-"%JAVAC%" %BOOTJAVAC_OPTS% -d %CLASSDIR% %TOOLS%\bzip2\*.java %TOOLS%\tar\*.java %TOOLS%\zip\*.java %TOOLS%\ant\*.java %TOOLS%\ant\types\*.java %TOOLS%\ant\taskdefs\*.java %TOOLS%\ant\util\regexp\RegexpMatcher.java %TOOLS%\ant\util\regexp\RegexpMatcherFactory.java %TOOLS%\ant\taskdefs\condition\*.java %TOOLS%\ant\taskdefs\compilers\*.java %TOOLS%\ant\types\resources\*.java %TOOLS%\ant\property\*.java
+IF %JAVAC_RELEASE_VERSION% == "" (
+  echo ... Compiling Ant Classes
+  "%JAVAC%" %BOOTJAVAC_OPTS% -d %CLASSDIR% %TOOLS%\bzip2\*.java %TOOLS%\tar\*.java %TOOLS%\zip\*.java %TOOLS%\ant\*.java %TOOLS%\ant\types\*.java %TOOLS%\ant\taskdefs\*.java %TOOLS%\ant\util\regexp\RegexpMatcher.java %TOOLS%\ant\util\regexp\RegexpMatcherFactory.java %TOOLS%\ant\taskdefs\condition\*.java %TOOLS%\ant\taskdefs\compilers\*.java %TOOLS%\ant\types\resources\*.java %TOOLS%\ant\property\*.java
+) ELSE (
+  echo ... Compiling Ant Classes with %JAVAC_RELEASE_VERSION%
+  "%JAVAC%" %BOOTJAVAC_OPTS% -d %CLASSDIR% %JAVAC_RELEASE_VERSION% %TOOLS%\bzip2\*.java %TOOLS%\tar\*.java %TOOLS%\zip\*.java %TOOLS%\ant\*.java %TOOLS%\ant\types\*.java %TOOLS%\ant\taskdefs\*.java %TOOLS%\ant\util\regexp\RegexpMatcher.java %TOOLS%\ant\util\regexp\RegexpMatcherFactory.java %TOOLS%\ant\taskdefs\condition\*.java %TOOLS%\ant\taskdefs\compilers\*.java %TOOLS%\ant\types\resources\*.java %TOOLS%\ant\property\*.java
+)
 
 if ERRORLEVEL 1 goto mainend
 
@@ -121,8 +128,7 @@
 echo.
 echo ... Cleaning Up Build Directories
 
-if     "%OS%" == "Windows_NT" if exist %CLASSDIR%\nul rmdir/s/q %CLASSDIR%
-if not "%OS%" == "Windows_NT" if exist %CLASSDIR%\nul deltree/y %CLASSDIR%
+if exist %CLASSDIR%\nul rmdir/s/q %CLASSDIR%
 
 echo.
 echo ... Done Bootstrapping Ant Distribution
diff --git a/bootstrap.sh b/bootstrap.sh
index d1013d1..c97abb3 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -7,7 +7,7 @@
 # (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
+#     https://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,
@@ -127,9 +127,24 @@
 mkdir -p ${CLASSDIR}
 mkdir -p bin
 
-echo ... Compiling Ant Classes
+# Check if javac tool supports the --release param
+echo "public class JavacVersionCheck {}" > ${CLASSDIR}/JavacVersionCheck.java
+"${JAVAC}" --release 8 -d ${CLASSDIR} ${CLASSDIR}/JavacVersionCheck.java 1>&2 2>/dev/null
+ret=$?
+rm ${CLASSDIR}/JavacVersionCheck.java ${CLASSDIR}/JavacVersionCheck.class 1>&2 2>/dev/null
+JAVAC_RELEASE_VERSION=
+if [ $ret -eq 0 ]; then
+  # set --release to 8
+  JAVAC_RELEASE_VERSION="--release 8"
+fi
+if [ "${JAVAC_RELEASE_VERSION}" = "" ]; then
+  echo ... Compiling Ant Classes
+else
+  echo ... Compiling Ant Classes with ${JAVAC_RELEASE_VERSION}
+fi
 
-"${JAVAC}" $BOOTJAVAC_OPTS -d ${CLASSDIR} ${TOOLS}/bzip2/*.java ${TOOLS}/tar/*.java ${TOOLS}/zip/*.java \
+"${JAVAC}" $BOOTJAVAC_OPTS -d ${CLASSDIR} ${JAVAC_RELEASE_VERSION} \
+           ${TOOLS}/bzip2/*.java ${TOOLS}/tar/*.java ${TOOLS}/zip/*.java \
            ${TOOLS}/ant/util/regexp/RegexpMatcher.java \
            ${TOOLS}/ant/util/regexp/RegexpMatcherFactory.java \
            ${TOOLS}/ant/property/*.java \
diff --git a/build.bat b/build.bat
index 0f1a52d..dc6e447 100755
--- a/build.bat
+++ b/build.bat
@@ -7,7 +7,7 @@
 REM  (the "License"); you may not use this file except in compliance with
 REM  the License.  You may obtain a copy of the License at
 REM 
-REM      http://www.apache.org/licenses/LICENSE-2.0
+REM      https://www.apache.org/licenses/LICENSE-2.0
 REM 
 REM  Unless required by applicable law or agreed to in writing, software
 REM  distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/build.sh b/build.sh
index ee8e571..34b4875 100755
--- a/build.sh
+++ b/build.sh
@@ -7,7 +7,7 @@
 # (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
+#     https://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,
diff --git a/build.xml b/build.xml
index 3636bf7..8d401aa 100644
--- a/build.xml
+++ b/build.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
@@ -33,15 +33,16 @@
   <property name="name" value="ant"/>
   <!-- this is the directory corresponding to groupId of Ant in the Maven repository -->
   <property name="groupid" value="org/apache/ant"/>
-  <property name="project.version" value="1.9.17alpha"/>
+  <property name="project.version" value="1.10.13alpha"/>
   <!-- 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.17-SNAPSHOT"/>
-  <property name="manifest-version" value="1.9.17"/>
+  <property name="pom.version" value="1.10.13-SNAPSHOT"/>
+  <property name="manifest-version" value="1.10.13"/>
   <property name="bootstrap.jar" value="ant-bootstrap.jar"/>
 
   <property name="ant.package" value="org/apache/tools/ant"/>
   <property name="taskdefs.package" value="${ant.package}/taskdefs"/>
   <property name="condition.package" value="${taskdefs.package}/condition"/>
+  <property name="modules.package" value="${taskdefs.package}/modules"/>
   <property name="optional.package" value="${taskdefs.package}/optional"/>
   <property name="type.package" value="${ant.package}/types"/>
   <property name="optional.type.package" value="${type.package}/optional"/>
@@ -65,7 +66,6 @@
   <property name="src.antunit" value="${src.dir}/tests/antunit"/>
   <property name="etc.dir" value="${src.dir}/etc"/>
   <property name="tests.etc.dir" value="${etc.dir}/testcases"/>
-  <property name="manifest" value="${etc.dir}/manifest"/>
   <property name="lib.dir" value="lib"/>
   <property name="manual.dir" value="manual"/>
 
@@ -85,12 +85,13 @@
   <property name="build.junit.xml" location="${build.tests}/xml"/>
   <property name="build.junit.tmpdir" location="${build.tests}/tmp"/>
   <property name="build.junit.reports" location="${build.tests}/reports"/>
+  <property name="build.pkg.dir" value="${build.dir}/pkg"/>
   <property name="antunit.xml" location="${build.dir}/antunit/xml"/>
   <property name="antunit.tmpdir" location="${build.dir}/antunit/tmp"/>
   <property name="antunit.reports" location="${build.dir}/antunit/reports"/>
   <property name="antunit.loglevel" value="none"/>
-  <property name="manifest.tmp" value="${build.dir}/optional.manifest"/>
   <!-- the absolute path -->
+  <property name="build.classes.value" location="${build.classes}"/>
   <property name="build.tests.value" location="${build.tests}"/>
 
   <!--
@@ -99,12 +100,13 @@
        ===================================================================
   -->
   <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="setpermissions.nonposixmode" value="tryDosOrPass"/>
   <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="javac.release" value="8"/>
   <property name="junit.filtertrace" value="off"/>
   <property name="junit.summary" value="no"/>
   <property name="test.haltonfailure" value="false"/>
@@ -121,7 +123,6 @@
   <property name="junit.collector.dir" value="${build.dir}/failingTests"/>
   <property name="junit.collector.class" value="FailedTests"/>
 
-
   <!--
        ===================================================================
          Set the paths used in the build
@@ -179,6 +180,10 @@
        ===================================================================
   -->
 
+  <selector id="needs.jdk9+">
+    <filename name="${modules.package}/"/>
+  </selector>
+
   <!-- Kaffe has some JDK 1.5 features including java.lang.Readable,
        but not all of them -->
   <selector id="not.in.kaffe">
@@ -210,6 +215,29 @@
       </or>
   </selector>
 
+  <selector id="needs.junitlauncher">
+    <or>
+      <filename name="${optional.package}/junitlauncher/"/>
+      <filename name="org/example/junitlauncher/Tracker.java"/>
+    </or>
+  </selector>
+
+  <selector id="needs.junit.engine.vintage">
+    <or>
+      <!-- we need JUnit vintage engine only in tests where we test the junitlauncher task -->
+      <filename name="${optional.package}/junitlauncher/**/JUnitLauncherTaskTest.java"/>
+      <filename name="org/example/junitlauncher/vintage/**/*"/>
+    </or>
+  </selector>
+
+  <selector id="needs.junit.engine.jupiter">
+    <or>
+      <!-- we need JUnit jupiter engine only in tests where we test the junitlauncher task -->
+      <filename name="${optional.package}/junitlauncher/**/JUnitLauncherTaskTest.java"/>
+      <filename name="org/example/junitlauncher/jupiter/**/*"/>
+    </or>
+  </selector>
+
   <selector id="needs.apache-regexp">
     <filename name="${regexp.package}/JakartaRegexp*"/>
   </selector>
@@ -249,6 +277,12 @@
     </or>
   </selector>
 
+  <selector id="needs.jakartamail">
+    <or>
+      <filename name="${ant.package}/taskdefs/email/JakartaMimeMailer*"/>
+    </or>
+  </selector>
+
   <selector id="needs.netrexx">
     <filename name="${optional.package}/NetRexxC*"/>
   </selector>
@@ -265,13 +299,21 @@
     <filename name="${optional.package}/ANTLR*"/>
   </selector>
 
+  <selector id="needs.imageio">
+    <or>
+      <filename name="${optional.package}/image/ImageIO*"/>
+      <filename name="${optional.type.package}/imageio/"/>
+    </or>
+  </selector>
+
   <selector id="needs.jmf">
     <filename name="${optional.package}/sound/"/>
   </selector>
 
   <selector id="needs.jai">
     <or>
-      <filename name="${optional.package}/image/"/>
+      <filename name="${optional.package}/image/Image.*"/>
+      <filename name="${optional.package}/image/ImageTest.*"/>
       <filename name="${optional.type.package}/image/"/>
     </or>
   </selector>
@@ -293,6 +335,17 @@
     <filename name="${optional.package}/Xalan2TraceSupport*"/>
   </selector>
 
+  <selector id="needs.xz">
+    <or>
+      <filename name="${optional.package}/xz/"/>
+      <filename name="${type.package}/optional/xz/"/>
+    </or>
+  </selector>
+
+  <selector id="needs.graaljs">
+    <filename name="${optional.package}/script/graal/*"/>
+  </selector>
+
   <selector id="ant.launcher">
     <filename name="${ant.package}/launch/"/>
   </selector>
@@ -310,15 +363,19 @@
         <selector refid="needs.apache-xalan2"/>
         <selector refid="needs.commons-logging"/>
         <selector refid="needs.commons-net"/>
+        <selector refid="needs.imageio"/>
         <selector refid="needs.jai"/>
         <selector refid="needs.javamail"/>
+        <selector refid="needs.jakartamail"/>
         <selector refid="needs.jdepend"/>
         <selector refid="needs.jmf"/>
         <selector refid="needs.jsch"/>
         <selector refid="needs.junit"/>
         <selector refid="needs.junit4"/>
+        <selector refid="needs.junitlauncher"/>
         <selector refid="needs.netrexx"/>
         <selector refid="needs.swing"/>
+        <selector refid="needs.xz"/>
         <selector refid="ant.launcher"/>
       </or>
     </not>
@@ -337,7 +394,7 @@
     <exclude unless="run.failing.tests" name="${optional.package}/jdepend/JDependTest.java"/>
   </patternset>
 
-  <!--tests that need an XML Schema-supporting parser to work-->
+  <!-- tests that need an XML Schema-supporting parser to work -->
   <selector id="needs.xmlschema">
     <or>
       <filename name="${optional.package}/SchemaValidateTest.*"/>
@@ -356,6 +413,7 @@
     <include name="${ant.package}/BuildFileTest*"/>
     <include name="${ant.package}/BuildFileRule*"/>
     <include name="${ant.package}/FileUtilities*"/>
+    <include name="${ant.package}/MagicTestNames*"/>
     <include name="${regexp.package}/RegexpMatcherTest*"/>
     <include name="${regexp.package}/RegexpTest*"/>
     <include name="${optional.package}/AbstractXSLTLiaisonTest*"/>
@@ -374,9 +432,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"/>
     <condition property="jdk10+">
       <javaversion atleast="10"/>
@@ -402,6 +457,15 @@
     <available property="junit4.present"
                classname="org.junit.Test"
                classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="junitlauncher.present"
+               classname="org.junit.platform.launcher.Launcher"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="junit.engine.vintage.present"
+               classname="org.junit.vintage.engine.VintageTestEngine"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="junit.engine.jupiter.present"
+               classname="org.junit.jupiter.engine.JupiterTestEngine"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
     <available property="antunit.present"
                classname="org.apache.ant.antunit.AntUnit"
                classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
@@ -417,6 +481,9 @@
     <available property="apache.oro.present"
                classname="org.apache.oro.text.regex.Perl5Matcher"
                classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="imageio.present"
+               classname="javax.imageio.ImageIO"
+               classpathref="classpath"/>
     <available property="jmf.present"
                classname="javax.sound.sampled.Clip"
                classpathref="classpath"/>
@@ -444,15 +511,34 @@
     <available property="bcel.present"
                classname="org.apache.bcel.Constants"
                classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="javamail.present"
+               classname="javax.mail.Transport"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="jakartamail.present"
+               classname="jakarta.mail.Transport"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="graaljs.present"
+               classname="com.oracle.truffle.js.scriptengine.GraalJSScriptEngine"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
 
-    <condition property="javamail.complete">
+    <condition property="javaxmail.complete">
       <and>
-        <available classname="javax.activation.DataHandler"
-          classpathref="classpath"/>
-        <available classname="javax.mail.Transport"
-          classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+        <available classname="javax.activation.DataHandler"/>
+        <available classname="javax.mail.Transport"/>
       </and>
     </condition>
+    <condition property="jakartamail.complete">
+      <and>
+        <available classname="jakarta.activation.DataHandler"/>
+        <available classname="jakarta.mail.Transport"/>
+      </and>
+    </condition>
+    <condition property="javamail.complete">
+      <or>
+        <isset property="javaxmail.complete"/>
+        <isset property="jakartamail.complete"/>
+      </or>
+    </condition>
 
     <condition property="tests.and.ant.share.classloader">
       <or>
@@ -511,10 +597,13 @@
     <available property="jsch.present"
                classname="com.jcraft.jsch.Session"
                classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="xz.present"
+               classname="org.tukaani.xz.XZOutputStream"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
 
     <property name="build.compiler" value="modern"/>
 
-    <!--check for XSD support in the parser-->
+    <!-- check for XSD support in the parser -->
     <condition property="xmlschema.present">
       <or>
         <parsersupports feature="http://apache.org/xml/features/validation/schema"/>
@@ -522,18 +611,15 @@
       </or>
     </condition>
 
-    <!-- 
-    Java8 introduced a HTML checker 'doclint' which is very strict and breaks 
+    <!--
+    Java8 introduced a HTML checker 'doclint' which is very strict and breaks
     the build if there is a HTML error in the JavaDoc.
     -->
-    <condition 
-      property="javadoc.doclint.none" 
-      value="-Xdoclint:none" 
-      else="">
-      <and>
-        <isset property="jdk1.8+"/>
-        <not><isset property="withDoclint"/></not>
-      </and>
+    <condition
+            property="javadoc.doclint.none"
+            value="-Xdoclint:none"
+            else="">
+      <not><isset property="withDoclint"/></not>
     </condition>
   </target>
 
@@ -542,7 +628,7 @@
          Prepare the build
        ===================================================================
   -->
-  <target name="prepare">
+  <target name="prepare" depends="check-optional-packages">
     <tstamp>
       <format property="year" pattern="yyyy"/>
     </tstamp>
@@ -556,50 +642,35 @@
          Build the code
        ===================================================================
   -->
-  <target name="build" depends="prepare,check-optional-packages"
+  <target name="build" depends="prepare, compile, compile-jdk9+" unless="skip.build"
           description="--> compiles the source code">
-    <mkdir dir="${build.dir}"/>
-    <mkdir dir="${build.classes}"/>
-    <mkdir dir="${build.lib}"/>
 
+    <!-- Builds and verifies that the classes belonging in the confined package of
+    junitlauncher task do not depend on classes they aren't meant to -->
+    <!-- first wipe out the "confined" package that might have been built already
+     due to the javac above -->
+    <delete dir="${build.classes}/${optional.package}/junitlauncher/confined/"/>
     <javac srcdir="${java.dir}"
            includeantruntime="false"
            destdir="${build.classes}"
            debug="${debug}"
            deprecation="${deprecation}"
+           includes="${optional.package}/junitlauncher/confined/**"
            target="${javac.target}"
            source="${javac.source}"
+           release="${javac.release}"
            optimize="${optimize}">
-      <classpath refid="classpath"/>
+      <classpath>
+        <!-- A very limited classpath which only doesn't include optional libraries,
+         which the classes in confined package aren't meant to depend on -->
+        <fileset dir="${build.classes}">
+          <!-- exclude the org/apache/tools/ant/taskdefs/optional/junitlauncher package
+          from the classpath, since the confined package isn't meant to depend on
+          classes in this package -->
+          <exclude name="org/apache/tools/ant/taskdefs/optional/junitlauncher/*"/>
+        </fileset>
+      </classpath>
 
-      <selector id="conditional-patterns">
-        <not>
-          <or>
-            <selector refid="not.in.kaffe" if="kaffe"/>
-
-            <selector refid="needs.apache-resolver" unless="apache.resolver.present"/>
-            <selector refid="needs.junit" unless="junit.present"/> <!-- TODO should perhaps use -source 1.4? -->
-            <selector refid="needs.junit4" unless="junit4.present"/>
-            <selector refid="needs.apache-regexp" unless="apache.regexp.present"/>
-            <selector refid="needs.apache-oro" unless="apache.oro.present"/>
-            <selector refid="needs.apache-bcel" unless="bcel.present"/>
-            <selector refid="needs.apache-log4j" unless="log4j.present"/>
-            <selector refid="needs.commons-logging" unless="commons.logging.present"/>
-            <selector refid="needs.apache-bsf" unless="bsf.present"/>
-            <selector refid="needs.javamail" unless="javamail.complete"/>
-            <selector refid="needs.netrexx" unless="netrexx.present"/>
-            <selector refid="needs.commons-net" unless="commons.net.present"/>
-            <selector refid="needs.antlr" unless="antlr.present"/>
-            <selector refid="needs.jmf" unless="jmf.present"/>
-            <selector refid="needs.jai" unless="jai.present"/>
-            <selector refid="needs.jdepend" unless="jdepend.present"/>
-            <selector refid="needs.swing" unless="swing.present"/>
-            <selector refid="needs.jsch" unless="jsch.present"/>
-            <selector refid="needs.xmlschema" unless="xmlschema.present"/>
-            <selector refid="needs.apache-xalan2" unless="recent.xalan2.present"/>
-          </or>
-        </not>
-      </selector>
     </javac>
 
     <copy todir="${build.classes}">
@@ -624,10 +695,84 @@
       <fileset dir="${etc.dir}">
         <include name="junit-frames.xsl"/>
         <include name="junit-noframes.xsl"/>
+        <include name="junit-frames-saxon.xsl"/>
+        <include name="junit-noframes-saxon.xsl"/>
       </fileset>
     </copy>
   </target>
 
+  <target name="compile" depends="prepare">
+    <mkdir dir="${build.classes}"/>
+    <javac srcdir="${java.dir}"
+           includeantruntime="false"
+           destdir="${build.classes}"
+           debug="${debug}"
+           deprecation="${deprecation}"
+           excludes="${optional.package}/junitlauncher/confined/**"
+           target="${javac.target}"
+           source="${javac.source}"
+           release="${javac.release}"
+           optimize="${optimize}">
+      <classpath refid="classpath"/>
+
+      <selector id="conditional-patterns">
+        <not>
+          <or>
+            <selector refid="needs.jdk9+"/>
+            <selector refid="not.in.kaffe" if="kaffe"/>
+            <selector refid="needs.apache-resolver" unless="apache.resolver.present"/>
+            <selector refid="needs.junit" unless="junit.present"/> <!-- TODO should perhaps use -source 1.4? -->
+            <selector refid="needs.junit4" unless="junit4.present"/>
+            <selector refid="needs.junitlauncher" unless="junitlauncher.present"/>
+            <selector refid="needs.junit.engine.vintage" unless="junit.engine.vintage.present"/>
+            <selector refid="needs.junit.engine.jupiter" unless="junit.engine.jupiter.present"/>
+            <selector refid="needs.apache-regexp" unless="apache.regexp.present"/>
+            <selector refid="needs.apache-oro" unless="apache.oro.present"/>
+            <selector refid="needs.apache-bcel" unless="bcel.present"/>
+            <selector refid="needs.apache-log4j" unless="log4j.present"/>
+            <selector refid="needs.commons-logging" unless="commons.logging.present"/>
+            <selector refid="needs.apache-bsf" unless="bsf.present"/>
+            <selector refid="needs.javamail" unless="javamail.present"/>
+            <selector refid="needs.jakartamail" unless="jakartamail.present"/>
+            <selector refid="needs.netrexx" unless="netrexx.present"/>
+            <selector refid="needs.commons-net" unless="commons.net.present"/>
+            <selector refid="needs.antlr" unless="antlr.present"/>
+            <selector refid="needs.imageio" unless="imageio.present"/>
+            <selector refid="needs.jmf" unless="jmf.present"/>
+            <selector refid="needs.jai" unless="jai.present"/>
+            <selector refid="needs.jdepend" unless="jdepend.present"/>
+            <selector refid="needs.swing" unless="swing.present"/>
+            <selector refid="needs.jsch" unless="jsch.present"/>
+            <selector refid="needs.xz" unless="xz.present"/>
+            <selector refid="needs.xmlschema" unless="xmlschema.present"/>
+            <selector refid="needs.apache-xalan2" unless="recent.xalan2.present"/>
+          </or>
+        </not>
+      </selector>
+    </javac>
+  </target>
+
+  <target name="compile-jdk9+" depends="prepare" if="jdk9+">
+    <mkdir dir="${build.classes}"/>
+
+    <javac srcdir="${java.dir}"
+           includeantruntime="false"
+           destdir="${build.classes}"
+           debug="${debug}"
+           deprecation="${deprecation}"
+           target="${javac.target}"
+           source="${javac.source}"
+           optimize="${optimize}">
+      <classpath refid="classpath"/>
+
+      <selector id="conditional-patterns-jdk9+">
+          <or>
+            <selector refid="needs.jdk9+"/>
+          </or>
+      </selector>
+    </javac>
+  </target>
+
   <!--
        ===================================================================
          Create the all of the Apache Ant jars
@@ -647,28 +792,8 @@
       <mapper type="glob" from="*" to="*.txt"/>
     </copy>
 
-    <copy file="${manifest}" tofile="${manifest.tmp}"/>
-    <manifest file="${manifest.tmp}">
-      <section name="${optional.package}/">
-        <attribute name="Extension-name"
-                   value="org.apache.tools.ant"/>
-        <attribute name="Specification-Title"
-                   value="Apache Ant"/>
-        <attribute name="Specification-Version"
-                   value="${manifest-version}"/>
-        <attribute name="Specification-Vendor"
-                   value="Apache Software Foundation"/>
-        <attribute name="Implementation-Title"
-                   value="org.apache.tools.ant"/>
-        <attribute name="Implementation-Version"
-                   value="${manifest-version}"/>
-        <attribute name="Implementation-Vendor"
-                   value="Apache Software Foundation"/>
-      </section>
-    </manifest>
-
     <jar destfile="${build.lib}/${name}-launcher.jar"
-         basedir="${build.classes}"
+         basedir="${build.classes}" index="true"
          whenmanifestonly="fail">
       <selector refid="ant.launcher"/>
       <metainf dir="${build.dir}">
@@ -681,8 +806,7 @@
     </jar>
 
     <jar destfile="${build.lib}/${name}.jar"
-         basedir="${build.classes}"
-         manifest="${manifest}"
+         basedir="${build.classes}" index="true"
          whenmanifestonly="fail">
       <!-- Verification: (cd dist/lib; for j in *.jar; do jar tf $j; done) | egrep -v '/$|META-INF/MANIFEST\.MF' | sort | uniq -d -->
       <selector refid="ant.core"/>
@@ -690,10 +814,10 @@
         <include name="LICENSE.txt"/>
         <include name="NOTICE.txt"/>
       </metainf>
-
       <manifest>
+        <attribute name="Main-Class" value="org.apache.tools.ant.Main"/>
         <section name="${ant.package}/">
-          <attribute name="Extension-name"
+          <attribute name="Extension-Name"
                      value="org.apache.tools.ant"/>
           <attribute name="Specification-Title"
                      value="Apache Ant"/>
@@ -717,7 +841,6 @@
 
     <jar destfile="${build.lib}/${bootstrap.jar}"
          basedir="${build.classes}"
-         manifest="${manifest}"
          whenmanifestonly="fail">
       <include name="${ant.package}/Main.class"/>
       <metainf dir="${build.dir}">
@@ -725,8 +848,8 @@
         <include name="NOTICE.txt"/>
       </metainf>
       <manifest>
-        <attribute name="Class-Path"
-                   value="ant.jar xalan.jar"/>
+        <attribute name="Main-Class" value="org.apache.tools.ant.Main"/>
+        <attribute name="Class-Path" value="ant.jar xalan.jar"/>
       </manifest>
     </jar>
 
@@ -734,14 +857,31 @@
       <attribute name="dep"/>
       <sequential>
         <jar destfile="${build.lib}/${optional.jars.prefix}-@{dep}.jar"
-             basedir="${build.classes}"
-             manifest="${manifest.tmp}"
+             basedir="${build.classes}" index="true"
              whenmanifestonly="${optional.jars.whenmanifestonly}">
           <selector refid="needs.@{dep}"/>
           <metainf dir="${build.dir}">
             <include name="LICENSE.txt"/>
             <include name="NOTICE.txt"/>
           </metainf>
+          <manifest>
+            <section name="${optional.package}/">
+              <attribute name="Extension-Name"
+                         value="org.apache.tools.ant"/>
+              <attribute name="Specification-Title"
+                         value="Apache Ant"/>
+              <attribute name="Specification-Version"
+                         value="${manifest-version}"/>
+              <attribute name="Specification-Vendor"
+                         value="Apache Software Foundation"/>
+              <attribute name="Implementation-Title"
+                         value="org.apache.tools.ant"/>
+              <attribute name="Implementation-Version"
+                         value="${manifest-version}"/>
+              <attribute name="Implementation-Vendor"
+                         value="Apache Software Foundation"/>
+            </section>
+          </manifest>
         </jar>
       </sequential>
     </macrodef>
@@ -749,6 +889,7 @@
     <optional-jar dep="apache-resolver"/>
     <optional-jar dep="junit"/>
     <optional-jar dep="junit4"/>
+    <optional-jar dep="junitlauncher"/>
     <optional-jar dep="apache-regexp"/>
     <optional-jar dep="apache-oro"/>
     <optional-jar dep="apache-bcel"/>
@@ -756,15 +897,18 @@
     <optional-jar dep="commons-logging"/>
     <optional-jar dep="apache-bsf"/>
     <optional-jar dep="javamail"/>
+    <optional-jar dep="jakartamail"/>
     <optional-jar dep="netrexx"/>
     <optional-jar dep="commons-net"/>
     <optional-jar dep="antlr"/>
+    <optional-jar dep="imageio"/>
     <optional-jar dep="jmf"/>
     <optional-jar dep="jai"/>
     <optional-jar dep="swing"/>
     <optional-jar dep="jsch"/>
     <optional-jar dep="jdepend"/>
     <optional-jar dep="apache-xalan2"/>
+    <optional-jar dep="xz"/>
 
   </target>
 
@@ -776,7 +920,7 @@
       We cannot build the test jar unless JUnit is present,
       as JUnit is needed to compile the test classes.
     </fail>
-    <jar destfile="${build.lib}/${name}-testutil.jar"
+    <jar destfile="${build.lib}/${name}-testutil.jar" index="true"
          basedir="${build.tests}">
       <patternset refid="useful.tests"/>
       <metainf dir="${build.dir}">
@@ -841,6 +985,7 @@
     <optional-src-jar dep="apache-resolver"/>
     <optional-src-jar dep="junit"/>
     <optional-src-jar dep="junit4"/>
+    <optional-src-jar dep="junitlauncher"/>
     <optional-src-jar dep="apache-regexp"/>
     <optional-src-jar dep="apache-oro"/>
     <optional-src-jar dep="apache-bcel"/>
@@ -848,15 +993,18 @@
     <optional-src-jar dep="commons-logging"/>
     <optional-src-jar dep="apache-bsf"/>
     <optional-src-jar dep="javamail"/>
+    <optional-src-jar dep="jakartamail"/>
     <optional-src-jar dep="netrexx"/>
     <optional-src-jar dep="commons-net"/>
     <optional-src-jar dep="antlr"/>
+    <optional-src-jar dep="imageio"/>
     <optional-src-jar dep="jmf"/>
     <optional-src-jar dep="jai"/>
     <optional-src-jar dep="swing"/>
     <optional-src-jar dep="jsch"/>
     <optional-src-jar dep="jdepend"/>
     <optional-src-jar dep="apache-xalan2"/>
+    <optional-src-jar dep="xz"/>
 
   </target>
 
@@ -878,7 +1026,7 @@
          Create the essential distribution that can run Apache Ant
        ===================================================================
   -->
-  <target name="dist-lite" depends="jars,test-jar"
+  <target name="dist-lite" depends="jars,test-jar,-ant-dist-warn-jdk9+"
           description="--> creates a minimum distribution to run Apache Ant">
 
     <mkdir dir="${dist.dir}"/>
@@ -909,18 +1057,23 @@
       <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}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
+      <dirset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="644" failonerror="${setpermissions.fail}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
+      <fileset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="755" failonerror="${setpermissions.fail}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
       <fileset dir="${dist.bin}">
         <include name="**/ant"/>
         <include name="**/antRun"/>
         <include name="**/*.pl"/>
         <include name="**/*.py"/>
       </fileset>
-    </chmod>
+    </setpermissions>
 
   </target>
 
@@ -1005,18 +1158,23 @@
       </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}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
+      <dirset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="644" failonerror="${setpermissions.fail}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
+      <fileset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="755" failonerror="${setpermissions.fail}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
       <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}">
@@ -1063,8 +1221,10 @@
 
     <copy todir="${src.dist.lib}">
       <fileset dir="${lib.dir}">
-        <include name="optional/junit*.jar"/>
-        <include name="optional/hamcrest*.jar"/>
+        <include name="optional/junit-3.8.2.jar"/>
+        <include name="optional/junit-4.13.1.jar"/>
+        <include name="optional/hamcrest-core-1.3.jar"/>
+        <include name="optional/hamcrest-library-1.3.jar"/>
         <include name="README"/>
         <include name="libraries.properties"/>
       </fileset>
@@ -1120,18 +1280,26 @@
       <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}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
+      <dirset dir="${src.dist.dir}"/>
+    </setpermissions>
+
+    <setpermissions mode="644" failonerror="${setpermissions.fail}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
+      <fileset dir="${src.dist.dir}"/>
+    </setpermissions>
+
+    <setpermissions mode="755" failonerror="${setpermissions.fail}"
+                    nonPosixMode="${setpermissions.nonposixmode}">
       <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>
 
@@ -1181,10 +1349,28 @@
   </condition>
 
   <target name="pkg-distribution" depends="zip-distribution" if="buildosxpackage">
-    <exec executable="release/build-osx-pkg.py">
-      <arg value="--output-dir"/>
-      <arg value="${dist.base.binaries}"/>
-      <arg value="${dist.base.binaries}/${dist.name}-bin.zip"/>
+    <mkdir dir="${build.pkg.dir}"/>
+    <unzip src="${dist.base.binaries}/${dist.name}-bin.zip" dest="${build.pkg.dir}">
+      <mapper type="regexp" from="^([^/]*)/(.*)$$" to="\2"/>
+    </unzip>
+    <chmod perm="+x" type="file">
+      <fileset dir="${build.pkg.dir}/bin">
+        <include name="ant"/>
+        <include name="antRun"/>
+        <include name="*.pl"/>
+        <include name="*.py"/>
+      </fileset>
+    </chmod>
+    <exec executable="/usr/bin/pkgbuild">
+      <arg value="--root"/>
+      <arg value="${build.pkg.dir}"/>
+      <arg value="--identifier"/>
+      <arg value="org.apache.ant"/>
+      <arg value="--version"/>
+      <arg value="${project.version}"/>
+      <arg value="--install-location"/>
+      <arg value="/usr/local/ant"/>
+      <arg value="${dist.base.binaries}/${dist.name}.pkg"/>
     </exec>
   </target>
 
@@ -1214,6 +1400,8 @@
           src="${dist.base.binaries}/${dist.name}-bin.tar"/>
     <bzip2 destfile="${dist.base.binaries}/${dist.name}-bin.tar.bz2"
            src="${dist.base.binaries}/${dist.name}-bin.tar"/>
+    <xz destfile="${dist.base.binaries}/${dist.name}-bin.tar.xz"
+        src="${dist.base.binaries}/${dist.name}-bin.tar"/>
     <delete file="${dist.base.binaries}/${dist.name}-bin.tar"/>
   </target>
 
@@ -1261,6 +1449,8 @@
           src="${dist.base.manual}/${dist.name}-manual.tar"/>
     <bzip2 destfile="${dist.base.manual}/${dist.name}-manual.tar.bz2"
            src="${dist.base.manual}/${dist.name}-manual.tar"/>
+    <xz destfile="${dist.base.manual}/${dist.name}-manual.tar.xz"
+        src="${dist.base.manual}/${dist.name}-manual.tar"/>
     <delete file="${dist.base.manual}/${dist.name}-manual.tar"/>
 
     <delete dir="${dist.name}"/>
@@ -1308,6 +1498,8 @@
           src="${dist.base.source}/${dist.name}-src.tar"/>
     <bzip2 destfile="${dist.base.source}/${dist.name}-src.tar.bz2"
            src="${dist.base.source}/${dist.name}-src.tar"/>
+    <xz destfile="${dist.base.source}/${dist.name}-src.tar.xz"
+        src="${dist.base.source}/${dist.name}-src.tar"/>
     <delete file="${dist.base.source}/${dist.name}-src.tar"/>
     <delete dir="${dist.name}"/>
     <checksums>
@@ -1346,8 +1538,10 @@
           description="--> cleans up everything">
     <delete file="${bootstrap.dir}/bin/antRun"/>
     <delete file="${bootstrap.dir}/bin/antRun.bat"/>
-    <delete file="${bootstrap.dir}/bin/*.pl"/>
-    <delete file="${bootstrap.dir}/bin/*.py"/>
+    <delete>
+      <fileset dir="${bootstrap.dir}/bin" includes="*.pl"/>
+      <fileset dir="${bootstrap.dir}/bin" includes="*.py"/>
+    </delete>
   </target>
 
   <!--
@@ -1374,20 +1568,20 @@
          Creates the API documentation
        ===================================================================
   -->
-  <target name="check-javadoc">
+  <target name="check-javadoc" depends="prepare">
     <uptodate property="javadoc.notrequired"
-      targetfile="${build.javadocs}/packages.html">
+              targetfile="${build.javadocs}/packages.html">
       <srcfiles dir="${java.dir}" includes="**/*.java"/>
     </uptodate>
     <uptodate property="tests.javadoc.notrequired"
-      targetfile="${build.tests.javadocs}/packages.html">
+              targetfile="${build.tests.javadocs}/packages.html">
       <srcfiles dir="${src.junit}">
         <patternset refid="useful.tests"/>
       </srcfiles>
     </uptodate>
   </target>
 
-  <target name="javadocs" depends="prepare,check-javadoc,check-optional-packages"
+  <target name="javadocs" depends="check-javadoc"
           description="--> creates the API documentation" unless="javadoc.notrequired">
     <mkdir dir="${build.javadocs}"/>
     <javadoc useexternalfile="yes"
@@ -1421,7 +1615,7 @@
     </javadoc>
   </target>
 
-  <target name="test-javadocs" depends="prepare,check-javadoc" unless="tests.javadoc.notrequired"
+  <target name="test-javadocs" depends="check-javadoc" unless="tests.javadoc.notrequired"
           description="--> creates the API documentation for test utilities">
     <mkdir dir="${build.tests.javadocs}"/>
     <javadoc useexternalfile="yes"
@@ -1458,6 +1652,7 @@
            debug="${debug}"
            target="${javac.target}"
            source="${javac.source}"
+           release="${javac.release}"
            deprecation="${deprecation}">
       <classpath refid="tests-classpath"/>
 
@@ -1556,6 +1751,14 @@
 
   <target name="test-init" depends="probe-offline,check-optional-packages,dump-info">
     <mkdir dir="${build.junit.tmpdir}"/>
+    <condition property="sun.io.useCanonCaches" value="false">
+      <not>
+        <javaversion atleast="9"/>
+      </not>
+    </condition>
+    <condition property="java.security.manager" value="allow">
+      <javaversion exactly="18"/>
+    </condition>
     <macrodef name="test-junit">
       <element name="junit-nested" implicit="true"/>
       <sequential>
@@ -1591,7 +1794,7 @@
                errorproperty="junit.failed"
                filtertrace="${junit.filtertrace}">
           <sysproperty key="ant.home" value="${ant.home}"/>
-          <sysproperty key="build.tests" file="${build.tests}"/>
+          <sysproperty key="build.classes.value" value="${build.classes.value}"/>
           <sysproperty key="build.tests.value" value="${build.tests.value}"/>
           <sysproperty key="offline" value="${offline}"/>
           <sysproperty key="tests-classpath.value"
@@ -1601,6 +1804,18 @@
           <sysproperty key="tests.and.ant.share.classloader"
                        value="${tests.and.ant.share.classloader}"/>
           <sysproperty key="java.io.tmpdir" file="${build.junit.tmpdir}"/>
+          <!-- in Java8 the canonical cache seems to interfere with
+               our symlink tests -->
+          <syspropertyset>
+            <propertyref name="sun.io.useCanonCaches"/>
+          </syspropertyset>
+          <!-- Many JUnit tests, in the Ant project, launch Java programs through Ant's
+           java task, which internally calls System.setSecurityManager(). In Java 18
+           an explicit system property value needs to be set to prevent exception from
+           being thrown from that call -->
+          <syspropertyset>
+            <propertyref name="java.security.manager"/>
+          </syspropertyset>
           <classpath>
             <path refid="tests-runtime-classpath"/>
             <pathelement location="${junit.collector.dir}"/>
@@ -1706,7 +1921,41 @@
     </junitreport>
   </target>
 
-  <target name="junit-tests" depends="junit-batch,junit-single-test"/>
+  <target name="junit-tests" depends="junit-batch,graaljs-tests,junit-single-test"/>
+
+  <target name="graaljs-tests" depends="compile-tests,test-init"
+          if="graaljs.present">
+    <junit printsummary="${junit.summary}"
+           haltonfailure="${test.haltonfailure}"
+           fork="true"
+           forkmode="perTest"
+           tempdir="${build.dir}"
+           failureproperty="junit.failed"
+           errorproperty="junit.failed"
+           filtertrace="${junit.filtertrace}">
+      <sysproperty key="ant.home" value="${ant.home}"/>
+      <sysproperty key="build.classes.value" value="${build.classes.value}"/>
+      <sysproperty key="build.tests.value" value="${build.tests.value}"/>
+      <sysproperty key="offline" value="${offline}"/>
+      <sysproperty key="tests-classpath.value"
+                   value="${toString:tests-runtime-classpath}"/>
+      <sysproperty key="root" file="${basedir}"/>
+      <sysproperty key="build.compiler" value="${build.compiler}"/>
+      <sysproperty key="tests.and.ant.share.classloader"
+                   value="${tests.and.ant.share.classloader}"/>
+      <sysproperty key="java.io.tmpdir" file="${build.junit.tmpdir}"/>
+      <classpath>
+        <path refid="tests-runtime-classpath"/>
+        <pathelement location="${junit.collector.dir}"/>
+      </classpath>
+      <formatter type="xml"/>
+      <batchtest todir="${build.junit.xml}" unless="hasFailingTests">
+        <fileset dir="${src.junit}" excludes="**/Abstract*">
+          <selector refid="needs.graaljs" if="graaljs.present"/>
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
 
   <target name="junit-batch" depends="compile-tests,test-init" if="junit.batch">
 
@@ -1723,6 +1972,7 @@
           <!-- abstract classes, not testcases -->
           <exclude name="${taskdefs.package}/TaskdefsTest.java"/>
           <exclude name="${ant.package}/BuildFileTest.java"/>
+          <exclude name="${ant.package}/MagicTestNames.java"/>
           <exclude name="${regexp.package}/RegexpMatcherTest.java"/>
           <exclude name="${regexp.package}/RegexpTest.java"/>
           <exclude name="${optional.package}/AbstractXSLTLiaisonTest.java"/>
@@ -1735,12 +1985,17 @@
           <exclude name="${optional.package}/junit/TestFormatter.java"/>
           <exclude name="${ant.package}/TestHelper.java"/>
 
+          <!-- JUnit 5 / junitlauncher tests that aren't meant to run by junit task -->
+          <exclude name="${optional.package}/junitlauncher/"/>
+
           <!-- interactive tests -->
           <exclude name="${taskdefs.package}/TestProcess.java"/>
           <exclude name="${optional.package}/splash/SplashScreenTest.java"/>
 
-          <!-- only run these tests if their required libraries are
-               installed -->
+          <!-- GraalVM JavaScript Nashorn compat tests influencing current JVM -->
+          <exclude name="${optional.package}/script/graal/"/>
+
+          <!-- only run these tests if their required libraries are installed -->
           <selector refid="conditional-patterns"/>
 
           <!-- tests excluded if the test is run in offline mode -->
@@ -1875,6 +2130,10 @@
       <echo>AntUnit tests must be run with ${bootstrap.dir} (or ${dist.dir}), not ${ant.home}. Try './build.sh antunit-tests' for example.</echo>
   </target>
 
+  <target name="-ant-dist-warn-jdk9+" unless="jdk9+">
+      <echo>Java 9+ features won't be available in the distribution</echo>
+  </target>
+
   <target name="antunit-tests" depends="build,test-init,-antunit-warn-location" if="run.antunit"
           description="--> run the antunit tests">
     <condition property="antunit.includes" value="${antunit.testcase}"
diff --git a/check.xml b/check.xml
index b5a6586..fe3bacc 100644
--- a/check.xml
+++ b/check.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,43 +18,65 @@
 <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
-    checkstyle and simian.
+    Check Ant codebase against certain code style guidelines using
+    Checkstyle, Apache Rat, SpotBugs, OWASP Dependency Check, Simian
+    and Nu Html Checker (v.Nu).
 
     Checkstyle uses an abstract syntax tree (AST) for doing checks
-    against java sources. It is available at http://checkstyle.sourceforge.net/
+    against Java sources. It is available at https://checkstyle.org/
     under GPL 2.1 license.
 
-    "Simian (Similarity Analyser) identifies duplication in Java, C#, C,
-    CPP, COBOL, JSP, HTML source code and even plain text files."
-    It is available at http://www.redhillconsulting.com.au/products/simian/
+    "Apache Rat is a release audit tool, focused on licenses." It is available
+    at https://creadur.apache.org/rat/ under Apache License, Version 2.0.
+
+    "SpotBugs is a program which uses static analysis to look for bugs in Java
+    code." It is available at https://spotbugs.github.io/ under LGPL 3 license.
+
+    "Dependency-Check is a utility that identifies project dependencies and
+    checks if there are any known, publicly disclosed, vulnerabilities." It is
+    available at https://www.owasp.org/index.php/OWASP_Dependency_Check under
+    Apache License, Version 2.0.
+
+    "Simian (Similarity Analyser) identifies duplication in Java, C#, C, CPP,
+    COBOL, Ruby, JSP, ASP, HTML, XML, Visual Basic, Groovy source code and even
+    plain text files."  It is available at https://www.harukizaemon.com/simian/
     and is for free use in open source projects.
 
+    "The Nu Html Checker (v.Nu) is the backend of checker.html5.org,
+    html5.validator.nu, and validator.w3.org/nu." It is available at
+    https://validator.github.io/validator/ under MIT license.
+
     See external task page and homepages for more information.
   </description>
 
   <import file="build.xml"/>
+  <property name="reports.dir"
+            value="${build.dir}/reports"
+            description="Base directory for generated reports"/>
 
-  <property name="config.dir" location="${etc.dir}/checkstyle"/>
 
-  <!-- Ant Checkstyle report -->
+  <!-- Ant Checkstyle -->
+  <property name="checkstyle.src.dir" location="${etc.dir}/checkstyle"/>
+  <property name="checkstyle.version"
+            value="6.19"
+            description="Which version of Checkstyle to use"/>
   <property name="checkstyle.reportdir"
-            location="${build.dir}/reports/checkstyle"
+            location="${reports.dir}/checkstyle"
             description="Where to store Checkstyle reports"/>
   <property name="checkstyle.raw"
             location="${checkstyle.reportdir}/raw.xml"
-            description="Name of Checkstyle XML-Report"/>
+            description="Name of Checkstyle XML report"/>
   <property name="stylesheet.html"
-            location="${config.dir}/checkstyle-frames.xsl"
+            location="${checkstyle.src.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"
+            location="${checkstyle.src.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"
+            location="${checkstyle.src.dir}/checkstyle-text.xsl"
             description="Name of Checkstyle XSLT for generating plain text"/>
   <property name="stylesheet.xdoc"
-            location="${config.dir}/checkstyle-xdoc.xsl"
+            location="${checkstyle.src.dir}/checkstyle-xdoc.xsl"
             description="Name of Checkstyle XSLT for generating XDOC"/>
 
   <property name="checkstyle.basedir"
@@ -64,35 +86,38 @@
             value="**/*.java"
             description="Include pattern of the files to check"/>
 
-  <!-- Findbugs: Running Findbugs -->
+  <!-- Findbugs: Running SpotBugs -->
+  <property name="spotbugs.version"
+            value="3.1.4"
+            description="Which version of SpotBugs to use"/>
   <property name="findbugs.reportdir"
-            location="${build.dir}/reports/findbugs"
-            description="Where to store Findbugs results"/>
+            location="${reports.dir}/findbugs"
+            description="Where to store SpotBugs results"/>
   <property name="findbugs.raw"
             value="raw.xml"
-            description="Findbugs Output xml-file"/>
+            description="Name of SpotBugs XML report"/>
   <property name="findbugs.xsl"
             value="fancy.xsl"
-            description="Which XSL to use for generating Output: default, fancy, plain, summary"/>
+            description="Which XSL to use for generating output: default, fancy, plain, summary"/>
   <property name="findbugs.jvmargs"
             value="-Xms128m -Xmx512m"
-            description="JVMArgs for invoking Findbugs"/>
+            description="JVM arguments when invoking SpotBugs"/>
 
-  <!-- RAT Release Auditing Tool -->
+  <!-- Apache Rat: Release Auditing Tool -->
+  <property name="rat.version"
+            value="0.13"
+            description="Which version of Apache Rat to use"/>
   <property name="rat.report.dir"
-            value="${build.dir}/reports/rat"
-            description="Where to store the RAT reports"/>
+            value="${reports.dir}/rat"
+            description="Where to store Apache Rat reports"/>
   <property name="rat.report.file"
             value="${rat.report.dir}/report.html"
-            description="RAT-Report file"/>
-  <property name="rat.version"
-            value="0.11"
-            description="Which Version of RAT to use"/>
+            description="Name of Apache Rat report"/>
 
   <!-- Simian -->
   <property name="simian.version"
-            value="2.5.9"
-            description="Which Version of Simian to use"/>
+            value="2.5.10"
+            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"/>
@@ -100,13 +125,32 @@
             value="${build.dir}/simian-lib"
             description="Where to store Simian resources"/>
   <property name="simian.report.dir"
-            value="${build.dir}/simian"
+            value="${reports.dir}/simian"
             description="Where to store Simian reports"/>
 
+  <!-- OWASP Dependency Check -->
+  <property name="owasp.dc.version"
+            value="3.2.1"
+            description="Which version of OWASP Dependency Check to use"/>
+  <property name="owasp.dc.report.dir"
+            value="${reports.dir}/owasp-dc"
+            description="Where to store the OWASP Dependency Check reports"/>
+
+  <!-- Nu Html Checker -->
+  <property name="htmlcheck.nu.version"
+            value="18.11.5"
+            description="Which version of Nu Html Checker to use"/>
+  <property name="htmlcheck.report.dir"
+            value="${reports.dir}/html-check"
+            description="Directory where to store the HTML-Check report"/>
+  <property name="htmlcheck.report.file"
+            value="${htmlcheck.report.dir}/report.txt"
+            description="Report file of the HTML-Check"/>
+
 
   <target name="init-ivy">
-    <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.version"  value="2.5.0"/>
+    <property name="ivy.jar.url"  value="https://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"/>
     <mkdir dir="${ivy.jar.dir}"/>
@@ -117,7 +161,7 @@
     <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
   </target>
 
-  <target name="checkstyle" description="--> checks Ant codebase according to ${config.dir}/checkstyle-config" depends="init-ivy">
+  <target name="checkstyle" description="--> checks Ant codebase according to ${checkstyle.src.dir}/checkstyle-config" depends="init-ivy">
     <available property="antlr.present" classname="antlr.CommonAST"/>
     <echo if:set="antlr.present">
         Found antlr on the classpath.
@@ -126,11 +170,11 @@
         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" />
+      <ivy:cachepath organisation="com.puppycrawl.tools" module="checkstyle" revision="${checkstyle.version}"
+                     inline="true" conf="default" pathid="checkstyle.classpath"/>
+      <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">
+      <checkstyle config="${checkstyle.src.dir}/checkstyle-config" failOnViolation="false">
         <formatter type="xml" toFile="${checkstyle.raw}"/>
         <fileset dir="${java.dir}">
           <include name="${tocheck}"/>
@@ -167,7 +211,7 @@
 
   <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">
+          out="${checkstyle.reportdir}/xdocs/index.xml">
       <param name="basedir" expression="${checkstyle.basedir}"/>
     </xslt>
   </target>
@@ -203,7 +247,7 @@
     </taskdef>
     <mkdir dir="${simian.report.dir}"/>
     <simian failureProperty="simian.duplicates.found">
-        <fileset dir="${java.dir}" />
+        <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>
@@ -226,40 +270,66 @@
     <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="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" />
+  <target name="findbugs" description="--> checks Ant codebase with SpotBugs" depends="init-ivy,build"
+          xmlns:fb="http://findbugs.sourceforge.net/">
+    <!-- Path of optional libs is provided through CLI to forked JVM -->
+    <path id="optional.libs">
+      <fileset dir="lib/optional" includes="*.jar"/>
+    </path>
 
-    <!-- Start Findbugs -->
+    <ivy:cachepath organisation="com.github.spotbugs" module="spotbugs-ant" revision="${spotbugs.version}"
+                   inline="true" conf="default" pathid="spotbugs.classpath"/>
+    <!-- Load the SpotBugs AntTasks -->
+    <taskdef uri="http://findbugs.sourceforge.net/" resource="edu/umd/cs/findbugs/anttask/tasks.properties"
+             classpathref="spotbugs.classpath"/>
+
+    <!-- Start SpotBugs -->
     <mkdir dir="${findbugs.reportdir}"/>
-    <fb:findbugs pluginlistref="findbugs.real.classpath"
-                 classpathref="findbugs.real.classpath"
+    <fb:spotbugs classpathref="spotbugs.classpath"
                  output="xml:withMessages"
                  outputFile="${findbugs.reportdir}/${findbugs.raw}"
                  jvmargs="${findbugs.jvmargs}"
                  projectName="${Name} ${project.version}">
-      <class location="${build.classes}" />
-      <sourcePath path="${java.dir}" />
-    </fb:findbugs>
+      <class location="${build.classes}"/>
+      <sourcePath path="${java.dir}"/>
+      <auxClasspath refid="optional.libs"/>
+    </fb:spotbugs>
 
     <!-- Generate (human) readable output -->
     <xslt basedir="${findbugs.reportdir}" includes="${findbugs.raw}" destdir="${findbugs.reportdir}">
       <style>
-        <javaresource name="${findbugs.xsl}" classpathref="findbugs.real.classpath"/>
+        <javaresource name="${findbugs.xsl}" classpathref="spotbugs.classpath"/>
       </style>  
     </xslt>
   </target>
 
   <target name="rat" description="--> Runs the ReleaseAuditingTool" depends="init-ivy">
     <ivy:cachepath organisation="org.apache.rat" module="apache-rat-tasks" revision="${rat.version}"
-                   inline="true" conf="default" pathid="rat.classpath" transitive="true"/>
+                   inline="true" conf="default" pathid="rat.classpath"/>
     <typedef resource="org/apache/rat/anttasks/antlib.xml"
              uri="antlib:org.apache.rat.anttasks"
              classpathref="rat.classpath"/>
     <mkdir dir="${rat.report.dir}"/>
-    <rat:report xmlns:rat="antlib:org.apache.rat.anttasks" reportfile="${build.dir}/reports/rat/report.txt">
+    <rat:report xmlns:rat="antlib:org.apache.rat.anttasks" reportfile="${rat.report.dir}/report.txt">
+      <rat:fullTextMatcher licenseFamilyCategory="AL   "
+             licenseFamilyName="Apache License Version 2.0 with HTTPS reference">
+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
+
+   https://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.
+      </rat:fullTextMatcher>
+      <rat:approvedLicense
+             familyName="Apache License Version 2.0 with HTTPS reference"/>
       <fileset dir="${java.dir}">
         <exclude name="org/apache/tools/ant/defaultManifest.mf"/>
         <exclude name="org/apache/tools/ant/version.txt"/>
@@ -267,42 +337,35 @@
     </rat:report>
   </target>
 
-  <target name="dependency-check" description="--> Runs the OWASP dependency check">
-    <property name="dependency-check.url" value="http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-3.1.0-release.zip"/>
-    <property name="tools.dir" value="tools"/>
-    <property name="dependency-check.dir" value="${tools.dir}/dependency-check"/>
-    <property name="dependency-check.home" value="${dependency-check.dir}/dependency-check-ant"/>
-
-    <!--available property="dependency-check.present" file="${dependency-check.home}/dependency-check-ant/dependency-check-ant.jar"/-->
-    <condition property="dependency-check.present">
-      <resourcecount when="greater" count="0">
-        <fileset dir="${dependency-check.home}" includes="**/dependency-check-ant.jar"/>
-      </resourcecount>
-    </condition>
-    
-    <sequential unless:set="dependency-check.present">
-      <mkdir dir="${dependency-check.home}"/>
-      <get src="${dependency-check.url}" dest="${dependency-check.dir}/dependency-check-ant.zip"/>
-      <unzip src="${dependency-check.dir}/dependency-check-ant.zip" dest="${dependency-check.dir}/dependency-check-ant"/>
-    </sequential>
-
-    <path id="dependency-check.path">
-      <pathelement location="${dependency-check.home}/dependency-check-ant.jar"/>
-      <fileset dir="${dependency-check.home}">
-        <include name="**/*.jar"/>
-      </fileset>
-    </path>
-    <taskdef resource="dependency-check-taskdefs.properties" uri="https://jeremylong.github.io/">
-      <classpath refid="dependency-check.path"/>
-    </taskdef>
-
-    <owasp:dependency-check
-        xmlns:owasp="https://jeremylong.github.io/"
-        projectName="${ant.project.name}"
-    >
+  <target name="dependency-check" description="--> Runs the OWASP Dependency Check" depends="init-ivy">
+    <ivy:cachepath organisation="org.owasp" module="dependency-check-ant" revision="${owasp.dc.version}"
+                   inline="true" conf="default" pathid="owasp.dc.classpath"/>
+    <taskdef resource="dependency-check-taskdefs.properties" uri="https://jeremylong.github.io/"
+             classpathref="owasp.dc.classpath"/>
+    <mkdir dir="${owasp.dc.report.dir}"/>
+    <owasp:dependency-check xmlns:owasp="https://jeremylong.github.io/"
+                            projectName="${ant.project.name}"
+                            reportOutputDirectory="${owasp.dc.report.dir}">
       <fileset dir="lib" includes="**/*.jar"/>
       <fileset dir="." includes="dist/**/*.jar"/>
     </owasp:dependency-check>
   </target>
 
+  <target name="html-check" description="--> Runs the Nu Html Checker" depends="init-ivy">
+    <ivy:cachepath organisation="nu.validator" module="validator" revision="${htmlcheck.nu.version}"
+                   inline="true" conf="default" pathid="nu.classpath"/>
+    <fileset dir="." id="html.files">
+      <include name="${src.dir}/**/*.html"/>
+      <include name="${manual.dir}/**/*.html"/>
+      <exclude name="${manual.dir}/index.html"/>
+    </fileset>
+    <pathconvert pathsep=" " property="html.list" refid="html.files"/>
+    <mkdir dir="${htmlcheck.report.dir}"/>
+    <java classname="nu.validator.client.SimpleCommandLineValidator" classpathref="nu.classpath"
+          taskname="html-check" output="${htmlcheck.report.file}">
+      <arg line="--html --format text"/>
+      <arg line="${html.list}"/>
+    </java>
+    <concat><file name="${htmlcheck.report.file}"/></concat>
+  </target>
 </project>
diff --git a/contributors.xml b/contributors.xml
index 8e161bc..ddc55ec 100644
--- a/contributors.xml
+++ b/contributors.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -40,6 +40,14 @@
   </name>
   <name>
     <first>Adam</first>
+    <last>Murdoch</last>
+  </name>
+  <name>
+    <first>Adam</first>
+    <last>Retter</last>
+  </name> 
+  <name>
+    <first>Adam</first>
     <last>Sotona</last>
   </name>
   <name>
@@ -47,10 +55,22 @@
     <last>Nistor</last>
   </name>
   <name>
+    <first>Adrien</first>
+    <last>Grand</last>
+  </name>
+  <name>
     <first>Aleksandr</first>
     <last>Ishutin</last>
   </name>
   <name>
+    <first>Aleksei</first>
+    <last>Zotov</last>
+  </name>
+  <name>
+    <first>Alex</first>
+    <last></last>
+  </name>
+  <name>
     <first>Alex</first>
     <last>Rosen</last>
   </name>
@@ -83,6 +103,10 @@
     <last>Ames</last>
   </name>
   <name>
+    <first>Andreas</first>
+    <last>Mross</last>
+  </name>
+  <name>
     <first>Andrew</first>
     <last>Eisenberg</last>
   </name>
@@ -136,6 +160,10 @@
     <last>Mazkovoi</last>
   </name>
   <name>
+    <first>Arcadius</first>
+    <last>Ahouansou</last>
+  </name>
+  <name>
     <first>Arjan</first>
     <last>Veenstra</last>
   </name>
@@ -149,8 +177,16 @@
     <last>Kuiper</last>
   </name>
   <name>
+    <first>Arturo</first>
+    <last>Bernal</last>
+  </name>
+  <name>
+    <first>Arun</first>
+    <last>Jamwal</last>
+  </name>
+  <name>
     <first>Aslak</first>
-    <last>Helles&#244;y</last>
+    <last>Hellesôy</last>
   </name>
   <name>
     <first>Atsuhiko</first>
@@ -165,10 +201,17 @@
     <last>Fejes 2</last>
   </name>
   <name>
+    <last>barney2k7</last>
+  </name>
+  <name>
     <first>Bart</first>
     <last>Vanhaute</last>
   </name>
   <name>
+    <first>Basil</first>
+    <last>Crow</last>
+  </name>
+  <name>
     <first>Benjamin</first>
     <last>Burgess</last>
   </name>
@@ -222,6 +265,14 @@
     <last>Atherton</last>
   </name>
   <name>
+    <first>Cedomir</first>
+    <last>Igaly</last>
+  </name>
+  <name>
+    <first>Charles</first>
+    <last>Duffy</last>
+  </name>
+  <name>
     <first>Charles</first>
     <last>Hudak</last>
   </name>
@@ -287,6 +338,10 @@
     <last>MacNeill</last>
   </name>
   <name>
+    <first>Costin</first>
+    <last>Manolache</last>
+  </name>
+  <name>
     <first>Craeg</first>
     <last>Strong</last>
   </name>
@@ -296,16 +351,20 @@
   </name>
   <name>
     <first>Craig</first>
+    <last>Pell</last>
+  </name>
+  <name>
+    <first>Craig</first>
     <middle>R.</middle>
     <last>McClanahan</last>
   </name>
   <name>
     <first>Craig</first>
-    <last>Ryan</last>
+    <last>Richardson</last>
   </name>
   <name>
     <first>Craig</first>
-    <last>Richardson</last>
+    <last>Ryan</last>
   </name>
   <name>
     <first>Craig</first>
@@ -372,6 +431,10 @@
     <last>Briones</last>
   </name>
   <name>
+    <first>Darrell</first>
+    <last>DeBoer</last>
+  </name>
+  <name>
     <first>Davanum</first>
     <last>Srinivas</last>
   </name>
@@ -385,7 +448,8 @@
   </name>
   <name>
     <first>David</first>
-    <last>A.</last>
+    <middle>A.</middle>
+    <last>Herman</last>
   </name>
   <name>
     <first>David</first>
@@ -393,7 +457,7 @@
   </name>
   <name>
     <first>David</first>
-    <last>G&#228;rtner</last>
+    <last>Gärtner</last>
   </name>
   <name>
     <first>David</first>
@@ -456,12 +520,8 @@
     <last>Devienne</last>
   </name>
   <name>
-    <first>Donal</first>
-    <last>Quinlan</last>
-  </name>
-  <name>
     <first>Don</first>
-    <last>Bnamen</last>
+    <last>Brown</last>
   </name>
   <name>
     <first>Don</first>
@@ -472,6 +532,14 @@
     <last>Jeffery</last>
   </name>
   <name>
+    <first>Donal</first>
+    <last>Quinlan</last>
+  </name>
+  <name>
+    <first>Donald</first>
+    <last>Leslie</last>
+  </name>
+  <name>
     <first>Drew</first>
     <last>Sudell</last>
   </name>
@@ -500,6 +568,14 @@
     <last>Bourg</last>
   </name>
   <name>
+    <first>Eugène</first>
+    <last>Adell</last>
+  </name>
+  <name>
+    <first>Eric</first>
+    <last>Delaunay</last>
+  </name>
+  <name>
     <first>Eric</first>
     <last>Olsen</last>
   </name>
@@ -556,6 +632,10 @@
     <last>Lavigne</last>
   </name>
   <name>
+    <first>Gal</first>
+    <last>Shachor</last>
+  </name>
+  <name>
     <first>Gary</first>
     <middle>S.</middle>
     <last>Weaver</last>
@@ -605,6 +685,10 @@
     <last>Twiggs</last>
   </name>
   <name>
+    <first>Gösen</first>
+    <last></last>
+  </name>
+  <name>
     <first>Greg</first>
     <last>Nelson</last>
   </name>
@@ -633,6 +717,10 @@
     <last>Rafique</last>
   </name>
   <name>
+    <first>Helder</first>
+    <last>Pereira</last>
+  </name>
+  <name>
     <first>Hiroaki</first>
     <last>Nakamura</last>
   </name>
@@ -677,11 +765,20 @@
     <last>Bleijenbergh</last>
   </name>
   <name>
+    <first>JC</first>
+    <last>Mann</last>
+  </name>
+  <name>
     <first>Jack</first>
     <middle>J.</middle>
     <last>Woehr</last>
   </name>
   <name>
+    <first>Jacobus</first>
+    <middle>Martinus</middle>
+    <last>Kruithof</last>
+  </name>
+  <name>
     <first>Jaikiran</first>
     <last>Pai</last>
   </name>  
@@ -691,12 +788,16 @@
     <last>Davidson</last>
   </name>
   <name>
+    <first>James</first>
+    <last>Todd</last>
+  </name>
+  <name>
     <first>Jan</first>
     <last>Cumps</last>
   </name>
   <name>
     <first>Jan</first>
-    <last>Mat&#232;rne</last>
+    <last>Matèrne</last>
   </name>
   <name>
     <first>Jan</first>
@@ -736,18 +837,14 @@
     <last>van der Meer</last>
   </name>
   <name>
-    <first>JC</first>
-    <last>Mann</last>
-  </name>
-  <name>
-    <first>J</first>
-    <last>D</last>
-  </name>
-  <name>
     <first>Jean-Francois</first>
     <last>Brousseau</last>
   </name>
   <name>
+    <first>Jean-Louis</first>
+    <last>Boudart</last>
+  </name>
+  <name>
     <first>Jeff</first>
     <last>Gettle</last>
   </name>
@@ -796,14 +893,14 @@
     <last>Casey</last>
   </name>
   <name>
-    <first>Joerg</first>
-    <last>Wassmer</last>
-  </name>
-  <name>
     <first>Joel</first>
     <last>Tucci</last>
   </name>
   <name>
+    <first>Joerg</first>
+    <last>Wassmer</last>
+  </name>
+  <name>
     <first>Joey</first>
     <last>Richey</last>
   </name>
@@ -833,19 +930,24 @@
     <last>Stevens</last>
   </name>
   <name>
+    <first>Jonathan</first>
+    <middle>K.</middle>
+    <last>Schneider</last>
+  </name>
+  <name>
     <first>Jose</first>
     <middle>Alberto</middle>
     <last>Fernandez</last>
   </name>
   <name>
-    <first>Josh</first>
-    <last>Lucas</last>
-  </name>
-  <name>
     <first>Joseph</first>
     <last>Walton</last>
   </name>
   <name>
+    <first>Josh</first>
+    <last>Lucas</last>
+  </name>
+  <name>
     <first>Juerg</first>
     <last>Wanner</last>
   </name>
@@ -854,10 +956,22 @@
     <last>Simpson</last>
   </name>
   <name>
+    <first>Julien</first>
+    <last>Lepiller</last>
+  </name>
+  <name>
     <first>Justin</first>
     <last>Vallon</last>
   </name>
   <name>
+    <first>Justyna</first>
+    <last>Horwat</last>
+  </name>
+  <name>
+    <first>Karl</first>
+    <last>Jansen</last>
+  </name>
+  <name>
     <first>Keiron</first>
     <last>Liddle</last>
   </name>
@@ -884,7 +998,7 @@
   </name>
   <name>
     <first>Kevin</first>
-    <middle>Z</middle>
+    <middle>Z.</middle>
     <last>Grey</last>
   </name>
   <name>
@@ -939,6 +1053,10 @@
     <last>Claude</last>
   </name>
   <name>
+    <first>Maarten</first>
+    <last>Coene</last>
+  </name>
+  <name>
     <first>Magesh</first>
     <last>Umasankar</last>
   </name>
@@ -947,6 +1065,14 @@
     <last>Sahu</last>
   </name>
   <name>
+    <first>Marc</first>
+    <last>Guillemot</last>
+  </name>
+  <name>
+    <first>Marc</first>
+    <last>Strapetz</last>
+  </name>
+  <name>
     <first>Marcel</first>
     <last>Schutte</last>
   </name>
@@ -964,15 +1090,24 @@
   </name>
   <name>
     <first>Mark</first>
+    <middle>A.</middle>
+    <last>Ziesemer</last>
+  </name>
+  <name>
+    <first>Mark</first>
     <last>DeLaFranier</last>
   </name>
   <name>
     <first>Mark</first>
+    <last>Harmer</last>
+  </name>
+  <name>
+    <first>Mark</first>
     <last>Hecker</last>
   </name>
   <name>
     <first>Mark</first>
-    <last>Salter</last>
+    <last>Niggemann</last>
   </name>
   <name>
     <first>Mark</first>
@@ -981,12 +1116,7 @@
   </name>
   <name>
     <first>Mark</first>
-    <last>Niggemann</last>
-  </name>
-  <name>
-    <first>Mark</first>
-    <middle>A.</middle>
-    <last>Ziesemer</last>
+    <last>Salter</last>
   </name>
   <name>
     <first>Markus</first>
@@ -1013,6 +1143,14 @@
     <last>von Gagern</last>
   </name>
   <name>
+    <first>Mathieu</first>
+    <last>Champlon</last>
+  </name>
+  <name>
+    <first>Mathieu</first>
+    <last>Peltier</last>
+  </name>
+  <name>
     <first>Matt</first>
     <last>Albrecht</last>
   </name>
@@ -1045,18 +1183,6 @@
     <last>Wildig</last>
   </name>
   <name>
-    <first>Mathieu</first>
-    <last>Champlon</last>
-  </name>
-  <name>
-    <first>Mathieu</first>
-    <last>Peltier</last>
-  </name>
-  <name>
-    <first>Matthias</first>
-    <last>Bhend</last>
-  </name>
-  <name>
     <first>Matthew</first>
     <last>Hawthorne</last>
   </name>
@@ -1071,6 +1197,10 @@
   </name>
   <name>
     <first>Matthew</first>
+    <last>Warman</last>
+  </name>
+  <name>
+    <first>Matthew</first>
     <last>Watson</last>
   </name>
   <name>
@@ -1078,6 +1208,19 @@
     <last>Yanos</last>
   </name>
   <name>
+    <first>Matthias</first>
+    <last>Bhend</last>
+  </name>
+  <name>
+    <first>Matthias</first>
+    <last>Gutheil</last>
+  </name>
+  <name>
+    <first>Matthias</first>
+    <middle>Johann</middle>
+    <last>Vill</last>
+  </name>
+  <name>
     <first>Michael</first>
     <last>Bayne</last>
   </name>
@@ -1100,6 +1243,10 @@
   </name>
   <name>
     <first>Michael</first>
+    <last>Montuori</last>
+  </name>
+  <name>
+    <first>Michael</first>
     <last>Newcomb</last>
   </name>
   <name>
@@ -1111,6 +1258,14 @@
     <last>Saunders</last>
   </name>
   <name>
+    <first>Michael</first>
+    <last>Seele</last>
+  </name>
+  <name>
+    <first>Mickaël</first>
+    <last>Guessant</last>
+  </name>
+  <name>
     <last>Miha</last>
   </name>
   <name>
@@ -1126,11 +1281,12 @@
     <last>Williams</last>
   </name>
   <name>
-    <first>Miroslav</first>
-    <last>Zaťko</last>
+    <first>Mikolaj</first>
+    <last>Izdebski</last>
   </name>
   <name>
-    <last>mnowostawski</last>
+    <first>Miroslav</first>
+    <last>Zaťko</last>
   </name>
   <name>
     <first>Mounir</first>
@@ -1150,21 +1306,34 @@
   </name>
   <name>
     <first>Nick</first>
+    <last>Davis</last>
+  </name>
+  <name>
+    <first>Nick</first>
     <last>Fortescue</last>
   </name>
   <name>
     <first>Nick</first>
+    <last>King</last>
+  </name>
+  <name>
+    <first>Nick</first>
     <last>Pellow</last>
   </name>
   <name>
-    <first>Nicola</first>
-    <last>Ken</last>
-  </name>
-  <name>
     <first>Nico</first>
     <last>Seessle</last>
   </name>
   <name>
+    <first>Nicola</first>
+    <middle>Ken</middle>
+    <last>Barozzi</last>
+  </name>
+  <name>
+    <first>Nicolas</first>
+    <last>Lalevée</last>
+  </name>
+  <name>
     <first>Nigel</first>
     <last>Magnay</last>
   </name>
@@ -1177,6 +1346,10 @@
     <last>Rossmueller</last>
   </name>
   <name>
+    <first>Olivier</first>
+    <last>Parent</last>
+  </name>
+  <name>
     <first>Omer</first>
     <last>Shapira</last>
   </name>
@@ -1185,16 +1358,13 @@
     <last>Medek</last>
   </name>
   <name>
-    <first>&#216;ystein</first>
-    <last>Gisn&#229;s</last>
-  </name>
-  <name>
     <first>Patrick</first>
     <last>Altaie</last>
   </name>
   <name>
     <first>Patrick</first>
-    <last>C.</last>
+    <middle>C.</middle>
+    <last>Beard</last>
   </name>
   <name>
     <first>Patrick</first>
@@ -1202,7 +1372,12 @@
   </name>
   <name>
     <first>Patrick</first>
-    <last>Gus</last>
+    <middle>Gus</middle>
+    <last>Heck</last>
+  </name>
+  <name>
+    <first>Patrick</first>
+    <last>Martin</last>
   </name>
   <name>
     <first>Paul</first>
@@ -1286,8 +1461,8 @@
     <last>Dittgen</last>
   </name>
   <name>
-    <first>R</first>
-    <last>Handerson</last>
+    <first>Preston</first>
+    <last>Bannister</last>
   </name>
   <name>
     <first>Ralf</first>
@@ -1310,6 +1485,10 @@
     <last>Waldin</last>
   </name>
   <name>
+    <first>Razzi</first>
+    <last>Abuissa</last>
+  </name>
+  <name>
     <first>Reinhard</first>
     <last>Pointner</last>
   </name>
@@ -1338,11 +1517,24 @@
     <last>Beton</last>
   </name>
   <name>
+    <first>Rob</first>
+    <last>Riasol</last>
+  </name>
+  <name>
+    <first>Rob</first>
+    <last>Oxspring</last>
+  </name>
+  <name>
+    <first>Rob</first>
+    <last>van Oostrum</last>
+  </name>
+  <name>
     <first>Robbie</first>
     <last>Gibson</last>
   </name>
   <name>
     <first>Robert</first>
+    <middle>H.</middle>
     <last>Anderson</last>
   </name>
   <name>
@@ -1382,14 +1574,6 @@
     <last>Verduijn</last>
   </name>
   <name>
-    <first>Rob</first>
-    <last>Oxspring</last>
-  </name>
-  <name>
-    <first>Rob</first>
-    <last>van Oostrum</last>
-  </name>
-  <name>
     <first>Rodrigo</first>
     <last>Schmidt</last>
   </name>
@@ -1426,6 +1610,11 @@
     <last>Metz</last>
   </name>
   <name>
+    <first>Santosh</first>
+    <middle>R.</middle>
+    <last>Dhariwal</last>
+  </name>
+  <name>
     <first>Scott</first>
     <last>Carlson</last>
   </name>
@@ -1452,6 +1641,10 @@
     <last>Kane</last>
   </name>
   <name>
+    <first>Sebastian</first>
+    <last>Kantha</last>
+  </name>
+  <name>
     <first>Sebastien</first>
     <last>Arod</last>
   </name>
@@ -1460,12 +1653,16 @@
     <last>Kanga</last>
   </name>
   <name>
-    <first>Sebastian</first>
-    <last>Kantha</last>
+    <first>Simeon</first>
+    <last>Fitch</last>
   </name>
   <name>
-      <first>Simon</first>
-      <last>Law</last>
+    <first>Simon</first>
+    <last>Law</last>
+  </name>
+  <name>
+    <first>Simon</first>
+    <last>Legner</last>
   </name>
   <name>
     <first>Simone</first>
@@ -1484,6 +1681,13 @@
     <last>Mazzocchi</last>
   </name>
   <name>
+    <last>stephan</last>
+  </name>
+  <name>
+    <first>Stephan</first>
+    <last>Michels</last>
+  </name>
+  <name>
     <first>Stephan</first>
     <last>Strittmatter</last>
   </name>
@@ -1492,15 +1696,12 @@
     <last>Bailliez</last>
   </name>
   <name>
-    <last>stephan</last>
-  </name>
-  <name>
-    <first>Stephan</first>
-    <last>Michels</last>
+    <first>Stephen</first>
+    <last>Chin</last>
   </name>
   <name>
     <first>Stephen</first>
-    <last>Chin</last>
+    <last>Goetze</last>
   </name>
   <name>
     <first>Steve</first>
@@ -1548,6 +1749,10 @@
     <last>Master</last>
   </name>
   <name>
+    <first>Taylor</first>
+    <last>Smock</last>
+  </name>
+  <name>
     <first>Thomas</first>
     <last>Aglassinger</last>
   </name>
@@ -1585,6 +1790,10 @@
   </name>
   <name>
     <first>Tim</first>
+    <last>Stephenson</last>
+  </name>
+  <name>
+    <first>Tim</first>
     <last>Whittington</last>
   </name>
   <name>
@@ -1597,8 +1806,8 @@
     <last>Endres</last>
   </name>
   <name>
-    <first>Tim</first>
-    <last>Stephenson</last>
+    <first>TJ</first>
+    <last>Rothwell</last>
   </name>
   <name>
     <first>Tom</first>
@@ -1606,6 +1815,10 @@
   </name>
   <name>
     <first>Tom</first>
+    <last>Brus</last>
+  </name>
+  <name>
+    <first>Tom</first>
     <last>Cunningham</last>
   </name>
   <name>
@@ -1629,8 +1842,12 @@
     <last>Zezula</last>
   </name>
   <name>
+    <first>Tony</first>
+    <last>Gravagno</last>
+  </name>
+  <name>
     <first>Trejkaz</first>
-    <last>Xaoz</last>
+    <last>Xaoza</last>
   </name>
   <name>
     <first>Ulrich</first>
@@ -1649,6 +1866,14 @@
     <last>Toni</last>
   </name>
   <name>
+    <first>Ville</first>
+    <last>Skyttä</last>
+  </name>
+  <name>
+    <first>Vimil</first>
+    <last>Saju</last>
+  </name>
+  <name>
     <first>Vincent</first>
     <last>Legoll</last>
   </name>
@@ -1657,22 +1882,30 @@
     <last>Privat</last>
   </name>
   <name>
-    <first>Vimil</first>
-    <last>Saju</last>
-  </name>
-  <name>
     <first>Vitold</first>
     <last>Sedyshev</last>
   </name>
   <name>
+    <first>Vladislav</first>
+    <last>Bauer</last>
+  </name>
+  <name>
     <first>Volker</first>
     <last>Leidl</last>
   </name>
   <name>
+    <first>Waldek</first>
+    <last>Herka</last>
+  </name>
+  <name>
     <first>Wang</first>
     <last>Weijun</last>
   </name>
   <name>
+    <first>Wenjing</first>
+    <last>Wang</last>
+  </name>
+  <name>
     <first>Will</first>
     <last>Wang</last>
   </name>
@@ -1717,6 +1950,10 @@
     <last>Witdouck</last>
   </name>
   <name>
+    <first>Xia</first>
+    <last>Li</last>
+  </name>
+  <name>
     <first>Yohann</first>
     <last>Roussel</last>
   </name>
@@ -1737,7 +1974,7 @@
     <last>Wagner</last>
   </name>
   <name>
-    <first/>
-    <last>riasol</last>
+    <first>Øystein</first>
+    <last>Gisnås</last>
   </name>
 </contributors>
diff --git a/docs.xml b/docs.xml
index 3f80b26..cccd2cb 100644
--- a/docs.xml
+++ b/docs.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -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/fetch.xml b/fetch.xml
index 106237d..ac231ea 100644
--- a/fetch.xml
+++ b/fetch.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
@@ -98,7 +98,7 @@
 
 
   <target name="macros" depends="pick-dest,get-m2"
-          xmlns:artifact="antlib:org.apache.maven.artifact.ant">
+          xmlns:resolver="antlib:org.apache.maven.resolver.ant">
     <fail>
       Cannot execute multiple targets due to the bug in Maven Ant tasks
       <condition>
@@ -119,16 +119,21 @@
             </not>
           </condition>
         </fail>
-        <artifact:dependencies pathID="@{archive}.path" useScope="runtime">
-          <dependency groupId="@{project}"
-                      artifactId="@{archive}"
-                      version="${@{archive}.version}">
-            <!-- exclude dependencies of ant-antunit (they should be in optional scope) -->
-            <exclusion groupId="org.apache.ant" artifactId="ant"/>
-            <exclusion groupId="org.apache.ant" artifactId="ant-launcher"/>
-          </dependency>
-          <artifact:remoteRepository url="@{repository}" id="@{id}"/>
-        </artifact:dependencies>
+        <resolver:remoterepo url="@{repository}" id="@{id}"/>
+        <resolver:resolve>
+          <dependencies id="@{archive}.path">
+            <dependency groupId="@{project}"
+                        artifactId="@{archive}"
+                        version="${@{archive}.version}"
+                        scope="runtime">
+              <!-- exclude dependencies of ant-antunit (they should be in optional scope) -->
+              <exclusion groupId="org.apache.ant" artifactId="ant"/>
+              <exclusion groupId="org.apache.ant" artifactId="ant-launcher"/>
+            </dependency>
+          </dependencies>
+          <!-- create a path containing all these resolved dependencies -->
+          <path refid="@{archive}.path"/>
+        </resolver:resolve>
         <!-- now we are left with the problem of getting the files into our directory -->
         <copy todir="${dest.dir}">
           <path refid="@{archive}.path"/>
@@ -232,6 +237,24 @@
     <f2 project="org.hamcrest" archive="hamcrest-library"/>
   </target>
 
+  <target name="junitlauncher"
+    description="load junitlauncher libraries"
+    depends="init">
+    <f2 project="org.junit.platform" archive="junit-platform-launcher" />
+  </target>
+
+  <target name="junit-engine-jupiter"
+          description="load junit jupiter engine libraries (necessary only for internal Ant project tests)"
+          depends="init">
+    <f2 project="org.junit.jupiter" archive="junit-jupiter-engine" />
+  </target>
+
+  <target name="junit-engine-vintage"
+          description="load junit vintage engine libraries (necessary only for internal Ant project tests)"
+          depends="init">
+    <f2 project="org.junit.vintage" archive="junit-vintage-engine" />
+  </target>
+
   <target name="xml"
           description="load full XML libraries (Xalan and xml-resolver)"
           depends="init">
@@ -262,7 +285,7 @@
   <target name="bcel"
           description="load Byte Code Engineering Library (BCEL)"
           depends="init">
-    <f2 project="bcel"/>
+    <f2 project="org.apache.bcel" archive="bcel"/>
   </target>
 
   <target name="jdepend"
@@ -287,7 +310,6 @@
           description="load BeanShell support"
           depends="bsf">
     <f2 project="org.beanshell" archive="bsh"/>
-    <f2 project="org.beanshell" archive="bsh-core"/>
   </target>
 
   <target name="jython"
@@ -302,9 +324,15 @@
     <f2 project="org.mozilla" archive="rhino"/>
   </target>
 
+  <target name="graal.js"
+          description="load Graal.js">
+    <f2 project="org.graalvm.js" archive="js"/>
+    <f2 project="org.graalvm.js" archive="js-scriptengine"/>
+  </target>
+
   <target name="script"
           description="load script languages (except Jython)"
-          depends="bsf,jruby,beanshell,rhino"/>
+          depends="bsf,jruby,beanshell,rhino,graal.js"/>
 
   <target name="debugging"
     description="internal Ant debugging"
@@ -315,11 +343,17 @@
   <target name="javamail"
           description="load Java Mail"
           depends="init">
+    <f2 project="com.sun.mail" archive="javax.mail"/>
+  </target>
+
+  <target name="jakartamail"
+          description="load Jakarta Mail"
+          depends="init">
     <!-- We only need this one dependency as per
-      the project doc https://javaee.github.io/javamail/#Download_JavaMail_Release
+      the project doc https://eclipse-ee4j.github.io/mail/
       This alone should bring in all necessary dependencies (including the API
        jars and the activation jars -->
-    <f2 project="com.sun.mail" archive="javax.mail"/>
+    <f2 project="com.sun.mail" archive="jakarta.mail"/>
   </target>
 
   <target name="jspc"
@@ -371,8 +405,14 @@
          dest="${temp.dir}/NetRexx.zip" skipexisting="true"/>
   </target>
 
+  <target name="xz"
+          description="load XZ for Java"
+          depends="init">
+    <f2 project="org.tukaani" archive="xz"/>
+  </target>
+
   <target name="all"
     description="load all the libraries (except jython)"
-    depends="antunit,ivy,logging,junit,xml,networking,regexp,antlr,bcel,jdepend,bsf,debugging,script,javamail,jspc,jai,netrexx"/>
-
+    depends="antunit,ivy,logging,junit,junitlauncher,xml,networking,regexp,antlr,bcel,jdepend,bsf,debugging,script,
+      javamail,jakartamail,jspc,jai,xz,junit-engine-vintage,junit-engine-jupiter,netrexx"/>
 </project>
diff --git a/get-m2.xml b/get-m2.xml
index 4111e81..c0c540b 100644
--- a/get-m2.xml
+++ b/get-m2.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
@@ -48,10 +48,10 @@
   <property file="get-m2.properties" />
 
   <property name="m2.antlib.resource"
-            value="org/apache/maven/artifact/ant/antlib.xml" />
+            value="org/apache/maven/resolver/ant/antlib.xml" />
 
   <property name="m2.antlib.uri"
-            value="antlib:org.apache.maven.artifact.ant" />
+            value="antlib:org.apache.maven.resolver.ant" />
 
   <macrodef name="require">
     <attribute name="property" />
@@ -100,7 +100,7 @@
   </target>
 
   <target name="checksum-mismatch" depends="validate-m2-checksum"
-          if="m2.sha1.checksum" unless="checksum.equal">
+          if="m2.sha1.checksum" unless="${checksum.equal}">
     <delete file="${m2.artifact}" />
     <fail>
       Failed to verify the downloaded file ${m2.antlib.url}" against the checksum
@@ -116,6 +116,6 @@
   </target>
 
   <target name="get-m2" depends="checksum-match"
-      description="Download the Maven2 Ant tasks" />
+      description="Download the Maven Artifact Resolver Ant tasks" />
 
 </project>
diff --git a/java-latest-ea-ci.xml b/java-latest-ea-ci.xml
new file mode 100644
index 0000000..70e6f2e
--- /dev/null
+++ b/java-latest-ea-ci.xml
@@ -0,0 +1,51 @@
+<?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
+
+       https://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.
+-->
+
+
+<!-- This build file is here to help with the CI jobs in Jenkins where we
+	download and run the Ant tests against the latest early access binaries of
+	Java -->
+<project default="download-jdk">
+	<property environment="env"/>
+	<target name="download-jdk" depends="check-file-type, download-extract-zip, download-extract-tar"/>
+	<target name="check-file-type">
+		<condition property="zip-artifact">
+			<!-- check if it ends with .zip -->
+  			<matches string="${env.JDK_DOWNLOAD_URL}" pattern="\.zip$"/>
+		</condition>
+		<condition property="tar-artifact">
+			<!-- check if it ends with .tar.gz -->
+			<matches string="${env.JDK_DOWNLOAD_URL}" pattern="\.tar.gz$"/>
+		</condition>
+	</target>
+	<target name="download-extract-zip" if="zip-artifact">
+		<echo message="Downloading zip file from ${env.JDK_DOWNLOAD_URL}"/>
+		<get src="${env.JDK_DOWNLOAD_URL}" dest="${basedir}/jdk.zip"/>
+		<unzip src="jdk.zip" dest="${basedir}/java-latest-ea"/>
+	</target>
+	<target name="download-extract-tar" if="tar-artifact">
+		<echo message="Downloading tar.gz file from ${env.JDK_DOWNLOAD_URL}"/>
+		<get src="${env.JDK_DOWNLOAD_URL}" dest="${basedir}/jdk.tar.gz"/>
+		<untar src="jdk.tar.gz" dest="${basedir}/java-latest-ea" compression="gzip"/>
+		<!-- restore permission on the extracted tar's bin directory contents -->
+		<echo message="restoring permissions of files in directory ${basedir}/java-latest-ea/**/bin/*"/>
+		<chmod dir="${basedir}/java-latest-ea/" perm="a+x" includes="**/bin/*"/>
+	</target>
+
+</project>
\ No newline at end of file
diff --git a/launch-build.xml b/launch-build.xml
index 753ef2b..0c5feea 100644
--- a/launch-build.xml
+++ b/launch-build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/lib/libraries.properties b/lib/libraries.properties
index 62ef19c..f6c0356 100644
--- a/lib/libraries.properties
+++ b/lib/libraries.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
@@ -16,14 +16,14 @@
 # This file declares the libraries for use in a given release of the components
 
 # If you change this, change the checksum to match
-m2.version=2.1.3
-m2.url=https://archive.apache.org/dist/maven/ant-tasks
-m2.artifact-name=maven-ant-tasks
-m2.jar.name=${m2.artifact-name}-${m2.version}.jar
+m2.version=1.4.0
+m2.url=https://repo1.maven.org/maven2/org/apache/maven/resolver
+m2.artifact-name=maven-resolver-ant-tasks
+m2.jar.name=${m2.artifact-name}-${m2.version}-uber.jar
 #this is the URL of the antlib library, that is pulled down for everything else.
-m2.antlib.url=${m2.url}/${m2.version}/binaries/${m2.jar.name}
+m2.antlib.url=${m2.url}/${m2.artifact-name}/${m2.version}/${m2.jar.name}
 #this is the sha1 checksum of the artifact
-m2.sha1.checksum=b09be554228d66d208e5fef5266844aacf443abc
+m2.sha1.checksum=c4642858aa22465650ad2a469b24e22696177441
 
 # Repository to use by default for fetching dependencies.
 m2.repo=https://repo1.maven.org/maven2/
@@ -33,36 +33,45 @@
 
 # Versions of different libraries. Please keep in alphabetical order, except
 # when a specific dependency forces them to be out-of-order
-ivy.version=2.4.0
-activation.version=1.1.1
+ivy.version=2.5.0
 ant-antunit.version=1.4.1
 antlr.version=2.7.7
-bcel.version=5.1
+bcel.version=6.5.0
 bsf.version=2.4.0
-bsh.version=2.0b4
-bsh-core.version=${bsh.version}
-# Later versions are built with Java 6
-commons-net.version=2.2
+bsh.version=2.0b5
+commons-net.version=3.8.0
 commons-logging.version=1.1
 commons-logging-api.version=${commons-logging.version}
+js.version=20.1.0
+js-scriptengine.version=${js.version}
+# Note - When updating the hamcrest versions here, make sure to also update the
+# "src-dist" target in build.xml to copy the correct hamcrest jars
+# into the source distribution
 hamcrest-core.version=1.3
 hamcrest-library.version=${hamcrest-core.version}
 jai-core.version=1.1.3
 jai-codec.version=1.1.3
+# Later 1.6 versions call themselves "jakarta.mail" but do not use the namespace yet
+javax.mail.version=1.6.2
+jakarta.mail.version=2.0.1
 jakarta-regexp.version=1.4
 # Later versions of Tomcat provide a jspc task
 jasper-compiler.version=4.1.36
 jasper-runtime.version=${jasper-compiler.version}
-# Later versions are built with Java 7
-javax.mail.version=1.5.6
 jdepend.version=2.9.1
-# Later versions are built with Java 7
 jruby.version=1.6.8
+# Note - When updating the junit.version here, make sure to also update the
+# "src-dist" target in build.xml to copy the correct junit 4.x jar
+# into the source distribution
 junit.version=4.13.1
-# Later versions are built with Java 6
-rhino.version=1.7R5
+rhino.version=1.7.11
+junit-platform-launcher.version=1.8.2
+# Only used for internal tests in Ant project
+junit-vintage-engine.version=5.8.2
+# Only used for internal tests in Ant project
+junit-jupiter-engine.version=5.8.2
 jsch.version=0.1.55
-jython.version=2.5.3
+jython.version=2.7.2
 # log4j 1.2.15 requires JMS and a few other Sun jars that are not in the m2 repo
 log4j.version=1.2.14
 oro.version=2.0.8
@@ -70,6 +79,7 @@
 which.version=1.0
 xalan.version=2.7.2
 xml-resolver.version=1.2
+xz.version=1.8
 # paired
 jacl.version=1.2.6
 tcljava.version=${jacl.version}
diff --git a/lib/optional/junit-4.12.jar b/lib/optional/junit-4.12.jar
deleted file mode 100644
index 3a7fc26..0000000
--- a/lib/optional/junit-4.12.jar
+++ /dev/null
Binary files differ
diff --git a/lib/optional/junit-4.13.1.jar b/lib/optional/junit-4.13.1.jar
new file mode 100644
index 0000000..b376ffc
--- /dev/null
+++ b/lib/optional/junit-4.13.1.jar
Binary files differ
diff --git a/manual/Integration/jext-plugin.html b/manual/Integration/jext-plugin.html
index 84e88c0..dade832 100644
--- a/manual/Integration/jext-plugin.html
+++ b/manual/Integration/jext-plugin.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,43 +15,39 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-  <meta http-equiv="Content-Language" content="en-us">
-  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Apache AntWork Plugin for the Jext Java Text Editor</title>
 </head>
 <body>
 
-<h1>AntWork Plugin for the Jext Java Text Editor</h1>
- <a name="authors"></a>by<ul>
-  <li>Klaus Hartlage
-      (<a href="mailto:KHartlage@t-online.de">KHartlage@t-online.de</a>)</li>
+<h1 id="authors">AntWork Plugin for the Jext Java Text Editor</h1>
+by
+<ul>
+  <li>Klaus Hartlage (<a href="mailto:KHartlage@t-online.de">KHartlage@t-online.de</a>)</li>
 </ul>
-<hr>
+<hr/>
 
-<p>You can download the plugin at: <a
-href="ftp://jext.sourceforge.net/pub/jext/plugins/AntWork.zip">ftp://jext.sourceforge.net/pub/jext/plugins/AntWork.zip</a></p>
+<p>You can download the plugin
+at: <a href="https://sourceforge.net/projects/jext/files/OldFiles/antwork_plugin.zip/download"
+target="_top">https://sourceforge.net/projects/jext/files/OldFiles/antwork_plugin.zip/download</a></p>
 
-<h2>Installation instructions from the Readme.txt:</h2>
+<h2>Installation instructions from the Readme.txt</h2>
 
 <p>You have to enable the Jext Console to see the Apache Ant output (menu:
-Edit-&gt;Options... - General Panel), because the Ant messages are
-redirected to the Jext console.</p>
+Edit&rarr;Options&hellip;&ndash;General Panel), because Ant messages are redirected to the Jext
+console.</p>
 
-<p>You can configure the Ant call in the Jext menu: Edit-&gt;Options... -
-Plugin Options - Antwork Plugin Panel; here you can set the ant home
-directory and the path to your build file.</p>
+<p>You can configure the Ant call in the Jext menu: Edit&rarr;Options&hellip;&ndash; Plugin
+Options&ndash;Antwork Plugin Panel; here you can set Ant home directory and the path to your build
+file.</p>
 
-<p>You can start AntWork in the menu: Plugins-&gt;Ant-&gt;Work Now!  In the
-appearing dialog box you can enter the target which you want to
-compile.</p>
+<p>You can start AntWork in the menu: Plugins&rarr;Ant&rarr;Work Now!  In the appearing dialog box
+you can enter the target which you want to compile.</p>
 
-<p>If a javac error occurs in the ant run an error-list opens within
-Jext. With a double-click on the error-message you jump to the error
-in the specified java text file.</p>
+<p>If a <code>javac</code> error occurs in the Ant run, an error list opens within Jext. With a
+double click on the error message you jump to the error in the specified Java source file.</p>
 
-
-</body></html>
+</body>
+</html>
diff --git a/manual/LICENSE b/manual/LICENSE
index f820d4b..239ec94 100644
--- a/manual/LICENSE
+++ b/manual/LICENSE
@@ -1,7 +1,7 @@
 /*
  *                                 Apache License
  *                           Version 2.0, January 2004
- *                        http://www.apache.org/licenses/
+ *                        https://www.apache.org/licenses/
  *
  *   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  *
@@ -193,7 +193,7 @@
  *   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
+ *       https://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,
diff --git a/manual/Tasks/BorlandEJBTasks.html b/manual/Tasks/BorlandEJBTasks.html
index 126fe5c..a60d3d2 100644
--- a/manual/Tasks/BorlandEJBTasks.html
+++ b/manual/Tasks/BorlandEJBTasks.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,130 +15,122 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Borland EJB Tasks</title>
 </head>
 
 <body>
 
-<h2><a name="log">BorlandDeploy</a>Tool</h2>
+<h2 id="log">BorlandDeployTool</h2>
 <p>by Benoit Moussaud (<a href="mailto:benoit.moussaud@criltelecom.com">benoit.moussaud@criltelecom.com</a>)</p>
 
 
 <h3>Description</h3>
 <p>The BorlandDeployTool is a vendor specific nested element for the Ejbjar optional task.</p>
-<p>BorlandDeploymentTool is dedicated to the Borland Application Server 4.5.x and Borland
-  Enterprise Server 5.x. It  generates and compiles the stubs and skeletons for all ejb described into the
-  Deployment Descriptor, builds the jar file including the support files and
-  verify whether the produced jar is valid or not.</p>
+<p>BorlandDeployTool is dedicated to the Borland Application Server 4.5.x and Borland Enterprise
+Server 5.x. It generates and compiles the stubs and skeletons for all EJBs described in the
+Deployment Descriptor, builds the jar file including the support files and verifies whether the
+produced jar is valid or not.</p>
 
-<p>Benoit Moussaud maintains a separate <a
-href="http://www.moussaud.org/ejbjar.html">FAQ</a> for this task at
-his homepage.</p>
+<p>Benoit Moussaud maintains a
+separate <a href="https://web.archive.org/web/20141122083215/http://www.moussaud.org/ejbjar.html"
+target="_top">FAQ</a> for this task at his homepage.</p>
 
 <h3>Borland element</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top" width="63"><b>Attribute</b></td>
-    <td valign="top" width="915"><b>Description</b></td>
-    <td align="center" valign="top" width="62"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top" width="63">destdir</td>
-    <td valign="top" width="915">The base directory into which the generated borland
-      ready jar files are deposited</td>
-    <td align="center" valign="middle" width="62">yes</td>
+    <td>destdir</td>
+    <td>The base directory in which the generated Borland ready jar files are stored</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top" width="63">debug</td>
-    <td valign="top" width="915">If true, turn on the debug mode for each borland
-      tools (java2iiop, iastool ...) default = false</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>debug</td>
+    <td>If <q>true</q>, turn on the debug mode for each Borland tools
+      (<code>java2iiop</code>, <code>iastool</code>, ...)</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top" width="63">verify</td>
-    <td valign="top" width="915">If true, turn on the verification at the end
-      of the jar production (default = false)</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>verify</td>
+    <td>If <q>true</q>, turn on the verification at the end of the jar production.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top" width="63">verifyargs</td>
-    <td valign="top" width="915">extra parameter for verify command</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>verifyargs</td>
+    <td>extra parameter for verify command</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top" width="63">suffix</td>
-    <td valign="top" width="915">String value appended to the basename of the
-      deployment descriptor to create the filename of the Borland EJB jar file.</td>
-    <td align="center" valign="middle" width="62">No, defaults to '-ejb.jar'.</td>
+    <td>suffix</td>
+    <td>String value appended to the basename of the deployment descriptor to create the filename of
+      the Borland EJB jar file.</td>
+    <td>No; defaults to <q class="no-break">-ejb.jar</q></td>
   </tr>
   <tr>
-    <td valign="top" width="63">basdtd</td>
-    <td valign="top" width="915"><b>Deprecated</b>. Defines the location of the
-      DTD which covers the Borland specific deployment descriptors.
-      This should not be necessary if you have borland in your classpath. If you
-      do not, you should use a nested
+    <td>basdtd</td>
+    <td><em><u>Deprecated</u></em>. Defines the location of the DTD which covers the Borland
+      specific deployment descriptors.  This should not be necessary if you have borland in your
+      classpath. If you do not, you should use a nested
       <a href="ejb.html#ejbjar-dtd"><code>&lt;dtd&gt;</code></a> element, described
       in the ejbjar task documentation.</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top" width="63">ejbdtd</td>
-    <td valign="top" width="915"><b>Deprecated</b>. Defines the location of the
-      ejb-jar DTD in the class hierarchy. This should not be necessary
-      if you have borland in your classpath. If you do not, you should use a
-      nested <a href="ejb.html#ejbjar-dtd"><code>&lt;dtd&gt;</code></a> element,
-      described in the ejbjar task
-      documentation. </td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>ejbdtd</td>
+    <td><em><u>Deprecated</u></em>. Defines the location of the ejb-jar DTD in the class
+      hierarchy. This should not be necessary if you have borland in your classpath. If you do not,
+      you should use a nested <a href="ejb.html#ejbjar-dtd"><code>&lt;dtd&gt;</code></a> element,
+      described in the ejbjar task documentation.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top" width="63">generateclient </td>
-    <td valign="top" width="915">If true, turn on the generation of the corresponding
-      ejbjar (default = false)</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>generateclient</td>
+    <td>If <q>true</q>, turn on the generation of the corresponding EJB jar.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top" width="63">version</td>
-    <td valign="top" width="915">set the Borland Application Version.
-            <ul>
-              <li>4 means B.A.S (Borland Application Server) 4.x, target will add ejb-inprise.xml file</li>
-              <li>5 means B.E.S (Borland Application Server) 5.x, target will add ejb-borland.xml file</li>
-            </ul>
-          </td>
-    <td align="center" valign="middle" width="62">No, defaults to 4</td>
+    <td>version</td>
+    <td>set the Borland Application Version.
+      <ul>
+        <li>4 means B.A.S (Borland Application Server) 4.x, target will add ejb-inprise.xml file</li>
+        <li>5 means B.E.S (Borland Application Server) 5.x, target will add ejb-borland.xml file</li>
+      </ul>
+    </td>
+    <td>No; defaults to <q>4</q></td>
   </tr>
   <tr>
-    <td valign="top" width="63">java2iiopParams </td>
-    <td valign="top" width="915">If filled, the params are added to the java2iiop command (ex: -no_warn_missing_define)</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>java2iiopParams</td>
+    <td>If filled, the params are added to the <kbd>java2iiop</kbd> command
+    (ex: <kbd>-no_warn_missing_define</kbd>)</td>
+    <td>No</td>
   </tr>
 
 </table>
 
 <h3>Examples</h3>
-<p>The following build.xml snippet is an example of how to use Borland element
-  into the ejbjar task</p>
-<pre>    &lt;ejbjar srcdir=&quot;${build.classes}&quot; basejarname=&quot;vsmp&quot; descriptordir=&quot;${rsc.dir}/hrmanager&quot;&gt;
-        &lt;borland destdir=&quot;lib&quot; verify=&quot;on&quot; generateclient=&quot;on&quot; version=&quot;5&quot;&gt;
-          &lt;classpath refid=&quot;classpath&quot;/&gt;
-        &lt;/borland&gt;
-        &lt;include name=&quot;**\ejb-jar.xml&quot;/&gt;
-        &lt;support dir=&quot;${build.classes}&quot;&gt;
-          &lt;include name=&quot;demo\*.class&quot;/&gt;
-          &lt;include name=&quot;demo\helper\*.class&quot;/&gt;
-         &lt;/support&gt;
-     &lt;/ejbjar&gt;</pre>
-<pre>The borland element will generate into the lib dir an ejb jar file using the deployment descriptor placed into the ${rsc.dir}/hrmanager directory.
-The verify phase is turned on and the generate client phase as well.
-</pre>
-
-<h3>&nbsp;</h3>
+<p>The following <samp>build.xml</samp> snippet is an example of how to use Borland element in
+the <code>ejbjar</code> task</p>
+<pre>
+&lt;ejbjar srcdir=&quot;${build.classes}&quot; basejarname=&quot;vsmp&quot; descriptordir=&quot;${rsc.dir}/hrmanager&quot;&gt;
+    &lt;borland destdir=&quot;lib&quot; verify=&quot;on&quot; generateclient=&quot;on&quot; version=&quot;5&quot;&gt;
+        &lt;classpath refid=&quot;classpath&quot;/&gt;
+    &lt;/borland&gt;
+    &lt;include name=&quot;**\ejb-jar.xml&quot;/&gt;
+    &lt;support dir=&quot;${build.classes}&quot;&gt;
+        &lt;include name=&quot;demo\*.class&quot;/&gt;
+        &lt;include name=&quot;demo\helper\*.class&quot;/&gt;
+    &lt;/support&gt;
+&lt;/ejbjar&gt;</pre>
+<p>The <code>borland</code> element will generate into the <samp>lib</samp> directory an EJB jar
+file using the deployment descriptor placed into the <samp>${rsc.dir}/hrmanager</samp> directory.
+The verify phase is turned on and the generate client phase as well.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/BorlandGenerateClient.html b/manual/Tasks/BorlandGenerateClient.html
index 01956b2..3a43861 100644
--- a/manual/Tasks/BorlandGenerateClient.html
+++ b/manual/Tasks/BorlandGenerateClient.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,77 +15,73 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>BorlandGenerateClient Task</title>
 </head>
 
 <body>
 
-<h2><a name="log">BorlandGenerateClient</a></h2>
+<h2 id="log">BorlandGenerateClient</h2>
 <p>by Benoit Moussaud (<a href="mailto:benoit.moussaud@criltelecom.com">benoit.moussaud@criltelecom.com</a>)</p>
 <h3>Description</h3>
-<p>The BorlandGenerateClient is a task dedicated to Borland Application Server
-  v 4.5. It offers to generate the client jar file corresponding to an ejb jar
-  file.</p>
+<p>The BorlandGenerateClient is a task dedicated to Borland Application Server v 4.5. It offers to
+generate the client jar file corresponding to an EJB jar file.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top" width="63"><b>Attribute</b></td>
-    <td valign="top" width="915"><b>Description</b></td>
-    <td align="center" valign="top" width="62"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top" width="63">ejbjar</td>
-    <td valign="top" width="915">ejb jar file</td>
-    <td align="center" valign="middle" width="62">yes</td>
+    <td>ejbjar</td>
+    <td>EJB jar file</td>
+    <td>yes</td>
   </tr>
   <tr>
-    <td valign="top" width="63">debug</td>
-    <td valign="top" width="915">If true, turn on the debug mode for each borland
-      tools (java2iiop, iastool ...) default = false</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>debug</td>
+    <td>If <q>true</q>, turn on the debug mode for each Borland tool
+      (<code>java2iiop</code>, <code>iastool</code>, ...)</td>
+    <td>no; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top" width="63">clientjar</td>
-    <td valign="top" width="915">client jar file name. If missing the client jar
-      file name is build using the ejbjar file name: ejbjar = hellobean-ejb.jar
-      =&gt; hellobean-ejbclient.jar</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>clientjar</td>
+    <td>client jar file name. If missing the client jar file name is build using
+      the <var>ejbjar</var> file name: <var>ejbjar</var>=<q>hellobean-ejb.jar</q>
+      &rArr; <q>hellobean-ejbclient.jar</q></td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top" width="63">mode</td>
-    <td valign="top" width="915">choose the command launching mode. Two values:
-      java or fork. default = fork. java is not supported for version=5.Possibility to specify a classpath.</td>
-    <td align="center" valign="middle" width="62">no</td>
+    <td>mode</td>
+    <td>choose the command launching mode. Two values: <q>java</q> or <q>fork</q>
+      (default). <q>java</q> is not supported for <var>version</var>=<q>5</q>. Possibility to
+      specify a classpath.</td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top" width="63">version</td>
-    <td valign="top" width="915">set the Borland Application Version.
-            <ul>
-              <li>4 means B.A.S (Borland Application Server 4.x)</li>
-              <li>5 means B.E.S (Borland Application Server 5.x)</li>
-            </ul>
-          </td>
-    <td align="center" valign="middle" width="62">No, defaults to 4</td>
+    <td>version</td>
+    <td>set the Borland Application Version.
+      <ul>
+        <li><q>4</q> means B.A.S (Borland Application Server 4.x)</li>
+        <li><q>5</q> means B.E.S (Borland Application Server 5.x)</li>
+      </ul>
+    </td>
+    <td>No; defaults to <q>4</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<p>The following build.xml snippet is an example of how to use Borland element
-   into the ejbjar task using the java mode.</p>
+<p>The following <samp>build.xml</samp> snippet is an example of how to use Borland element in
+the <code>ejbjar</code> task using the <q>fork</q> <var>mode</var>.</p>
 <pre>
-&lt;blgenclient ejbjar=&quot;lib/secutest-ejb.jar&quot; clientjar=&quot;lib/client.jar&quot; debug=&quot;true&quot; mode=&quot;fork&quot;&gt; version=&quot;5&quot;&gt;
+&lt;blgenclient ejbjar=&quot;lib/secutest-ejb.jar&quot; clientjar=&quot;lib/client.jar&quot; debug=&quot;true&quot; mode=&quot;fork&quot; version=&quot;5&quot;&gt;
     &lt;classpath&gt;
         &lt;pathelement location=&quot;mymodule.jar&quot;/&gt;
     &lt;/classpath&gt;
-&lt;/blgenclient&gt;
-</pre>
-<pre>&nbsp;</pre>
+&lt;/blgenclient&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/ant.html b/manual/Tasks/ant.html
index 87b78bb..f867701 100644
--- a/manual/Tasks/ant.html
+++ b/manual/Tasks/ant.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,323 +15,286 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Ant Task</title>
 </head>
 
 <body>
 
-<h2><a name="ant">Ant</a></h2>
+<h2 id="ant">Ant</h2>
 <h3>Description</h3>
 
-<p>Runs Apache Ant on a supplied buildfile. This can be used to build
-subprojects.  <strong>This task must not be used outside of a
-<code>target</code> if it invokes the same build file it is part
+<p>Runs Apache Ant on a supplied buildfile. This can be used to build subprojects.  <strong>This
+task must not be used outside of a <code>target</code> if it invokes the same build file it is part
 of.</strong></p>
 
-<p>When the <i>antfile</i> attribute is omitted, the file &quot;build.xml&quot;
-in the supplied directory (<i>dir</i> attribute) is used.</p>
-<p>If no target attribute is supplied, the default target of the new project is
-used.</p>
-<p>By default, all of the properties of the current project will be
-available in the new project.  Alternatively, you can set the
-<i>inheritAll</i> attribute to <code>false</code> and only
-&quot;user&quot; properties (i.e., those passed on the command-line)
-will be passed to the new project.  In either case, the set of
-properties passed to the new project will override the properties that
-are set in the new project (See also the <a
-href="property.html">property task</a>).</p>
+<p>When the <var>antfile</var> attribute is omitted, the file <samp>build.xml</samp> in the supplied
+directory (<var>dir</var> attribute) is used.</p>
+<p>If no target attribute is supplied, the default target of the new project is used.</p>
+<p>By default, all of the properties of the current project will be available in the new project.
+Alternatively, you can set the <var>inheritAll</var> attribute to <q>false</q> and only
+&quot;user&quot; properties (i.e., those passed on the command-line) will be passed to the new
+project.  In either case, the set of properties passed to the new project will override the
+properties that are set in the new project (See also the <a href="property.html">property</a>
+task).</p>
 
-<p>You can also set properties in the new project from the old project
-by using nested property tags. These properties are always passed
-to the new project and any project created in that project
-regardless of the setting of <i>inheritAll</i>.  This allows you to
-parameterize your subprojects.</p>
+<p>You can also set properties in the new project from the old project by using
+nested <code>property</code> tags. These properties are always passed to the new project and any
+project created in that project regardless of the setting of <var>inheritAll</var>.  This allows you
+to parameterize your subprojects.</p>
 
-<p>When more than one nested <code>&lt;property&gt;</code> element
-  would set a property of the same name, the one declared last will
-  win.  This is for backwards compatibility reasons even so it is
-  different from the way <code>&lt;property&gt;</code> tasks in build
-  files behave.</p>
+<p>When more than one nested <code>&lt;property&gt;</code> element would set a property of the same
+name, the one declared last will win.  This is for backwards compatibility reasons even though it is
+different from the way <code>&lt;property&gt;</code> tasks in build files behave.</p>
 
 <p>Properties defined on the command line cannot be overridden by
-  nested <code>&lt;property&gt;</code> elements.  <em>Since Ant
-  1.8.0.</em> the same is true for nested structures
-  of <code>&lt;ant&gt;</code> tasks: if a build file <em>A</em>
-  invokes <em>B</em> via an <code>&lt;ant&gt;</code> task setting a
-  property with a nested <code>&lt;property&gt;</code> element
-  and <em>B</em> contains an <code>&lt;ant&gt;</code> tasks
-  invoking <em>C</em>, <em>C</em> will see the value set
-  in <em>A</em>, even if <em>B</em> used a
-  nested <code>&lt;property&gt;</code> element as well.</p>
+nested <code>&lt;property&gt;</code> elements.  <em>Since Ant 1.8.0</em>, the same is true for
+nested structures of <code>&lt;ant&gt;</code> tasks: if a build file <var>A</var>
+invokes <var>B</var> via an <code>&lt;ant&gt;</code> task setting a property with a
+nested <code>&lt;property&gt;</code> element and <var>B</var> contains an <code>&lt;ant&gt;</code>
+tasks invoking <var>C</var>, <var>C</var> will see the value set in <var>A</var>, even
+if <var>B</var> used a nested <code>&lt;property&gt;</code> element as well.</p>
 
-<p>References to data types can also be passed to the new project, but
-by default they are not.  If you set the inheritrefs attribute to
-true, all references will be copied, but they will not override
-references defined in the new project.</p>
+<p>References to data types can also be passed to the new project, but by default they are not.  If
+you set the <var>inheritrefs</var> attribute to <q>true</q>, all references will be copied, but they
+will not override references defined in the new project.</p>
 
-<p>Nested <a href="#reference"><i><code>&lt;reference&gt;</code></i></a> elements
-can also be used to copy references from the calling project to the
-new project, optionally under a different id.  References taken from
-nested elements will override existing references that have been
-defined outside of targets in the new project - but not those defined
-inside of targets.</p>
+<p>Nested <a href="#reference"><code>&lt;reference&gt;</code></a> elements can also be used to copy
+references from the calling project to the new project, optionally under a different <var>id</var>.
+References taken from nested elements will override existing references that have been defined
+outside of targets in the new project&mdash;but not those defined inside of targets.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">antfile</td>
-    <td valign="top">the buildfile to use. Defaults to
-      &quot;build.xml&quot;.  This file is expected to be a filename
-      relative to the dir attribute given.</td>
-    <td valign="top" align="center">No</td>
+    <td>antfile</td>
+    <td>the buildfile to use. This file is expected to be a filename relative to the <var>dir</var>
+      attribute given.</td>
+    <td>No; defaults to <q>build.xml</q></td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the directory to use as a basedir for the new Ant
-      project (unless useNativeBasedir is set to true).
-      Defaults to the current project's basedir, unless
-      inheritall has been set to false, in which case it doesn't
-      have a default value.  This will override the basedir
-      setting of the called project.<br/>
-      Also serves as the directory to resolve the antfile and output
-      attribute's values (if any).
+    <td>dir</td>
+    <td>the directory to use as a <var>basedir</var> for the new Ant project
+      (unless <var>useNativeBasedir</var> is set to <q>true</q>).  This will override
+      the <var>basedir</var> setting of the called project.<br/>  Also serves as the directory to
+      resolve the <var>antfile</var> and <var>output</var> attribute's values (if any).
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to the current project's <var>basedir</var>, unless <var>inheritall</var> has
+      been set to <q>false</q>, in which case it doesn't have a default value</td>
   </tr>
   <tr>
-    <td valign="top">target</td>
-    <td valign="top">the target of the new Ant project that should be executed.
-      Defaults to the new project's default target.</td>
-    <td valign="top" align="center">No</td>
+    <td>target</td>
+    <td>the target of the new Ant project that should be executed.</td>
+    <td>No; defaults to the new project's default target</td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">Filename to write the ant output to.  This is
-    relative to the value of the dir attribute if it has been set or
-    to the base directory of the current project otherwise.
+    <td>output</td>
+    <td>Filename to write the Ant output to.  This is relative to the value of the <var>dir</var>
+      attribute if it has been set or to the <var>basedir</var> of the current project otherwise.
     </td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inheritAll</td>
-    <td valign="top">If <code>true</code>, pass all properties to the
-      new Ant project.  Defaults to <code>true</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>inheritAll</td>
+    <td>If <q>true</q>, pass all properties to the new Ant project.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">inheritRefs</td>
-    <td valign="top">If <code>true</code>, pass all references to the
-      new Ant project.  Defaults to <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>inheritRefs</td>
+    <td>If <q>true</q>, pass all references to the new Ant project.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">useNativeBasedir</td>
-    <td valign="top">If set to true, the child build will use the same
-      basedir as it would have used when run from the command line
-      (i.e. the basedir one would expect when looking at the child
-      build's buildfile).  Defaults to <code>false</code>.  <em>since
-      Ant 1.8.0</em></td>
-    <td valign="top" align="center">No</td>
+    <td>useNativeBasedir</td>
+    <td>If set to <q>true</q>, the child build will use the same <var>basedir</var> as it would have
+      used when run from the command line (i.e. the <var>basedir</var> one would expect when looking
+      at the child build's buildfile).  <em>Since Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
 <h4>property</h4>
-<p>See the description of the <a href="property.html">property
-task</a>. <br>
-These properties become equivalent to properties you define on
-the command line. These are special properties and they will always get passed
-down, even through additional <code>&lt;*ant*&gt;</code> tasks with inheritall set to
-false (see above). <br>
-Note that the <code>refid</code> attribute points to a
-reference in the calling project, not in the new one.</p>
+<p>See the description of the <a href="property.html">property</a> task.<br/>  These properties
+become equivalent to properties you define on the command line. These are special properties and
+they will always get passed down, even through additional <code>&lt;*ant*&gt;</code> tasks
+with <var>inheritAll</var> set to <q>false</q> (see above).<br/>  Note that the <var>refid</var>
+attribute points to a reference in the calling project, not in the new one.</p>
 
-<h4><a name="reference">reference</a></h4>
-<p>Used to choose references that shall be copied into the new project,
-optionally changing their id.</p>
+<h4 id="reference">reference</h4>
+<p>Used to choose references that shall be copied into the new project, optionally changing
+their <var>id</var>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">The id of the reference in the calling project.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>refid</td>
+    <td>The <var>id</var> of the reference in the calling project.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">torefid</td>
-    <td valign="top">The id of the reference in the new project.</td>
-    <td valign="top" align="center">No, defaults to the value of refid.</td>
+    <td>torefid</td>
+    <td>The <var>id</var> of the reference in the new project.</td>
+    <td>No; defaults to the value of <var>refid</var></td>
   </tr>
 </table>
 
 <h4>propertyset</h4>
 
-<p>You can specify a set of properties to be copied into the new
-project with <a
-href="../Types/propertyset.html">propertyset</a>s.</p>
+<p><em>Since Ant 1.6</em>.</p>
 
-<p><em>since Ant 1.6</em>.</p>
+<p>You can specify a set of properties to be copied into the new project
+with <a href="../Types/propertyset.html">propertyset</a>s.</p>
 
 <h4>target</h4>
+<p><em>Since Ant 1.6.3</em>.</p>
 
-<p>You can specify multiple targets using nested <code>&lt;target&gt;</code> elements
-instead of using the target attribute.  These will be executed as if
-Ant had been invoked with a single target whose dependencies are the
-targets so specified, in the order specified.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>You can specify multiple targets using nested <code>&lt;target&gt;</code> elements instead of
+using the <var>target</var> attribute.  These will be executed as if Ant had been invoked with a
+single target whose dependencies are the targets so specified, in the order specified.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the called target.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>The name of the called target.</td>
+    <td>Yes</td>
   </tr>
 </table>
-<p><em>since Ant 1.6.3</em>.</p>
 
 <h3>Basedir of the new project</h3>
 
-<p>If you set <code>useNativeBasedir</code> to true, the basedir of
-  the new project will be whatever the basedir attribute of
-  the <code>&lt;project&gt;</code> element of the new project says (or
-  the new project's directory if the there is no basedir attribute) -
-  no matter what any other attribute of this task says and no matter
-  how deeply nested into levels of
-  <code>&lt;ant&gt;</code> invocations this task lives.</p>
- 
-<p>If you haven't set <code>useNativeBasedir</code> or set it to
-  false, the following rules apply:</p>
+<p>If you set <var>useNativeBasedir</var> to true, the <var>basedir</var> of the new project will be
+whatever the <var>basedir</var> attribute of the <code>&lt;project&gt;</code> element of the new
+project says (or the new project's directory if the there is no <var>basedir</var>
+attribute)&mdash;no matter what any other attribute of this task says and no matter how deeply
+nested into levels of <code>&lt;ant&gt;</code> invocations this task lives.</p>
 
-<p>The basedir value of the new project is affected by the two
-  attributes dir and inheritall as well as
-  the <code>&lt;ant&gt;</code> task's history.  The current behaviour
-  is known to be confusing but cannot be changed without breaking
-  backwards compatibility in subtle ways.</p>
+<p>If you haven't set <var>useNativeBasedir</var> or set it to <q>false</q>, the following rules
+apply:</p>
 
-<p>If the <code>&lt;ant&gt;</code> task is in a "top level" build
-  file, i.e. the project containing the <code>&lt;ant&gt;</code> task
-  has not itself been invoked as part of a
-  different <code>&lt;ant&gt;</code> (or <code>&lt;antcall&gt;</code>)
-  task "higher up", the following table shows the details:</p>
+<p>The <var>basedir</var> value of the new project is affected by the two attributes, <var>dir</var>
+and <var>inheritall</var>, as well as the <code>&lt;ant&gt;</code> task's history.  The current
+behaviour is known to be confusing but cannot be changed without breaking backwards compatibility in
+subtle ways.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<p>If the <code>&lt;ant&gt;</code> task is in a "top level" build file, i.e. the project containing
+the <code>&lt;ant&gt;</code> task has not itself been invoked as part of a
+different <code>&lt;ant&gt;</code> (or <code>&lt;antcall&gt;</code>) task "higher up", the following
+table shows the details:</p>
+
+<table>
   <tr>
-    <td valign="top"><b>dir attribute</b></td>
-    <td valign="top"><b>inheritAll attribute</b></td>
-    <td valign="top"><b>new project's basedir</b></td>
+    <th scope="col"><var>dir</var> attribute</th>
+    <th scope="col"><var>inheritAll</var> attribute</th>
+    <th scope="col">new project's <var>basedir</var></th>
   </tr>
   <tr>
-    <td valign="top">value provided</td>
-    <td valign="top">true</td>
-    <td valign="top">value of dir attribute</td>
+    <td>value provided</td>
+    <td><q>true</q></td>
+    <td>value of <var>dir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">value provided</td>
-    <td valign="top">false</td>
-    <td valign="top">value of dir attribute</td>
+    <td>value provided</td>
+    <td><q>false</q></td>
+    <td>value of <var>dir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">omitted</td>
-    <td valign="top">true</td>
-    <td valign="top">basedir of calling project (the one whose build
-        file contains the <code>&lt;ant&gt;</code> task).</td>
+    <td>omitted</td>
+    <td><q>true</q></td>
+    <td><var>basedir</var> of calling project (the one whose build
+      file contains the <code>&lt;ant&gt;</code> task).</td>
   </tr>
   <tr>
-    <td valign="top">omitted</td>
-    <td valign="top">false</td>
-    <td valign="top">basedir attribute of the <code>&lt;project&gt;</code> element
-        of the new project</td>
+    <td>omitted</td>
+    <td><q>false</q></td>
+    <td><var>basedir</var> attribute of the <code>&lt;project&gt;</code> element
+      of the new project</td>
   </tr>
 </table>
 
-<p>If on the other hand the <code>&lt;ant&gt;</code> task is already
-  nested into another invocation, the parent invocation's settings
-  affect the outcome of the basedir value.  The current task's dir
-  attribute will always win, but if the dir attribute has been omitted
-  an even more complex situation arises:</p>
+<p>If on the other hand the <code>&lt;ant&gt;</code> task is already nested into another invocation,
+the parent invocation's settings affect the outcome of the <var>basedir</var> value.  The current
+task's <var>dir</var> attribute will always win, but if the <var>dir</var> attribute has been
+omitted an even more complex situation arises:</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>parent dir attribute</b></td>
-    <td valign="top"><b>parent inheritAll attribute</b></td>
-    <td valign="top"><b>current inheritAll attribute</b></td>
-    <td valign="top"><b>new project's basedir</b></td>
+    <th scope="col">parent <var>dir</var> attribute</th>
+    <th scope="col">parent <var>inheritAll</var> attribute</th>
+    <th scope="col">current <var>inheritAll</var> attribute</th>
+    <th scope="col">new project's <var>basedir</var></th>
   </tr>
   <tr>
-    <td valign="top">value provided</td>
-    <td valign="top">any</td>
-    <td valign="top">any</td>
-    <td valign="top">value of parent's dir attribute</td>
+    <td>value provided</td>
+    <td>any</td>
+    <td>any</td>
+    <td>value of parent's <var>dir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">omitted</td>
-    <td valign="top">true</td>
-    <td valign="top">true</td>
-    <td valign="top">basedir of parent project (the one whose build
-        file called the build file that contains
-        the current <code>&lt;ant&gt;</code> task).</td>
+    <td>omitted</td>
+    <td><q>true</q></td>
+    <td><q>true</q></td>
+    <td><var>basedir</var> of parent project (the one whose build file called the build file that
+      contains the current <code>&lt;ant&gt;</code> task).</td>
   </tr>
   <tr>
-    <td valign="top">omitted</td>
-    <td valign="top">true</td>
-    <td valign="top">false</td>
-    <td valign="top">basedir of parent project (the one whose build
-        file called the build file that contains
-        the current <code>&lt;ant&gt;</code> task).</td>
+    <td>omitted</td>
+    <td><q>true</q></td>
+    <td><q>false</q></td>
+    <td><var>basedir</var> of parent project (the one whose build file called the build file that
+      contains the current <code>&lt;ant&gt;</code> task).</td>
   </tr>
   <tr>
-    <td valign="top">omitted</td>
-    <td valign="top">false</td>
-    <td valign="top">true</td>
-    <td valign="top">basedir of calling project (the one whose build
-        file contains the current <code>&lt;ant&gt;</code> task).</td>
+    <td>omitted</td>
+    <td><q>false</q></td>
+    <td><q>true</q></td>
+    <td><var>basedir</var> of calling project (the one whose build file contains the
+      current <code>&lt;ant&gt;</code> task).</td>
   </tr>
   <tr>
-    <td valign="top">omitted</td>
-    <td valign="top">false</td>
-    <td valign="top">false</td>
-    <td valign="top">basedir attribute of the <code>&lt;project&gt;</code> element
-        of the new project</td>
+    <td>omitted</td>
+    <td><q>false</q></td>
+    <td><q>false</q></td>
+    <td><var>basedir</var> attribute of the <code>&lt;project&gt;</code> element of the new
+      project</td>
   </tr>
 </table>
 
-<p>If you add even deeper levels of nesting, things get even more
-  complicated and you need to apply the above table recursively.</p>
+<p>If you add even deeper levels of nesting, things get even more complicated and you need to apply
+the above table recursively.</p>
 
-<p>If the basedir of the outer most build has been specified as a
-  property on the command line (i.e. <code>-Dbasedir=some-value</code>
-  or a <code>-propertyfile</code> argument) the value provided will
-  get an even higher priority.  For any <code>&lt;ant&gt;</code> task
-  that doesn't specify a dir attribute, the new project's basedir will
-  be the value specified on the command line - no matter how deeply
-  nested into layers of build files the task may be.</p>
+<p>If the <var>basedir</var> of the outermost build has been specified as a property on the command
+line (i.e. <kbd>-Dbasedir=some-value</kbd> or a <kbd>-propertyfile</kbd> argument) the value
+provided will get an even higher priority.  For any <code>&lt;ant&gt;</code> task that doesn't
+specify a <var>dir</var> attribute, the new project's <var>basedir</var> will be the value specified
+on the command line&mdash;no matter how deeply nested into layers of build files the task may
+be.</p>
 
-<p>The same happens if the basedir is specified as a
-  nested <code>&lt;property&gt;</code> of an <code>&lt;ant&gt;</code>
-  task.  The basedir of build files started at deeper levels will be
-  set to the specified value of the property element unless the
-  corresponding Ant tasks set the dir attribute explicitly.</p>
+<p>The same happens if the <var>basedir</var> is specified as a nested <code>&lt;property&gt;</code>
+of an <code>&lt;ant&gt;</code> task.  The <var>basedir</var> of build files started at deeper levels
+will be set to the specified value of the property element unless the corresponding Ant tasks set
+the <var>dir</var> attribute explicitly.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
+<p>These are different ways of using the task:</p>
+<pre>
 &lt;ant antfile=&quot;subproject/subbuild.xml&quot; target=&quot;compile&quot;/&gt;
 
 &lt;ant dir=&quot;subproject&quot;/&gt;
@@ -342,72 +306,55 @@
 
 &lt;ant inheritAll=&quot;false&quot; antfile=&quot;subproject/subbuild.xml&quot;&gt;
   &lt;property name=&quot;output.type&quot; value=&quot;html&quot;/&gt;
-&lt;/ant&gt;
-</pre></blockquote>
+&lt;/ant&gt;</pre>
 
 <p>These lines invoke the same build file:</p>
-<blockquote><pre>
-&lt;ant antfile=&quot;sub1/sub2/build.xml&quot; /&gt;
-&lt;ant antfile=&quot;sub2/build.xml&quot; dir=&quot;sub1&quot; /&gt;
-&lt;ant antfile=&quot;build.xml&quot; dir=&quot;sub1/sub2&quot; /&gt;
-</pre></blockquote>
+<pre>
+&lt;ant antfile=&quot;sub1/sub2/build.xml&quot;/&gt;
+&lt;ant antfile=&quot;sub2/build.xml&quot; dir=&quot;sub1&quot;/&gt;
+&lt;ant antfile=&quot;build.xml&quot; dir=&quot;sub1/sub2&quot;/&gt;</pre>
 
-<p>The build file of the calling project defines some
-<code>&lt;path&gt;</code> elements like this:</p>
+<p>The build file of the calling project defines some <code>&lt;path&gt;</code> elements like
+this:</p>
 
-<blockquote><pre>
+<pre>
 &lt;path id="path1"&gt;
     ...
 &lt;/path&gt;
 &lt;path id="path2"&gt;
     ...
-&lt;/path&gt;
-</pre></blockquote>
+&lt;/path&gt;</pre>
 
-<p>and the called build file (<code>subbuild.xml</code>) also defines
-a <code>&lt;path&gt;</code> with the id <code>path1</code>, but
-<code>path2</code> is not defined:</p>
+<p>and the called build file (<samp>subbuild.xml</samp>) also defines a <code>&lt;path&gt;</code>
+with the <var>id</var> <samp>path1</samp>, but <samp>path2</samp> is not defined; then</p>
 
-<blockquote><pre>
-&lt;ant antfile=&quot;subbuild.xml&quot; inheritrefs=&quot;true&quot;/&gt;
-</pre></blockquote>
+<pre>&lt;ant antfile=&quot;subbuild.xml&quot; inheritrefs=&quot;true&quot;/&gt;</pre>
 
-<p>will not override <code>subbuild</code>'s definition of
-<code>path1</code>, but make the parent's definition of
-<code>path2</code> available in the subbuild.</p>
+<p>will not override <samp>subbuild</samp>'s definition of <samp>path1</samp>, but make the parent's
+definition of <samp>path2</samp> available in the <samp>subbuild</samp>, whereas</p>
 
-<blockquote><pre>
-&lt;ant antfile=&quot;subbuild.xml&quot;/&gt;
-</pre></blockquote>
+<pre>&lt;ant antfile=&quot;subbuild.xml&quot;/&gt;</pre>
 
 <p>as well as</p>
 
-<blockquote><pre>
-&lt;ant antfile=&quot;subbuild.xml&quot; inheritrefs=&quot;false&quot;/&gt;
-</pre></blockquote>
+<pre>&lt;ant antfile=&quot;subbuild.xml&quot; inheritrefs=&quot;false&quot;/&gt;</pre>
 
-<p>will neither override <code>path1</code> nor copy
-<code>path2</code>.</p>
+<p>will neither override <samp>path1</samp> nor copy <samp>path2</samp>, while</p>
 
-<blockquote><pre>
+<pre>
 &lt;ant antfile=&quot;subbuild.xml&quot; inheritrefs=&quot;false&quot;&gt;
   &lt;reference refid=&quot;path1&quot;/&gt;
-&lt;/ant&gt;
-</pre></blockquote>
+&lt;/ant&gt;</pre>
 
-<p>will override <code>subbuild</code>'s definition of
-<code>path1</code>.</p>
+<p>will override <samp>subbuild</samp>'s definition of <samp>path1</samp>, and</p>
 
-<blockquote><pre>
+<pre>
 &lt;ant antfile=&quot;subbuild.xml&quot; inheritrefs=&quot;false&quot;&gt;
   &lt;reference refid=&quot;path1&quot; torefid=&quot;path2&quot;/&gt;
-&lt;/ant&gt;
-</pre></blockquote>
+&lt;/ant&gt;</pre>
 
-<p>will copy the parent's definition of <code>path1</code> into the
-new project using the id <code>path2</code>.</p>
-
-
+<p>will copy the parent's definition of <samp>path1</samp> into the new project using
+the <var>id</var> <samp>path2</samp>.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/antcall.html b/manual/Tasks/antcall.html
index 00cf615..47c8337 100644
--- a/manual/Tasks/antcall.html
+++ b/manual/Tasks/antcall.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,166 +15,147 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>AntCall Task</title>
 </head>
 
 <body>
 
-<h2><a name="antcall">AntCall</a></h2>
+<h2 id="antcall">AntCall</h2>
 <h3>Description</h3>
 
-<p>Call another target within the same buildfile optionally
-specifying some properties (params in this context).  <strong>This
-task must not be used outside of a <code>target</code>.</strong></p>
+<p>Call another target within the same buildfile optionally specifying some properties (params in
+this context).  <strong>This task must not be used outside of a <code>target</code>.</strong></p>
 
-<p>By default, all of the properties of the current project will be
-available in the new project.   Alternatively, you can
-set the <i>inheritAll</i> attribute to <code>false</code> and only
-&quot;user&quot; properties (i.e., those passed on the command-line)
-will be passed to the new project.  In either case, the set of
-properties passed to the new project will override the properties that
-are set in the new project (See also the <a href="property.html">property task</a>).</p>
-<p>You can also set properties in the new project from the old project
-by using nested param tags. These properties are always passed
-to the new project and any project created in that project
-regardless of the setting of <i>inheritAll</i>.  This allows you to
-parameterize your subprojects.  Properties defined on the command line
-can not be overridden by nested <code>&lt;param&gt;</code> elements.</p>
+<p>By default, all of the properties of the current project will be available in the new project.
+Alternatively, you can set the <var>inheritAll</var> attribute to <q>false</q> and only
+&quot;user&quot; properties (i.e., those passed on the command-line) will be passed to the new
+project.  In either case, the set of properties passed to the new project will override the
+properties that are set in the new project (see also the <a href="property.html">property</a>
+task).</p>
+<p>You can also set properties in the new project from the old project by using
+nested <code>&lt;param&gt;</code> tags. These properties are always passed to the new project and
+any project created in that project regardless of the setting of <var>inheritAll</var>.  This allows
+you to parameterize your subprojects.  Properties defined on the command line can not be overridden
+by nested <code>&lt;param&gt;</code> elements.</p>
 
-<p>When more than one nested <code>&lt;param&gt;</code> element
-  would set a property of the same name, the one declared last will
-  win.  This is for backwards compatibility reasons even so it is
-  different from the way <code>&lt;property&gt;</code> tasks in build
-  files behave.</p>
+<p>When more than one nested <code>&lt;param&gt;</code> element would set a property of the same
+name, the one declared last will win.  This is for backwards compatibility reasons even so it is
+different from the way <code>&lt;property&gt;</code> tasks in build files behave.</p>
 
-<p>Nested <a href="#reference"><i><code>&lt;reference&gt</code>;</i></a> elements can
-be used to copy references from the calling project to the new
-project, optionally under a different id.  References taken from
-nested elements will override existing references that have been
-defined outside of targets in the new project - but not those defined
-inside of targets.</p>
+<p>Nested <a href="#reference"><code>&lt;reference&gt;</code></a> elements can be used to copy
+references from the calling project to the new project, optionally under a different <var>id</var>.
+References taken from nested elements will override existing references that have been defined
+outside of targets in the new project&mdash;but not those defined inside of targets.</p>
 
-<p>
-When a target is invoked by antcall, all of its dependent targets will
-also be called within the context of any new parameters. For example. if
-the target &quot;doSomethingElse&quot; depended on the target &quot;init&quot;, then the
-<i>antcall</i> of &quot;doSomethingElse&quot; will call &quot;init&quot; during the call.
-Of course, any properties defined in the antcall task or inherited from the calling target
-will be fixed and not overridable in the init task--or indeed in the &quot;doSomethingElse&quot; task.
-</p>
+<p>When a target is invoked by <code>antcall</code>, all of its dependent targets will also be
+called within the context of any new parameters. For example. if the target <q>doSomethingElse</q>;
+depended on the target <q>init</q>, then the <code>antcall</code> of <q>doSomethingElse</q> will
+call <q>init</q> during the call.  Of course, any properties defined in the <code>antcall</code>
+task or inherited from the calling target will be fixed and not overridable in the <q>init</q>
+target&mdash;or indeed in the <q>doSomethingElse</q> target.</p>
 
-<p>The called target(s) are run in a new project; be aware that this
-means properties, references, etc.  set by called targets will not
-persist back to the calling project.</p>
+<p>The called target(s) are run in a new project; be aware that this means properties, references,
+etc. set by called targets will not persist back to the calling project.</p>
 
-<p>If the build file changes after you've started the build, the
-behavior of this task is undefined.</p>
+<p>If the build file changes after you've started the build, the behavior of this task is
+undefined.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">target</td>
-    <td valign="top">The target to execute.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>target</td>
+    <td>The target to execute.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">inheritAll</td>
-    <td valign="top">If <code>true</code>, pass all properties to the new Apache Ant
-    project.  Defaults to <code>true</code>.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>inheritAll</td>
+    <td>If <q>true</q>, pass all properties to the new Apache Ant project.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">inheritRefs</td>
-    <td valign="top">If <code>true</code>, pass all references to the
-      new Ant project.  Defaults to <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>inheritRefs</td>
+    <td>If <q>true</q>, pass all references to the new Ant project.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
 <h3>Note on <code>inheritRefs</code></h3>
 
-<p><code>&lt;antcall&gt;</code> will not override existing references,
-even if you set <code>inheritRefs</code> to true.  As the called build
-files is the same build file as the calling one, this means it will
-not override any reference set via an <code>id</code> attribute at
-all.  The only references that can be inherited by the child project
-are those defined by nested <code>&lt;reference&gt;</code> elements or
-references defined by tasks directly (not using the <code>id</code>
-attribute).</p>
+<p><code>&lt;antcall&gt;</code> will not override existing references, even if you
+set <var>inheritRefs</var> to true.  As the called build files is the same build file as the calling
+one, this means it will not override any reference set via an <var>id</var> attribute at all.  The
+only references that can be inherited by the child project are those defined by
+nested <code>&lt;reference&gt;</code> elements or references defined by tasks directly (not using
+the <var>id</var> attribute).</p>
 
 <h3>Parameters specified as nested elements</h3>
 <h4>param</h4>
-<p>Specifies the properties to set before running the specified target. See <a
-href="property.html">property</a> for usage guidelines.<br>
-These properties become equivalent to properties you define on
-the command line. These are special properties and they will always get passed
-down, even through additional <code>&lt;*ant*&gt;</code> tasks with inheritall set to
-false (see above).
-</p>
+<p>Specifies the properties to set before running the specified
+target. See <a href="property.html">property</a> for usage guidelines.<br/>  These properties become
+equivalent to properties you define on the command line. These are special properties and they will
+always get passed down, even through additional <code>&lt;*ant*&gt;</code> tasks
+with <var>inheritAll</var> set to <q>false</q> (see above).</p>
 
-<h4><a name="reference">reference</a></h4>
-<p>Used to choose references that shall be copied into the new project,
-optionally changing their id.</p>
+<h4 id="reference">reference</h4>
+<p>Used to choose references that shall be copied into the new project, optionally changing
+their <var>id</var>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">The id of the reference in the calling project.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>refid</td>
+    <td>The <var>id</var> of the reference in the calling project.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">torefid</td>
-    <td valign="top">The id of the reference in the new project.</td>
-    <td valign="top" align="center">No, defaults to the value of refid.</td>
+    <td>torefid</td>
+    <td>The <var>id</var> of the reference in the new project.</td>
+    <td>No; defaults to the value of <var>refid</var></td>
   </tr>
 </table>
 
 <h4>propertyset</h4>
 
-<p>You can specify a set of properties to be copied into the new
-project with <a
-href="../Types/propertyset.html">propertyset</a>s.</p>
+<p><em>Since Ant 1.6</em>.</p>
 
-<p><em>since Ant 1.6</em>.</p>
+<p>You can specify a set of properties to be copied into the new project
+with <a href="../Types/propertyset.html">propertyset</a>s.</p>
 
 <h4>target</h4>
+<p><em>Since Ant 1.6.3</em>.</p>
 
-<p>You can specify multiple targets using nested <code>&lt;target&gt;</code> elements
-instead of using the target attribute.  These will be executed as if
-Ant had been invoked with a single target whose dependencies are the
-targets so specified, in the order specified.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>You can specify multiple targets using nested <code>&lt;target&gt;</code> elements instead of
+using the <var>target</var> attribute.  These will be executed as if Ant had been invoked with a
+single target whose dependencies are the targets so specified, in the order specified.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the called target.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>The name of the called target.</td>
+    <td>Yes</td>
   </tr>
 </table>
-<p><em>since Ant 1.6.3</em>.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
+<p>The following</p>
+<pre>
 &lt;target name=&quot;default&quot;&gt;
   &lt;antcall target=&quot;doSomethingElse&quot;&gt;
     &lt;param name=&quot;param1&quot; value=&quot;value&quot;/&gt;
@@ -182,20 +164,14 @@
 
 &lt;target name=&quot;doSomethingElse&quot;&gt;
   &lt;echo message=&quot;param1=${param1}&quot;/&gt;
-&lt;/target&gt;
-</pre></blockquote>
-<p>Will run the target 'doSomethingElse' and echo 'param1=value'.</p>
-
-<blockquote><pre>
+&lt;/target&gt;</pre>
+<p>will run the target <var>doSomethingElse</var> and echo <code>param1=value</code>, whereas</p>
+<pre>
 &lt;antcall ... &gt;
   &lt;reference refid=&quot;path1&quot; torefid=&quot;path2&quot;/&gt;
-&lt;/antcall&gt;
-</pre></blockquote>
-
-<p>will copy the parent's definition of <code>path1</code> into the
-new project using the id <code>path2</code>.</p>
-
-
+&lt;/antcall&gt;</pre>
+<p>will copy the parent's definition of <samp>path1</samp> into the new project using
+the <var>id</var> <samp>path2</samp>.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/antlr.html b/manual/Tasks/antlr.html
index ca0bcde..8add5c0 100644
--- a/manual/Tasks/antlr.html
+++ b/manual/Tasks/antlr.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,190 +15,134 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ANTLR Task</title>
 </head>
 
 <body>
 
-<h2><a name="antlr">ANTLR</a></h2>
+<h2 id="antlr">ANTLR</h2>
 <h3>Description</h3>
-<p>
-  Invokes the <a HREF="http://www.antlr.org/" target="_top">ANTLR</a> Translator generator
-  on a grammar file.
-</p>
-<p>
-  To use the ANTLR task, set the <i>target</i> attribute to the name of the
-  grammar file to process.  Optionally, you can also set the
-  <i>outputdirectory</i> to write the generated file to a specific directory.
-  Otherwise ANTLR writes the generated files to the directory containing
-  the grammar file.
-</p>
-<p>
-  This task only invokes ANTLR if the grammar file (or the
-  supergrammar specified by the glib attribute) is newer than the
-  generated files.
-</p>
-<p><strong>Note:</strong> This task depends on external libraries not
-included in the Apache Ant distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a>
-for more information.</p>
-<p>Antlr 2.7.1 Note:
-<i>
-  To successfully run ANTLR, your best option is probably to build the whole
-  jar with the provided script <b>mkalljar</b> and drop the resulting jar (about 300KB)
-  into ${ant.home}/lib. Dropping the default jar (70KB) is probably not enough
-  for most needs and your only option will be to add ANTLR home directory
-  to your classpath as described in ANTLR <tt>install.html</tt> document.
-</i>
-</p>
-<p>Antlr 2.7.2 Note:
-<i>
-  Instead of the above, you will need antlrall.jar that can be created
-  by the <b>antlr-all.jar</b> target of the Makefile provided with the
-  download.
-</i>
-</p>
+<p>Invokes the <a href="https://www.antlr.org/" target="_top">ANTLR</a> Translator generator on a
+grammar file.</p>
+<p>To use the ANTLR task, set the <var>target</var> attribute to the name of the grammar file to
+process.  Optionally, you can also set the <var>outputdirectory</var> to write the generated file to
+a specific directory.  Otherwise ANTLR writes the generated files to the directory containing the
+grammar file.</p>
+<p>This task only invokes ANTLR if the grammar file (or the supergrammar specified by
+the <var>glib</var> attribute) is newer than the generated files.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
+<p>Antlr 2.7.2 Note: <em>You will need <samp>antlrall.jar</samp> that can be created by
+the <q>antlr-all.jar</q> target of the Makefile provided with the download.</em></p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">target</td>
-    <td valign="top">The grammar file to process.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>target</td>
+    <td>The grammar file to process.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">outputdirectory</td>
-    <td valign="top">
-      The directory to write the generated files to.  If not set, the files
-      are written to the directory containing the grammar file.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>outputdirectory</td>
+    <td>The directory to write the generated files to.</td>
+    <td>No; defaults to the directory containing the grammar file</td>
   </tr>
   <tr>
-    <td valign="top">glib</td>
-    <td valign="top">
-      An optional super grammar file that the target grammar overrides.  This
-      feature is only needed for advanced vocabularies.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>glib</td>
+    <td>An optional super grammar file that the target grammar overrides.  This feature is only
+      needed for advanced vocabularies.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">debug</td>
-    <td valign="top">
-      When set to "yes", this flag adds code to the generated parser that will
-      launch the ParseView debugger upon invocation.  The default is "no".
-      <br>
-      Note: ParseView is a separate component that needs to be installed or your
-      grammar will have compilation errors.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>debug</td>
+    <td>When set to <q>yes</q>, this flag adds code to the generated parser that will launch the
+      ParseView debugger upon invocation.<br/>  Note: ParseView is a separate component that needs
+      to be installed or your grammar will have compilation errors.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">html</td>
-    <td valign="top">
-      Emit an html version of the grammar with hyperlinked actions.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>html</td>
+    <td>Emit an HTML version of the grammar with hyperlinked actions if set to <q>yes</q>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">diagnostic</td>
-    <td valign="top">
-      Generates a text file with debugging information based on the target grammar.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>diagnostic</td>
+    <td>Generate a text file with debugging information based on the target grammar if set
+      to <q>yes</q>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">trace</td>
-    <td valign="top">
-      Forces <b>all</b> rules to call traceIn/traceOut if set to "yes".
-      The default is "no".
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>trace</td>
+    <td>Force <strong>all</strong> rules to call traceIn/traceOut if set to <q>yes</q>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">traceParser</td>
-    <td valign="top">
-      Only forces parser rules to call traceIn/traceOut if set to "yes".
-      The default is "no".
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>traceParser</td>
+    <td>Only force parser rules to call traceIn/traceOut if set to <q>yes</q>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">traceLexer</td>
-    <td valign="top">
-      Only forces lexer rules to call traceIn/traceOut if set to "yes".
-      The default is "no".
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>traceLexer</td>
+    <td>Only force lexer rules to call traceIn/traceOut if set to <q>yes</q>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">traceTreeWalker</td>
-    <td valign="top">
-      Only forces tree walker rules to call traceIn/traceOut if set to
-      "yes".  The default is "no".
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>traceTreeWalker</td>
+    <td>Only force tree walker rules to call traceIn/traceOut if set to <q>yes</q>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <!--tr>
-    <td valign="top">fork</td>
-    <td valign="top">Run ANTLR in a separate VM.</td>
-    <td align="center" valign="top">No, default is &quot;off&quot;</td>
+    <td>fork</td>
+    <td>Run ANTLR in a separate JVM.</td>
+    <td>No; default is <q>off</q></td>
   </tr-->
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The directory to invoke the VM in. <!--(ignored if
-      fork is disabled)--></td>
-    <td align="center" valign="top">No</td>
+    <td>dir</td>
+    <td>The directory to invoke JVM in.<!--(ignored if fork is disabled)--></td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3><a name="nested">Nested Elements</a></h3>
+<h3 id="nested">Parameters specified as nested elements</h3>
 
-<p><code>ANTLR</code> supports a nested <code>&lt;classpath&gt;</code>
-element, that represents a <a href="../using.html#path">PATH like
-structure</a>. It is given as a convenience if you have to specify
-the original ANTLR directory. In most cases, dropping the appropriate
-ANTLR jar in the normal Ant lib repository will be enough.</p>
+<p>The task supports a nested <code>&lt;classpath&gt;</code> element, that represents
+a <a href="../using.html#path">path-like structure</a>. It is given as a convenience if you have to
+specify the original ANTLR directory. In most cases, dropping the appropriate ANTLR jar in the
+normal Ant lib repository will be enough.</p>
 
 <h4>jvmarg</h4>
 
-<p><!--If fork is enabled, -->Additional parameters may be passed to the new
-VM via nested <code>&lt;jvmarg&gt;</code> attributes, for example:</p>
+<p><!--If fork is enabled, -->Additional parameters may be passed to the new JVM via
+nested <code>&lt;jvmarg&gt;</code> attributes, for example:</p>
 
 <pre>
 &lt;antlr target="..."&gt;
   &lt;jvmarg value=&quot;-Djava.compiler=NONE&quot;/&gt;
   ...
-&lt;/antlr&gt;
-</pre>
+&lt;/antlr&gt;</pre>
 
-<p>would run ANTLR in a VM without JIT.</p>
+<p>would run ANTLR in a JVM without JIT.</p>
 
-<p><code>&lt;jvmarg&gt;</code> allows all attributes described in <a
-href="../using.html#arg">Command line arguments</a>.</p>
+<p><code>&lt;jvmarg&gt;</code> allows all attributes described
+in <a href="../using.html#arg">Command line arguments</a>.</p>
 
 <h3>Example</h3>
-<blockquote><pre>
+<p>Invoke ANTLR on grammar file <samp>etc/java.g</samp>, writing the generated files
+to <samp>build/src</samp>:</p>
+<pre>
 &lt;antlr
     target=&quot;etc/java.g&quot;
-    outputdirectory=&quot;build/src&quot;
-/&gt;
-</pre></blockquote>
-<p>
-  This invokes ANTLR on grammar file etc/java.g, writing the generated
-  files to build/src.
-</p>
-
+    outputdirectory=&quot;build/src&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/antstructure.html b/manual/Tasks/antstructure.html
index ab7acc1..8cda7fe 100644
--- a/manual/Tasks/antstructure.html
+++ b/manual/Tasks/antstructure.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,86 +15,77 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>AntStructure Task</title>
 </head>
 
 <body>
 
-<h2><a name="antstructure">AntStructure</a></h2>
-<h3>Description</h3> 
+<h2 id="antstructure">AntStructure</h2>
+<h3>Description</h3>
 
-<p>Generates an DTD for Apache Ant buildfiles which contains information
-about all tasks currently known to Ant.</p>
+<p>Generates an DTD for Apache Ant buildfiles which contains information about all tasks currently
+known to Ant.</p>
 
-<p>Actually the DTD will not be a real DTD for buildfiles since Ant's
-usage of XML cannot be captured with a DTD.  Several elements in Ant
-can have different attribute lists depending on the element that
-contains them.  &quot;fail&quot; for example can be <a
-href="fail.html">the task</a> or the nested child element of the <a
-href="../Tasks/sound.html">sound</a> task.  Don't consider the
-generated DTD something to rely upon.</p>
+<p>Actually the DTD will not be a real DTD for buildfiles since Ant's usage of XML cannot be
+captured with a DTD.  Several elements in Ant can have different attribute lists depending on the
+element that contains them. <a href="fail.html"><code>&lt;fail&gt;</code></a> for example can be a
+task or a nested child element of the <a href="../Tasks/sound.html"><code>&lt;sound&gt;</code></a>
+task.  Don't consider the generated DTD something to rely upon.</p>
 
-<p>Also note that the DTD generated by this task is incomplete, you can
-always add XML entities using <a
-href="taskdef.html"><code>&lt;taskdef&gt;</code></a> or <a
-href="typedef.html"><code>&lt;typedef&gt;</code></a>. See <a
-href="http://www.sdv.fr/pages/casa/html/ant-dtd.en.html"
+<p>Also note that the DTD generated by this task is incomplete, you can always add XML entities
+using <a href="taskdef.html"><code>&lt;taskdef&gt;</code></a>
+or <a href="typedef.html"><code>&lt;typedef&gt;</code></a>.
+See <a href="https://web.archive.org/web/20071231061243/http://www.sdv.fr/pages/casa/html/ant-dtd.en.html"
 target="_top">here</a> for a way to get around this problem.</p>
-<p>This task doesn't know about required attributes, all will be
-listed as <code>#IMPLIED</code>.</p>
+<p>This task doesn't know about required attributes, all will be listed
+as <code>#IMPLIED</code>.</p>
 
-<p><em>Since Ant 1.7</em> custom structure printers can be used
-instead of the one that emits a DTD.  In order to plug in your own
-structure, you have to implement the interface
-<code>org.apache.tools.ant.taskdefs.AntStructure.StructurePrinter</code>
-and <code>&lt;typedef&gt; your class and use the new type as a nested
-element of this task - see the example below.</code>
+<p><em>Since Ant 1.7</em> custom structure printers can be used instead of the one that emits a DTD.
+In order to plug in your own structure, you have to implement the
+interface <code class="code">org.apache.tools.ant.taskdefs.AntStructure.StructurePrinter</code>
+and <code>&lt;typedef&gt;</code> your class and use the new type as a nested element of this
+task&mdash;see the example below.
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">file to write the DTD to.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>output</td>
+    <td>file to write the DTD to.</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;antstructure output=&quot;project.dtd&quot; /&gt;
-</pre></blockquote>
+<p>Basic usage</p>
 
-<p><b>Emitting your own structure instead of a DTD</b></p>
+<pre>&lt;antstructure output=&quot;project.dtd&quot;/&gt;</pre>
 
-<p>First you need to implement the interface</p>
+<p>Emit your own structure instead of a DTD: first you need to implement the interface</p>
 
 <pre>
 package org.example;
 import org.apache.tools.ant.taskdefs.AntStructure;
 public class MyPrinter implements AntStructure.StructurePrinter {
     ...
-}
-</pre>
+}</pre>
 
 <p>and then use it via typedef</p>
 
 <pre>
-  &lt;typedef name="myprinter" classname="org.example.MyPrinter" /&gt;
-  &lt;antstructure output="project.my"&gt;
-    &lt;myprinter /&gt;
-  &lt;/antstructure&gt;
-</pre>
+&lt;typedef name="myprinter" classname="org.example.MyPrinter"/&gt;
+&lt;antstructure output="project.my"&gt;
+  &lt;myprinter/&gt;
+&lt;/antstructure&gt;</pre>
 
-<p>Your own StructurePrinter can accept attributes and nested elements
+<p>Your own <code class="code">StructurePrinter</code> can accept attributes and nested elements
 just like any other Ant type or task.</p>
 
 </body>
diff --git a/manual/Tasks/antversion.html b/manual/Tasks/antversion.html
index cd9f838..7f032b5 100644
--- a/manual/Tasks/antversion.html
+++ b/manual/Tasks/antversion.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,82 +15,73 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Antversion Task</title>
 </head>
 
 <body>
 
-<h2><a name="antversion">Antversion</a></h2>
+<h2 id="antversion">Antversion</h2>
+<p><em>Since Ant 1.7.0</em></p>
 <h3>Description</h3>
-<p>
-Stores the Apache Ant version (when used as task) or checks for a specific Ant version 
-(when used as condition).
-<b>Since Ant 1.7.0</b>
-</p>
+<p>Stores the Apache Ant version (when used as task) or checks for a specific Ant version (when used
+as condition).</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required (Task)</b></td>
-    <td align="center" valign="top"><b>Required (Condition)</b></td>
+    <th scope="col" rowspan="2">Attribute</th>
+    <th scope="col" rowspan="2">Description</th>
+    <th scope="col" colspan="2">Required</th>
   </tr>
   <tr>
-    <td valign="top">atleast</td>
-    <td valign="top">The version that this at least.
-      The format is major.minor.point.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" rowspan="2" align="center">One of these.</td>
+    <th scope="col">Task</th>
+    <th scope="col">Condition</th>
   </tr>
   <tr>
-    <td valign="top">exactly</td>
-    <td valign="top">The version that this ant is exactly.
-      The format is <tt>major.minor.point</tt>.</td>
-    <td valign="top" align="center">No</td>
+    <td>atleast</td>
+    <td>The version that this Ant is of at least.  The format
+      is <code>major.minor.point</code>.</td>
+    <td class="center">No</td>
+    <td rowspan="2">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to set.</td>
-    <td valign="top" align="center">Yes</td>
-    <td valign="top" align="center">No (ignored)</td>
+    <td>exactly</td>
+    <td>The version that this Ant is of exactly.  The format is <code>major.minor.point</code>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>property</td>
+    <td>The name of the property to set.</td>
+    <td class="center">Yes</td>
+    <td>Ignored</td>
   </tr>
 </table>
 
-
 <h3>Examples</h3>
 
-<blockquote><pre>
-&lt;antversion property=&quot;antversion&quot;/&gt;
-</pre></blockquote>
-<p>Stores the current Ant version in the property <i>antversion</i>.</p>
+<p>Store the current Ant version in the property <code>antversion</code>.</p>
+<pre>&lt;antversion property=&quot;antversion&quot;/&gt;</pre>
 
-<blockquote><pre>
-&lt;antversion property=&quot;antversion&quot; atleast=&quot;1.6&quot;/&gt;
-</pre></blockquote>
-<p>Stores the Ant version in the property <i>antversion</i> if the current Ant version is 1.6.0
+<p>Store the Ant version in the property <code>antversion</code> if the current Ant version is 1.6.0
 or higher. Otherwise the property remains unset.</p>
+<pre>&lt;antversion property=&quot;antversion&quot; atleast=&quot;1.6&quot;/&gt;</pre>
 
-<blockquote><pre>
-&lt;antversion property=&quot;ant-is-exact-7&quot; exactly=&quot;1.7.0&quot;/&gt;
-</pre></blockquote>
-<p>Sets the property <i>ant-is-exact-7</i> if Ant 1.7.0 is running. Neither 1.6.5 nor 1.7.0
+<p>Set the property <code>ant-is-exact-7</code> if Ant 1.7.0 is running. Neither 1.6.5 nor 1.7.1
 would match.</p>
+<pre>&lt;antversion property=&quot;ant-is-exact-7&quot; exactly=&quot;1.7.0&quot;/&gt;</pre>
 
-<blockquote><pre>
+<p>Set <code>Ant17isOnline</code> if Ant 1.7.0 is running and can get a non-error-response from the
+Ant homepage.</p>
+<pre>
 &lt;condition property=&quot;Ant17isOnline&quot;&gt;
   &lt;and&gt;
     &lt;antversion exactly=&quot;1.7.0&quot;/&gt;
-    &lt;http url=&quot;http://ant.apache.org&quot;/&gt;
+    &lt;http url=&quot;https://ant.apache.org&quot;/&gt;
   &lt;/and&gt;
-&lt;/condition&gt;
-</pre></blockquote>
-<p>Sets <i>Ant17isOnline</i> if Ant 1.7.0 is running and can get a non-error-response from
-the Ant homepage.</p>
+&lt;/condition&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/apply.html b/manual/Tasks/apply.html
index 5444a64..fad38c0 100644
--- a/manual/Tasks/apply.html
+++ b/manual/Tasks/apply.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,393 +15,366 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Apply Task</title>
 </head>
 
 <body>
 
-<h2><a name="apply">Apply/<i>ExecOn</i></a></h2>
-<p><i>The name <code>execon</code> is deprecated and only kept for backwards
-compatibility.</i></p>
+<h2 id="apply">Apply</h2>
+<p><em>The name <code>execon</code> is <u>deprecated</u> and only kept for backwards
+compatibility.</em></p>
 <h3>Description</h3>
-<p>Executes a system command. When the <i>os</i> attribute is specified, then
-the command is only executed when Apache Ant is run on one of the specified operating
-systems.</p>
+<p>Executes a system command. When the <var>os</var> attribute is specified, then the command is
+only executed when Apache Ant is run on one of the specified operating systems.</p>
 
-<p>The files and/or directories of a number of <a
-href="../Types/resources.html#collection">Resource Collection</a>s
-&ndash; including but not restricted to
- <a href="../Types/fileset.html">FileSet</a>s,
- <a href="../Types/dirset.html">DirSet</a>s
- (<em>since&nbsp;Ant&nbsp;1.6</em>) or
- <a href="../Types/filelist.html">FileList</a>s
- (<em>since&nbsp;Ant&nbsp;1.6</em>)
-&ndash;
- are passed as arguments to the system command.</p>
-<p>If you specify a nested <a href="../Types/mapper.html">mapper</a>,
-the timestamp of each source file is compared to the timestamp of a
-target file which is defined by the nested mapper element and searched
-for in the given <i>dest</i>, if specified.</p>
-<p>At least one fileset or filelist is required,
-and you must not specify more than one mapper.</p>
+<p>The files and/or directories of a number of <a href="../Types/resources.html#collection">Resource
+Collection</a>s &ndash;- including but not restricted
+to <a href="../Types/fileset.html">FileSet</a>s, <a href="../Types/dirset.html">DirSet</a>s
+(<em>since Ant 1.6</em>) or <a href="../Types/filelist.html">FileList</a>s (<em>since Ant 1.6</em>)
+&ndash;- are passed as arguments to the system command.</p>
+<p>If you specify a nested <a href="../Types/mapper.html">mapper</a>, the timestamp of each source
+file is compared to the timestamp of a target file which is defined by the
+nested <code>mapper</code> element and searched for in the given <var>dest</var>, if specified.</p>
+<p>At least one <code>fileset</code> or <code>filelist</code> is required, and you must not specify
+more than one <code>mapper</code>.</p>
 
-<p>Note that you cannot interact with the forked program, the only way
-to send input to it is via the input and inputstring attributes.</p>
+<p>Note that you cannot interact with the forked program, the only way to send input to it is via
+the <var>input</var> and <var>inputstring</var> attributes.</p>
 
-<h4><a name="background">Running Ant as a background process on
-    Unix(-like) systems</a></h4>
+<h4 id="background">Running Ant as a background process on Unix(-like) systems</h4>
 
-<p>If you run Ant as a background process (like <code>ant &</code>)
-  and use the <code>&lt;apply&gt;</code> task with <code>spawn</code>
-  set to <code>false</code>, you must provide explicit input to the
-  forked process or Ant will be suspended because it tries to read
-  from the standard input.</p>
+<p>If you run Ant as a background process (like <kbd>ant &amp;</kbd>) and use
+the <code>&lt;apply&gt;</code> task with <var>spawn</var> set to <q>false</q>, you must provide
+explicit input to the forked process or Ant will be suspended because it tries to read from the
+standard input.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">the command to execute without any command line
-      arguments.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>executable</td>
+    <td>the command to execute without any command line arguments.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">the directory where the command is expected to place
-    target files when it is executed. This attribute is valid only when used
-    in conjunction with a nested mapper; if omitted, the target filenames
-    returned by the mapper will be interpreted as absolute paths.</td>
-    <td align="center" valign="top">No</td>
+    <td>dest</td>
+    <td>the directory where the command is expected to place target files when it is executed.</td>
+    <td>No; ignored unless a nested mapper is specified; by default, the target filenames returned
+      by the mapper will be interpreted as absolute paths</td>
   </tr>
   <tr>
-    <td valign="top">spawn</td>
-    <td valign="top">whether or not you want the commands to be spawned.<br>
-    If you spawn a command, its output will not be logged by ant.<br>
-    The input, output, error, and result property settings are not active when spawning a process.<br>
-    <em>since&nbsp;Ant&nbsp;1.6</em>
-    </td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
-  </tr>
-
-  <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the directory in which the command should be executed.</td>
-    <td align="center" valign="top">No.<br/>
-      <strong>Note:</strong> the default used when dir has not been
-      specified depends on the <code>vmlauncher</code> attribute.  If
-      <code>vmlauncher</code> is <code>true</code> the task will use
-      the current working directory, otherwise it uses the project's basedir.
-    </td>
+    <td>spawn</td>
+    <td>whether or not you want the commands to be spawned.<br/>  If you spawn a command, its output
+    will not be logged by Ant.<br/>  The input, output, error, and result property settings are not
+    active when spawning a process.<br/>  <em>since Ant 1.6</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">relative</td>
-    <td valign="top">whether the filenames should be passed on the
-      command line as relative pathnames (relative to the base directory
-      of the corresponding fileset/list for source files or the
-      <i>dest</i> attribute for target files).</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>dir</td>
+    <td>the directory in which the command should be executed.</td>
+    <td>No; if <var>vmlauncher</var> is <q>true</q>, defaults to the current working directory,
+      otherwise the project's <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">forwardslash</td>
-    <td valign="top">whether the file names should be passed
-      with forward slashes even if the operating system requires other
-      file separator. The option is ignored if the system file separator
-      is a forward slash.</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>relative</td>
+    <td>whether the filenames should be passed on the command line as relative pathnames (relative
+      to the base directory of the corresponding fileset/list for source files or
+      the <var>dest</var> attribute for target files).</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">os</td>
-    <td valign="top">list of Operating Systems on which the command may be
-      executed.</td>
-    <td align="center" valign="top">No</td>
+    <td>forwardslash</td>
+    <td>whether the file names should be passed with forward slashes even if the operating system
+      requires other file separator. The option is ignored if the system file separator is a forward
+      slash.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">osfamily</td>
-    <td valign="top">OS family as used in the &lt;os&gt; condition.
+    <td>os</td>
+    <td>list of Operating Systems on which the command may be executed.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>osfamily</td>
+    <td>OS family as used in the <code>&lt;os&gt;</code> condition.
     <em>since Ant 1.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">the file to which the output of the command
-    should be redirected.  If the error stream is not also redirected
-    to a file or property, it will appear in this output.</td>
-    <td align="center" valign="top">No</td>
+    <td>output</td>
+    <td>the file to which the output of the command should be redirected.  If the error stream is
+    not also redirected to a file or property, it will appear in this output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">error</td>
-    <td valign="top">The file to which the standard error of the
-    command should be redirected.  <em>since&nbsp;Ant&nbsp;1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>error</td>
+    <td>The file to which the standard error of the command should be redirected.  <em>since Ant
+    1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">logError</td>
-    <td valign="top">This attribute is used when you wish to see error
-    output in Ant's log and you are redirecting output to a
-    file/property. The error output will not be included in the output
-    file/property. If you redirect error with the &quot;error&quot; or
-    &quot;errorProperty&quot; attributes, this will have no effect.
-    <em>since&nbsp;Ant&nbsp;1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>logError</td>
+    <td>This attribute is used when you wish to see error output in Ant's log and you are
+    redirecting output to a file/property. The error output will not be included in the output
+    file/property. If you redirect error with the <var>error</var> or <var>errorProperty</var>
+    attributes, this will have no effect.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">whether output should be appended to or overwrite
-      an existing file.  If you set parallel to false, you will probably
-      want to set this one to true.</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>append</td>
+    <td>whether output should be appended to or overwrite an existing file.  If you
+      set <var>parallel</var> to <q>false</q>, you will probably want to set this one
+      to <q>true</q>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">outputproperty</td>
-    <td valign="top">the name of a property in which the output of the
-    command should be stored.  Unless the error stream is redirected
-    to a separate file or stream, this property will include the error
+    <td>outputproperty</td>
+    <td>the name of a property in which the output of the command should be stored.  Unless the
+    error stream is redirected to a separate file or stream, this property will include the error
     output.</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property in which the standard error of the
-      command should be stored.  <em>since&nbsp;Ant&nbsp;1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property in which the standard error of the command should be
+      stored.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">input</td>
-    <td valign="top">A file from which the executed command's standard
-    input is taken. This attribute is mutually exclusive with the
-    inputstring attribute.  <em>since&nbsp;Ant&nbsp;1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>input</td>
+    <td>A file from which the executed command's standard input is taken. This attribute is mutually
+    exclusive with the <var>inputstring</var> attribute.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputstring</td>
-    <td valign="top">A string which serves as the input stream for the
-    executed command. This attribute is mutually exclusive with the
-    input attribute.  <em>since&nbsp;Ant&nbsp;1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>inputstring</td>
+    <td>A string which serves as the input stream for the executed command. This attribute is
+    mutually exclusive with the <var>input</var> attribute.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">resultproperty</td>
-    <td valign="top">the name of a property in which the return code
-      of the command should be stored. Only of interest if
-      failonerror=false. If you set parallel to false, only the result
-      of the first execution will be stored.</td>
-    <td align="center" valign="top">No</td>
+    <td>resultproperty</td>
+    <td>the name of a property in which the return code of the command should be stored. Only of
+      interest if <var>failonerror</var> is <q>false</q>. If you set <var>parallel</var>
+      to <q>false</q>, only the result of the first execution will be stored.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Stop the command if it doesn't finish within the
-      specified time (given in milliseconds).</td>
-    <td align="center" valign="top">No</td>
+    <td>timeout</td>
+    <td>Stop the command if it doesn't finish within the specified time (given in
+      milliseconds).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the buildprocess if the command exits with a
-      returncode other than 0.</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failifexecutionfails</td>
-    <td valign="top">Stop the build if we can't start the program.
-      Defaults to true. </td>
-    <td align="center" valign="top">No</td>
+    <td>failifexecutionfails</td>
+    <td>Stop the build if we can't start the program.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">skipemptyfilesets</td>
-    <td valign="top">Don't run the command, if no source files have
-      been found or are newer than their corresponding target
-      files.  Despite its name, this attribute applies to filelists as
+    <td>skipemptyfilesets</td>
+    <td>Don't run the command, if no source files have been found or are newer than their
+      corresponding target files.  Despite its name, this attribute applies to filelists as
       well.</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">parallel</td>
-    <td valign="top">Run the command only once, appending all files as
-      arguments. If false, command will be executed once for every file.</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>parallel</td>
+    <td>Run the command only once, appending all files as arguments. If <q>false</q>, command will
+      be executed once for every file.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">One of <i>file</i>, <i>dir</i> or
-      <i>both</i>. If set to <i>file</i>, only the names of plain
-      files will be sent to the command. If set to <i>dir</i>, only
-      the names of directories are considered.<br>
-      <strong>Note:</strong> The type attribute does not apply to
-      nested <i>dirset</i>s - <i>dirset</i>s always implicitly
-      assume type to be <i>dir</i>.</td>
-    <td align="center" valign="top">No, default is <i>file</i></td>
+    <td>type</td>
+    <td>One of <q>file</q>, <q>dir</q> or <q>both</q>. If set to <q>file</q>, only the names of
+      plain files will be sent to the command. If set to <q>dir</q>, only the names of directories
+      are considered.<br/>
+      <strong>Note</strong>: The <var>type</var> attribute does not apply to
+      nested <code>dirset</code>s&mdash;<code>dirset</code>s always implicitly assume type to
+      be <q>dir</q>.</td>
+    <td>No; default is <q>file</q></td>
   </tr>
   <tr>
-    <td valign="top">newenvironment</td>
-    <td valign="top">Do not propagate old environment when new environment
-      variables are specified.</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>newenvironment</td>
+    <td>Do not propagate old environment when new environment variables are specified.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">vmlauncher</td>
-    <td valign="top">Run command using the Java VM's execution facilities
-        where available. If set to false the underlying OS's shell,
-        either directly or through the antRun scripts, will be used.
-        Under some operating systems, this gives access to facilities
-        not normally available through the VM including, under Windows,
-        being able to execute scripts, rather than their associated
-        interpreter.  If you want to specify the name of the
-        executable as a relative path to the directory given by the
-        dir attribute, it may become necessary to set vmlauncher to
-        false as well.</td>
-    <td align="center" valign="top">No, default is <i>true</i></td>
+    <td>vmlauncher</td>
+    <td>Run command using the JVM's execution facilities where available. If set to <q>false</q> the
+      underlying OS's shell, either directly or through the <kbd>antRun</kbd> scripts, will be
+      used.  Under some operating systems, this gives access to facilities not normally available
+      through JVM including, under Windows, being able to execute scripts, rather than their
+      associated interpreter.  If you want to specify the name of the executable as a relative path
+      to the directory given by the <var>dir</var> attribute, it may become necessary to
+      set <var>vmlauncher</var> to <q>false</q> as well.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">resolveExecutable</td>
-    <td valign="top">When this attribute is true, the name of the
-    executable if resolved firstly against the project basedir and if
-    that does not exist, against the execution directory if
-    specified. On Unix systems, if you only want to allow execution of
-    commands in the user's path, set this to false.
-    <em>since&nbsp;Ant&nbsp;1.6</em></td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>resolveExecutable</td>
+    <td>When this attribute is <q>true</q>, the name of the executable if resolved firstly against
+      the project <var>basedir</var> and if that does not exist, against the execution directory if
+      specified. On Unix systems, if you only want to allow execution of commands in the user's
+      path, set this to <q>false</q>.
+    <em>since Ant 1.6</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">maxparallel</td>
-    <td valign="top">Limit the amount of parallelism by passing at
-      most this many sourcefiles at once.  Set it to &lt;= 0 for
-      unlimited. <em>Since&nbsp;Ant&nbsp;1.6.</em></td>
-    <td align="center" valign="top">No, unlimited by default</td>
+    <td>maxparallel</td>
+    <td>Limit the amount of parallelism by passing at most this many sourcefiles at once.  Set it to
+      negative integer for unlimited. <em>Since Ant 1.6</em>.</td>
+    <td>No, unlimited by default</td>
   </tr>
   <tr>
-    <td valign="top">addsourcefile</td>
-    <td valign="top">Whether source file names should be added to the
-      command automatically. <em>Since&nbsp;Ant&nbsp;1.6.</em></td>
-    <td align="center" valign="top">No, default is <i>true</i></td>
+    <td>addsourcefile</td>
+    <td>Whether source file names should be added to the command automatically. <em>Since Ant
+      1.6</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to print a summary after execution or not.
-      <em>Since&nbsp;Ant&nbsp;1.6.</em></td>
-    <td align="center" valign="top">No, default <i>false</i></td>
+    <td>verbose</td>
+    <td>Whether to print a summary after execution or not.  <em>Since Ant 1.6</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">ignoremissing</td>
-    <td valign="top">Whether to ignore nonexistent files specified
-      via filelists.  <em>Since&nbsp;Ant&nbsp;1.6.2.</em></td>
-    <td align="center" valign="top">No, default is <i>true</i></td>
+    <td>ignoremissing</td>
+    <td>Whether to ignore nonexistent files specified via filelists.  <em>Since Ant 1.6.2</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">Whether to bypass timestamp comparisons
-      for target files.  <em>Since&nbsp;Ant&nbsp;1.6.3.</em></td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>force</td>
+    <td>Whether to bypass timestamp comparisons for target files.  <em>Since Ant 1.6.3</em>.</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>discardOutput</td>
+    <td>Whether output should completely be discarded. This setting is
+      incompatible with any setting that redirects output to files or
+      properties.<br/>
+      If you set this to <q>true</q> error output will be discared as
+      well unless you redirect error output to files, properties or
+      enable <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>discardError</td>
+    <td>Whether error output should completely be discarded. This
+      setting is incompatible with any setting that redirects error
+      output to files or properties as well as <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>fileset</h4>
-<p>You can use any number of nested <code>&lt;fileset&gt;</code>
-elements to define the files for this task and refer to
-<code>&lt;fileset&gt;</code>s defined elsewhere.</p>
-<h4>filelist</h4>
-<p><em>Since&nbsp;Ant&nbsp;1.6</em></p>
-<p>You can use any number of nested <code>&lt;filelist&gt;</code>
-elements to define the files for this task and refer to
-<code>&lt;filelist&gt;</code>s defined elsewhere.</p>
-<h4>dirset</h4>
-<p><em>Since&nbsp;Ant&nbsp;1.6</em></p>
-<p>You can use any number of nested <code>&lt;dirset&gt;</code>
-elements to define the directories for this task and refer to
-<code>&lt;dirset&gt;</code>s defined elsewhere.</p>
+<p>You can use any number of nested <code>&lt;fileset&gt;</code> elements to define the files for
+this task and refer to <code>&lt;fileset&gt;</code>s defined elsewhere.</p>
 
-<h4>Any other <a href="../Types/resources.html#collection">Resource
-Collection</a></h4>
-<p><em>since Ant 1.7</em></p>
+<h4>filelist</h4>
+<p><em>Since Ant 1.6</em></p>
+<p>You can use any number of nested <code>&lt;filelist&gt;</code> elements to define the files for
+this task and refer to <code>&lt;filelist&gt;</code>s defined elsewhere.</p>
+
+<h4>dirset</h4>
+<p><em>Since Ant 1.6</em></p>
+<p>You can use any number of nested <code>&lt;dirset&gt;</code> elements to define the directories
+for this task and refer to <code>&lt;dirset&gt;</code>s defined elsewhere.</p>
+
+<h4>Any other <a href="../Types/resources.html#collection">resource collection</a></h4>
+<p><em>Since Ant 1.7</em></p>
 <p>You can use any number of nested resource collections.</p>
 
 <h4>mapper</h4>
-<p>A single <code>&lt;mapper&gt;</code> specifies the target files relative
-to the <code>dest</code> attribute for dependency checking. If the
-<code>dest</code> attribute is specified it will be used as a base directory
-for resolving relative pathnames returned by the mapper. At least one
+<p>A single <code>&lt;mapper&gt;</code> specifies the target files relative to the <var>dest</var>
+attribute for dependency checking. If the <var>dest</var> attribute is specified it will be used as
+a base directory for resolving relative pathnames returned by the mapper. At least one
 <code>&lt;fileset&gt;</code> or <code>&lt;filelist&gt;</code> is required.</p>
+
 <h4>arg</h4>
-<p>Command line arguments should be specified as nested
-<code>&lt;arg&gt;</code> elements. See <a
-href="../using.html#arg">Command line arguments</a>.</p>
+<p>Command line arguments should be specified as nested <code>&lt;arg&gt;</code>
+elements. See <a href="../using.html#arg">Command line arguments</a>.</p>
+
 <h4>srcfile</h4>
-<p>By default the file names of the source files will be added to the
-end of the command line (unless you set addsourcefile to
-<code>false</code>). If you need to place it somewhere different,
-use a nested <code>&lt;srcfile&gt;</code> element between your
-<code>&lt;arg&gt;</code> elements to mark the insertion point.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>By default the file names of the source files will be added to the end of the command line
+(unless you set <var>addsourcefile</var> to <q>false</q>). If you need to place it somewhere
+different, use a nested <code>&lt;srcfile&gt;</code> element between your <code>&lt;arg&gt;</code>
+elements to mark the insertion point.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">a prefix to place in front of the file name when
-    building the command line argument.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No.</td>
+    <td>prefix</td>
+    <td>a prefix to place in front of the file name when building the command line
+    argument.  <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">a suffix to append to the file name when
-    building the command line argument.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No.</td>
+    <td>suffix</td>
+    <td>a suffix to append to the file name when building the command line argument.  <em>Since Ant
+    1.8.0</em></td>
+    <td>No</td>
   </tr>
 </table>
 <h4>targetfile</h4>
-<p><code>&lt;targetfile&gt;</code> is similar to
-<code>&lt;srcfile&gt;</code> and marks the position of the target
-filename on the command line. If omitted, the target filenames will
-not be added to the command line at all. This element can only be
-specified if you also define a nested mapper.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p><code>&lt;targetfile&gt;</code> is similar to <code>&lt;srcfile&gt;</code> and marks the position
+of the target filename on the command line. If omitted, the target filenames will not be added to
+the command line at all. This element can only be specified if you also define a nested mapper.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">a prefix to place in front of the file name when
-    building the command line argument.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No.</td>
+    <td>prefix</td>
+    <td>a prefix to place in front of the file name when building the command line
+    argument.  <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">a suffix to append to the file name when
-    building the command line argument.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No.</td>
+    <td>suffix</td>
+    <td>a suffix to append to the file name when building the command line argument.  <em>Since Ant
+    1.8.0</em></td>
+    <td>No</td>
   </tr>
 </table>
 <h4>env</h4>
-<p>It is possible to specify environment variables to pass to the
-system command via nested <code>&lt;env&gt;</code> elements. See the
-description in the section about <a href="exec.html#env">exec</a></p>
+<p>It is possible to specify environment variables to pass to the system command via
+nested <code>&lt;env&gt;</code> elements. See the description in the section
+about <a href="exec.html#env">exec</a></p>
 <h4>redirector</h4>
-<i><b>Since&nbsp;Ant&nbsp;1.6.2</b></i>
-<p>A nested <a href="../Types/redirector.html">I/O Redirector</a>
-can be specified.  &lt;apply&gt;'s behavior is like that of
-<a href="exec.html#redirector">exec</a> with regard to
-redirectors, with the exception that, in non-<i>parallel</i> mode,
-file mapping will take place with each iteration.  This grants the
-user the capacity to receive input from, and send output to, different
-files for each sourcefile.
-</p>
-<p>In <i>parallel</i>-mode the redirector will be reset for each batch
-  of executions (with <i>maxparallel</i> &gt; 0) and null will be used
-  a source file just like it is in the case of <code>exec</code>.</p>
+<em>Since Ant 1.6.2</em>
+<p>A nested <a href="../Types/redirector.html">I/O Redirector</a> can be specified.  &lt;apply&gt;'s
+behavior is like that of <a href="exec.html#redirector">exec</a> with regard to redirectors, with
+the exception that, in non-<var>parallel</var> mode, file mapping will take place with each
+iteration.  This grants the user the capacity to receive input from, and send output to, different
+files for each sourcefile.</p>
+<p>In <var>parallel</var> mode the redirector will be reset for each batch of executions
+(with <var>maxparallel</var> &gt; 0) and null will be used a source file just like it is in the case
+of <code>exec</code>.</p>
 <h3>Examples</h3>
-<blockquote><pre>
+<p>Invoke <kbd>ls -l</kbd>, adding the absolute filenames of all files below <samp>/tmp</samp> not
+ending in <samp>.txt</samp> and all files of the FileSet with <var>id</var> <samp>other.files</samp>
+to the command line.</p>
+<pre>
 &lt;apply executable=&quot;ls&quot;&gt;
   &lt;arg value=&quot;-l&quot;/&gt;
   &lt;fileset dir=&quot;/tmp&quot;&gt;
@@ -409,26 +383,26 @@
     &lt;/patternset&gt;
   &lt;/fileset&gt;
   &lt;fileset refid=&quot;other.files&quot;/&gt;
-&lt;/apply&gt;
-</pre></blockquote>
-<p>invokes <code>ls -l</code>, adding the absolute filenames of all
-files below <code>/tmp</code> not ending in <code>.txt</code> and all
-files of the FileSet with <code>id</code> <code>other.files</code> to
-the command line.</p>
-<blockquote><pre>
+&lt;/apply&gt;</pre>
+
+<p>Invoke <kbd>somecommand arg1 SOURCEFILENAME arg2</kbd> for each file in <samp>/tmp</samp>
+replacing <code>SOURCEFILENAME</code> with the absolute filename of each file in
+turn. If <var>parallel</var> had been set to <q>true</q>, <code>SOURCEFILENAME</code> would be
+replaced with the absolute filenames of all files separated by spaces.</p>
+<pre>
 &lt;apply executable=&quot;somecommand&quot; parallel=&quot;false&quot;&gt;
   &lt;arg value=&quot;arg1&quot;/&gt;
   &lt;srcfile/&gt;
   &lt;arg value=&quot;arg2&quot;/&gt;
   &lt;fileset dir=&quot;/tmp&quot;/&gt;
 &lt;/apply&gt;
-</pre></blockquote>
-<p>invokes <code>somecommand arg1 SOURCEFILENAME arg2</code> for each
-file in <code>/tmp</code> replacing SOURCEFILENAME with the absolute
-filename of each file in turn. If <code>parallel</code> had been set
-to true, SOURCEFILENAME would be replaced with the absolute filenames
-of all files separated by spaces.</p>
-<blockquote><pre>
+</pre>
+
+<p>Invoke <kbd>cc -c -o TARGETFILE SOURCEFILE</kbd> for each <samp>.c</samp> file that is newer than
+the corresponding <samp>.o</samp>, replacing <code>TARGETFILE</code> with the absolute filename of
+the <samp>.o</samp> and <code>SOURCEFILE</code> with the absolute name of the <samp>.c</samp>
+file.</p>
+<pre>
 &lt;apply executable=&quot;cc&quot; dest=&quot;src/C&quot; parallel=&quot;false&quot;&gt;
   &lt;arg value=&quot;-c&quot;/&gt;
   &lt;arg value=&quot;-o&quot;/&gt;
@@ -436,14 +410,17 @@
   &lt;srcfile/&gt;
   &lt;fileset dir=&quot;src/C&quot; includes=&quot;*.c&quot;/&gt;
   &lt;mapper type=&quot;glob&quot; from=&quot;*.c&quot; to=&quot;*.o&quot;/&gt;
-&lt;/apply&gt;
-</pre></blockquote>
-<p>invokes <code>cc -c -o TARGETFILE SOURCEFILE</code> for each
-<code>.c</code> file that is newer than the corresponding
-<code>.o</code>, replacing TARGETFILE with the absolute filename of
-the <code>.o</code> and SOURCEFILE with the absolute name of the
-<code>.c</code> file.</p>
-<blockquote><pre>
+&lt;/apply&gt;</pre>
+
+<p>Apply the fictitious <kbd>processfile</kbd> executable to all files matching <samp>*.file</samp>
+in the <samp>src</samp> directory.  The <samp>out</samp> <code>&lt;mapper&gt;</code> has been set up
+to map <samp>*.file</samp> to <samp>*.out</samp>, then this <code>&lt;mapper&gt;</code> is used to
+specify <code>targetfile</code>s for this <code>&lt;apply&gt;</code> task.  A reference
+to <samp>out</samp> is then used as an <code>&lt;outputmapper&gt;</code> nested in
+a <code>&lt;redirector&gt;</code>, which in turn is nested beneath this <code>&lt;apply&gt;</code>
+instance.  This allows us to perform dependency checking against output files&mdash;the target files
+in this case.</p>
+<pre>
 &lt;mapper id=&quot;out&quot; type=&quot;glob&quot;
            from=&quot;src${file.separator}*.file&quot;
            to=&quot;dest${file.separator}*.out&quot;/&gt;
@@ -454,30 +431,23 @@
   &lt;redirector&gt;
     &lt;outputmapper refid=&quot;out&quot;/&gt;
   &lt;/redirector&gt;
-&lt;/apply&gt;
-</pre></blockquote>
-Applies the fictitious &quot;processfile&quot; executable to all
-files matching <code>*.file</code> in the <code>src</code> directory.
-The <code>out</code> <code>&lt;mapper&gt;</code> has been set up to map
-<code>*.file</code> to <code>*.out</code>, then this <code>&lt;mapper&gt;</code>
-is used to specify <code>targetfile</code>s for this &lt;apply&gt;
-task.  A reference to <code>out</code> is then used as an
-<code>&lt;outputmapper&gt;</code> nested in a <code>&lt;redirector&gt;</code>, which in turn is
-nested beneath this <code>&lt;apply&gt;</code> instance.  This allows us to perform
-dependency checking against output files--the target files in this case.
-<blockquote><pre>
+&lt;/apply&gt;</pre>
+
+<p>Apply the <kbd>ls</kbd> executable to all directories in the <code>PATH</code>, effectively
+listing all executables that are available on the <code>PATH</code>.</p>
+<pre>
 &lt;apply executable="ls" parallel="true"
        force="true" dest="${basedir}" append="true" type="both"&gt;
   &lt;path&gt;
     &lt;pathelement path="${env.PATH}"/&gt;
   &lt;/path&gt;
   &lt;identitymapper/&gt;
-&lt;/apply&gt;
-</pre></blockquote>
-Applies the "ls" executable to all directories in the PATH, effectively
-listing all executables that are available on the PATH.
+&lt;/apply&gt;</pre>
 
-<blockquote><pre>
+<p>Convert all JavaScript files in the <samp>src</samp> directory using the command <kbd>jsmin &lt;
+src/a.js &gt; dest/a.js</kbd>. Because the filename itself should not be passed to
+the <code>jsmin</code> program, the <var>addsourcefile</var> is set to <q>false</q>.</p>
+<pre>
 &lt;apply executable="jsmin" addsourcefile="false"&gt;
     &lt;!-- Collect the JS-files --&gt;
     &lt;fileset dir="src" includes="*.js"/&gt;
@@ -488,17 +458,7 @@
         &lt;!-- redirect STDOUT to file in dest-dir --&gt;
         &lt;outputmapper id="out" type="glob" from="*.js" to="dest/*.js"/&gt;
     &lt;/redirector&gt;
-&lt;/apply&gt;
-</pre></blockquote>
-Conversion of the command <code>jsmin &lt; src/a.js &gt; dest/a.js</code> but for
-all files in the src-directory. Because the filename itself should not be passed
-to the <code>jsmin</code> program, the <code>addsourcefile</code> is set to
-<code>false</code>.
-
-
-
-
-
+&lt;/apply&gt;</pre>
 
 </body>
 </html>
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..abf0aac 100644
--- a/manual/Tasks/attrib.html
+++ b/manual/Tasks/attrib.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,34 +15,31 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Apache Ant User Manual</title>
 </head>
 
 <body>
 
-<h2><a name="attrib">Attrib</a></h2>
-<p><em>Since Apache Ant 1.6.</em></p>
+<h2 id="attrib">Attrib</h2>
+<p><em>Since Apache Ant 1.6</em>.</p>
 <h3>Description</h3>
 
-<p>Changes the attributes of a file or all files inside specified
-directories.  Right now it has effect only under Windows. Each of the
-4 possible permissions has its own attribute, matching the arguments
-for the attrib command.</p>
+<p>Changes the attributes of a file or all files inside specified directories.  Right now it has
+effect only under Windows. Each of the 4 possible permissions has its own attribute, matching the
+arguments for the attrib command.</p>
 
-<p><a href="../Types/fileset.html">FileSet</a>s, 
-<a href="../Types/dirset.html">DirSet</a>s or <a
-href="../Types/filelist.html">FileList</a>s can be specified using
-nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and 
-<code>&lt;filelist&gt;</code> elements.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s, <a href="../Types/dirset.html">DirSet</a>s
+or <a href="../Types/filelist.html">FileList</a>s can be specified using
+nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and <code>&lt;filelist&gt;</code>
+elements.</p>
 
-<p>Starting with Ant 1.7, this task supports arbitrary <a
-href="../Types/resources.html#collection">Resource Collection</a>s
-as nested elements.</p>
+<p><em>Since Ant 1.7</em>, this task supports
+arbitrary <a href="../Types/resources.html#collection">resource collections</a> as nested
+elements.</p>
 
 <!--p>By default this task will use a single invocation of the underlying
 attrib command.  If you are working on a large number of files this
@@ -51,117 +49,104 @@
 use highly depends on the length of your file names (the depth of your
 directory tree), so you'll have to experiment a little.</p-->
 
-<p>By default this task won't do anything unless it detects it is
-  running on a Windows system.  If you know for sure that you have a
-  "attrib" executable on your PATH that is command line compatible with
-  the Windows command, you can use the task's os attribute and set its
-  value to your current os.</p>
+<p>By default this task won't do anything unless it detects it is running on a Windows system.  If
+you know for sure that you have a <code>attrib</code> executable on your <code>PATH</code> that is
+command line compatible with the Windows command, you can use the task's <var>os</var> 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">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file or directory of which the permissions must be
-    changed.</td>
-    <td valign="top" valign="middle">Yes or nested
-    <code>&lt;fileset/list&gt;</code> elements.</td>
+    <td>file</td>
+    <td>the file or directory of which the permissions must be changed.</td>
+    <td>Yes, or nested <code>&lt;fileset/list&gt;</code> elements</td>
   </tr>
   <tr>
-    <td valign="top">readonly</td>
-    <td valign="top">the readonly permission.</td>
-    <td valign="top" rowspan="4">at least one of the four. </td>
+    <td>readonly</td>
+    <td>the readonly permission.</td>
+    <td rowspan="4">At least one of the four</td>
   </tr>
   <tr>
-    <td valign="top">archive</td>
-    <td valign="top">the archive permission.</td>
+    <td>archive</td>
+    <td class="left">the archive permission.</td>
   </tr>
   <tr>
-    <td valign="top">system</td>
-    <td valign="top">the system permission.</td>
+    <td>system</td>
+    <td class="left">the system permission.</td>
   </tr>
   <tr>
-    <td valign="top">hidden</td>
-    <td valign="top">the hidden permission.</td>
+    <td>hidden</td>
+    <td class="left">the hidden permission.</td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">One of <i>file</i>, <i>dir</i> or <i>both</i>. If set to
-      <i>file</i>, only the permissions of plain files are going to be changed.
-      If set to <i>dir</i>, only the directories are considered.<br>
-      <strong>Note:</strong> The type attribute does not apply to
-      nested <i>dirset</i>s - <i>dirset</i>s always implicitly
-      assume type to be <i>dir</i>.</td>
-    <td align="center" valign="top">No, default is <i>file</i></td>
+    <td>type</td>
+    <td>One of <q>file</q>, <q>dir</q> or <q>both</q>. If set to <q>file</q>, only the permissions
+      of plain files are going to be changed.  If set to <q>dir</q>, only the directories are
+      considered.<br/>
+      <strong>Note</strong>: The type attribute does not apply to
+      nested <code>dirset</code>s&mdash;<code>dirset</code>s always implicitly assume type to
+      be <q>dir</q>.</td>
+    <td>No; default is <q>file</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to print a summary after execution or not.
-      Defaults to <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>verbose</td>
+    <td>Whether to print a summary after execution or not.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <!--tr>
-    <td valign="top">parallel</td>
-    <td valign="top">process all specified files using a single
-      <code>chmod</code> command. Defaults to true.</td>
-    <td valign="top" align="center">No</td>
+    <td>parallel</td>
+    <td>process all specified files using a single
+      <kbd>chmod</kbd> command.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">maxparallel</td>
-    <td valign="top">Limit the amount of parallelism by passing at
-      most this many sourcefiles at once.  Set it to &lt;= 0 for
-      unlimited.  Defaults to unlimited.  <em>Since Ant 1.6.</em></td>
-    <td align="center" valign="top">No</td>
+    <td>maxparallel</td>
+    <td>Limit the amount of parallelism by passing at
+      most this many sourcefiles at once.  Set it to negative integer for
+      unlimited.  <em>Since Ant 1.6</em>.</td>
+    <td>No, defaults to unlimited</td>
   </tr-->
   <tr>
-    <td valign="top">os</td>
-    <td valign="top">list of Operating Systems on which the command may be
-      executed.</td>
-    <td align="center" valign="top">No</td>
+    <td>os</td>
+    <td>list of Operating Systems on which the command may be executed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">osfamily</td>
-    <td valign="top">OS family as used in
-      the <a href="../Tasks/conditions.html#os">&lt;os&gt;</a>
+    <td>osfamily</td>
+    <td>OS family as used in the <a href="../Tasks/conditions.html#os">&lt;os&gt;</a>
       condition.</td>
-    <td align="center" valign="top">No - defaults to "windows"</td>
+    <td>No; defaults to <q>windows</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-  <blockquote>
+
+<p>Make the <code>run.bat</code> file read-only and hidden.</p>
 <pre>&lt;attrib file=&quot;${dist}/run.bat&quot; readonly=&quot;true&quot; hidden=&quot;true&quot;/&gt;</pre>
-</blockquote>
-<p>makes the &quot;run.bat&quot; file read-only and hidden.</p>
 
-<blockquote>
-  <pre>&lt;attrib readonly=&quot;false&quot;&gt;
+<p>Make all <samp>.xml</samp> files below <samp>${meta.inf}</samp> readable.</p>
+<pre>&lt;attrib readonly=&quot;false&quot;&gt;
   &lt;fileset dir=&quot;${meta.inf}&quot; includes=&quot;**/*.xml&quot;/&gt;
-&lt;/attrib&gt;
-</pre>
-</blockquote>
-<p>makes all &quot;.xml&quot; files below <code>${meta.inf}</code> readable.</p>
+&lt;/attrib&gt;</pre>
 
-<blockquote>
-  <pre>
+<p>Make all files below <samp>shared/sources1</samp> (except those below any directory
+named <samp>trial</samp>) read-only and archived. In addition all files belonging to a FileSet
+with <var>id</var> <samp>other.shared.sources</samp> get the same attributes.</p>
+<pre>
 &lt;attrib readonly=&quot;true&quot; archive=&quot;true&quot;&gt;
   &lt;fileset dir=&quot;shared/sources1&quot;&gt;
     &lt;exclude name=&quot;**/trial/**&quot;/&gt;
   &lt;/fileset&gt;
   &lt;fileset refid=&quot;other.shared.sources&quot;/&gt;
-&lt;/attrib&gt;
-</pre>
-</blockquote>
-<p>makes all files below <code>shared/sources1</code> (except those below any
-  directory named trial) read-only and archived. In addition all files belonging
-  to a FileSet with <code>id</code> <code>other.shared.sources</code> get the
-  same attributes.</p>
-
+&lt;/attrib&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/augment.html b/manual/Tasks/augment.html
index 305e39a..b934c75 100644
--- a/manual/Tasks/augment.html
+++ b/manual/Tasks/augment.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Augment Task</title>
 </head>
@@ -25,59 +25,51 @@
 <body>
 
 <h2>Augment</h2>
-
+<p><em>Since Apache Ant 1.8.1</em></p>
 <h3>Description</h3>
-<p>Modify an existing reference by adding nested elements or (re-)assigning properties
-mapped as XML attributes. This is an unusual task that makes use of Ant's internal
-processing mechanisms to reload a previously declared reference by means of the 'id'
-attribute, then treats the declared <code>augment</code> element as though it were the
-original element.
-<b>Since Apache Ant 1.8.1</b></p>
+<p>Modify an existing reference by adding nested elements or (re-)assigning properties mapped as XML
+attributes. This is an unusual task that makes use of Ant's internal processing mechanisms to reload
+a previously declared reference by means of the <var>id</var> attribute, then treats the
+declared <code>augment</code> element as though it were the original element.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">id</td>
-    <td valign="top">The id of the reference to augment. If no such reference has
-      been declared a <code>BuildException</code> is generated.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>id</td>
+    <td>The <var>id</var> of the reference to augment. If no such reference has been declared
+      a <code>BuildException</code> is thrown.</td>
+    <td>Yes</td>
   </tr>
 </table>
-<p>
-Additional permissible attributes are dependent on the reference to be modified.
-</p>
+<p>Additional permissible attributes are dependent on the reference to be modified.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
-<p>
-Permissible nested elements are dependent on the reference to be modified.
-</p>
+<p>Permissible nested elements are dependent on the reference to be modified.</p>
 
 <h3>Examples</h3>
 
-Given
-<pre>
-  &lt;fileset id="input-fs" dir="${basedir}" /&gt;
-</pre>
+<p>Given</p>
+
+<pre>&lt;fileset id="input-fs" dir="${basedir}"/&gt;</pre>
+
+<p>invocation</p>
+
+<pre>&lt;augment id="input-fs" excludes="foo"/&gt;</pre>
+
+<p>modifies the <var>excludes</var> attribute of <samp>input-fs</samp>, whereas</p>
 
 <pre>
-  &lt;augment id="input-fs" excludes="foo" /&gt;
-</pre>
+&lt;augment id="input-fs"&gt;
+  &lt;filename name="bar"/&gt;
+&lt;/augment&gt;</pre>
 
-<p>Modifies the <code>excludes</code> attribute of <code>input-fs</code>.</p>
-
-<pre>
-  &lt;augment id="input-fs"&gt;
-    &lt;filename name="bar" /&gt;
-  &lt;/augment&gt;
-</pre>
-
-<p>Adds a <code>filename</code> selector to <code>input-fs</code>.</p>
+<p>adds a <code>filename</code> selector to <samp>input-fs</samp>.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/available.html b/manual/Tasks/available.html
index 6e4a171..7b246e0 100644
--- a/manual/Tasks/available.html
+++ b/manual/Tasks/available.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,147 +15,140 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Available Task</title>
 </head>
 
 <body>
 
-<h2><a name="available">Available</a></h2>
+<h2 id="available">Available</h2>
 <h3>Description</h3>
-<p>Sets a property if a resource is available at runtime. This resource can be a
-file, a directory, a class in the classpath, or a JVM system resource.</p>
-<p>If the resource is present, the property value is set to true by
-default; otherwise, the property is not set. You can set the value to
-something other than the default by specifying the <code>value</code> attribute.</p>
-<p>Normally, this task is used to set properties that are useful to avoid target
-execution depending on system parameters.</p>
+<p>Sets a property if a resource is available at run time. This resource can be a file, a directory,
+a class in the classpath, or a JVM system resource.</p>
+<p><strong>Note</strong>: a class is available in the classpath when it can be loaded; i.e., all
+classes it depends on must be in the classpath, too.</p>
+<p>If the resource is present, the property value is set to <q>true</q> by default; otherwise, the
+property is not set. You can set the value to something other than the default by specifying
+the <var>value</var> attribute.</p>
+<p>Normally, this task is used to set properties that are useful to avoid target execution depending
+on system parameters.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to set.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of the property to set.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The value to set the property to. Defaults to &quot;true&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>value</td>
+    <td>The value to set the property to.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">The class to look for in the classpath.</td>
-    <td valign="middle" align="center" rowspan="3">Yes</td>
+    <td>classname</td>
+    <td>The class to look for in the classpath.</td>
+    <td rowspan="3">Exactly one of the three</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to look for.</td>
+    <td>file</td>
+    <td class="left">The file to look for.</td>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top">The resource to look for in the JVM.</td>
+    <td>resource</td>
+    <td class="left">The resource to look for in the JVM.</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to use when looking up <code>classname</code> or <code>resource</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>The classpath to use when looking up <var>classname</var> or <var>resource</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">filepath</td>
-    <td valign="top">The path to use when looking up <code>file</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>filepath</td>
+    <td>The path to use when looking up <var>file</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use, given as a <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a path
+    defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">The type of <code>file</code> to look for, either a directory (<code>type=&quot;dir&quot;</code>) or a file
-      (<code>type=&quot;file&quot;</code>). If not set, the property will be set if the name specified in the <code>file</code>
-      attribute exists as either a file or a directory.</td>
-    <td align="center" valign="top">No</td>
+    <td>type</td>
+    <td>The type of <var>file</var> to look for, either a directory (<var>type</var>=<q>dir</q>) or
+    a file (<var>type</var>=<q>file</q>). If not set, the property will be set if the name specified
+    in the <var>file</var> attribute exists as either a file or a directory.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">ignoresystemclasses</td>
-    <td valign="top">Ignore Ant's runtime classes, using only the specified
-      classpath.  Only affects the "classname" attribute.  Defaults to &quot;false&quot;</td>
-    <td align="center" valign="top">No</td>
+    <td>ignoresystemclasses</td>
+    <td>Ignore Ant's runtime classes, using only the specified classpath.  Only affects
+    the <var>classname</var> attribute.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">searchparents</td>
-    <td valign="top">This contains the behaviour of the "file" type.
-      If true, the available task will, when
-      searching for a file, search not only the directories specified but
-      will also search the parent directories of those
-      specified.
-      If false, only the directories specified will be searched.
-      Defaults to "false".
-      <em>Since Ant 1.7</em>
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>searchparents</td>
+    <td>This contains the behaviour of the <q>file</q> <var>type</var>.  If <q>true</q>, the task
+    will, when searching for a file, search not only the directories specified but will also search
+    the parent directories of those specified.  If <q>false</q>, only the directories specified will
+    be searched.  <em>Since Ant 1.7</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>classpath</h4>
-<p><code>Available</code>'s <code>classpath</code> attribute is a <a
-href="../using.html#path">path-like structure</a> and can also be set via a nested
+<p><code>Available</code>'s <var>classpath</var> attribute is
+a <a href="../using.html#path">path-like structure</a> and can also be set via a nested
 <code>&lt;classpath&gt;</code> element.</p>
 <h4>filepath</h4>
-<p><code>Available</code>'s <code>filepath</code> attribute is a <a
-href="../using.html#path">path-like structure</a> and can also be set via a nested
-<code>&lt;filepath&gt;</code> element.</p>
+<p><code>Available</code>'s <var>filepath</var> attribute is
+a <a href="../using.html#path">path-like structure</a> and can also be set via a
+nested <code>&lt;filepath&gt;</code> element.</p>
+
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;available classname=&quot;org.whatever.Myclass&quot; property=&quot;Myclass.present&quot;/&gt;
-</pre></blockquote>
-<p>sets the <code>Myclass.present</code> property to the value &quot;true&quot;
-if the class <code>org.whatever.Myclass</code> is found in Ant's classpath.</p>
-<blockquote><pre>
+<p>Set the <code>Myclass.present</code> property to the value <q>true</q> if the
+class <code>org.whatever.Myclass</code> is found in Ant's classpath.</p>
+<pre>&lt;available classname=&quot;org.whatever.Myclass&quot; property=&quot;Myclass.present&quot;/&gt;</pre>
+
+<p>Set the <code>jaxp.jar.present</code> property to the value <q>true</q> if the
+file <samp>./lib/jaxp11/jaxp.jar</samp> is found.</p>
+<pre>
 &lt;property name=&quot;jaxp.jar&quot; value=&quot;./lib/jaxp11/jaxp.jar&quot;/&gt;
-&lt;available file=&quot;${jaxp.jar}&quot; property=&quot;jaxp.jar.present&quot;/&gt;
-</pre></blockquote>
-<p>sets the <code>jaxp.jar.present</code> property to the value &quot;true&quot;
-if the file <code>./lib/jaxp11/jaxp.jar</code> is found.</p>
-<blockquote><pre>
+&lt;available file=&quot;${jaxp.jar}&quot; property=&quot;jaxp.jar.present&quot;/&gt;</pre>
+
+<p>Set the <code>local.lib.present</code> property to the value <q>true</q> if the
+directory <samp>/usr/local/lib</samp> is found.</p>
+<pre>
 &lt;available file=&quot;/usr/local/lib&quot; type=&quot;dir&quot;
-           property=&quot;local.lib.present&quot;/&gt;
-</pre></blockquote>
-<p>sets the <code>local.lib.present</code> property to the value &quot;true&quot;
-if the directory <code>/usr/local/lib</code> is found.</p>
-<blockquote><pre>
+           property=&quot;local.lib.present&quot;/&gt;</pre>
+
+<p>Set the <code>jaxp11.present</code> property to the value <q>true</q> if the
+class <code>javax.xml.transform.Transformer</code> is found in the classpath referenced
+by <samp>jaxp</samp> (in this case, <samp>./lib/jaxp11/jaxp.jar</samp>).</p>
+<pre>
 ...in project ...
 &lt;property name=&quot;jaxp.jar&quot; value=&quot;./lib/jaxp11/jaxp.jar&quot;/&gt;
 &lt;path id=&quot;jaxp&quot; location=&quot;${jaxp.jar}&quot;/&gt;
 ...in target ...
 &lt;available classname=&quot;javax.xml.transform.Transformer&quot;
-           classpathref=&quot;jaxp&quot; property=&quot;jaxp11.present&quot;/&gt;
-</pre></blockquote>
-<p>sets the <code>jaxp11.present</code> property to the value &quot;true&quot;
-if the class <code>javax.xml.transform.Transformer</code> is found in the classpath referenced by <code>jaxp</code> (in this case, <code>./lib/jaxp11/jaxp.jar</code>).
-</p>
-<blockquote><pre>
+           classpathref=&quot;jaxp&quot; property=&quot;jaxp11.present&quot;/&gt;</pre>
+
+<p>Set the <code>have.extras</code> property to the value <q>true</q> if the resource
+file <samp>extratasks.properties</samp> is found.</p>
+<pre>
 &lt;available property=&quot;have.extras&quot; resource=&quot;extratasks.properties&quot;&gt;
   &lt;classpath&gt;
-    &lt;pathelement location=&quot;/usr/local/ant/extra.jar&quot; /&gt;
-&nbsp;&nbsp;&lt;/classpath&gt;
-&lt;/available&gt;
-</pre></blockquote>
-<p>sets the <code>have.extras</code> property to the value &quot;true&quot;
-if the resource-file <code>extratasks.properties</code> is found.
-</p>
-
+    &lt;pathelement location=&quot;/usr/local/ant/extra.jar&quot;/&gt;
+  &lt;/classpath&gt;
+&lt;/available&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/basename.html b/manual/Tasks/basename.html
index 0822d8f..ac5a2d3 100644
--- a/manual/Tasks/basename.html
+++ b/manual/Tasks/basename.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,79 +15,66 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Basename Task</title>
 </head>
 
 <body>
 
-<h2><a name="echo">Basename</a></h2>
+<h2 id="echo">Basename</h2>
+
 <h3>Description</h3>
-<p>
-Task to determine the basename of a specified file, optionally minus a
-specified suffix.
-</p>
-<p>
-When this task executes, it will set the specified property to the
-value of the last path element of the specified file. If <code>file</code> is a
-directory, the basename will be the last directory element. If
-<code>file</code> is a full-path, relative-path, or simple filename,
-the basename will be the simple file name, without any directory elements.
-</p>
-<p> 
+<p>Task to determine the basename of a specified file, optionally minus a specified suffix.</p>
+<p>When this task executes, it will set the specified property to the value of the last path element
+of the specified file. If <var>file</var> is a directory, the basename will be the last directory
+element. If <var>file</var> is a full-path, relative-path, or simple filename, the basename will be
+the simple file name, without any directory elements.</p>
+
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The path to take the basename of.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>file</td>
+    <td>The path to take the basename of.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to set.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of the property to set.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">The suffix to remove from the resulting basename
-      (specified either with or without the &quot;<code>.</code>&quot;).</td>
-    <td valign="top" align="center">No</td>
+    <td>suffix</td>
+    <td>The suffix to remove from the resulting basename (specified either with or without
+    the <q>.</q>).</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;basename property=&quot;jar.filename&quot; file=&quot;${lib.jarfile}&quot;/&gt;
-</pre></blockquote>
-will set <code>jar.filename</code> to
-<code>myjar.jar</code>, if <code>lib.jarfile</code> is defined as either a
-full-path filename (eg., <code>/usr/local/lib/myjar.jar</code>),
-a relative-path filename (eg., <code>lib/myjar.jar</code>),
-or a simple filename (eg., <code>myjar.jar</code>).
-<blockquote><pre>
+<p>Set <code>jar.filename</code> to <samp>myjar.jar</samp>, if <code>lib.jarfile</code> is defined
+as either a full-path filename (eg., <samp>/usr/local/lib/myjar.jar</samp>), a relative-path
+filename (eg., <samp>lib/myjar.jar</samp>), or a simple filename (eg., <samp>myjar.jar</samp>).</p>
+<pre>&lt;basename property=&quot;jar.filename&quot; file=&quot;${lib.jarfile}&quot;/&gt;</pre>
+
+<p>Set <code>cmdname</code> to <samp>foo</samp>.</p>
+<pre>
 &lt;basename property=&quot;cmdname&quot; file=&quot;D:/usr/local/foo.exe&quot;
-          suffix=&quot;.exe&quot;/&gt;
-</pre></blockquote>
-will set <code>cmdname</code> to <code>foo</code>.
-<blockquote><pre>
+          suffix=&quot;.exe&quot;/&gt;</pre>
+
+<p>Set <code>temp.dirname</code> to the last directory element of the path defined for
+the <code>TEMP</code> environment variable.</p>
+<pre>
 &lt;property environment=&quot;env&quot;/&gt;
 &lt;basename property=&quot;temp.dirname&quot; file=&quot;${env.TEMP}&quot;/&gt;
-</pre></blockquote>
-
-will set <code>temp.dirname</code> to the last directory element of
-the path defined for the <code>TEMP</code> environment variable.</p>
-
-
+</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/bindtargets.html b/manual/Tasks/bindtargets.html
index d8374a4..f138f75 100644
--- a/manual/Tasks/bindtargets.html
+++ b/manual/Tasks/bindtargets.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,79 +15,68 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Bindtargets Task</title>
 </head>
 
 <body>
 
-<h2><a name="ant">Bindtargets</a></h2>
+<h2 id="ant">Bindtargets</h2>
+<p><em>Since Apache Ant 1.8.2</em></p>
 <h3>Description</h3>
 
-<p>Make some target the extension of some defined
-<a href="../targets.html#extension-points">extension point</a>. It will make the
-list of targets dependencies of the extension point.</p>
+<p>Make some target the extension of some
+defined <a href="../targets.html#extension-points">extension point</a>. It will make the list of
+targets dependencies of the extension point.</p>
 
-<p>This target is useful when you want to have a target participate to another
-build workflow, build workflow which explicitly expose an extension point for
-that kind of insertion. But the target to bind and the extension point to
-bind to are both declared in some imported build files. Modifying directly the
-target dependency graph of these external build files may have a side effect
-on some other project which import them. This task helps then to modify the
-target dependencies but only in your context.
-</p>
+<p>This target is useful when you want to have a target to participate in another build workflow
+which explicitly exposes an extension point for that kind of insertion. Thus the target to bind and
+the extension point to bind to are both declared in some imported build files. But directly
+modifying the target dependency graph of these external build files may have a side effect on some
+other project which imports them. This task helps to modify the target dependencies but only in your
+context.</p>
 
-<p>Note: this task is quite equivalent to the definition of an intermediate
-target which will be the bridge between the target to bind and the extension
-point. For instance:
-</p>
-<blockquote><pre>&lt;bindtargets targets="jar,javadoc" extensionPoint="dist" /&gt;</pre></blockquote>
-is quite equivalent to:
-<blockquote><pre>&lt;target name="bind-to-dist" depends="jar,javadoc" extensionOf="dist" /&gt;</pre></blockquote>
-<p>
-This task basically avoid the creation of a target.
-</p>
+<p><strong>Note</strong>: this task is quite equivalent to the definition of an intermediate target
+which will be the bridge between the target to bind and the extension point. For instance:</p>
+<pre>&lt;bindtargets targets="jar,javadoc" extensionPoint="dist"/&gt;</pre>
+<p>is quite equivalent to:</p>
+<pre>&lt;target name="bind-to-dist" depends="jar,javadoc" extensionOf="dist"/&gt;</pre>
+<p>This task basically avoids the creation of a target.</p>
 
-<p>The bindtargets task may only be used as a top-level task. This means that
-it may not be used in a target. This is making the target dependency graph static
-and predictable as soon as every build file is loaded.</p>
-
-<p><b>Since Apache Ant 1.8.2</b></p>
+<p>The <code>bindtargets</code> task may only be used as a top-level task. This means that it may
+not be used in a target. This is making the target dependency graph static and predictable as soon
+as every build file is loaded.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">targets</td>
-    <td valign="top">a comma separated list of target names to bind.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>targets</td>
+    <td>a comma separated list of target names to bind.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">extensionPoint</td>
-    <td valign="top">the name of the extension point to bind the targets to.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>extensionPoint</td>
+    <td>the name of the extension point to bind the targets to.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">onMissingExtensionPoint</td>
-    <td valign="top">What to do if this target tries to extend a missing
-        <a href="../targets.html#extension-points">extension-point</a>. ("fail",
-        "warn", "ignore").</td>
-    <td valign="top" align="center">No. Defaults to <code>fail</code></td>
+    <td>onMissingExtensionPoint</td>
+    <td>What to do if this target tries to extend a
+    missing <a href="../targets.html#extension-points">extension-point</a>: <q>fail</q>, <q>warn</q>, <q>ignore</q>.</td>
+    <td>No; defaults to <q>fail</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;bindtargets targets=&quot;build-jar,build-src-jar&quot; extensionPoint=&quot;dist&quot; /&gt;
-</pre></blockquote>
+<pre>&lt;bindtargets targets=&quot;build-jar,build-src-jar&quot; extensionPoint=&quot;dist&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/buildnumber.html b/manual/Tasks/buildnumber.html
index aaaa14c..c13b48d 100644
--- a/manual/Tasks/buildnumber.html
+++ b/manual/Tasks/buildnumber.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,61 +15,44 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>BuildNumber Task</title>
 </head>
 
 <body>
 
-<h2><a name="buildnumber">BuildNumber</a></h2>
+<h2 id="buildnumber">BuildNumber</h2>
 <h3>Description</h3>
 <p>This is a basic task that can be used to track build numbers.</p>
-<p>It will first attempt to read a build number from a file (by default,
-<code>build.number</code> in the current directory), then
-set the property <code>build.number</code> to the value that was read in
-(or to <code>0</code>, if no such value). It will then increment the
-number by one and write it back out to the file.
-(See the
-<a href="../Tasks/propertyfile.html">PropertyFile</a> task
-if you need finer control over things such as the property name or
-the number format.)
-</p>
+<p>It will first attempt to read a build number from a file (by default, <samp>build.number</samp>
+in the current directory), then set the property <code>build.number</code> to the value that was
+read in (or to <q>0</q>, if no such value). It will then increment the number by one and write it
+back out to the file.  (See the <a href="../Tasks/propertyfile.html">PropertyFile</a> task if you
+need finer control over things such as the property name or the number format.)</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to read and write the build number from/to.</td>
-    <td align="center" valign="top">No; defaults to &quot;build.number&quot;</td>
+    <td>file</td>
+    <td>The file to read and write the build number from/to.</td>
+    <td>No; defaults to <q>build.number</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;buildnumber/&gt;
-</pre></blockquote>
+<p>Read, increment, and write a build number to the default file, <samp>build.number</samp>.</p>
+<pre>&lt;buildnumber/&gt;</pre>
 
-<p>Read, increment, and write a build number to the default file,
-<code>build.number</code>.</p>
-
-<blockquote><pre>
-&lt;buildnumber file=&quot;mybuild.number&quot;/&gt;
-</pre></blockquote>
-
-<p>Read, increment, and write a build number to the file
-<code>mybuild.number</code>.</p>
-
-
+<p>Read, increment, and write a build number to the file <samp>mybuild.number</samp>.</p>
+<pre>&lt;buildnumber file=&quot;mybuild.number&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/cab.html b/manual/Tasks/cab.html
index 42312f5..a773b04 100644
--- a/manual/Tasks/cab.html
+++ b/manual/Tasks/cab.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,158 +15,135 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Cab Task</title>
 </head>
 
 <body>
 
-<h2><a name="cab">Cab</a></h2>
+<h2 id="cab">Cab</h2>
 <h3>Description</h3>
-<p>The cab task creates Microsoft cab archive files.  It is invoked
-similar to the <a href="../Tasks/jar.html">jar</a> or <a href="../Tasks/zip.html">zip</a> tasks.
-This task will work on Windows using the external cabarc tool (provided by Microsoft)
-which must be located in your executable path.</p>
-<p>To use this task on other platforms you need to download and compile libcabinet from
-<a href="http://trill.cis.fordham.edu/~barbacha/cabinet_library/">
-http://trill.cis.fordham.edu/~barbacha/cabinet_library/</a>.</p>
-<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based
-tasks</a>, on how the inclusion/exclusion of files works, and how to
-write patterns.</p>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>basedir</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
+<p>The cab task creates Microsoft cabinet archive files.  It is invoked similar to
+the <a href="../Tasks/jar.html">jar</a> or <a href="../Tasks/zip.html">zip</a> tasks.  This task
+will work on Windows using the external <kbd>cabarc</kbd> tool (provided by Microsoft) which must
+be located in your executable path.</p>
+<p>To use this task on other platforms you need to download and compile <code>libcabinet</code>
+from <a href="https://www.freshports.org/archivers/libcabinet/"
+target="_top">https://www.freshports.org/archivers/libcabinet/</a>.</p>
+<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on
+how the inclusion/exclusion of files works, and how to write patterns.</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>basedir</var>) as well as
+the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
 
 <p>On non-Unix platforms this task writes the list of files to archive
   to the <a href="../running.html#tmpdir">temporary directory</a>.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">cabfile</td>
-    <td valign="top">the name of the cab file to create.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>cabfile</td>
+    <td>the name of the cab file to create.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the directory to start archiving files from.</td>
-    <td valign="top" align="center">No</td>
+    <td>basedir</td>
+    <td>the directory to start archiving files from.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">set to &quot;yes&quot; if you want to see the output from
-      the cabarc tool.  defaults to &quot;no&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>verbose</td>
+    <td>set to <q>yes</q> if you want to see the output from the <code>cabarc</code> tool.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">compress</td>
-    <td valign="top">set to &quot;no&quot; to store files without compressing.
-      defaults to &quot;yes&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>compress</td>
+    <td>set to <q>no</q> to store files without compressing.</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">options</td>
-    <td valign="top">use to set additional command-line options for
-      the cabarc tool.  should not normally be necessary.</td>
-    <td valign="top" align="center">No</td>
+    <td>options</td>
+    <td>set additional command-line options for the <code>cabarc</code> tool.  Should not
+      normally be necessary.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that
-      must be included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that
-      must be excluded. No files (except default excludes) are excluded
-      when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used
-      or not (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>fileset</h4>
 
-<p>The cab task supports one nested <a
-href="../Types/fileset.html"><code>&lt;fileset&gt;</code></a>
-element to specify the files to be included in the archive.
-  If this is specified, the "basedir" attribute cannot be used.
-</p>
+<p>The cab task supports one nested <a href="../Types/fileset.html"><code>&lt;fileset&gt;</code></a>
+element to specify the files to be included in the archive.  If this is specified,
+the <var>basedir</var> attribute cannot be used.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
+<p>Cab all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.cab</samp> in the <samp>${dist}</samp> directory.</p>
+<pre>
+&lt;cab cabfile=&quot;${dist}/manual.cab&quot;
+     basedir=&quot;htdocs/manual&quot;/&gt;</pre>
+
+<p>Cab all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.cab</samp> in the <samp>${dist}</samp> directory. Files in the
+directory <samp>mydocs</samp>, or files with the name <samp>todo.html</samp> are excluded.</p>
+<pre>
 &lt;cab cabfile=&quot;${dist}/manual.cab&quot;
      basedir=&quot;htdocs/manual&quot;
-  /&gt;
-</pre></blockquote>
-<p>cabs all files in the htdocs/manual directory into a file called
-manual.cab in the ${dist} directory.</p>
-<blockquote><pre>
-&lt;cab cabfile=&quot;${dist}/manual.cab&quot;
-     basedir=&quot;htdocs/manual&quot;
-     excludes=&quot;mydocs/**, **/todo.html&quot;
-  /&gt;
-</pre></blockquote>
-<p>cabs all files in the htdocs/manual directory into a file called
-manual.cab in the ${dist} directory. Files in the directory mydocs,
-or files with the name todo.html are excluded.</p>
-<blockquote><pre>
+     excludes=&quot;mydocs/**, **/todo.html&quot;/&gt;</pre>
+
+<p>Cab all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.cab</samp> in the <samp>${dist}</samp> directory. Only <samp>.html</samp> files
+under the directory <samp>api</samp> are archived, and files with the name <samp>todo.html</samp>
+are excluded. Output from the <kbd>cabarc</kbd> tool is displayed in the build output.</p>
+<pre>
 &lt;cab cabfile=&quot;${dist}/manual.cab&quot;
      basedir=&quot;htdocs/manual&quot;
      includes=&quot;api/**/*.html&quot;
      excludes=&quot;**/todo.html&quot;
-     verbose=&quot;yes&quot;
-  /&gt;
-</pre></blockquote>
-<p>Cab all files in the htdocs/manual directory into a file called
-manual.cab in the ${dist} directory. Only html files under the
-directory api are archived, and files with the name todo.html are
-excluded. Output from the cabarc tool is displayed in the build
-output.</p>
+     verbose=&quot;yes&quot;/&gt;</pre>
 
-<blockquote><pre>
+<p>The following is equivalent to the example above.</p>
+<pre>
 &lt;cab cabfile=&quot;${dist}/manual.cab&quot;
      verbose=&quot;yes&quot;&gt;
   &lt;fileset
        dir=&quot;htdocs/manual&quot;
        includes=&quot;api/**/*.html&quot;
-       excludes=&quot;**/todo.html&quot;
-  /&gt;
-&lt;/cab&gt;
-</pre></blockquote>
-<p>is equivalent to the example above.</p>
-
-
+       excludes=&quot;**/todo.html&quot;/&gt;
+&lt;/cab&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/ccm.html b/manual/Tasks/ccm.html
index 9f4725f..c1fcaf8 100644
--- a/manual/Tasks/ccm.html
+++ b/manual/Tasks/ccm.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Continuus Tasks</title>
 </head>
@@ -33,18 +33,22 @@
   <li><a href="#ccmcreatetask">CCMCreateTask</a></li>
 </ul>
 
-<p>These Apache Ant tasks are wrappers around Continuus Source Manager. They have been tested
-  against versions 5.1/6.2 on Windows 2000, but should work on other platforms with ccm installed.</p>
-<hr>
-<h2><a name="ccmcheckin">CCMCheckin</a></h2>
+<p>These Apache Ant tasks are wrappers
+around <a href="https://en.wikipedia.org/wiki/Rational_Synergy" target="_top">Continuus Source
+Manager</a>. They have been tested against versions 5.1/6.2 on Windows 2000, but should work on
+other platforms with <kbd>ccm</kbd> installed.</p>
+
+<hr/>
+
+<h2 id="ccmcheckin">CCMCheckin</h2>
 <h3>Description</h3>
-Task to checkin a file
+<p>Check in a file to Continuus</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0" width="598">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>file</td>
@@ -53,100 +57,97 @@
   </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment. Default is &quot;Checkin&quot; plus the date</td>
-    <td>No</td>
+    <td>Specify a comment.</td>
+    <td>No; default is <q>Checkin</q> plus the date</td>
   </tr>
   <tr>
     <td>task</td>
-    <td>Specify the task number used to check in the file (may use 'default')</td>
+    <td>Specify the task number used to check in the file (may use <q>default</q>)</td>
     <td>No</td>
   </tr>
   <tr>
     <td>ccmdir</td>
-    <td>path to the ccm executable file, required if it is not on the PATH</td>
+    <td>path to the <kbd>ccm</kbd> executable file, required if it is not on
+    the <code>PATH</code></td>
     <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-  <pre>&lt;ccmcheckin file=&quot;c:/wa/com/foo/MyFile.java&quot;
-        comment=&quot;mycomment&quot;/&gt;
-</pre>
-</blockquote>
-<p>Checks in the file <i>c:/wa/com/foo/MyFile.java</i>.
-  Comment attribute <i>mycomment</i> is added as a task comment. The task
-  used is the one set as the default.</p>
-<hr>
-<h2><a name="ccmcheckout">CCMCheckout</a></h2>
+
+<p>Check in the file <samp>c:/wa/com/foo/MyFile.java</samp>.  Text <samp>mycomment</samp> is added
+as a comment. The task used is the one set as the default.</p>
+<pre>
+&lt;ccmcheckin file=&quot;c:/wa/com/foo/MyFile.java&quot;
+            comment=&quot;mycomment&quot;/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccmcheckout">CCMCheckout</h2>
 <h3>Description</h3>
-Task to perform a Checkout command to Continuus
+<p>Run a Continuus checkout command</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0" width="614">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>file</td>
     <td>Path to the file that the command will operate on</td>
-    <td rowspan=2">Yes (file|fileset)</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
     <td>fileset</td>
-    <td>fileset containing the file to be checked out</td>
+    <td class="left">fileset containing the file to be checked out</td>
   </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment.</td>
+    <td>Specify a comment</td>
     <td>No</td>
   </tr>
   <tr>
     <td>task</td>
-    <td>Specify the task number used to checkin the file (may use
-      'default')</td>
+    <td>Specify the task number used to checkin the file (may use <q>default</q>)</td>
     <td>No</td>
   </tr>
   <tr>
     <td>ccmdir</td>
-    <td>path to the ccm executable file, required if it is not on the PATH</td>
+    <td>path to the <kbd>ccm</kbd> executable file, required if it is not on
+    the <code>PATH</code></td>
     <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-  <pre>&lt;ccmcheckout file=&quot;c:/wa/com/foo/MyFile.java&quot;
-        comment=&quot;mycomment&quot;/&gt;
-</pre>
-</blockquote>
-<p>Check out the file <i>c:/wa/com/foo/MyFile.java</i>.
-  Comment attribute <i>mycomment</i> is added as a task comment
-   The used task is the one set as the default.</p>
-<blockquote>
-  <pre>&lt;ccmcheckout  comment=&quot;mycomment&quot;&gt;
+
+<p>Check out the file <samp>c:/wa/com/foo/MyFile.java</samp>.  Comment
+attribute <samp>mycomment</samp> is added as a task comment. The task used is the one set as the
+default.</p>
+<pre>
+&lt;ccmcheckout file=&quot;c:/wa/com/foo/MyFile.java&quot;
+             comment=&quot;mycomment&quot;/&gt;</pre>
+
+<p>Check out all the files in the <samp>lib</samp> directory having the <samp>.jar</samp>
+extension. Comment attribute <samp>mycomment</samp> is added as a task comment The used task is the
+one set as the default.</p>
+<pre>
+&lt;ccmcheckout comment=&quot;mycomment&quot;&gt;
   &lt;fileset dir=&quot;lib&quot; &gt;
     &lt;include name=&quot;**/*.jar&quot;/&gt;
   &lt;/fileset&gt;
-&lt;/ccmcheckout &gt;
-  </pre>
-</blockquote>
+&lt;/ccmcheckout &gt;</pre>
 
-<p>Check out all the files in the <i>lib</i> directory having the <i>.jar</i> extension.
-  Comment attribute <i>mycomment</i> is added as a task comment
-   The used task is the one set as the default.</p>
+<hr/>
 
-
-
-<hr>
-<h2><a name="ccmcheckintask">CCMCheckinTask</a></h2>
+<h2 id="ccmcheckintask">CCMCheckinTask</h2>
 <h3>Description</h3>
-Task to perform a check in default task command to Continuus
+<p>Run a Continuus command to checkin default task</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>comment</td>
@@ -155,41 +156,42 @@
   </tr>
   <tr>
     <td>task</td>
-    <td>Specify the task number used to check in the file (may use 'default')</td>
+    <td>Specify the task number used to check in the file (may use <q>default</q>)</td>
     <td>No</td>
   </tr>
   <tr>
     <td>ccmdir</td>
-    <td >path to the ccm executable file, required if it is not on the PATH</td>
+    <td>path to the <kbd>ccm</kbd> executable file, required if it is not on
+    the <code>PATH</code></td>
     <td>No</td>
   </tr>
 </table>
-<h3>Examples </h3>
-<blockquote>
-  <pre>&lt;ccmcheckintask comment=&quot;blahblah/&gt;
-</pre>
-</blockquote>
-<p>Does a Checkin default task on all the checked out files in the current task.</p>
-<hr>
-<h2><a name="ccmreconfigure">CCMReconfigure</a></h2>
+<h3>Examples</h3>
+
+<p>Perform a Checkin default task on all the checked out files in the current task.</p>
+<pre>&lt;ccmcheckintask comment=&quot;blahblah/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccmreconfigure">CCMReconfigure</h2>
 <h3>Description</h3>
-Task to perform an reconfigure command to Continuus.
+<p>Run a Continuus reconfigure/update command</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>recurse</td>
-    <td>recurse on subproject (default false)</td>
-    <td>No</td>
+    <td>recurse on subproject</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
     <td>verbose</td>
-    <td>do a verbose reconfigure operation (default false)</td>
-    <td>No</td>
+    <td>do a verbose reconfigure operation</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
     <td>ccmproject</td>
@@ -198,32 +200,33 @@
   </tr>
   <tr>
     <td>ccmdir</td>
-    <td >path to the ccm executable file, required if it is not on the PATH</td>
+    <td>path to the <kbd>ccm</kbd> executable file, required if it is not on
+    the <code>PATH</code></td>
     <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
- <pre>&lt;ccmreconfigure ccmproject=&quot;ANTCCM_TEST#BMO_1&quot;
-         verbose=&quot;true&quot;/&gt;
-</pre>
-</blockquote>
-<p>Does a Continuus <i>reconfigure</i> on the project <i>ANTCCM_TEST#BMO_1</i>.
-</p>
-<hr>
-<h2><a name="ccmcreatetask">CCMCreateTask</a></h2>
+
+<p>Perform a Continuus <code>reconfigure</code> on the project <samp>ANTCCM_TEST#BMO_1</samp>.</p>
+<pre>
+&lt;ccmreconfigure ccmproject=&quot;ANTCCM_TEST#BMO_1&quot;
+                verbose=&quot;true&quot;/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccmcreatetask">CCMCreateTask</h2>
 <h3>Description</h3>
-Create a Continuus task.
+<p>Create a Continuus task.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment.</td>
+    <td>Specify a comment</td>
     <td>No</td>
   </tr>
   <tr>
@@ -233,7 +236,8 @@
   </tr>
   <tr>
     <td>ccmdir</td>
-    <td >path to the ccm executable file, required if it is not on the PATH</td>
+    <td>path to the <kbd>ccm</kbd> executable file, required if it is not on
+    the <code>PATH</code></td>
     <td>No</td>
   </tr>
   <tr>
@@ -253,20 +257,17 @@
   </tr>
   <tr>
     <td>task</td>
-    <td>Specify the task number used to checkin the file (may use 'default')</td>
+    <td>Specify the task number used to checkin the file (may use <q>default</q>)</td>
     <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-  <pre>&lt;ccmcreatetask resolver=&quot;${user.name}&quot;
-            release=&quot;ANTCCM_TEST&quot; comment=&quot;blahblah&quot;/&gt;
-</pre>
-</blockquote>
-<p>Creates a task for the release <i>ANTCCM_TEST</i> with the
-  current user as the resolver for this task.</p>
 
+<p>Create a task for the release <samp>ANTCCM_TEST</samp> with the current user as the resolver for
+this task.</p>
+<pre>
+&lt;ccmcreatetask resolver=&quot;${user.name}&quot;
+               release=&quot;ANTCCM_TEST&quot; comment=&quot;blahblah&quot;/&gt;</pre>
 
 </body>
-
 </html>
diff --git a/manual/Tasks/changelog.html b/manual/Tasks/changelog.html
index 8d9a70b..2b5411b 100644
--- a/manual/Tasks/changelog.html
+++ b/manual/Tasks/changelog.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,259 +15,232 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ChangeLog Task</title>
 </head>
 
 <body>
 
-<h2><a name="changelog">CvsChangeLog</a></h2>
+<h2 id="changelog">CvsChangeLog</h2>
 <h3>Description</h3>
-<p>Generates an XML-formatted report file of the change logs recorded in a
-<a href="http://www.nongnu.org/cvs/" target="_top">CVS</a> repository. </p>
-<p><b>Important:</b> This task needs &quot;<code>cvs</code>&quot; on the path. If it isn't, you will get
-an error (such as error <code>2</code> on windows). If <code>&lt;cvs&gt;</code> doesn't work, try to execute <code>cvs.exe</code>
-from the command line in the target directory in which you are working.
-Also note that this task assumes that the cvs executable is compatible
-with the Unix version from cvshome.org, this is not completely true
-for certain other cvs clients - like CVSNT for example - and some
-operation may fail when using such an incompatible client.
-</p>
+<p>Generates an XML-formatted report file of the change logs recorded in
+a <a href="https://www.nongnu.org/cvs/" target="_top">CVS</a> repository.</p>
+<p><strong>Important</strong>: This task needs <kbd>cvs</kbd> on the path. If it isn't, you will get
+an error (such as <code>error=2</code> on Windows). If <code>&lt;cvs&gt;</code> doesn't work, try to
+execute <kbd>cvs.exe</kbd> from the command line in the target directory in which you are working.
+Also note that this task assumes that the <kbd>cvs</kbd> executable is compatible with the Unix
+version, this is not completely true for certain other CVS clients&mdash;like CVSNT for
+example&mdash;and some operation may fail when using such an incompatible client.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td colspan="3">Attributes from parent Cvs task which are meaningful here<br>
-    Since Apache Ant 1.6.1</td>
+    <td colspan="3" class="left">Attributes from parent <code>&lt;cvs&gt;</code> task which are
+    meaningful here<br/><em>Since Apache Ant 1.6.1</em></td>
   </tr>
   <tr>
-    <td valign="top">cvsRoot</td>
-    <td valign="top">the <code>CVSROOT</code> variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRoot</td>
+    <td>the <code>CVSROOT</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">cvsRsh</td>
-    <td valign="top">the <code>CVS_RSH</code> variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRsh</td>
+    <td>the <code>CVS_RSH</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">the package/module to check out.  <b>Note:</b>
-      multiple attributes can be split using spaces.  Use a nested
-      &lt;module&gt; element if you want to specify a module with
-      spaces in its name.</td>
-    <td align="center" valign="top">No</td>
+    <td>package</td>
+    <td>the package/module to check out.  <strong>Note</strong>: multiple attributes can be split
+      using spaces.  Use a nested <code>&lt;module&gt;</code> element if you want to specify a
+      module with spaces in its name.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">Port used by CVS to communicate with the server.</td>
-    <td align="center" valign="top">No, default port 2401.</td>
+    <td>port</td>
+    <td>Port used by CVS to communicate with the server.</td>
+    <td>No; defaults to <q>2401</q></td>
   </tr>
   <tr>
-    <td valign="top">passfile</td>
-    <td valign="top">Password file to read passwords from.</td>
-    <td align="center" valign="top">No, default file <code>~/.cvspass</code>.</td>
+    <td>passfile</td>
+    <td>Password file to read passwords from.</td>
+    <td>No; defaults to <q>~/.cvspass</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the build process if the command exits with a
-      return code other than <code>0</code>. Defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">tag</td>
-    <td valign="top">query the changelog for a specific branch.</td>
-    <td align="center" valign="top">No</td>
+    <td>tag</td>
+    <td>query the changelog for a specific branch.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td colspan="3">Specific attributes</td>
+    <td colspan="3" class="left">Specific attributes</td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The directory from which to run the CVS <em>log</em>
-     command.</td>
-    <td align="center" valign="top">No; defaults to ${basedir}.</td>
+    <td>dir</td>
+    <td>The directory from which to run the <kbd>cvs log</kbd> command.</td>
+    <td>No; defaults to <q>${basedir}</q></td>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">The file in which to write the change log report.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>destfile</td>
+    <td>The file in which to write the change log report.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">usersfile</td>
-    <td valign="top">Property file that contains name-value pairs mapping
-     user IDs and names that should be used in the report in place of
-     the user ID.</td>
-    <td align="center" valign="top">No</td>
+    <td>usersfile</td>
+    <td>Property file that contains name-value pairs mapping user IDs and names that should be used
+      in the report in place of the user ID.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">daysinpast</td>
-    <td valign="top">Sets the number of days into the past for which the
-     change log information should be retrieved.</td>
-    <td align="center" valign="top">No</td>
+    <td>daysinpast</td>
+    <td>Sets the number of days into the past for which the change log information should be
+      retrieved.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">start</td>
-    <td valign="top">The earliest date from which change logs are to be
-     included in the report.</td>
-    <td align="center" valign="top">No</td>
+    <td>start</td>
+    <td>The earliest date from which change logs are to be included in the report.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">end</td>
-    <td valign="top">The latest date to which change logs are to be
-     included in the report.</td>
-    <td align="center" valign="top">No</td>
+    <td>end</td>
+    <td>The latest date to which change logs are to be included in the report.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">remote</td>
-    <td valign="top">If set to true, works against the repository
-      (using rlog) without a working copy.  Default is
-      false.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>remote</td>
+    <td>If set to true, works against the repository (using <kbd>cvs rlog</kbd>) without a working
+      copy.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">startTag</td>
-    <td valign="top">The start of a tag range. If endTag is also
-      specified, they must both be on the same branch. If endTag is not
-      specified, the end of the range will be the latest on the same
-      branch on which startTag lives.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>startTag</td>
+    <td>The start of a tag range. If <var>endTag</var> is also specified, they must both be on the
+      same branch. If <var>endTag</var> is not specified, the end of the range will be the latest on
+      the same branch on which <var>startTag</var> lives. <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">endTag</td>
-    <td valign="top">The end of a tag range. If startTag is also
-     specified, they must both be on the same branch. If startTag is
-     not specified, the start of the range will be the top of the
-     branch on which endTag lives.</td>  included in the report.
-    <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>endTag</td>
+    <td>The end of a tag range. If <var>startTag</var> is also specified, they must both be on the
+      same branch. If <var>startTag</var> is not specified, the start of the range will be the top
+      of the branch on which <var>endTag</var> lives. <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
-<h4><a name="user">user</a></h4>
-<p>The nested <code>&lt;user&gt;</code> element allows you to specify a
-mapping between a user ID as it appears on the CVS server and a name to
-include in the formatted report.
-Anytime the specified user ID has made a change in the repository, the
-<code>&lt;author&gt;</code> tag in the report file will include
-the name specified in <code>displayname</code> rather than the user ID.
-</p>
+<h4 id="user">user</h4>
+<p>The nested <code>&lt;user&gt;</code> element allows you to specify a mapping between a user ID as
+it appears on the CVS server and a name to include in the formatted report.  Anytime the specified
+user ID has made a change in the repository, the <code>&lt;author&gt;</code> tag in the report file
+will include the name specified in <var>displayname</var> rather than the user ID.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">displayname</td>
-    <td valign="top">The name to be used in the CVS change log report.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>displayname</td>
+    <td>The name to be used in the CVS change log report.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">userid</td>
-    <td valign="top">The userid of the person as it exists on the CVS server.
+    <td>userid</td>
+    <td>The user ID of the person as it exists on the CVS server.
     </td>
-    <td valign="top" align="center">Yes</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>module</h4>
 
-<p>Specifies a package/module to work on, unlike the package attribute
-  modules specified using this attribute can contain spaces in their
-  name.</p>
+<p>Specifies a package/module to work on, unlike the package attribute modules specified using this
+attribute can contain spaces in their name.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The module's/package's name.</td>
-    <td align="center" valign="top">Yes.</td>
+    <td>name</td>
+    <td>The module's/package's name.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<pre>  &lt;cvschangelog dir=&quot;dve/network&quot;
-                destfile=&quot;changelog.xml&quot;
-  /&gt;</pre>
-
-<p>Generates a change log report for all the changes that have been made
-under the <code>dve/network</code> directory.
-It writes these changes into the file <code>changelog.xml</code>.</p>
-
-<pre>  &lt;cvschangelog dir=&quot;dve/network&quot;
-                destfile=&quot;changelog.xml&quot;
-                daysinpast=&quot;10&quot;
-  /&gt;</pre>
-
-<p>Generates a change log report for any changes that were made
-under the <code>dve/network</code> directory in the past 10 days.
-It writes these changes into the file <code>changelog.xml</code>.</p>
-
-<pre>  &lt;cvschangelog dir=&quot;dve/network&quot;
-                destfile=&quot;changelog.xml&quot;
-                start=&quot;20 Feb 2002&quot;
-                end=&quot;20 Mar 2002&quot;
-  /&gt;</pre>
-
-<p>Generates a change log report for any changes that were made
-between February 20, 2002 and March 20, 2002
-under the <code>dve/network</code> directory.
-It writes these changes into the file <code>changelog.xml</code>.</p>
-
-<pre>  &lt;cvschangelog dir=&quot;dve/network&quot;
-                destfile=&quot;changelog.xml&quot;
-                start=&quot;20 Feb 2002&quot;
-  /&gt;</pre>
-
-<p>Generates a change log report for any changes that were made
-after February 20, 2002 under the <code>dve/network</code> directory.
-It writes these changes into the file <code>changelog.xml</code>.</p>
-
-<pre>  &lt;cvschangelog dir=&quot;dve/network&quot;
-                destfile=&quot;changelog.xml&quot;&gt;
-       &lt;user displayname=&quot;Peter Donald&quot; userid=&quot;donaldp&quot;/&gt;
-  &lt;/cvschangelog&gt;</pre>
-
-<p>Generates a change log report for all the changes that were made
-under the <code>dve/network</code> directory, substituting the name
-&quot;Peter Donald&quot; in the <code>&lt;author&gt;</code> tags
-anytime it encounters a change made by the user ID &quot;donaldp&quot;.
-It writes these changes into the file <code>changelog.xml</code>.</p>
-
-<p>Generates a change log report on the <code>ANT_16_BRANCH</code>.</p>
+<p>Generate a change log report for all the changes that have been made under
+the <samp>dve/network</samp> directory. Write these changes into the
+file <samp>changelog.xml</samp>.</p>
 <pre>
- &lt;cvschangelog dir=&quot;c:/dev/asf/ant.head&quot; passfile=&quot;c:/home/myself/.cvspass&quot;
-                destfile=&quot;changelogant.xml&quot; tag=&quot;ANT_16_BRANCH&quot;/&gt;
-</pre>
+&lt;cvschangelog dir=&quot;dve/network&quot;
+              destfile=&quot;changelog.xml&quot;/&gt;</pre>
+
+<p>Generate a change log report for any changes that were made under the <samp>dve/network</samp>
+directory in the past 10 days. Write these changes into the file <samp>changelog.xml</samp>.</p>
+<pre>
+&lt;cvschangelog dir=&quot;dve/network&quot;
+              destfile=&quot;changelog.xml&quot;
+              daysinpast=&quot;10&quot;/&gt;</pre>
+
+<p>Generate a change log report for any changes that were made between February 20, 2002 and March
+20, 2002 under the <samp>dve/network</samp> directory. Write these changes into the
+file <samp>changelog.xml</samp>.</p>
+<pre>
+&lt;cvschangelog dir=&quot;dve/network&quot;
+              destfile=&quot;changelog.xml&quot;
+              start=&quot;20 Feb 2002&quot;
+              end=&quot;20 Mar 2002&quot;/&gt;</pre>
+
+<p>Generate a change log report for any changes that were made after February 20, 2002 under
+the <samp>dve/network</samp> directory. Write these changes into the
+file <samp>changelog.xml</samp>.</p>
+<pre>
+&lt;cvschangelog dir=&quot;dve/network&quot;
+              destfile=&quot;changelog.xml&quot;
+              start=&quot;20 Feb 2002&quot;/&gt;</pre>
+
+<p>Generate a change log report for all the changes that were made under
+the <code>dve/network</code> directory, substituting the name <samp>Peter Donald</samp> in
+the <code>&lt;author&gt;</code> tags anytime a change made by the user ID <samp>donaldp</samp> is
+encountered.  Write these changes into the file <samp>changelog.xml</samp>.</p>
+<pre>
+&lt;cvschangelog dir=&quot;dve/network&quot;
+              destfile=&quot;changelog.xml&quot;&gt;
+    &lt;user displayname=&quot;Peter Donald&quot; userid=&quot;donaldp&quot;/&gt;
+&lt;/cvschangelog&gt;</pre>
+
+<p>Generate a change log report on the <code>ANT_16_BRANCH</code>.</p>
+<pre>
+&lt;cvschangelog dir=&quot;c:/dev/asf/ant.head&quot; passfile=&quot;c:/home/myself/.cvspass&quot;
+              destfile=&quot;changelogant.xml&quot; tag=&quot;ANT_16_BRANCH&quot;/&gt;</pre>
 <h4>Generate Report</h4>
-<p>Ant includes a basic XSLT stylesheet that you can use to generate 
-a HTML report based on the xml output. The following example illustrates
-how to generate a HTML report from the XML report.</p>
+<p>Ant includes a basic XSLT stylesheet that you can use to generate a HTML report based on the XML
+output. The following example illustrates how to generate a HTML report from the XML report.</p>
 
 <pre>
-        &lt;style in="changelog.xml" 
-               out="changelog.html" 
-               style="${ant.home}/etc/changelog.xsl"&gt;
-          &lt;param name="title" expression="Ant ChangeLog"/&gt;
-          &lt;param name="module" expression="ant"/&gt;
-          &lt;param name="cvsweb" expression="http://cvs.apache.org/viewcvs/"/&gt;
-        &lt;/style&gt;
-</pre>
+&lt;style in="changelog.xml"
+      out="changelog.html"
+      style="${ant.home}/etc/changelog.xsl"&gt;
+  &lt;param name="title" expression="Ant ChangeLog"/&gt;
+  &lt;param name="module" expression="ant"/&gt;
+  &lt;param name="cvsweb" expression="https://cvs.apache.org/viewcvs/"/&gt;
+&lt;/style&gt;</pre>
 
 <h4>Sample Output</h4>
 <pre>
@@ -284,11 +258,7 @@
 
 This allows templates to be stored inside jar]]&gt;&lt;/msg&gt;
   &lt;/entry&gt;
-&lt;/changelog&gt;
-</pre>
-
-
+&lt;/changelog&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/checksum.html b/manual/Tasks/checksum.html
index 29f48dd..0640814 100644
--- a/manual/Tasks/checksum.html
+++ b/manual/Tasks/checksum.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,256 +15,224 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Checksum Task</title>
 </head>
 
 <body>
 
-<h2><a name="checksum">Checksum</a></h2>
+<h2 id="checksum">Checksum</h2>
 <h3>Description</h3>
-<p>
-Generates checksum for files.  This task can also be used to
-perform checksum verifications.
-</p>
+<p>Generates checksum for files.  This task can also be used to perform checksum verifications.</p>
 
-<p>Note that many popular message digest functions - including MD5 and
-SHA-1 - have been broken recently.  If you are going to use the task
-to create checksums used in an environment where security is
-important, please take some time to investigate the algorithms offered
-by your JCE provider.  Note also that some JCE providers like the one
-by <a href="http://www.bouncycastle.org/">The Legion of the Bouncy
-Castle</a>, the <a href="http://www.gnu.org/software/gnu-crypto/">GNU
-project</a> or <a
-href="http://jce.iaik.tugraz.at/products/01_jce/index.php">the
-Technical University Graz</a> offer more digest algorithms than those
-built-in into your JDK.</p>
+<p>Note that many popular message digest functions&mdash;including MD5 and SHA-1&mdash;have been
+broken recently.  If you are going to use the task to create checksums used in an environment where
+security is important, please take some time to investigate the algorithms offered by your JCE
+provider.  Note also that some JCE providers like the one by <a href="https://www.bouncycastle.org/"
+target="_top">The Legion of the Bouncy Castle</a>,
+the <a href="https://www.gnu.org/software/gnu-crypto/" target="_top">GNU Crypto project</a>
+or <a href="https://jce.iaik.tugraz.at/sic/Products" target="_top">the Technical University Graz</a>
+offer more digest algorithms than those built-in into your JDK.</p>
 
-<p>
-Warning: the case of the extension is that of the algorithm used.
-If you ask for "SHA1", you get a .SHA1 extension; if you ask for "sha1", you
-get a file ending in .sha1. The Java Crypto Engines are case-insensitive
-in matching algorithms, so choose a name to match your desired output extension,
-or set the <tt>fileext</tt> attribute. The names of common hashing algorithms can be located on the
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest">Cryptography Architecture Standard Algorithm Name Documentation</a>
-</p>
+<p>Warning: the case of the extension is that of the algorithm used.  If you ask
+for <samp>SHA1</samp>, you get a <samp>.SHA1</samp> extension; if you ask for <samp>sha1</samp>, you
+get a file ending in <samp>.sha1</samp>. The Java Crypto Engines are case-insensitive in matching
+algorithms, so choose a name to match your desired output extension, or set the <var>fileext</var>
+attribute. The names of common hashing algorithms can be located on
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"
+target="_top">Cryptography Architecture Standard Algorithm Name Documentation</a></p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to generate checksum for.</td>
-    <td valign="top" align="center">One of either <var>file</var> or
-    at least one nested (filesystem-only) resource collection.</td>
+    <td>file</td>
+    <td>The file to generate checksum for.</td>
+    <td>Yes, unless at least one nested (filesystem-only) resource collection is specified.</td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">The root directory where checksums should be written.</td>
-    <td valign="top" align="center">No. If not specified, checksum files
-      will be written to the same directory as the files themselves.
-      <em>since Apache Ant 1.6</em>
+    <td>todir</td>
+    <td>The root directory where checksums should be written.</td>
+    <td>No; by default, checksum files will be written to the same directory as the original
+      files.  <em>since Apache Ant 1.6</em>
     </td>
   </tr>
   <tr>
-    <td valign="top">algorithm</td>
-    <td valign="top">Specifies the algorithm to be used to
-      compute the checksum. Defaults to &quot;MD5&quot;.
-      Other <a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest">popular algorithms</a> like &quot;SHA&quot; or &quot;SHA-512&quot; may be used
-      as well.
+    <td>algorithm</td>
+    <td>Specifies the algorithm to be used to compute the checksum. Please check
+      the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest"
+      target="_top">documentation</a> for available algorithm names, like <q>SHA-1</q>
+      or <q>SHA-512</q>.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to <q>MD5</q></td>
   </tr>
   <tr>
-    <td valign="top">provider</td>
-    <td valign="top">Specifies the provider of the algorithm.</td>
-    <td valign="top" align="center">No</td>
+    <td>provider</td>
+    <td>Specifies the provider of the algorithm.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">fileext</td>
-    <td valign="top">The generated checksum file's name will be the
-    original filename with the fileext added to it.
-    Defaults to a "." and the algorithm name being used.
+    <td>fileext</td>
+    <td>The generated checksum file's name will be the original filename with the <var>fileext</var>
+      added to it.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to a <q>.</q> and the algorithm name being used</td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">This attribute can mean two different things, it
-    depends on the presence of the verifyproperty attribute.<br>
-    <b>If you don't set the verifyproperty attribute</b>, property
-    specifies the name of the property to be set with the generated
-    checksum value.<br>
-    <b>If you set the verifyproperty attribute</b>, property specifies
-    the checksum you expect to be generated (the checksum itself, not
-    a name of a property containing the checksum).<br>
-    This cannot be specified when fileext is being used or when the
-    number of files for which checksums is to be generated is greater
-    than 1.
+    <td>property</td>
+    <td>This attribute can mean two different things, it depends on the presence of
+      the <var>verifyproperty</var> attribute.<br/><strong>If you don't set</strong>
+      the <var>verifyproperty</var> attribute, property specifies the name of the property to be set
+      with the generated checksum value.<br/><strong>If you set</strong>
+      the <var>verifyproperty</var> attribute, property specifies the checksum you expect to be
+      generated (the checksum itself, not a name of a property containing the checksum).<br/>  This
+      cannot be specified when <var>fileext</var> is being used or when the number of files for
+      which checksums are to be generated is greater than 1.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">Specifies the pattern to use as a pattern
-    suitable
-    for <a href="http://download.oracle.com/javase/6/docs/api/java/text/MessageFormat.html">MessageFormat</a>
-    where <code>{0}</code> is replaced with the checksum and
-      <code>{1}</code> with the file name. <em>Since Ant
-      1.7.0</em><br/>
-      <em>starting with Ant 1.8.2</em> <code>{2}</code> is replaced by
-      the path of the file relative to the checksum file being
-      written, <code>{3}</code> with tha path of the file relative to
-      the project's basedir and <code>{4}</code> with the absolute
-      path of the file.</td>
-    <td valign="top" align="center">No - default is &quot;{0}&quot;.</td>
+    <td>pattern</td>
+    <td>Specifies the pattern to use as a pattern suitable
+    for <a href="https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html"
+    target="_top">MessageFormat</a> where <code>{0}</code> is replaced with the checksum
+    and <code>{1}</code> with the file name. <em>Since Ant 1.7.0</em><br/><em>Since Ant
+    1.8.2</em> <code>{2}</code> is replaced by the path of the file relative to the checksum file
+    being written, <code>{3}</code> with the path of the file relative to the
+    project's <var>basedir</var> and <code>{4}</code> with the absolute path of the file.</td>
+    <td>No; default is <q>{0}</q></td>
   </tr>
   <tr>
-    <td valign="top">format</td>
-    <td valign="top">Specifies the pattern to use as one of a
-    well-known format.  Supported values are 
-      <table border="1">
+    <td>format</td>
+    <td>Specifies the pattern to use as one of a well-known format.  Supported values are
+      <table>
       <tr>
-        <th>name</th>
-        <th>pattern</th>
-        <th>description</th>
+        <th scope="col">name</th>
+        <th scope="col">pattern</th>
+        <th scope="col">description</th>
       </tr>
       <tr>
-        <td>CHECKSUM </td>
-        <td><tt>{0}</tt></td>
-        <td>only the checksum itself </td>
+        <td>CHECKSUM</td>
+        <td><code>{0}</code></td>
+        <td>only the checksum itself</td>
       </tr>
       <tr>
-        <td>MD5SUM </td>
-        <td><tt>{0} *{1}</tt></td>
-        <td>the format of GNU textutils md5sum</td>
+        <td>MD5SUM</td>
+        <td><code>{0} *{1}</code></td>
+        <td>the format of GNU textutils <code>md5sum</code></td>
       </tr>
       <tr>
-        <td>SVF </td>
-        <td><tt>MD5 ({1}) = {0}</tt></td>
-        <td>the format of BSDs md5 command </td>
+        <td>SVF</td>
+        <td><code>MD5 ({1}) = {0}</code></td>
+        <td>the format of BSD <code>md5</code> command</td>
       </tr>
       </table>
-       <em>Since Ant 1.7.0</em>
-    </td>
-    <td valign="top" align="center">No - default is &quot;CHECKSUM&quot;.</td>
+      <em>Since Ant 1.7.0</em></td>
+    <td>No; default is <q>CHECKSUM</q></td>
   </tr>
   <tr>
-    <td valign="top">totalproperty</td>
-    <td valign="top">If specified, this attribute specifies the name of
-      the property that will hold a checksum of all the checksums and
-      file paths. The individual checksums and the relative paths to the files
-      within the resource collections in which they are defined will be used to
-      compute this checksum. (The file separators in the paths will be
-      converted to '/' before computation to ensure platform portability).
-      <em>since Ant 1.6</em>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>totalproperty</td>
+    <td>If specified, this attribute specifies the name of the property that will hold a checksum of
+      all the checksums and file paths. The individual checksums and the relative paths to the files
+      within the resource collections in which they are defined will be used to compute this
+      checksum. (The file separators in the paths will be converted to <q>/</q> before computation
+      to ensure platform portability).  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">forceoverwrite</td>
-    <td valign="top">Overwrite existing files even if the destination
-      files are newer. Defaults to &quot;no&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>forceoverwrite</td>
+    <td>Overwrite existing files even if the destination files are newer.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">verifyproperty</td>
-    <td valign="top">Specifies the name of the property to be set
-    with &quot;true&quot; or &quot;false&quot; depending upon whether
-    the generated checksum matches the existing checksum.  When
-    this is set, the generated checksum is not written to a file or
-    property, but rather, the content of the file or property is used to
-    check against the generated checksum.
-    <td valign="top" align="center">No</td>
+    <td>verifyproperty</td>
+    <td>Specifies the name of the property to be set with <q>true</q> or <q>false</q> depending upon
+      whether the generated checksum matches the existing checksum.  When this is set, the generated
+      checksum is not written to a file or property, but rather, the content of the file or property
+      is used to check against the generated checksum.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">readbuffersize</td>
-    <td valign="top">The size of the buffer (in bytes) to use when
-    reading a file. Defaults to &quot;8192&quot; - you may get a
-    better performance on big files if you increase this value.</td>
-    <td valign="top" align="center">No</td>
+    <td>readbuffersize</td>
+    <td>The size of the buffer (in bytes) to use when reading a file.</td>
+    <td>No; defaults to <q>8192</q>&mdash;you may get a better performance on big files if you
+      increase this value</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
-<h4>resource collection</h4>
- <p>
- <a href="../Types/resources.html#collection">Resource collections</a> are
- used to select files for which checksums should be generated.
- </p>
+<h4>resource collections</h4>
+<p><a href="../Types/resources.html#collection">Resource collections</a> are used to select files
+for which checksums should be generated.</p>
 
 <h3>Examples</h3>
-<p><b>Example 1</b></p>
-<blockquote><pre>&lt;checksum file=&quot;foo.bar&quot;/&gt;</pre></blockquote>
-Generates a MD5 checksum for foo.bar and stores the checksum in the destination file
-foo.bar.MD5.  foo.bar.MD5 is overwritten only if foo.bar is newer than itself.
 
-<p><b>Example 2</b></p>
-<blockquote><pre>&lt;checksum file=&quot;foo.bar&quot; forceOverwrite=&quot;yes&quot;/&gt;</pre></blockquote>
-Generates a MD5 checksum for foo.bar and stores the checksum in foo.bar.MD5.
-If foo.bar.MD5 already exists, it is overwritten.
+<p><strong>Example 1</strong></p>
+<p>Generate a MD5 checksum for <samp>foo.bar</samp> and store the checksum in the destination
+file <samp>foo.bar.MD5</samp>.  <samp>foo.bar.MD5</samp> is overwritten only if <samp>foo.bar</samp>
+is newer than itself.</p>
+<pre>&lt;checksum file=&quot;foo.bar&quot;/&gt;</pre>
 
-<p><b>Example 3</b></p>
-<blockquote><pre>&lt;checksum file=&quot;foo.bar&quot; property=&quot;foobarMD5&quot;/&gt;</pre></blockquote>
-Generates a MD5 checksum for foo.bar and stores it in the Project Property foobarMD5.
+<p><strong>Example 2</strong></p>
+<p>Generate a MD5 checksum for <samp>foo.bar</samp> and store the checksum
+in <samp>foo.bar.MD5</samp>.  If <samp>foo.bar.MD5</samp> already exists, it is overwritten.</p>
+<pre>&lt;checksum file=&quot;foo.bar&quot; forceOverwrite=&quot;yes&quot;/&gt;</pre>
 
-<p><b>Example 4</b></p>
-<blockquote><pre>&lt;checksum file=&quot;foo.bar&quot; verifyProperty=&quot;isMD5ok&quot;/&gt;</pre></blockquote>
-Generates a MD5 checksum for foo.bar, compares it against foo.bar.MD5 and sets
-isMD5ok to either true or false, depending upon the result.
+<p><strong>Example 3</strong></p>
+<p>Generate a MD5 checksum for <samp>foo.bar</samp> and store it in the project
+property <code>foobarMD5</code>.</p>
+<pre>&lt;checksum file=&quot;foo.bar&quot; property=&quot;foobarMD5&quot;/&gt;</pre>
 
-<p><b>Example 5</b></p>
-<blockquote><pre>&lt;checksum file=&quot;foo.bar&quot; algorithm=&quot;SHA-512&quot; fileext=&quot;asc&quot;/&gt;</pre></blockquote>
-Generates a SHA-512 checksum for foo.bar and stores the checksum in the destination file
-foo.bar.asc.  foo.bar.asc is overwritten only if foo.bar is newer than itself.
+<p><strong>Example 4</strong></p>
+<p>Generate a MD5 checksum for <samp>foo.bar</samp>, compare it against <samp>foo.bar.MD5</samp> and
+set <code>isMD5ok</code> to either <q>true</q> or <q>false</q>, depending upon the result.</p>
+<pre>&lt;checksum file=&quot;foo.bar&quot; verifyProperty=&quot;isMD5ok&quot;/&gt;</pre>
 
-<p><b>Example 6</b></p>
-<blockquote><pre>
-&lt;checksum file=&quot;foo.bar&quot; property=&quot;${md5}&quot; verifyProperty=&quot;isEqual&quot;/&gt;
-</pre></blockquote>
-Generates a MD5 checksum for foo.bar, compares it against the value of the property
-md5, and sets isEqual to either true or false, depending upon the result.
+<p><strong>Example 5</strong></p>
+<p>Generate a SHA-512 checksum for <samp>foo.bar</samp> and store the checksum in the destination
+file <samp>foo.bar.asc</samp>.  <samp>foo.bar.asc</samp> is overwritten only if <samp>foo.bar</samp>
+is newer than itself.</p>
+<pre>&lt;checksum file=&quot;foo.bar&quot; algorithm=&quot;SHA-512&quot; fileext=&quot;asc&quot;/&gt;</pre>
 
-<p><b>Example 7</b></p>
-<blockquote><pre>
+<p><strong>Example 6</strong></p>
+<p>Generate a MD5 checksum for <samp>foo.bar</samp>, compare it against the value of the
+property <code>md5</code>, and set <code>isEqual</code> to either <q>true</q> or <q>false</q>,
+depending upon the result.</p>
+<pre>&lt;checksum file=&quot;foo.bar&quot; property=&quot;${md5}&quot; verifyProperty=&quot;isEqual&quot;/&gt;</pre>
+
+<p><strong>Example 7</strong></p>
+<p>Just like Example 1, but generates a <samp>.MD5</samp> file for every file that begins with the
+name <samp>foo</samp>.</p>
+<pre>
 &lt;checksum&gt;
   &lt;fileset dir=&quot;.&quot;&gt;
     &lt;include name=&quot;foo*&quot;/&gt;
   &lt;/fileset&gt;
-&lt;/checksum&gt;
-</pre></blockquote>
-Works just like Example 1, but generates a .MD5 file for every file that begins with the name foo.
+&lt;/checksum&gt;</pre>
 
-<p><b>Example 8</b></p>
-<blockquote><pre>
+<p><strong>Example 8</strong></p>
+<p>Just like Example 4, but only sets <code>isChecksumEqual</code> to <q>true</q>, if the checksum
+matches&mdash;it will never be set to <q>false</q>.  This example demonstrates use with
+the <code>condition</code> task.</p>
+<pre>
 &lt;condition property=&quot;isChecksumEqual&quot;&gt;
   &lt;checksum&gt;
     &lt;fileset dir=&quot;.&quot;&gt;
       &lt;include name=&quot;foo.bar&quot;/&gt;
     &lt;/fileset&gt;
   &lt;/checksum&gt;
-&lt;/condition&gt;
-</pre></blockquote>
-Works like Example 4, but only sets isChecksumEqual to true, if the
-checksum matches - it will never be set to false.  This example
-demonstrates use with the Condition task.
+&lt;/condition&gt;</pre>
 
-
-<h3>Note:</h3>
-When working with more than one file, if condition and/or verifyproperty is used,
-the result will be true only if the checksums matched correctly for all files being
-considered.
-
-
+<h3>Note</h3>
+<p>When working with more than one file, if condition and/or <var>verifyproperty</var> is used, the
+result will be true only if the checksums matched correctly for all files being considered.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/chgrp.html b/manual/Tasks/chgrp.html
index 2126fb7..9b05568 100644
--- a/manual/Tasks/chgrp.html
+++ b/manual/Tasks/chgrp.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,135 +15,116 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Chgrp Task</title>
 </head>
 
 <body>
 
-<h2><a name="Chgrp">Chgrp</a></h2>
-<p><em>Since Apache Ant 1.6.</em></p>
+<h2 id="chgrp">Chgrp</h2>
+<p><em>Since Apache Ant 1.6</em>.</p>
 <h3>Description</h3>
 
-<p>Changes the group of a file or all files inside specified
-directories. Right now it has effect only under Unix.  The group
-attribute is equivalent to the corresponding argument for the chgrp
-command.</p>
+<p>Changes the group of a file or all files inside specified directories. Right now it has effect
+only under Unix.  The group attribute is equivalent to the corresponding argument for
+the <kbd>chgrp</kbd> command.</p>
 
-<p><a href="../Types/fileset.html">FileSet</a>s, 
-<a href="../Types/dirset.html">DirSet</a>s or <a
-href="../Types/filelist.html">FileList</a>s can be specified using
-nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and 
-<code>&lt;filelist&gt;</code> elements.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s, <a href="../Types/dirset.html">DirSet</a>s
+or <a href="../Types/filelist.html">FileList</a>s can be specified using
+nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and <code>&lt;filelist&gt;</code>
+elements.</p>
 
-<p>Starting with Ant 1.7, this task supports arbitrary <a
-href="../Types/resources.html#collection">Resource Collection</a>s
-as nested elements.</p>
+<p><em>Since Ant 1.7</em>, this task supports
+arbitrary <a href="../Types/resources.html#collection">resource collections</a> as nested
+elements.</p>
 
-<p>By default this task will use a single invocation of the underlying
-chgrp command.  If you are working on a large number of files this may
-result in a command line that is too long for your operating system.
-If you encounter such problems, you should set the maxparallel
-attribute of this task to a non-zero value.  The number to use highly
-depends on the length of your file names (the depth of your directory
-tree) and your operating system, so you'll have to experiment a
-little.  POSIX recommends command line length limits of at least 4096
-characters, this may give you an approximation for the number you
-could use as initial value for these experiments.</p>
+<p>By default this task will use a single invocation of the underlying <kbd>chgrp</kbd> command.
+If you are working on a large number of files this may result in a command line that is too long for
+your operating system.  If you encounter such problems, you should set the <var>maxparallel</var>
+attribute of this task to a non-zero value.  The number to use highly depends on the length of your
+file names (the depth of your directory tree) and your operating system, so you'll have to
+experiment a little.  POSIX recommends command line length limits of at least 4096 characters, this
+may give you an approximation for the number you could use as initial value for these
+experiments.</p>
 
-<p>By default this task won't do anything unless it detects it is
-  running on a Unix system.  If you know for sure that you have a
-  "chgrp" executable on your PATH that is command line compatible with
-  the Unix command, you can use the task's os attribute and set its
-  value to your current os.</p>
+<p>By default this task won't do anything unless it detects it is running on a Unix system.  If you
+know for sure that you have a <kbd>chgrp</kbd> executable on your <code>PATH</code> that is
+command line compatible with the Unix command, you can use the task's <var>os</var> attribute and
+set its value to your current OS.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file or directory of which the group must be
-    changed.</td>
-    <td valign="top" valign="middle">Yes, unless nested
-      <code>&lt;fileset|filelist|dirset&gt;</code>
-      elements are specified</td>
+    <td>file</td>
+    <td>the file or directory of which the group must be changed.</td>
+    <td>Yes, unless nested <code>&lt;fileset|filelist|dirset&gt;</code> elements are specified</td>
   </tr>
   <tr>
-    <td valign="top">group</td>
-    <td valign="top">the new group.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>group</td>
+    <td>the new group.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">parallel</td>
-    <td valign="top">process all specified files using a single
-      <code>chgrp</code> command. Defaults to true.</td>
-    <td valign="top" align="center">No</td>
+    <td>parallel</td>
+    <td>process all specified files using a single <kbd>chgrp</kbd> command.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">One of <i>file</i>, <i>dir</i> or
-      <i>both</i>. If set to <i>file</i>, only the group of
-      plain files are going to be changed. If set to <i>dir</i>, only
-      the directories are considered.<br>
-      <strong>Note:</strong> The type attribute does not apply to
-      nested <i>dirset</i>s - <i>dirset</i>s always implicitly
-      assume type to be <i>dir</i>.</td>
-    <td align="center" valign="top">No, default is <i>file</i></td>
+    <td>type</td>
+    <td>One of <q>file</q>, <q>dir</q> or <q>both</q>. If set to <q>file</q>, only the group of
+      plain files are going to be changed. If set to <q>dir</q>, only the directories are
+      considered.<br/><strong>Note</strong>: The type attribute does not apply to
+      nested <code>dirset</code>s&mdash;<code>dirset</code>s always implicitly assume type to
+      be <q>dir</q>.</td>
+    <td>No; default is <q>file</q></td>
   </tr>
   <tr>
-    <td valign="top">maxparallel</td>
-    <td valign="top">Limit the amount of parallelism by passing at
-      most this many sourcefiles at once.  Set it to &lt;= 0 for
-      unlimited.  Defaults to unlimited.</td>
-    <td align="center" valign="top">No</td>
-
+    <td>maxparallel</td>
+    <td>Limit the amount of parallelism by passing at most this many sourcefiles at once.  Set it to
+      negative integer for unlimited.</td>
+    <td>No; defaults to unlimited</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to print a summary after execution or not.
-      Defaults to <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>verbose</td>
+    <td>Whether to print a summary after execution or not.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">os</td>
-    <td valign="top">list of Operating Systems on which the command may be
-      executed.</td>
-    <td align="center" valign="top">No</td>
+    <td>os</td>
+    <td>list of Operating Systems on which the command may be executed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">osfamily</td>
-    <td valign="top">OS family as used in
-      the <a href="../Tasks/conditions.html#os">&lt;os&gt;</a>
+    <td>osfamily</td>
+    <td>OS family as used in the <a href="../Tasks/conditions.html#os">&lt;os&gt;</a>
       condition.</td>
-    <td align="center" valign="top">No - defaults to "unix"</td>
+    <td>No; defaults to <q>unix</q></td>
   </tr>
-
 </table>
 <h3>Examples</h3>
-  <blockquote><pre>
-&lt;chgrp file=&quot;${dist}/start.sh&quot; group=&quot;coders&quot;/&gt;
-</pre>
-</blockquote>
-<p>makes the &quot;start.sh&quot; file belong to the coders group on a
-UNIX system.</p>
-<blockquote>
+
+<p>Make the <samp>start.sh</samp> file belong to the <samp>coders</samp> group on a UNIX system.</p>
+<pre>&lt;chgrp file=&quot;${dist}/start.sh&quot; group=&quot;coders&quot;/&gt;</pre>
+
+<p>Make all <samp>.sh</samp> files below <samp>${dist}/bin</samp> belong to the <samp>coders</samp>
+group on a UNIX system.</p>
 <pre>
 &lt;chgrp group=&quot;coders&quot;&gt;
   &lt;fileset dir=&quot;${dist}/bin&quot; includes=&quot;**/*.sh&quot;/&gt;
-&lt;/chgrp&gt;
-</pre>
-</blockquote>
-<p>makes all &quot;.sh&quot; files below <code>${dist}/bin</code>
-belong to the coders group on a UNIX system.</p>
-<blockquote>
+&lt;/chgrp&gt;</pre>
+
+<p>Make all files below <samp>shared/sources1</samp> (except those below any directory
+named <samp>trial</samp>) belong to the <samp>coders</samp> group on a UNIX system. In addition, all
+files belonging to a FileSet with <var>id</var>=<samp>other.shared.sources</samp> get the same
+group.</p>
 <pre>
 &lt;chgrp group=&quot;coders&quot;&gt;
   &lt;fileset dir=&quot;shared/sources1&quot;&gt;
@@ -151,14 +133,11 @@
   &lt;fileset refid=&quot;other.shared.sources&quot;/&gt;
 &lt;/chgrp&gt;
 </pre>
-</blockquote>
-<p>makes all files below <code>shared/sources1</code> (except those
-below any directory named trial) belong to the coders group on a UNIX 
-system. In addition all files belonging to a FileSet
-with <code>id</code> <code>other.shared.sources</code> get the same
-group.</p>
 
-<blockquote>
+<p>Make all <samp>.test.jsp</samp>, and <samp>.new</samp> files belong to
+group <samp>webdev</samp>. Directories with names beginning with <samp>test_</samp> also will belong
+to <samp>webdev</samp>, but if there is a directory name that ends in <samp>.new</samp> or a file
+name that begins with <samp>test_</samp> it will be unaffected.</p>
 <pre>
 &lt;chgrp group=&quot;webdev&quot; type=&quot;file&quot;&gt;
   &lt;fileset dir=&quot;/web&quot;&gt;
@@ -168,18 +147,7 @@
   &lt;dirset dir=&quot;/web&quot;&gt;
     &lt;include name=&quot;**/test_*&quot;/&gt;
   &lt;/dirset&gt;
-&lt;/chmod&gt;
-</pre>
-</blockquote>
-
-<p>makes all <code>.test.jsp</code>, and <code>.new</code> files belong to 
-group webdev. Directories beginning with <code>test_</code> also will belong 
-to webdev, but if there is a directory that ends in <code>.new</code> or a file
-that begins with <code>test_</code> it will be unaffected.</p>
-
-
-
+&lt;/chmod&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/chmod.html b/manual/Tasks/chmod.html
index 74e71d0..13371dd 100644
--- a/manual/Tasks/chmod.html
+++ b/manual/Tasks/chmod.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,179 +15,158 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Chmod Task</title>
 </head>
 
 <body>
 
-<h2><a name="chmod">Chmod</a></h2>
+<h2 id="chmod">Chmod</h2>
 <h3>Description</h3>
-<p>Changes the permissions of a file or all files inside specified
-directories. Right now it has effect only under Unix or NonStop Kernel (Tandem).
-The permissions are also UNIX style, like the argument for the chmod command.</p>
-<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based
-tasks</a>, on how the inclusion/exclusion of files works, and how to
-write patterns.</p>
+<p>Changes the permissions of a file or all files inside specified directories. Right now it has
+effect only under Unix or NonStop Kernel (Tandem).  The permissions are also UNIX style, like the
+argument for the <kbd>chmod</kbd> command.</p>
+<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on
+how the inclusion/exclusion of files works, and how to write patterns.</p>
 
-<p>This task holds an implicit <a
-href="../Types/fileset.html">FileSet</a> and supports all of
-FileSet's attributes and nested elements directly. More sets can be
-specified using nested <code>&lt;fileset&gt;</code> or
-<code>&lt;dirset&gt;</code> (<em>since Apache Ant 1.6</em>) elements. </p>
+<p>This task holds an implicit <a href="../Types/fileset.html">FileSet</a> and supports all of
+FileSet's attributes and nested elements directly. More sets can be specified using
+nested <code>&lt;fileset&gt;</code> or <code>&lt;dirset&gt;</code> (<em>since Apache Ant 1.6</em>)
+elements.</p>
 
-<p>Starting with Ant 1.6, this task also supports nested <a
-href="../Types/filelist.html">filelist</a>s.</p>
+<p><em>Since Ant 1.6</em>, this task also supports
+nested <a href="../Types/filelist.html">filelist</a>s.</p>
 
-<p>Starting with Ant 1.7, this task supports arbitrary <a
-href="../Types/resources.html#collection">Resource Collection</a>s
-as nested elements.</p>
+<p><em>Since Ant 1.7</em>, this task supports
+arbitrary <a href="../Types/resources.html#collection">resource collections</a> as nested
+elements.</p>
 
-<p>By default this task will use a single invocation of the underlying
-chmod command.  If you are working on a large number of files this may
-result in a command line that is too long for your operating system.
-If you encounter such problems, you should set the maxparallel
-attribute of this task to a non-zero value.  The number to use highly
-depends on the length of your file names (the depth of your directory
-tree) and your operating system, so you'll have to experiment a
-little.  POSIX recommends command line length limits of at least 4096
-characters, this may give you an approximation for the number you
-could use as initial value for these experiments.</p>
+<p>By default this task will use a single invocation of the underlying <kbd>chmod</kbd> command.
+If you are working on a large number of files this may result in a command line that is too long for
+your operating system.  If you encounter such problems, you should set the <var>maxparallel</var>
+attribute of this task to a non-zero value.  The number to use highly depends on the length of your
+file names (the depth of your directory tree) and your operating system, so you'll have to
+experiment a little.  POSIX recommends command line length limits of at least 4096 characters, this
+may give you an approximation for the number you could use as initial value for these
+experiments.</p>
 
-<p>By default this task won't do anything unless it detects it is
-  running on a Unix system.  If you know for sure that you have a
-  "chmod" executable on your PATH that is command line compatible with
-  the Unix command, you can use the task's os attribute and set its
-  value to your current os.</p>
+<p>By default this task won't do anything unless it detects it is running on a Unix system.  If you
+know for sure that you have a <kbd>chmod</kbd> executable on your <code>PATH</code> that is
+command line compatible with the Unix command, you can use the task's <var>os</var> 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">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file or single directory of which the permissions 
-      must be changed.</td>
-    <td valign="top" valign="middle" rowspan="2">exactly one of the two or nested <code>&lt;fileset/list&gt;</code> elements.</td>
+    <td>file</td>
+    <td>the file or single directory of which the permissions must be changed.</td>
+    <td rowspan="2">Exactly one of the two, unless
+      nested <code>&lt;fileset|filelist|dirset&gt;</code> elements are specified</td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the directory which holds the files whose permissions 
-      must be changed.<br/>
-      <b>Note:</b> for backwards compatibility
-      reasons <code>&lt;chmod&nbsp;dir="some-dir"/&gt;</code> will
-      only change the permissions on "some-dir" but not recurse into
-      it, unless you also specify any patterns.</td>
+    <td>dir</td>
+    <td class="left">the directory which holds the files whose permissions must be
+      changed.<br/><strong>Note</strong>: for backwards compatibility reasons <code>&lt;chmod
+      dir="some-dir"/&gt;</code> will only change the permissions on <samp>some-dir</samp> but not
+      recurse into it, unless you also specify any patterns.</td>
   </tr>
   <tr>
-    <td valign="top">perm</td>
-    <td valign="top">the new permissions.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>perm</td>
+    <td>the new permissions.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">parallel</td>
-    <td valign="top">process all specified files using a single
-      <code>chmod</code> command. Defaults to true.</td>
-    <td valign="top" align="center">No</td>
+    <td>parallel</td>
+    <td>process all specified files using a single <kbd>chmod</kbd> command.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">One of <i>file</i>, <i>dir</i> or
-      <i>both</i>. If set to <i>file</i>, only the permissions of
-      plain files are going to be changed. If set to <i>dir</i>, only
-      the directories are considered.<br>
-      <strong>Note:</strong> The type attribute does not apply to
-      nested <i>dirset</i>s - <i>dirset</i>s always implicitly
-      assume type to be <i>dir</i>.</td>
-    <td align="center" valign="top">No, default is <i>file</i></td>
+    <td>type</td>
+    <td>One of <q>file</q>, <q>dir</q> or <q>both</q>. If set to <q>file</q>, only the permissions
+      of plain files are going to be changed. If set to <q>dir</q>, only the directories are
+      considered.<br/><strong>Note</strong>: The type attribute does not apply to
+      nested <code>dirset</code>s&mdash;<code>dirset</code>s always implicitly assume type to
+      be <q>dir</q>.</td>
+    <td>No; default is <q>file</q></td>
   </tr>
   <tr>
-    <td valign="top">maxparallel</td>
-    <td valign="top">Limit the amount of parallelism by passing at
-      most this many sourcefiles at once.  Set it to &lt;= 0 for
-      unlimited.  Defaults to unlimited.  <em>Since Ant 1.6.</em></td>
-    <td align="center" valign="top">No</td>
+    <td>maxparallel</td>
+    <td>Limit the amount of parallelism by passing at most this many sourcefiles at once.  Set it to
+      negative integer for unlimited.  <em>Since Ant 1.6</em>.</td>
+    <td>No; defaults to unlimited</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to print a summary after execution or not.
-      Defaults to <code>false</code>.  <em>Since Ant 1.6.</em></td>
-    <td align="center" valign="top">No</td>
+    <td>verbose</td>
+    <td>Whether to print a summary after execution or not.  <em>Since Ant 1.6</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">os</td>
-    <td valign="top">list of Operating Systems on which the command may be
-      executed.</td>
-    <td align="center" valign="top">No</td>
+    <td>os</td>
+    <td>list of Operating Systems on which the command may be executed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">osfamily</td>
-    <td valign="top">OS family as used in
-      the <a href="conditions.html#os">&lt;os&gt;</a> condition.</td>
-    <td align="center" valign="top">No - defaults to "unix"</td>
+    <td>osfamily</td>
+    <td>OS family as used in the <a href="conditions.html#os">&lt;os&gt;</a> condition.</td>
+    <td>No; defaults to <q>unix</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-  <blockquote><pre>
-&lt;chmod file=&quot;${dist}/start.sh&quot; perm=&quot;ugo+rx&quot;/&gt;
-</pre></blockquote>
-<p>makes the &quot;start.sh&quot; file readable and executable for anyone on a
+
+<p>Make the <samp>start.sh</samp> file readable and executable for anyone on a UNIX system.</p>
+<pre>&lt;chmod file=&quot;${dist}/start.sh&quot; perm=&quot;ugo+rx&quot;/&gt;</pre>
+
+<p>Make the <samp>start.sh</samp> file readable, writable and executable only for the owner on a
 UNIX system.</p>
-<blockquote><pre>
-&lt;chmod file=&quot;${dist}/start.sh&quot; perm=&quot;700&quot;/&gt;
-</pre></blockquote>
-<p>makes the &quot;start.sh&quot; file readable, writable and executable only for the owner on a
-UNIX system.</p>
-<blockquote>
+<pre>&lt;chmod file=&quot;${dist}/start.sh&quot; perm=&quot;700&quot;/&gt;</pre>
+
+<p>Make all <samp>.sh</samp> files below <samp>${dist}/bin</samp> readable and executable for anyone
+on a UNIX system.</p>
 <pre>
-&lt;chmod dir=&quot;${dist}/bin&quot; perm=&quot;ugo+rx&quot; 
-       includes=&quot;**/*.sh&quot;/&gt;
-</pre>
-</blockquote>
-<p>makes all &quot;.sh&quot; files below <code>${dist}/bin</code>
-readable and executable for anyone on a UNIX system.</p>
-<blockquote>
+&lt;chmod dir=&quot;${dist}/bin&quot; perm=&quot;ugo+rx&quot;
+       includes=&quot;**/*.sh&quot;/&gt;</pre>
+
+<p>Make all files below <samp>shared/sources1</samp> (except those below any directory
+named <samp>trial</samp>) writable for members of the same group on a UNIX system. In addition, all
+files belonging to a FileSet with <var>id</var> <samp>other.shared.sources</samp> get the same
+permissions.</p>
 <pre>
 &lt;chmod perm=&quot;g+w&quot;&gt;
   &lt;fileset dir=&quot;shared/sources1&quot;&gt;
     &lt;exclude name=&quot;**/trial/**&quot;/&gt;
   &lt;/fileset&gt;
   &lt;fileset refid=&quot;other.shared.sources&quot;/&gt;
-&lt;/chmod&gt;
-</pre>
-</blockquote>
-<p>makes all files below <code>shared/sources1</code> (except those
-below any directory named trial) writable for members of the same
-group on a UNIX system. In addition all files belonging to a FileSet
-with <code>id</code> <code>other.shared.sources</code> get the same
-permissions.</p>
+&lt;/chmod&gt;</pre>
 
-<blockquote>
+<p>Keep non-owners from touching <code>cgi</code> scripts, files with a <samp>.old</samp> extension
+or directories beginning with <samp>private_</samp>. A directory ending in <samp>.old</samp> or a
+file beginning with <samp>private_</samp> would remain unaffected.</p>
 <pre>
 &lt;chmod perm=&quot;go-rwx&quot; type=&quot;file&quot;&gt;
   &lt;fileset dir=&quot;/web&quot;&gt;
@@ -196,30 +176,14 @@
   &lt;dirset dir=&quot;/web&quot;&gt;
     &lt;include name=&quot;**/private_*&quot;/&gt;
   &lt;/dirset&gt;
-&lt;/chmod&gt;
-</pre>
-</blockquote>
+&lt;/chmod&gt;</pre>
 
-<p>keeps non-owners from touching cgi scripts, files with a <code>.old</code>
-extension or directories beginning with <code>private_</code>. A directory 
-ending in <code>.old</code> or a file beginning with private_ would remain
-unaffected.</p>
-
-
-  <h3>Note on maxparallel attribute</h3>
-  <p>
-    Some shells have a limit of the number of characters that
-    a command line may contain. 
-    This maximum limit varies from shell to shell and from operating
-    system to operating system.
-    If one has a large number of files to change mode on, consider
-    using the <em>maxparallel</em> attribute. For example
-    when using AIX and the limit is reached, the system responds
-    with a warning: "Warning: 
-    UNIXProcess.forkAndExec native error: The parameter or environment lists
-    are too long". A value of about 300 seems to result in a
-    command line that is acceptable.
-  </p>
+<h3>Note on <var>maxparallel</var> attribute</h3>
+<p>Some shells have a limit of the number of characters that a command line may contain.  This
+maximum limit varies from shell to shell and from operating system to operating system.  If one has
+a large number of files to change mode on, consider using the <var>maxparallel</var> attribute. For
+example when using AIX and the limit is reached, the system responds with a warning: <code>"Warning:
+UNIXProcess.forkAndExec native error: The parameter or environment lists are too long"</code>. A
+value of about 300 seems to result in a command line that is acceptable.</p>
 </body>
 </html>
-
diff --git a/manual/Tasks/chown.html b/manual/Tasks/chown.html
index 33a9f44..5bd8f94 100644
--- a/manual/Tasks/chown.html
+++ b/manual/Tasks/chown.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,150 +15,127 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Chown Task</title>
 </head>
 
 <body>
 
-<h2><a name="Chown">Chown</a></h2>
-<p><em>Since Apache Ant 1.6.</em></p>
+<h2 id="chown">Chown</h2>
+<p><em>Since Apache Ant 1.6</em>.</p>
 <h3>Description</h3>
 
-<p>Changes the owner of a file or all files inside specified
-directories. Right now it has effect only under Unix.  The owner
-attribute is equivalent to the corresponding argument for the chown
-command.</p>
+<p>Changes the owner of a file or all files inside specified directories. Right now it has effect
+only under Unix.  The owner attribute is equivalent to the corresponding argument for
+the <kbd>chown</kbd> command.</p>
 
-<p><a href="../Types/fileset.html">FileSet</a>s, 
-<a href="../Types/dirset.html">DirSet</a>s or <a
-href="../Types/filelist.html">FileList</a>s can be specified using
-nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and 
-<code>&lt;filelist&gt;</code> elements.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s, <a href="../Types/dirset.html">DirSet</a>s
+or <a href="../Types/filelist.html">FileList</a>s can be specified using
+nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and <code>&lt;filelist&gt;</code>
+elements.</p>
 
-<p>Starting with Ant 1.7, this task supports arbitrary <a
-href="../Types/resources.html#collection">Resource Collection</a>s
-as nested elements.</p>
+<p><em>Since Ant 1.7</em>, this task supports
+arbitrary <a href="../Types/resources.html#collection">resource collections</a> as nested
+elements.</p>
 
-<p>By default this task will use a single invocation of the underlying
-chown command.  If you are working on a large number of files this may
-result in a command line that is too long for your operating system.
-If you encounter such problems, you should set the maxparallel
-attribute of this task to a non-zero value.  The number to use highly
-depends on the length of your file names (the depth of your directory
-tree) and your operating system, so you'll have to experiment a
-little.  POSIX recommends command line length limits of at least 4096
-characters, this may give you an approximation for the number you
-could use as initial value for these experiments.</p>
+<p>By default this task will use a single invocation of the underlying <kbd>chown</kbd> command.
+If you are working on a large number of files this may result in a command line that is too long for
+your operating system.  If you encounter such problems, you should set the <var>maxparallel</var>
+attribute of this task to a non-zero value.  The number to use highly depends on the length of your
+file names (the depth of your directory tree) and your operating system, so you'll have to
+experiment a little.  POSIX recommends command line length limits of at least 4096 characters, this
+may give you an approximation for the number you could use as initial value for these
+experiments.</p>
 
-<p>By default this task won't do anything unless it detects it is
-  running on a Unix system.  If you know for sure that you have a
-  "chown" executable on your PATH that is command line compatible with
-  the Unix command, you can use the task's os attribute and set its
-  value to your current os.</p>
+<p>By default this task won't do anything unless it detects it is running on a Unix system.  If you
+know for sure that you have a <kbd>chown</kbd> executable on your <code>PATH</code> that is command
+line compatible with the Unix command, you can use the task's <var>os</var> attribute and set its
+value to your current OS.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file or directory of which the owner must be
+    <td>file</td>
+    <td>the file or directory of which the owner must be
     changed.</td>
-    <td valign="top" valign="middle">Yes or nested
-    <code>&lt;fileset/list&gt;</code> elements.</td>
+    <td>Yes, unless nested <code>&lt;fileset|filelist|dirset&gt;</code> elements are specified</td>
   </tr>
   <tr>
-    <td valign="top">owner</td>
-    <td valign="top">the new owner.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>owner</td>
+    <td>the new owner.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">parallel</td>
-    <td valign="top">process all specified files using a single
-      <code>chown</code> command. Defaults to true.</td>
-    <td valign="top" align="center">No</td>
+    <td>parallel</td>
+    <td>process all specified files using a single <kbd>chown</kbd> command.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">One of <i>file</i>, <i>dir</i> or
-      <i>both</i>. If set to <i>file</i>, only the owner of
-      plain files are going to be changed. If set to <i>dir</i>, only
-      the directories are considered.<br>
-      <strong>Note:</strong> The type attribute does not apply to
-      nested <i>dirset</i>s - <i>dirset</i>s always implicitly
-      assume type to be <i>dir</i>.</td>
-    <td align="center" valign="top">No, default is <i>file</i></td>
+    <td>type</td>
+    <td>One of <q>file</q>, <q>dir</q> or <q>both</q>. If set to <q>file</q>, only the owner of
+      plain files are going to be changed. If set to <q>dir</q>, only the directories are
+      considered.<br/><strong>Note</strong>: The <var>type</var> attribute does not apply to
+      nested <code>dirset</code>s&mdash;<code>dirset</code>s always implicitly assume type to
+      be <q>dir</q>.</td>
+    <td>No; default is <q>file</q></td>
   </tr>
   <tr>
-    <td valign="top">maxparallel</td>
-    <td valign="top">Limit the amount of parallelism by passing at
-      most this many sourcefiles at once.  Set it to &lt;= 0 for
-      unlimited.  Defaults to unlimited.</td>
-    <td align="center" valign="top">No</td>
-
+    <td>maxparallel</td>
+    <td>Limit the amount of parallelism by passing at most this many sourcefiles at once.  Set it to
+      negative integer for unlimited.</td>
+    <td>No; defaults to unlimited</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to print a summary after execution or not.
-      Defaults to <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>verbose</td>
+    <td>Whether to print a summary after execution or not.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">os</td>
-    <td valign="top">list of Operating Systems on which the command may be
-      executed.</td>
-    <td align="center" valign="top">No</td>
+    <td>os</td>
+    <td>list of Operating Systems on which the command may be executed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">osfamily</td>
-    <td valign="top">OS family as used in
-      the <a href="../Tasks/conditions.html#os">&lt;os&gt;</a>
+    <td>osfamily</td>
+    <td>OS family as used in the <a href="../Tasks/conditions.html#os">&lt;os&gt;</a>
       condition.</td>
-    <td align="center" valign="top">No - defaults to "unix"</td>
+    <td>No; defaults to <q>unix</q></td>
   </tr>
-
 </table>
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;chown file="${dist}/start.sh" owner="coderjoe"/&gt;
-</pre>
-</blockquote>
-<p>makes the "start.sh" file belong to coderjoe on a
-UNIX system.</p>
-<blockquote>
+
+<p>Make the <samp>start.sh</samp> file belong to <samp>coderjoe</samp> on a UNIX system.</p>
+<pre>&lt;chown file="${dist}/start.sh" owner="coderjoe"/&gt;</pre>
+
+<p>Make all <samp>.sh</samp> files below <samp>${dist}/bin</samp> belong to <samp>coderjoe</samp> on
+a UNIX system.</p>
 <pre>
-    &lt;chown owner="coderjoe"&gt;
-      &lt;fileset dir="${dist}/bin" includes="**/*.sh"/&gt;
-    &lt;/chown&gt;
-</pre>
-</blockquote>
-<p>makes all ".sh" files below <code>${dist}/bin</code>
-belong to coderjoe on a UNIX system.</p>
-<blockquote>
+&lt;chown owner="coderjoe"&gt;
+  &lt;fileset dir="${dist}/bin" includes="**/*.sh"/&gt;
+&lt;/chown&gt;</pre>
+
+<p>Make all files below <samp>shared/sources1</samp> (except those below any directory
+named <samp>trial</samp>) belong to <samp>coderjoe</samp> on a UNIX system. In addition, all files
+belonging to a FileSet with <var>id</var>=<code>other.shared.sources</code> get the same owner.</p>
 <pre>
 &lt;chown owner="coderjoe"&gt;
   &lt;fileset dir="shared/sources1"&gt;
     &lt;exclude name="**/trial/**"/&gt;
   &lt;/fileset&gt;
   &lt;fileset refid="other.shared.sources"/&gt;
-&lt;/chown&gt;
-</pre>
-</blockquote>
-<p>makes all files below <code>shared/sources1</code> (except those
-below any directory named trial) belong to coderjoe on a UNIX 
-system. In addition all files belonging to a FileSet
-with <code>id</code> <code>other.shared.sources</code> get the same
-owner.</p>
+&lt;/chown&gt;</pre>
 
-<blockquote>
+<p>Make <samp>cgi</samp> scripts, files with a <samp>.old</samp> extension or directories beginning
+with <samp>private_</samp> belong to the user named <samp>webadmin</samp>. A directory ending
+in <samp>.old</samp> or a file beginning with <samp>private_</samp> would remain unaffected.</p>
 <pre>
 &lt;chown owner="webadmin" type="file"&gt;
   &lt;fileset dir="/web"&gt;
@@ -167,17 +145,7 @@
   &lt;dirset dir="/web"&gt;
     &lt;include name="**/private_*"/&gt;
   &lt;/dirset&gt;
-&lt;/chmod&gt;
-</pre>
-</blockquote>
-
-<p>makes cgi scripts, files with a <code>.old</code> extension or
-directories beginning with <code>private_</code> belong to the user named
-webadmin. A directory ending in <code>.old</code> or a file beginning with 
-<code>private_</code> would remain unaffected.</p>
-
-
+&lt;/chmod&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/clearcase.html b/manual/Tasks/clearcase.html
index 902d5ef..c3ca41f 100644
--- a/manual/Tasks/clearcase.html
+++ b/manual/Tasks/clearcase.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,86 +15,80 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-  <title>Clearcase Tasks</title>
+  <title>ClearCase Tasks</title>
 </head>
 
 <body>
 <h1>Apache Ant ClearCase Tasks</h1>
-<p>by:<br>
-Curtis White (cwhite at aracnet dot com),<br>
-Sean P. Kane (spkane at genomatica dot com),<br>
-Rob Anderson (Anderson.Rob at vectorscm dot com), and<br>
+<p>by:<br/>
+Curtis White (cwhite at aracnet dot com),<br/>
+Sean P. Kane (spkane at genomatica dot com),<br/>
+Rob Anderson (Anderson.Rob at vectorscm dot com), and<br/>
 Sean Egan    (sean at cm-logic dot com)</p>
 
-<p>Version 1.6 - 02/25/2003</p>
+<p>Version 1.6&mdash;02/25/2003</p>
 
 <h1>ClearCase Support</h1>
 <h2>Table of Contents</h2>
 <ul>
-  <li><A href="#introduction">Introduction</a>
-  <li><A href="#cccheckin">CCCheckin</a>
-  <li><A href="#cccheckout">CCCheckout</a>
-  <li><A href="#ccuncheckout">CCUnCheckout</a>
-  <li><A href="#ccupdate">CCUpdate</a>
-  <li><A href="#ccmklbtype">CCMklbtype</a>
-  <li><A href="#ccmklabel">CCMklabel</a>
-  <li><A href="#ccrmtype">CCRmtype</a>
-  <li><A href="#cclock">CCLock</a>
-  <li><A href="#ccunlock">CCUnlock</a>
-  <li><A href="#ccmkbl">CCMkbl</a>
-  <li><A href="#ccmkattr">CCMkattr</a>
-  <li><A href="#ccmkdir">CCMkdir</a>
-  <li><A href="#ccmkelem">CCMkelem</a></li>
+  <li><a href="#introduction">Introduction</a>
+  <li><a href="#cccheckin">CCCheckin</a>
+  <li><a href="#cccheckout">CCCheckout</a>
+  <li><a href="#ccuncheckout">CCUnCheckout</a>
+  <li><a href="#ccupdate">CCUpdate</a>
+  <li><a href="#ccmklbtype">CCMklbtype</a>
+  <li><a href="#ccmklabel">CCMklabel</a>
+  <li><a href="#ccrmtype">CCRmtype</a>
+  <li><a href="#cclock">CCLock</a>
+  <li><a href="#ccunlock">CCUnlock</a>
+  <li><a href="#ccmkbl">CCMkbl</a>
+  <li><a href="#ccmkattr">CCMkattr</a>
+  <li><a href="#ccmkdir">CCMkdir</a>
+  <li><a href="#ccmkelem">CCMkelem</a></li>
 
 </ul>
 
-<hr>
-<h2><a name="introduction">Introduction</a></h2>
-<p>Apache Ant provides several optional tasks for working with ClearCase. These tasks correspond to various
-ClearCase commands using the Cleartool program. The current tasks available for Ant correspond to only
-a few of the significant ClearCase commands.</p>
+<hr/>
+<h2 id="introduction">Introduction</h2>
+<p>Apache Ant provides several optional tasks for working with ClearCase. These tasks correspond to
+various ClearCase commands using the <kbd>cleartool</kbd> program. The current tasks available for
+Ant correspond to only a few of the significant ClearCase commands.</p>
 
-<p>More tasks can be easily added by deriving from the ClearCase class and then adding
-functionality that is specific to that ClearCase command.</p>
-<p>
-    Important: these tasks all require <code>cleartool</code> on the command line.
-    If a task fails with an IOException, especially error code 2 on Windows,
-    this is your problem.
-</p>
+<p>More tasks can be easily added by deriving from the ClearCase class and then adding functionality
+that is specific to that ClearCase command.</p>
+<p>Important: these tasks all require <kbd>cleartool</kbd> on the command line.  If a task fails
+with an <code>IOException</code>, especially <code>error=2</code> on Windows, this is your
+problem.</p>
 
+<hr/>
 
-<hr>
-<h2><a name="cccheckin">CCCheckin</a></h2>
+<h2 id="cccheckin">CCCheckin</h2>
 <h3>Description</h3>
-Task to perform a "cleartool checkin" command to ClearCase.
+<p>Task to perform a <kbd>cleartool checkin</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>viewpath</td>
-    <td>Path to the ClearCase view file or directory that the command
-        will operate on</td>
+    <td>Path to the ClearCase view file or directory that the command will operate on</td>
     <td>No</td>
   </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment. Only one of comment or commentfile may be used.</td>
-    <td>No</td>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
   </tr>
   <tr>
     <td>commentfile</td>
-    <td>Specify a file containing a comment. Only one of comment or commentfile
-        may be used.</td>
-    <td>No</td>
+    <td class="left">Specify a file containing a comment</td>
   </tr>
   <tr>
     <td>nowarn</td>
@@ -107,49 +102,47 @@
   </tr>
   <tr>
     <td>keepcopy</td>
-    <td>Keeps a copy of the file with a .keep extension</td>
+    <td>Keeps a copy of the file with a <samp>.keep</samp> extension</td>
     <td>No</td>
   </tr>
   <tr>
     <td>identical</td>
-    <td>Allows the file to be checked in even if it is identical
-        to the original</td>
+    <td>Allows the file to be checked in even if it is identical to the original</td>
     <td>No</td>
   </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails</td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>checkin</code> on the file <samp>c:/views/viewdir/afile</samp>. Comment
+text from the file <samp>acomment.txt</samp> is added to ClearCase as a comment. All warning
+messages are suppressed. The file is checked in even if it is <em>identical</em> to the
+original.</p>
 <pre>
 &lt;cccheckin viewpath="c:/views/viewdir/afile"
-        commentfile="acomment.txt"
-        nowarn="true"
-        identical="true"/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>checkin</i> on the file <i>c:/views/viewdir/afile</i>.
-Comment text from the file <i>acomment.txt</i> is added to ClearCase as a comment.
-All warning messages are suppressed. The file is checked in even if it is
-<i>identical</i> to the original.</p>
-<hr>
-<h2><a name="cccheckout">CCCheckout</a></h2>
+           commentfile="acomment.txt"
+           nowarn="true"
+           identical="true"/&gt;</pre>
+
+<hr/>
+
+<h2 id="cccheckout">CCCheckout</h2>
 <h3>Description</h3>
-Task to perform a "cleartool checkout" command to ClearCase.
+<p>Task to perform a <kbd>cleartool checkout</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>viewpath</td>
-    <td>Path to the ClearCase view file or directory that the command
-        will operate on</td>
+    <td>Path to the ClearCase view file or directory that the command will operate on</td>
     <td>No</td>
   </tr>
   <tr>
@@ -164,8 +157,7 @@
   </tr>
   <tr>
     <td>nodata</td>
-    <td>Checks out the file but does not create an editable file
-        containing its data</td>
+    <td>Checks out the file but does not create an editable file containing its data</td>
     <td>No</td>
   </tr>
   <tr>
@@ -175,7 +167,8 @@
   </tr>
   <tr>
     <td>version</td>
-    <td>Allows checkout of a version other than main latest</td>
+    <td>Allows checkout of a version other than <code>/main/LATEST</code> (or whatever is selected
+    by a config spec)</td>
     <td>No</td>
   </tr>
   <tr>
@@ -185,96 +178,86 @@
   </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment. Only one of comment or commentfile may be used.</td>
-    <td>No</td>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
   </tr>
   <tr>
     <td>commentfile</td>
-    <td>Specify a file containing a comment. Only one of comment or
-        commentfile may be used.</td>
-    <td>No</td>
+    <td class="left">Specify a file containing a comment</td>
   </tr>
   <tr>
     <td>notco</td>
-    <td>Fail if it's already checked out to the current view. Set to false to ignore it.<br>
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Fail if it's already checked out to the current view. Set to <q>false</q> to ignore
+    it.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true.<br>
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>checkout</code> on the file <samp>c:/views/viewdir/afile</samp>. It is
+checked out as <em>reserved</em> on branch called <samp>abranch</samp>. All warning messages are
+suppressed. A &quot;<samp>Some comment text</samp>&quot; is added to ClearCase as a comment.</p>
 <pre>
 &lt;cccheckout viewpath="c:/views/viewdir/afile"
-        reserved="true"
-        branch="abranch"
-        nowarn="true"
-        comment="Some comment text"/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>checkout</i> on the file <i>c:/views/viewdir/afile</i>.
-It is checked out as <i>reserved</i> on branch called <i>abranch</i>. All
-warning messages are suppressed. A <i>Some comment text</i> is added to
-ClearCase as a comment.</p>
-<hr>
-<h2><a name="ccuncheckout">CCUnCheckout</a></h2>
+            reserved="true"
+            branch="abranch"
+            nowarn="true"
+            comment="Some comment text"/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccuncheckout">CCUnCheckout</h2>
 <h3>Description</h3>
-Task to perform a UnCheckout command to ClearCase.
+<p>Task to perform a <kbd>cleartool uncheckout</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>viewpath</td>
-    <td>Path to the ClearCase view file or directory that the command
-        will operate on</td>
+    <td>Path to the ClearCase view file or directory that the command will operate on</td>
     <td>No</td>
   </tr>
   <tr>
     <td>keepcopy</td>
-    <td>Specifies whether to keep a copy of the file with a .keep
-        extension or not</td>
+    <td>Specifies whether to keep a copy of the file with a <samp>.keep</samp> extension or not</td>
     <td>No</td>
   </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true<br>
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;ccuncheckout viewpath="c:/views/viewdir/afile"
-        keepcopy="true"/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>uncheckout</i> on the file <i>c:/views/viewdir/afile</i>.
-A copy of the file called <i>c:/views/viewdir/afile.keep</i> is kept.</p>
-<hr>
-<h2><a name="ccupdate">CCUpdate</a></h2>
+
+<p>Perform a ClearCase <code>uncheckout</code> on the file <samp>c:/views/viewdir/afile</samp>. A
+copy of the file named <samp>c:/views/viewdir/afile.keep</samp> is kept.</p>
+<pre>&lt;ccuncheckout viewpath="c:/views/viewdir/afile" keepcopy="true"/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccupdate">CCUpdate</h2>
 <h3>Description</h3>
-Task to perform an "cleartool update" command to ClearCase.
+<p>Task to perform an <kbd>cleartool update</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>viewpath</td>
-    <td>Path to the ClearCase snapshot view file or directory that the command
-        will operate on</td>
+    <td>Path to the ClearCase snapshot view file or directory that the command will operate on</td>
     <td>No</td>
   </tr>
   <tr>
@@ -294,665 +277,629 @@
   </tr>
   <tr>
     <td>rename</td>
-    <td>Specifies that hijacked files should be renamed with a .keep extension</td>
+    <td>Specifies that hijacked files should be renamed with a <samp>.keep</samp> extension</td>
     <td>No</td>
   </tr>
   <tr>
     <td>currenttime</td>
-    <td>Specifies that modification time should be written as the
-        current time. Either currenttime or preservetime can be
-        specified.</td>
+    <td>Specifies that modification time should be written as the current time. Mutually exclusive
+    with <var>preservetime</var>.</td>
     <td>No</td>
   </tr>
   <tr>
     <td>preservetime</td>
-    <td>Specifies that modification time should preserved from the
-        VOB time. Either currenttime or preservetime can be
-        specified.</td>
+    <td>Specifies that modification time should preserved from the VOB time. Mutually exclusive
+    with <var>currenttime</var>.</td>
     <td>No</td>
   </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true.<br>
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails.<br/>  <em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>update</code> on the snapshot view
+directory <samp>c:/views/viewdir</samp>. A graphical dialog will be displayed. The output will be
+logged to <samp>log.log</samp> and it will overwrite any hijacked files. The modified time will be
+set to the current time.</p>
 <pre>
 &lt;ccupdate viewpath="c:/views/viewdir"
-        graphical="false"
-        log="log.log"
-        overwrite="true"
-        currenttime="true"
-        rename="false"/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>update</i> on the snapshot view directory <i>c:/views/viewdir</i>.
-A graphical dialog will be displayed. The output will be logged to
-<i>log.log</i> and it will overwrite any hijacked files. The modified
-time will be set to the current time.</p>
+          graphical="false"
+          log="log.log"
+          overwrite="true"
+          currenttime="true"
+          rename="false"/&gt;</pre>
 
+<hr/>
 
-
-<hr>
-<h2><a name="ccmklbtype">CCMklbtype</a></h2>
+<h2 id="ccmklbtype">CCMklbtype</h2>
 <h3>Description</h3>
-Task to perform a "mklbtype" command to ClearCase.
+<p>Task to perform a <kbd>cleartool mklbtype</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>typename</td>
     <td>Name of the label type to create</td>
     <td>Yes</td>
-  <tr>
+  </tr>
   <tr>
     <td>vob</td>
     <td>Name of the VOB</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>replace</td>
     <td>Replace an existing label definition of the same type</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>global</td>
-    <td>Either global or ordinary can be specified, not both. Creates a label type that is global to the VOB or to VOBs that use this VOB</td>
-    <td>No</td>
-  <tr>
+    <td>Creates a label type that is global to the VOB or to VOBs that use this VOB.</td>
+    <td rowspan="2">No; only one of the two may be used,
+    default <var>ordinary</var>=<q>true</q></td>
+  </tr>
   <tr>
     <td>ordinary</td>
-    <td>Either global or ordinary can be specified, not both. Creates a label type that can be used only in the current VOB. <B>Default</B></td>
-    <td>No</td>
-  <tr>
+    <td class="left">Creates a label type that can be used only in the current VOB.</td>
+  </tr>
   <tr>
     <td>pbranch</td>
     <td>Allows the label type to be used once per branch in a given element's version tree</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>shared</td>
-    <td>Sets the way mastership is checked by ClearCase. See ClearCase documentation for details</td>
+    <td>Sets the way mastership is checked by ClearCase. See ClearCase documentation for
+    details</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment. Only one of comment or cfile may be used.</td>
-    <td>No</td>
-  <tr>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
   <tr>
     <td>commentfile</td>
-    <td>Specify a file containing a comment. Only one of comment or cfile may be used.</td>
-    <td>No</td>
-  <tr></tr>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true<br>
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>mklbtype</code> to create a label type named <samp>VERSION_1</samp>. It
+is created as <em>ordinary</em> so it is available only to the current VOB. The text <q>Development
+version 1</q> is added as a comment.</p>
 <pre>
 &lt;ccmklbtype typename="VERSION_1"
-        ordinary="true"
-        comment="Development version 1"/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>mklbtype</i> to create a label type named <i>VERSION_1</i>.
-It is created as <i>ordinary</i> so it is available only to the current VOB.
-The text <i>Development version 1</i> is added as a comment.</p>
+            ordinary="true"
+            comment="Development version 1"/&gt;</pre>
 
+<hr/>
 
-<hr>
-<h2><a name="ccmklabel">CCMklabel</a></h2>
+<h2 id="ccmklabel">CCMklabel</h2>
 <h3>Description</h3>
-Task to perform a "mklabel" command to ClearCase.
+<p>Task to perform a <kbd>cleartool mklabel</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>typename</td>
     <td>Name of the label type</td>
     <td>Yes</td>
-  <tr>
+  </tr>
   <tr>
     <td>viewpath</td>
     <td>Path to the ClearCase view file or directory that the command will operate on</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>replace</td>
     <td>Replace a label of the same type on the same branch</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>recurse</td>
-    <td>Process each subdirectory under viewpath</td>
+    <td>Process each subdirectory under <var>viewpath</var></td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>version</td>
     <td>Identify a specific version to attach the label to</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>vob</td>
     <td>Name of the VOB</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment. Only one of comment or cfile may be used.</td>
-    <td>No</td>
-  <tr>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
   <tr>
     <td>commentfile</td>
-    <td>Specify a file containing a comment. Only one of comment or cfile may be used.</td>
-    <td>No</td>
-  <tr></tr>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true<br>
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>mklabel</code> on the file <samp>c:/views/viewdir/afile</samp> under
+the <samp>main</samp> branch for version 2 (<samp>\main\2</samp>). Text &quot;<samp>Some comment
+text</samp>&quot; is added as a comment. It will <em>recurse</em> all subdirectories.</p>
 <pre>
 &lt;ccmklabel viewpath="c:/views/viewdir/afile"
-        comment="Some comment text"
-        recurse="true"
-        version="\main\2"
-        typename="VERSION_1"/&gt;
+           comment="Some comment text"
+           recurse="true"
+           version="\main\2"
+           typename="VERSION_1"/&gt;
 </pre>
-</blockquote>
-<p>Does a ClearCase <i>mklabel</i> on the file <i>c:/views/viewdir/afile</i> under
-the main branch for version 2 (<i>\main\2</i>). Text <i>Some comment text</i> is added
-as a comment. It will <i>recurse</i> all subdirectories.
 
+<hr/>
 
-<hr>
-<h2><a name="ccrmtype">CCRmtype</a></h2>
+<h2 id="ccrmtype">CCRmtype</h2>
 <h3>Description</h3>
-Task to perform a "rmtype" command to ClearCase.
+<p>Task to perform a <kbd>cleartool rmtype</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
     <td>typekind</td>
     <td>The kind of type to create. Valid types are:
-      <table border="0" width="40%">
+      <table>
         <tr>
-          <td width="15%"> </td>
-          <td><b>attype</b><br>
-              <b>brtype</b><br>
-              <b>eltype</b><br>
-              <b>hltype</b><br>
-              <b>lbtype</b><br>
-              <b>trtype</b>
-          </td>
-          <td>- <br>
-              - <br>
-              - <br>
-              - <br>
-              - <br>
-              -
-          </td>
-          <td>attribute type<br>
-              branch type<br>
-              element type<br>
-              hyperlink type<br>
-              label type<br>
-              trigger type
-          </td>
+          <th scope="col">Kind</th>
+          <th scope="col">Description</th>
         </tr>
-      </table>
-    </td>
+        <tr>
+          <td><q>attype</q></td>
+          <td>attribute type</td>
+        </tr>
+        <tr>
+          <td><q>brtype</q></td>
+          <td>branch type</td>
+        </tr>
+        <tr>
+          <td><q>eltype</q></td>
+          <td>element type</td>
+        </tr>
+        <tr>
+          <td><q>hltype</q></td>
+           <td>hyperlink type</td>
+        </tr>
+        <tr>
+          <td><q>lbtype</q></td>
+          <td>label type</td>
+        </tr>
+        <tr>
+          <td><q>trtype</q></td>
+          <td>trigger type</td>
+        </tr>
+      </table></td>
     <td>Yes</td>
-  <tr>
+  </tr>
   <tr>
     <td>typename</td>
     <td>The name of the type to remove</td>
     <td>Yes</td>
-  <tr>
+  </tr>
   <tr>
     <td>ignore</td>
-    <td>Used with trigger types only. Forces removal of trigger type even if a pre-operation trigger would prevent its removal</td>
+    <td>Used with trigger types only. Forces removal of trigger type even if a pre-operation trigger
+    would prevent its removal</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>rmall</td>
     <td>Removes all instances of a type and the type object itself</td>
     <td>No</td>
-  <tr>
+  </tr>
   <tr>
     <td>comment</td>
-    <td>Specify a comment. Only one of comment or cfile may be used.</td>
-    <td>No</td>
-  <tr>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
   <tr>
     <td>commentfile</td>
-    <td>Specify a file containing a comment. Only one of comment or cfile may be used.</td>
-    <td>No</td>
-  <tr></tr>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
   <tr>
     <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true
-    Since ant 1.6.1</td>
-    <td>No</td>
+    <td>Throw an exception if the command fails.  <em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>rmtype</code> to remove a label type (<q>lbtype</q>)
+named <samp>VERSION_1</samp>. Comment text from the file <samp>acomment.txt</samp> is added as a
+comment. All instances of the type are removed, including the type object itself.</p>
 <pre>
 &lt;ccrmtype typekind="lbtype"
-        typename="VERSION_1"
-        commentfile="acomment.txt"
-        rmall="true"/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>rmtype</i> to remove a label type (<i>lbtype</i>) named <i>VERSION_1</i>.
-Comment text from the file <i>acomment.txt</i> is added as a comment. All instances of the type
-are removed, including the type object itself.</p>
-<hr>
+          typename="VERSION_1"
+          commentfile="acomment.txt"
+          rmall="true"/&gt;</pre>
 
-<h2><a name="cclock">CCLock</a></h2>
+<hr/>
+
+<h2 id="cclock">CCLock</h2>
 <h3>Description</h3>
-Task to perform a "cleartool lock" command to ClearCase.
+<p>Task to perform a <kbd>cleartool lock</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
- <table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
-   <tr>
-      <td>replace</td>
-      <td>Specifies replacing an existing lock</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>nusers</td>
-      <td>Specifies user(s) who can still modify the object</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>obsolete</td>
-      <td>Specifies that the object should be marked obsolete</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>comment</td>
-      <td>Specifies how to populate comments fields</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>pname</td>
-      <td>Specifies the object pathname to be locked.</td>
-      <td>No</td>
-   <tr>
-      <td>objselect</td>
-      <td>This variable is obsolete. Should use <i>objsel</i> instead.</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>objsel</td>
-      <td>Specifies the object(s) to be locked.<br>
-      Since ant 1.6.1</td>
-      <td>No</td>
-   <tr>
+<table class="attr">
   <tr>
-    <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true.<br>
-    Since ant 1.6.1</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>replace</td>
+    <td>Specifies replacing an existing lock</td>
     <td>No</td>
   </tr>
-
- </table>
-<h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;cclock
-    objsel="stream:Application_Integration@\MyProject_PVOB"
-    /&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>lock</i> on the object <i>stream:Application_Integration@\MyProject_PVOB</i>.</p>
-<hr>
-
-<h2><a name="ccunlock">CCUnlock</a></h2>
-<h3>Description</h3>
-Task to perform a "cleartool unlock" command to ClearCase.
-<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
-   <tr>
-      <td>comment</td>
-      <td>Specifies how to populate comments fields</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>pname</td>
-      <td>Specifies the object pathname to be unlocked.</td>
-      <td>No</td>
-   <tr>
-      <td>objselect</td>
-      <td>This variable is obsolete. Should use <i>objsel</i> instead.</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>objsel</td>
-      <td>Specifies the object(s) to be unlocked.<br>
-      Since ant 1.6.1</td>
-      <td>No</td>
-   <tr>
   <tr>
-    <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true.<br>
-    Since ant 1.6.1</td>
+    <td>nusers</td>
+    <td>Specifies user(s) who can still modify the object</td>
     <td>No</td>
   </tr>
-
- </table>
- <h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;ccunlock
-    objsel="stream:Application_Integration@\MyProject_PVOB"
-    /&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>unlock</i> on the object <i>stream:Application_Integration@\MyProject_PVOB</i>.</p>
-<hr>
-
-<h2><a name="ccmkbl">CCMkbl</a></h2>
-<h3>Description</h3>
-Task to perform a "cleartool mkbl" command to ClearCase.
-<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
-   <tr>
-      <td>comment</td>
-      <td>Specify a comment. Only one of comment or cfile may be
-used.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>commentfile</td>
-      <td>Specify a file containing a comment. Only one of comment or
-cfile may be used.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>baselinerootname</td>
-      <td>Specify the name to be associated with the baseline.</td>
-      <td>Yes</td>
-   </tr>
-   <tr>
-      <td>nowarn</td>
-      <td>Suppress warning messages</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>identical</td>
-      <td>Allows the baseline to be created even if it is identical to the
-previous baseline.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>full</td>
-      <td>Creates a full baseline.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>nlabel</td>
-      <td>Allows the baseline to be created without a label.</td>
-      <td>No</td>
-   </tr>
   <tr>
-    <td>failonerr</td>
-    <td>Throw an exception if the command fails. Default is true.<br>
-    Since ant 1.6.1</td>
+    <td>obsolete</td>
+    <td>Specifies that the object should be marked obsolete</td>
     <td>No</td>
   </tr>
- </table>
+  <tr>
+    <td>comment</td>
+    <td>Specifies how to populate comments fields</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>pname</td>
+    <td>Specifies the object pathname to be locked.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>objselect</td>
+    <td><em>Obsolete</em>. Use <var>objsel</var> instead.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>objsel</td>
+    <td>Specifies the object(s) to be locked.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerr</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+</table>
 <h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;ccmkbl
-    baselinerootname="Application_Baseline_AUTO"
-    identical="yes"
-    full="no"
-    viewpath="v:\ApplicationCC"
-    /&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>mkbl</i> on the Integration view at <i>v:\ApplicationCC</i>
-even if it is <i>identical</i> to a previous baseline. The new baseline with be
-incremental and named "Application_Baseline_AUTO".</p>
-<hr>
 
-<h2><a name="ccmkattr">CCMkattr</a></h2>
+<p>Perform a ClearCase <code>lock</code> on the
+object <samp>stream:Application_Integration@\MyProject_PVOB</samp>.</p>
+<pre>&lt;cclock objsel="stream:Application_Integration@\MyProject_PVOB"/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccunlock">CCUnlock</h2>
 <h3>Description</h3>
-Task to perform a &quot;cleartool mkattr&quot; command to ClearCase.<br>
-Since ant 1.6.1
+<p>Task to perform a <kbd>cleartool unlock</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
-   <tr>
-      <td>viewpath</td>
-      <td>Path to the ClearCase view file or directory that the command will operate on</td>
-      <td>Yes</td>
-   </tr>
-   <tr>
-      <td>replace</td>
-      <td>Replace the value of the attribute if it already exists</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>recurse</td>
-      <td>Process each subdirectory under viewpath</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>version</td>
-      <td>Identify a specific version to attach the attribute to</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>typename</td>
-      <td>Name of the attribute type</td>
-      <td>Yes</td>
-   </tr>
-   <tr>
-      <td>typevalue</td>
-      <td>Value to attach to the attribute type</td>
-      <td>Yes</td>
-   </tr>
-   <tr>
-      <td>comment</td>
-      <td>Specify a comment. Only one of comment or cfile may be used.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>commentfile</td>
-      <td>Specify a file containing a comment. Only one of comment or cfile may be used.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>failonerr</td>
-      <td>Throw an exception if the command fails. Default is true</td>
-      <td>No</td>
-   </tr>
- </table>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>Specifies how to populate comments fields</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>pname</td>
+    <td>Specifies the object pathname to be unlocked.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>objselect</td>
+    <td><em>Obsolete</em>. Use <var>objsel</var> instead.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>objsel</td>
+    <td>Specifies the object(s) to be unlocked.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerr</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+</table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>unlock</code> on the
+object <samp>stream:Application_Integration@\MyProject_PVOB</samp>.</p>
+<pre>&lt;ccunlock objsel="stream:Application_Integration@\MyProject_PVOB"/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccmkbl">CCMkbl</h2>
+<h3>Description</h3>
+<p>Task to perform a <kbd>cleartool mkbl</kbd> command to ClearCase.</p>
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
+  <tr>
+    <td>commentfile</td>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
+  <tr>
+    <td>baselinerootname</td>
+    <td>Specify the name to be associated with the baseline.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>nowarn</td>
+    <td>Suppress warning messages</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>identical</td>
+    <td>Allows the baseline to be created even if it is identical to the previous baseline.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>full</td>
+    <td>Creates a full baseline.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>nlabel</td>
+    <td>Allows the baseline to be created without a label.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerr</td>
+    <td>Throw an exception if the command fails.<br/><em>Since Ant 1.6.1</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+</table>
+<h3>Examples</h3>
+
+<p>Perform a ClearCase <code>mkbl</code> on the Integration view at <samp>v:\ApplicationCC</samp>
+even if it is <em>identical</em> to a previous baseline. The new baseline with be incremental and
+named <samp>Application_Baseline_AUTO</samp>.</p>
+<pre>
+&lt;ccmkbl baselinerootname="Application_Baseline_AUTO"
+        identical="yes"
+        full="no"
+        viewpath="v:\ApplicationCC"/&gt;</pre>
+
+<hr/>
+
+<h2 id="ccmkattr">CCMkattr</h2>
+<p><em>Since Ant 1.6.1</em></p>
+<h3>Description</h3>
+<p>Task to perform a <kbd>cleartool mkattr</kbd> command to ClearCase.</p>
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>viewpath</td>
+    <td>Path to the ClearCase view file or directory that the command will operate on</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>replace</td>
+    <td>Replace the value of the attribute if it already exists</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>recurse</td>
+    <td>Process each subdirectory under <var>viewpath</var></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>version</td>
+    <td>Identify a specific version to attach the attribute to</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>typename</td>
+    <td>Name of the attribute type</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>typevalue</td>
+    <td>Value to attach to the attribute type</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
+  <tr>
+    <td>commentfile</td>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
+  <tr>
+    <td>failonerr</td>
+    <td>Throw an exception if the command fails.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+</table>
+<h3>Examples</h3>
+
+<p>Perform a ClearCase <code>mkattr</code> on the file <samp>c:/views/viewdir/afile</samp> and
+attach the attribute <samp>BugFix</samp> with a value of <samp>34445</samp> to it.</p>
 <pre>
 &lt;ccmkattr viewpath=&quot;c:/views/viewdir/afile&quot;
-    typename=&quot;BugFix&quot;
-    typevalue=&quot;34445&quot;
-    /&gt;
+          typename=&quot;BugFix&quot;
+          typevalue=&quot;34445&quot;/&gt;
 </pre>
-</blockquote>
-<p>Does a ClearCase <i>mkattr</i> on the file <i>c:/views/viewdir/afile</i> and
-attaches the attribute <i>BugFix</i> with a value of <i>34445</i> to it.</p>
-<hr>
 
-<h2><a name="ccmkdir">CCMkdir</a></h2>
+<hr/>
+
+<h2 id="ccmkdir">CCMkdir</h2>
+<p><em>Since Ant 1.6.1</em></p>
 <h3>Description</h3>
-Task to perform a &quot;cleartool mkdir&quot; command to ClearCase.<br>
-Since ant 1.6.1
+<p>Task to perform a <kbd>cleartool mkdir</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
-   <tr>
-      <td>viewpath</td>
-      <td>Path to the ClearCase view directory that the command will operate on</td>
-      <td>Yes</td>
-   </tr>
-   <tr>
-      <td>comment</td>
-      <td>Specify a comment. Only one of comment or cfile may be used.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>commentfile</td>
-      <td>Specify a file containing a comment. Only one of comment or cfile may be used.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>nocheckout</td>
-      <td>Do not checkout after element creation</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>failonerr</td>
-      <td>Throw an exception if the command fails. Default is true</td>
-      <td>No</td>
-   </tr>
- </table>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>viewpath</td>
+    <td>Path to the ClearCase view directory that the command will operate on</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
+  <tr>
+    <td>commentfile</td>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
+  <tr>
+    <td>nocheckout</td>
+    <td>Do not checkout after element creation</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerr</td>
+    <td>Throw an exception if the command fails.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+</table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a ClearCase <code>mkdir</code> on the dir <samp>c:/views/viewdir/adir</samp> and do not
+automatically check it out.</p>
 <pre>
 &lt;ccmkdir viewpath=&quot;c:/views/viewdir/adir&quot;
-        nocheckout=&quot;true&quot;
-        comment=&quot;Some comment text&quot;/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>mkdir</i> on the dir <i>c:/views/viewdir/adir</i> and
-does not automatically check it out.</p>
-<hr>
+         nocheckout=&quot;true&quot;
+         comment=&quot;Some comment text&quot;/&gt;</pre>
 
-<h2><a name="ccmkelem">CCMkelem</a></h2>
+<hr/>
+
+<h2 id="ccmkelem">CCMkelem</h2>
+<p><em>Since Ant 1.6.1</em></p>
 <h3>Description</h3>
-Task to perform a &quot;cleartool mkelem&quot; command to ClearCase.<br>
-Since ant 1.6.1
+<p>Task to perform a <kbd>cleartool mkelem</kbd> command to ClearCase.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
-   <tr>
-      <td>viewpath</td>
-      <td>Path to the ClearCase view file or directory that the command will operate on</td>
-      <td>Yes</td>
-   <tr>
-   <tr>
-      <td>comment</td>
-      <td>Specify a comment. Only one of comment or cfile may be used.</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>commentfile</td>
-      <td>Specify a file containing a comment. Only one of comment or cfile may be used.</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>nowarn</td>
-      <td>Suppress warning messages</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>nocheckout</td>
-      <td>Do not checkout after element creation</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>checkin</td>
-      <td>Checkin element after creation</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>preservetime</td>
-      <td>Preserve the modification time (for checkin)</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>master</td>
-      <td>Assign mastership of the main branch to the current site</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>eltype</td>
-      <td>Element type to use during element creation</td>
-      <td>No</td>
-   <tr>
-   <tr>
-      <td>failonerr</td>
-      <td>Throw an exception if the command fails. Default is true</td>
-      <td>No</td>
-   <tr>
- </table>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>viewpath</td>
+    <td>Path to the ClearCase view file or directory that the command will operate on</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>Specify a comment</td>
+    <td rowspan="2">No; only one of the two may be used</td>
+  </tr>
+  <tr>
+    <td>commentfile</td>
+    <td class="left">Specify a file containing a comment</td>
+  </tr>
+  <tr>
+    <td>nowarn</td>
+    <td>Suppress warning messages</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>nocheckout</td>
+    <td>Do not checkout after element creation</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>checkin</td>
+    <td>Checkin element after creation</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>preservetime</td>
+    <td>Preserve the modification time (for checkin)</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>master</td>
+    <td>Assign mastership of the main branch to the current site</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>eltype</td>
+    <td>Element type to use during element creation</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerr</td>
+    <td>Throw an exception if the command fails.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+</table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform ClearCase <code>mkelem</code> on the file <samp>c:/views/viewdir/afile</samp> with
+element type <samp>text_file</samp>, check in the file after creation.</p>
 <pre>
 &lt;ccmkelem viewpath=&quot;c:/views/viewdir/afile&quot;
-        eltype=&quot;text_file&quot;
-        checkin=&quot;true&quot;
-        comment=&quot;Some comment text&quot;/&gt;
-</pre>
-</blockquote>
-<p>Does a ClearCase <i>mkelem</i> on the file <i>c:/views/viewdir/afile</i> with
-element type <i>text_file</i>. It also checks in the file after creation.</p>
+          eltype=&quot;text_file&quot;
+          checkin=&quot;true&quot;
+          comment=&quot;Some comment text&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/common.html b/manual/Tasks/common.html
index 6fa3418..1ad5f62 100644
--- a/manual/Tasks/common.html
+++ b/manual/Tasks/common.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,46 +15,42 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Common</title>
 </head>
 
 <body>
 
-<h2><a name="javac">Common Attributes of all Tasks</a></h2>
+<h2 id="javac">Common Attributes of all Tasks</h2>
 <p>All tasks share the following attributes:</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">id</td>
-    <td valign="top">Unique identifier for this task instance, can be
+    <td>id</td>
+    <td>Unique identifier for this task instance, can be
        used to reference this task in scripts.</td>
-    <td valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">taskname</td>
-    <td valign="top">A different name for this task instance - will
+    <td>taskname</td>
+    <td>A different name for this task instance&mdash;will
       show up in the logging output.</td>
-    <td valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">description</td>
-    <td valign="top">Room for your comments</td>
-    <td valign="top">No</td>
+    <td>description</td>
+    <td>Room for your comments</td>
+    <td>No</td>
   </tr>
 </table>
 
-
-
 </body>
 </html>
-
diff --git a/manual/Tasks/componentdef.html b/manual/Tasks/componentdef.html
index e28e681..27fd1f4 100644
--- a/manual/Tasks/componentdef.html
+++ b/manual/Tasks/componentdef.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,49 +15,36 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Componentdef Task</title>
 </head>
 
 <body>
 
-<h2><a name="componentdef">componentdef</a></h2>
+<h2 id="componentdef">componentdef</h2>
 <h3>Description</h3>
-  <p>
-    Adds a component definition to the current project.
-    A component definition is the same as a
-    <a href="typedef.html">typedef</a> except:
-  </p>
-    <ol>
-      <li>
-        that it can only be used in other types or tasks that
-        accept components (by having an <i>add()</i> method).
-      </li>
-      <li>
-        multiple components may have the same name, provided they
-        implement different interfaces.
-      </li>
-    </ol>
-  <p>
-    The purpose of this is to allow internal Apache Ant definitions to be
-    made for tags like "and" or "or".
-  </p>
+<p>Adds a component definition to the current project.  A component definition is the same as
+a <a href="typedef.html">typedef</a> except:</p>
+<ol>
+  <li>that it can only be used in other types or tasks that accept components (by having
+    an <code>add()</code> method).</li>
+  <li>multiple components may have the same name, provided they implement different interfaces.</li>
+</ol>
+<p>The purpose of this is to allow internal Apache Ant definitions to be made for tags
+like <samp>and</samp> or <samp>or</samp>.</p>
 
-  <h3>Examples</h3>
+<h3>Examples</h3>
 
-<pre> &lt;componentdef name="or" onerror="ignore"
-    classname="com.apache.tools.ant.taskdefs.conditions.Or"/&gt;
-  &lt;componentdef name="or" onerror="ignore"
-    classname="com.apache.tools.ant.types.resources.selectors.Or"/&gt;</pre>
-  <p>
-    defines two components with the same name "or"; one is a condition
-    (see <a href="conditions.html">conditions</a>) and one is 
-    a selector (see <a href="../Types/selectors.html">selectors</a>).
-  </p>
+<p>Define two components with the same name <samp>or</samp>; one is a
+condition (see <a href="conditions.html">conditions</a>) and one is a
+selector (see <a href="../Types/selectors.html">selectors</a>).</p>
+<pre>
+&lt;componentdef name="or" onerror="ignore"
+              classname="com.apache.tools.ant.taskdefs.conditions.Or"/&gt;
+&lt;componentdef name="or" onerror="ignore"
+              classname="com.apache.tools.ant.types.resources.selectors.Or"/&gt;</pre>
 </body>
 </html>
-
diff --git a/manual/Tasks/concat.html b/manual/Tasks/concat.html
index 11372d0..71aba61 100644
--- a/manual/Tasks/concat.html
+++ b/manual/Tasks/concat.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,324 +15,246 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
-    <head>
-      <meta http-equiv="Content-Language" content="en-us">
-      <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>Concat</title>
-    </head>
+  <head>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+    <title>Concat</title>
+  </head>
 
-    <body>
+  <body>
 
-      <h2><a name="Concat">Concat</a></h2>
+    <h2 id="concat">Concat</h2>
 
-      <h3>Description</h3>
+    <h3>Description</h3>
 
-      <p>
-        Concatenates one or more 
-        <a href="../Types/resources.html">resource</a>s
-        to a single file or to the console. The destination
-        file will be created if it does not exist unless the resource
-        list is empty and ignoreempty is true.
-      </p>
+    <p>Concatenates one or more <a href="../Types/resources.html">resource</a>s to a single file or
+      to the console. The destination file will be created if it does not exist unless the resource
+      list is empty and <var>ignoreempty</var> is <q>true</q>.</p>
 
-      <p><strong>Since Apache Ant 1.7.1</strong>, this task can be used as a
-        <a href="../Types/resources.html#collection">Resource Collection</a>
-        that will return exactly one 
-        <a href="../Types/resources.html">resource</a>.
-      </p>
+    <p><em>Since Apache Ant 1.7.1</em>, this task can be used as
+      a <a href="../Types/resources.html#collection">resource collection</a> that will return
+      exactly one <a href="../Types/resources.html">resource</a>.</p>
 
-      <p>
-        <a href="../Types/resources.html#collection">
-Resource Collection</a>s are used to
-        select which resources are to be concatenated. There is no
-        singular attribute to specify a single resource to cat.
-      </p>
+    <p><a href="../Types/resources.html#collection">Resource collections</a> are used to select
+      which resources are to be concatenated. There is no singular attribute to specify a single
+      resource to <code>concat</code>.</p>
 
-      <h3>Parameters</h3>
+    <h3>Parameters</h3>
 
-      <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>destfile</td>
+        <td>The destination file for the concatenated stream.  If not specified the console will be
+          used instead.</td>
+        <td>No</td>
+      </tr>
+      <tr>
+        <td>append</td>
+        <td>Specifies whether or not the file specified by <var>destfile</var> should be
+          appended.</td>
+        <td>No; defaults to <q>no</q></td>
+      </tr>
+      <tr>
+        <td>force</td>
+        <td>Specifies whether or not the file specified by <var>destfile</var> should be written to
+          even if it is newer than all source files. <em><u>Deprecated</u>, use
+          the <var>overwrite</var> attribute instead.</em></td>
+        <td>No; defaults to <q>yes</q></td>
+      </tr>
+      <tr>
+        <td>overwrite</td>
+        <td>Specifies whether or not the file specified by <var>destfile</var> should be written to
+          even if it is newer than all source files.  <em>Since Ant 1.8.2</em>.</td>
+        <td>No; defaults to <q>yes</q></td>
+      </tr>
+      <tr>
+        <td>forceReadOnly</td>
+        <td>Overwrite read-only destination files.  <em>Since Ant 1.8.2</em></td>
+        <td>No; defaults to <q>false</q></td>
+      </tr>
+      <tr>
+        <td>encoding</td>
+        <td>Specifies the encoding for the input files. Please
+          see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+          target="_top">Supported Encodings</a> for a list of possible values.</td>
+        <td>No; defaults to default JVM character encoding</td>
+      </tr>
+      <tr>
+        <td>outputencoding</td>
+        <td>The encoding to use when writing the output file.  <em>Since Ant 1.6</em>.</td>
+        <td>No; defaults to <var>encoding</var> if set or default JVM character encoding
+          otherwise</td>
+      </tr>
+      <tr>
+        <td>fixlastline</td>
+        <td>Specifies whether or not to check if each file concatenated is terminated by a new
+          line. If this attribute is <q>yes</q> a new line will be appended to the stream if the
+          file did not end in a new line.  <em>Since Ant 1.6</em>.  This attribute does not apply to
+          embedded text.</td>
+        <td>No; defaults to <q>no</q></td>
+      </tr>
+      <tr>
+        <td>eol</td>
+        <td>Specifies what the end of line character are for use by the fixlastline
+          attribute.  <em>Since Ant 1.6</em> Valid values for this property are:
+          <ul>
+            <li><q>cr</q>: a single CR</li>
+            <li><q>lf</q>: a single LF</li>
+            <li><q>crlf</q>: the pair CRLF</li>
+            <li><q>mac</q>: a single CR</li>
+            <li><q>unix</q>: a single LF</li>
+            <li><q>dos</q>: the pair CRLF</li>
+          </ul></td>
+        <td>No; default is platform dependent: <q>lf</q> for Unix, <q>crlf</q> for DOS family
+        (including Windows), <q>cr</q> for Mac OS 9 or earlier</td></tr>
+      <tr>
+        <td>binary</td>
+        <td><em>Since Ant 1.6.2</em> If this attribute is set to <q>true</q>, the task concatenates
+          the files in a byte by byte fashion. If this attribute is <q>false</q>, concat will not
+          normally work for binary files due to character encoding issues.  If this option is set
+          to <q>true</q>, the <var>destfile</var> attribute must be set, and the task cannot used
+          nested text.  Also the
+          attributes <var>encoding</var>, <var>outputencoding</var>, <var>filelastline</var> cannot
+          be used.</td>
+        <td>No; default is <q>false</q></td>
+      </tr>
+      <tr>
+        <td>filterbeforeconcat</td>
+        <td>If this attribute is set to <q>true</q>, the task applies the filterchain to each
+          input after applying <code>fixlastline</code>. If this attribute is <q>false</q>, concat
+          will apply the filterchain only once to the already concatenated inputs. Filtering of
+          <code>header</code> and <code>footer</code> is not affected by this setting.
+          <em>Since Ant 1.10.10</em></td>
+        <td>No; default is <q>false</q></td>
+      </tr>
+      <tr>
+        <td>ignoreempty</td>
+        <td><em>Since Ant 1.8.0</em> Specifies whether or not the file specified
+          by <var>destfile</var> should be created if the source resource list is empty.
+        </td>
+        <td>No; defaults to <q>true</q></td>
+      </tr>
+      <tr>
+        <td>resourcename</td>
+        <td><em>Since Ant 1.8.3</em> Specifies the name reported if this task is exposed as
+          a <a href="../Types/resources.html">resource</a>.
+        </td>
+        <td>No</td>
+      </tr>
+    </table>
 
-        <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>
+    <h3>Parameters specified as nested elements</h3>
+    <h4>resource collection</h4>
+    <p><em>Since Ant 1.7</em>.</p>
 
-        <tr>
-          <td valign="top">destfile</td>
-          <td valign="top">
-            The destination file for the concatenated stream.
-        If not specified the console will be used instead.
-          </td>
-          <td valign="top" align="center">
-            No
-          </td>
-        </tr>
+    <p>Any of the various <a href="../Types/resources.html#collection">resource collection</a> types
+      can specify the resources to be concatenated.</p>
 
-        <tr>
-          <td valign="top">append</td>
-          <td valign="top">
-            Specifies whether or not the file specified by 'destfile'
-            should be appended. Defaults to &quot;no&quot;.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">force</td>
-          <td valign="top">
-            Specifies whether or not the file specified by 'destfile'
-            should be written to even if it is newer than all source files.
-            <strong>deprecated, use the overwrite attribute instead</strong>
-            Defaults to &quot;yes&quot;.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">overwrite</td>
-          <td valign="top">
-            Specifies whether or not the file specified by 'destfile'
-            should be written to even if it is newer than all source files.
-            <em>since Ant 1.8.2</em>.
-            Defaults to &quot;yes&quot;.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
+    <h4>filterchain</h4>
+    <p><em>Since Ant 1.6</em>.</p>
+    <p>The task supports nested <a href="../Types/filterchain.html">FilterChain</a>s.</p>
 
-        <tr>
-          <td valign="top">forceReadOnly</td>
-          <td valign="top">Overwrite read-only destination
-            files.  <em>since Ant 1.8.2</em></td>
-          <td valign="top" align="center">No; defaults to false.</td>
-        </tr>
+    <h4>header, footer</h4>
+    <p><em>Since Ant 1.6</em>.</p>
+    <p>Used to prepend or postpend text into the concatenated stream.</p>
+    <p>The text may be in-line or be in a file.</p>
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>filtering</td>
+        <td>Whether to filter the text provided by this sub element.</td>
+        <td>No; default is <q>yes</q></td>
+      </tr>
+      <tr>
+        <td>file</td>
+        <td>A file to place at the head or tail of the concatenated text.</td>
+        <td>No</td>
+      </tr>
+      <tr>
+        <td>trim</td>
+        <td>Whether to trim the value.</td>
+        <td>No; default is <q>no</q></td>
+      </tr>
+      <tr>
+        <td>trimleading</td>
+        <td>Whether to trim leading white space on each line.</td>
+        <td>No; default is <q>no</q></td>
+      </tr>
+    </table>
 
-        <tr>
-          <td valign="top">encoding</td>
-          <td valign="top">
-            Specifies the encoding for the input files. Please see <a
-            href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">
-            Supported Encodings</a>
-            for a list of possible values. Defaults to the platform's
-            default character encoding.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">outputencoding</td>
-          <td valign="top">
-            The encoding to use when writing the output file
-            <em>since Ant 1.6</em>.
-            Defaults to the value of the encoding attribute
-            if given or the default JVM encoding otherwise.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">fixlastline</td>
-          <td valign="top">
-                 Specifies whether or not to check if
-            each file concatenated is terminated by
-            a new line. If this attribute is &quot;yes&quot;
-            a new line will be appended to the stream if
-            the file did not end in a new line.
-            <em>since Ant 1.6</em>.
-            Defaults to &quot;no&quot;.
-            This attribute does not apply to embedded text.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">eol</td>
-          <td valign="top">
-            Specifies what the end of line character are
-            for use by the fixlastline attribute.
-            <em>since Ant 1.6</em>
-            Valid values for this property are:
-            <ul>
-              <li>cr: a single CR</li>
-              <li>lf: a single LF</li>
-              <li>crlf: the pair CRLF</li>
-              <li>mac: a single CR</li>
-              <li>unix: a single LF</li>
-              <li>dos: the pair CRLF</li>
-            </ul>
-            The default is platform dependent.
-            For Unix platforms, the default is &quot;lf&quot;.
-            For DOS based systems (including Windows),
-            the default is &quot;crlf&quot;.
-            For Mac OS, the default is &quot;cr&quot;.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">binary</td>
-          <td valign="top">
-            <em>since Ant 1.6.2</em>
-            If this attribute is set to true, the task concatenates the files
-            in a byte by byte fashion. If this attribute is false, concat will
-            not normally work for binary files due to character encoding
-            issues.
-            If this option is set to true, the destfile attribute must be
-            set, and the task cannot used nested text.
-            Also the attributes encoding, outputencoding, filelastline
-            cannot be used.
-            The default is &quot;false&quot;.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">ignoreempty</td>
-          <td valign="top">
-          <em>Since Ant 1.8.0</em>
-            Specifies whether or not the file specified by 'destfile'
-            should be created if the source resource list is
-            empty. Defaults to &quot;true&quot;.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">resourcename</td>
-          <td valign="top">
-          <em>Since Ant 1.8.3</em>
-            Specifies the name reported if this task is exposed
-            as a <a href="../Types/resources.html">resource</a>.
-          </td>
-          <td valign="top" align="center">No</td>
-        </tr>
+    <h3>Examples</h3>
 
-      </table>
+    <p>Concatenate a string to a file:</p>
+    <pre>&lt;concat destfile=&quot;README&quot;&gt;Hello, World!&lt;/concat&gt;</pre>
 
-      <h3>Parameters specified as nested elements</h3>
-        <h4>Resource Collection</h4>
-        <p><em>since Ant 1.7</em>.</p>
+    <p>Concatenate a series of files to the console:</p>
+    <pre>
+&lt;concat&gt;
+  &lt;fileset dir=&quot;messages&quot; includes=&quot;*important*&quot;/&gt;
+&lt;/concat&gt;</pre>
 
-      <p>
-        Any of the various <a href="../Types/resources.html#collection">
-        Resource Collection</a> types can specify the resources to be
-        concatenated.
-      </p>
+    <p>Concatenate a single file, appending if the destination file exists:</p>
+    <pre>
+&lt;concat destfile=&quot;NOTES&quot; append=&quot;true&quot;&gt;
+  &lt;filelist dir=&quot;notes&quot; files=&quot;note.txt&quot;/&gt;
+&lt;/concat&gt;</pre>
 
-      <h4>filterchain</h4>
-        <p><em>since Ant 1.6</em>.</p>
-      <p>The concat task supports nested
-        <a href="../Types/filterchain.html"> FilterChain</a>s.</p>
+    <p>Concatenate a series of files, update the destination file only if is older that all the
+      source files:</p>
+    <pre>
+&lt;concat destfile=&quot;${docbook.dir}/all-sections.xml&quot;
+        force=&quot;no&quot;&gt;
+  &lt;filelist dir=&quot;${docbook.dir}/sections&quot;
+            files=&quot;introduction.xml,overview.xml&quot;/&gt;
+  &lt;fileset dir=&quot;${docbook.dir}&quot;
+           includes=&quot;sections/*.xml&quot;
+           excludes=&quot;introduction.xml,overview.xml&quot;/&gt;
+&lt;/concat&gt;</pre>
 
-      <h4>header, footer</h4>
-        <p><em>since Ant 1.6</em>.</p>
-      <p>Used to prepend or postpend text into the concatenated stream.</p>
-      <p>The text may be in-line or be in a file.</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">filtering</td>
-          <td valign="top">
-            Whether to filter the text provided by this sub element,
-            default is "yes".
-          <td valign="top" align = "center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">file</td>
-          <td valign="top">A file to place at the head or tail of the
-                           concatenated text.
-          <td valign="top" align = "center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">trim</td>
-          <td valign="top">Whether to trim the value, default is "no"</td>
-          <td valign="top" align = "center">No</td>
-        </tr>
-        <tr>
-          <td valign="top">trimleading</td>
-          <td valign="top">
-            Whether to trim leading white space on each line, default is "no"
-          </td>
-          <td valign="top" align = "center">No</td>
-        </tr>
-      </table>
+    <p>Concatenate a series of files, expanding Ant properties.</p>
+    <pre>
+&lt;concat destfile="${build.dir}/subs"&gt;
+  &lt;path&gt;
+    &lt;fileset dir="${src.dir}" includes="*.xml"/&gt;
+    &lt;pathelement location="build.xml"/&gt;
+  &lt;/path&gt;
+  &lt;filterchain&gt;
+    &lt;expandproperties/&gt;
+  &lt;/filterchain&gt;
+&lt;/concat&gt;</pre>
 
-      <h3>Examples</h3>
+    <p>Filter the lines containing project from <samp>build.xml</samp> and output them
+      to <samp>report.output</samp>, prepending with a header.</p>
+    <pre>
+&lt;concat destfile="${build.dir}/report.output"&gt;
+  &lt;header filtering="no" trimleading="yes"&gt;
+      Lines that contain project
+      ==========================
+  &lt;/header&gt;
+  &lt;path path="build.xml"/&gt;
+  &lt;filterchain&gt;
+    &lt;linecontains&gt;
+      &lt;contains value="project"/&gt;
+    &lt;/linecontains&gt;
+  &lt;/filterchain&gt;
+&lt;/concat&gt;</pre>
 
-      <p><b>Concatenate a string to a file:</b></p>
+    <p>Concatenate a number of binary files.</p>
+    <pre>
+&lt;concat destfile="${build.dir}/dist.bin" binary="yes"&gt;
+  &lt;fileset file="${src.dir}/scripts/dist.sh"/&gt;
+  &lt;fileset file="${build.dir}/dist.tar.bz2"/&gt;
+&lt;/concat&gt;</pre>
 
-      <pre>
-  &lt;concat destfile=&quot;README&quot;&gt;Hello, World!&lt;/concat&gt;
-      </pre>
-
-      <p><b>Concatenate a series of files to the console:</b></p>
-
-      <pre>
-  &lt;concat&gt;
-    &lt;fileset dir=&quot;messages&quot; includes=&quot;*important*&quot;/&gt;
-  &lt;/concat&gt;
-      </pre>
-
-      <p><b>Concatenate a single file, appending if the destination file exists:</b></p>
-
-      <pre>
-  &lt;concat destfile=&quot;NOTES&quot; append=&quot;true&quot;&gt;
-    &lt;filelist dir=&quot;notes&quot; files=&quot;note.txt&quot;/&gt;
-  &lt;/concat&gt;
-      </pre>
-
-      <p><b>Concatenate a series of files, update the destination
-      file only if is older that all the source files:</b></p>
-
-      <pre>
-  &lt;concat destfile=&quot;${docbook.dir}/all-sections.xml&quot;
-          force=&quot;no&quot;&gt;
-    &lt;filelist dir=&quot;${docbook.dir}/sections&quot;
-         files=&quot;introduction.xml,overview.xml&quot;/&gt;
-    &lt;fileset dir=&quot;${docbook.dir}&quot;
-         includes=&quot;sections/*.xml&quot;
-         excludes=&quot;introduction.xml,overview.xml&quot;/&gt;
-  &lt;/concat&gt;
-      </pre>
-
-      <p><b>Concatenate a series of files, expanding ant properties</b></p>
-        <pre>
-   &lt;concat destfile="${build.dir}/subs"&gt;
-      &lt;path&gt;
-        &lt;fileset dir="${src.dir}" includes="*.xml"/&gt;
-        &lt;pathelement location="build.xml"/&gt;
-      &lt;/path&gt;
-      &lt;filterchain&gt;
-        &lt;expandproperties/&gt;
-      &lt;/filterchain&gt;
-   &lt;/concat&gt;
-        </pre>
-
-      <p><b>Filter the lines containing project from build.xml and output
-           them to report.output, prepending with a header</b></p>
-        <pre>
-   &lt;concat destfile="${build.dir}/report.output"&gt;
-      &lt;header filtering="no" trimleading="yes"&gt;
-          Lines that contain project
-          ==========================
-      &lt;/header&gt;
-      &lt;path path="build.xml"/&gt;
-      &lt;filterchain&gt;
-         &lt;linecontains&gt;
-           &lt;contains value="project"/&gt;
-         &lt;/linecontains&gt;
-      &lt;/filterchain&gt;
-   &lt;/concat&gt;
-        </pre>
-
-      <p><b>Concatenate a number of binary files.</b></p>
-        <pre>
-   &lt;concat destfile="${build.dir}/dist.bin" binary="yes"&gt;
-     &lt;fileset file="${src.dir}/scripts/dist.sh" /&gt;
-     &lt;fileset file="${build.dir}/dist.tar.bz2" /&gt;
-   &lt;/concat&gt;
-        </pre>
-
-      
-
-    </body>
-
-  </html>
+  </body>
+</html>
diff --git a/manual/Tasks/condition.html b/manual/Tasks/condition.html
index 405f95e..cc04b13 100644
--- a/manual/Tasks/condition.html
+++ b/manual/Tasks/condition.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,97 +15,83 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Condition Task</title>
 </head>
 
 <body>
 
-<h2><a name="Condition">Condition</a></h2>
+<h2 id="condition">Condition</h2>
 <h3>Description</h3>
-<p>Sets a property if a certain condition holds true - this is a
-generalization of <a href="available.html">Available</a> and <a
-href="uptodate.html">Uptodate</a>.</p>
-<p>If the condition holds true, the property value is set to true by
-default; otherwise, the property is not set. You can set the value to
-something other than the default by specifying the <code>value</code>
-attribute.</p>
-<p>Conditions are specified as <a href="#nested">nested elements</a>,
-you must specify exactly one condition.</p>
+<p>Sets a property if a certain condition holds true&mdash;this is a generalization
+of <a href="available.html">Available</a> and <a href="uptodate.html">Uptodate</a>.</p>
+<p>If the condition holds true, the property value is set to <q>true</q> by default; otherwise, the
+property is not set. You can set the value to something other than the default by specifying
+the <var>value</var> attribute.</p>
+<p>Conditions are specified as <a href="#nested">nested elements</a>, you must specify exactly one
+condition.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to set.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of the property to set.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The value to set the property to. Defaults to
-      &quot;true&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>value</td>
+    <td>The value to set the property to.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">else</td>
-    <td valign="top">The value to set the property to if the condition
-      evaluates to <i>false</i>. By default the property will remain unset.
-      <em>Since Apache Ant 1.6.3</em>
+    <td>else</td>
+    <td>The value to set the property to if the condition evaluates to <q>false</q>. <em>Since
+      Apache Ant 1.6.3</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; by default the property will remain unset</td>
   </tr>
 </table>
-<h3><a name="nested">Parameters specified as nested elements</a></h3>
-<p>All conditions to test are specified as nested elements, for a
-complete list see <a href="conditions.html">here</a>.</p>
+<h3 id="nested">Parameters specified as nested elements</h3>
+<p>All conditions to test are specified as nested elements, for a complete list
+see <a href="conditions.html">here</a>.</p>
 
 <h3>Examples</h3>
+
+<p>Set the property <code>javamail.complete</code> if both the JavaBeans Activation Framework and
+JavaMail are available in the classpath.</p>
 <pre>
-  &lt;condition property=&quot;javamail.complete&quot;&gt;
-    &lt;and&gt;
-      &lt;available classname=&quot;javax.activation.DataHandler&quot;/&gt;
-      &lt;available classname=&quot;javax.mail.Transport&quot;/&gt;
-    &lt;/and&gt;
-  &lt;/condition&gt;
-</pre>
-<p>sets the property <code>javamail.complete</code> if both the
-JavaBeans Activation Framework and JavaMail are available in the
-classpath.</p>
+&lt;condition property=&quot;javamail.complete&quot;&gt;
+  &lt;and&gt;
+    &lt;available classname=&quot;javax.activation.DataHandler&quot;/&gt;
+    &lt;available classname=&quot;javax.mail.Transport&quot;/&gt;
+  &lt;/and&gt;
+&lt;/condition&gt;</pre>
 
+<p>Set the property <code>isMacOsButNotMacOsX</code> if the current operating system is MacOS, but
+not MacOS X/macOS&mdash;which Ant considers to be in the Unix family as well.</p>
 <pre>
-  &lt;condition property=&quot;isMacOsButNotMacOsX&quot;&gt;
-    &lt;and&gt;
-      &lt;os family=&quot;mac&quot;/&gt;
+&lt;condition property=&quot;isMacOsButNotMacOsX&quot;&gt;
+  &lt;and&gt;
+    &lt;os family=&quot;mac&quot;/&gt;
+    &lt;not&gt;
+      &lt;os family=&quot;unix&quot;/&gt;
+    &lt;/not&gt;
+  &lt;/and&gt;
+&lt;/condition&gt;</pre>
 
-      &lt;not&gt;
-        &lt;os family=&quot;unix&quot;/&gt;
-
-      &lt;/not&gt;
-    &lt;/and&gt;
-  &lt;/condition&gt;
-</pre>
-<p>sets the property <code>isMacOsButNotMacOsX</code> if the current
-operating system is MacOS, but not MacOS X - which Ant considers to be
-in the Unix family as well.</p>
-
+<p>Set the property <code>isSunOSonSparc</code> if the current operating system is SunOS and if it
+is running on a SPARC architecture.</p>
 <pre>
-  &lt;condition property=&quot;isSunOSonSparc&quot;&gt;
-    &lt;os name=&quot;SunOS&quot; arch=&quot;sparc&quot;/&gt;
-
-  &lt;/condition&gt;
-</pre>
-<p>sets the property <code>isSunOSonSparc</code> if the current
-operating system is SunOS and if it is running on a sparc architecture.</p>
-
-
+&lt;condition property=&quot;isSunOSonSparc&quot;&gt;
+  &lt;os name=&quot;SunOS&quot; arch=&quot;sparc&quot;/&gt;
+&lt;/condition&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/conditions.html b/manual/Tasks/conditions.html
index 2af7b30..247f2dd 100644
--- a/manual/Tasks/conditions.html
+++ b/manual/Tasks/conditions.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,958 +15,824 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Conditions Task</title>
 </head>
 
 <body>
 
-<h2><a name="Conditions">Conditions</a></h2>
-  <p>Conditions are nested elements of the 
-<a href="condition.html"><code>&lt;condition&gt;</code></a> and
-<a href="waitfor.html"><code>&lt;waitfor&gt;</code></a> tasks.
-    There are core conditions and custom conditions. Custom
-    conditions are described in
-    <a href="../Types/custom-programming.html#customconditions">
-      Custom Conditions</a>.
-    Core Conditions are described below.
-  </p>
-  <h3><a name="coreconditions">Core Conditions</a></h3>
+<h2 id="conditions">Conditions</h2>
+<p>Conditions are nested elements of the <a href="condition.html"><code>&lt;condition&gt;</code></a>
+and <a href="waitfor.html"><code>&lt;waitfor&gt;</code></a> tasks.  There are core conditions and
+custom conditions. Custom conditions are described
+in <a href="../Types/custom-programming.html#customconditions">Custom Conditions</a>.  Core
+Conditions are described below.</p>
+<h3 id="coreconditions">Core Conditions</h3>
 
-<p>These are the nested elements that can be used as conditions in the
-<a href="condition.html"><code>&lt;condition&gt;</code></a> and
-<a href="waitfor.html"><code>&lt;waitfor&gt;</code></a> tasks.</p>
+<p>These are the nested elements that can be used as conditions in
+the <a href="condition.html"><code>&lt;condition&gt;</code></a>
+and <a href="waitfor.html"><code>&lt;waitfor&gt;</code></a> tasks.</p>
 
-<h4><a name="not">not</a></h4>
-<p>The <code>&lt;not&gt;</code> element expects exactly one other
-condition to be nested into this element, negating the result of the
-condition.  It doesn't have any attributes and accepts all nested
-elements of the condition task as nested elements as well.</p>
+<h4 id="not">not</h4>
+<p>The <code>&lt;not&gt;</code> element expects exactly one other condition to be nested into this
+element, negating the result of the condition.  It doesn't have any attributes and accepts all
+nested elements of the condition task as nested elements as well.</p>
 
-<h4><a name="and">and</a></h4> <p>
-The <code>&lt;and&gt;</code> element doesn't have any attributes and
-accepts an arbitrary number of conditions as nested elements - all
-nested elements of the condition task are supported.  This condition
-is true if all of its contained conditions are, conditions will be
-evaluated in the order they have been specified in the build file.</p>
-<p>The <code>&lt;and&gt;</code> condition has the same shortcut
-semantics as the Java &amp;&amp; operator, as soon as one of the
-nested conditions is false, no other condition will be evaluated.</p>
+<h4 id="and">and</h4>
+<p>The <code>&lt;and&gt;</code> element doesn't have any attributes and accepts an arbitrary number
+of conditions as nested elements&mdash;all nested elements of the condition task are supported.
+This condition is true if all of its contained conditions are, conditions will be evaluated in the
+order they have been specified in the build file.</p>
+<p>The <code>&lt;and&gt;</code> condition has the same shortcut semantics as the
+Java <code>&amp;&amp;</code> operator, as soon as one of the nested conditions is false, no other
+condition will be evaluated.</p>
 
-<h4><a name="or">or</a></h4> <p>
-The <code>&lt;or&gt;</code> element doesn't have any attributes and
-accepts an arbitrary number of conditions as nested elements - all
-nested elements of the condition task are supported.  This condition
-is true if at least one of its contained conditions is, conditions
-will be evaluated in the order they have been specified in the build
-file.</p> <p>The <code>&lt;or&gt;</code> condition has the same
-shortcut semantics as the Java || operator, as soon as one of the
-nested conditions is true, no other condition will be evaluated.</p>
+<h4 id="or">or</h4>
+<p>The <code>&lt;or&gt;</code> element doesn't have any attributes and accepts an arbitrary number
+of conditions as nested elements&mdash;all nested elements of the condition task are supported.
+This condition is true if at least one of its contained conditions is, conditions will be evaluated
+in the order they have been specified in the build file.</p>
+<p>The <code>&lt;or&gt;</code> condition has the same shortcut semantics as the Java <code>||</code>
+operator, as soon as one of the nested conditions is true, no other condition will be evaluated.</p>
 
-<h4><a name="xor">xor</a></h4>
-<p>The <code>&lt;xor&gt;</code> element performs an exclusive
-or on all nested elements, similar to the <code>^</code> operator
-in Java. It only evaluates to true if an odd number of nested conditions
+<h4 id="xor">xor</h4>
+<p>The <code>&lt;xor&gt;</code> element performs an exclusive or on all nested elements, similar to
+the <code>^</code> operator in Java. It only evaluates to true if an odd number of nested conditions
 are true. There is no shortcutting of evaluation, unlike the <code>&lt;and&gt;</code>
-and <code>&lt;or&gt;</code> tests.
-It doesn't have any attributes and accepts all nested
-elements of the condition task as nested elements as well.</p>
+and <code>&lt;or&gt;</code> tests.  It doesn't have any attributes and accepts all nested elements
+of the condition task as nested elements as well.</p>
 
-<h4><a name="available">available</a></h4>
-<p>This condition is identical to the <a
-href="available.html">Available</a> task, all attributes and nested
-elements of that task are supported, the property and value attributes
-are redundant and will be ignored.</p>
+<h4 id="available">available</h4>
+<p>This condition is identical to the <a href="available.html">Available</a> task, all attributes
+and nested elements of that task are supported, the property and value attributes are redundant and
+will be ignored.</p>
 
-<h4><a name="uptodate">uptodate</a></h4>
-<p>This condition is identical to the <a
-href="uptodate.html">Uptodate</a> task, all attributes and nested
-elements of that task are supported, the property and value attributes
-are redundant and will be ignored.</p>
+<h4 id="uptodate">uptodate</h4>
+<p>This condition is identical to the <a href="uptodate.html">Uptodate</a> task, all attributes and
+nested elements of that task are supported, the property and value attributes are redundant and will
+be ignored.</p>
 
-<h4><a name="os">os</a></h4>
-<p>Test whether the current operating system is of a given type.  Each
-defined attribute is tested and the result is true only if <i>all</i>
-the tests succeed.
+<h4 id="os">os</h4>
+<p>Test whether the current operating system is of a given type.  Each defined attribute is tested
+and the result is true only if <em>all</em> the tests succeed.
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">family</td>
-    <td valign="top">The name of the operating system family to expect.</td>
-    <td valign="top" align="center">No</td>
+    <td>family</td>
+    <td>The name of the operating system family to expect.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the operating system to expect.</td>
-    <td valign="top" align="center">No</td>
+    <td>name</td>
+    <td>The name of the operating system to expect.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">arch</td>
-    <td valign="top">The architecture of the operating system to expect.</td>
-    <td valign="top" align="center">No</td>
+    <td>arch</td>
+    <td>The architecture of the operating system to expect.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">version</td>
-    <td valign="top">The version of the operating system to expect.</td>
-    <td valign="top" align="center">No</td>
+    <td>version</td>
+    <td>The version of the operating system to expect.</td>
+    <td>No</td>
   </tr>
 </table>
 <p>Supported values for the family attribute are:
 <ul>
-  <li>windows (for all versions of Microsoft Windows)</li>
-  <li>dos (for all Microsoft DOS based operating systems including
-    Microsoft Windows and OS/2)</li>
-  <li>mac (for all Apple Macintosh systems)</li>
-  <li>unix (for all Unix and Unix-like operating systems)</li>
-  <li>netware (for Novell NetWare)</li>
-  <li>os/2 (for OS/2)</li>
-  <li>tandem (for HP's NonStop Kernel - formerly Tandem)</li>
-  <li>win9x for Microsoft Windows 95 and 98, ME and CE</li>
-  <li>winnt for Microsoft Windows NT-based systems, including Windows 2000, XP and
+  <li><q>windows</q>&mdash;for all versions of Microsoft Windows</li>
+  <li><q>dos</q>&mdash;for all Microsoft DOS based operating systems including Microsoft Windows and
+    OS/2</li>
+  <li><q>mac</q>&mdash;for all Apple Macintosh systems prior to Mac OS X</li>
+  <li><q>unix</q>&mdash;for all Unix(-like) operating systems, including Linux and Mac OS
+      X/macOS</li>
+  <li><q>netware</q>&mdash;for Novell NetWare</li>
+  <li><q>os/2</q>&mdash;for OS/2</li>
+  <li><q>tandem</q>&mdash;for HP's NonStop Kernel, formerly Tandem</li>
+  <li><q>win9x</q>&mdash;for Microsoft Windows 95 and 98, ME and CE</li>
+  <li><q>winnt</q>&mdash;for Microsoft Windows NT-based systems, including Windows 2000, XP and
       successors</li>
-  <li>z/os for z/OS and OS/390</li>
-  <li>os/400 for OS/400</li>
-  <li>openvms for OpenVMS</li>
+  <li><q>z/os</q>&mdash;for z/OS and OS/390</li>
+  <li><q>os/400</q>&mdash;for OS/400</li>
+  <li><q>openvms</q>&mdash;for OpenVMS</li>
 </ul>
 
-<h4><a name="equals">equals</a></h4>
+<h4 id="equals">equals</h4>
 <p>Tests whether the two given values are equal.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">arg1</td>
-    <td valign="top">First value to test.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>arg1</td>
+    <td>First value to test.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">arg2</td>
-    <td valign="top">Second value to test.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>arg2</td>
+    <td>Second value to test.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Perform a case sensitive comparison.  Default is
-        true.</td>
-    <td valign="top" align="center">No</td>
+    <td>casesensitive</td>
+    <td>Perform a case sensitive comparison.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">trim</td>
-    <td valign="top">Trim whitespace from arguments before comparing
-        them.  Default is false.</td>
-    <td valign="top" align="center">No</td>
+    <td>trim</td>
+    <td>Trim whitespace from arguments before comparing them.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">forcestring</td>
-    <td valign="top">Force string comparison of <code>arg1/arg2</code>.
-        Default is false.  <em>Since Apache Ant 1.8.1</em>
+    <td>forcestring</td>
+    <td>Force string comparison of <var>arg1</var>/<var>arg2</var>.  <em>Since Apache Ant 1.8.1</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
-<h4><a name="isset">isset</a></h4>
+<h4 id="isset">isset</h4>
 <p>Test whether a given property has been set in this project.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to test.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of the property to test.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h4><a name="checksum">checksum</a></h4>
-<p>This condition is identical to the <a href="checksum.html">Checksum</a>
-task, all attributes and nested elements of that task are supported,
-the property and overwrite attributes are redundant and will be
-ignored.</p>
+<h4 id="checksum">checksum</h4>
+<p>This condition is identical to the <a href="checksum.html">Checksum</a> task, all attributes and
+nested elements of that task are supported, the property and overwrite attributes are redundant and
+will be ignored.</p>
 
-<h4><a name="http">http</a></h4>
-<p>The <code>http</code> condition checks for a valid response from a
-web server of the specified url. By default, HTTP responses errors
-of 400 or greater are viewed as invalid.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="http">http</h4>
+<p>The <code>http</code> condition checks for a valid response from a web server of the specified
+URL. By default, HTTP responses errors of 400 or greater are viewed as invalid.</p>
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">The full URL of the page to request. The web server must
-      return a status code below the value of <tt>errorsBeginAt</tt></td>
-    <td align="center">Yes.</td>
+    <td>url</td>
+    <td>The full URL of the page to request. The web server must return a status code below the
+      value of <var>errorsBeginAt</var></td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">errorsBeginAt</td>
-    <td valign="top">The lowest HTTP response code that signals an error;
-    by default '400'; server errors, not-authorized, not-found and the like
-    are detected</td>
-    <td align="center">No</td>
+    <td>errorsBeginAt</td>
+    <td>The lowest HTTP response code that signals an error; server errors, not-authorized,
+      not-found and the like are detected</td>
+    <td>No; default is <q>400</q></td>
   </tr>
   <tr>
-    <td valign="top">requestMethod</td>
-    <td valign="top">The HTTP method to be used when issuing the request.
-    Any of GET, POST, HEAD, OPTIONS, PUT, DELETEm and TRACE
-    are valid, subject to protocol restrictions. The default if not
-    specified is &quot;GET&quot;.<br/>
-      <em>since Ant 1.8.0</em></td>
-    <td align="center">No</td>
+    <td>requestMethod</td>
+    <td>The HTTP method to be used when issuing the request.  Any
+      of <q>GET</q>, <q>POST</q>, <q>HEAD</q>, <q>OPTIONS</q>, <q>PUT</q>, <q>DELETE</q>
+      and <q>TRACE</q> are valid, subject to protocol restrictions.<br/><em>since Ant
+      1.8.0</em></td>
+    <td>No; default is <q>GET</q></td>
   </tr>
   <tr>
-    <td valign="top">followRedirects</td>
-    <td valign="top">Whether redirects should be followed. The default
-      is <code>true</code><br/>
-      <em>since Ant 1.9.7</em></td>
-    <td align="center">No</td>
+    <td>followRedirects</td>
+    <td>Whether redirects should be followed.<br/><em>since Ant 1.9.7</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>readTimeout</td>
+    <td>Read timeout, in milliseconds, that will be used while reading from the target URL.
+      Accepts any value &ge; 0. Value of 0 implies wait indefinitely. Value &lt; 0 will be silently
+      ignored.<br/>
+      <em>since Ant 1.10.6</em></td>
+    <td>No; defaults to <q>0</q></td>
   </tr>
 </table>
 
-<h4><a name="socket">socket</a></h4>
-<p>The <code>socket</code> condition checks for the existence of a
-TCP/IP listener at the specified host and port.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="socket">socket</h4>
+<p>The <code>socket</code> condition checks for the existence of a TCP/IP listener at the specified
+host and port.</p>
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">server</td>
-    <td valign="top">The DNS name or IP address of the server.</td>
-    <td align="center">Yes.</td>
+    <td>server</td>
+    <td>The DNS name or IP address of the server.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">The port number to connect to.</td>
-    <td align="center">Yes.</td>
+    <td>port</td>
+    <td>The port number to connect to.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h4><a name="filesmatch">filesmatch</a></h4>
-<p>Test two files for matching. Nonexistence of one file results in "false",
-although if neither exists they are considered equal in terms of content.
-This test does a byte for byte comparison, so test time scales with
-byte size. NB: if the files are different sizes, one of them is missing
-or the filenames match the answer is so obvious the detailed test is omitted.
-
+<h4 id="filesmatch">filesmatch</h4>
+<p>Test two files for matching. Nonexistence of one file results in <q>false</q>, although if
+neither exists they are considered equal in terms of content.  This test does a byte for byte
+comparison, so test time scales with byte size. <strong>Note</strong>: if the files are different
+sizes, one of them is missing or the filenames match the answer is so obvious the detailed test is
+omitted.
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file1</td>
-    <td valign="top">First file to test</td>
-    <td align="center">Yes</td>
+    <td>file1</td>
+    <td>First file to test</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">file2</td>
-    <td valign="top">Second file to test</td>
-    <td align="center">Yes</td>
+    <td>file2</td>
+    <td>Second file to test</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">textfile</td>
-    <td valign="top">Whether to ignore line endings when comparing
-        files; defaults to <i>false</i> which triggers a binary
-        comparison. <b>Since Ant 1.7</b>
+    <td>textfile</td>
+    <td>Whether to ignore line endings when comparing files. <em>Since Ant 1.7</em>
     </td>
-    <td align="center">No</td>
+    <td>No; defaults to <q>false</q> which triggers a binary comparison</td>
   </tr>
 </table>
 
-<h4><a name="contains">contains</a></h4>
+<h4 id="contains">contains</h4>
 <p>Tests whether a string contains another one.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">string</td>
-    <td valign="top">The string to search in.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>string</td>
+    <td>The string to search in.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">substring</td>
-    <td valign="top">The string to search for.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>substring</td>
+    <td>The string to search for.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Perform a case sensitive comparison.  Default is
-        true.</td>
-    <td valign="top" align="center">No</td>
+    <td>casesensitive</td>
+    <td>Perform a case sensitive comparison.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
-<h4><a name="istrue">istrue</a></h4>
-<p>Tests whether a string equals any of the ant definitions of true,
-that is "true","yes", or "on"</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="istrue">istrue</h4>
+<p>Tests whether a string equals any of the Ant definitions of true, that
+is <q>true</q>, <q>yes</q>, or <q>on</q></p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">value to test</td>
-    <td valign="top" align="center">Yes</td>
+    <td>value</td>
+    <td>value to test</td>
+    <td>Yes</td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;istrue value=&quot;${someproperty}&quot;/&gt;
-&lt;istrue value=&quot;false&quot;/&gt;
-</pre></blockquote>
+&lt;istrue value=&quot;false&quot;/&gt;</pre>
 
-<h4><a name="isfalse">isfalse</a></h4>
-<p>Tests whether a string is not true, the negation of &lt;istrue&gt;
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="isfalse">isfalse</h4>
+<p>Tests whether a string is not true, the negation of <code>&lt;istrue&gt;</code></p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">value to test</td>
-    <td valign="top" align="center">Yes</td>
+    <td>value</td>
+    <td>value to test</td>
+    <td>Yes</td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;isfalse value=&quot;${someproperty}&quot;/&gt;
-&lt;isfalse value=&quot;false&quot;/&gt;
-</pre></blockquote>
+&lt;isfalse value=&quot;false&quot;/&gt;</pre>
 
-<h4><a name="isreference">isreference</a></h4>
+<h4 id="isreference">isreference</h4>
+<p>Test whether a given reference has been defined in this project and&mdash;optionally&mdash;is of
+an expected type.</p>
 
-<p>Test whether a given reference has been defined in this project and
-- optionally - is of an expected type.</p>
+<p><em>Since Apache Ant 1.6</em>.</p>
 
-<p>This condition has been added in Apache Ant 1.6.</p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">The id of the reference to test.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>refid</td>
+    <td>The <var>id</var> of the reference to test.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">Name of the data type or task this reference is
-       expected to be.</td>
-    <td valign="top" align="center">No</td>
+    <td>type</td>
+    <td>Name of the data type or task this reference is expected to be.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="issigned">issigned</a></h4>
-  <p>
-    Test whether a jarfile is signed.
-    If the name of the
-    signature is passed, the file is checked for presence of that
-    particular signature; otherwise the file is checked for the
-    existence of any signature. It does not perform rigorous
-    signature validation; it only looks for the presence of a signature.
-  </p>
-  <p>
-    This condition was added in Apache Ant 1.7.
-  </p>
-  <table border="1" cellpadding="2" cellspacing="0">
+<h4 id="issigned">issigned</h4>
+<p>Test whether a jarfile is signed.  If the name of the signature is passed, the file is checked
+for presence of that particular signature; otherwise the file is checked for the existence of any
+signature. It does not perform rigorous signature validation; it only looks for the presence of a
+signature.</p>
+<p><em>Since Apache Ant 1.7</em>.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">
-      The jarfile that is to be tested for the presence
-      of a signature.
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>file</td>
+    <td>The jarfile that is to be tested for the presence of a signature.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top"> The signature name to check for.</td>
-    <td valign="top" align="center">No</td>
+    <td>name</td>
+    <td>The signature name to check for.</td>
+    <td>No</td>
   </tr>
-  </table>
+</table>
 
-<h4><a name="isfileselected">isfileselected</a></h4>
-  <p>
-    Test whether a file passes an embedded
-    <a href="../Types/selectors.html">selector</a>.
-  </p>
-  <p>
-    This condition was added in Apache Ant 1.6.3.
-  </p>
-  <table border="1" cellpadding="2" cellspacing="0">
+<h4 id="isfileselected">isfileselected</h4>
+<p>Test whether a file passes an embedded <a href="../Types/selectors.html">selector</a>.</p>
+<p><em>Since Apache Ant 1.6.3</em>.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">
-      The file to check if is passes the embedded selector.
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>file</td>
+    <td>The file to check if is passes the embedded selector.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">The base directory to use for name based selectors. It this is not set,
-      the project's basedirectory will be used.</td>
-    <td valign="top" align="center">No</td>
+    <td>basedir</td>
+    <td>The base directory to use for name based selectors. It this is not set, the
+      project's <var>basedir</var> will be used.</td>
+    <td>No</td>
   </tr>
-  </table>
-  <p>
-    Example usage:
-  </p>
-<blockquote><pre>
+</table>
+<p>Example usage:</p>
+<pre>
 &lt;isfileselected file="a.xml"&gt;
   &lt;date datetime="06/28/2000 2:02 pm" when="equal"/&gt;
-&lt;/isfileselected&gt;
-</pre></blockquote>
+&lt;/isfileselected&gt;</pre>
 
-<h4><a name="typefound">typefound</a></h4>
+<h4 id="typefound">typefound</h4>
 
-<p>Test whether a given type is defined, and that
-its implementation class can be loaded. Types include
-tasks, datatypes, scriptdefs, macrodefs and presetdefs.</p>
+<p>Test whether a given type is defined, and that its implementation class can be loaded. Types
+include tasks, datatypes, scriptdefs, macrodefs and presetdefs.</p>
 
-<p>This condition was added in Apache Ant 1.7.</p>
+<p><em>Since Apache Ant 1.7</em>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">name of the type</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>Name of the type</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">uri</td>
-    <td valign="top">
-      The uri that this type lives in.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>uri</td>
+    <td>The URI that this type lives in.</td>
+    <td>No</td>
   </tr>
 </table>
 
-  <p>
-    Example usages:
-  </p>
-<blockquote><pre>
+<p>Example usages:</p>
+<pre>
 &lt;typefound name="junit"/&gt;
-&lt;typefound uri="antlib:org.apache.maven.artifact.ant" name="artifact"/&gt;
-</pre></blockquote>
+&lt;typefound uri="antlib:org.apache.maven.artifact.ant" name="artifact"/&gt;</pre>
 
-<h4><a name="scriptcondition">scriptcondition</a></h4>
+<h4 id="scriptcondition">scriptcondition</h4>
 
-<p>Evaluate a condition based on a script in any
-<a href="http://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
-  or
-  <a href="https://scripting.dev.java.net">JSR 223</a>
-supported language.
-</p>
-<p>
-See the <a href="../Tasks/script.html">Script</a> task for
-an explanation of scripts and dependencies.
-</p>
+<p>Evaluate a condition based on a script in any <a href="https://jakarta.apache.org/bsf"
+target="_top">Apache BSF</a>
+or <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr223/223ChangeLog.html"
+target="_top">JSR 223</a> supported language.</p>
+<p>See the <a href="../Tasks/script.html">Script</a> task for an explanation of scripts and
+dependencies.</p>
 
-<p>This condition was added in Apache Ant 1.7.</p>
+<p><em>Since Apache Ant 1.7</em>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">language</td>
-    <td valign="top">script language</td>
-    <td valign="top" align="center">Yes</td>
+    <td>language</td>
+    <td>script language</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">manager</td>
-    <td valign="top">
-      The script engine manager to use.
-      See the <a href="../Tasks/script.html">script</a> task
-      for using this attribute.
-    </td>
-    <td valign="top" align="center">No - default is "auto"</td>
+    <td>manager</td>
+    <td>The script engine manager to use.  See the <a href="../Tasks/script.html">script</a> task
+      for using this attribute.</td>
+    <td>No; default is <q>auto</q></td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">default boolean value</td>
-    <td valign="top" align="center">No -default is "false"</td>
-  </tr>  
-  <tr>
-    <td valign="top">src</td>
-    <td valign="top">filename of script source</td>
-    <td valign="top" align="center">No</td>
+    <td>value</td>
+    <td>default boolean value</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">setbeans</td>
-    <td valign="top">whether to have all properties, references and targets as
-      global variables in the script.  <em>since Ant 1.8.0</em></td>
-    <td valign="top" align="center">No, default is "true".</td>
+    <td>src</td>
+    <td>filename of script source</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">
-      The classpath to pass into the script.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The encoding of the script source. <em>Since Ant 1.10.2</em>.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use, given as a
-       <a href="../using.html#references">reference</a> to a path defined elsewhere.
-    <td align="center" valign="top">No</td>
+    <td>setbeans</td>
+    <td>whether to have all properties, references and targets as global variables in the
+      script.  <em>since Ant 1.8.0</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>The classpath to pass into the script.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a path
+    defined elsewhere.</td>
+    <td>No</td>
   </tr>
 </table>
 <h5>Parameters specified as nested elements</h5>
 <h6>classpath</h6>
-  <p>
-    See the <a href="../Tasks/script.html">script</a> task
-    for using this nested element.
-  </p>
+<p>See the <a href="../Tasks/script.html">script</a> task for using this nested element.</p>
 <h5>Description</h5>
-<p>
-The script supports script language inline, this script has access to the
-same beans as the <code>&lt;script&gt;</code> task, and to the <code>self</code> bean,
-which refers back to the condition itself. If the script evaluates to a boolean result,
-this is the result of the condition's evaluation (<em>since Ant 1.7.1</em>).
-Alternatively, <code>self.value</code> can be used to set the evaluation result.
-</p>
-<p>
-Example:
-</p>
-<blockquote><pre>
+<p>The script supports script language inline, this script has access to the same beans as
+the <code>&lt;script&gt;</code> task, and to the <code>self</code> bean, which refers back to the
+condition itself. If the script evaluates to a boolean result, this is the result of the condition's
+evaluation (<em>since Ant 1.7.1</em>).  Alternatively, <code>self.value</code> can be used to set
+the evaluation result.</p>
+<p>Example:</p>
+<pre>
 &lt;scriptcondition language=&quot;javascript&quot;
         value=&quot;true&quot;&gt;
     self.setValue(false);
-&lt;/scriptcondition&gt;
-</pre></blockquote>
+&lt;/scriptcondition&gt;</pre>
 
-Sets the default value of the condition to true, then in the script, 
-sets the value to false. This condition always evaluates to "false"
+<p>Sets the default value of the condition to <q>true</q>, then in the script, sets the value
+to <q>false</q>. This condition always evaluates to <q>false</q>.</p>
 
-<h4><a name="parsersupports">parsersupports</a></h4>
+<h4 id="parsersupports">parsersupports</h4>
 
-<p>Tests whether Ant's XML parser supports a given
-feature or property, as per the SAX/JAXP specifications, by
-attempting to set the appropriate property/feature/</p>
+<p>Tests whether Ant's XML parser supports a given feature or property, as per the SAX/JAXP
+specifications, by attempting to set the appropriate property/feature</p>
 
-<p>This condition was added in Apache Ant 1.7.</p>
+<p><em>Since Apache Ant 1.7</em>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">property to set</td>
-    <td valign="top" align="center">one of property or feature</td>
+    <td>property</td>
+    <td>property to set</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">feature</td>
-    <td valign="top">feature to set</td>
-    <td valign="top" align="center">one of property or feature</td>
+    <td>feature</td>
+    <td class="left">feature to set</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">string (property) or boolean (feature)</td>
-    <td valign="top" align="center">For property tests, but not for feature tests</td>
+    <td>value</td>
+    <td>string (property) or boolean (feature)</td>
+    <td>For property tests, but not for feature tests</td>
   </tr>
 </table>
 
-<blockquote><pre>
-&lt;parsersupports feature="http://xml.org/sax/features/namespaces"/&gt;
-</pre></blockquote>
-Check for namespace support. All SAX2 parsers should have this.
-<blockquote><pre>
+<pre>&lt;parsersupports feature="http://xml.org/sax/features/namespaces"/&gt;</pre>
+<p>Check for namespace support. All SAX2 parsers should have this.</p>
+
+<pre>
 &lt;or&gt;
   &lt;parsersupports
     feature="http://apache.org/xml/features/validation/schema"/&gt;
   &lt;parsersupports
     feature="http://java.sun.com/xml/jaxp/properties/schemaSource"/&gt;
-&lt;/or&gt;
-</pre></blockquote>
-
-Check for XML Schema support.
+&lt;/or&gt;</pre>
+<p>Check for XML Schema support.</p>
 
 <pre>
 &lt;parsersupports
   property="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"
-  value="document.xsd"/&gt;
-</pre>
+  value="document.xsd"/&gt;</pre>
+<p>Check for Xerces-specific definition of the location of the no namespace schema.</p>
 
-Check for Xerces-specific definition of the location of the no namespace schema.
+<h4 id="isreachable">isreachable</h4>
 
-<h4><a name="isreachable">isreachable</a></h4>
+<p>Uses Java 5+ networking APIs to probe for a (remote) system being reachable. Exactly what probe
+mechanisms are used is an implementation feature of the JVM. They may include ICMP "ping" packets,
+UDP or TCP connections to port 7 "echo service" or other means.</p>
+<p>This condition turns unknown host exceptions into false conditions. This is because on a laptop,
+DNS is one of the first services when the network goes; you are implicitly offline.</p>
+<p>If a URL is supplied instead of a <var>host</var>, the hostname is extracted and used in the
+test&mdash;all other parts of the URL are discarded.</p>
+<p>The test may not work through firewalls, that is, something may be reachable using a protocol
+such as HTTP, while the lower level ICMP packets get dropped on the floor. Similarly, a host may
+detected as reachable with ICMP, but not reachable on other ports (i.e. port 80), because of
+firewalls.</p>
+<p><em>Since Apache Ant 1.7</em>.</p>
 
-<p>Uses Java1.5+ networking APIs to probe for a (remote) system being
-reachable. Exactly what probe mechanisms are used is an implementation
-feature of the JVM. They may include ICMP "ping" packets, UDP or TCP connections
-to port 7 "echo service" or other means.
+<table class="attr">
 
-</p>
-<p>
-This condition turns unknown host exceptions into false conditions. This is
-because on a laptop, DNS is one of the first services when the network goes; you
-are implicitly offline.
-</p>
-<p>
- If a URL is supplied instead of a host, the hostname is extracted
- and used in the test - all other parts of the URL are discarded.
-</p>
-<p>
-The test may not work through firewalls, that is, something may be reachable
-using a protocol such as HTTP, while the lower level ICMP packets get dropped
-on the floor. Similarly, a host may detected as reachable with ICMP, but
-not reachable on other ports (i.e. port 80), because of firewalls.
-</p>
-<p>
-
-This condition was added in Apache Ant 1.7.</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>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">host</td>
-    <td valign="top">host to check for</td>
-    <td valign="top" align="center">one of url or host</td>
+    <td>host</td>
+    <td>host to check for</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">URL containing hostname</td>
-    <td valign="top" align="center">one of url or host</td>
+    <td>url</td>
+    <td class="left">URL containing hostname</td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">timeout in seconds</td>
-    <td valign="top" align="center">no, default is 30s</td>
+    <td>timeout</td>
+    <td>timeout in seconds</td>
+    <td>No; default is <q>30</q></td>
   </tr>
 </table>
 
-<blockquote><pre>
+<pre>
 &lt;condition property="offline"&gt;
-  &lt;isreachable url="http://ibiblio.org/maven/" /&gt;
-&lt;/condition&gt;
-</pre></blockquote>
+  &lt;isreachable url="https://ibiblio.org/maven/"/&gt;
+&lt;/condition&gt;</pre>
 
-<p>
-Probe for the maven repository being reachable.
-</p>
+<p>Probe for the Maven repository being reachable.</p>
 
-<blockquote><pre>
+<pre>
 &lt;condition property="offline"&gt;
-  &lt;isreachable host="ibiblio.org" timeout="10" /&gt;
-&lt;/condition&gt;
-</pre></blockquote>
+  &lt;isreachable host="ibiblio.org" timeout="10"/&gt;
+&lt;/condition&gt;</pre>
 
-<p>
-Probe for the maven repository being reachable using the hostname, ten second timeout..
-</p>
+<p>Probe for the Maven repository being reachable using the hostname, ten second timeout.</p>
 
-<h4><a name="length">length</a></h4>
-<p>This condition is a facet of the <a href="length.html">Length</a> task.
-  It is used to test the length of a string or one or more files.
-  <b>Since Ant 1.6.3</b>
-</p>
+<h4 id="length">length</h4>
+<p><em>Since Ant 1.6.3</em></p>
+<p>This condition is a facet of the <a href="length.html">Length</a> task. It is used to test the
+length of a string or one or more files.</p>
 
-<blockquote><pre>
-&lt;length string=" foo " trim="true" length="3" /&gt;
-</pre></blockquote>
+<pre>&lt;length string=" foo " trim="true" length="3"/&gt;</pre>
 <p>Verify a string is of a certain length.</p>
 
-<blockquote><pre>
-&lt;length file=&quot;foo&quot; when=&quot;greater&quot; length=&quot;0&quot; /&gt;
-</pre></blockquote>
-<p>Verify that file <i>foo</i> is not empty.</p>
+<pre>&lt;length file=&quot;foo&quot; when=&quot;greater&quot; length=&quot;0&quot;/&gt;</pre>
+<p>Verify that file <samp>foo</samp> is not empty.</p>
 
-<h4><a name="isfailure">isfailure</a></h4>
+<h4 id="isfailure">isfailure</h4>
+<p><em>Since Ant 1.7</em></p>
+<p>Test the return code of an executable (see the <a href="exec.html">Exec</a> task) for
+failure.</p>
 
-<p>Test the return code of an executable (see the
-<a href="exec.html">Exec</a> task) for failure. <b>Since Ant 1.7</b></p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">code</td>
-    <td valign="top">The return code to test.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>code</td>
+    <td>The return code to test.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h4><a name="resourcecount">resourcecount</a></h4>
-<p>This condition is a facet of the
-  <a href="resourcecount.html">ResourceCount</a> task.
-  It is used to test the size of a 
-  <a href="../Types/resources.html#collection">resource collection</a>.
-  <b>Since Ant 1.7</b>
-</p>
+<h4 id="resourcecount">resourcecount</h4>
+<p><em>Since Ant 1.7</em></p>
+<p>This condition is a facet of the <a href="resourcecount.html">ResourceCount</a> task.  It is used
+to test the size of a <a href="../Types/resources.html#collection">resource
+collection</a>.</p>
 
-<blockquote><pre>
-&lt;resourcecount refid=&quot;myresourcecollection&quot; when=&quot;greater&quot; count=&quot;0&quot; /&gt;
-</pre></blockquote>
+<pre>&lt;resourcecount refid=&quot;myresourcecollection&quot; when=&quot;greater&quot; count=&quot;0&quot;/&gt;</pre>
 <p>Verify that a resource collection is not empty.</p>
 
-<h4><a name="resourcesmatch">resourcesmatch</a></h4>
-<p>Test resources for matching. Nonexistence of one or more resources results in
-"false", although if none exists they are considered equal in terms of content.
-By default this test does a byte for byte comparison, so test time scales with
-byte size. NB: if the files are different sizes, one of them is missing
-or the filenames match the answer is so obvious the detailed test is omitted.
-The resources to check are specified as nested
-<a href="../Types/resources.html#collection">resource collections</a>,
-meaning that more than two resources can be checked; in this case all resources
-must match. <b>Since Ant 1.7</b>
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="resourcesmatch">resourcesmatch</h4>
+<p><em>Since Ant 1.7</em></p>
+<p>Test resources for matching. Nonexistence of one or more resources results in <q>false</q>,
+although if none exists they are considered equal in terms of content.  By default, this test does a
+byte for byte comparison, so test time scales with byte size. <strong>Note</strong>: if the files
+are different sizes, one of them is missing or the filenames match the answer is so obvious the
+detailed test is omitted.  The resources to check are specified as
+nested <a href="../Types/resources.html#collection">resource collections</a>, meaning that more than
+two resources can be checked; in this case all resources must match.</p>
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">astext</td>
-    <td valign="top">Whether to ignore line endings
-        when comparing resource content; defaults to <i>false</i>,
-        while <i>true</i> triggers a binary comparison.
-    </td>
-    <td align="center">No</td>
+    <td>astext</td>
+    <td>Whether to ignore line endings when comparing resource content; <q>true</q> triggers a
+      binary comparison.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
-<h4><a name="resourcecontains">resourcecontains</a></h4>
+<h4 id="resourcecontains">resourcecontains</h4>
+<p><em>Since Ant 1.7.1</em></p>
 <p>Tests whether a resource contains a given (sub)string.</p>
-<p>The resources to check are specified via references or - in the
-  case of file resources via the resource attribute.  <b>Since Ant 1.7.1</b>
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>The resources to check are specified via references or&mdash;in the case of file
+resources&mdash;via the <var>resource</var> attribute.</p>
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top">Name of a file that is the resource to test.
-    </td>
-    <td align="center" rowspan="2">One of the two</td>
+    <td>resource</td>
+    <td>Name of a file that is the resource to test.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">Reference to a resource defined inside the project.</td>
+    <td>refid</td>
+    <td class="left">Reference to a resource defined inside the project.</td>
   </tr>
   <tr>
-    <td valign="top">substring</td>
-    <td valign="top">The string to search for.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>substring</td>
+    <td>The string to search for.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Perform a case sensitive comparison.  Default is
-        true.</td>
-    <td valign="top" align="center">No</td>
+    <td>casesensitive</td>
+    <td>Perform a case sensitive comparison.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
-<h4><a name="hasmethod">hasmethod</a></h4>
+<h4 id="hasmethod">hasmethod</h4>
+<p><em>Since Ant 1.7</em></p>
+<p>Tests for a class having a method or field. If the class is not found or fails to load, the build
+fails.</p>
 
-<p> Tests for a class having a method or field. If the class is not found 
-    or fails to load, the build fails. 
-    
-    <b>Since Ant 1.7</b>
-</p>
-
-<table border="1" cellpadding="2" cellspacing="0">
-    <tr>
-        <td width="12%" valign="top"><b>Attribute</b></td>
-        <td width="78%" valign="top"><b>Description</b></td>
-        <td width="10%" valign="top"><b>Required</b></td>
-    </tr>
-    <tr>
-        <td valign="top">classname</td>
-        <td valign="top">name of the class to load</td>
-        <td align="center">yes</td>
-    </tr>
-    <tr>
-        <td valign="top">field</td>
-        <td valign="top">name of a field to look for</td>
-        <td align="center">one of field or method</td>
-    </tr>
-    <tr>
-        <td valign="top">method</td>
-        <td valign="top">name of a method to look for</td>
-        <td align="center">one of field or method</td>
-    </tr>
-    
-    <tr>
-        <td valign="top">ignoreSystemClasses</td>
-        <td valign="top">should system classes be ignored?</td>
-        <td align="center">No -default is false</td>
-    </tr>
-    <tr>
-        <td valign="top">classpath</td>
-        <td valign="top">a class path</td>
-        <td align="center">No</td>
-    </tr>
-    <tr>
-        <td valign="top">classpathref</td>
-        <td valign="top">reference to a class path</td>
-        <td align="center">No</td>
-    </tr>
-</table>
-
-<p>
-    There is also a nested &lt;classpath&gt; element, which can be used to specify 
-    a classpath.
-</p>
-<blockquote><pre>
-&lt;hasmethod classname="java.util.ArrayList" method="trimToSize"  /&gt;
-</pre></blockquote>
-
-<p>Looks for the method trimToSize in the ArrayList class.</p>
-
-<h4><a name="matches">matches</a></h4>
-
-<p>
-  Test if the specified string matches the specified regular
-  expression pattern.
-  <b>Since Ant 1.7</b></p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">string</td>
-    <td valign="top">The string to test.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>classname</td>
+    <td>name of the class to load</td>
+    <td>yes</td>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">The regular expression pattern used to test.</td>
-    <td valign="top" align="center">Yes, unless there is a nested
-      <code>&lt;regexp&gt;</code> element.</td>
+    <td>field</td>
+    <td>name of a field to look for</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Perform a case sensitive match.  Default is
-        true.</td>
-    <td valign="top" align="center">No</td>
+    <td>method</td>
+    <td class="left">name of a method to look for</td>
   </tr>
   <tr>
-    <td valign="top">multiline</td>
-    <td valign="top">
-      Perform a multi line match.
-      Default is false.</td>
-    <td valign="top" align="center">No</td>
+    <td>ignoreSystemClasses</td>
+    <td>should system classes be ignored?</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">singleline</td>
-    <td valign="top">
-      This allows '.' to match new lines.
-      SingleLine is not to be confused with multiline, SingleLine is a perl
-      regex term, it corresponds to dotall in java regex.
-      Default is false.</td>
-    <td valign="top" align="center">No</td>
+    <td>classpath</td>
+    <td>a class path</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>reference to a class path</td>
+    <td>No</td>
   </tr>
 </table>
 
-  <p>
-    There is also an optional &lt;regexp&gt; element, which can be used to specify
-    a regular expression instead of the "pattern" attribute.
-    See <a href="../Types/regexp.html">Regexp Type</a> for the description
-    of the nested element regexp and of
-    the choice of regular expression implementation.
-  </p>
-  <p>
-    An example:
-  </p>
-<blockquote><pre>
+<p>There is also a nested <code>&lt;classpath&gt;</code> element, which can be used to specify a
+classpath.</p>
+<pre>&lt;hasmethod classname="java.util.ArrayList" method="trimToSize"/&gt;</pre>
+<p>Looks for the method <code class="code">trimToSize()</code> in
+the <code class="code">java.util.ArrayList</code> class.</p>
+
+<h4 id="matches">matches</h4>
+<p><em>Since Ant 1.7</em></p>
+<p>Test if the specified string matches the specified regular expression pattern</p>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>string</td>
+    <td>The string to test.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>pattern</td>
+    <td>The regular expression pattern used to test.</td>
+    <td>Yes, unless there is a nested <code>&lt;regexp&gt;</code> element</td>
+  </tr>
+  <tr>
+    <td>casesensitive</td>
+    <td>Perform a case sensitive match.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>multiline</td>
+    <td>Perform a multi line match.</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>singleline</td>
+    <td>This allows <q>.</q> to match new lines. <var>SingleLine</var> is not to be confused with
+      multiline, <var>SingleLine</var> is a perl regex term, it corresponds to <var>dotall</var> in
+      Java regex.</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+</table>
+
+<p>There is also an optional <code>&lt;regexp&gt;</code> element, which can be used to specify a
+regular expression instead of the <var>pattern</var> attribute.
+See <a href="../Types/regexp.html">Regexp Type</a> for the description of the nested element regexp
+and of the choice of regular expression implementation.</p>
+<p>An example:</p>
+<pre>
 &lt;condition property="legal-password"&gt;
   &lt;matches pattern="[1-9]" string="${user-input}"/&gt;
 &lt;/condition&gt;
 &lt;fail message="Your password should at least contain one number"
-      unless="legal-password"/&gt;
-</pre></blockquote>
-  <p>
-    The following example sets the property "ok" if
-    the property "input" is three characters long, starting
-    with 'a' and ending with 'b'.
-  </p>
-<blockquote><pre>
+      unless="legal-password"/&gt;</pre>
+<p>The following example sets the property <code>ok</code> if the property <code>input</code> is
+three characters long, starting with <q>a</q> and ending with <q>b</q>.</p>
+<pre>
 &lt;condition property="ok"&gt;
   &lt;matches string="${input}" pattern="^a.b$"/&gt;
-&lt;/condition&gt;
-</pre></blockquote>
-  <p>
-    The following defines a reference regular expression for
-    matching dates and then uses antunit to check if the
-    property "today" is in the correct format:
-  </p>
-<blockquote><pre>
+&lt;/condition&gt;</pre>
+<p>The following defines a reference regular expression for matching dates and then uses antunit to
+check if the property <code>today</code> is in the correct format:</p>
+<pre>
 &lt;regexp id="date.pattern" pattern="^[0123]\d-[01]\d-[12]\d\d\d$"/&gt;
 
 &lt;au:assertTrue xmlns:au="antlib:org.apache.ant.antunit"&gt;
   &lt;matches string="${today}"&gt;
     &lt;regexp refid="date.pattern"/&gt;
   &lt;/matches&gt;
-&lt;/au:assertTrue&gt;
-</pre></blockquote>
-  <p>
-    The following example shows the use of the singleline and the casesensitive
-    flags.
-  </p>
-<blockquote><pre>
+&lt;/au:assertTrue&gt;</pre>
+<p>The following example shows the use of the <var>singleline</var> and the <var>casesensitive</var>
+flags.</p>
+<pre>
 &lt;au:assertTrue&gt;
   &lt;matches string="AB${line.separator}C" pattern="^ab.*C$"
            casesensitive="false"
@@ -975,156 +842,136 @@
   &lt;matches string="AB${line.separator}C" pattern="^ab.*C$"
            casesensitive="false"
            singleline="false"/&gt;
-&lt;/au:assertFalse&gt;
-</pre></blockquote>
+&lt;/au:assertFalse&gt;</pre>
 
-<h4><a name="antversion">antversion</a></h4>
-<p>This condition is identical to the <a
-href="antversion.html">Antversion</a> task, all attributes are supported, the property attribute
-is redundant and will be ignored.</p>
+<h4 id="antversion">antversion</h4>
+<p>This condition is identical to the <a href="antversion.html">Antversion</a> task, all attributes
+are supported, the <var>property</var> attribute is redundant and will be ignored.</p>
 
+<h4 id="hasfreespace">hasfreespace</h4>
+<p><em>Since Ant 1.7.0</em></p>
+<p>Tests a partition to see if there is enough space.</p>
+<p>Needed attribute can be specified using standard computing terms:</p>
+<ul>
+  <li>K : Kilobytes (1024 bytes)</li>
+  <li>M : Megabytes (1024 K)</li>
+  <li>G : Gigabytes (1024 M)</li>
+  <li>T : Terabytes (1024 G)</li>
+  <li>P : Petabytes (1024 T)</li>
+</ul>
 
-<h4><a name="hasfreespace">hasfreespace</a></h4>
-
-<p>
-  Tests a partition to see if there is enough space.
-  <b>Since Ant 1.7.0</b></p>
-  <p>Needed attribute can be specified using standard computing terms:<br/>
-    <ul>
-      <li>K : Kilobytes (1024 bytes)</li>
-      <li>M : Megabytes (1024 K)</li>
-      <li>G : Gigabytes (1024 M)</li>
-      <li>T : Terabytes (1024 G)</li>
-      <li>P : Petabytes (1024 T)</li>
-    </ul>
-  </p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">partition</td>
-    <td valign="top">The partition or filesystem to check for freespace</td>
-    <td valign="top" align="center">Yes</td>
+    <td>partition</td>
+    <td>The partition or filesystem to check for free space</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">needed</td>
-    <td valign="top">The amount of freespace needed.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>needed</td>
+    <td>The amount of free space needed.</td>
+    <td>Yes</td>
   </tr>
 </table>
-  <p>
-    An example:
-  </p>
-<blockquote><pre>
-&lt;hasfreespace partition="c:" needed="100M"/&gt;
-</pre></blockquote>
+<p>An example:</p>
+<pre>&lt;hasfreespace partition="c:" needed="100M"/&gt;</pre>
 
-<h4><a name="islastmodified">islastmodified</a></h4>
+<h4 id="islastmodified">islastmodified</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>Tests the last modified date of a resource.</p>
 
-<p>Tests the last modified date of a resource.  <em>Since Ant
-1.8.0</em></p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">millis</td>
-    <td valign="top">Specifies the expected modification time of the resource
-      in milliseconds since midnight Jan 1 1970.</td>
-    <td valign="center" align="center" rowspan="2">Exactly one of the
-      two.</td>
+    <td>millis</td>
+    <td>Specifies the expected modification time of the resource in milliseconds since midnight Jan
+      1 1970.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">datetime</td>
-    <td valign="top">Specifies the expected modification time of the
-       resource. The special value &quot;now&quot; indicates the
-       current time.</td>
+    <td>datetime</td>
+    <td class="left">Specifies the expected modification time of the resource. The special
+      value <q>now</q> indicates the current time.</td>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">SimpleDateFormat-compatible pattern string.
-       Defaults to MM/DD/YYYY HH:MM AM_or_PM or MM/DD/YYYY HH:MM:SS AM_or_PM.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>pattern</td>
+    <td>SimpleDateFormat-compatible pattern string.</td>
+    <td>No; defaults to <q>MM/dd/YYYY hh:mm a</q> or <q>MM/dd/YYYY hh:mm:ss a</q></td>
   </tr>
   <tr>
-    <td valign="top">mode</td>
-    <td valign="top">How to compare the timestamp.  Accepted values
-      are "equals", "before", "not-before", "after" and "not-after".
-    <td valign="top">No, defaults to "equals".</td>
+    <td>mode</td>
+    <td>How to compare the timestamp.  Accepted values
+      are <q>equals</q>, <q>before</q>, <q>not-before</q>, <q>after</q> and <q>not-after</q>.
+    <td>No; defaults to <q>equals</q></td>
   </tr>
 </table>
 
 <p>The actual resource to test is specified as a nested element.</p>
 
-  <p>
-    An example:
-  </p>
-<blockquote><pre>
+<p>An example:</p>
+<pre>
 &lt;islastmodified dateTime="08/18/2009 04:41:19 AM" mode="not-before"&gt;
   &lt;file file="${file}"/&gt;
-&lt;/islastmodified&gt;
-</pre></blockquote>
+&lt;/islastmodified&gt;</pre>
 
-<h4><a name="resourceexists">resourceexists</a></h4>
-
-<p>Tests a resource for existence.  <em>since Ant 1.8.0</em></p>
+<h4 id="resourceexists">resourceexists</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>Tests a resource for existence.</p>
 
 <p>The actual resource to test is specified as a nested element.</p>
 
-  <p>
-    An example:
-  </p>
-<blockquote><pre>
+<p>An example:</p>
+<pre>
 &lt;resourceexists&gt;
   &lt;file file="${file}"/&gt;
-&lt;/resourceexists&gt;
-</pre></blockquote>
+&lt;/resourceexists&gt;</pre>
 
-<h4><a name="javaversion">javaversion</a></h4>
+<h4 id="javaversion">javaversion</h4>
+<p><em>Since Ant 1.10.2</em></p>
+<p>Tests the version of the JVM executing Ant.</p>
 
-<p>Tests the version of the JVM executing Ant.  <em>Since Ant
-1.9.10</em></p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">atleast</td>
-    <td valign="top">The version that this JVM is at least.
-      The format is major.minor.point. Starting with Java9 really
-      only the major number is determined.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" rowspan="2" align="center">One of these.</td>
+    <td class="left">atleast</td>
+    <td>The version that this JVM is of at least. The format
+      is <code>major.minor.point</code>. Starting with Java 9 really only the major number is
+      determined.</td>
+    <td rowspan="3">Exactly one of the three</td>
   </tr>
   <tr>
-    <td valign="top">exactly</td>
-    <td valign="top">The version that this JVM is exactly.
-      The format is <tt>major.minor.point</tt>. Starting with Java9 really
-      only the major number is determined.</td>
-    <td valign="top" align="center">No</td>
+    <td>atmost</td>
+    <td class="left">The version that this JVM is of at most. The format
+      is <code>major.minor.point</code>. Starting with Java 9 really only the major number is
+      determined.<br/>
+      <em>Since Ant 1.10.10</em>
+    </td>
+  </tr>
+  <tr>
+    <td>exactly</td>
+    <td class="left">The version that this JVM is of exactly. The format
+      is <code>major.minor.point</code>. Starting with Java 9 really only the major number is
+      determined.</td>
   </tr>
 </table>
 
-  <p>
-    An example:
-  </p>
+<p>An example:</p>
 
-<blockquote><pre>
-&lt;javaversion atleast=&quot;9&quot;/&gt;
-</pre></blockquote>
+<pre>&lt;javaversion atleast=&quot;9&quot;/&gt;</pre>
 
-<p>will evaluate to true if the current JVM is Java9 or above.</p>
+<p>will evaluate to true if the current JVM is Java 9 or above.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/copy.html b/manual/Tasks/copy.html
index 2e39116..29a459e 100644
--- a/manual/Tasks/copy.html
+++ b/manual/Tasks/copy.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,366 +15,289 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Copy Task</title>
 </head>
 
 <body>
 
-<h2><a name="copy">Copy</a></h2>
+<h2 id="copy">Copy</h2>
 <h3>Description</h3>
-<p>Copies a file or resource collection to a new file or directory.  By default, files are
-only copied if the source file is newer than the destination file,
-or when the destination file does not exist - please see
-the <code>granularity</code> attribute for Ant's idea
-of <em>newer</em>.
-However, you can explicitly
-overwrite files with the <code>overwrite</code> attribute.</p>
+<p>Copies a file or resource collection to a new file or directory.  By default, files are only
+copied if the source file is newer than the destination file, or when the destination file does not
+exist - please see the <var>granularity</var> attribute for Ant's idea of <em>newer</em>.
+However, you can explicitly overwrite files with the <code>overwrite</code> attribute.</p>
 
-<p><a href="../Types/resources.html#collection">Resource
-Collection</a>s are used to select a group of files to copy.  To use a
-resource collection, the <code>todir</code> attribute must be set.
-<strong>Note</strong> that some resources (for example
-the <a href="../Types/resources.html#file">file</a> resource)
-return absolute paths as names and the result of using them without
-using a nested mapper (or the flatten attribute) may not be what you
+<p><a href="../Types/resources.html#collection">Resource collections</a> are used to select a group
+of files to copy.  To use a resource collection, the <var>todir</var> attribute must be
+set. <strong>Note</strong> that some resources (for example
+the <a href="../Types/resources.html#file">file</a> resource) return absolute paths as names and the
+result of using them without using a nested mapper (or the flatten attribute) may not be what you
 expect.</p>
 
-<p>
-<strong>Note: </strong>If you employ filters in your copy operation,
-you should limit the copy to text files. Binary files will be corrupted
-by the copy operation.
-This applies whether the filters are implicitly defined by the
-<a href="filter.html">filter</a> task or explicitly provided to the copy
-operation as <a href="../Types/filterset.html">filtersets</a>.
-  <em>See <a href="#encoding">encoding note</a></em>.
-</p>
+<p><strong>Note</strong>: If you employ filters in your copy operation, you should limit the copy to
+text files. Binary files will be corrupted by the copy operation.  This applies whether the filters
+are implicitly defined by the <a href="filter.html">filter</a> task or explicitly provided to the
+copy operation
+as <a href="../Types/filterset.html">filtersets</a>.  <em>See <a href="#encoding">encoding
+note</a></em>.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to copy.</td>
-    <td valign="top" align="center">Yes, unless a nested
-    resource collection element is used.</td>
+    <td>file</td>
+    <td>The file to copy.</td>
+    <td>Yes, unless a nested resource collection element is used</td>
   </tr>
   <tr>
-    <td valign="top">preservelastmodified</td>
-    <td valign="top">Give the copied files the same last modified
-      time as the original source files.</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>preservelastmodified</td>
+    <td>Give the copied files the same last modified time as the original source files.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">tofile</td>
-    <td valign="top">The file to copy to.</td>
-    <td valign="top" align="center" rowspan="2">With the <code>file</code>
-      attribute, either <code>tofile</code> or <code>todir</code> can be used.<br/>
-
-      With nested resource collection elements, if the number of
-      included resources
-      is greater than 1, or if only the <code>dir</code> attribute is
-      specified in the <code>&lt;fileset&gt;</code>, or if the
-      <code>file</code> attribute is also specified, then only
-      <code>todir</code> is allowed.<br/>
-      <em>Prior to Apache Ant 1.8.2</em> the <code>tofile</code> attribute
-      only supported filesystem resources top copy from.</td>
+    <td>tofile</td>
+    <td>The file to copy to. Prior to Apache Ant 1.8.2, the <var>tofile</var> attribute only
+      supported <a href="../Types/resources.html#file">file resources</a> to copy from.</td>
+    <td rowspan="2">With the <var>file</var> attribute, either <var>tofile</var> or <var>todir</var>
+      can be used.<br/>  With nested resource collection elements, if the number of included
+      resources is greater than 1, or if only the <var>dir</var> attribute is specified in
+      the <code>&lt;fileset&gt;</code>, or if the <var>file</var> attribute is also specified, then
+      only <var>todir</var> is allowed.<br/></td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">The directory to copy to.</td>
+    <td>todir</td>
+    <td class="left">The directory to copy to.</td>
   </tr>
   <tr>
-    <td valign="top">overwrite</td>
-    <td valign="top">Overwrite existing files even if the destination
-      files are newer.</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>overwrite</td>
+    <td>Overwrite existing files even if the destination files are newer.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">Overwrite read-only destination
-      files.  <em>since Ant 1.8.2</em></td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>force</td>
+    <td>Overwrite read-only destination files.  <em>since Ant 1.8.2</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">filtering</td>
-    <td valign="top">Indicates whether token filtering using the <a href="../using.html#filters">global
-        build-file filters</a> should take place during the copy.
-      <em>Note</em>: Nested <code>&lt;filterset&gt;</code> elements will
-      always be used, even if this attribute is not specified, or its value is
-      <code>false</code> (<code>no</code>, or <code>off</code>).</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>filtering</td>
+    <td>Indicates whether token filtering using the <a href="../using.html#filters">global
+      build-file filters</a> should take place during the copy.  <strong>Note</strong>:
+      Nested <code>&lt;filterset&gt;</code> elements will always be used, even if this attribute is
+      not specified, or its value is <q>false</q>, <q>no</q>, or <q>off</q>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">flatten</td>
-    <td valign="top">Ignore the directory structure of the source files,
-      and copy all files into the directory specified by the <code>todir</code>
-      attribute.  Note that you can achieve the same effect by using a
-      <a href="../Types/mapper.html#flatten-mapper">flatten mapper</a>.</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>flatten</td>
+    <td>Ignore the directory structure of the source files, and copy all files into the directory
+      specified by the <var>todir</var> attribute.  Note that you can achieve the same effect by
+      using a <a href="../Types/mapper.html#flatten-mapper">flatten mapper</a>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includeEmptyDirs</td>
-     <td valign="top">Copy any empty directories included in the FileSet(s).
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>includeEmptyDirs</td>
+     <td>Copy any empty directories included in the FileSet(s).</td>
+     <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-     <td valign="top">If false, log a warning message, but do not stop the
-       build, when the file to copy does not exist or one of the nested
-       filesets points to a directory that doesn't exist or an error occurs
-       while copying.
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>failonerror</td>
+     <td>If <q>false</q>, log a warning message, but do not stop the build, when the file to copy
+       does not exist or one of the nested filesets points to a directory that doesn't exist or an
+       error occurs while copying.</td>
+     <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-      <td valign="top">If true and failonerror is false, then do not log a
-       warning message when the file to copy does not exist or one of the nested
-       filesets points to a directory that doesn't exist or an error occurs
-       while copying. <em>since Ant 1.8.3</em>.
-     </td>
-     <td valign="top" align="center">No; defaults to false.</td>
+    <td>quiet</td>
+    <td>If <q>true</q> and <var>failonerror</var> is <q>false</q>, then do not log a warning message
+       when the file to copy does not exist or one of the nested filesets points to a directory that
+       doesn't exist or an error occurs while copying. <em>since Ant 1.8.3</em>.</td>
+     <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-     <td valign="top">Log the files that are being copied.</td>
-     <td valign="top" align="center">No; defaults to false.</td>
+    <td>verbose</td>
+     <td>Log the files that are being copied.</td>
+     <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding to assume when filter-copying the
-    files. <em>since Ant 1.5</em>.</td>
-    <td align="center">No - defaults to default JVM encoding</td>
+    <td>encoding</td>
+    <td>The encoding to assume when filter-copying the files. <em>since Ant 1.5</em>.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">outputencoding</td>
-    <td valign="top">The encoding to use when writing the files.
+    <td>outputencoding</td>
+    <td>The encoding to use when writing the files.
     <em>since Ant 1.6</em>.</td>
-    <td align="center">No - defaults to the value of the encoding
-    attribute if given or the default JVM encoding otherwise.</td>
+    <td>No; defaults to <var>encoding</var> if set or default JVM character encoding otherwise</td>
   </tr>
   <tr>
-    <td valign="top">enablemultiplemappings</td>
-    <td valign="top">
-      If true the task will process to all the mappings for a
-      given source path. If false the task will only process
-      the first file or directory. This attribute is only relevant
-      if there is a mapper subelement.
-      <em>since Ant 1.6</em>.</td>
-    <td align="center">No - defaults to false.</td>
+    <td>enablemultiplemappings</td>
+    <td>If <q>true</q> the task will process to all the mappings for a given source
+      path. If <q>false</q> the task will only process the first file or directory. This attribute
+      is only relevant if there is a <code>mapper</code> subelement.  <em>since Ant 1.6</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">granularity</td>
-    <td valign="top">The number of milliseconds leeway to give before
-    deciding a file is out of date. This is needed because not every
-    file system supports tracking the last modified time to the
-    millisecond level. Default is 1 second, or 2 seconds on DOS
-    systems.  This can also be useful if source and target files live
-    on separate machines with clocks being out of sync.  <em>since Ant
-    1.6.2</em>.</td>
-    <td align="center">No</td>
+    <td>granularity</td>
+    <td>The number of milliseconds leeway to give before deciding a file is out of date. This is
+      needed because not every file system supports tracking the last modified time to the
+      millisecond level. This can also be useful if source and target files live on separate
+      machines with clocks being out of sync. <em>since Ant 1.6.2</em>.</td>
+    <td>No; default is 1 second, or 2 seconds on DOS systems</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
-<h4>fileset or any other resource collection</h4>
-<p><a href="../Types/resources.html#collection">Resource
-Collection</a>s are used to select groups of files to copy.  To use a
-resource collection, the <code>todir</code> attribute must be set.</p>
-<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> has been
-supported as a nested element.</p>
+<h4>any filesystem based resource collection</h4>
+<p><a href="../Types/resources.html#collection">Resource collections</a> are used to select groups
+of files to copy.  To use a resource collection, the <var>todir</var> attribute must be set.</p>
+<p>Prior to Ant 1.7, only <code>&lt;fileset&gt;</code> has been supported as a nested element.</p>
 
 <h4>mapper</h4>
- <p>You can define filename transformations by using a nested <a
- href="../Types/mapper.html">mapper</a> element. The default mapper used by
- <code>&lt;copy&gt;</code> is the <a
- href="../Types/mapper.html#identity-mapper">identity mapper</a>.</p>
-  <p>
-    <em>Since Ant 1.6.3</em>,
-    one can use a filenamemapper type in place of the mapper element.
-  </p>
+<p>You can define filename transformations by using a
+nested <a href="../Types/mapper.html">mapper</a> element. The default mapper used
+by <code>&lt;copy&gt;</code> is the <a href="../Types/mapper.html#identity-mapper">identity
+mapper</a>.</p>
+<p><em>Since Ant 1.6.3</em>, one can use a filenamemapper type in place of the mapper element.</p>
 
-<p>Note that the source name handed to the mapper depends on the
-resource collection you use.  If you use <code>&lt;fileset&gt;</code>
-or any other collection that provides a base directory, the name
-passed to the mapper will be a relative filename, relative to the base
-directory.  In any other case the absolute filename of the source will
-be used.</p>
+<p>Note that the source name handed to the mapper depends on the resource collection you use.  If
+you use <code>&lt;fileset&gt;</code> or any other collection that provides a base directory, the
+name passed to the mapper will be a relative filename, relative to the base directory.  In any other
+case the absolute filename of the source will be used.</p>
 
 <h4>filterset</h4>
- <p><a href="../Types/filterset.html">FilterSet</a>s are used to replace
-tokens in files that are copied.
- To use a FilterSet, use the nested <code>&lt;filterset&gt;</code> element.</p>
+<p><a href="../Types/filterset.html">FilterSet</a>s are used to replace tokens in files that are
+copied.  To use a FilterSet, use the nested <code>&lt;filterset&gt;</code> element.</p>
 
 <p>It is possible to use more than one filterset.</p>
 
 <h4>filterchain</h4>
-<p>The Copy task supports nested <a href="../Types/filterchain.html">
-FilterChain</a>s.</p>
+<p>The Copy task supports nested <a href="../Types/filterchain.html">FilterChain</a>s.</p>
 
-<p>
-If <code>&lt;filterset&gt;</code> and <code>&lt;filterchain&gt;</code> elements are used inside the
-same <code>&lt;copy&gt;</code> task, all <code>&lt;filterchain&gt;</code> elements are processed first
-followed by <code>&lt;filterset&gt;</code> elements.
-</p>
+<p>If <code>&lt;filterset&gt;</code> and <code>&lt;filterchain&gt;</code> elements are used inside
+the same <code>&lt;copy&gt;</code> task, all <code>&lt;filterchain&gt;</code> elements are processed
+first followed by <code>&lt;filterset&gt;</code> elements.</p>
 
 <h3>Examples</h3>
-<p><b>Copy a single file</b></p>
-<pre>
-  &lt;copy file=&quot;myfile.txt&quot; tofile=&quot;mycopy.txt&quot;/&gt;
-</pre>
-<p><b>Copy a single file to a directory</b></p>
-<pre>
-  &lt;copy file=&quot;myfile.txt&quot; todir=&quot;../some/other/dir&quot;/&gt;
-</pre>
-<p><b>Copy a directory to another directory</b></p>
-<pre>
-  &lt;copy todir=&quot;../new/dir&quot;&gt;
-    &lt;fileset dir=&quot;src_dir&quot;/&gt;
-  &lt;/copy&gt;
-</pre>
-<p><b>Copy a set of files to a directory</b></p>
-<pre>
-  &lt;copy todir=&quot;../dest/dir&quot;&gt;
-    &lt;fileset dir=&quot;src_dir&quot;&gt;
-      &lt;exclude name=&quot;**/*.java&quot;/&gt;
-    &lt;/fileset&gt;
-  &lt;/copy&gt;
 
-  &lt;copy todir=&quot;../dest/dir&quot;&gt;
-    &lt;fileset dir=&quot;src_dir&quot; excludes=&quot;**/*.java&quot;/&gt;
-  &lt;/copy&gt;
-</pre>
-<p><b>Copy a set of files to a directory, appending
-<code>.bak</code> to the file name on the fly</b></p>
+<p>Copy a single file</p>
+<pre>&lt;copy file=&quot;myfile.txt&quot; tofile=&quot;mycopy.txt&quot;/&gt;</pre>
+
+<p>Copy a single file to a directory</p>
+<pre>&lt;copy file=&quot;myfile.txt&quot; todir=&quot;../some/other/dir&quot;/&gt;</pre>
+
+<p>Copy a directory to another directory</p>
 <pre>
-  &lt;copy todir=&quot;../backup/dir&quot;&gt;
-    &lt;fileset dir=&quot;src_dir&quot;/&gt;
-    &lt;globmapper from=&quot;*&quot; to=&quot;*.bak&quot;/&gt;
-  &lt;/copy&gt;
+&lt;copy todir=&quot;../new/dir&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot;/&gt;
+&lt;/copy&gt;
 </pre>
 
-<p><b>Copy a set of files to a directory, replacing @TITLE@ with Foo Bar
-in all files.</b></p>
+<p>Copy a set of files to a directory</p>
 <pre>
-  &lt;copy todir=&quot;../backup/dir&quot;&gt;
-    &lt;fileset dir=&quot;src_dir&quot;/&gt;
-    &lt;filterset&gt;
-      &lt;filter token=&quot;TITLE&quot; value=&quot;Foo Bar&quot;/&gt;
-    &lt;/filterset&gt;
-  &lt;/copy&gt;
-</pre>
+&lt;copy todir=&quot;../dest/dir&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot;&gt;
+    &lt;exclude name=&quot;**/*.java&quot;/&gt;
+  &lt;/fileset&gt;
+&lt;/copy&gt;
 
-<p><b>Collect all items from the current CLASSPATH setting into a
-destination directory, flattening the directory structure.</b></p>
+&lt;copy todir=&quot;../dest/dir&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot; excludes=&quot;**/*.java&quot;/&gt;
+&lt;/copy&gt;</pre>
+
+<p>Copy a set of files to a directory, appending <samp>.bak</samp> to the file name on the
+fly</p>
 <pre>
-  &lt;copy todir=&quot;dest&quot; flatten=&quot;true&quot;&gt;
-    &lt;path&gt;
-      &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
-    &lt;/path&gt;
-  &lt;/copy&gt;
-</pre>
+&lt;copy todir=&quot;../backup/dir&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot;/&gt;
+  &lt;globmapper from=&quot;*&quot; to=&quot;*.bak&quot;/&gt;
+&lt;/copy&gt;</pre>
 
-<p><b>Copies some resources to a given directory.</b></p>
+<p>Copy a set of files to a directory, replacing <code>@TITLE@</code> with <samp>Foo
+Bar</samp> in all files.</p>
 <pre>
-  &lt;copy todir=&quot;dest&quot; flatten=&quot;true&quot;&gt;
-    &lt;resources&gt;
-      &lt;file file=&quot;src_dir/file1.txt&quot;/&gt;
-      &lt;url url=&quot;http://ant.apache.org/index.html&quot;/&gt;
-    &lt;/resources&gt;
-  &lt;/copy&gt;
-</pre>
+&lt;copy todir=&quot;../backup/dir&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot;/&gt;
+  &lt;filterset&gt;
+    &lt;filter token=&quot;TITLE&quot; value=&quot;Foo Bar&quot;/&gt;
+  &lt;/filterset&gt;
+&lt;/copy&gt;</pre>
 
-<p>If the example above didn't use the flatten attribute,
-  the <code>&lt;file&gt;</code> resource would have returned its full
-  path as source and target name and would not have been copied at
-  all.  In general it is a good practice to use an explicit mapper
-  together with resources that use an absolute path as their
-  names.</p>
-
-<p><b>Copies the two newest resources into a destination directory.</b></p>
+<p>Collect all items from the current <code>CLASSPATH</code> setting into a destination
+directory, flattening the directory structure.</p>
 <pre>
-  &lt;copy todir=&quot;dest&quot; flatten=&quot;true&quot;&gt;
-    &lt;first count=&quot;2&quot;&gt;
-      &lt;sort&gt;
-        &lt;date xmlns=&quot;antlib:org.apache.tools.ant.types.resources.comparators&quot;/&gt;
-        &lt;resources&gt;
-          &lt;file file=&quot;src_dir/file1.txt&quot;/&gt;
-          &lt;file file=&quot;src_dir/file2.txt&quot;/&gt;
-          &lt;file file=&quot;src_dir/file3.txt&quot;/&gt;
-          &lt;url url=&quot;http://ant.apache.org/index.html&quot;/&gt;
-        &lt;/resources&gt;
-      &lt;/sort&gt;
-    &lt;/first&gt;
-  &lt;/copy&gt;
-</pre>
+&lt;copy todir=&quot;dest&quot; flatten=&quot;true&quot;&gt;
+  &lt;path&gt;
+    &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
+  &lt;/path&gt;
+&lt;/copy&gt;</pre>
 
-<p>The paragraph following the previous example applies to this
-  example as well.</p>
+<p>Copies some resources to a given directory.</p>
+<pre>
+&lt;copy todir=&quot;dest&quot; flatten=&quot;true&quot;&gt;
+  &lt;resources&gt;
+    &lt;file file=&quot;src_dir/file1.txt&quot;/&gt;
+    &lt;url url=&quot;https://ant.apache.org/index.html&quot;/&gt;
+  &lt;/resources&gt;
+&lt;/copy&gt;</pre>
 
-<p><strong>Unix Note:</strong> File permissions are not retained when files
-are copied; they end up with the default <code>UMASK</code> permissions
-instead. This
-is caused by the lack of any means to query or set file permissions in the
-current Java runtimes. If you need a permission-preserving copy function,
-use <code>&lt;exec executable="cp" ... &gt;</code> instead.
-</p>
+<p>If the example above didn't use the <var>flatten</var> attribute, the <code>&lt;file&gt;</code>
+resource would have returned its full path as source and target name and would not have been copied
+at all.  In general it is a good practice to use an explicit mapper together with resources that use
+an absolute path as their names.</p>
 
-<p><strong>Windows Note:</strong> If you copy a file to a directory
-where that file already exists, but with different casing,
-the copied file takes on the case of the original. The workaround is to
-<a href="delete.html">delete</a>
-the file in the destination directory before you copy it.
-</p>
-  <p>
-    <strong><a name="encoding">Important Encoding Note:</a></strong>
-    The reason that binary files when filtered get corrupted is that
-    filtering involves reading in the file using a Reader class. This
-    has an encoding specifying how files are encoded. There are a number
-    of different types of encoding - UTF-8, UTF-16, Cp1252, ISO-8859-1,
-    US-ASCII and (lots) others. On Windows the default character encoding
-    is Cp1252, on Unix it is usually UTF-8. For both of these encoding
-    there are illegal byte sequences (more in UTF-8 than for Cp1252).
-  </p>
-  <p>
-    How the Reader class deals with these illegal sequences is up to the
-    implementation
-    of the character decoder. The current Sun Java implementation is to
-    map them to legal characters. Previous Sun Java (1.3 and lower) threw
-    a MalformedInputException. IBM Java 1.4 also throws this exception.
-    It is the mapping of the characters that cause the corruption.
-  </p>
-  <p>
-    On Unix, where the default is normally UTF-8, this is a <em>big</em>
-    problem, as it is easy to edit a file to contain non US Ascii characters
-    from ISO-8859-1, for example the Danish oe character. When this is
-    copied (with filtering) by Ant, the character get converted to a
-    question mark (or some such thing).
-  </p>
-  <p>
-    There is not much that Ant can do. It cannot figure out which
-    files are binary - a UTF-8 version of Korean will have lots of
-    bytes with the top bit set. It is not informed about illegal
-    character sequences by current Sun Java implementions.
-  </p>
-  <p>
-    One trick for filtering containing only US-ASCII is to
-    use the ISO-8859-1 encoding. This does not seem to contain
-    illegal character sequences, and the lower 7 bits are US-ASCII.
-    Another trick is to change the LANG environment variable from
-    something like "us.utf8" to "us".
-  </p>
-    
+<p>Copies the two newest resources into a destination directory.</p>
+<pre>
+&lt;copy todir=&quot;dest&quot; flatten=&quot;true&quot;&gt;
+  &lt;first count=&quot;2&quot;&gt;
+    &lt;sort&gt;
+      &lt;date xmlns=&quot;antlib:org.apache.tools.ant.types.resources.comparators&quot;/&gt;
+      &lt;resources&gt;
+        &lt;file file=&quot;src_dir/file1.txt&quot;/&gt;
+        &lt;file file=&quot;src_dir/file2.txt&quot;/&gt;
+        &lt;file file=&quot;src_dir/file3.txt&quot;/&gt;
+        &lt;url url=&quot;https://ant.apache.org/index.html&quot;/&gt;
+      &lt;/resources&gt;
+    &lt;/sort&gt;
+  &lt;/first&gt;
+&lt;/copy&gt;</pre>
 
+<p>The paragraph following the previous example applies to this example as well.</p>
 
+<p><strong>Unix Note</strong>: File permissions are not retained when files are copied; they end up
+with the default <code>UMASK</code> permissions instead. This is caused by the lack of any means to
+query or set file permissions in the current Java runtimes. If you need a permission-preserving copy
+function, use <code>&lt;exec executable="cp" ... &gt;</code> instead.</p>
 
-</body></html>
+<p><strong>Windows Note</strong>: If you copy a file to a directory where that file already exists,
+but with different case, the copied file takes on the case of the original. The workaround is
+to <a href="delete.html">delete</a> the file in the destination directory before you copy it.</p>
+<p id="encoding"><strong>Important Encoding Note</strong>: The reason that binary files when
+filtered get corrupted is that filtering involves reading in the file using a Reader class. This has
+an encoding specifying how files are encoded. There are a number of different types of
+encoding&mdash;UTF-8, UTF-16, Cp1252, ISO-8859-1, US-ASCII and (lots of) others. On Windows the
+default character encoding is Cp1252, on Unix it is usually UTF-8. For both of these encoding there
+are illegal byte sequences (more in UTF-8 than for Cp1252).</p>
+<p>How the Reader class deals with these illegal sequences is up to the implementation of the
+character decoder. The current Sun Java implementation is to map them to legal characters. Previous
+Sun Java (1.3 and lower) threw a <code>MalformedInputException</code>. IBM Java 1.4 also throws this
+exception. It is the mapping of the characters that cause the corruption.</p>
+<p>On Unix, where the default is normally UTF-8, this is a <em>big</em> problem, as it is easy to
+edit a file to contain non US-ASCII characters from ISO-8859-1, for example the Danish &oelig;
+character. When this is copied (with filtering) by Ant, the character get converted to a question
+mark (or some such thing).</p>
+<p>There is not much that Ant can do. It cannot figure out which files are binary&mdash;a UTF-8
+version of Korean will have lots of bytes with the top bit set. It is not informed about illegal
+character sequences by current Sun Java implementations.</p>
+<p>One trick for filtering containing only US-ASCII is to use the ISO-8859-1 encoding. This does not
+seem to contain illegal character sequences, and the lower 7 bits are US-ASCII.  Another trick is to
+change the <code>LANG</code> environment variable from something like <q>us.utf8</q>
+to <q>us</q>.</p>
+
+</body>
+</html>
diff --git a/manual/Tasks/copydir.html b/manual/Tasks/copydir.html
index 9e9e60e..9f2bc0c 100644
--- a/manual/Tasks/copydir.html
+++ b/manual/Tasks/copydir.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,123 +15,115 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Copydir Task</title>
 </head>
 
 <body>
 
-<h2><a name="copydir">Copydir</a></h2>
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated.  Use the Copy task instead.</i></p>
+<h2 id="copydir">Copydir</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>.  Use the <code>Copy</code> task instead.</em></p>
 <h3>Description</h3>
 <p>Copies a directory tree from the source to the destination.</p>
-<p>It is possible to refine the set of files that are being copied. This can be
-done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and <i>defaultexcludes</i>
-attributes. With the <i>includes</i> or <i>includesfile</i> attribute you specify the files you want to
-have included by using patterns. The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
-the files you want to have excluded. This is also done with patterns. And
-finally with the <i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+<p>It is possible to refine the set of files that are being copied. This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+and <var>defaultexcludes</var> attributes. With the <var>includes</var> or <var>includesfile</var>
+attribute you specify the files you want to have included by using patterns. The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded. This is
+also done with patterns. And finally with the <var>defaultexcludes</var> attribute, you can specify
+whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
 inclusion/exclusion of files works, and how to write patterns.</p>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>src</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>src</var>) as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">the directory to copy.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>src</td>
+    <td>the directory to copy.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">the directory to copy to.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dest</td>
+    <td>the directory to copy to.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">filtering</td>
-    <td valign="top">indicates whether token filtering should take place during
-      the copy</td>
-    <td valign="top" align="center">No</td>
+    <td>filtering</td>
+    <td>indicates whether token filtering should take place during the copy</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">flatten</td>
-    <td valign="top">ignore directory structure of source directory,
-      copy all files into a single directory, specified by the <code>dest</code>
-      attribute (default is <code>false</code>).</td>
-    <td valign="top" align="center">No</td>
+    <td>flatten</td>
+    <td>ignore directory structure of source directory, copy all files into a single directory,
+      specified by the <code>dest</code> attribute.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">forceoverwrite</td>
-    <td valign="top">overwrite existing files even if the destination
-      files are newer (default is false).</td>
-    <td valign="top" align="center">No</td>
+    <td>forceoverwrite</td>
+    <td>overwrite existing files even if the destination files are newer.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;copydir src=&quot;${src}/resources&quot;
-           dest=&quot;${dist}&quot;
-  /&gt;</pre>
-<p>copies the directory <code>${src}/resources</code> to <code>${dist}</code>.</p>
-<pre>  &lt;copydir src=&quot;${src}/resources&quot;
-           dest=&quot;${dist}&quot;
-           includes=&quot;**/*.java&quot;
-           excludes=&quot;**/Test.java&quot;
-  /&gt;</pre>
-<p>copies the directory <code>${src}/resources</code> to <code>${dist}</code>
-recursively. All java files are copied, except for files with the name <code>Test.java</code>.</p>
-<pre>  &lt;copydir src=&quot;${src}/resources&quot;
-           dest=&quot;${dist}&quot;
-           includes=&quot;**/*.java&quot;
-           excludes=&quot;mypackage/test/**&quot;/&gt;</pre>
-<p>copies the directory <code>${src}/resources</code> to <code>${dist}</code>
-recursively. All java files are copied, except for the files under the <code>mypackage/test</code>
-directory.</p>
+<p>Copy the directory <samp>${src}/resources</samp> to <samp>${dist}</samp>.</p>
+<pre>
+&lt;copydir src=&quot;${src}/resources&quot;
+         dest=&quot;${dist}&quot;/&gt;</pre>
 
+<p>Copy the directory <samp>${src}/resources</samp> to <samp>${dist}</samp>
+recursively. All <samp>.java</samp> files are copied, except for files with the
+name <samp>Test.java</samp>.</p>
+<pre>
+&lt;copydir src=&quot;${src}/resources&quot;
+         dest=&quot;${dist}&quot;
+         includes=&quot;**/*.java&quot;
+         excludes=&quot;**/Test.java&quot;/&gt;</pre>
+
+<p>Copy the directory <samp>${src}/resources</samp> to <samp>${dist}</samp>
+recursively. All <samp>.java</samp> files are copied, except for the files under
+the <samp>mypackage/test</samp> directory.</p>
+<pre>
+&lt;copydir src=&quot;${src}/resources&quot;
+         dest=&quot;${dist}&quot;
+         includes=&quot;**/*.java&quot;
+         excludes=&quot;mypackage/test/**&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/copyfile.html b/manual/Tasks/copyfile.html
index e204a7e..693f10b 100644
--- a/manual/Tasks/copyfile.html
+++ b/manual/Tasks/copyfile.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,60 +15,53 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Copyfile Task</title>
 </head>
 
 <body>
 
-<h2><a name="copyfile">Copyfile</a></h2>
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated.  Use the Copy task instead.</i></p>
+<h2 id="copyfile">Copyfile</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <em>deprecated</em>.  Use the <code>Copy</code> task instead.</em></p>
 <h3>Description</h3>
-<p>Copies a file from the source to the destination. The file is only copied if
-the source file is newer than the destination file, or when the destination file
-does not exist.</p>
+<p>Copies a file from the source to the destination. The file is only copied if the source file is
+newer than the destination file, or when the destination file does not exist.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">the filename of the file to copy.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>src</td>
+    <td>the filename of the file to copy.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">the filename of the file where to copy to.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dest</td>
+    <td>the filename of the file where to copy to.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">filtering</td>
-    <td valign="top">indicates whether token filtering should take place during
-      the copy</td>
-    <td valign="top" align="center">No</td>
+    <td>filtering</td>
+    <td>indicates whether token filtering should take place during the copy</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">forceoverwrite</td>
-    <td valign="top">overwrite existing files even if the destination
-      files are newer (default is false).</td>
-    <td valign="top" align="center">No</td>
+    <td>forceoverwrite</td>
+    <td>overwrite existing files even if the destination files are newer.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-  <p><code>&lt;copyfile src=&quot;test.java&quot; dest=&quot;subdir/test.java&quot;/&gt;</code></p>
-  <p><code>&lt;copyfile src=&quot;${src}/index.html&quot; dest=&quot;${dist}/help/index.html&quot;/&gt;</code></p>
-</blockquote>
-
+<pre>
+&lt;copyfile src=&quot;test.java&quot; dest=&quot;subdir/test.java&quot;/&gt;
+&lt;copyfile src=&quot;${src}/index.html&quot; dest=&quot;${dist}/help/index.html&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/cvs.html b/manual/Tasks/cvs.html
index e941ed6..fdb0832 100644
--- a/manual/Tasks/cvs.html
+++ b/manual/Tasks/cvs.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,144 +15,136 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>CVS Task</title>
 </head>
 
 <body>
 
-<h2><a name="cvs">Cvs</a></h2>
+<h2 id="cvs">Cvs</h2>
 <h3>Description</h3>
-<p>Handles packages/modules retrieved from a
-<a href="http://www.nongnu.org/cvs/" target="_top">CVS</a> repository.</p>
-<p><b>Important:</b> This task needs &quot;<code>cvs</code>&quot; on the path. If it isn't, you will get
-an error (such as error <code>2</code> on windows). If <code>&lt;cvs&gt;</code> doesn't work, try to execute <code>cvs.exe</code>
-from the command line in the target directory in which you are working.
-Also note that this task assumes that the cvs executable is compatible
-with the Unix version from cvshome.org, this is not completely true
-for certain other cvs clients - like CVSNT for example - and some
-operation may fail when using such an incompatible client.
-</p>
+<p>Handles packages/modules retrieved from a <a href="https://www.nongnu.org/cvs/"
+target="_top">CVS</a> repository.</p>
+<p><strong>Important:</strong> This task needs <kbd>cvs</kbd> binary on the path. If it isn't, you
+will get an error (such as <code>error=2</code> on Windows). If <code>&lt;cvs&gt;</code> doesn't
+work, try to execute <kbd>cvs.exe</kbd> from the command line in the target directory in which you
+are working.  Also note that this task assumes that the <kbd>cvs</kbd> executable is compatible with
+the Unix version, this is not completely true for certain other CVS clients&mdash;like CVSNT for
+example&mdash;and some operation may fail when using such an incompatible client.</p>
 
-<p><b>CVSNT Note</b>: CVSNT prefers users to store the passwords
-inside the registry.  If the <a href="cvspass.html">cvspass task</a>
-and the passfile attribute don't seem to work for you, the most likely
-reason is that CVSNT ignores your .cvspass file completely.  See <a
-href="http://issues.apache.org/bugzilla/show_bug.cgi?id=21657#c5">bugzilla
+<p><strong>CVSNT Note</strong>: CVSNT prefers users to store the passwords inside the registry.  If
+the <a href="cvspass.html">cvspass task</a> and the <var>passfile</var> attribute don't seem to work
+for you, the most likely reason is that CVSNT ignores your <samp>.cvspass</samp> file completely.
+See <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=21657#c5" target="_top">bugzilla
 report 21657</a> for recommended workarounds.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">command</td>
-    <td valign="top">the CVS command to execute.</td>
-    <td align="center" valign="top">No, default &quot;checkout&quot;.</td>
+    <td>command</td>
+    <td>the CVS command to execute.</td>
+    <td>No; default is <q>checkout</q></td>
   </tr>
   <tr>
-    <td valign="top">compression</td>
-    <td valign="top"><code>true</code> or <code>false</code> - if set
-    to true, this is the same as <code>compressionlevel=&quot;3&quot;</code></td>
-    <td align="center" valign="top">No. Defaults to false.</td>
+    <td>compression</td>
+    <td><q>true</q> (equivalent to <var>compressionlevel</var>=<q>3</q>) or <q>false</q></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">compressionlevel</td>
-    <td valign="top">A number between 1 and 9 (corresponding to
-    possible values for CVS' <code>-z#</code> argument). Any
-    other value is treated as <code>compression=&quot;false&quot;</code></td>
-    <td align="center" valign="top">No. Defaults to no compression.</td>
-  </tr>
-
-  <tr>
-    <td valign="top">cvsRoot</td>
-    <td valign="top">the <code>CVSROOT</code> variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>compressionlevel</td>
+    <td>A number between <q>1</q> and <q>9</q> (corresponding to possible values for
+      CVS <kbd>-z#</kbd> argument). Any other value is treated
+      as <var>compression</var>=<q>false</q></td>
+    <td>No; defaults to no compression</td>
   </tr>
   <tr>
-    <td valign="top">cvsRsh</td>
-    <td valign="top">the <code>CVS_RSH</code> variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRoot</td>
+    <td>the <code>CVSROOT</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">the directory where the checked out files should
-    be placed.  Note that this is different from CVS's <code>-d</code> command line
-    switch as Apache Ant will never shorten pathnames to avoid empty
-    directories.</td>
-    <td align="center" valign="top">No, default is project's basedir.</td>
+    <td>cvsRsh</td>
+    <td>the <code>CVS_RSH</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">the package/module to check out.  <b>Note:</b>
-      multiple attributes can be split using spaces.  Use a nested
-      &lt;module&gt; element if you want to specify a module with
-      spaces in its name.</td>
-    <td align="center" valign="top">No</td>
+    <td>dest</td>
+    <td>the directory where the checked out files should be placed.  Note that this is different
+      from CVS's <kbd>-d</kbd> command line switch as Apache Ant will never shorten pathnames to
+      avoid empty directories.</td>
+    <td>No; default is project's <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">tag</td>
-    <td valign="top">the tag of the package/module to check out.</td>
-    <td align="center" valign="top">No</td>
+    <td>package</td>
+    <td>the package/module to check out.  <strong>Note</strong>: multiple attributes can be split
+      using spaces.  Use a nested <code>&lt;module&gt;</code> element if you want to specify a
+      module with spaces in its name.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">date</td>
-    <td valign="top">Use the most recent revision no later than the given date</td>
-    <td align="center" valign="top">No</td>
+    <td>tag</td>
+    <td>the tag of the package/module to check out.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">suppress informational messages. This is the same as <code>-q</code> on the command line.</td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>date</td>
+    <td>Use the most recent revision no later than the given date</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">reallyquiet</td>
-    <td valign="top">suppress all messages. This is the same as
-      <code>-Q</code> on the command line.  <em>since Ant 1.6</em>.</td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>quiet</td>
+    <td>suppress informational messages. This is the same as <kbd>-q</kbd> on the command
+    line.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">noexec</td>
-    <td valign="top">report only, don't change any files.</td>
-    <td align="center" valign="top">No, default to &quot;false&quot;</td>
+    <td>reallyquiet</td>
+    <td>suppress all messages. This is the same as <kbd>-Q</kbd> on the command line.  <em>since
+      Ant 1.6</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">the file to direct standard output from the command.</td>
-    <td align="center" valign="top">No, default output to ANT Log as <code>MSG_INFO</code>.</td>
+    <td>noexec</td>
+    <td>report only, don't change any files.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">error</td>
-    <td valign="top">the file to direct standard error from the command.</td>
-    <td align="center" valign="top">No, default error to ANT Log as <code>MSG_WARN</code>.</td>
+    <td>output</td>
+    <td>the file to direct standard output from the command.</td>
+    <td>No; default is output to the log as <code>MSG_INFO</code></td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">whether to append output/error when redirecting to a file.</td>
-    <td align="center" valign="top">No, default to &quot;false&quot;.</td>
+    <td>error</td>
+    <td>the file to direct standard error from the command.</td>
+    <td>No; default is error to the log as <code>MSG_WARN</code></td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">Port used by CVS to communicate with the server.</td>
-    <td align="center" valign="top">No, default port <code>2401</code>.</td>
+    <td>append</td>
+    <td>whether to append output/error when redirecting to a file.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">passfile</td>
-    <td valign="top">Password file to read passwords from.</td>
-    <td align="center" valign="top">No, default file <code>~/.cvspass</code>.</td>
+    <td>port</td>
+    <td>Port used by CVS to communicate with the server.</td>
+    <td>No; default is <q>2401</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the build process if the command exits with a
-      return code other than <code>0</code>. Defaults to &quot;false&quot;</td>
-    <td align="center" valign="top">No</td>
+    <td>passfile</td>
+    <td>Password file to read passwords from.</td>
+    <td>No; default is <q>~/.cvspass</q></td>
+  </tr>
+  <tr>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
@@ -159,39 +152,40 @@
 
 <h4>module</h4>
 
-<p>Specifies a package/module to work on, unlike the package attribute
-  modules specified using this attribute can contain spaces in their
-  name.</p>
+<p>Specifies a package/module to work on, unlike the package attribute modules specified using this
+attribute can contain spaces in their name.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The module's/package's name.</td>
-    <td align="center" valign="top">Yes.</td>
+    <td>name</td>
+    <td>The module's/package's name.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<pre>  &lt;cvs cvsRoot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
-       package=&quot;ant&quot;
-       dest=&quot;${ws.dir}&quot;
-  /&gt;</pre>
-<p>checks out the package/module &quot;ant&quot; from the CVS
-repository pointed to by the <code>cvsRoot</code> attribute, and stores the files in &quot;<code>${ws.dir}</code>&quot;.</p>
-<pre>  &lt;cvs dest=&quot;${ws.dir}&quot; command=&quot;update&quot;/&gt;</pre>
-<p>updates the package/module that has previously been checked out into
-&quot;<code>${ws.dir}</code>&quot;.</p>
 
-<pre>  &lt;cvs command=&quot;-q diff -u -N&quot; output=&quot;patch.txt&quot;/&gt;</pre>
+<p>Check out the package/module <samp>ant</samp> from the CVS repository pointed to by
+the <var>cvsRoot</var> attribute, and store the files in <samp>${ws.dir}</samp>.</p>
+<pre>
+&lt;cvs cvsRoot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
+     package=&quot;ant&quot;
+     dest=&quot;${ws.dir}&quot;/&gt;</pre>
 
-<p>silently (<code>-q</code>) creates a file called <code>patch.txt</code> which contains a unified (<code>-u</code>) diff which includes new files added via &quot;cvs add&quot; (<code>-N</code>) and can be used as input to patch.
-The equivalent, using  <code>&lt;commandline&gt;</code> elements, is:
-</p>
+<p>Update the package/module that has previously been checked out into <samp>${ws.dir}</samp>.</p>
+<pre>&lt;cvs dest=&quot;${ws.dir}&quot; command=&quot;update&quot;/&gt;</pre>
+
+<p>Silently (<kbd>-q</kbd>) create a file called <samp>patch.txt</samp> containing a unified
+(<kbd>-u</kbd>) diff which includes new files added via <kbd>cvs add</kbd> (<kbd>-N</kbd>) and can
+be used as input to <kbd>patch</kbd>.</p>
+<pre>&lt;cvs command=&quot;-q diff -u -N&quot; output=&quot;patch.txt&quot;/&gt;</pre>
+
+<p>The equivalent, using <code>&lt;commandline&gt;</code> elements, is:</p>
 <pre>
 &lt;cvs output=&quot;patch&quot;&gt;
     &lt;commandline&gt;
@@ -200,31 +194,27 @@
         &lt;argument value=&quot;-u&quot;/&gt;
         &lt;argument value=&quot;-N&quot;/&gt;
     &lt;/commandline&gt;
-&lt;/cvs&gt;
-</pre>
-or:
+&lt;/cvs&gt;</pre>
+<p>or:</p>
 <pre>
 &lt;cvs output=&quot;patch&quot;&gt;
     &lt;commandline&gt;
         &lt;argument line=&quot;-q diff -u -N&quot;/&gt;
     &lt;/commandline&gt;
-&lt;/cvs&gt;
-</pre>
-<p>
-You may include as many <code>&lt;commandline&gt;</code> elements as you like. 
-Each will inherit the <code>failonerror</code>, <code>compression</code>, and other &quot;global&quot; parameters
-from the <code>&lt;cvs&gt;</code> element.
-</p>
+&lt;/cvs&gt;</pre>
+<p>You may include as many <code>&lt;commandline&gt;</code> elements as you like.  Each will inherit
+the <var>failonerror</var>, <var>compression</var>, and other &quot;global&quot; parameters from
+the <code>&lt;cvs&gt;</code> element.</p>
 
-
-<pre>  &lt;cvs command=&quot;update -A -d&quot;/&gt;</pre>
-<p>Updates from the head of repository ignoring sticky bits (<code>-A</code>) and creating any new directories as necessary (<code>-d</code>).</p>
-<p>Note: the text of the command is passed to cvs &quot;as-is&quot; so any cvs options should appear
-before the command, and any command options should appear after the command as in the diff example
-above. See <a href="http://ximbiot.com/cvs/wiki/index.php?title=Category:User_Documentation" target="_top">the cvs manual</a> for details,
-specifically the <a href="http://ximbiot.com/cvs/wiki/index.php?title=CVS--Concurrent_Versions_System_v1.12.12.1:_Guide_to_CVS_commands#SEC116" target="_top">Guide to CVS commands</a></p>
-
+<p>Update from the head of repository ignoring sticky bits (<kbd>-A</kbd>) and creating any new
+directories as necessary (<kbd>-d</kbd>).</p>
+<pre>&lt;cvs command=&quot;update -A -d&quot;/&gt;</pre>
+<p>Note: the text of the command is passed to <kbd>cvs</kbd> &quot;as-is&quot; so any <kbd>cvs</kbd>
+options should appear before the command, and any command options should appear after the command as
+in the <code>diff</code> example above. See <a href="http://cvsbook.red-bean.com/cvsbook.html"
+target="_top">the CVS book</a> for details, specifically
+the <a href="http://cvsbook.red-bean.com/cvsbook.html#Commands%20And%20Options" target="_top">Guide
+to CVS commands</a>.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/cvspass.html b/manual/Tasks/cvspass.html
index 185dde7..5c3a106 100644
--- a/manual/Tasks/cvspass.html
+++ b/manual/Tasks/cvspass.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,57 +15,54 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>CVSPass Task</title>
 </head>
 
 <body>
 
-<h2><a name="cvs">cvspass</a></h2>
+<h2 id="cvs">cvspass</h2>
 <h3>Description</h3>
-<p>Adds entries to a .cvspass file. Adding entries to this file has the same affect as a cvs login command.</p>
+<p>Adds entries to a <samp>.cvspass</samp> file. Adding entries to this file has the same affect as
+a <kbd>cvs login</kbd> command.</p>
 
-<p><b>CVSNT Note</b>: CVSNT prefers users to store the passwords
-inside the registry.  If the task doesn't seem to work for you, the
-most likely reason is that CVSNT ignores your .cvspass file
-completely.  See <a
-href="http://issues.apache.org/bugzilla/show_bug.cgi?id=21657#c5">bug
-zilla report 21657</a> for recommended workarounds.</p>
+<p><strong>CVSNT Note</strong>: CVSNT prefers users to store the passwords inside the registry.  If
+the task doesn't seem to work for you, the most likely reason is that CVSNT ignores
+your <samp>.cvspass</samp> file
+completely. See <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=21657#c5"
+target="_top">bugzilla report 21657</a> for recommended workarounds.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">cvsroot</td>
-    <td valign="top">the CVS repository to add an entry for.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>cvsroot</td>
+    <td>the CVS repository to add an entry for.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">Password to be added to the password file.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>password</td>
+    <td>Password to be added to the password file.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">passfile</td>
-    <td valign="top">Password file to add the entry to.</td>
-    <td align="center" valign="top">No, default is <code>~/.cvspass</code>.</td>
+    <td>passfile</td>
+    <td>Password file to add the entry to.</td>
+    <td>No; default is <q>~/.cvspass</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;cvspass cvsroot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
-       password=&quot;anoncvs&quot;
-  /&gt;</pre>
-<p>Adds an entry into the ~/.cvspass password file.</p>
-
+<p>Add an entry into the <samp>~/.cvspass</samp> password file.</p>
+<pre>
+&lt;cvspass cvsroot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
+         password=&quot;anoncvs&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/cvstagdiff.html b/manual/Tasks/cvstagdiff.html
index f4083a9..ad1c67e 100644
--- a/manual/Tasks/cvstagdiff.html
+++ b/manual/Tasks/cvstagdiff.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,124 +15,116 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>CvsTagDiff Task</title>
 </head>
 <body>
-<h2><a name="cvstagdiff">CvsTagDiff</a></h2>
+<h2 id="cvstagdiff">CvsTagDiff</h2>
 <h3>Description</h3>
-<p>Generates an XML-formatted report file of the changes between two tags or dates recorded in a
-<a href="http://www.nongnu.org/cvs/" target="_top">CVS</a> repository. </p>
-<p><b>Important:</b> This task needs &quot;<code>cvs</code>&quot; on the path. If it isn't, you will get
-an error (such as error <code>2</code> on windows). If <code>&lt;cvs&gt;</code> doesn't work, try to execute <code>cvs.exe</code>
-from the command line in the target directory in which you are working.
-Also note that this task assumes that the cvs executable is compatible
-with the Unix version from cvshome.org, this is not completely true
-for certain other cvs clients - like CVSNT for example - and some
-operation may fail when using such an incompatible client.
-</p>
+<p>Generates an XML-formatted report file of the changes between two tags or dates recorded in
+a <a href="https://www.nongnu.org/cvs/" target="_top">CVS</a> repository.</p>
+<p><strong>Important</strong>: This task needs <kbd>cvs</kbd> on the path. If it isn't, you will get
+an error (such as <code>error=2</code> on Windows). If <code>&lt;cvs&gt;</code> doesn't work, try to
+execute <kbd>cvs.exe</kbd> from the command line in the target directory in which you are working.
+Also note that this task assumes that the <kbd>cvs</kbd> executable is compatible with the Unix
+version, this is not completely true for certain other CVS clients&mdash;like CVSNT for
+example&mdash;and some operation may fail when using such an incompatible client.</p>
 <p>This task captures the output of the CVS command in a file inside of
   the <a href="../running.html#tmpdir">temporary directory</a>.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">startTag</td>
-    <td valign="top">The earliest tag from which diffs are to be
-     included in the report.</td>
-    <td align="center" valign="top" rowspan="2">exactly one of the two.</td>
+    <td>startTag</td>
+    <td>The earliest tag from which diffs are to be included in the report.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">startDate</td>
-    <td valign="top">The earliest date from which diffs are to be
-     included in the report.<br>
-     accepts all formats accepted by the cvs command for -D date_spec arguments</td>
+    <td>startDate</td>
+    <td class="left">The earliest date from which diffs are to be included in the
+     report.<br/>Accepts all formats accepted by the <kbd>cvs</kbd> command for <kbd>-D
+     date_spec</kbd> arguments.</td>
   </tr>
   <tr>
-    <td valign="top">endTag</td>
-    <td valign="top">The latest tag from which diffs are to be
-     included in the report.</td>
-    <td align="center" valign="top" rowspan="2">exactly one of the two.</td>
+    <td>endTag</td>
+    <td>The latest tag from which diffs are to be included in the report.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">endDate</td>
-    <td valign="top">The latest date from which diffs are to be
-     included in the report.<br>
-     accepts all formats accepted by the cvs command for -D date_spec arguments</td>
+    <td>endDate</td>
+    <td class="left">The latest date from which diffs are to be included in the report.<br/>Accepts
+     all formats accepted by the <kbd>cvs</kbd> command for <kbd>-D date_spec</kbd>
+     arguments.</td>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">The file in which to write the diff report.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>destfile</td>
+    <td>The file in which to write the diff report.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">ignoreRemoved</td>
-    <td valign="top">When set to true, the report will not include any
-      removed files.  <em>Since Apache Ant 1.8.0</em></td>
-    <td align="center" valign="top">No, defaults to false.</td>
+    <td>ignoreRemoved</td>
+    <td>When set to <q>true</q>, the report will not include any removed files.  <em>Since Apache
+      Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
 </table>
 
 <h3>Parameters inherited from the <code>cvs</code> task</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">compression</td>
-    <td valign="top"><code>true</code>, <code>false</code>, or the number 1-9 (corresponding to possible values for CVS <code>-z#</code> argument). Any other value is treated as false</td>
-    <td align="center" valign="top">No. Defaults to no compression. if passed <code>true</code>, level 3 compression is assumed.</td>
+    <td>compression</td>
+    <td><q>true</q> (equivalent to <q>3</q>), <q>false</q>, or a number between <q>1</q>
+    and <q>9</q> (corresponding to possible values for CVS <kbd>-z#</kbd> argument). Any other
+    value is treated as <q>false</q></td>
+    <td>No; defaults to no compression</td>
   </tr>
   <tr>
-    <td valign="top">cvsRoot</td>
-    <td valign="top">the CVSROOT variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRoot</td>
+    <td>the <code>CVSROOT</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">cvsRsh</td>
-    <td valign="top">the CVS_RSH variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRsh</td>
+    <td>the <code>CVS_RSH</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">the package/module to analyze.<br>
-    Since Ant 1.6
-    multiple packages separated by spaces are possible.
-    aliases corresponding to different modules are also possible
-    Use a nested &lt;module&gt; element if you want to specify a module with
-    spaces in its name.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-    <td align="center" valign="top">Yes</td>
+    <td>package</td>
+    <td>the package/module to analyze.<br/><em>Since Ant 1.6</em> multiple packages separated by
+      spaces are possible.  aliases corresponding to different modules are also possible.  Use a
+      nested <code>&lt;module&gt;</code> element if you want to specify a module with spaces in its
+      name.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">suppress informational messages.</td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>quiet</td>
+    <td>suppress informational messages.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">Port used by CVS to communicate with the server.</td>
-    <td align="center" valign="top">No, default port 2401.</td>
+    <td>port</td>
+    <td>Port used by CVS to communicate with the server.</td>
+    <td>No; default <q>2401</q></td>
   </tr>
   <tr>
-    <td valign="top">passfile</td>
-    <td valign="top">Password file to read passwords from.</td>
-    <td align="center" valign="top">No, default file <code>~/.cvspass</code>.</td>
+    <td>passfile</td>
+    <td>Password file to read passwords from.</td>
+    <td>No; default <q>~/.cvspass</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the buildprocess if the command exits with a
-      returncode other than 0. Defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
@@ -139,93 +132,98 @@
 
 <h4>module</h4>
 
-<p>Specifies a package/module to work on, unlike the package attribute
-  modules specified using this attribute can contain spaces in their
-  name.</p>
+<p>Specifies a package/module to work on, unlike the package attribute modules specified using this
+attribute can contain spaces in their name.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The module's/package's name.</td>
-    <td align="center" valign="top">Yes.</td>
+    <td>name</td>
+    <td>Name of the module/package.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<pre>  &lt;cvstagdiff cvsRoot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
-                destfile=&quot;tagdiff.xml&quot;
-                package=&quot;ant&quot;
-                startTag=&quot;ANT_14&quot;
-                endTag=&quot;ANT_141&quot;
-  /&gt;</pre>
+<p>Generate a <code>tagdiff</code> report for all the changes that have been made in
+  the <code>ant</code> module between the tags <samp>ANT_14</samp>
+  and <samp>ANT_141</samp>. Write these changes into the file <samp>tagdiff.xml</samp>.</p>
+<pre>
+&lt;cvstagdiff cvsRoot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
+            destfile=&quot;tagdiff.xml&quot;
+            package=&quot;ant&quot;
+            startTag=&quot;ANT_14&quot;
+            endTag=&quot;ANT_141&quot;/&gt;</pre>
 
-<p>Generates a tagdiff report for all the changes that have been made
-in the <code>ant</code> module between the tags <code>ANT_14</code> and <code>ANT_141</code>.
-It writes these changes into the file <code>tagdiff.xml</code>.</p>
+<p>Generate a <code>tagdiff</code> report for all the changes that have been made in
+  the <samp>ant</samp> module in January 2002. Write the changes into the
+  file <samp>tagdiff.xml</samp>. In this example, <var>cvsRoot</var> has not been
+  set. The current <var>cvsRoot</var> will be used (assuming the build is started from a folder stored
+  in CVS.</p>
+<pre>
+&lt;cvstagdiff destfile=&quot;tagdiff.xml&quot;
+            package=&quot;ant&quot;
+            startDate=&quot;2002-01-01&quot;
+            endDate=&quot;2002-31-01&quot;/&gt;</pre>
 
-<pre>  &lt;cvstagdiff
-                destfile=&quot;tagdiff.xml&quot;
-                package=&quot;ant&quot;
-                startDate=&quot;2002-01-01&quot;
-                endDate=&quot;2002-31-01&quot;
-  /&gt;</pre>
-
-<p>Generates a tagdiff report for all the changes that have been made
-in the <code>ant</code> module in january 2002. In this example <code>cvsRoot</code>
-has not been set. The current <code>cvsRoot</code> will be used (assuming the build is started
-from a folder stored in <code>cvs</code>.
-It writes these changes into the file <code>tagdiff.xml</code>.</p>
-
-<pre>  &lt;cvstagdiff
-                destfile=&quot;tagdiff.xml&quot;
-                package=&quot;ant jakarta-gump&quot;
-                startDate=&quot;2003-01-01&quot;
-                endDate=&quot;2003-31-01&quot;
-  /&gt;</pre>
-
-<p>Generates a tagdiff report for all the changes that have been made
-in the <code>ant</code> and <code>jakarta-gump</code> modules in january 2003.
-In this example <code>cvsRoot</code>
-has not been set. The current <code>cvsRoot</code> will be used (assuming the build is started
-from a folder stored in <code>cvs</code>.
-It writes these changes into the file <code>tagdiff.xml</code>.</p>
+<p>Generate a <code>tagdiff</code> report for all the changes that have been made in
+  the <samp>ant</samp> and <samp>jakarta-gump</samp> modules in January 2003. Write the changes into
+  the file <samp>tagdiff.xml</samp>. In this
+  example, <var>cvsRoot</var> has not been set. The current <var>cvsRoot</var> will be used (assuming
+  the build is started from a folder stored in CVS.</p>
+<pre>
+&lt;cvstagdiff destfile=&quot;tagdiff.xml&quot;
+            package=&quot;ant jakarta-gump&quot;
+            startDate=&quot;2003-01-01&quot;
+            endDate=&quot;2003-31-01&quot;/&gt;</pre>
 
 <h4>Generate Report</h4>
-<p>Ant includes a basic XSLT stylesheet that you can use to generate 
-a HTML report based on the xml output. The following example illustrates
-how to generate a HTML report from the XML report.</p>
+<p>Ant includes a basic XSLT stylesheet that you can use to generate a HTML report based on the XML
+output. The following example illustrates how to generate an HTML report from the XML report.</p>
 
 <pre>
-        &lt;style in="tagdiff.xml" 
-               out="tagdiff.html" 
-               style="${ant.home}/etc/tagdiff.xsl"&gt;
-          &lt;param name="title" expression="Ant Diff"/&gt;
-          &lt;param name="module" expression="ant"/&gt;
-          &lt;param name="cvsweb" expression="http://cvs.apache.org/viewcvs/"/&gt;
-        &lt;/style&gt;
-</pre>
+&lt;style in="tagdiff.xml"
+       out="tagdiff.html"
+       style="${ant.home}/etc/tagdiff.xsl"&gt;
+  &lt;param name="title" expression="Ant Diff"/&gt;
+  &lt;param name="module" expression="ant"/&gt;
+  &lt;param name="cvsweb" expression="https://cvs.apache.org/viewcvs/"/&gt;
+&lt;/style&gt;</pre>
 
 <h4>Output</h4>
-<p>
-The cvsroot and package attributes of the tagdiff element are new in ant 1.6.<br>
-Notes on entry attributes :
-<table border="1">
-<tr><th>Attribute</th><th>Comment</th></tr>
-<tr><td>name</td><td>when reporting on one package, the package name is removed from the output</td></tr>
-<tr><td>revision</td><td>supplied for files which exist at the end of the reporting period</td></tr>
-<tr><td>prevrevision</td><td>supplied for files which exist at the beginning of the reporting period.<br>
-Old CVS servers do not supply it for deleted files. CVS 1.12.2 supplies it.</td></tr>
+<p>The <var>cvsroot</var> and <var>package</var> attributes of the <code>&lt;tagdiff&gt;</code> element are
+  added <em>since Ant 1.6</em>.</p>
+
+<p>Description of <code>&lt;entry&gt;</code> attributes:</p>
+<table>
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Comment</th>
+  </tr>
+  <tr>
+    <td><var>name</var></td>
+    <td>when reporting on one package, the package name is removed from the output</td>
+  </tr>
+  <tr>
+    <td><var>revision</var></td>
+    <td>supplied for files which exist at the end of the reporting period</td>
+  </tr>
+  <tr>
+    <td><var>prevrevision</var></td>
+    <td>supplied for files which exist at the beginning of the reporting period.<br/>Old CVS servers
+      do not supply it for deleted files. CVS 1.12.2 supplies it.</td>
+  </tr>
 </table>
-</p>
+
+<p>Example:</p>
 <pre>
 &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
-&lt;tagdiff startTag=&quot;ANT_14&quot; endTag=&quot;ANT_141&quot; 
-cvsroot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot; package=&quot;ant&quot;&gt;
+&lt;tagdiff startTag=&quot;ANT_14&quot; endTag=&quot;ANT_141&quot;
+         cvsroot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot; package=&quot;ant&quot;&gt;
   &lt;entry&gt;
     &lt;file&gt;
       &lt;name&gt;src/main/org/apache/tools/ant/DirectoryScanner.java&lt;/name&gt;
@@ -236,8 +234,5 @@
 &lt;/tagdiff&gt;
 </pre>
 
-
-
 </body>
 </html>
-
diff --git a/manual/Tasks/cvsversion.html b/manual/Tasks/cvsversion.html
index 09e7cee..c75064c 100644
--- a/manual/Tasks/cvsversion.html
+++ b/manual/Tasks/cvsversion.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,95 +15,88 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>CVSVersion Task</title>
 </head>
 
 <body>
 
-<h2><a name="cvs">CvsVersion</a></h2>
+<h2 id="cvs">CvsVersion</h2>
+<p><em>Since Apache Ant 1.6.1</em>.</p>
 <h3>Description</h3>
-<p>
-This task allows to retrieve a CVS client and server version.
-  <i>Since Apache Ant 1.6.1.</i>
-</p>
+<p>This task allows to retrieve a CVS client and server version.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td colspan="3">Attributes from parent Cvs task which are meaningful here</td>
+    <td colspan="3" class="left">Attributes from parent <code>&lt;cvs&gt;</code> task which are
+    meaningful here</td>
   </tr>
   <tr>
-    <td valign="top">cvsRoot</td>
-    <td valign="top">the <code>CVSROOT</code> variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRoot</td>
+    <td>the <code>CVSROOT</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">cvsRsh</td>
-    <td valign="top">the <code>CVS_RSH</code> variable.</td>
-    <td align="center" valign="top">No</td>
+    <td>cvsRsh</td>
+    <td>the <code>CVS_RSH</code> variable.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">directory containing the checked out version of the project</td>
-    <td align="center" valign="top">No, default is project's basedir.</td>
+    <td>dest</td>
+    <td>directory containing the checked out version of the project</td>
+    <td>No; default is project's <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">the package/module to check out.</td>
-    <td align="center" valign="top">No</td>
+    <td>package</td>
+    <td>the package/module to check out.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">Port used by CVS to communicate with the server.</td>
-    <td align="center" valign="top">No, default port 2401.</td>
+    <td>port</td>
+    <td>Port used by CVS to communicate with the server.</td>
+    <td>No; default is <q>2401</q></td>
   </tr>
   <tr>
-    <td valign="top">passfile</td>
-    <td valign="top">Password file to read passwords from.</td>
-    <td align="center" valign="top">No, default file ~/.cvspass.</td>
+    <td>passfile</td>
+    <td>Password file to read passwords from.</td>
+    <td>No; default is <q>~/.cvspass</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the build process if the command exits with a
-      return code other than <code>0</code>. Defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td colspan="3">Specific attributes</td>
+    <td colspan="3" class="left">Specific attributes</td>
   </tr>
   <tr>
-    <td valign="top">clientversionproperty</td>
-    <td valign="top">Name of a property where the cvsclient version
-      should be stored</td>
-    <td align="center" valign="top">No</td>
+    <td>clientversionproperty</td>
+    <td>Name of a property where the CVS client version should be stored</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">serverversionproperty</td>
-    <td valign="top">Name of a property where the cvs server version
-      should be stored</td>
-    <td align="center" valign="top">No</td>
+    <td>serverversionproperty</td>
+    <td>Name of a property where the CVS server version should be stored</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;cvsversion cvsRoot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
-       passfile=&quot;/home/myself/.cvspass&quot;
-       serverversionproperty=&quot;apachecvsversion&quot;
-       clientversionproperty=&quot;localcvsversion&quot;
-  /&gt;</pre>
-<p>finds out the cvs client and server versions and stores the versions in the
-properties called apachecvsversion and localcvsversion</p>
 
-
+<p>Find out the CVS client and server versions and store the versions in the properties
+called <code>apachecvsversion</code> and <code>localcvsversion</code></p>
+<pre>
+&lt;cvsversion cvsRoot=&quot;:pserver:anoncvs@cvs.apache.org:/home/cvspublic&quot;
+            passfile=&quot;/home/myself/.cvspass&quot;
+            serverversionproperty=&quot;apachecvsversion&quot;
+            clientversionproperty=&quot;localcvsversion&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/defaultexcludes.html b/manual/Tasks/defaultexcludes.html
index 5511b90..4efcbb7 100644
--- a/manual/Tasks/defaultexcludes.html
+++ b/manual/Tasks/defaultexcludes.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,52 +15,49 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>DefaultExcludes Task</title>
 </head>
 
 <body>
 
-<h2><a name="echo">DefaultExcludes</a></h2>
+<h2 id="defaultexcludes">DefaultExcludes</h2>
 
-<p><em>since Apache Ant 1.6</em></p>
+<p><em>Since Apache Ant 1.6</em></p>
 
 <h3>Description</h3>
-<p>Alters the default excludes for all subsequent processing in the
-build, and prints out the current default excludes if desired.
+<p>Alters the default excludes for all subsequent processing in the build, and prints out the
+current default excludes if desired.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">echo</td>
-    <td valign="top">whether or not to print out the default excludes.(defaults to false)</td>
-    <td valign="top" align="center">attribute "true" required if no
-                                    other attribute specified</td>
+    <td>echo</td>
+    <td>whether or not to print out the default excludes</td>
+    <td><q>true</q> required if no other attribute specified; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">default</td>
-    <td valign="top">go back to hard wired default excludes</td>
-    <td valign="top" align="center">attribute "true" required if no
-    if no other attribute is specified</td>
+    <td>default</td>
+    <td>go back to hard wired default excludes</td>
+    <td><q>true</q> required if no other attribute is specified</td>
   </tr>
   <tr>
-    <td valign="top">add</td>
-    <td valign="top">the pattern to add to the default excludes</td>
-    <td valign="top" align="center">if no other attribute is specified</td>
+    <td>add</td>
+    <td>the pattern to add to the default excludes</td>
+    <td>if no other attribute is specified</td>
   </tr>
   <tr>
-    <td valign="top">remove</td>
-    <td valign="top">remove the specified pattern from the default excludes</td>
-    <td valign="top" align="center">if no other attribute is specified</td>
+    <td>remove</td>
+    <td>remove the specified pattern from the default excludes</td>
+    <td>if no other attribute is specified</td>
   </tr>
 </table>
 
@@ -67,41 +65,37 @@
 
 <p>Print out the default excludes</p>
 
-<pre>  &lt;defaultexcludes echo=&quot;true&quot;/&gt;</pre>
+<pre>&lt;defaultexcludes echo=&quot;true&quot;/&gt;</pre>
 
-<p>Print out the default excludes and exclude all *.bak files in
-<strong>all</strong> further processing</p>
+<p>Print out the default excludes and exclude all <samp>*.bak</samp> files in <strong>all</strong>
+further processing</p>
 
-<pre>  &lt;defaultexcludes echo=&quot;true&quot; add=&quot;**/*.bak&quot;/&gt;</pre>
+<pre>&lt;defaultexcludes echo=&quot;true&quot; add=&quot;**/*.bak&quot;/&gt;</pre>
 
-<p>Silently allow several fileset based tasks to operate on emacs
-backup files and then restore normal behavior</p>
+<p>Silently allow several fileset based tasks to operate on emacs backup files and then restore
+normal behavior</p>
 
 <pre>
-  &lt;defaultexcludes remove=&quot;**/*~&quot;/&gt;
+&lt;defaultexcludes remove=&quot;**/*~&quot;/&gt;
 
-  (do several fileset based tasks here)
+(do several fileset based tasks here)
 
-  &lt;defaultexcludes default=&quot;true&quot;/&gt;
-</pre>
+&lt;defaultexcludes default=&quot;true&quot;/&gt;</pre>
 
 <h3>Notes</h3>
-By default the pattern <tt>**/.svn</tt> and <tt>**/.svn/**</tt> are set as default 
-excludes. With version 1.3 Subversion supports the 
-<a target="_blank" href="http://subversion.apache.org/docs/release-notes/1.3.html#_svn-hack">&quot;_svn hack&quot;</a>.
-That means, that the svn-libraries evaluate environment variables and use <i>.svn</i> 
-or <i>_svn</i> directory regarding to that value. We had chosen not to evaluate environment variables to
-get a more reliable build. Instead you have to change the settings by yourself by changing
-the exclude patterns:
+<p>By default the pattern <samp>**/.svn</samp> and <samp>**/.svn/**</samp> are set as default
+excludes. Since version 1.3, Subversion supports
+the <a href="https://subversion.apache.org/docs/release-notes/1.3.html#_svn-hack"
+target="_top">&quot;_svn hack&quot;</a>.  That means, that the svn-libraries evaluate environment
+variables and use <samp>.svn</samp> or <samp>_svn</samp> directory regarding to that value. We had
+chosen not to evaluate environment variables to get a more reliable build. Instead you have to
+change the settings by yourself by changing the exclude patterns:</p>
 <pre>
-  &lt;defaultexcludes remove=&quot;**/.svn&quot;/&gt;
-  &lt;defaultexcludes remove=&quot;**/.svn/**&quot;/&gt;
-  &lt;defaultexcludes add=&quot;**/_svn&quot;/&gt;
-  &lt;defaultexcludes add=&quot;**/_svn/**&quot;/&gt;
+&lt;defaultexcludes remove=&quot;**/.svn&quot;/&gt;
+&lt;defaultexcludes remove=&quot;**/.svn/**&quot;/&gt;
+&lt;defaultexcludes add=&quot;**/_svn&quot;/&gt;
+&lt;defaultexcludes add=&quot;**/_svn/**&quot;/&gt;
 </pre>
 
-
-
-
 </body>
 </html>
diff --git a/manual/Tasks/delete.html b/manual/Tasks/delete.html
index 635b10f..a019de9 100644
--- a/manual/Tasks/delete.html
+++ b/manual/Tasks/delete.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,215 +15,184 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Delete Task</title>
 </head>
 
 <body>
 
-<h2><a name="delete">Delete</a></h2>
+<h2 id="delete">Delete</h2>
 <h3>Description</h3>
-<p>Deletes a single file, a specified directory and all its files and
-subdirectories, or a set of files specified by one or more
-<a href="../Types/resources.html#collection">resource collection</a>s.
-The literal implication of <code>&lt;fileset&gt;</code> is that
-directories are not included; however the removal of empty directories can
-be triggered when using nested filesets by setting the
-<code>includeEmptyDirs</code> attribute to <i>true</i>. Note that this
-attribute is meaningless in the context of any of the various resource
-collection types that <i>do</i> include directories, but that no attempt
-will be made to delete non-empty directories in any case.  Whether a
-directory is empty or not is decided by looking into the filesystem -
-include or exclude patterns don't apply here.</p>
-<p>
-If you use this task to delete temporary files created by editors
-and it doesn't seem to work, read up on the
-<a href="../dirtasks.html#defaultexcludes">default exclusion set</a>
-in <strong>Directory-based Tasks</strong>, and see the
-<code>defaultexcludes</code> attribute below.
+<p>Deletes a single file, a specified directory and all its files and subdirectories, or a set of
+files specified by one or more <a href="../Types/resources.html#collection">resource
+collection</a>s.  The literal implication of <code>&lt;fileset&gt;</code> is that directories are
+not included; however the removal of empty directories can be triggered when using nested filesets
+by setting the <var>includeEmptyDirs</var> attribute to <q>true</q>. Note that this attribute is
+meaningless in the context of any of the various resource collection types that <em>do</em> include
+directories, but that no attempt will be made to delete non-empty directories in any case.  Whether
+a directory is empty or not is decided by looking into the filesystem&mdash;include or exclude
+patterns don't apply here.</p>
+<p>If you use this task to delete temporary files created by editors and it doesn't seem to work,
+read up on the <a href="../dirtasks.html#defaultexcludes">default exclusion set</a>
+in <strong>Directory-based Tasks</strong>, and see the <code>defaultexcludes</code> attribute
+below.</p>
 
-<p>For historical reasons <code>&lt;delete dir="x"/&gt;</code> is
-  different from <code>&lt;delete&gt;&lt;fileset
-  dir="x"/&gt;&lt;/delete&gt;</code>, it will try to remove everything
-  inside "x" including "x" itself, not taking default excludes into
-  account, blindly following all symbolic links.  If you need more
-  control, use a nested <code>&lt;fileset&gt;</code>.</p>
+<p>For historical reasons <code>&lt;delete dir="x"/&gt;</code> is different
+from <code>&lt;delete&gt;&lt;fileset dir="x"/&gt;&lt;/delete&gt;</code>; it will try to remove
+everything inside <q>x</q> including <q>x</q> itself, not taking default excludes into account,
+blindly following all symbolic links.  If you need more control, use a
+nested <code>&lt;fileset&gt;</code>.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to delete, specified as either the simple
-     filename (if the file exists in the current base directory), a
-     relative-path filename, or a full-path filename.</td>
-    <td align="center" valign="middle" rowspan="2">At least one of the two,
-     unless nested resource collections are specified
+    <td>file</td>
+    <td>The file to delete, specified as either the simple filename (if the file exists in the
+      current base directory), a relative-path filename, or a full-path filename.</td>
+    <td rowspan="2">At least one of the two, unless nested resource collections are specified</td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The directory to delete, including all its files and
-     subdirectories.<br>
-     <b>Note:</b> <code>dir</code> is <em>not</em> used
-     to specify a directory name for <code>file</code>; <code>file</code>
-     and <code>dir</code> are independent of each other.<br>
-     <b>WARNING:</b> Do <b>not</b> set <code>dir</code> to
-     <code>&quot;.&quot;</code>, <code>&quot;${basedir}&quot;</code>,
-     or the full-pathname equivalent unless you truly <em>intend</em> to
-     recursively remove the entire contents of the current base directory
-     (and the base directory itself, if different from the current working
-     directory).</td>
+    <td>dir</td>
+    <td class="left">The directory to delete, including all its files and
+     subdirectories.<br/><strong>Note</strong>: <var>dir</var> is <em>not</em> used to specify a
+     directory name for <var>file</var>; <var>file</var> and <var>dir</var> are independent of each
+     other.<br/><strong>Warning</strong>: Do <strong>not</strong> set <var>dir</var>
+     to <q>.</q>, <q>${basedir}</q>, or the full-pathname equivalent unless you
+     truly <em>intend</em> to recursively remove the entire contents of the current base directory
+     (and the base directory itself, if different from the current working directory).</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to show the name of each deleted file.</td>
-    <td align="center" valign="top">No, default &quot;false&quot;</i></td>
+    <td>verbose</td>
+    <td>Whether to show the name of each deleted file.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">If the specified file or directory does not exist,
-     do not display a diagnostic message (unless Apache Ant
-     has been invoked with the <code>-verbose</code> or
-     <code>-debug</code> switches) or modify the exit status to
-     reflect an error.
-     When set to &quot;true&quot;, if a file or directory cannot be deleted,
-     no error is reported. This setting emulates the
-     <code>-f</code> option to the Unix <em>rm</em> command.
-     Setting this to &quot;true&quot; implies setting
-     <code>failonerror</code> to &quot;false&quot;.
-    </td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>quiet</td>
+    <td>If the specified file or directory does not exist, do not display a diagnostic message
+      (unless Apache Ant has been invoked with the <kbd>-verbose</kbd> or <kbd>-debug</kbd>
+      switches) or modify the exit status to reflect an error.  When set to <q>true</q>, if a file
+      or directory cannot be deleted, no error is reported. This setting emulates
+      the <kbd>-f</kbd> option to the Unix <em>rm</em> command.  Setting this to <q>true</q>
+      implies setting <var>failonerror</var> to <q>false</q>.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Controls whether an error (such as a failure to
-    delete a file) stops the build or is merely reported to the screen.
-    Only relevant if <code>quiet</code> is &quot;false&quot;.</td>
-    <td align="center" valign="top">No, default &quot;true&quot;</td>
+    <td>failonerror</td>
+    <td>Controls whether an error (such as a failure to delete a file) stops the build or is merely
+      reported to the screen.  Only relevant if <code>quiet</code> is <q>false</q>.</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">includeemptydirs</td>
-    <td valign="top">Whether to delete empty directories
-                     when using filesets.</td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>includeemptydirs</td>
+    <td>Whether to delete empty directories when using filesets.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top"><em>Deprecated.</em>  Use resource collections.
-      Comma- or space-separated list of patterns of
-      files that must be deleted. All files are relative to the directory
-      specified in <code>dir</code>.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td><em><u>Deprecated</u></em>.  Use resource collections.  Comma- or space-separated list of
+      patterns of files that must be deleted. All files are relative to the directory specified
+      in <var>dir</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top"><em>Deprecated.</em>  Use resource collections.
-      The name of a file. Each line of
-      this file is taken to be an include pattern.</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td><em><u>Deprecated</u></em>.  Use resource collections.  Name of a file; each line of this
+      file is taken to be an include pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top"><em>Deprecated.</em>  Use resource collections.
-      Comma- or space-separated list of patterns of
-      files that must be excluded from the deletion list.
-      All files are relative to the directory specified in <code>dir</code>.
-      No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td><em><u>Deprecated</u></em>.  Use resource collections.  Comma- or space-separated list of
+      patterns of files that must be excluded from the deletion list.  All files are relative to the
+      directory specified in <var>dir</var>.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top"><em>Deprecated.</em>  Use resource collections.
-      The name of a file. Each line of
-      this file is taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td><em><u>Deprecated</u></em>.  Use resource collections.  Name of a file; each line of this
+      file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top"><em>Deprecated.</em>  Use resource collections.
-      Whether to use <a href="../dirtasks.html#defaultexcludes">
-      default excludes.</a></td>
-    <td align="center" valign="top">No, default &quot;true&quot;</td>
+    <td>defaultexcludes</td>
+    <td><em><u>Deprecated</u></em>.  Use resource collections.  Whether to
+      use <a href="../dirtasks.html#defaultexcludes">default excludes.</a></td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">deleteonexit</td>
-    <td valign="top">
-      Indicates whether to use File#deleteOnExit() if there is a
-      failure to delete a file, this causes the jvm to attempt
-      to delete the file when the jvm process is terminating.
-      <em>Since Ant 1.6.2</em></td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>deleteonexit</td>
+    <td>Indicates whether to use <code>File#deleteOnExit()</code> if there is a failure to delete a
+      file. This causes the JVM to attempt to delete the file when the JVM process is
+      terminating.  <em>Since Ant 1.6.2</em></td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">removeNotFollowedSymlinks</td>
-    <td valign="top">
-      Whether symbolic links (not the files/directories they link to)
-      should be removed if they haven't been followed because
-      followSymlinks was false or the maximum number of symbolic links
-      was too big.
-      <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No, default &quot;false&quot;</td>
+    <td>removeNotFollowedSymlinks</td>
+    <td>Whether symbolic links (not the files/directories they link to) should be removed if they
+      haven't been followed because <var>followSymlinks</var> was <q>false</q> or the maximum number
+      of symbolic links was too big.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">performGCOnFailedDelete</td>
-    <td valign="top">
-      If Ant fails to delete a file or directory it will retry the
-      operation once.  If this flag is set to true it will perform a
-      garbage collection before retrying the delete.<br/>
-      Setting this flag to true is known to resolve some problems on
-      Windows (where it defaults to true) but also for directory trees
-      residing on an NFS share.
-      <em>Since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No, default &quot;true&quot; on
-      Windows and &quot;true&quot; on any other OS.</td>
+    <td>performGCOnFailedDelete</td>
+    <td>If Ant fails to delete a file or directory it will retry the operation once.  If this flag
+      is set to <q>true</q> it will perform a garbage collection before retrying the
+      delete.<br/>Setting this flag to true is known to resolve some problems on Windows (where it
+      defaults to <q>true</q>) but also for directory trees residing on an NFS share.  <em>Since Ant
+      1.8.3</em></td>
+    <td>No; default <q>true</q> on Windows and <q>true</q> on any other OS</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<pre>  &lt;delete file=&quot;/lib/ant.jar&quot;/&gt;</pre>
-<p>deletes the file <code>/lib/ant.jar</code>.</p>
-<pre>  &lt;delete dir=&quot;lib&quot;/&gt;</pre>
-<p>deletes the <code>lib</code> directory, including all files
-and subdirectories of <code>lib</code>.</p>
 
-<pre>  &lt;delete&gt;
-    &lt;fileset dir=&quot;.&quot; includes=&quot;**/*.bak&quot;/&gt;
-  &lt;/delete&gt;
+<p>Delete the file <samp>/lib/ant.jar</samp>.</p>
+<pre>&lt;delete file=&quot;/lib/ant.jar&quot;/&gt;</pre>
+
+<p>Delete the <samp>lib</samp> directory, including all files and subdirectories
+of <samp>lib</samp>.</p>
+<pre>&lt;delete dir=&quot;lib&quot;/&gt;</pre>
+
+<p>Delete all files with the extension <samp>.bak</samp> from the current directory and any
+subdirectories.</p>
+<pre>
+&lt;delete&gt;
+  &lt;fileset dir=&quot;.&quot; includes=&quot;**/*.bak&quot;/&gt;
+&lt;/delete&gt;
 </pre>
-<p>deletes all files with the extension <code>.bak</code> from the current directory
-and any subdirectories.</p>
 
-<pre>  &lt;delete includeEmptyDirs=&quot;true&quot;&gt;
-    &lt;fileset dir=&quot;build&quot;/&gt;
-  &lt;/delete&gt;
+<p>Delete all files and subdirectories of <samp>build</samp>, including <samp>build</samp>
+itself.</p>
+<pre>
+&lt;delete includeEmptyDirs=&quot;true&quot;&gt;
+  &lt;fileset dir=&quot;build&quot;/&gt;
+&lt;/delete&gt;
 </pre>
-<p>deletes all files and subdirectories of <code>build</code>, including
-<code>build</code> itself.</p>
 
-<pre>  &lt;delete includeemptydirs=&quot;true&quot;&gt;
-    &lt;fileset dir=&quot;build&quot; includes=&quot;**/*&quot;/&gt;
-  &lt;/delete&gt;
+<p>Delete all files and subdirectories of <samp>build</samp>, without <samp>build</samp> itself.</p>
+<pre>
+&lt;delete includeemptydirs=&quot;true&quot;&gt;
+  &lt;fileset dir=&quot;build&quot; includes=&quot;**/*&quot;/&gt;
+&lt;/delete&gt;
 </pre>
-<p>deletes all files and subdirectories of <code>build</code>, without
-<code>build</code> itself.</p>
 
-<pre>  &lt;delete includeemptydirs=&quot;true&quot;&gt;
-    &lt;fileset dir=&quot;src&quot; includes=&quot;**/.svn/&quot; defaultexcludes=&quot;false&quot;/&gt;
-  &lt;/delete&gt;
+<p>Delete the Subversion metadata directories under <samp>src</samp>. Because <samp>.svn</samp> is
+on of the <a href="../dirtasks.html#defaultexcludes">default excludes</a> you have to use
+the <var>defaultexcludes</var> flag, otherwise Ant won't delete these directories and the files in
+it.</p>
+<pre>
+&lt;delete includeemptydirs=&quot;true&quot;&gt;
+  &lt;fileset dir=&quot;src&quot; includes=&quot;**/.svn/&quot; defaultexcludes=&quot;false&quot;/&gt;
+&lt;/delete&gt;
 </pre>
-<p>deletes the subversion metadata directories under <code>src</code>. Because <code>.svn</code>
-is on of the <a href="../dirtasks.html#defaultexcludes">default excludes</a> you have to use the 
-<code>defaultexcludes</code> flag, otherwise Ant wont delete these directories and the files in it.</p>
-
-
 
 </body>
 </html>
diff --git a/manual/Tasks/deltree.html b/manual/Tasks/deltree.html
index 98adf4f..a60577e 100644
--- a/manual/Tasks/deltree.html
+++ b/manual/Tasks/deltree.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,43 +15,40 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Deltree Task</title>
 </head>
 
 <body>
 
-<h2><a name="deltree">Deltree</a></h2>
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated.  Use the Delete task instead.</i></p>
+<h2 id="deltree">Deltree</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>.  Use the <code>Delete</code> task instead.</em></p>
 <h3>Description</h3>
 <p>Deletes a directory with all its files and subdirectories.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the directory to delete.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dir</td>
+    <td>the directory to delete.</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;deltree dir=&quot;dist&quot;/&gt;</pre>
-<p>deletes the directory <code>dist</code>, including its files and
-subdirectories.</p>
-<pre>  &lt;deltree dir=&quot;${dist}&quot;/&gt;</pre>
-<p>deletes the directory <code>${dist}</code>, including its files and
-subdirectories.</p>
 
+<p>Delete the directory <samp>dist</samp>, including its files and subdirectories.</p>
+<pre>&lt;deltree dir=&quot;dist&quot;/&gt;</pre>
+
+<p>Delete the directory <samp>${dist}</samp>, including its files and subdirectories.</p>
+<pre>&lt;deltree dir=&quot;${dist}&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/depend.html b/manual/Tasks/depend.html
index a094319..c8dfb9b 100644
--- a/manual/Tasks/depend.html
+++ b/manual/Tasks/depend.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Depend Task</title>
 </head>
@@ -26,191 +26,169 @@
 
 <h2>Depend</h2>
 
-A task to manage Java class file dependencies.
+<p>A task to manage Java class file dependencies.</p>
 
 <h3>Description</h3>
 
-<p>
-The depend task works by determining which classes are out of date with
-respect to their source and then removing the class files of any other
-classes which depend on the out-of-date classes.
-</p>
+<p>The <code>depend</code> task works by determining which classes are out of date with respect to
+their source and then removing the class files of any other classes which depend on the out-of-date
+classes.</p>
 
-<p> To determine the class dependencies, the depend task analyzes the class 
-files of all class files passed to it. Depend does not parse your source code in 
-any way but relies upon the class references encoded into the class files by the 
-compiler. This is generally faster than parsing the Java source.</p>
+<p>To determine the class dependencies, the <code>depend</code> task analyzes the class files of all
+class files passed to it. The task does not parse your source code in any way but relies upon the
+class references encoded into the class files by the compiler. This is generally faster than parsing
+the Java source files.</p>
 
-<p>
-To learn more about how this information is obtained from the class files, 
-please refer to <a href="http://docs.oracle.com/javase/specs/">the Java
-Virtual Machine Specification</a>
-</p>
+<p>To learn more about how this information is obtained from the class files, please refer
+to <a href="https://docs.oracle.com/javase/specs/" target="_top">the Java Virtual Machine
+Specification</a></p>
 
-<p> Since a class' dependencies only change when the class itself changes, the 
-depend task is able to cache dependency information. Only those class files 
-which have changed will have their dependency information re-analysed. Note that 
-if you change a class' dependencies by changing the source, it will be 
-recompiled anyway. You can examine the dependency files created to understand 
-the  dependencies of your classes. Please do not rely, however, on the format of 
-the information, as it may change in a later release. </p>
+<p>Since a class' dependencies only change when the class itself changes, the
+<code>depend</code> task is able to cache dependency information. Only those class files which have
+changed will have their dependency information re-analysed. Note that if you change a class'
+dependencies by changing the source, it will be recompiled anyway. You can examine the dependency
+files created to understand the dependencies of your classes. Please do not rely, however, on the
+format of the information, as it may change in a later release.</p>
 
-<p> Once depend discovers all of the class dependencies, it &quot;inverts&quot; 
-this relation to determine, for each class, which other classes are dependent 
-upon it. This &quot;affects&quot; list is used to discover which classes are 
-invalidated by the out of date class. The class files of the invalidated 
-classes are removed, triggering the compilation of the affected classes. </p>
+<p>Once <code>depend</code> discovers all of the class dependencies, it &quot;inverts&quot; this
+relation to determine, for each class, which other classes are dependent upon it. This
+&quot;affects&quot; list is used to discover which classes are invalidated by the out of date
+class. The class files of the invalidated classes are removed, triggering the compilation of the
+affected classes.</p>
 
-<p> The depend task supports an attribute, &quot;closure&quot; which controls 
-whether depend will only consider direct class-class relationships or whether it 
-will also consider transitive, indirect relationships. For example, say there 
-are three classes, A, which depends on B, which in-turn depend on C. Now say 
-that class C is out of date. Without closure, only class B would be removed by 
-depend. With closure set, class A would also be removed. Normally direct 
-relationships are sufficient - it is unusual for a class to depend on another 
-without having a direct relationship. With closure set, you will notice that 
-depend typically removes far more class files. </p>
+<p>The <code>depend</code> task supports an attribute, <var>closure</var>, which controls
+whether <code>depend</code> will only consider direct class-class relationships or whether it will
+also consider transitive, indirect relationships. For example, say there are three classes, A, which
+depends on B, which in-turn depends on C. Now say that class C is out of
+date. Without <var>closure</var>, only class B would be removed
+by <code>depend</code>. With <var>closure</var> set, class A would also be removed. Normally direct
+relationships are sufficient&mdash;it is unusual for a class to depend on another without having a
+direct relationship. With <var>closure</var> set, you will notice that <code>depend</code> typically
+removes far more class files.</p>
 
-<p>The classpath attribute for <code>&lt;depend&gt;</code> is optional. If it is present, 
-depend will check class dependencies against classes and jars on this classpath.
-Any classes which depend on an element from this classpath and which are older 
-than that element will be deleted. A typical example where you would use this 
-facility would be where you are building a utility jar and want to make sure 
-classes which are out of date with respect to this jar are rebuilt. You should
-<b>not</b> include jars in this classpath which you do not expect to change, 
-such as the JDK runtime jar or third party jars, since doing so will just slow 
-down the dependency check. This means that if you do use a classpath for the 
-depend task it may be different from the classpath necessary to actually 
-compile your code.</p>
+<p>The <var>classpath</var> attribute for <code>&lt;depend&gt;</code> is optional. If it is
+present, <code>depend</code> will check class dependencies against classes and jars on this
+classpath.  Any classes which depend on an element from this classpath and which are older than that
+element will be deleted. A typical example where you would use this facility would be where you are
+building a utility jar and want to make sure classes which are out of date with respect to this jar
+are rebuilt. In this classpath, you should <strong>not</strong> include jars that you do not expect
+to change, such as the JDK runtime jar or third party jars, since doing so will just slow down the
+dependency check. This means that if you do use a classpath for the <code>depend</code> task it may
+be different from the classpath necessary to actually compile your code.</p>
 
-<h3>Performance</h3> 
+<h3>Performance</h3>
 
-<p> The performance of the depend task is dependent on a 
-number of factors such as class relationship complexity and how many class files 
-are out of date. The decision about whether it is cheaper to just recompile all 
-classes or to use the depend task will depend on the size of your project and 
-how interrelated your classes are. </p>
-
+<p>The performance of the <code>depend</code> task is dependent on a number of factors such as class
+relationship complexity and how many class files are out of date. The decision about whether it is
+cheaper to just recompile all classes or to use the <code>depend</code> task will depend on the size
+of your project and how interrelated your classes are.</p>
 
 <h3>Limitations</h3>
 
-<p> There are some source dependencies which depend will not detect. </p>
+<p>There are some source dependencies which <code>depend</code> will not detect:</p>
 
 <ul>
-<li>If the Java compiler optimizes away a class relationship, 
-    there can be a source dependency without a class dependency. </li>
-    
-<li>Non public classes cause two problems. Firstly depend cannot relate
-    the class file to a source file. In the future this may be addressed
-    using the source file attribute in the classfile. Secondly, neither 
-    depend nor the compiler tasks can detect when a non public class is
-    missing. Inner classes are handled by the depend task.</li>
+<li>If the Java compiler optimizes away a class relationship, there can be a source dependency
+without a class dependency.</li>
+
+<li>Non-public classes cause two problems. Firstly, depend cannot relate the class file to a source
+file. In the future this may be addressed using the source file attribute in the
+classfile. Secondly, neither <code>depend</code> nor the compiler tasks can detect when a non-public
+class is missing. Inner classes are handled by the <code>depend</code> task.</li>
 </ul>
 
-The most obvious example of these limitations is that the task can't tell
-which classes to recompile when a constant primitive data type exported 
-by other classes is changed. For example, a change in the definition of
-something like
+<p>The most obvious example of these limitations is that the task can't tell which classes to
+recompile when a constant primitive data type exported by other classes is changed. For example, a
+change in the definition of something like</p>
 <pre>
 public final class Constants {
-  public final static boolean DEBUG=false;
-}
-</pre> will not be picked up by other classes.
+    public final static boolean DEBUG=false;
+}</pre>
+<p>will not be picked up by other classes.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">srcDir</td>
-    <td valign="top">This is the directory where the source exists. depend
-will examine this to determine which classes are out of date. If you use multiple
-source directories you can pass this attribute a path of source directories.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>srcDir</td>
+    <td>This is the directory where the source exists. <code>depend</code> will examine this to
+      determine which classes are out of date. If you use multiple source directories you can pass
+      this attribute a path of source directories.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">destDir</td>
-    <td valign="top">This is the root directory of the class files which
-will be analysed. If this is not present, the srcdir is used.</td>
-    <td valign="top" align="center">No</td>
+    <td>destDir</td>
+    <td>This is the root directory of the class files which will be analysed.</td>
+    <td>No; defaults to <var>srcdir</var></td>
   </tr>
   <tr>
-    <td valign="top">cache</td>
-    <td valign="top">This is a directory in which depend can store and
-retrieve dependency information. If this is not present, depend will not
-use a cache </td>
-    <td valign="top" align="center">No</td>
+    <td>cache</td>
+    <td>This is a directory in which <code>depend</code> can store and retrieve dependency
+      information.</td>
+    <td>No; defaults to no cache</td>
   </tr>
   <tr>
-    <td valign="top">closure</td>
-    <td valign="top">This attribute controls whether depend only removes
-classes which directly depend on out of date classes. If this is set to true,
-depend will traverse the class dependency graph deleting all affected
-classes. Defaults to false</td>
-    <td valign="top" align="center">No</td>
+    <td>closure</td>
+    <td>This attribute controls whether <code>depend</code> only removes classes which directly
+      depend on out of date classes. If this is set to <q>true</q>, <code>depend</code> will
+      traverse the class dependency graph deleting all affected classes.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">dump</td>
-    <td valign="top">If true the dependency information will be written to the debug level log
-                     </td>
-    <td valign="top" align="center">No</td>
+    <td>dump</td>
+    <td>If true the dependency information will be written to the debug level log</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath containing jars and classes for which <code>&lt;depend&gt;</code> should also
-                     check dependencies</td>
-    <td valign="top" align="center">No</td>
+    <td>classpath</td>
+    <td>The classpath containing jars and classes for which <code>&lt;depend&gt;</code> should also
+      check dependencies</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">warnOnRmiStubs</td>
-    <td valign="top">Flag to disable warnings about files that look like rmic generated stub/skeleton
-    classes, and which have no .java source. Useful when doing rmi development. </td>
-    <td valign="top" align="center">No, default=true</td>
+    <td>warnOnRmiStubs</td>
+    <td>Flag to disable warnings about files that look like <kbd>rmic</kbd> generated
+      stub/skeleton classes and have no <samp>.java</samp> source. Useful when doing RMI
+      development.</td>
+    <td>No; default <q>true</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
-<p>The <code>depend</code> task's <code>classpath</code> attribute is a 
-<a href="../using.html#path">PATH-like structure</a> and can also be set
-via a nested <code>&lt;classpath&gt;</code> element.</p>
+<p>The <code>depend</code> task's <var>classpath</var> attribute is
+a <a href="../using.html#path">path-like structure</a> and can also be set via a
+nested <code>&lt;classpath&gt;</code> element.</p>
 
-<p>Additionally,
-this task forms an implicit
-<a href="../Types/fileset.html">FileSet</a>
-and supports most attributes of
-<code>&lt;fileset&gt;</code> (<code>dir</code> becomes <code>srcdir</code>),
-as well as the nested <code>&lt;include&gt;</code>,
-<code>&lt;exclude&gt;</code>, and <code>&lt;patternset&gt;</code> elements.
+<p>Additionally, this task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
+supports most attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>srcdir</var>),
+as well as the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>,
+and <code>&lt;patternset&gt;</code> elements.</p>
 
 <h3>Examples</h3>
-<pre>&lt;depend srcdir=&quot;${java.dir}&quot;
+
+<p>Remove any classes in the <samp>${build.classes}</samp> directory that depend on out-of-date
+classes. Classes are considered out-of-date with respect to the source in
+the <samp>${java.dir}</samp> directory, using the same mechanism as the <code>&lt;javac&gt;</code>
+task. In this example, the <code>&lt;depend&gt;</code> task caches its dependency information in
+the <samp>depcache</samp> directory.</p>
+<pre>
+&lt;depend srcdir=&quot;${java.dir}&quot;
         destdir=&quot;${build.classes}&quot;
         cache=&quot;depcache&quot;
         closure=&quot;yes&quot;/&gt;</pre>
 
-<p>removes any classes in the <code>${build.classes}</code> directory
-that depend on out-of-date classes. Classes are considered out-of-date with 
-respect to the source in the <code>${java.dir}</code> directory, using the same
-mechanism as the <code>&lt;javac&gt;</code> task. In this example, the
-<code>&lt;depend&gt;</code> task caches its dependency 
-information in the <code>depcache</code> directory. </p>
-
+<p>Do the same as the previous example, but explicitly include all <samp>.java</samp> files, except
+those that match the list given in <samp>${java.dir}/build_excludes</samp>.</p>
 <pre>
 &lt;depend srcdir=&quot;${java.dir}&quot; destdir=&quot;${build.classes}&quot;
         cache=&quot;depcache&quot; closure=&quot;yes&quot;&gt;
   &lt;include name=&quot;**/*.java&quot;/&gt;
   &lt;excludesfile name=&quot;${java.dir}/build_excludes&quot;/&gt;
-&lt;/depend&gt;
-</pre>
-<p>does the same as the previous example, but explicitly includes all
-<code>.java</code> files, except those that match the list given
-in <code>${java.dir}/build_excludes</code>.</p>
-
-
+&lt;/depend&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/dependset.html b/manual/Tasks/dependset.html
index 34ec238..7346767 100644
--- a/manual/Tasks/dependset.html
+++ b/manual/Tasks/dependset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>DependSet Task</title>
 </head>
@@ -30,142 +30,113 @@
 
 <h3>Description</h3>
 
-<p>
-The dependset task compares a set of sources with a set of target
-files.  If any of the sources has been modified more recently than
-any of the target files, all of the target files are removed.
-</p>
-<p>
-Sources and target files are specified via nested
-<a href="../Types/resources.html#collection">Resource Collection</a>s;
-sources can be resources of any type, while targets are restricted to files
-only. At least one set of sources and one set of targets is required.
-</p>
-<p>
-Use a FileSet when you want to use wildcard include or exclude
-patterns and don't care about missing files.  Use a FileList when you
-want to consider the non-existence of a file as if it were out of
-date.  If there are any non-existing files in any source or target
-FileList, all target files will be removed.
-</p>
-<p>
-DependSet is useful to capture dependencies that are not or cannot be
-determined algorithmically.  For example, the <code>&lt;style&gt;</code> task only
-compares the source XML file and XSLT stylesheet against the target
-file to determined whether to restyle the source.  Using dependset you
-can extend this dependency checking to include a DTD or XSD file as
-well as other stylesheets imported by the main stylesheet.
-</p>
+<p>The <code>dependset</code> task compares a set of sources with a set of target files.  If any of
+the sources has been modified more recently than any of the target files, all of the target files
+are removed.</p>
+<p>Sources and target files are specified via
+nested <a href="../Types/resources.html#collection">resource collections</a>; sources can be
+resources of any type, while targets are restricted to files only. At least one set of sources and
+one set of targets is required.</p>
+<p>Use a FileSet when you want to use wildcard include or exclude patterns and don't care about
+missing files.  Use a FileList when you want to consider the non-existence of a file as if it were
+out of date.  If there are any non-existing files in any source or target FileList, all target files
+will be removed.</p>
+<p>DependSet is useful to capture dependencies that are not or cannot be determined algorithmically.
+For example, the <code>&lt;style&gt;</code> task only compares the source XML file and XSLT
+stylesheet against the target file to determined whether to restyle the source.
+Using <code>dependset</code> you can extend this dependency checking to include a DTD or XSD file as
+well as other stylesheets imported by the main stylesheet.</p>
 
 <h3>Parameters</h3>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top" align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Makes the task list all deleted targets files
-      and the reason why they get deleted.</td>
-    <td align="center" valign="top" rowspan="2">No</td>
+    <td>verbose</td>
+    <td>Makes the task list all deleted targets files and the reason why they get deleted.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3>Parameters Specified as Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
 <h4>sources</h4>
 
-<p>The <code>&lt;sources&gt;</code> element is a
-<a href="../Types/resources.html#union">Union</a> into which
-arbitrary resource collections can be nested. <b>Since Apache Ant 1.7</b>
+<p>The <code>&lt;sources&gt;</code> element is a <a href="../Types/resources.html#union">Union</a>
+into which arbitrary resource collections can be nested. <em>Since Apache Ant 1.7</em>
 </p>
 
 <h4>srcfileset</h4>
 
-<p>
-The nested <code>&lt;srcfileset&gt;</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in
-this fileset will be compared against all files included in all of the
-<code>&lt;targetfileset&gt;</code> filesets and <code>&lt;targetfilelist&gt;</code>
-filelists.  Multiple <code>&lt;srcfileset&gt;</code> filesets may be specified.
-</p>
+<p>The nested <code>&lt;srcfileset&gt;</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>. All files included in this fileset will be compared
+against all files included in all of the <code>&lt;targetfileset&gt;</code> filesets
+and <code>&lt;targetfilelist&gt;</code> filelists.  Multiple <code>&lt;srcfileset&gt;</code>
+filesets may be specified.</p>
 
 <h4>srcfilelist</h4>
 
-<p>
-The nested <code>&lt;srcfilelist&gt;</code> element specifies a <a
-href="../Types/filelist.html">FileList</a>. All files included in
-this filelist will be compared against all files included in all of the 
-<code>&lt;targetfileset&gt;</code> filesets and <code>&lt;targetfilelist&gt;</code>
-filelists.  Multiple <code>&lt;srcfilelist&gt;</code> filelists may be specified.
-</p>
+<p>The nested <code>&lt;srcfilelist&gt;</code> element specifies
+a <a href="../Types/filelist.html">FileList</a>. All files included in this filelist will be
+compared against all files included in all of the <code>&lt;targetfileset&gt;</code> filesets
+and <code>&lt;targetfilelist&gt;</code> filelists.  Multiple <code>&lt;srcfilelist&gt;</code>
+filelists may be specified.</p>
 
 <h4>targets</h4>
 
-<p>The <code>&lt;targets&gt;</code> element is a
-<a href="../using.html#path">Path</a> and thus can
-include any filesystem-based resource. <b>Since Ant 1.7</b>
-</p>
+<p><em>Since Ant 1.7</em></p>
+
+<p>The <code>&lt;targets&gt;</code> element is a <a href="../using.html#path">Path</a> and thus can
+include any filesystem-based resource.</p>
 
 <h4>targetfileset</h4>
 
-<p>
-The nested <code>&lt;targetfileset&gt;</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>.  All files included in
-this fileset will be compared against all files included in all of the
-<code>&lt;srcfileset&gt;</code> filesets and <code>&lt;sourcefilelist&gt;</code>
-filelists, and if any are older, they are all deleted.
-Multiple <code>&lt;targetfileset&gt;</code> filesets may be specified.
-</p>
+<p>The nested <code>&lt;targetfileset&gt;</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>.  All files included in this fileset will be compared
+against all files included in all of the <code>&lt;srcfileset&gt;</code> filesets
+and <code>&lt;sourcefilelist&gt;</code> filelists, and if any are older, they are all deleted.
+Multiple <code>&lt;targetfileset&gt;</code> filesets may be specified.</p>
 
 <h4>targetfilelist</h4>
 
-<p>
-The nested <code>&lt;targetfilelist&gt;</code> element specifies a <a
-href="../Types/filelist.html">FileList</a>.  All files included in
-this filelist will be compared against all files included in all of the
-<code>&lt;srcfileset&gt;</code> filesets and <code>&lt;sourcefilelist&gt;</code>
-filelists, and if any are older, they are all deleted.
-Multiple <code>&lt;targetfilelist&gt;</code> filelists may be specified.
-</p>
+<p>The nested <code>&lt;targetfilelist&gt;</code> element specifies
+a <a href="../Types/filelist.html">FileList</a>.  All files included in this filelist will be
+compared against all files included in all of the <code>&lt;srcfileset&gt;</code> filesets
+and <code>&lt;sourcefilelist&gt;</code> filelists, and if any are older, they are all deleted.
+Multiple <code>&lt;targetfilelist&gt;</code> filelists may be specified.</p>
 
 <h3>Examples</h3>
-<blockquote> <pre>
-    &lt;dependset&gt;
-       &lt;srcfilelist
-           dir   = &quot;${dtd.dir}&quot;
-           files = &quot;paper.dtd,common.dtd&quot;/&gt;
-       &lt;srcfilelist
-           dir   = &quot;${xsl.dir}&quot;
-           files = &quot;common.xsl&quot;/&gt;
-       &lt;srcfilelist
-           dir   = &quot;${basedir}&quot;
-           files = &quot;build.xml&quot;/&gt;
-       &lt;targetfileset
-           dir      = &quot;${output.dir}&quot;
-           includes = &quot;**/*.html&quot;/&gt;
-    &lt;/dependset&gt;  </pre>
-</blockquote>
 
-<p> 
-In this example derived HTML files in the ${output.dir} directory 
-will be removed if any are out-of-date with respect to:</p>
+<p>Remove derived HTML files in the ${output.dir} directory if they are out-of-date with respect
+to:</p>
 <ol>
-<li>the DTD of their source XML files</li>
-<li>a common DTD (imported by the main DTD)</li>
-<li>a subordinate XSLT stylesheet (imported by the main stylesheet), or</li>
-<li>the buildfile</li>
+    <li>the DTD of their source XML files</li>
+    <li>a common DTD (imported by the main DTD)</li>
+    <li>a subordinate XSLT stylesheet (imported by the main stylesheet), or</li>
+    <li>the buildfile</li>
 </ol>
+<pre>
+&lt;dependset&gt;
+  &lt;srcfilelist
+      dir   = &quot;${dtd.dir}&quot;
+      files = &quot;paper.dtd,common.dtd&quot;/&gt;
+  &lt;srcfilelist
+      dir   = &quot;${xsl.dir}&quot;
+      files = &quot;common.xsl&quot;/&gt;
+  &lt;srcfilelist
+      dir   = &quot;${basedir}&quot;
+      files = &quot;build.xml&quot;/&gt;
+  &lt;targetfileset
+      dir      = &quot;${output.dir}&quot;
+      includes = &quot;**/*.html&quot;/&gt;
+&lt;/dependset&gt;</pre>
 
-<p>
-If any of the sources in the above example does not exist, all
-target files will also be removed.  To ignore missing sources instead,
-use filesets instead of filelists for the sources.
-</p>
-
-
+<p>If any of the sources in the above example does not exist, all target files will also be
+removed. To ignore missing sources instead, use filesets instead of filelists for the sources.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/diagnostics.html b/manual/Tasks/diagnostics.html
index cdb1693..68d08d1 100644
--- a/manual/Tasks/diagnostics.html
+++ b/manual/Tasks/diagnostics.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,36 +15,28 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Diagnostics Task</title>
 </head>
 
 <body>
 
-<h2><a name="diagnostics">Diagnostics</a></h2>
-<h3>Diagnostics</h3>
-<p>
-Runs Apache Ant's <code>-diagnostics</code> code inside Ant itself. This is good for 
-debugging Ant's configuration under an IDE. 
-<b>Since Ant 1.7.0</b>
-</p>
-
+<h2 id="diagnostics">Diagnostics</h2>
+<p><em>Since Ant 1.7.0</em></p>
+<h3>Description</h3>
+<p>Runs Apache Ant's <kbd>-diagnostics</kbd> code inside Ant itself. This is good for debugging
+Ant's configuration under an IDE.</p>
 
 <h3>Examples</h3>
 
+<p>Print out the current diagnostics dump.</p>
 <pre>
-    &lt;target name="diagnostics" description="diagnostics"&gt;
-        &lt;diagnostics/&gt;
-    &lt;/target&gt;
-</pre>
-<p>
-    Prints out the current diagnostics dump.
-</p>
-
+&lt;target name="diagnostics" description="diagnostics"&gt;
+    &lt;diagnostics/&gt;
+&lt;/target&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/dirname.html b/manual/Tasks/dirname.html
index 03227b4..8d9879c 100644
--- a/manual/Tasks/dirname.html
+++ b/manual/Tasks/dirname.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,61 +15,51 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Dirname Task</title>
 </head>
 
 <body>
 
-<h2><a name="echo">Dirname</a></h2>
+<h2 id="echo">Dirname</h2>
 <h3>Description</h3>
-<p>
-Task to determine the directory path of a specified file.
-</p>
-<p> 
-When this task executes, it will set the specified property to the
-value of the specified file (or directory) up to, but not including,
-the last path element. If the specified file is a path that ends in a
-filename, the filename will be dropped. If the specified file is just
-a filename, the directory will be the current directory.
-</p>
-  <p>
-    <em>Note:</em> This is not the same as the UNIX dirname command, which is
-    defined as "strip non-directory suffix from filename". &lt;dirname&gt;
-    determines the full directory path of the specified file.
-  </p>
+<p>Task to determine the directory path of a specified file.</p>
+<p>When this task executes, it will set the specified property to the value of the specified file
+(or directory) up to, but not including, the last path element. If the specified file is a path that
+ends in a filename, the filename will be dropped. If the specified file is just a filename, the
+directory will be the current directory.</p>
+<p><strong>Note</strong>: This is not the same as the UNIX <code>dirname</code> command, which is
+defined as "strip non-directory suffix from filename". <code>&lt;dirname&gt;</code> determines the
+full directory path of the specified file.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The path to take the dirname of.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>file</td>
+    <td>The path to take the dirname of.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to set.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of the property to set.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<pre>  &lt;dirname property=&quot;antfile.dir&quot; file=&quot;${ant.file}&quot;/&gt;</pre>
-will set <code>antfile.dir</code> to the directory path for
-<code>${ant.file}</code>.
-<pre>  &lt;dirname property=&quot;foo.dirname&quot; file=&quot;foo.txt&quot;/&gt;</pre>
-will set <code>foo.dirname</code> to the project's basedir.</p>
 
+<p>Set <code>antfile.dir</code> to the directory path for <samp>${ant.file}</samp>.</p>
+<pre>&lt;dirname property=&quot;antfile.dir&quot; file=&quot;${ant.file}&quot;/&gt;</pre>
 
+<p>Set <code>foo.dirname</code> to the project's <var>basedir</var>.</p>
+<pre>&lt;dirname property=&quot;foo.dirname&quot; file=&quot;foo.txt&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/ear.html b/manual/Tasks/ear.html
index 631d83a..081c752 100644
--- a/manual/Tasks/ear.html
+++ b/manual/Tasks/ear.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,264 +15,233 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>EAR Task</title>
 </head>
 
 <body>
 
-<h2><a name="ear">Ear</a></h2>
+<h2 id="ear">Ear</h2>
 <h3>Description</h3>
-<p>An extension of the <a href="jar.html">Jar</a> task with special
-treatment for files that should end up in an Enterprise Application archive.</p>
-<p>(The Ear task is a shortcut for specifying the particular layout of a EAR file. 
-The same thing can be accomplished by using the <i>prefix</i> and <i>fullpath</i>
-attributes of zipfilesets in a Zip or Jar task.)</p>
-<p>The extended zipfileset element from the zip task (with attributes <i>prefix</i>, <i>fullpath</i>, and <i>src</i>) is available in the Ear task.</p>
+<p>An extension of the <a href="jar.html">Jar</a> task with special treatment for files that should
+end up in an Enterprise Application archive.</p>
+<p>(The <code>Ear</code> task is a shortcut for specifying the particular layout of a EAR file.  The
+same thing can be accomplished by using the <var>prefix</var> and <var>fullpath</var> attributes of
+zipfilesets in a <code>Zip</code> or <code>Jar</code> task.)</p>
+<p>The extended zipfileset element from the <code>Zip</code> task (with
+attributes <var>prefix</var>, <var>fullpath</var>, and <var>src</var>) is available in
+the <code>Ear</code> task.</p>
 
-<p><b>Please note that the zip format allows multiple files of the same
-fully-qualified name to exist within a single archive.  This has been
-documented as causing various problems for unsuspecting users.  If you wish
-to avoid this behavior you must set the <code>duplicate</code> attribute
-to a value other than its default, <code>&quot;add&quot;</code>.</b></p>
+<p><strong>Please note that the zip format allows multiple files of the same fully-qualified name to
+exist within a single archive.  This has been documented as causing various problems for
+unsuspecting users.  If you wish to avoid this behavior you must set the <var>duplicate</var>
+attribute to a value other than its default, <q>add</q>.</strong></p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">the EAR file to create.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>destfile</td>
+    <td>the EAR file to create.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">appxml</td>
-    <td valign="top">The deployment descriptor to use (META-INF/application.xml).</td>
-    <td valign="top" align="center">Yes, unless update is set to true</td>
+    <td>appxml</td>
+    <td>The deployment descriptor to use (<samp>META-INF/application.xml</samp>).</td>
+    <td>Yes, unless <var>update</var> is set to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the directory from which to jar the files.</td>
-    <td valign="top" align="center">No</td>
+    <td>basedir</td>
+    <td>the directory from which to jar the files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compress</td>
-    <td valign="top">Not only store data but also compress them,
-    defaults to true.  Unless you set the <em>keepcompression</em>
-    attribute to false, this will apply to the entire archive, not
-    only the files you've added while updating.</td>
-    <td align="center" valign="top">No</td>
+    <td>compress</td>
+    <td>Not only store data but also compress them.  Unless you set the <var>keepcompression</var>
+      attribute to <q>false</q>, this will apply to the entire archive, not only the files you've
+      added while updating.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">keepcompression</td>
-    <td valign="top">For entries coming from existing archives (like
-    nested <em>zipfileset</em>s or while updating the archive), keep
-    the compression as it has been originally instead of using the
-    <em>compress</em> attribute.  Defaults false.  <em>Since Apache Ant
-    1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>keepcompression</td>
+    <td>For entries coming from existing archives (like nested <code>zipfileset</code>s or while
+    updating the archive), keep the compression as it has been originally instead of using the
+    <var>compress</var> attribute.  <em>Since Apache Ant 1.6</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The character encoding to use for filenames
-      inside the archive.  Defaults to UTF8. <strong>It is not
-      recommended to change this value as the created archive will most
-      likely be unreadable for Java otherwise.</strong>
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The character encoding to use for filenames inside the archive. <strong>It is not
+      recommended to change this value as the created archive will most likely be unreadable for
+      Java otherwise.</strong>  <br/>See also the <a href="zip.html#encoding">discussion in the zip
+      task page</a></td>
+    <td>No; defaults to <q>UTF8</q></td>
   </tr>
   <tr>
-    <td valign="top">filesonly</td>
-    <td valign="top">Store only file entries, defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>filesonly</td>
+    <td>Store only file entries.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">manifest</td>
-    <td valign="top">the manifest file to use.</td>
-    <td valign="top" align="center">No</td>
+    <td>manifest</td>
+    <td>the manifest file to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">filesetmanifest</td>
-    <td valign="top">behavior when a Manifest is found in a zipfileset or zipgroupfileset file is found.  Valid values are &quot;skip&quot;, &quot;merge&quot;, and &quot;mergewithoutmain&quot;.  &quot;merge&quot; will merge all of the manifests together, and merge this into any other specified manifests.  &quot;mergewithoutmain&quot; merges everything but the Main section of the manifests.  Default value is &quot;skip&quot;.
+    <td>filesetmanifest</td>
+    <td>behavior when a manifest file is found in a <code>zipfileset</code>
+      or <code>zipgroupfileset</code> file.  Valid values are <q>skip</q>, <q>merge</q>,
+      and <q>mergewithoutmain</q>.  <q>merge</q> will merge all of the manifests together, and merge
+      this into any other specified manifests.  <q>mergewithoutmain</q> merges everything but the
+      Main section of the manifests.</td>
+    <td>No; defaults to <q>skip</q></td>
+  </tr>
+  <tr>
+    <td>whenmanifestonly</td>
+    <td>behavior when no files match.  Valid values are <q>fail</q>, <q>skip</q>,
+    and <q>create</q>.</td>
+    <td>No; defaults to <q>create</q></td>
+  </tr>
+  <tr>
+    <td>manifestencoding</td>
+    <td>The encoding used to read the JAR manifest, when a manifest file is specified.</td>
+    <td>No; defaults to default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>index</td>
+    <td>whether to create
+      an <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Index"
+      target="_top">index list</a> to speed up classloading.  Unless you specify additional jars with
+      nested <a href="jar.html#indexjars"><code>indexjars</code></a> elements, only the contents of
+      this jar will be included in the index.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>indexMetaInf</td>
+    <td>whether to include <samp>META-INF</samp> and its children in the index.  Doesn't have any
+      effect if <var>index</var> is false.<br/>Oracle's jar implementation used to skip
+      the <samp>META-INF</samp> directory and Ant followed that example.  The behavior has been
+      changed with <a href="https://bugs.openjdk.java.net/browse/JDK-4408526" target="_top">Java
+      5</a>.  In order to avoid problems with Ant generated jars on Java 1.4 or earlier, Ant will
+      not include <samp>META-INF</samp> unless explicitly asked to.<br/><em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>update</td>
+    <td>indicates whether to update or overwrite the destination file if it already exists.</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>duplicate</td>
+    <td>behavior when a duplicate file is found.  Valid values are <q>add</q>, <q>preserve</q>,
+    and <q>fail</q>.</td>
+    <td>No; default is <q>add</q></td>
+  </tr>
+  <tr>
+    <td>roundup</td>
+    <td>Whether the file modification times will be rounded up to the next even number of
+      seconds.<br/>Zip archives store file modification times with a granularity of 2 seconds, so
+      the times will either be rounded up or down.  If you round down, the archive will always seem
+      out-of-date when you rerun the task, so the default is to round up.  Rounding up may lead to a
+      different type of problems like JSPs inside a web archive that seem to be slightly more recent
+      than precompiled pages, rendering precompilation useless.<br/><em>Since Ant 1.6.2</em></td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>level</td>
+    <td>Non-default level at which file compression should be performed. Valid values range
+    from <q>0</q> (no compression/fastest) to <q>9</q> (maximum compression/slowest). <em>Since Ant
+    1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>preserve0permissions</td>
+    <td>when updating an archive or adding entries from a different archive Ant will assume that a
+      Unix permissions value of 0 (nobody is allowed to do anything to the file/directory) means
+      that the permissions haven't been stored at all rather than real permissions and will instead
+      apply its own default values.<br/>  Set this attribute to <q>true</q> if you really want to
+      preserve the original permission field. <em>Since Ant 1.8.0</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">whenmanifestonly</td>
-    <td valign="top">behavior when no files match.  Valid values are &quot;fail&quot;, &quot;skip&quot;, and &quot;create&quot;.  Default is &quot;create&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>useLanguageEncodingFlag</td>
+    <td>Whether to set the language encoding flag if the encoding is UTF-8.  This setting doesn't
+      have any effect if the encoding is not UTF-8. <em>Since Ant 1.8.0</em>.<br/>See also
+      the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">manifestencoding</td>
-    <td valign="top">The encoding used to read the JAR manifest, when a manifest file is specified.</td>
-    <td valign="top" align="center">No, defaults to the platform encoding.</td>
+    <td>createUnicodeExtraFields</td>
+    <td>Whether to create Unicode extra fields to store the file names a second time inside the
+      entry's metadata.<br/>Possible values are <q>never</q>, <q>always</q>
+      and <q>not-encodeable</q> which will only add Unicode extra fields if the file name cannot be
+      encoded using the specified encoding. <em>Since Ant 1.8.0</em>.  <br/>See also
+      the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; default is <q>never</q></td>
   </tr>
   <tr>
-    <td valign="top">index</td>
-    <td valign="top">whether to create an <A
-    HREF="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#JAR_Index">index
-    list</A> to speed up classloading.  This is a JDK 1.3+ specific
-    feature.  Unless you specify additional jars with nested <a
-    href="jar.html#indexjars"><code>indexjars</code></a> elements, only the
-    contents of this jar will be included in the index.  Defaults to
-    false.</td>
-    <td valign="top" align="center">No</td>
+    <td>fallbacktoUTF8</td>
+    <td>Whether to use UTF-8 and the language encoding flag instead of the specified encoding if a
+      file name cannot be encoded using the specified encoding. <em>Since Ant 1.8.0</em>.<br/>See
+      also the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">indexMetaInf</td>
-    <td valign="top">whether to include META-INF and its children in
-      the index.  Doesn't have any effect if <em>index</em> is
-      false.<br/>
-      Oracle's jar implementation used to skip the META-INF directory and
-      Ant followed that example.  The behavior has been changed with
-      <a href="https://bugs.openjdk.java.net/browse/JDK-4408526">Java
-      5</a>.  In order to avoid problems with Ant generated jars on
-      Java 1.4 or earlier Ant will not include META-INF unless
-      explicitly asked to.<br/>
-      <em>Ant 1.8.0</em> - Defaults to false.</td>
-    <td valign="top" align="center">No</td>
+    <td>mergeClassPathAttributes</td>
+    <td>Whether to merge the <code>Class-Path</code> attributes found in different manifests (if
+      merging manifests).  If <q>false</q>, only the attribute of the last merged manifest will be
+      preserved.  <em>Since Ant 1.8.0</em>.<br/>unless you also set <var>flattenAttributes</var>
+      to <q>true</q> this may result in manifests containing multiple <code>Class-Path</code>
+      attributes which violates the manifest specification.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">update</td>
-    <td valign="top">indicates whether to update or overwrite
-      the destination file if it already exists.  Default is &quot;false&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>flattenAttributes</td>
+    <td>Whether to merge attributes occurring more than once in a section (this can only happen for
+      the <code>Class-Path</code> attribute) into a single attribute.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">duplicate</td>
-    <td valign="top">behavior when a duplicate file is found.  Valid values are &quot;add&quot;, &quot;preserve&quot;, and &quot;fail&quot;.  The default value is &quot;add&quot;.  </td>
-    <td valign="top" align="center">No</td>
-  </tr>
-  <tr>
-    <td valign="top">roundup</td>
-    <td valign="top">Whether the file modification times will be
-    rounded up to the next even number of seconds.<br>
-    Zip archives store file modification times with a granularity of
-    two seconds, so the times will either be rounded up or down.  If
-    you round down, the archive will always seem out-of-date when you
-    rerun the task, so the default is to round up.  Rounding up may
-    lead to a different type of problems like JSPs inside a web
-    archive that seem to be slightly more recent than precompiled
-    pages, rendering precompilation useless.<br>
-    Defaults to true.  <em>Since Ant 1.6.2</em></td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">level</td>
-    <td valign="top">Non-default level at which file compression should be
-    performed. Valid values range from 0 (no compression/fastest) to 9
-    (maximum compression/slowest). <em>Since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
-  </tr>
-  <tr>
-    <td valign="top">preserve0permissions</td>
-    <td valign="top">when updating an archive or adding entries from a
-    different archive Ant will assume that a Unix permissions value of
-    0 (nobody is allowed to do anything to the file/directory) means
-    that the permissions haven't been stored at all rather than real
-    permissions and will instead apply its own default values.<br/>
-    Set this attribute to true if you really want to preserve the
-      original permission field.<em>since Ant 1.8.0</em>
-    </td>
-    <td valign="top" align="center">No, default is false</td>
-  </tr>
-  <tr>
-    <td valign="top">useLanguageEncodingFlag</td>
-    <td valign="top">Whether to set the language encoding flag if the
-      encoding is UTF-8.  This setting doesn't have any effect if the
-      encoding is not UTF-8.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td valign="top" align="center">No, default is true</td>
-  </tr>
-  <tr>
-    <td valign="top">createUnicodeExtraFields</td>
-    <td valign="top">Whether to create unicode extra fields to store
-      the file names a second time inside the entry's metadata.
-      <br>Possible values are "never", "always" and "not-encodeable"
-      which will only add Unicode extra fields if the file name cannot
-      be encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
-  </tr>
-  <tr>
-    <td valign="top">fallbacktoUTF8</td>
-    <td valign="top">Whether to use UTF-8 and the language encoding
-      flag instead of the specified encoding if a file name cannot be
-      encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is false</td>
-  </tr>
-  <tr>
-    <td valign="top">mergeClassPathAttributes</td>
-    <td valign="top">Whether to merge the Class-Path attributes found
-      in different manifests (if merging manifests).  If false, only
-      the attribute of the last merged manifest will be preserved.
-      <em>Since Ant 1.8.0</em>.
-      <br/>unless you also set flattenAttributes to true this may
-      result in manifests containing multiple Class-Path attributes
-      which violates the manifest specification.</td>
-    <td align="center" valign="top">No, default is false</td>
-  </tr>
-  <tr>
-    <td valign="top">flattenAttributes</td>
-    <td valign="top">Whether to merge attributes occurring more than
-      once in a section (this can only happen for the Class-Path
-      attribute) into a single attribute.
-      <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No, default is false</td>
-  </tr>
-  <tr>
-    <td valign="top">zip64Mode</td>
-    <td valign="top">When to use Zip64 extensions for entries.  The
-      possible values are "never", "always" and "as-needed".
-      <em>Since Ant 1.9.1</em>.
-      <br/>See also the <a href="zip.html#zip64">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
+    <td>zip64Mode</td>
+    <td>When to use Zip64 extensions for entries.  The possible values
+      are <q>never</q>, <q>always</q> and <q>as-needed</q>.  <em>Since Ant 1.9.1</em>.<br/>See also
+      the <a href="zip.html#zip64">discussion in the zip task page</a></td>
+    <td>No; default is <q>never</q></td>
   </tr>
   <tr>
     <td valign="top">modificationtime</td>
@@ -279,33 +249,28 @@
     given time. This can either be a number interpreted as
     milliseconds since 1970-01-01T00:00:00Z or a string that can be
     parsed as a ISO 8601 timestamp with optional timezone.
-      <em>Since Ant 1.9.10</em>.
+      <em>Since Ant 1.10.2</em>.
     </td>
     <td align="center" valign="top">No</td>
   </tr>
 </table>
 
-<h3>Nested elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
 <h4>metainf</h4>
-<p>The nested <code>metainf</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in this fileset will
-end up in the <code>META-INF</code> directory of the ear file. If this
-fileset includes a file named <code>MANIFEST.MF</code>, the file is
-ignored and you will get a warning.</p>
+<p>The nested <code>metainf</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>. All files included in this fileset will end up in
+the <samp>META-INF</samp> directory of the ear file. If this fileset includes a file
+named <samp>MANIFEST.MF</samp>, the file is ignored and you will get a warning.</p>
 
 <h4>manifest, indexjars, service</h4>
-These are inherited from <a href="jar.html">&lt;jar&gt;</a>
+<p>These are inherited from <a href="jar.html">&lt;jar&gt;</a></p>
 
-<h2>Example</h2>
+<h3>Example</h3>
 <pre>
-    &lt;ear destfile=&quot;${build.dir}/myapp.ear&quot; appxml=&quot;${src.dir}/metadata/application.xml&quot;&gt;
-      &lt;fileset dir=&quot;${build.dir}&quot; includes=&quot;*.jar,*.war&quot;/&gt;
-    &lt;/ear&gt;
-</pre>
-
+&lt;ear destfile=&quot;${build.dir}/myapp.ear&quot; appxml=&quot;${src.dir}/metadata/application.xml&quot;&gt;
+  &lt;fileset dir=&quot;${build.dir}&quot; includes=&quot;*.jar,*.war&quot;/&gt;
+&lt;/ear&gt;</pre>
 
 </body>
 </html>
-
-
diff --git a/manual/Tasks/echo.html b/manual/Tasks/echo.html
index bcf804e..88aacde 100644
--- a/manual/Tasks/echo.html
+++ b/manual/Tasks/echo.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,180 +15,160 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Echo Task</title>
 </head>
 
 <body>
 
-<h2><a name="echo">Echo</a></h2>
+<h2 id="echo">Echo</h2>
 <h3>Description</h3>
-<p>Echoes a message to the current loggers and listeners which
-means <tt>System.out</tt> unless overridden. A <tt>level</tt>
-can be specified, which controls at what logging level the message is
-filtered at.
-<p>
-The task can also echo to a file, in which case the option to append rather
-than overwrite the file is available, and the <tt>level</tt> option is
-ignored</p>
+<p>Echoes a message to the current loggers and listeners which means <code>System.out</code> unless
+overridden. A <var>level</var> can be specified, which controls at what logging level the message is
+filtered at.</p>
+<p>The task can also echo to a file, in which case the option to append rather than overwrite the
+file is available, and the <var>level</var> option is ignored</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">message</td>
-    <td valign="top">the message to echo.</td>
-    <td valign="top" align="center">No.  Text may also be included in a
-      character section within this element.  If neither is included a 
-      blank line will be emitted in the output.</td>
+    <td>message</td>
+    <td>the message to echo.</td>
+    <td>No; defaults to a blank line unless text is included in a character section within this
+      element</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file to write the message to.</td>
-    <td valign="top" align="center" rowspan="2">Optionally one of these may be specified.</td>
+    <td>file</td>
+    <td>the file to write the message to.</td>
+    <td rowspan="2">No; only one of these may be used</td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">the <a href="../Types/resources.html">Resource</a>
+    <td>output</td>
+    <td class="left">the <a href="../Types/resources.html">Resource</a>
       to write the message to (see <a href="../develop.html#set-magic">note</a>).
-      <b>Since Apache Ant 1.8</b></td>
+      <em>Since Apache Ant 1.8</em></td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Append to an existing file (or
-      <a href="http://docs.oracle.com/javase/7/docs/api//java/io/FileWriter.html#FileWriter%28java.lang.String,%20boolean%29" target="_blank">
-      open a new file / overwrite an existing file</a>)? Default <i>false</i>.
+    <td>append</td>
+    <td>Append to an existing file
+      (or <a href="https://docs.oracle.com/javase/8/docs/api//java/io/FileWriter.html#FileWriter-java.lang.String-boolean-"
+      target="_top"> open a new file / overwrite an existing file</a>)?
     </td>
-    <td valign="top" align="center">No; ignored unless <i>output</i> indicates a
-      filesystem destination.</td>
+    <td>No; ignored unless <var>output</var> indicates a filesystem destination, default
+      is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">level</td>
-    <td valign="top">Control the level at which this message is reported.
-            One of "error", "warning", "info", "verbose", "debug" (decreasing order)</td>
-    <td valign="top" align="center">No - default is "warning".</td>
+    <td>level</td>
+    <td>Control the level at which this message is reported.  One
+      of <q>error</q>, <q>warning</q>, <q>info</q>, <q>verbose</q>, <q>debug</q> (decreasing
+      order)</td>
+    <td>No; default is <q>warning</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">encoding to use, default is ""; the local system encoding. <em>since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
+    <td>encoding</td>
+    <td>encoding to use. <em>since Ant 1.7</em></td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">Overwrite read-only destination
-      files.  <em>since Ant 1.8.2</em></td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>force</td>
+    <td>Overwrite read-only destination files.  <em>since Ant 1.8.2</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<pre>
-&lt;echo message=&quot;Hello, world&quot;/&gt;
-</pre>
-<pre>
-&lt;echo message=&quot;Embed a line break:${line.separator}&quot;/&gt;
-</pre>
-<pre>
-&lt;echo&gt;Embed another:${line.separator}&lt;/echo&gt;
-</pre>
-<pre>
-&lt;echo&gt;This is a longer message stretching over
+
+<p>Basic use:</p>
+<pre>&lt;echo message=&quot;Hello, world&quot;/&gt;</pre>
+<pre>&lt;echo message=&quot;Embed a line break:${line.separator}&quot;/&gt;</pre>
+<pre>&lt;echo&gt;Embed another:${line.separator}&lt;/echo&gt;</pre>
+<pre>&lt;echo&gt;This is a longer message stretching over
 two lines.
-&lt;/echo&gt;
-</pre>
-<pre>
-&lt;echo&gt;
+&lt;/echo&gt;</pre>
+
+<p>The newline immediately following the <code>&lt;echo&gt;</code> tag is part of the
+output. Newlines in character data within the content of an element are not discarded by XML
+parsers.<br/>See <a href="https://www.w3.org/TR/xml/#sec-line-ends" target="_top">W3C Recommendation
+26 November 2008 / End of Line handling</a> for more details.</p>
+<pre>&lt;echo&gt;
 This is a longer message stretching over
 three lines; the first line is a blank
-&lt;/echo&gt;
-</pre>
-The newline immediately following the &lt;echo&gt; tag will be part of the output.<br>
-Newlines in character data within the content of an element are not discarded by XML parsers.<br>
-See <a href="http://www.w3.org/TR/2004/REC-xml-20040204/#sec-line-ends">
-W3C Recommendation 04 February 2004 / End of Line handling
-</a> for more details.
+&lt;/echo&gt;</pre>
 
+<p>A message which only appears in <kbd>-debug</kbd> mode.</p>
 <pre>&lt;echo message=&quot;Deleting drive C:&quot; level=&quot;debug&quot;/&gt;</pre>
-A message which only appears in <tt>-debug</tt> mode.
+
+<p>A message which appears even in <kbd>-quiet</kbd> mode.</p>
 <pre>&lt;echo level=&quot;error&quot;&gt;
 Imminent failure in the antimatter containment facility.
 Please withdraw to safe location at least 50km away.
-&lt;/echo&gt;
-</pre>
-A message which appears even in <tt>-quiet</tt> mode.
+&lt;/echo&gt;</pre>
 
+<p>Generate a shell script by echoing to a file.  Note the use of a double <q>$</q> symbol to stop
+Ant filtering out the single <q>$</q> during variable expansion.</p>
 <pre>&lt;echo file="runner.csh" append="false"&gt;#\!/bin/tcsh
 java-1.3.1 -mx1024m ${project.entrypoint} $$*
 &lt;/echo&gt;</pre>
-Generate a shell script by echoing to a file.
-Note the use of a double $ symbol to stop Ant
-filtering out the single $ during variable expansion
 
-<p>Depending on the loglevel Ant runs, messages are print out or silently
-ignored:
+<p>Depending on the log level Ant runs at, messages are print out or silently ignored:</p>
 <table>
 <tr>
-  <th>Ant-Statement</th>
-  <th>-quiet, -q</th>
-  <th><i>no statement</th>
-  <th>-verbose, -v</th>
-  <th>-debug, -d</th>
+  <th scope="col">Ant command line</th>
+  <th scope="col"><kbd>-quiet</kbd>, <kbd>-q</kbd></th>
+  <th scope="col"><em>no switch</em></th>
+  <th scope="col"><kbd>-verbose</kbd>, <kbd>-v</kbd></th>
+  <th scope="col"><kbd>-debug</kbd>, <kbd>-d</kbd></th>
 </tr>
 <tr>
-  <td><pre>&lt;echo message="This is error message." level="error" /&gt;</pre></td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
+  <td><pre>&lt;echo message="This is error message." level="error"/&gt;</pre></td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
 </tr>
 <tr>
-  <td><pre>&lt;echo message="This is warning message." /&gt;</pre></td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
+  <td><pre>&lt;echo message="This is warning message."/&gt;</pre></td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
 </tr>
 <tr>
-  <td><pre>&lt;echo message="This is warning message." level="warning" /&gt;</pre></td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
+  <td><pre>&lt;echo message="This is warning message." level="warning"/&gt;</pre></td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
 </tr>
 <tr>
-  <td><pre>&lt;echo message="This is info message." level="info" /&gt;</pre></td>
-  <td align="center">not logged</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
+  <td><pre>&lt;echo message="This is info message." level="info"/&gt;</pre></td>
+  <td>not logged</td>
+  <td>ok</td>
+  <td>ok</td>
+  <td>ok</td>
 </tr>
 <tr>
-  <td><pre>&lt;echo message="This is verbose message." level="verbose" /&gt;</pre></td>
-  <td align="center">not logged</td>
-  <td align="center">not logged</td>
-  <td align="center">ok</td>
-  <td align="center">ok</td>
+  <td><pre>&lt;echo message="This is verbose message." level="verbose"/&gt;</pre></td>
+  <td>not logged</td>
+  <td>not logged</td>
+  <td>ok</td>
+  <td>ok</td>
 </tr>
 <tr>
-  <td><pre>&lt;echo message="This is debug message." level="debug" /&gt;</pre></td>
-  <td align="center">not logged</td>
-  <td align="center">not logged</td>
-  <td align="center">not logged</td>
-  <td align="center">ok</td>
+  <td><pre>&lt;echo message="This is debug message." level="debug"/&gt;</pre></td>
+  <td>not logged</td>
+  <td>not logged</td>
+  <td>not logged</td>
+  <td>ok</td>
 </tr>
 </table>
 
-
-
-
-
-
 </body>
 </html>
diff --git a/manual/Tasks/echoproperties.html b/manual/Tasks/echoproperties.html
index ec1e4b4..edf2981 100644
--- a/manual/Tasks/echoproperties.html
+++ b/manual/Tasks/echoproperties.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,73 +15,62 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Echoproperties Task</title>
 </head>
 
 <body>
 
-<h2><a name="echoproperties">echoproperties</a></h2>
+<h2 id="echoproperties">echoproperties</h2>
 <h3>Description</h3>
 
-<p>Displays all the current properties (or a subset of them specified
-by a nested <code>&lt;propertyset&gt;</code>) in the project.  The
-output can be sent to a file if desired.  This task can be used as a
-somewhat contrived means of returning data from an
-<tt>&lt;ant&gt;</tt> invocation, but is really for debugging build
+<p>Displays all the current properties (or a subset of them specified by a
+nested <code>&lt;propertyset&gt;</code>) in the project.  The output can be sent to a file if
+desired.  This task can be used as a somewhat contrived means of returning data from an
+<kbd>ant</kbd> invocation, but is really for debugging build
 files.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">If specified, the value indicates the name of the
-    file to send the output of the statement to.  The generated output file
-    is compatible for loading by any Java application as a property file.
-    If not specified, then the output will go to the Apache Ant log.</td>
-    <td valign="top" align="center">No</td>
+    <td>destfile</td>
+    <td>If specified, the value indicates the name of the file to send the output of the statement
+      to.  The generated output file is compatible for loading by any Java application as a property
+      file.</td>
+    <td>No; by default, output to the log</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">
-        a prefix which is used to filter the properties
-        only those properties starting with this prefix will be echoed.
-        <P>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>prefix</td>
+    <td>a prefix which is used to filter the properties: only properties whose names start with this
+      prefix will be echoed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">regex</td>
-    <td valign="top">
-        a regular expression which is used to filter the
-        properties
-        only those properties whose names match it will be echoed.
-    </td>
-    <td valign="top" align="center">No</td>
-  </tr>   
-  <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">By default, the "failonerror" attribute is enabled.
-    If an error occurs while writing the properties to a file, and this
-    attribute is enabled, then a BuildException will be thrown, causing the
-    build to fail.  If disabled, then IO errors will be reported as a log
-    statement, and the build will continue without failure from this task.</td>
-    <td valign="top" align="center">No</td>
+    <td>regex</td>
+    <td>a regular expression which is used to filter the properties: only those properties whose
+      names match it will be echoed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">format</td>
-    <td valign="top">One of <code>text</code> or <code>xml</code>.
-    Determines the output format.  Defaults to <code>text</code>.</td>
-    <td valign="top" align="center">No</td>
+    <td>failonerror</td>
+    <td>If an error occurs while writing the properties to a file, and this attribute is enabled,
+      then a <code>BuildException</code> will be thrown, causing the build to fail.  If disabled,
+      then IO errors will be reported as a log statement, and the build will continue without
+      failure from this task.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>format</td>
+    <td>One of <q>text</q> or <q>xml</q>.  Determines the output format.</td>
+    <td>No; defaults to <q>text</q></td>
   </tr>
 </table>
 
@@ -88,59 +78,47 @@
 
 <h4>propertyset</h4>
 
-<p>You can specify subsets of properties to be echoed with <a
-href="../Types/propertyset.html">propertyset</a>s. Using
-<tt>propertyset</tt>s gives more control on which properties will be
-picked up. The attributes <tt>prefix</tt> and <tt>regex</tt> are just
-shortcuts that use <tt>propertyset</tt>s internally.
-</p>
+<p><em>Since Ant 1.6</em>.</p>
 
-<p><em>since Ant 1.6</em>.</p>
+<p>You can specify subsets of properties to be echoed
+with <a href="../Types/propertyset.html">propertyset</a>s. Using <code>propertyset</code>s gives
+more control on which properties will be picked up. The attributes <var>prefix</var>
+and <var>regex</var> are just shortcuts that use <code>propertyset</code>s internally.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
-  &lt;echoproperties/&gt;
-</pre></blockquote>
 <p>Report the current properties to the log.</p>
-<blockquote><pre>
-  &lt;echoproperties destfile="my.properties"/&gt;
-</pre></blockquote>
-<p>Report the current properties to the file "my.properties", and will
-fail the build if the file could not be created or written to.</p>
-<blockquote><pre>
-  &lt;echoproperties destfile="my.properties" failonerror="false"/&gt;
-</pre></blockquote>
-<p>Report the current properties to the file "my.properties", and will
-log a message if the file could not be created or written to, but will still
-allow the build to continue.</p>
-<blockquote><pre>
-  &lt;echoproperties prefix="java."/&gt;
-</pre></blockquote>
-<p>List all properties beginning with "java."</p>
-<blockquote><pre>
-  &lt;echoproperties&gt;
-    &lt;propertyset&gt;
-      &lt;propertyref prefix="java."/&gt;
-    &lt;/propertyset&gt;
-  &lt;/echoproperties&gt;
-</pre></blockquote>
-<p>This again lists all properties beginning with "java." using a nested
-<tt>&lt;/propertyset&gt;</tt> which is an equivalent but longer way.</p>
-<blockquote><pre>
-  &lt;echoproperties regex=".*ant.*"/&gt;
-</pre></blockquote>
-<p>Lists all properties that contain "ant" in their names.
-The equivalent snippet with <tt>&lt;/propertyset&gt;</tt> is:</p>
-<blockquote><pre>
-  &lt;echoproperties&gt;
-    &lt;propertyset&gt;
-      &lt;propertyref regex=".*ant.*"/&gt;
-    &lt;/propertyset&gt;
-  &lt;/echoproperties&gt;
-</pre></blockquote>
+<pre>&lt;echoproperties/&gt;</pre>
 
+<p>Report the current properties to the file <samp>my.properties</samp>, and fail the build if the
+file could not be created or written to.</p>
+<pre>&lt;echoproperties destfile="my.properties"/&gt;</pre>
 
+<p>Report the current properties to the file <samp>my.properties</samp>, and log a message if the
+file could not be created or written to, but still allow the build to continue.</p>
+<pre>&lt;echoproperties destfile="my.properties" failonerror="false"/&gt;</pre>
+
+<p>List all properties beginning with <samp>java.</samp></p>
+<pre>&lt;echoproperties prefix="java."/&gt;</pre>
+
+<p>Lists all properties beginning with <samp>java.</samp> using a
+nested <code>&lt;propertyset/&gt;</code> which is an equivalent but longer way.</p>
+<pre>
+&lt;echoproperties&gt;
+  &lt;propertyset&gt;
+    &lt;propertyref prefix="java."/&gt;
+  &lt;/propertyset&gt;
+&lt;/echoproperties&gt;</pre>
+
+<p>Lists all properties that contain <samp>ant</samp> in their names.</p>
+<pre>&lt;echoproperties regex=".*ant.*"/&gt;</pre>
+
+<p>The equivalent snippet with <code>&lt;propertyset/&gt;</code> is:</p>
+<pre>
+&lt;echoproperties&gt;
+  &lt;propertyset&gt;
+    &lt;propertyref regex=".*ant.*"/&gt;
+  &lt;/propertyset&gt;
+&lt;/echoproperties&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/echoxml.html b/manual/Tasks/echoxml.html
index 74cbf7f..16b07b9 100644
--- a/manual/Tasks/echoxml.html
+++ b/manual/Tasks/echoxml.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>EchoXML Task</title>
 </head>
@@ -25,50 +25,47 @@
 <body>
 
 <h2>EchoXML</h2>
+<p><em>Since Apache Ant 1.7</em></p>
 <h3>Description</h3>
-<p>Echo nested XML to the console or a file. <b>Since Apache Ant 1.7</b></p>
+<p>Echo nested XML to the console or a file.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to receive the XML. If omitted nested
-      XML will be echoed to the log.</td>
-    <td valign="top" align="center">No</td>
+    <td>file</td>
+    <td>The file to receive the XML.</td>
+    <td>No; by default nested XML is echoed to the log</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Whether to append <code>file</code>, if specified.</td>
-    <td valign="top" align="center">No</td>
+    <td>append</td>
+    <td>Whether to append <var>file</var>, if specified.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">namespacePolicy</td>
-    <td valign="top">Sets the namespace policy as defined
-      by <code>org.apache.tools.ant.util.DOMElementWriter.XmlNamespacePolicy</code>.
-      Valid values are <code>ignore</code>, <code>elementsOnly</code>, or <code>all</code>.
-      <strong>Since Apache Ant 1.8</strong>
-    </td>
-    <td valign="top" align="center">No, default <code>ignore</code></td>
+    <td>namespacePolicy</td>
+    <td>Sets the namespace policy as defined
+      by <code>org.apache.tools.ant.util.DOMElementWriter.XmlNamespacePolicy</code>.  Valid values
+      are <q>ignore</q>, <q>elementsOnly</q>, or <q>all</q>.  <em>Since Apache Ant 1.8</em></td>
+    <td>No; default <q>ignore</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
-Nested XML content is required.
+<p>Nested XML content is required.</p>
 
 <h3>Examples</h3>
+
+<p>Create an Ant buildfile, <samp>subbuild.xml</samp>.</p>
 <pre>&lt;echoxml file=&quot;subbuild.xml&quot;&gt;
   &lt;project default=&quot;foo&quot;&gt;
     &lt;target name=&quot;foo&quot;&gt;
       &lt;echo&gt;foo&lt;/echo&gt;
     &lt;/target&gt;
   &lt;/project&gt;
-&lt;/echoxml&gt;
-</pre>
-<p>Creates an Ant buildfile, <code>subbuild.xml</code>.</p>
+&lt;/echoxml&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/ejb.html b/manual/Tasks/ejb.html
index 37a34a9..0e78bde 100644
--- a/manual/Tasks/ejb.html
+++ b/manual/Tasks/ejb.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>EJB Tasks</title>
 
@@ -36,94 +36,93 @@
   <li>Conor MacNeill</li>
   <li>Cyrille Morvan (<a href="mailto:cmorvan@ingenosya.com">cmorvan@ingenosya.com</a>)</li>
   <li>Greg Nelson (<a href="mailto:gn@sun.com">gn@sun.com</a>)</li>
-  <li>Rob van Oostrum(<a href="mailto:rob@springwellfarms.ca">rob@springwellfarms.ca</a>)</li>
+  <li>Rob van Oostrum (<a href="mailto:rob@springwellfarms.ca">rob@springwellfarms.ca</a>)</li>
 </ul>
 
-<hr>
+<hr/>
 <h2>Table of Contents</h2>
 <ul>
   <li><a href="#introduction">Introduction</a></li>
   <li><a href="#ejbtasks">EJB Tasks</a></li>
 </ul>
 
-<hr>
-<h2><a name="introduction">Introduction</a></h2>
-<p>Ant provides a number of optional tasks for developing 1.x and 2.x
-<a href="http://www.oracle.com/technetwork/java/index-jsp-140203.html" target="_top">Enterprise Java Beans (EJBs)</a>.
-In general these tasks are specific to the particular vendor's EJB Server.</p>
+<hr/>
+<h2 id="introduction">Introduction</h2>
+<p>Ant provides a number of optional tasks for developing 1.x and
+2.x <a href="https://www.oracle.com/technetwork/java/index-jsp-140203.html" target="_top">Enterprise
+Java Beans (EJBs)</a>.  In general these tasks are specific to the particular vendor's EJB
+Server.</p>
 
-<p> The tasks support:<br>
+<p>The tasks support:</p>
 
 <ul>
-  <li><a href="http://www.borland.com">Borland </a>
-  Application Server 4.5</li>
-  <li><a href="http://www.iplanet.com">iPlanet </a>
-  Application Server 6.0</li>
-  <li><a href="http://www.jboss.org/" target="_top">
-  JBoss 2.1</a> and above EJB servers</li>
-  <li><a href="http://web.archive.org/web/20080516210506/http://www.ironflare.com/">
-  Orion Application Server</a> 2.0 <em>since 1.9.10</em></li>
-  <li><a href="http://www.bea.com" target="_top">Weblogic</a>
-   4.5.1 through to 7.0 EJB servers</li>
-  <li><a href="http://www.objectweb.org/jonas/" target="_top">JOnAS</a>
-   2.4.x and 2.5 Open Source EJB server</li>
-  <li><a href="http://www.ibm.com/websphere">IBM WebSphere</a> 4.0</li>
+  <li><a href="https://www.borland.com" target="_top">Borland</a>Application Server 4.5</li>
+  <li><a href="https://web.archive.org/web/20020202082841/http://www.iplanet.com/products/iplanet_application/home_ias.html"
+         target="_top">iPlanet</a> Application Server 6.0</li>
+  <li><a href="https://www.jboss.org/" target="_top">JBoss 2.1</a> and above EJB servers</li>
+  <li><a href="https://web.archive.org/web/20080516210506/http://www.ironflare.com/"
+         target="_top">Orion Application Server</a> 2.0 (<em>since Ant 1.10.2</em>)</li>
+  <li><a href="https://www.oracle.com/corporate/acquisitions/bea/" target="_top">WebLogic</a> 4.5.1 through to 7.0 EJB servers</li>
+  <li><a href="https://jonas.ow2.org/" target="_top">JOnAS</a> 2.4.x and 2.5 Open Source EJB server</li>
+  <li><a href="https://www.ibm.com/websphere" target="_top">IBM WebSphere</a> 4.0</li>
 </ul>
-    Vendors such as BEA and IBM now provide custom Ant tasks to work with their
-    particular products. More importantly, EJB3.0 renders this whole process obsolete.
-    Accordingly, development of these tasks is effectively frozen. Bug reports
-    and especially patches are welcome, but there is no pressing need to add
-    support for new application servers. Nobody should be writing new EJB2.x applications
-    and definitely not new EJB2.x servers.
-</p>
+<p>Vendors such as BEA and IBM now provide custom Ant tasks to work with their particular
+products. More importantly, EJB 3.0 renders this whole process obsolete.  Accordingly, development
+of these tasks is effectively frozen. Bug reports and especially patches are welcome, but there is
+no pressing need to add support for new application servers. Nobody should be writing new EJB 2.x
+applications and definitely not new EJB 2.x servers.</p>
 
-<hr>
-<h2><a name="ejbtasks">EJB Tasks</a></h2>
-<table border="1" cellpadding="5">
- <tr><td>Task</td><td colspan="2">Application Servers</td></tr>
- <tr><td><a href="BorlandGenerateClient.html">blgenclient</a></td><td colspan="2">Borland Application Server 4.5 and 5.x</td></tr>
- <tr><td><a href="#iplanet-ejbc">iplanet-ejbc</a></td><td colspan="2">iPlanet Application Server 6.0</td></tr>
- <tr><td rowspan="8"><a href="#ejbjar">ejbjar</a></td><td colspan="2" align="center"><b>Nested Elements</b></td></tr>
- <tr><td><a href="BorlandEJBTasks.html">borland</a></td><td>Borland Application Server 4.5 and 5.x</td></tr>
- <tr><td><a href="#ejbjar_iplanet">iPlanet</a></td><td>iPlanet Application Server 6.0</td></tr>
- <tr><td><a href="#ejbjar_jboss">jboss</a></td><td>JBoss</td></tr>
- <tr><td><a href="#ejbjar_jonas">jonas</a></td><td>JOnAS 2.4.x and 2.5</td></tr>
- <tr><td><a href="#ejbjar_weblogic">weblogic</a></td><td>Weblogic 5.1 to 7.0</td></tr>
- <tr><td><a href="#ejbjar_websphere">websphere</a></td><td>IBM WebSphere 4.0</td></tr>
- <tr><td><a href="#ejbjar_orion">orion</a></td><td>IronFlare(Oracle) Orion Application Server 2.0.6</td></tr>
-
+<hr/>
+<h2 id="ejbtasks">EJB Tasks</h2>
+<table>
+  <tr><th scope="col">Task</th><th scope="col" colspan="2">Application Servers</th></tr>
+  <tr><td><a href="BorlandGenerateClient.html">blgenclient</a></td><td colspan="2">Borland
+    Application Server 4.5 and 5.x</td></tr>
+  <tr><td><a href="#iplanet-ejbc">iplanet-ejbc</a></td><td colspan="2">iPlanet Application Server
+    6.0</td></tr>
+  <tr><td rowspan="8"><a href="#ejbjar">ejbjar</a></td><th scope="col" colspan="2">Nested Elements</th></tr>
+  <tr><td><a href="BorlandEJBTasks.html">borland</a></td><td>Borland Application Server 4.5 and
+    5.x</td></tr>
+  <tr><td><a href="#ejbjar_iplanet">iPlanet</a></td><td>iPlanet Application Server 6.0</td></tr>
+  <tr><td><a href="#ejbjar_jboss">jboss</a></td><td>JBoss</td></tr>
+  <tr><td><a href="#ejbjar_jonas">jonas</a></td><td>JOnAS 2.4.x and 2.5</td></tr>
+  <tr><td><a href="#ejbjar_weblogic">weblogic</a></td><td>WebLogic 5.1 to 7.0</td></tr>
+  <tr><td><a href="#ejbjar_websphere">websphere</a></td><td>IBM WebSphere 4.0</td></tr>
+  <tr><td><a href="#ejbjar_orion">orion</a></td><td>IronFlare (Oracle) Orion Application Server
+    2.0.6</td></tr>
 </table>
 
-<hr>
-<h2><a name="ddcreator">ddcreator</a></h2>
-<h3><b>Description:</b></h3>
-<p>ddcreator will compile a set of Weblogic text-based deployment descriptors into a serialized
-EJB deployment descriptor. The selection of which of the text-based descriptors are to be compiled
-is based on the standard Ant include and exclude selection mechanisms.
-</p>
+<hr/>
 
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<h2 id="ddcreator">ddcreator</h2>
+<h3>Description</h3>
+<p><code>ddcreator</code> will compile a set of WebLogic text-based deployment descriptors into a
+serialized EJB deployment descriptor. The selection of which of the text-based descriptors are to be
+compiled is based on the standard Ant <code>include</code> and <code>exclude</code> selection
+mechanisms.</p>
+
+<h3>Parameters</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">descriptors</td>
-    <td valign="top">This is the base directory from which descriptors are selected.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>descriptors</td>
+    <td>This is the base directory from which descriptors are selected.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">The directory where the serialized deployment descriptors will be written</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dest</td>
+    <td>The directory where the serialized deployment descriptors will be written</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">This is the classpath to use to run the underlying weblogic ddcreator tool.
-                     This must include the <code>weblogic.ejb.utils.DDCreator</code> class</td>
-    <td valign="top" align="center">No</td>
+    <td>classpath</td>
+    <td>This is the classpath to use to run the underlying WebLogic <code>ddcreator</code> tool.
+      This must include the <code>weblogic.ejb.utils.DDCreator</code> class</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
@@ -132,69 +131,67 @@
            dest=&quot;${gen.classes}&quot;
            classpath=&quot;${descriptorbuild.classpath}&quot;&gt;
   &lt;include name=&quot;*.txt&quot;/&gt;
-&lt;/ddcreator&gt;
-</pre>
+&lt;/ddcreator&gt;</pre>
 
-<hr>
-<h2><a name="ejbc">ejbc</a></h2>
-<h3><b>Description:</b></h3>
-<p>The ejbc task will run Weblogic's ejbc tool. This tool will take a serialized deployment descriptor,
-examine the various EJB interfaces and bean classes and then generate the required support classes
-necessary to deploy the bean in a Weblogic EJB container. This will include the RMI stubs and skeletons
-as well as the classes which implement the bean's home and remote interfaces.</p>
-<p>
-The ant task which runs this tool is able to compile several beans in a single operation. The beans to be
-compiled are selected by including their serialized deployment descriptors. The standard ant
-<code>include</code> and <code>exclude</code> constructs can be used to select the deployment descriptors
-to be included. </p>
-<p>
-Each descriptor is examined to determine whether the generated classes are out of date and need to be
-regenerated. The deployment descriptor is de-serialized to discover the home, remote and
+<hr/>
+<h2 id="ejbc">ejbc</h2>
+<h3>Description</h3>
+<p>The <code>ejbc</code> task will run WebLogic's <kbd>ejbc</kbd> tool. This tool will take a
+serialized deployment descriptor, examine the various EJB interfaces and bean classes and then
+generate the required support classes necessary to deploy the bean in a WebLogic EJB container. This
+will include the RMI stubs and skeletons as well as the classes which implement the bean's home and
+remote interfaces.</p>
+<p>The Ant task which runs this tool is able to compile several beans in a single operation. The
+beans to be compiled are selected by including their serialized deployment descriptors. The standard
+Ant <code>include</code> and <code>exclude</code> constructs can be used to select the deployment
+descriptors to be included.</p>
+<p>Each descriptor is examined to determine whether the generated classes are out of date and need
+to be regenerated. The deployment descriptor is de-serialized to discover the home, remote and
 implementation classes. The corresponding source files are determined and checked to see their
 modification times. These times and the modification time of the serialized descriptor itself are
-compared with the modification time of the generated classes. If the generated classes are not present
-or are out of date, the ejbc tool is run to generate new versions.</p>
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+compared with the modification time of the generated classes. If the generated classes are not
+present or are out of date, the <kbd>ejbc</kbd> tool is run to generate new versions.</p>
+<h3>Parameters</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">descriptors</td>
-    <td valign="top">This is the base directory from which the serialized deployment descriptors are selected.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>descriptors</td>
+    <td>This is the base directory from which the serialized deployment descriptors are
+      selected.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">The base directory where the generated classes, RIM stubs and RMI skeletons are written</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dest</td>
+    <td>The base directory where the generated classes, RIM stubs and RMI skeletons are written</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">manifest</td>
-    <td valign="top">The name of a manifest file to be written. This manifest will contain an entry for each EJB processed</td>
-    <td valign="top" align="center">Yes</td>
+    <td>manifest</td>
+    <td>The name of a manifest file to be written. This manifest will contain an entry for each EJB
+      processed</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">The base directory of the source tree containing the source files of the home interface,
-                     remote interface and bean implementation classes.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>src</td>
+    <td>The base directory of the source tree containing the source files of the home interface,
+      remote interface and bean implementation classes.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">This classpath must include both the <code>weblogic.ejbc</code> class and the
-                     class files of the bean, home interface, remote interface, etc of the bean being
-                     processed.</td>
-    <td valign="top" align="center">No</td>
+    <td>classpath</td>
+    <td>This classpath must include both the <code>weblogic.ejbc</code> class and the class files of
+      the bean, home interface, remote interface, etc of the bean being processed.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keepgenerated</td>
-    <td>Controls whether ejbc will keep the
-        intermediate Java files used to build the class files. This can be
-        useful when debugging.</td>
-    <td>No, defaults to false.</td>
+    <td>keepgenerated</td>
+    <td>Controls whether <kbd>ejbc</kbd> will keep the intermediate java files used to build the
+      class files. This can be useful when debugging.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
@@ -205,113 +202,83 @@
            manifest=&quot;${build.manifest}&quot;
            classpath=&quot;${descriptorbuild.classpath}&quot;&gt;
   &lt;include name=&quot;*.ser&quot;/&gt;
-&lt;/ejbc&gt;
-</pre>
+&lt;/ejbc&gt;</pre>
 
-<hr>
-<h2>
-<a NAME="iplanet-ejbc"></a>iplanet-ejbc</h2>
+<hr/>
+<h2 id="iplanet-ejbc">iplanet-ejbc</h2>
 
-<h3>
-<b>Description:</b></h3>
-Task to compile EJB stubs and skeletons for the iPlanet Application Server
-6.0.  Given a standard EJB 1.1 XML descriptor as well as an iAS-specific
-EJB descriptor, this task will generate the stubs and skeletons required
-to deploy the EJB to iAS.  Since the XML descriptors can include multiple
-EJBs, this is a convenient way of specifying many EJBs in a single Ant
-task.
-<p>For each EJB specified, the task will locate the three classes that
-comprise the EJB in the destination directory.  If these class files
-cannot be located in the destination directory, the task will fail. The
-task will also attempt to locate the EJB stubs and skeletons in this directory.
-If found, the timestamps on the stubs and skeletons will be checked to
-ensure they are up to date. Only if these files cannot be found or if they
-are out of date will the iAS ejbc utility be called to generate new stubs
-and skeletons.</p>
-<h3>
-Parameters:</h3>
+<h3>Description</h3>
+<p>Task to compile EJB stubs and skeletons for the iPlanet Application Server 6.0.  Given a standard
+EJB 1.1 XML descriptor as well as an iAS-specific EJB descriptor, this task will generate the stubs
+and skeletons required to deploy the EJB to iAS.  Since the XML descriptors can include multiple
+EJBs, this is a convenient way of specifying many EJBs in a single Ant task.</p>
+<p>For each EJB specified, the task will locate the three classes that comprise the EJB in the
+destination directory.  If these class files cannot be located in the destination directory, the
+task will fail. The task will also attempt to locate the EJB stubs and skeletons in this directory.
+If found, the timestamps on the stubs and skeletons will be checked to ensure they are up to
+date. Only if these files cannot be found or if they are out of date will the iAS <kbd>ejbc</kbd>
+utility be called to generate new stubs and skeletons.</p>
+<h3>Parameters</h3>
 
-<table border="1" cellspacing="0" cellpadding="2">
-<tr>
-<td valign="top"><b>Attribute</b></td>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
 
-<td valign="top"><b>Description</b></td>
+  <tr>
+    <td>ejbdescriptor</td>
+    <td>Standard EJB 1.1 XML descriptor (typically titled <q>ejb-jar.xml</q>).</td>
+    <td>Yes</td>
+  </tr>
 
-<td align="center" valign="top"><b>Required</b></td>
-</tr>
+  <tr>
+    <td>iasdescriptor</td>
+    <td>iAS-specific EJB XML descriptor (typically titled <q>ias-ejb-jar.xml</q>).</td>
+    <td>Yes</td>
+  </tr>
 
-<tr>
-<td valign="top">ejbdescriptor</td>
+  <tr>
+    <td>dest</td>
+    <td>The is the base directory where the RMI stubs and skeletons are written. In addition, the
+      class files for each bean (home interface, remote interface, and EJB implementation) must be
+      found in this directory.</td>
+    <td>Yes</td>
+  </tr>
 
-<td valign="top">Standard EJB 1.1 XML descriptor (typically titled "ejb-jar.xml").</td>
+  <tr>
+    <td>classpath</td>
+    <td>The classpath used when generating EJB stubs and skeletons.  Nested <code>classpath</code>
+      elements may also be used.</td>
+    <td>No; defaults to the classpath specified when Ant was started</td>
+  </tr>
 
-<td align="center" valign="top">Yes</td>
-</tr>
+  <tr>
+    <td>keepgenerated</td>
+    <td>Indicates whether or not the Java source files which are generated by <kbd>ejbc</kbd> will
+      be saved or automatically deleted. If <q>yes</q>, the source files will be retained.</td>
+    <td>No; defaults to <q>no</q></td>
+  </tr>
 
-<tr>
-<td valign="top">iasdescriptor</td>
+  <tr>
+    <td>debug</td>
+    <td>Indicates whether or not the <kbd>ejbc</kbd> utility should log additional debugging
+      statements to the standard output. If <q>yes</q>, the additional debugging statements will be
+      generated.</td>
+    <td>No; defaults to <q>no</q></td>
+  </tr>
 
-<td valign="top">iAS-specific EJB XML descriptor (typically titled "ias-ejb-jar.xml").</td>
-
-<td align="center" valign="top">Yes</td>
-</tr>
-
-<tr>
-<td valign="top">dest</td>
-
-<td valign="top">The is the base directory where the RMI stubs and skeletons
-are written. In addition, the class files for each bean (home interface,
-remote interface, and EJB implementation) must be found in this directory.</td>
-
-<td align="center" valign="top">Yes</td>
-</tr>
-
-<tr>
-<td valign="top">classpath</td>
-
-<td valign="top">The classpath used when generating EJB stubs and skeletons.
-If omitted, the classpath specified when Ant was started will be used.
-Nested "classpath" elements may also be used.</td>
-
-<td align="center" valign="top">No</td>
-</tr>
-
-<tr>
-<td valign="top">keepgenerated</td>
-
-<td valign="top">Indicates whether or not the Java source files which are
-generated by ejbc will be saved or automatically deleted. If "yes", the
-source files will be retained. If omitted, it defaults to "no". </td>
-
-<td align="center" valign="top">No</td>
-</tr>
-
-<tr>
-<td valign="top">debug</td>
-
-<td>Indicates whether or not the ejbc utility should log additional debugging
-statements to the standard output. If "yes", the additional debugging statements
-will be generated.  If omitted, it defaults to "no". </td>
-
-<td align="center" valign="top">
-<center>No</center>
-</td>
-</tr>
-
-<tr>
-<td valign="top">iashome</td>
-
-<td>May be used to specify the "home" directory for this iAS installation.
-This is used to find the ejbc utility if it isn't included in the user's
-system path. If specified, it should refer to the "[install-location]/iplanet/ias6/ias"
-directory. If omitted, the ejbc utility must be on the user's system path. </td>
-
-<td align="center" valign="top">No</td>
-</tr>
+  <tr>
+    <td>iashome</td>
+    <td>May be used to specify the "home" directory for this iAS installation.  This is used to find
+      the <kbd>ejbc</kbd> utility if it isn't included in the user's system path. If specified, it
+      should refer to the <samp>[install-location]/iplanet/ias6/ias</samp> directory.</td>
+    <td>No; by default the <kbd>ejbc</kbd> utility must be on the user's system path</td>
+  </tr>
 </table>
 
-<h3>
-Examples</h3>
+<h3>Examples</h3>
 
 <pre>
 &lt;iplanet-ejbc ejbdescriptor="ejb-jar.xml"
@@ -330,129 +297,111 @@
                   &lt;pathelement path="."/&gt;
                   &lt;pathelement path="${build.classpath}"/&gt;
               &lt;/classpath&gt;
-&lt;/iplanet-ejbc&gt;
+&lt;/iplanet-ejbc&gt;</pre>
 
+<hr/>
+<h2 id="wlrun">wlrun</h2>
+<h3>Description</h3>
 
-</pre>
+<p>The <code>wlrun</code> task is used to start a WebLogic server. The task runs a WebLogic instance
+in a separate JVM. A number of parameters are used to control the operation of the WebLogic
+instance. Note that the task, and hence Ant, will not complete until the WebLogic instance is
+stopped.</p>
 
-<hr>
-<h2><a name="wlrun">wlrun</a></h2>
-<h3><b>Description:</b></h3>
-
-<p>The <code>wlrun</code> task is used to start a weblogic server. The task runs
-a weblogic instance in a separate Java Virtual Machine. A number of parameters
-are used to control the operation of the weblogic instance. Note that the task,
-and hence ant, will not complete until the weblogic instance is stopped.</p>
-
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required for 4.5.1 and 5.1</b></td>
-    <td align="center" valign="top"><b>Required for 6.0</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required for 4.5.1 and 5.1</th>
+    <th scope="col">Required for 6.0</th>
   </tr>
   <tr>
-    <td valign="top">BEA Home</td>
-    <td valign="top">The location of the BEA Home where the server's config is defined.
-                     If this attribute is present, wlrun assumes that the server will
-                     be running under Weblogic 6.0</td>
-    <td valign="top" align="center">N/A</td>
-    <td valign="top" align="center">Yes</td>
+    <td>BEAhome</td>
+    <td>The location of the <var>BEAhome</var> where the server's config is stored.  If this
+      attribute is present, <code>wlrun</code> assumes that the server will be running under
+      WebLogic 6.0</td>
+    <td class="center">N/A</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">home</td>
-    <td valign="top">The location of the weblogic home that is to be used. This is the location
-                     where weblogic is installed.</td>
-    <td valign="top" align="center">Yes</td>
-    <td valign="top" align="center">Yes. Note this is the absolute location, not relative to
-                                    BEA home.</td>
+    <td>home</td>
+    <td>The location of the WebLogic "home" where WebLogic is installed.</td>
+    <td class="center">Yes</td>
+    <td>Yes. Note this is the absolute location, not relative to <var>BEAhome</var>.</td>
   </tr>
   <tr>
-    <td valign="top">Domain</td>
-    <td valign="top">The domain to which the server belongs.</td>
-    <td valign="top" align="center">N/A</td>
-    <td valign="top" align="center">Yes</td>
+    <td>Domain</td>
+    <td>The domain to which the server belongs.</td>
+    <td class="center">N/A</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to be used with the Java Virtual Machine that runs the Weblogic
-                     Server. Prior to Weblogic 6.0, this is typically set to the Weblogic
-                     boot classpath. Under Weblogic 6.0 this should include all the
-                     weblogic jars</td>
-    <td valign="top" align="center">Yes</td>
-    <td valign="top" align="center">Yes</td>
+    <td>classpath</td>
+    <td>The classpath to be used with the JVM that runs the WebLogic Server. Prior to WebLogic 6.0,
+      this is typically set to the WebLogic boot classpath. Under WebLogic 6.0 this should include
+      all the WebLogic jars</td>
+    <td colspan="2">Yes</td>
   </tr>
   <tr>
-    <td valign="top">wlclasspath</td>
-    <td valign="top">The weblogic classpath used by the Weblogic Server.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">N/A</td>
+    <td>wlclasspath</td>
+    <td>The WebLogic classpath used by the WebLogic Server.</td>
+    <td class="center">No</td>
+    <td rowspan="2">N/A</td>
   </tr>
   <tr>
-    <td valign="top">properties</td>
-    <td valign="top">The name of the server's properties file within the weblogic home directory
-                     used to control the weblogic instance.</td>
-    <td valign="top" align="center">Yes</td>
-    <td valign="top" align="center">N/A</td>
+    <td>properties</td>
+    <td>The name of the server's properties file within the WebLogic home directory used to control
+      the WebLogic instance.</td>
+    <td class="center">Yes</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the weblogic server within the weblogic home which is to be run.
-                     This defaults to &quot;myserver&quot;</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">No</td>
+    <td>name</td>
+    <td>The name of the WebLogic server within the WebLogic home which is to be run.</td>
+    <td colspan="2">No; defaults to <q>myserver</q></td>
   </tr>
   <tr>
-    <td valign="top">policy</td>
-    <td valign="top">The name of the security policy file within the weblogic home directory that
-                     is to be used. If not specified, the default policy file <code>weblogic.policy</code>
-                     is used.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">No</td>
+    <td>policy</td>
+    <td>The name of the security policy file within the WebLogic home directory that is to be
+      used.</td>
+    <td colspan="2">No; defaults to <q>weblogic.policy</q></td>
   </tr>
   <tr>
-    <td valign="top">username</td>
-    <td valign="top">The management username used to manage the server</td>
-    <td valign="top" align="center">N/A</td>
-    <td valign="top" align="center">No</td>
+    <td>username</td>
+    <td>The management username used to manage the server</td>
+    <td class="center" rowspan="3">N/A</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">The server's management password</td>
-    <td valign="top" align="center">N/A</td>
-    <td valign="top" align="center">Yes</td>
+    <td>password</td>
+    <td>The server's management password</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">pkPassword</td>
-    <td valign="top">The private key password so the server can decrypt the SSL
-                     private key file</td>
-    <td valign="top" align="center">N/A</td>
-    <td valign="top" align="center">No</td>
+    <td>pkPassword</td>
+    <td>The private key password so the server can decrypt the SSL private key file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">jvmargs</td>
-    <td valign="top">Additional argument string passed to the Java Virtual Machine used to run the
-                     Weblogic instance.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">No</td>
+    <td>jvmargs</td>
+    <td>Additional argument string passed to the JVM used to run the WebLogic instance.</td>
+    <td colspan="2">No</td>
   </tr>
   <tr>
-    <td valign="top">weblogicMainClass</td>
-    <td valign="top">name of the main class for weblogic</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">No</td>
+    <td>weblogicMainClass</td>
+    <td>The name of the main class for WebLogic</td>
+    <td colspan="2">No</td>
   </tr>
 </table>
 
-<h3>Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
-<p>The wlrun task supports nested <code>&lt;classpath&gt;</code> and <code>&lt;wlclasspath&gt;</code>
-elements to set the respective classpaths.</p>
+<p>The <code>wlrun</code> task supports nested <code>&lt;classpath&gt;</code>
+and <code>&lt;wlclasspath&gt;</code> elements to set the respective classpaths.</p>
 
 <h3>Examples</h3>
 
-<p>This example shows the use of wlrun to run a server under Weblogic 5.1</p>
+<p>This example shows the use of <code>wlrun</code> to run a server under WebLogic 5.1</p>
 
 <pre>
     &lt;wlrun taskname=&quot;myserver&quot;
@@ -463,1357 +412,1196 @@
            properties=&quot;myserver/myserver.properties&quot;/&gt;
 </pre>
 
-<p>This example shows wlrun being used to run the petstore server under
-Weblogic 6.0</p>
+<p>This example shows <code>wlrun</code> being used to run the <samp>petstore</samp> server under
+WebLogic 6.0</p>
 
 <pre>
-    &lt;wlrun taskname=&quot;petstore&quot;
-           classpath=&quot;${weblogic.classes}&quot;
-           name=&quot;petstoreServer&quot;
-           domain=&quot;petstore&quot;
-           home=&quot;${weblogic.home}&quot;
-           password=&quot;petstorePassword&quot;
-           beahome=&quot;${bea.home}&quot;/&gt;
-</pre>
+&lt;wlrun taskname=&quot;petstore&quot;
+       classpath=&quot;${weblogic.classes}&quot;
+       name=&quot;petstoreServer&quot;
+       domain=&quot;petstore&quot;
+       home=&quot;${weblogic.home}&quot;
+       password=&quot;petstorePassword&quot;
+       beahome=&quot;${bea.home}&quot;/&gt;</pre>
 
-<hr>
-<h2><a name="wlstop">wlstop</a></h2>
-<h3><b>Description:</b></h3>
+<hr/>
+<h2 id="wlstop">wlstop</h2>
+<h3>Description</h3>
 
-<p>The <code>wlstop</code> task is used to stop a weblogic instance which is
-currently running. To shut down an instance you must supply both a username and
-a password. These will be stored in the clear in the build script used to stop
-the instance. For security reasons, this task is therefore only appropriate in a
-development environment. </p>
+<p>The <code>wlstop</code> task is used to stop a WebLogic instance which is currently running. To
+shut down an instance you must supply both a username and a password. These will be stored in the
+clear in the build script used to stop the instance. For security reasons, this task is therefore
+only appropriate in a development environment.</p>
 
-<p>This task works for most version of Weblogic, including 6.0. You need to
-specify the BEA Home to have this task work correctly under 6.0</p>
+<p>This task works for most versions of WebLogic, including 6.0. You need to specify
+the <var>BEAHome</var> to have this task work correctly under 6.0</p>
 
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">BEAHome</td>
-    <td valign="top">This attribute selects Weblogic 6.0 shutdown.</td>
-    <td valign="top" align="center">No</td>
+    <td>BEAHome</td>
+    <td>This attribute selects WebLogic 6.0 shutdown.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to be used with the Java Virtual Machine that runs the Weblogic
-                     Shutdown command.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>classpath</td>
+    <td>The classpath to be used with the JVM that runs the WebLogic Shutdown command.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">user</td>
-    <td valign="top">The username of the account which will be used to shutdown the server</td>
-    <td valign="top" align="center">Yes</td>
+    <td>user</td>
+    <td>The username of the account which will be used to shutdown the server</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">The password for the account specified in the user parameter.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>password</td>
+    <td>The password for the account specified in the user parameter.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">The URL which describes the port to which the server is listening for T3 connections.
-                     For example, t3://localhost:7001</td>
-    <td valign="top" align="center">Yes</td>
+    <td>url</td>
+    <td>The URL which describes the port to which the server is listening for T3 connections.  For
+      example, <samp>t3://localhost:7001</samp></td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">delay</td>
-    <td valign="top">The delay in seconds after which the server will stop. This defaults to an
-                     immediate shutdown.</td>
-    <td valign="top" align="center">No</td>
+    <td>delay</td>
+    <td>The delay in seconds after which the server will stop.</td>
+    <td>No; default is <q>0</q> (immediate shutdown)</td>
   </tr>
 </table>
 
-<h3>Nested Element</h3>
+<h3>Parameters specified as nested elements</h3>
 
-<p>The classpath of the wlstop task can be set by a <code>&lt;classpath&gt;</code> nested element.</p>
+<p>The classpath of the <code>wlstop</code> task can be set by a <code>&lt;classpath&gt;</code>
+nested element.</p>
 
 <h3>Examples</h3>
 
-<p>This example show the shutdown for a Weblogic 6.0 server</p>
+<p>This example show the shutdown for a WebLogic 6.0 server</p>
 
 <pre>
-    &lt;wlstop classpath=&quot;${weblogic.classes}&quot;
-            user=&quot;system&quot;
-            url=&quot;t3://localhost:7001&quot;
-            password=&quot;foobar&quot;
-            beahome=&quot;${bea.home}&quot;/&gt;
-</pre>
+&lt;wlstop classpath=&quot;${weblogic.classes}&quot;
+        user=&quot;system&quot;
+        url=&quot;t3://localhost:7001&quot;
+        password=&quot;foobar&quot;
+        beahome=&quot;${bea.home}&quot;/&gt;</pre>
 
-<hr>
+<hr/>
+<h2 id="ejbjar">ejbjar</h2>
+<h3>Description</h3>
 
-<h2><a name="ejbjar">ejbjar</a></h2>
-<h3><b>Description:</b></h3>
-
-<p>This task is designed to support building of EJB jar files (EJB 1.1 &amp; 2.0).
-Support is currently provided for 'vanilla' EJB jar files - i.e. those containing only
-the user generated class files and the standard deployment descriptor. Nested
-elements provide support for vendor specific deployment tools. These currently
-include: </p>
+<p>This task is designed to support building of EJB jar files (EJB 1.1 &amp; 2.0).  Support is
+currently provided for 'vanilla' EJB jar files&mdash;i.e. those containing only the user generated
+class files and the standard deployment descriptor. Nested elements provide support for vendor
+specific deployment tools. These currently include:</p>
 <ul>
   <li>Borland Application Server 4.5</li>
   <li>iPlanet Application Server 6.0</li>
   <li>JBoss 2.1 and above</li>
-  <li>Weblogic 5.1/6.0 session/entity beans using the weblogic.ejbc tool</li>
+  <li>WebLogic 5.1/6.0 session/entity beans using the <code>weblogic.ejbc</code> tool</li>
   <li>IBM WebSphere 4.0</li>
   <li>TOPLink for WebLogic 2.5.1-enabled entity beans</li>
-  <li><a href="http://www.objectweb.org/jonas/">JOnAS</a> 2.4.x and 2.5 Open Source EJB server</li>
+  <li><a href="https://jonas.ow2.org/" target="_top">JOnAS</a> 2.4.x and 2.5 Open Source EJB
+    server</li>
   <li>IronFlare Orion Application Server 2.0</li>
 </ul>
 
-
-<p>The task works as a directory scanning task, and performs an action for each
-deployment descriptor found. As such the includes and excludes should be set
-to ensure that all desired EJB descriptors are found, but no application
-server descriptors are found. For each descriptor found, ejbjar will parse the
-deployment descriptor to determine the necessary class files which implement the
-bean. These files are assembled along with the deployment descriptors into a
-well formed EJB jar file. Any support files which need to be included in the
-generated jar can be added with the <code>&lt;support&gt;</code> nested element. For each
-class included in the jar, ejbjar will scan for any super classes or super
+<p>The task works as a directory scanning task, and performs an action for each deployment
+descriptor found. As such the <code>includes</code> and <code>excludes</code> should be set to
+ensure that all desired EJB descriptors are found, but no application server descriptors are
+found. For each descriptor found, <code>ejbjar</code> will parse the deployment descriptor to
+determine the necessary class files which implement the bean. These files are assembled along with
+the deployment descriptors into a well formed EJB jar file. Any support files which need to be
+included in the generated jar can be added with the <code>&lt;support&gt;</code> nested element. For
+each class included in the jar, <code>ejbjar</code> will scan for any super classes or super
 interfaces. These will be added to the generated jar.</p>
 
-<p>If no nested vendor-specific deployment elements are present, the task will
-simply generate a generic EJB jar. Such jars are typically used as the input to
-vendor-specific deployment tools. For each nested deployment element, a vendor
-specific deployment tool is run to generate a jar file ready for deployment in
-that vendor's EJB container. </p>
+<p>If no nested vendor-specific deployment elements are present, the task will simply generate a
+generic EJB jar. Such jars are typically used as the input to vendor-specific deployment tools. For
+each nested deployment element, a vendor specific deployment tool is run to generate a jar file
+ready for deployment in that vendor's EJB container.</p>
 
-<p>The jar files are only built if they are out of date.  Each deployment tool
-element will examine its target jar file and determine if it is out of date with
-respect to the class files and deployment descriptors that make up the bean. If
-any of these files are newer than the jar file the jar will be rebuilt otherwise
-a message is logged that the jar file is up to date.</p>
+<p>The jar files are only built if they are out of date.  Each deployment tool element will examine
+its target jar file and determine if it is out of date with respect to the class files and
+deployment descriptors that make up the bean. If any of these files are newer than the jar file the
+jar will be rebuilt otherwise a message is logged that the jar file is up to date.</p>
 
-<p>The task uses the
-<a href="http://commons.apache.org/bcel/">BCEL</a> <a href="../install.html#librarydependencies">library</a>
-to extract all dependent classes. This
-means that, in addition to the classes that are mentioned in the
-deployment descriptor, any classes that these depend on are also
-automatically included in the jar file.</p>
+<p>The task uses the <a href="https://commons.apache.org/bcel/"
+target="_top">BCEL</a> <a href="../install.html#librarydependencies">library</a> to extract all
+dependent classes. This means that, in addition to the classes that are mentioned in the deployment
+descriptor, any classes that these depend on are also automatically included in the jar file.</p>
 
+<h3 id="naming">Naming convention</h3>
 
-<h3>Naming Convention</h3>
-
-Ejbjar handles the processing of multiple beans, and it uses a set of naming
-conventions to determine the name of the generated EJB jars. The naming convention
-that is used is controlled by the &quot;naming&quot; attribute. It supports the
-following values
-<ul>
-
-<li>descriptor</li>
-<p>This is the default naming scheme. The name of the generated bean is derived from the
-name of the deployment descriptor.  For an Account bean, for example, the deployment
-descriptor would be named <code>Account-ejb-jar.xml</code>. Vendor specific descriptors are
-located using the same naming convention. The weblogic bean, for example, would be named
-<code>Account-weblogic-ejb-jar.xml</code>. Under this arrangement, the deployment descriptors
+<code>Ejbjar</code> handles the processing of multiple beans, and it uses a set of naming
+conventions to determine the name of the generated EJB jars. The naming convention that is used is
+controlled by the <var>naming</var> attribute. It supports the following values
+<dl>
+<dt><q>descriptor</q></dt>
+<dd><p>This is the default naming scheme. The name of the generated bean is derived from the name of
+the deployment descriptor.  For an <samp>Account</samp> bean, for example, the deployment descriptor
+would be named <samp>Account-ejb-jar.xml</samp>. Vendor specific descriptors are located using the
+same naming convention. The WebLogic bean, for example, would be
+named <samp>Account-weblogic-ejb-jar.xml</samp>. Under this arrangement, the deployment descriptors
 can be separated from the code implementing the beans, which can be useful when the same bean code
-is deployed in separate beans.
-</p>
+is deployed in separate beans.</p>
+<p>This scheme is useful when you are using one bean per EJB jar and where you may be deploying the
+same bean classes in different beans, with different deployment characteristics.</p></dd>
 
-<p>This scheme is useful when you are using one bean per EJB jar and where you may be
-deploying the same bean classes in different beans, with different deployment characteristics.
-
-<li>ejb-name</li>
-<p> This naming scheme uses the <code>&lt;ejb-name&gt;</code> element from the deployment descriptor to
-determine the bean name. In this situation, the descriptors normally use the generic
-descriptor names, such as <code>ejb-jar.xml</code> along with any associated vendor specific descriptor
-names. For example, If the value of the <code>&lt;ejb-name&gt;</code> were to be given in the deployment descriptor
-as follows:
+<dt><q>ejb-name</q></dt>
+<dd><p>This naming scheme uses the <code>&lt;ejb-name&gt;</code> element from the deployment
+descriptor to determine the bean name. In this situation, the descriptors normally use the generic
+descriptor names, such as <samp>ejb-jar.xml</samp> along with any associated vendor specific
+descriptor names. For example, If the value of the <code>&lt;ejb-name&gt;</code> were to be given in
+the deployment descriptor as follows:</p>
 <pre>
 &lt;ejb-jar&gt;
     &lt;enterprise-beans&gt;
         &lt;entity&gt;
             &lt;ejb-name&gt;Sample&lt;/ejb-name&gt;
-            &lt;home&gt;org.apache.ant.ejbsample.SampleHome&lt;/home&gt;
-</pre>
+            &lt;home&gt;org.apache.ant.ejbsample.SampleHome&lt;/home&gt;</pre>
+<p>then the name of the generated bean would be <samp>Sample.jar</samp></p>
+<p>This scheme is useful where you want to use the standard deployment descriptor names, which may
+be more compatible with other EJB tools. This scheme must have one bean per jar.</p></dd>
+<dt><q>directory</q></dt>
+<dd><p>In this mode, the name of the generated bean jar is derived from the directory containing the
+deployment descriptors. Again the deployment descriptors typically use the standard filenames. For
+example, if the path to the deployment descriptor
+is <samp>/home/user/dev/appserver/dd/sample</samp>, then the generated bean will be
+named <samp>sample.jar</samp></p>
+<p>This scheme is also useful when you want to use standard style descriptor names. It is often most
+useful when the descriptors are located in the same directory as the bean source code, although that
+is not mandatory. This scheme can handle multiple beans per jar.</p></dd>
 
-then the name of the generated bean would be <code>Sample.jar</code>
-</p>
-<p> This scheme is useful where you want to use the standard deployment descriptor names, which may be more
-compatible with other EJB tools. This scheme must have one bean per jar.
-</p>
-<li>directory</li>
-<p>
-In this mode, the name of the generated bean jar is derived from the directory
-containing the deployment descriptors. Again the deployment descriptors typically use
-the standard filenames. For example, if the path to the deployment descriptor is
-<code>/home/user/dev/appserver/dd/sample</code>, then the generated
-bean will be named <code>sample.jar</code>
-</p>
-<p>
-This scheme is also useful when you want to use standard style descriptor names. It is often
-most useful when the  descriptors are located in the same directory as the bean source code,
-although that is not mandatory. This scheme can handle multiple beans per jar.
-</p>
+<dt><q>basejarname</q></dt>
+<dd><p>The final scheme supported by the <code>&lt;ejbjar&gt;</code> task is used when you want to
+specify the generated bean jar name directly. In this case the name of the generated jar is
+specified by the <var>basejarname</var> attribute. Since all generated beans will have the same
+name, this task should be only used when each descriptor is in its own directory.</p>
 
-<li>basejarname</li>
-<p>
-The final scheme supported by the <code>&lt;ejbjar&gt;</code> task is used when you want to specify the generated
-bean jar name directly. In this case the name of the generated jar is specified by the
-&quot;basejarname&quot; attribute. Since all generated beans will have the same name, this task should
-be only used when each descriptor is in its own directory.
-</p>
+<p>This scheme is most appropriate when you are using multiple beans per jar and only process a
+single deployment descriptor. You typically want to specify the name of the jar and not derive it
+from the beans in the jar.</p></dd>
+</dl>
 
-<p>
-This scheme is most appropriate when you are using multiple beans per jar and only process a single
-deployment descriptor. You typically want to specify the name of the jar and not derive it from the
-beans in the jar.
-</p>
+<h3 id="ejbjar_deps">Dependencies</h3>
+<p>In addition to the bean classes, <code>ejbjar</code> is able to ad additional classes to the
+generated EJB jar. These classes are typically the support classes which are used by the bean's
+classes or as parameters to the bean's methods.</p>
 
-</ul>
+<p>In versions of Ant prior to 1.5, <code>ejbjar</code> used reflection and attempted to add the
+super classes and super interfaces of the bean classes. For this technique to work the bean classes
+had to be loaded into Ant's JVM. This was not always possible due to class dependencies.</p>
 
-<a name="ejbjar_deps"><h3>Dependencies</h3></a>
-<p>In addition to the bean classes, ejbjar is able to ad additional classes to the generated
-ejbjar. These classes are typically the support classes which are used by the bean's classes or as
-parameters to the bean's methods.</p>
+<p><em>Since Ant 1.5</em> the task uses the <a href="https://commons.apache.org/bcel/"
+target="_top">BCEL</a> library to analyze the bean's class files directly, rather than loading them
+into the JVM. This also allows <code>ejbjar</code> to add all of the required support classes for a
+bean and not just super classes.</p>
 
-<p>In versions of Ant prior to 1.5, ejbjar used reflection and attempted to add the super
-classes and super interfaces of the bean classes. For this technique to work the bean
-classes had to be loaded into Ant's JVM. This was not always possible due to class dependencies.
-</p>
-
-<p>The ejbjar task in Ant releases 1.5 and later uses the
-<a href="http://commons.apache.org/bcel/"> BCEL </a> library
-to analyze the bean's class
-files directly, rather than loading them into the JVM. This also allows ejbjar to add all
-of the required support classes for a bean and not just super classes.
-</p>
-
-<p>In Ant 1.5, a new attribute, <code>dependency</code> has been introduced to allow the
-buildfile to control what additional classes are added to the generated jar. It takes three
-possible values</p>
+<p><em>Since Ant 1.5</em>, a <var>dependency</var> attribute allows the buildfile to control what
+additional classes are added to the generated jar. It takes three possible values</p>
 <ul>
-<li><code>none</code> - only the bean classes and interfaces described in the bean's
-descriptor are added to the jar.</li>
-<li><code>super</code> - this is the default value and replicates the original ejbjar
-behaviour where super classes and super interfaces are added to the jar</li>
-<li><code>full</code> - In this mode all classes used by the bean's classes and interfaces
-are added to the jar</li>
+  <li><q>none</q>&mdash;only the bean classes and interfaces described in the bean's descriptor are
+    added to the jar.</li>
+  <li><q>super</q>&mdash;this is the default value and replicates the original <code>ejbjar</code>
+    behaviour where super classes and super interfaces are added to the jar</li>
+  <li><q>full</q>&mdash;In this mode all classes used by the bean's classes and interfaces are added
+    to the jar</li>
 </ul>
-<p>The <code>super</code> and <code>full</code> values require the
-<a href="http://commons.apache.org/bcel/"> BCEL </a> library
-to be available. If it is not, ejbjar will drop back to the behaviour corresponding to
-the value <code>none</code>.</p>
+<p>The <q>super</q> and <q>full</q> values require the <a href="https://commons.apache.org/bcel/"
+target="_top">BCEL</a> library to be available. If it is not, <code>ejbjar</code> will drop back to
+the behaviour corresponding to the value <q>none</q>.</p>
 
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">descriptordir</td>
-    <td valign="top">The base directory under which to scan for EJB
-                     deployment descriptors. If this attribute is not
-                     specified, then the deployment descriptors must be
-                     located in the directory specified by the 'srcdir'
-                     attribute.</td>
-    <td valign="top" align="center">No</td>
+    <td>descriptordir</td>
+    <td>The base directory under which to scan for EJB deployment descriptors. If this attribute is
+      not specified, then the deployment descriptors must be located in the directory specified by
+      the <var>srcdir</var> attribute.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">srcdir</td>
-    <td valign="top">The base directory containing the .class files that
-                     make up the bean. Included are the home- remote- pk-
-                     and implementation- classes and all classes, that these
-                     depend on. Note that this can be the same as the
-                     descriptordir if all files are in the same directory
-                     tree.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>srcdir</td>
+    <td>The base directory containing the .class files that make up the bean. Included are
+      the <samp>home-</samp>, <samp>remote-</samp>, <samp>pk-</samp>
+      and <samp>implementation-</samp> classes and all classes that these depend on. Note that this
+      can be the same as the <var>descriptordir</var> if all files are in the same directory
+      tree.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">The base directory into which generated jar files are
-                     deposited. Jar files are deposited in directories
-                     corresponding to their location within the descriptordir
-                     namespace. Note that this attribute is only used if the
-                     task is generating generic jars (i.e. no vendor-specific
-                     deployment elements have been specified).</td>
-    <td valign="top" align="center">Yes, unless vendor-specific deployment elements
-    have been specified.</td>
+    <td>destdir</td>
+    <td>The base directory into which generated jar files are deposited. Jar files are deposited in
+      directories corresponding to their location within the <var>descriptordir</var>
+      namespace. Note that this attribute is only used if the task is generating generic jars
+      (i.e. no vendor-specific deployment elements have been specified).</td>
+    <td>Yes, unless vendor-specific deployment elements have been specified.</td>
   </tr>
   <tr>
-    <td valign="top">cmpversion</td>
-    <td valign="top">Either <code>1.0</code> or <code>2.0</code>.<br>
-    Default is <code>1.0</code>.<br>
-    A CMP 2.0 implementation exists currently only for JBoss.</td>
-    <td valign="top" align="center">No</td>
+    <td>cmpversion</td>
+    <td>Either <q>1.0</q> or <q>2.0</q>.<br/>A CMP 2.0 implementation exists currently only for
+    JBoss.</td>
+    <td>No; default is <q>1.0</q></td>
   </tr>
   <tr>
-    <td valign="top">naming</td>
-    <td valign="top">Controls the naming convention used to name generated
-                     EJB jars. Please refer to the description above.</td>
-    <td valign="top" align="center">No</td>
+    <td>naming</td>
+    <td>Controls the naming convention used to name generated EJB jars. Please refer to the
+      description <a href="#naming">above</a>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">basejarname</td>
-    <td valign="top">The base name that is used for the generated jar files.
-                     If this attribute is specified, the generic jar file name
-                     will use this value as the prefix (followed by the value
-                     specified in the 'genericjarsuffix' attribute) and the
-                     resultant ejb jar file (followed by any suffix specified
-                     in the nested element).</td>
-    <td valign="top" align="center">No</td>
+    <td>basejarname</td>
+    <td>The base name that is used for the generated jar files.  If this attribute is specified, the
+      generic jar file name will use this value as the prefix (followed by the value specified in
+      the <var>genericjarsuffix</var> attribute) and the resultant EJB jar file (followed by any
+      suffix specified in the nested element).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">basenameterminator</td>
-    <td valign="top">String value used to substring out a string from the name
-                     of each deployment descriptor found, which is then used to
-                     locate related deployment descriptors (e.g. the WebLogic
-                     descriptors). For example, a basename of '.' and a
-                     deployment descriptor called 'FooBean.ejb-jar.xml' would
-                     result in a basename of 'FooBean' which would then be used
-                     to find FooBean.weblogic-ejb-jar.xml and
-                     FooBean.weblogic-cmp-rdbms-jar.xml, as well as to create
-                     the filenames of the jar files as FooBean-generic.jar and
-                     FooBean-wl.jar. This attribute is not used if the
-                     'basejarname' attribute is specified.</td>
-    <td valign="top" align="center">No, defaults to '-'.</td>
+    <td>basenameterminator</td>
+    <td>String value used to substring out a string from the name of each deployment descriptor
+      found, which is then used to locate related deployment descriptors (e.g. the WebLogic
+      descriptors). For example, a basename of <q>.</q> and a deployment descriptor
+      called <samp>FooBean.ejb-jar.xml</samp> would result in a basename of <q>FooBean</q> which
+      would then be used to find <samp>FooBean.weblogic-ejb-jar.xml</samp>
+      and <samp>FooBean.weblogic-cmp-rdbms-jar.xml</samp>, as well as to create the filenames of the
+      jar files as <samp>FooBean-generic.jar</samp> and <samp>FooBean-wl.jar</samp>. This attribute
+      is not used if the <var>basejarname</var> attribute is specified.</td>
+    <td>No; defaults to <q>-</q></td>
   </tr>
   <tr>
-    <td valign="top">genericjarsuffix</td>
-    <td valign="top">String value appended to the basename of the deployment
-                     descriptor to create the filename of the generic EJB jar
-                     file.</td>
-    <td valign="top" align="center">No, defaults to '-generic.jar'.</td>
+    <td>genericjarsuffix</td>
+    <td>String value appended to the basename of the deployment descriptor to create the filename of
+      the generic EJB jar file.</td>
+    <td>No; defaults to <q class="no-break">-generic.jar</q></td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">This classpath is used when resolving classes which
-                     are to be added to the jar. Typically nested deployment
-                     tool elements will also support a classpath which
-                     will be combined with this classpath when resolving
-                     classes</td>
-    <td valign="top" align="center">No.</td>
+    <td>classpath</td>
+    <td>This classpath is used when resolving classes which are to be added to the jar. Typically
+      nested deployment tool elements will also support a classpath which will be combined with this
+      classpath when resolving classes</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">flatdestdir</td>
-    <td valign="top">Set this attribute to true if you want all generated jars
-                     to be placed in the root of the destdir, rather than
-                     according to the location of the deployment descriptor
-                     within the descriptor dir hierarchy.</td>
-    <td valign="top" align="center">No.</td>
+    <td>flatdestdir</td>
+      <td>Set this attribute to <q>true</q> if you want all generated jars to be placed in the root
+        of the <var>destdir</var>, rather than according to the location of the deployment
+        descriptor within the <var>descriptordir</var> hierarchy.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dependency</td>
-    <td valign="top">This attribute controls which additional classes and interfaces
-                     are added to the jar. Please refer to the description
-                     <a href="#ejbjar_deps">above</a></td>
-    <td valign="top" align="center">No.</td>
+    <td>dependency</td>
+    <td>This attribute controls which additional classes and interfaces are added to the jar. Please
+      refer to the description <a href="#ejbjar_deps">above</a></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">manifest</td>
-    <td valign="top">the manifest file to use, if any.</td>
-    <td valign="top" align="center">No</td>
+    <td>manifest</td>
+    <td>the manifest file to use, if any.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3>Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
-<p>In addition to the vendor specific nested elements, the ejbjar task provides
-three nested elements. </p>
+<p>In addition to the vendor specific nested elements, the <code>ejbjar</code> task provides three
+nested elements.</p>
 
-<h4>Classpath</h4>
+<h4>classpath</h4>
 
-<p>The <code>&lt;classpath&gt;</code> nested element allows the classpath
-to be set. It is useful when setting the classpath from a reference path. In all
-other respects the behaviour is the same as the classpath attribute.</p>
+<p>The <code>&lt;classpath&gt;</code> nested element allows the classpath to be set. It is useful
+when setting the classpath from a reference path. In all other respects the behaviour is the same as
+the classpath attribute.</p>
 
-<a name="ejbjar-dtd"><h4>dtd</h4></a>
+<h4 id="ejbjar-dtd">dtd</h4>
 
-<p>The <code>&lt;dtd&gt;</code> element is used to specify the local location of DTDs to be
-used when parsing the EJB deployment descriptor. Using a local DTD is much
-faster than loading the DTD across the net. If you are running ejbjar behind a
-firewall you may not even be able to access the remote DTD. The supported
-vendor-specific nested elements know the location of the required DTDs within
-the vendor class hierarchy and, in general, this means <code>&lt;dtd&gt;</code> elements are
-not required. It does mean, however, that the vendor's class hierarchy must be
-available in the classpath when Ant is started. If your want to run Ant without
-requiring the vendor classes in the classpath, you would need to use a
-<code>&lt;dtd&gt;</code> element.</p>
+<p>The <code>&lt;dtd&gt;</code> element is used to specify the local location of DTDs to be used
+when parsing the EJB deployment descriptor. Using a local DTD is much faster than loading the DTD
+across the net. If you are running <code>ejbjar</code> behind a firewall you may not even be able to
+access the remote DTD. The supported vendor-specific nested elements know the location of the
+required DTDs within the vendor class hierarchy and, in general, this means <code>&lt;dtd&gt;</code>
+elements are not required. It does mean, however, that the vendor's class hierarchy must be
+available in the classpath when Ant is started. If your want to run Ant without requiring the vendor
+classes in the classpath, you would need to use a <code>&lt;dtd&gt;</code> element.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">publicId</td>
-    <td valign="top">The public Id of the DTD for which the location is being provided</td>
-    <td align="center" valign="top">Yes</td>
+    <td>publicId</td>
+    <td>The public Id of the DTD for which the location is being provided</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">location</td>
-    <td valign="top">The location of the local copy of the DTD. This can either be a
-                     file or a resource loadable from the classpath.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>location</td>
+    <td>The location of the local copy of the DTD. This can either be a file or a resource loadable
+      from the classpath.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>support</h4>
 
-<p>The <code>&lt;support&gt;</code> nested element is used to supply additional classes
-(files) to be included in the generated jars. The <code>&lt;support&gt;</code> element is a
-<a href="../Types/fileset.html">FileSet</a>, so it can either reference a fileset declared elsewhere or it can be
-defined in-place with the appropriate <code>&lt;include&gt;</code> and <code>&lt;exclude&gt;</code> nested
-elements. The files in the support fileset are added into the generated EJB jar
-in the same relative location as their location within the support fileset. Note
-that when ejbjar generates more than one jar file, the support files are added
-to each one.</p>
+<p>The <code>&lt;support&gt;</code> nested element is used to supply additional classes (files) to
+be included in the generated jars. The <code>&lt;support&gt;</code> element is
+a <a href="../Types/fileset.html">FileSet</a>, so it can either reference a fileset declared
+elsewhere or it can be defined in-place with the appropriate <code>&lt;include&gt;</code>
+and <code>&lt;exclude&gt;</code> nested elements. The files in the support fileset are added into
+the generated EJB jar in the same relative location as their location within the support
+fileset. Note that when <code>ejbjar</code> generates more than one jar file, the support files are
+added to each one.</p>
 
 <h3>Vendor-specific deployment elements</h3>
 
-Each vendor-specific nested element controls the generation of a deployable jar
-specific to that vendor's EJB container. The parameters for each supported
-deployment element are detailed here.
+<p>Each vendor-specific nested element controls the generation of a deployable jar specific to that
+vendor's EJB container. The parameters for each supported deployment element are detailed here.</p>
 
+<h3 id="ejbjar_jboss">Jboss element</h3>
 
-<h3><a name="ejbjar_jboss">Jboss element</a></h3>
-
-<p>The jboss element searches for the JBoss specific deployment descriptors and adds them
-to the final ejb jar file. JBoss has two deployment descriptors:
-<ul><li>jboss.xml</li>
-<li>for container manager persistence:<br>
-<table border="1">
-<tr><td><b>CMP version</b></td><td><b>File name</b></td></tr>
-<tr><td>CMP 1.0</td><td>jaws.xml</td></tr>
-<tr><td>CMP 2.0</td><td>jbosscmp-jdbc.xml</td></tr>
-</table>
-</li>
+<p>The <code>jboss</code> element searches for the JBoss specific deployment descriptors and adds
+them to the final EJB jar file. JBoss has two deployment descriptors:</p>
+<ul>
+  <li><samp>jboss.xml</samp></li>
+  <li>for container manager persistence:
+    <table>
+      <tr><th scope="col">CMP version</th><th scope="col">File name</th></tr>
+      <tr><td>CMP 1.0</td><td><samp>jaws.xml</samp></td></tr>
+      <tr><td>CMP 2.0</td><td><samp>jbosscmp-jdbc.xml</samp></td></tr>
+    </table>
+  </li>
 </ul>
-<br>
-. The JBoss server uses hot deployment and does
-not require compilation of additional stubs and skeletons.</p>
+<p>The JBoss server uses hot deployment and does not require compilation of additional stubs and
+skeletons.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">The base directory into which the generated weblogic ready
-                     jar files are deposited. Jar files are deposited in
-                     directories corresponding to their location within the
-                     descriptordir namespace. </td>
-    <td valign="top" align="center">Yes</td>
+    <td>destdir</td>
+    <td>The base directory into which the generated JBoss ready jar files are deposited. Jar files
+      are deposited in directories corresponding to their location within
+      the <var>descriptordir</var> namespace.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">genericjarsuffix</td>
-    <td valign="top">A generic jar is generated as an intermediate step in
-                     build the weblogic deployment jar. The suffix used to
-                     generate the generic jar file is not particularly
-                     important unless it is desired to keep the generic
-                     jar file. It should not, however, be the same
-                     as the suffix setting.</td>
-    <td valign="top" align="center">No, defaults to '-generic.jar'.</td>
+    <td>genericjarsuffix</td>
+    <td>A generic jar is generated as an intermediate step in build the JBoss deployment jar. The
+      suffix used to generate the generic jar file is not particularly important unless it is
+      desired to keep the generic jar file. It should not, however, be the same as the suffix
+      setting.</td>
+    <td>No; defaults to <q class="no-break">-generic.jar</q></td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">String value appended to the basename of the deployment
-                     descriptor to create the filename of the JBoss EJB
-                     jar file.</td>
-    <td valign="top" align="center">No, defaults to '.jar'.</td>
+    <td>suffix</td>
+    <td>String value appended to the basename of the deployment descriptor to create the filename of
+      the JBoss EJB jar file.</td>
+    <td>No; defaults to <q>.jar</q></td>
   </tr>
   <tr>
-    <td valign="top">keepgeneric</td>
-    <td valign="top">This controls whether the generic file used as input to
-                     ejbc is retained.</td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>keepgeneric</td>
+    <td>This controls whether the generic file used as input to <kbd>ejbc</kbd> is retained.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
+<h3 id="ejbjar_weblogic">WebLogic element</h3>
 
-<h3><a name="ejbjar_weblogic">Weblogic element</a></h3>
+<p>The <code>weblogic</code> element is used to control the <code>weblogic.ejbc</code> compiler for
+generating WebLogic EJB jars. Prior to Ant 1.3, the method of locating CMP descriptors was to use
+the <code>ejbjar</code> naming convention. So if your EJB jar was
+called, <samp>Customer-ejb-jar.xml</samp>, your WebLogic descriptor was
+called <samp>Customer-weblogic-ejb-jar.xml</samp> and your CMP descriptor had to
+be <samp>Customer-weblogic-cmp-rdbms-jar.xml</samp>. In addition,
+the <code>&lt;type-storage&gt;</code> element in the WebLogic descriptor had to be set to the
+standard name <samp>META-INF/weblogic-cmp-rdbms-jar.xml</samp>, as that is where the CMP descriptor
+was mapped to in the generated jar.</p>
 
-<p>The weblogic element is used to control the weblogic.ejbc compiler for
-generating weblogic EJB jars. Prior to Ant 1.3, the method of locating CMP
-descriptors was to use the ejbjar naming convention. So if your ejb-jar was
-called, Customer-ejb-jar.xml, your weblogic descriptor was called Customer-
-weblogic-ejb-jar.xml and your CMP descriptor had to be Customer-weblogic-cmp-
-rdbms-jar.xml. In addition, the <code>&lt;type-storage&gt;</code> element in the weblogic
-descriptor had to be set to the standard name META-INF/weblogic-cmp-rdbms-
-jar.xml, as that is where the CMP descriptor was mapped to in the generated
-jar.</p>
+<p>There are a few problems with this scheme. It does not allow for more than one CMP descriptor to
+be defined in a jar and it is not compatible with the deployment descriptors generated by some
+tools.</p>
 
-<p>There are a few problems with this scheme. It does not allow for more than
-one CMP descriptor to be defined in a jar and it is not compatible with the
-deployment descriptors generated by some tools.</p>
+<p>In Ant 1.3, <code>ejbjar</code> parses the WebLogic deployment descriptor to discover the CMP
+descriptors, which are then included automatically. This behaviour is controlled by
+the <var>newCMP</var> attribute. Note that if you move to the new method of determining CMP
+descriptors, you will need to update your WebLogic deployment
+descriptor's <code>&lt;type-storage&gt;</code> element. In the above example, you would define this
+as <samp>META-INF/Customer-weblogic-cmp-rdbms-jar.xml</samp>.</p>
 
-<p>In Ant 1.3, ejbjar parses the weblogic deployment descriptor to discover the
-CMP descriptors, which are then included automatically. This behaviour is
-controlled by the newCMP attribute. Note that if you move to the new method of
-determining CMP descriptors, you will need to update your weblogic deployment
-descriptor's <code>&lt;type-storage&gt;</code> element. In the above example, you would
-define this as META-INF/Customer-weblogic-cmp-rdbms-jar.xml.</p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">The base directory into which the generated weblogic ready
-                     jar files are deposited. Jar files are deposited in
-                     directories corresponding to their location within the
-                     descriptordir namespace. </td>
-    <td valign="top" align="center">Yes</td>
+    <td>destdir</td>
+    <td>The base directory into which the generated WebLogic ready jar files are deposited. Jar
+      files are deposited in directories corresponding to their location within
+      the <var>descriptordir</var> namespace.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">genericjarsuffix</td>
-    <td valign="top">A generic jar is generated as an intermediate step in
-                     build the weblogic deployment jar. The suffix used to
-                     generate the generic jar file is not particularly
-                     important unless it is desired to keep the generic
-                     jar file. It should not, however, be the same
-                     as the suffix setting.</td>
-    <td valign="top" align="center">No, defaults to '-generic.jar'.</td>
+    <td>genericjarsuffix</td>
+    <td>A generic jar is generated as an intermediate step in build the WebLogic deployment jar. The
+      suffix used to generate the generic jar file is not particularly important unless it is
+      desired to keep the generic jar file. It should not, however, be the same as the suffix
+      setting.</td>
+    <td>No; defaults to <q class="no-break">-generic.jar</q></td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">String value appended to the basename of the deployment
-                     descriptor to create the filename of the WebLogic EJB
-                     jar file.</td>
-    <td valign="top" align="center">No, defaults to '.jar'.</td>
+    <td>suffix</td>
+    <td>String value appended to the basename of the deployment descriptor to create the filename of
+      the WebLogic EJB jar file.</td>
+    <td>No; defaults to <q>.jar</q></td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to be used when running the weblogic ejbc
-                     tool. Note that this tool typically requires the classes
-                     that make up the bean to be available on the classpath.
-                     Currently, however, this will cause the ejbc tool to be
-                     run in a separate VM</td>
-    <td valign="top" align="center">No</td>
+    <td>classpath</td>
+      <td>The classpath to be used when running the WebLogic <kbd>ejbc</kbd> tool. Note that this
+        tool typically requires the classes that make up the bean to be available on the classpath.
+        Currently, however, this will cause the <kbd>ejbc</kbd> tool to be run in a separate
+        JVM</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">wlclasspath</td>
-    <td valign="top">Weblogic 6.0 will give a warning if the home and remote interfaces
-                     of a bean are on the system classpath used to run weblogic.ejbc.
-                     In that case, the standard weblogic classes should be set with
-                     this attribute (or equivalent nested element) and the
-                     home and remote interfaces located with the standard classpath
-                     attribute</td>
-    <td valign="top" align="center">No</td>
+    <td>wlclasspath</td>
+    <td>WebLogic 6.0 will give a warning if the home and remote interfaces of a bean are on the
+      system classpath used to run <code>weblogic.ejbc</code>.  In that case, the standard WebLogic
+      classes should be set with this attribute (or equivalent nested element) and the home and
+      remote interfaces located with the standard classpath attribute</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keepgeneric</td>
-    <td valign="top">This controls whether the generic file used as input to
-                     ejbc is retained.</td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>keepgeneric</td>
+    <td>This controls whether the generic file used as input to <kbd>ejbc</kbd> is retained.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td valign="top">This allows for the selection of a different compiler
-                     to be used for the compilation of the generated Java
-                     files. This could be set, for example, to Jikes to
-                     compile with the Jikes compiler. If this is not set
-                     and the <code>build.compiler</code> property is set
-                     to jikes, the Jikes compiler will be used. If this
-                     is not desired, the value &quot;<code>default</code>&quot;
-                     may be given to use the default compiler</td>
-    <td valign="top" align="center">No</td>
+    <td>compiler</td>
+    <td>This allows for the selection of a different compiler to be used for the compilation of the
+      generated Java files. This could be set, for example, to <q>jikes</q> to compile with the
+      Jikes compiler. If this is not set and the <code>build.compiler</code> property is set
+      to <q>jikes</q>, the Jikes compiler will be used. If this is not desired, the
+      value <q>default</q> may be given to use the default compiler</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">rebuild</td>
-    <td valign="top">This flag controls whether weblogic.ejbc is always
-                     invoked to build the jar file. In certain circumstances,
-                     such as when only a bean class has been changed, the jar
-                     can be generated by merely replacing the changed classes
-                     and not rerunning ejbc. Setting this to false will reduce
-                     the time to run ejbjar.
-                     </td>
-    <td valign="top" align="center">No, defaults to true.</td>
+    <td>rebuild</td>
+    <td>This flag controls whether <code>weblogic.ejbc</code> is always invoked to build the jar
+      file. In certain circumstances, such as when only a bean class has been changed, the jar can
+      be generated by merely replacing the changed classes and not
+      rerunning <kbd>ejbc</kbd>. Setting this to <q>false</q> will reduce the time to
+      run <code>ejbjar</code>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">keepgenerated</td>
-    <td valign="top">Controls whether weblogic will keep the generated Java
-                     files used to build the class files added to the
-                     jar. This can be useful when debugging
-                     </td>
-    <td valign="top" align="center">No, defaults to false.</td>
+    <td>keepgenerated</td>
+    <td>Controls whether WebLogic will keep the generated Java files used to build the class files
+      added to the jar. This can be useful when debugging</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">args</td>
-    <td valign="top">Any additional arguments to be passed to the weblogic.ejbc
-                     tool.
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>args</td>
+    <td>Any additional arguments to be passed to the <code>weblogic.ejbc</code> tool.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">weblogicdtd</td>
-    <td valign="top"><b>Deprecated</b>. Defines the location of the ejb-jar DTD in
-                     the weblogic class hierarchy. This should not be necessary if you
-                     have weblogic in your classpath. If you do not, you should use a
-                     nested <code>&lt;dtd&gt;</code> element, described above. If you do choose
-                     to use an attribute, you should use a
-                     nested <code>&lt;dtd&gt;</code> element.
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>weblogicdtd</td>
+    <td><em><u>Deprecated</u></em>. Defines the location of the ejb-jar DTD in the WebLogic class
+      hierarchy. This should not be necessary if you have WebLogic in your classpath. If you do not,
+      you should use a nested <code>&lt;dtd&gt;</code> element, described above. If you do choose to
+      use an attribute, you should use a nested <code>&lt;dtd&gt;</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">wldtd</td>
-    <td valign="top"><b>Deprecated</b>. Defines the location of the weblogic-ejb-jar
-                     DTD which covers the Weblogic specific deployment descriptors.
-                     This should not be necessary if you have weblogic in your
-                     classpath. If you do not, you should use a nested <code>&lt;dtd&gt;</code>
-                     element, described above.
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>wldtd</td>
+    <td><em><u>Deprecated</u></em>. Defines the location of the weblogic-ejb-jar DTD which covers
+      the WebLogic specific deployment descriptors.  This should not be necessary if you have
+      WebLogic in your classpath. If you do not, you should use a nested <code>&lt;dtd&gt;</code>
+      element, described above.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">ejbdtd</td>
-    <td valign="top"><b>Deprecated</b>. Defines the location of the ejb-jar DTD in
-                     the weblogic class hierarchy. This should not be necessary if you
-                     have weblogic in your classpath. If you do not, you should use a
-                     nested <code>&lt;dtd&gt;</code> element, described above.
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>ejbdtd</td>
+    <td><em><u>Deprecated</u></em>. Defines the location of the ejb-jar DTD in the WebLogic class
+      hierarchy. This should not be necessary if you have WebLogic in your classpath. If you do not,
+      you should use a nested <code>&lt;dtd&gt;</code> element, described above.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">newCMP</td>
-    <td valign="top">If this is set to true, the new method for locating
-                     CMP descriptors will be used.</td>
-    <td valign="top" align="center">No. Defaults to false</td>
+    <td>newCMP</td>
+    <td>If this is set to <q>true</q>, the new method for locating CMP descriptors will be
+      used.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">oldCMP</td>
-    <td valign="top"><b>Deprecated</b> This is an antonym for newCMP which should be used instead.</td>
-    <td valign="top" align="center">No.</td>
+    <td>oldCMP</td>
+    <td><em><u>Deprecated</u></em> This is an antonym for <var>newCMP</var> which should be used
+      instead.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">noEJBC</td>
-    <td valign="top">If this attribute is set to true, Weblogic's ejbc will not be run on the EJB jar.
-                     Use this if you prefer to run ejbc at deployment time.</td>
-    <td valign="top" align="center">No.</td>
+    <td>noEJBC</td>
+    <td>If this attribute is set to <q>true</q>, WebLogic's <kbd>ejbc</kbd> will not be run on the
+      EJB jar.  Use this if you prefer to run <kbd>ejbc</kbd> at deployment time.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">ejbcclass</td>
-    <td valign="top">Specifies the classname of the ejbc compiler. Normally ejbjar determines
-                     the appropriate class based on the DTD used for the EJB. The EJB 2.0 compiler
-                     featured in weblogic 6 has, however, been deprecated in version 7. When
-                     using with version 7 this attribute should be set to
-                     &quot;weblogic.ejbc&quot; to avoid the deprecation warning.</td>
-    <td valign="top" align="center">No.</td>
+    <td>ejbcclass</td>
+    <td>Specifies the classname of the <kbd>ejbc</kbd> compiler. Normally <code>ejbjar</code>
+      determines the appropriate class based on the DTD used for the EJB. The EJB 2.0 compiler
+      featured in WebLogic 6 has, however, been deprecated in version 7. When using with version 7
+      this attribute should be set to <q>weblogic.ejbc</q> to avoid the deprecation warning.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">jvmargs</td>
-    <td valign="top">Any additional arguments to be passed to the Virtual Machine
-                     running weblogic.ejbc tool. For example to set the memory size,
-                     this could be jvmargs=&quot;-Xmx128m&quot;
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>jvmargs</td>
+    <td>Any additional arguments to be passed to the JVM running <code>weblogic.ejbc</code>
+      tool. For example to set the memory size, this could
+      be <var>jvmargs</var>=<q>-Xmx128m</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">jvmdebuglevel</td>
-    <td valign="top">Sets the weblogic.StdoutSeverityLevel to use when running
-                     the Virtual Machine that executes ejbc. Set to 16 to avoid
-                     the warnings about EJB Home and Remotes being in the classpath
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>jvmdebuglevel</td>
+    <td>Sets the <code>weblogic.StdoutSeverityLevel</code> to use when running the JVM that
+      executes <kbd>ejbc</kbd>. Set to <q>16</q> to avoid the warnings about EJB Home and Remotes
+      being in the classpath</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">outputdir</td>
-    <td valign="top">If set ejbc will be given this directory as the output
-                     destination rather than a jar file. This allows for the
-                     generation of &quot;exploded&quot; jars.
-                     </td>
-    <td valign="top" align="center">No.</td>
+    <td>outputdir</td>
+    <td>If set <kbd>ejbc</kbd> will be given this directory as the output destination rather than a
+      jar file. This allows for the generation of &quot;exploded&quot; jars.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p>The weblogic nested element supports three nested elements. The
-first two, <code>&lt;classpath&gt;</code> and <code>&lt;wlclasspath&gt;</code>, are used to set the
-respective classpaths. These nested elements are useful when setting up
-class paths using reference Ids. The last, <code>&lt;sysproperty&gt;</code>, allows
-Java system properties to be set during the compiler run. This turns out
-to be necessary for supporting CMP EJB compilation in all environments.
-</p>
+<p>The <code>weblogic</code> nested element supports three nested elements. The first
+two, <code>&lt;classpath&gt;</code> and <code>&lt;wlclasspath&gt;</code>, are used to set the
+respective classpaths. These nested elements are useful when setting up classpaths using reference
+Ids. The last, <code>&lt;sysproperty&gt;</code>, allows Java system properties to be set during the
+compiler run. This turns out to be necessary for supporting CMP EJB compilation in all
+environments.</p>
 
-<h3>TOPLink for Weblogic element</h3>
+<h3>TOPLink for WebLogic element</h3>
 
-<p><b><i>Deprecated</i></b></p>
+<p><em><u>Deprecated</u></em></p>
 
-<p>The toplink element is no longer required. Toplink beans can now be built with the standard
-weblogic element, as long as the newCMP attribute is set to &quot;true&quot;
-</p>
+<p>The <code>toplink</code> element is no longer required. Toplink beans can now be built with the
+standard <code>weblogic</code> element, as long as the <var>newCMP</var> attribute is set
+to <q>true</q></p>
 
-<p>The TopLink element is used to handle beans which use Toplink for the CMP operations. It
-is derived from the standard weblogic element so it supports the same set of attributes plus these
-additional attributes</p>
+<p>The <code>TopLink</code> element is used to handle beans which use Toplink for the CMP
+operations. It is derived from the standard <code>weblogic</code> element so it supports the same
+set of attributes plus these additional attributes</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">toplinkdescriptor</td>
-    <td valign="top">This specifies the name of the TOPLink deployment descriptor file contained in the
-                     'descriptordir' directory.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>toplinkdescriptor</td>
+    <td>This specifies the name of the TOPLink deployment descriptor file contained in
+    the <var>descriptordir</var> directory.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">toplinkdtd</td>
-    <td valign="top">This specifies the location of the TOPLink DTD file. This can be a file path or
-                     a file URL. This attribute is not required, but using a local DTD is recommended.</td>
-    <td valign="top" align="center">No, defaults to dtd file at www.objectpeople.com.</td>
+    <td>toplinkdtd</td>
+    <td>This specifies the location of the TOPLink DTD file. This can be a file path or a file
+      URL. This attribute is not required, but using a local DTD is recommended.</td>
+    <td>No; defaults to DTD file at <samp>www.objectpeople.com</samp>.</td>
   </tr>
 </table>
 
-
 <h3>Examples</h3>
 
-<p>This example shows ejbjar being used to generate deployment jars using a
-Weblogic EJB container. This example requires the naming standard to be used for
-the deployment descriptors. Using this format will create a ejb jar file for
-each variation of '*-ejb-jar.xml' that is found in the deployment descriptor
-directory.</p>
+<p>This example shows <code>ejbjar</code> being used to generate deployment jars using a WebLogic
+EJB container. This example requires the naming standard to be used for the deployment
+descriptors. Using this format will create a EJB jar file for each variation
+of <samp>*-ejb-jar.xml</samp> that is found in the deployment descriptor directory.</p>
 
 <pre>
-    &lt;ejbjar srcdir=&quot;${build.classes}&quot;
-            descriptordir=&quot;${descriptor.dir}&quot;&gt;
-      &lt;weblogic destdir=&quot;${deploymentjars.dir}&quot;
-                classpath=&quot;${descriptorbuild.classpath}&quot;/&gt;
-      &lt;include name=&quot;**/*-ejb-jar.xml&quot;/&gt;
-      &lt;exclude name=&quot;**/*weblogic*.xml&quot;/&gt;
-    &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar srcdir=&quot;${build.classes}&quot;
+        descriptordir=&quot;${descriptor.dir}&quot;&gt;
+  &lt;weblogic destdir=&quot;${deploymentjars.dir}&quot;
+            classpath=&quot;${descriptorbuild.classpath}&quot;/&gt;
+  &lt;include name=&quot;**/*-ejb-jar.xml&quot;/&gt;
+  &lt;exclude name=&quot;**/*weblogic*.xml&quot;/&gt;
+&lt;/ejbjar&gt;</pre>
 
-<p>If weblogic is not in the Ant classpath, the following example
-shows how to specify the location of the weblogic DTDs. This
-example also show the use of a nested classpath element.</p>
+<p>If WebLogic is not in the Ant classpath, the following example shows how to specify the location
+of the WebLogic DTDs. This example also show the use of a nested <code>classpath</code> element.</p>
 
 <pre>
-    &lt;ejbjar descriptordir=&quot;${src.dir}&quot; srcdir=&quot;${build.classes}&quot;&gt;
-       &lt;weblogic destdir=&quot;${deployment.webshop.dir}&quot;
-                 keepgeneric=&quot;true&quot;
-                 args=&quot;-g -keepgenerated ${ejbc.compiler}&quot;
-                 suffix=&quot;.jar&quot;
-                 oldCMP=&quot;false&quot;&gt;
-         &lt;classpath&gt;
-           &lt;pathelement path=&quot;${descriptorbuild.classpath}&quot;/&gt;
-         &lt;/classpath&gt;
-       &lt;/weblogic&gt;
-       &lt;include name=&quot;**/*-ejb-jar.xml&quot;/&gt;
-       &lt;exclude name=&quot;**/*-weblogic-ejb-jar.xml&quot;/&gt;
-       &lt;dtd publicId=&quot;-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN&quot;
-            location=&quot;${weblogic.home}/classes/weblogic/ejb/deployment/xml/ejb-jar.dtd&quot;/&gt;
-       &lt;dtd publicId=&quot;-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN&quot;
-            location=&quot;${weblogic.home}/classes/weblogic/ejb/deployment/xml/weblogic-ejb-jar.dtd&quot;/&gt;
-    &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar descriptordir=&quot;${src.dir}&quot; srcdir=&quot;${build.classes}&quot;&gt;
+   &lt;weblogic destdir=&quot;${deployment.webshop.dir}&quot;
+             keepgeneric=&quot;true&quot;
+             args=&quot;-g -keepgenerated ${ejbc.compiler}&quot;
+             suffix=&quot;.jar&quot;
+             oldCMP=&quot;false&quot;&gt;
+     &lt;classpath&gt;
+       &lt;pathelement path=&quot;${descriptorbuild.classpath}&quot;/&gt;
+     &lt;/classpath&gt;
+   &lt;/weblogic&gt;
+   &lt;include name=&quot;**/*-ejb-jar.xml&quot;/&gt;
+   &lt;exclude name=&quot;**/*-weblogic-ejb-jar.xml&quot;/&gt;
+   &lt;dtd publicId=&quot;-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN&quot;
+        location=&quot;${weblogic.home}/classes/weblogic/ejb/deployment/xml/ejb-jar.dtd&quot;/&gt;
+   &lt;dtd publicId=&quot;-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN&quot;
+        location=&quot;${weblogic.home}/classes/weblogic/ejb/deployment/xml/weblogic-ejb-jar.dtd&quot;/&gt;
+&lt;/ejbjar&gt;</pre>
 
-
-<p>This example shows ejbjar being used to generate a single deployment jar
-using a Weblogic EJB container. This example does not require the deployment
-descriptors to use the naming standard. This will create only one ejb jar file -
-'TheEJBJar.jar'.</p>
-
+<p>This example shows <code>ejbjar</code> being used to generate a single deployment jar using a
+WebLogic EJB container. This example does not require the deployment descriptors to use the naming
+standard. This will create only one EJB jar file&mdash;<samp>TheEJBJar.jar</samp>.</p>
 
 <pre>
-    &lt;ejbjar srcdir=&quot;${build.classes}&quot;
-            descriptordir=&quot;${descriptor.dir}&quot;
-            basejarname=&quot;TheEJBJar&quot;&gt;
-      &lt;weblogic destdir=&quot;${deploymentjars.dir}&quot;
-                classpath=&quot;${descriptorbuild.classpath}&quot;/&gt;
-      &lt;include name=&quot;**/ejb-jar.xml&quot;/&gt;
-      &lt;exclude name=&quot;**/weblogic*.xml&quot;/&gt;
-    &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar srcdir=&quot;${build.classes}&quot;
+        descriptordir=&quot;${descriptor.dir}&quot;
+        basejarname=&quot;TheEJBJar&quot;&gt;
+  &lt;weblogic destdir=&quot;${deploymentjars.dir}&quot;
+            classpath=&quot;${descriptorbuild.classpath}&quot;/&gt;
+  &lt;include name=&quot;**/ejb-jar.xml&quot;/&gt;
+  &lt;exclude name=&quot;**/weblogic*.xml&quot;/&gt;
+&lt;/ejbjar&gt;</pre>
 
-<p>This example shows ejbjar being used to generate deployment jars for a TOPLink-enabled entity bean using a
-Weblogic EJB container. This example does not require the deployment descriptors to use the naming standard.
-This will create only one TOPLink-enabled ejb jar file - 'Address.jar'.</p>
+<p>This example shows <code>ejbjar</code> being used to generate deployment jars for a
+TOPLink-enabled entity bean using a WebLogic EJB container. This example does not require the
+deployment descriptors to use the naming standard.  This will create only one TOPLink-enabled EJB
+jar file&mdash;<samp>Address.jar</samp>.</p>
 
 <pre>
-    &lt;ejbjar srcdir=&quot;${build.dir}&quot;
-            destdir=&quot;${solant.ejb.dir}&quot;
-            descriptordir=&quot;${descriptor.dir}&quot;
-            basejarname=&quot;Address&quot;&gt;
-            &lt;weblogictoplink destdir=&quot;${solant.ejb.dir}&quot;
-                    classpath=&quot;${java.class.path}&quot;
-                    keepgeneric=&quot;false&quot;
-                    toplinkdescriptor=&quot;Address.xml&quot;
-                    toplinkdtd=&quot;file:///dtdfiles/toplink-cmp_2_5_1.dtd&quot;
-                    suffix=&quot;.jar&quot;/&gt;
-            &lt;include name=&quot;**/ejb-jar.xml&quot;/&gt;
-            &lt;exclude name=&quot;**/weblogic-ejb-jar.xml&quot;/&gt;
-    &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar srcdir=&quot;${build.dir}&quot;
+        destdir=&quot;${solant.ejb.dir}&quot;
+        descriptordir=&quot;${descriptor.dir}&quot;
+        basejarname=&quot;Address&quot;&gt;
+        &lt;weblogictoplink destdir=&quot;${solant.ejb.dir}&quot;
+                classpath=&quot;${java.class.path}&quot;
+                keepgeneric=&quot;false&quot;
+                toplinkdescriptor=&quot;Address.xml&quot;
+                toplinkdtd=&quot;file:///dtdfiles/toplink-cmp_2_5_1.dtd&quot;
+                suffix=&quot;.jar&quot;/&gt;
+        &lt;include name=&quot;**/ejb-jar.xml&quot;/&gt;
+        &lt;exclude name=&quot;**/weblogic-ejb-jar.xml&quot;/&gt;
+&lt;/ejbjar&gt;</pre>
 
-<p>This final example shows how you would set-up ejbjar under Weblogic 6.0. It also shows the use of the
-<code>&lt;support&gt;</code> element to add support files</p>
+<p>This final example shows how you would set-up <code>ejbjar</code> under WebLogic 6.0. It also
+shows the use of the <code>&lt;support&gt;</code> element to add support files</p>
 
 <pre>
-    &lt;ejbjar descriptordir=&quot;${dd.dir}&quot; srcdir=&quot;${build.classes.server}&quot;&gt;
-       &lt;include name=&quot;**/*-ejb-jar.xml&quot;/&gt;
-       &lt;exclude name=&quot;**/*-weblogic-ejb-jar.xml&quot;/&gt;
-       &lt;support dir=&quot;${build.classes.server}&quot;&gt;
-            &lt;include name=&quot;**/*.class&quot;/&gt;
-       &lt;/support&gt;
-       &lt;weblogic destdir=&quot;${deployment.dir}&quot;
-                 keepgeneric=&quot;true&quot;
-                 suffix=&quot;.jar&quot;
-                 rebuild=&quot;false&quot;&gt;
-         &lt;classpath&gt;
-            &lt;pathelement path=&quot;${build.classes.server}&quot;/&gt;
-         &lt;/classpath&gt;
-         &lt;wlclasspath&gt;
-            &lt;pathelement path=&quot;${weblogic.classes}&quot;/&gt;
-         &lt;/wlclasspath&gt;
-       &lt;/weblogic&gt;
-    &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar descriptordir=&quot;${dd.dir}&quot; srcdir=&quot;${build.classes.server}&quot;&gt;
+   &lt;include name=&quot;**/*-ejb-jar.xml&quot;/&gt;
+   &lt;exclude name=&quot;**/*-weblogic-ejb-jar.xml&quot;/&gt;
+   &lt;support dir=&quot;${build.classes.server}&quot;&gt;
+        &lt;include name=&quot;**/*.class&quot;/&gt;
+   &lt;/support&gt;
+   &lt;weblogic destdir=&quot;${deployment.dir}&quot;
+             keepgeneric=&quot;true&quot;
+             suffix=&quot;.jar&quot;
+             rebuild=&quot;false&quot;&gt;
+     &lt;classpath&gt;
+        &lt;pathelement path=&quot;${build.classes.server}&quot;/&gt;
+     &lt;/classpath&gt;
+     &lt;wlclasspath&gt;
+        &lt;pathelement path=&quot;${weblogic.classes}&quot;/&gt;
+     &lt;/wlclasspath&gt;
+   &lt;/weblogic&gt;
+&lt;/ejbjar&gt;</pre>
 
+<h3 id="ejbjar_websphere">WebSphere element</h3>
 
-<h3><a name="ejbjar_websphere">WebSphere element</a></h3>
-
-<p>The websphere element searches for the websphere specific deployment descriptors and
-adds them to the final ejb jar file. Websphere has two specific descriptors for session
-beans:
+<p>The <code>websphere</code> element searches for the WebSphere specific deployment descriptors and
+adds them to the final EJB jar file. WebSphere has two specific descriptors for session beans:</p>
 <ul>
-   <li>ibm-ejb-jar-bnd.xmi</li>
-   <li>ibm-ejb-jar-ext.xmi</li>
+  <li><samp>ibm-ejb-jar-bnd.xmi</samp></li>
+  <li><samp>ibm-ejb-jar-ext.xmi</samp></li>
 </ul>
-and another two for container managed entity beans:
+<p>and another two for container managed entity beans:</p>
 <ul>
-   <li>Map.mapxmi</li>
-   <li>Schema.dbxmi</li>
+  <li><samp>Map.mapxmi</samp></li>
+  <li><samp>Schema.dbxmi</samp></li>
 </ul>
-In terms of WebSphere, the generation of container code and stubs is called <code>deployment</code>.
-This step can be performed by the websphere element as part of the jar generation process. If the
-switch <code>ejbdeploy</code> is on, the ejbdeploy tool from the websphere toolset is called for
-every ejb-jar. Unfortunately, this step only works, if you use the ibm jdk. Otherwise, the rmic
-(called by ejbdeploy) throws a ClassFormatError. Be sure to switch ejbdeploy off, if run ant with
-Oracle JDK or OpenJDK.
-</p>
+<p>In terms of WebSphere, the generation of container code and stubs is called <em>deployment</em>.
+This step can be performed by the <code>websphere</code> element as part of the jar generation
+process. If the switch <var>ejbdeploy</var> is on, the <kbd>ejbdeploy</kbd> tool from the
+WebSphere toolset is called for every EJB jar. Unfortunately, this step only works, if you use the
+IBM JDK. Otherwise, the <kbd>rmic</kbd> (called by <kbd>ejbdeploy</kbd>) throws
+a <code>ClassFormatError</code>. Be sure to switch <var>ejbdeploy</var> off, if Ant runs with Oracle
+JDK or OpenJDK.</p>
 
-<p>
-For the websphere element to work, you have to provide a complete classpath, that contains all
-classes, that are required to reflect the bean classes. For ejbdeploy to work, you must also provide
-the classpath of the ejbdeploy tool and set the <i>websphere.home</i> property (look at the examples below).
-</p>
+<p>For the <code>websphere</code> element to work, you have to provide a complete classpath, that
+contains all classes, that are required to reflect the bean classes. For <kbd>ejbdeploy</kbd> to
+work, you must also provide the classpath of the <kbd>ejbdeploy</kbd> tool and set
+the <code>websphere.home</code> property (look at the examples below).</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">The base directory into which the generated weblogic ready
-                     jar files are deposited. Jar files are deposited in
-                     directories corresponding to their location within the
-                     descriptordir namespace. </td>
-    <td valign="top" align="center">Yes</td>
+    <td>destdir</td>
+    <td>The base directory into which the generated WebSphere ready jar files are deposited. Jar
+      files are deposited in directories corresponding to their location within
+      the <var>descriptordir</var> namespace.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">ejbdeploy</td>
-    <td valign="top">Decides whether ejbdeploy is called. When you set this to true,
-                     be sure, to run ant with the ibm jdk.</td>
-    <td valign="top" align="center">No, defaults to true</td>
+    <td>ejbdeploy</td>
+      <td>Decides whether <kbd>ejbdeploy</kbd> is called. When you set this to <q>true</q>, be sure
+        to run Ant with the IBM JDK.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">String value appended to the basename of the deployment
-                     descriptor to create the filename of the WebLogic EJB
-                     jar file.</td>
-    <td valign="top" align="center">No, defaults to '.jar'.</td>
+    <td>suffix</td>
+    <td>String value appended to the basename of the deployment descriptor to create the filename of
+      the WebSphere EJB jar file.</td>
+    <td>No; defaults to <q>.jar</q></td>
   </tr>
   <tr>
-    <td valign="top">keepgeneric</td>
-    <td valign="top">This controls whether the generic file used as input to
-                     ejbdeploy is retained.</td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>keepgeneric</td>
+    <td>This controls whether the generic file used as input to <kbd>ejbdeploy</kbd> is
+      retained.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">rebuild</td>
-    <td valign="top">This controls whether ejbdeploy is called although no changes
-                     have occurred.</td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>rebuild</td>
+    <td>This controls whether <kbd>ejbdeploy</kbd> is called although no changes have occurred.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">tempdir</td>
-    <td valign="top">A directory, where ejbdeploy will write temporary files</td>
-    <td valign="top" align="center">No, defaults to '_ejbdeploy_temp'.</td>
+    <td>tempdir</td>
+    <td>A directory, where <kbd>ejbdeploy</kbd> will write temporary files</td>
+    <td>No; defaults to <q>_ejbdeploy_temp</q></td>
   </tr>
   <tr>
-    <td valign="top">dbName<br>dbSchema</td>
-    <td valign="top">These options are passed to ejbdeploy.</td>
-    <td valign="top" align="center">No</td>
+    <td>dbName<br/>dbSchema</td>
+    <td>These options are passed to <kbd>ejbdeploy</kbd>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dbVendor</td>
-    <td valign="top">This option is passed to ejbdeploy. 
-                   <p>
-                   Valid options can be obtained by running the following command:
-                   <code>
-                   &lt;WAS_HOME&gt;/bin/EJBDeploy.[sh/bat] -help
-                   </code>
-                   </p>
-                    This is also used to determine the name of the Map.mapxmi and
-                     Schema.dbxmi files, for example Account-DB2UDBWIN_V71-Map.mapxmi
-                     and Account-DB2UDBWIN_V71-Schema.dbxmi.
-                     </td>
-    <td valign="top" align="center">No</td>
+    <td>dbVendor</td>
+    <td>This option is passed to <kbd>ejbdeploy</kbd>.  Valid options can be obtained by running the
+      following command: <pre>&lt;WAS_HOME&gt;/bin/EJBDeploy.[sh/bat] -help</pre> This is also used
+      to determine the name of the <code>Map.mapxmi</code> and <code>Schema.dbxmi</code> files, for
+      example <samp>Account-DB2UDBWIN_V71-Map.mapxmi</samp>
+      and <samp>Account-DB2UDBWIN_V71-Schema.dbxmi</samp>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">codegen<br>quiet<br>novalidate<br>noinform<br>trace<br>
-                     use35MappingRules</td>
-    <td valign="top">These options are all passed to ejbdeploy. All options
-                     except 'quiet' default to false.</td>
-    <td valign="top" align="center">No</td>
+    <td>codegen<br/>quiet<br/>novalidate<br/>noinform<br/>trace<br/>use35MappingRules</td>
+    <td>These options are all passed to <kbd>ejbdeploy</kbd>.</td>
+    <td>No; default is <q>false</q> (except for <var>quiet</var>)</td>
   </tr>
   <tr>
-    <td valign="top">rmicOptions</td>
-    <td valign="top">This option is passed to ejbdeploy and will be passed
-                     on to rmic.</td>
-    <td valign="top" align="center">No</td>
+    <td>rmicOptions</td>
+      <td>This option is passed to <kbd>ejbdeploy</kbd> and will be passed on
+        to <kbd>rmic</kbd>.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p>This example shows ejbjar being used to generate deployment jars for all deployment descriptors
-in the descriptor dir:</p>
+<p>This example shows <code>ejbjar</code> being used to generate deployment jars for all deployment
+descriptors in the <var>descriptordir</var>:</p>
 
 <pre>
-    &lt;property name=&quot;websphere.home&quot; value=&quot;${was4.home}&quot;/&gt;
-    &lt;ejbjar srcdir="${build.class}" descriptordir="etc/ejb"&gt;
-      &lt;include name="*-ejb-jar.xml"/&gt;
-      &lt;websphere dbvendor="DB2UDBOS390_V6"
-                 ejbdeploy="true"
-                 oldCMP="false"
-                 tempdir="/tmp"
-                 destdir="${dist.server}"&gt;
-        &lt;wasclasspath&gt;
-          &lt;pathelement location="${was4.home}/deploytool/itp/plugins/org.eclipse.core.boot/boot.jar"/&gt;
-          &lt;pathelement location="${was4.home}/deploytool/itp/plugins/com.ibm.etools.ejbdeploy/runtime/batch.jar"/&gt;
-          &lt;pathelement location="${was4.home}/lib/xerces.jar"/&gt;
-          &lt;pathelement location="${was4.home}/lib/ivjejb35.jar"/&gt;
-          &lt;pathelement location="${was4.home}/lib/j2ee.jar"/&gt;
-          &lt;pathelement location="${was4.home}/lib/vaprt.jar"/&gt;
-        &lt;/wasclasspath&gt;
+&lt;property name=&quot;websphere.home&quot; value=&quot;${was4.home}&quot;/&gt;
+&lt;ejbjar srcdir="${build.class}" descriptordir="etc/ejb"&gt;
+  &lt;include name="*-ejb-jar.xml"/&gt;
+  &lt;websphere dbvendor="DB2UDBOS390_V6"
+             ejbdeploy="true"
+             oldCMP="false"
+             tempdir="/tmp"
+             destdir="${dist.server}"&gt;
+    &lt;wasclasspath&gt;
+      &lt;pathelement location="${was4.home}/deploytool/itp/plugins/org.eclipse.core.boot/boot.jar"/&gt;
+      &lt;pathelement location="${was4.home}/deploytool/itp/plugins/com.ibm.etools.ejbdeploy/runtime/batch.jar"/&gt;
+      &lt;pathelement location="${was4.home}/lib/xerces.jar"/&gt;
+      &lt;pathelement location="${was4.home}/lib/ivjejb35.jar"/&gt;
+      &lt;pathelement location="${was4.home}/lib/j2ee.jar"/&gt;
+      &lt;pathelement location="${was4.home}/lib/vaprt.jar"/&gt;
+    &lt;/wasclasspath&gt;
+    &lt;classpath&gt;
+      &lt;path refid="build.classpath"/&gt;
+    &lt;/classpath&gt;
+  &lt;/websphere&gt;
+  &lt;dtd publicId="-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
+       location="${lib}/dtd/ejb-jar_1_1.dtd"/&gt;
+&lt;/ejbjar&gt;</pre>
+
+<h3 id="ejbjar_iplanet">iPlanet Application Server (iAS) element</h3>
+
+<p>The <code>&lt;iplanet&gt;</code> nested element is used to build iAS-specific stubs and skeletons
+and construct a JAR file which may be deployed to the iPlanet Application Server 6.0.  The build
+process will always determine if the EJB stubs/skeletons and the EJB jar file are up to date, and it
+will do the minimum amount of work required.</p>
+<p>Like the <code>weblogic</code> element, a naming convention for the EJB descriptors is most
+commonly used to specify the name for the completed JAR file.  For example, if the EJB
+descriptor <samp>ejb/Account-ejb-jar.xml</samp> is found in the descriptor directory,
+the <code>iplanet</code> element will search for an iAS-specific EJB descriptor file
+named <samp>ejb/Account-ias-ejb-jar.xml</samp> (if it isn't found, the task will fail) and a JAR
+file named <samp>ejb/Account.jar</samp> will be written in the destination directory.  Note that
+when the EJB descriptors are added to the JAR file, they are automatically
+renamed <samp>META-INF/ejb-jar.xml</samp> and <samp>META-INF/ias-ejb-jar.xml</samp>.</p>
+<p>Of course, this naming behaviour can be modified by specifying attributes in
+the <code>ejbjar</code> task (for example, <var>basejarname</var>, <var>basenameterminator</var>,
+and <var>flatdestdir</var>) as well as the <code>iplanet</code> element (for
+example, <var>suffix</var>).  Refer to the appropriate documentation for more details.</p>
+
+<h3>Parameters</h3>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+
+  <tr>
+    <td>destdir</td>
+    <td>The base directory into which the generated JAR files will be written. Each JAR file is
+      written in directories which correspond to their location within the <var>descriptordir</var>
+      namespace.</td>
+    <td>Yes</td>
+  </tr>
+
+  <tr>
+    <td>classpath</td>
+    <td>The classpath used when generating EJB stubs and skeletons.  If
+      specified, <var>classpath</var> will be prepended to the classpath specified in the
+      parent <code>ejbjar</code> task. Note that nested <code>classpath</code> elements may also be
+      used.</td>
+    <td>No; defaults to the classpath specified in the <code>ejbjar</code> parent task</td>
+  </tr>
+
+  <tr>
+    <td>keepgenerated</td>
+    <td>Indicates whether or not the Java source files which are generated by <kbd>ejbc</kbd> will
+      be saved or automatically deleted. If <q>yes</q>, the source files will be retained.</td>
+    <td>No; defaults to <q>no</q></td>
+  </tr>
+
+  <tr>
+    <td>debug</td>
+    <td>Indicates whether or not the <kbd>ejbc</kbd> utility should log additional debugging
+      statements to the standard output. If <q>yes</q>, the additional debugging statements will be
+      generated.</td>
+    <td>No; defaults to <q>no</q></td>
+  </tr>
+
+  <tr>
+    <td>iashome</td>
+    <td>May be used to specify the "home" directory for this iAS installation.  This is used to find
+      the <kbd>ejbc</kbd> utility if it isn't included in the user's system path.  If specified, it
+      should refer to the <samp>[install-location]/iplanet/ias6/ias</samp> directory.</td>
+    <td>No; by default, the <kbd>ejbc</kbd> utility must be on the user's system path.</td>
+  </tr>
+
+  <tr>
+    <td>suffix</td>
+    <td>String value appended to the JAR filename when creating each JAR.</td>
+    <td>No; defaults to <q>.jar</q></td>
+  </tr>
+</table>
+
+<p>As noted above, the <code>iplanet</code> element supports
+additional <code>&lt;classpath&gt;</code> nested elements.</p>
+<h3>Examples</h3>
+<p>This example demonstrates the typical use of the <code>&lt;iplanet&gt;</code> nested element.  It
+will name each EJB jar using the "basename" prepended to each standard EJB descriptor.  For example,
+if the descriptor named <samp>Account-ejb-jar.xml</samp> is processed, the EJB-JAR will be
+named <samp>Account.jar</samp></p>
+<pre>
+&lt;ejbjar srcdir="${build.classesdir}"
+        descriptordir="${src}"&gt;
+
+    &lt;iplanet destdir="${assemble.ejbjar}"
+             classpath="${ias.ejbc.cpath}"/&gt;
+    &lt;include name="**/*-ejb-jar.xml"/&gt;
+    &lt;exclude name="**/*ias-*.xml"/&gt;
+&lt;/ejbjar&gt;</pre>
+
+<p>This example demonstrates the use of a nested <code>classpath</code> element as well as some of
+the other optional attributes.</p>
+<pre>
+&lt;ejbjar srcdir="${build.classesdir}"
+        descriptordir="${src}"&gt;
+
+    &lt;iplanet destdir="${assemble.ejbjar}"
+             iashome="${ias.home}"
+             debug="yes"
+             keepgenerated="yes"&gt;
         &lt;classpath&gt;
-          &lt;path refid="build.classpath"/&gt;
+            &lt;pathelement path="."/&gt;
+            &lt;pathelement path="${build.classpath}"/&gt;
         &lt;/classpath&gt;
-      &lt;/websphere&gt;
-      &lt;dtd publicId="-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
-           location="${lib}/dtd/ejb-jar_1_1.dtd"/&gt;
-    &lt;/ejbjar&gt;
-</pre>
+    &lt;/iplanet&gt;
+    &lt;include name="**/*-ejb-jar.xml"/&gt;
+    &lt;exclude name="**/*ias-*.xml"/&gt;
+&lt;/ejbjar&gt;</pre>
 
-<h3><a name="ejbjar_iplanet">iPlanet Application Server (iAS) element</a></h3>
+<p>This example demonstrates the use of <var>basejarname</var> attribute.  In this case, the
+completed EJB jar will be named <samp>HelloWorld.jar</samp>.  If multiple EJB descriptors might be
+found, care must be taken to ensure that the completed JAR files don't overwrite each other.</p>
 
-The &lt;iplanet&lt; nested element is used to build iAS-specific stubs and
-
-skeletons and construct a JAR file which may be deployed to the iPlanet
-Application Server 6.0.  The build process will always determine if
-the EJB stubs/skeletons and the EJB-JAR file are up to date, and it will
-do the minimum amount of work required.
-<p>Like the WebLogic element, a naming convention for the EJB descriptors
-is most commonly used to specify the name for the completed JAR file.
-For example, if the EJB descriptor ejb/Account-ejb-jar.xml is found in
-the descriptor directory, the iplanet element will search for an iAS-specific
-EJB descriptor file named ejb/Account-ias-ejb-jar.xml (if it isn't found,
-the task will fail) and a JAR file named ejb/Account.jar will be written
-in the destination directory.  Note that when the EJB descriptors
-are added to the JAR file, they are automatically renamed META-INF/ejb-jar.xml
-and META-INF/ias-ejb-jar.xml.</p>
-<p>Of course, this naming behaviour can be modified by specifying attributes
-in the ejbjar task (for example, basejarname, basenameterminator, and flatdestdir)
-as well as the iplanet element (for example, suffix).  Refer to the
-appropriate documentation for more details.</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">destdir</td>
-
-<td valign="top">The base directory into which the generated JAR files will
-be written. Each JAR file is written in directories which correspond to
-their location within the "descriptordir" namespace.</td>
-
-<td align="center" valign="top">Yes</td>
-</tr>
-
-<tr>
-<td valign="top">classpath</td>
-
-<td valign="top">The classpath used when generating EJB stubs and skeletons.
-If omitted, the classpath specified in the "ejbjar" parent task will be
-used.  If specified, the classpath elements will be prepended to the
-classpath specified in the parent "ejbjar" task. Note that nested "classpath"
-elements may also be used.</td>
-
-<td align="center" valign="top">No</td>
-</tr>
-
-<tr>
-<td valign="top">keepgenerated</td>
-
-<td valign="top">Indicates whether or not the Java source files which are
-generated by ejbc will be saved or automatically deleted. If "yes", the
-source files will be retained.  If omitted, it defaults to "no". </td>
-
-<td align="center" valign="top">No</td>
-</tr>
-
-<tr>
-<td valign="top">debug</td>
-
-<td>Indicates whether or not the ejbc utility should log additional debugging
-statements to the standard output. If "yes", the additional debugging statements
-will be generated.  If omitted, it defaults to "no". </td>
-
-<td align="center" valign="top">No</td>
-</tr>
-
-<tr>
-<td valign="top">iashome</td>
-
-<td>May be used to specify the "home" directory for this iAS installation.
-This is used to find the ejbc utility if it isn't included in the user's
-system path.  If specified, it should refer to the [install-location]/iplanet/ias6/ias
-directory.  If omitted, the ejbc utility must be on the user's system
-path. </td>
-
-<td align="center" valign="top">No</td>
-</tr>
-
-<tr>
-<td valign="top">suffix</td>
-
-<td>String value appended to the JAR filename when creating each JAR.
-If omitted, it defaults to ".jar". </td>
-
-<td align="center" valign="top">No</td>
-</tr>
-</table>
-
-<p>As noted above, the iplanet element supports additional <code>&lt;classpath&gt;</code>
-nested elements.</p>
-<h3>
-Examples</h3>
-This example demonstrates the typical use of the <code>&lt;iplanet&gt;</code> nested element.
-It will name each EJB-JAR using the "basename" prepended to each standard
-EJB descriptor.  For example, if the descriptor named "Account-ejb-jar.xml"
-is processed, the EJB-JAR will be named "Account.jar"
 <pre>
-    &lt;ejbjar srcdir="${build.classesdir}"
-            descriptordir="${src}"&gt;
+&lt;ejbjar srcdir="${build.classesdir}"
+        descriptordir="${src}"
+        basejarname="HelloWorld"&gt;
 
-            &lt;iplanet destdir="${assemble.ejbjar}"
-                     classpath="${ias.ejbc.cpath}"/&gt;
-            &lt;include name="**/*-ejb-jar.xml"/&gt;
-            &lt;exclude name="**/*ias-*.xml"/&gt;
-    &lt;/ejbjar&gt;</pre>
+    &lt;iplanet destdir="${assemble.ejbjar}"
+             classpath="${ias.ejbc.cpath}"/&gt;
+    &lt;include name="**/*-ejb-jar.xml"/&gt;
+    &lt;exclude name="**/*ias-*.xml"/&gt;
+&lt;/ejbjar&gt;</pre>
 
-This example demonstrates the use of a nested classpath element as well
-as some of the other optional attributes.
+<p>This example demonstrates the use of the <code>dtd</code> nested element. If the local copies of
+the DTDs are included in the classpath, they will be automatically referenced without the nested
+elements.  In iAS 6.0 SP2, these local DTDs are found in
+the <samp>[iAS-install-directory]/APPS</samp> directory.  In iAS 6.0 SP3, these local DTDs are found
+in the <samp>[iAS-install-directory]/dtd</samp> directory.</p>
+
 <pre>
-    &lt;ejbjar srcdir="${build.classesdir}"
-            descriptordir="${src}"&gt;
+&lt;ejbjar srcdir="${build.classesdir}"
+        descriptordir="${src}"&gt;
+    &lt;iplanet destdir="${assemble.ejbjar}"&gt;
+             classpath="${ias.ejbc.cpath}"/&gt;
+    &lt;include name="**/*-ejb-jar.xml"/&gt;
+    &lt;exclude name="**/*ias-*.xml"/&gt;
 
-            &lt;iplanet destdir="${assemble.ejbjar}"
-                     iashome="${ias.home}"
-                     debug="yes"
-                     keepgenerated="yes"&gt;
-                     &lt;classpath&gt;
-                         &lt;pathelement path="."/&gt;
-                         &lt;pathelement path="${build.classpath}"/&gt;
-                     &lt;/classpath&gt;
-            &lt;/iplanet&gt;
-            &lt;include name="**/*-ejb-jar.xml"/&gt;
-            &lt;exclude name="**/*ias-*.xml"/&gt;
-    &lt;/ejbjar&gt;</pre>
+    &lt;dtd publicId="-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
+         location="${ias.home}/APPS/ejb-jar_1_1.dtd"/&gt;
+    &lt;dtd publicId="-//Sun Microsystems, Inc.//DTD iAS Enterprise JavaBeans 1.0//EN"
+         location="${ias.home}/APPS/IASEjb_jar_1_0.dtd"/&gt;
+&lt;/ejbjar&gt;</pre>
 
-This example demonstrates the use of basejarname attribute.  In this
-case, the completed EJB-JAR will be named "HelloWorld.jar"  If multiple
-EJB descriptors might be found, care must be taken to ensure that the completed
-JAR files don't overwrite each other.
-<pre>
-    &lt;ejbjar srcdir="${build.classesdir}"
-            descriptordir="${src}"
-            basejarname="HelloWorld"&gt;
+<h3 id="ejbjar_jonas">JOnAS (Java Open Application Server) element</h3>
 
-            &lt;iplanet destdir="${assemble.ejbjar}"
-                     classpath="${ias.ejbc.cpath}"/&gt;
-            &lt;include name="**/*-ejb-jar.xml"/&gt;
-            &lt;exclude name="**/*ias-*.xml"/&gt;
-    &lt;/ejbjar&gt;</pre>
-This example demonstrates the use of the dtd nested element. If the local
-copies of the DTDs are included in the classpath, they will be automatically
-referenced without the nested elements.  In iAS 6.0 SP2, these local DTDs are
-found in the [iAS-install-directory]/APPS directory.  In iAS 6.0 SP3, these
-local DTDs are found in the [iAS-install-directory]/dtd directory.
-<pre>
-    &lt;ejbjar srcdir="${build.classesdir}"
-            descriptordir="${src}"&gt;
-            &lt;iplanet destdir="${assemble.ejbjar}"&gt;
-                     classpath="${ias.ejbc.cpath}"/&gt;
-            &lt;include name="**/*-ejb-jar.xml"/&gt;
-            &lt;exclude name="**/*ias-*.xml"/&gt;
+<p>The <code>&lt;jonas&gt;</code> nested element is used to build JOnAS-specific stubs and skeletons
+thanks to the <code>GenIC</code> specific tool, and construct a JAR file which may be deployed to
+the JOnAS Application Server. The build process will always determine if the EJB stubs/skeletons and
+the EJB jar file are up to date, and it will do the minimum amount of work required.</p>
 
-            &lt;dtd publicId="-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
-                 location="${ias.home}/APPS/ejb-jar_1_1.dtd"/&gt;
-            &lt;dtd publicId="-//Sun Microsystems, Inc.//DTD iAS Enterprise JavaBeans 1.0//EN"
-                 location="${ias.home}/APPS/IASEjb_jar_1_0.dtd"/&gt;
-    &lt;/ejbjar&gt;</pre>
+<p>Like the WebLogic element, a naming convention for the EJB descriptors is most commonly used to
+specify the name for the completed JAR file. For example, if the EJB
+descriptor <samp>ejb/Account-ejb-jar.xml</samp> is found in the descriptor directory,
+the <code>&lt;jonas&gt;</code> element will search for a JOnAS-specific EJB descriptor file
+named <samp>ejb/Account-jonas-ejb-jar.xml</samp> and a JAR file named <samp>ejb/Account.jar</samp>
+will be written in the destination directory. But the <code>&lt;jonas&gt;</code> element can also
+use the JOnAS naming convention. With the same example as below, the EJB descriptor can also be
+named <samp>ejb/Account.xml</samp> (no base name terminator here) in the descriptor directory. Then
+the <code>&lt;jonas&gt;</code> element will search for a JOnAS-specific EJB descriptor file
+called <samp>ejb/jonas-Account.xml</samp>. This convention do not follow strictly the EJB jar naming
+convention recommendation but is supported for backward compatibility with previous version of
+JOnAS.</p>
 
-<h3><a name="ejbjar_jonas">JOnAS (Java Open Application Server) element</a></h3>
-
-<p>The <code>&lt;jonas&gt;</code> nested element is used to build JOnAS-specific stubs and
-skeletons thanks to the <code>GenIC</code> specific tool, and construct a JAR
-file which may be deployed to the JOnAS Application Server. The build process
-will always determine if the EJB stubs/skeletons and the EJB-JAR file are up to
-date, and it will do the minimum amount of work required.</p>
-
-<p>Like the WebLogic element, a naming convention for the EJB descriptors is
-most commonly used to specify the name for the completed JAR file. For example,
-if the EJB descriptor <code>ejb/Account-ejb-jar.xml</code> is found in the
-descriptor directory, the <code>&lt;jonas&gt;</code> element will search for a JOnAS-specific
-EJB descriptor file named <code>ejb/Account-jonas-ejb-jar.xml</code> and a JAR
-file named <code>ejb/Account.jar</code> will be written in the destination
-directory. But the <code>&lt;jonas&gt;</code> element can also use the JOnAS naming
-convention. With the same example as below, the EJB descriptor can also be named
-<code>ejb/Account.xml</code> (no base name terminator here) in the descriptor
-directory. Then the <code>&lt;jonas&gt;</code> element will search for a JOnAS-specific EJB
-descriptor file called <code>ejb/jonas-Account.xml</code>. This convention do
-not follow strictly the ejb-jar naming convention recommendation but is
-supported for backward compatibility with previous version of JOnAS.</p>
-
-<p>Note that when the EJB descriptors are added to the JAR file, they are
-automatically renamed <code>META-INF/ejb-jar.xml</code> and
-<code>META-INF/jonas-ejb-jar.xml</code>.</p>
+<p>Note that when the EJB descriptors are added to the JAR file, they are automatically
+renamed <samp>META-INF/ejb-jar.xml</samp> and <samp>META-INF/jonas-ejb-jar.xml</samp>.</p>
 
 <p>Of course, this naming behavior can be modified by specifying attributes in
-the ejbjar task (for example, basejarname, basenameterminator, and flatdestdir)
-as well as the iplanet element (for example, suffix). Refer to the appropriate
-documentation for more details.</p>
+the <code>ejbjar</code> task (for example, <var>basejarname</var>, <var>basenameterminator</var>,
+and <var>flatdestdir</var>) as well as the <code>iplanet</code> element (for
+example, <var>suffix</var>). Refer to the appropriate documentation for more details.</p>
 
 <p>This task creates a directory for scratch data inside of
   the <a href="../running.html#tmpdir">temporary directory</a>.</p>
 
-<h3> Parameters:</h3>
+<h3>Parameters</h3>
 
-<table border="1" cellspacing="0" cellpadding="2">
+<table class="attr">
   <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>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="Top">destdir</td>
-      <td valign="Top">The base directory into which the generated JAR files
-      will be written. Each JAR file is written in directories which correspond
-      to their location within the "<code>descriptordir</code>" namespace.</td>
-      <td align="Center" valign="Top">Yes</td>
+      <td>destdir</td>
+      <td>The base directory into which the generated JAR files will be written. Each JAR file is
+        written in directories which correspond to their location within
+        the <var>descriptordir</var> namespace.</td>
+      <td>Yes</td>
     </tr>
     <tr>
-      <td valign="Top">jonasroot</td>
-      <td valign="Top">The root directory for JOnAS.</td>
-      <td valign="Top" align="Center">Yes</td>
+      <td>jonasroot</td>
+      <td>The root directory for JOnAS.</td>
+      <td>Yes</td>
     </tr>
     <tr>
-      <td valign="Top">classpath</td>
-      <td valign="Top">The classpath used when generating EJB stubs and
-      skeletons. If omitted, the classpath specified in the "ejbjar" parent
-      task will be used. If specified, the classpath elements will be prepended
-      to the classpath specified in the parent "ejbjar" task (see also the ORB
-      attribute documentation below). Note that nested "classpath" elements may
-      also be used.</td>
-      <td valign="Top" align="Center">No</td>
+      <td>classpath</td>
+      <td>The classpath used when generating EJB stubs and skeletons. If
+        specified, <var>classpath</var> will be prepended to the classpath specified in the
+        parent <code>ejbjar</code> task (see also the ORB attribute documentation below). Note that
+        nested <code>classpath</code> elements may also be used.</td>
+      <td>No; defaults to the classpath specified in the <code>ejbjar</code> parent task</td>
     </tr>
     <tr>
-      <td valign="Top">keepgenerated</td>
-      <td valign="Top"><code>true</code> if the intermediate Java
-      source files generated by GenIC must be deleted or not. If
-      omitted, it defaults to <code>false</code>.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>keepgenerated</td>
+      <td><q>true</q> if the intermediate Java source files generated by GenIC must be deleted or
+      not.</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
     <tr>
-      <td valign="Top">nocompil</td>
-      <td valign="Top"><code>true</code> if the generated source files
-      must not be compiled via the java and rmi compilers. If omitted,
-      it defaults to <code>false</code>.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>nocompil</td>
+      <td><q>true</q> if the generated source files must not be compiled via the Java and RMI
+      compilers.</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
     <tr>
-      <td valign="Top">novalidation</td>
-      <td valign="Top"><code>true</code> if the XML deployment descriptors must
-      be parsed without validation. If omitted, it defaults to <code>false</code>.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>novalidation</td>
+      <td><q>true</q> if the XML deployment descriptors must be parsed without validation.</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
     <tr>
-      <td valign="Top">javac</td>
-      <td valign="Top">Java compiler to use. If omitted, it defaults
-      to the value of <code>build.compiler</code> property.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>javac</td>
+      <td>Java compiler to use.</td>
+      <td>No; defaults
+      to the value of <code>build.compiler</code> property</td>
     </tr>
     <tr>
-      <td valign="Top">javacopts</td>
-      <td valign="Top">Options to pass to the java compiler.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>javacopts</td>
+      <td>Options to pass to the Java compiler.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="Top">rmicopts</td>
-      <td valign="Top">Options to pass to the rmi compiler.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>rmicopts</td>
+      <td>Options to pass to the RMI compiler.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">secpropag</td>
-      <td valign="top"><code>true</code> if the RMI Skel. and
-      Stub. must be modified to implement the implicit propagation of
-      the security context (the transactional context is always
-      provided). If omitted, it defaults to <code>false</code>.</td>
-      <td valign="top" align="center">No</td>
+      <td>secpropag</td>
+      <td><q>true</q> if the RMI skeletons and stubs must be modified to implement the implicit
+        propagation of the security context (the transactional context is always provided).</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
     <tr>
-      <td valign="Top">verbose</td>
-      <td valign="Top">Indicates whether or not to use -verbose switch. If
-      omitted, it defaults to <code>false</code>.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>verbose</td>
+      <td>Indicates whether or not to use <kbd>-verbose</kbd> switch.</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
     <tr>
-      <td valign="Top">additionalargs</td>
-      <td valign="Top">Add additional args to GenIC.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>additionalargs</td>
+      <td>Add additional args to GenIC.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="Top">keepgeneric</td>
-      <td valign="Top"><code>true</code> if the generic JAR file used as input
-      to GenIC must be retained. If omitted, it defaults to <code>false</code>.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>keepgeneric</td>
+      <td><q>true</q> if the generic JAR file used as input to GenIC must be retained.</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
     <tr>
-      <td valign="Top">jarsuffix</td>
-      <td>String value appended to the JAR filename when creating each JAR.  If
-      omitted, it defaults to ".jar". </td>
-      <td align="Center" valign="Top">No</td>
+      <td>jarsuffix</td>
+      <td>String value appended to the JAR filename when creating each JAR.</td>
+      <td>No; defaults to <q>.jar</q></td>
     </tr>
     <tr>
-      <td valign="Top">orb</td>
-      <td>Choose your ORB : RMI, JEREMIE, DAVID. If omitted, it defaults to the
-      one present in classpath. If specified, the corresponding JOnAS JAR is
-      automatically added to the classpath.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>orb</td>
+      <td>Choose your ORB: <q>RMI</q>, <q>JEREMIE</q>, <q>DAVID</q>.  If specified, the
+        corresponding JOnAS JAR is automatically added to the classpath.</td>
+      <td>No; defaults to the one present in classpath</td>
     </tr>
     <tr>
-      <td valign="Top">nogenic</td>
-      <td valign="Top">If this attribute is set to <code>true</code>,
-      JOnAS's GenIC will not be run on the EJB JAR. Use this if you
-      prefer to run GenIC at deployment time. If omitted, it defaults
-      to <code>false</code>.</td>
-      <td align="Center" valign="Top">No</td>
+      <td>nogenic</td>
+      <td>If this attribute is set to <q>true</q>, JOnAS's GenIC will not be run on the EJB jar. Use
+      this if you prefer to run GenIC at deployment time.</td>
+      <td>No; defaults to <q>false</q></td>
     </tr>
-    <tr>
   </tbody>
 </table>
 
-<p>As noted above, the jonas element supports additional <code>&lt;classpath&gt;</code>
+<p>As noted above, the <code>jonas</code> element supports additional <code>&lt;classpath&gt;</code>
 nested elements.</p>
 
 <h3>Examples</h3>
 
-<p>This example shows ejbjar being used to generate deployment jars using a
-JOnAS EJB container. This example requires the naming standard to be used for
-the deployment descriptors. Using this format will create a EJB JAR file for
-each variation of &nbsp;'*-jar.xml' that is found in the deployment descriptor
-directory.&nbsp;</p>
+<p>This example shows <code>ejbjar</code> being used to generate deployment jars using a JOnAS EJB
+container. This example requires the naming standard to be used for the deployment
+descriptors. Using this format will create a EJB jar file for each variation
+of <samp>*-jar.xml</samp> that is found in the deployment descriptor directory.</p>
 
 <pre>
-      &lt;ejbjar srcdir="${build.classes}"
-              descriptordir="${descriptor.dir}"&gt;
-        &lt;jonas destdir="${deploymentjars.dir}"
-             jonasroot="${jonas.root}"
-             orb="RMI"/&gt;
-        &lt;include name="**/*.xml"/&gt;
-        &lt;exclude name="**/jonas-*.xml"/&gt;
-        &lt;support dir="${build.classes}"&gt;
-             &lt;include name="**/*.class"/&gt;
-        &lt;/support&gt;
-      &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar srcdir="${build.classes}"
+        descriptordir="${descriptor.dir}"&gt;
+  &lt;jonas destdir="${deploymentjars.dir}"
+       jonasroot="${jonas.root}"
+       orb="RMI"/&gt;
+  &lt;include name="**/*.xml"/&gt;
+  &lt;exclude name="**/jonas-*.xml"/&gt;
+  &lt;support dir="${build.classes}"&gt;
+       &lt;include name="**/*.class"/&gt;
+  &lt;/support&gt;
+&lt;/ejbjar&gt;</pre>
 
-<p>This example shows ejbjar being used to generate a single deployment jar
-using a JOnAS EJB container. This example does require the deployment
-descriptors to use the naming standard. This will create only one ejb jar file -
-'TheEJBJar.jar'.</p>
+<p>This example shows <code>ejbjar</code> being used to generate a single deployment jar using a
+JOnAS EJB container. This example does require the deployment descriptors to use the naming
+standard. This will create only one EJB jar file&mdash;<samp>TheEJBJar.jar</samp>.</p>
 
 <pre>
-      &lt;ejbjar srcdir="${build.classes}"
-              descriptordir="${descriptor.dir}"
-              basejarname="TheEJBJar"&gt;
-        &lt;jonas destdir="${deploymentjars.dir}"
-                  jonasroot="${jonas.root}"
-                  suffix=".jar"
-                  classpath="${descriptorbuild.classpath}"/&gt;
-        &lt;include name="**/ejb-jar.xml"/&gt;
-        &lt;exclude name="**/jonas-ejb-jar.xml"/&gt;
-      &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar srcdir="${build.classes}"
+        descriptordir="${descriptor.dir}"
+        basejarname="TheEJBJar"&gt;
+  &lt;jonas destdir="${deploymentjars.dir}"
+            jonasroot="${jonas.root}"
+            suffix=".jar"
+            classpath="${descriptorbuild.classpath}"/&gt;
+  &lt;include name="**/ejb-jar.xml"/&gt;
+  &lt;exclude name="**/jonas-ejb-jar.xml"/&gt;
+&lt;/ejbjar&gt;</pre>
 
+<h3 id="ejbjar_orion">Orion element</h3>
 
-<h3><a name="ejbjar_orion">Orion element</a></h3>
-
-<p>The orion element searches for the Orion Application Server specific deployment descriptors and adds them
-to the final ejb jar file. Orion has one deployment descriptor:
-<ul><li>orion-ejb-jar.xml</li>
+<p>The <code>orion</code> element searches for the Orion Application Server specific deployment
+descriptors and adds them to the final EJB jar file. Orion has one deployment descriptor:</p>
+<ul>
+  <li><samp>orion-ejb-jar.xml</samp></li>
 </ul>
-<br>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">The base directory into which the generated
-                     jar files are deposited. Jar files are deposited in
-                     directories corresponding to their location within the
-                     descriptordir namespace. </td>
-    <td valign="top" align="center">Yes</td>
+    <td>destdir</td>
+    <td>The base directory into which the generated jar files are deposited. Jar files are deposited
+      in directories corresponding to their location within the <var>descriptordir</var>
+      namespace.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Example</h3>
 
 <pre>
-      &lt;ejbjar srcdir="${build.classes}"
-              descriptordir="${descriptor.dir}"
-              basejarname="TheEJBJar"
-              flatdestdir="true"
-              dependency="super"
-              genericjarsuffix=".jar"&gt;
-        &lt;include name="**/*-ejb-jar.xml"/&gt;
-        &lt;orion destdir="${deploymentjars.dir}"\&gt;
-      &lt;/ejbjar&gt;
-</pre>
+&lt;ejbjar srcdir="${build.classes}"
+        descriptordir="${descriptor.dir}"
+        basejarname="TheEJBJar"
+        flatdestdir="true"
+        dependency="super"
+        genericjarsuffix=".jar"&gt;
+  &lt;include name="**/*-ejb-jar.xml"/&gt;
+  &lt;orion destdir="${deploymentjars.dir}"\&gt;
+&lt;/ejbjar&gt;</pre>
 
 </body>
-
 </html>
diff --git a/manual/Tasks/exec.html b/manual/Tasks/exec.html
index 88e0fed..05eb9a5 100644
--- a/manual/Tasks/exec.html
+++ b/manual/Tasks/exec.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,54 +15,44 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Exec Task</title>
 </head>
 
 <body>
 
-<h2><a name="exec">Exec</a></h2>
+<h2 id="exec">Exec</h2>
 <h3>Description</h3>
-<p>Executes a system command. When the <i>os</i> attribute is specified, then
-the command is only executed when Apache Ant is run on one of the specified operating
-systems.</p>
+<p>Executes a system command. When the <var>os</var> attribute is specified, then the command is
+only executed when Apache Ant is run on one of the specified operating systems.</p>
 
-<p>Note that you cannot interact with the forked program, the only way
-to send input to it is via the input and inputstring attributes. Also note that
-since Ant 1.6, any attempt to read input in the forked program will receive an
-EOF (-1). This is a change from Ant 1.5, where such an attempt would block.</p>
+<p>Note that you cannot interact with the forked program, the only way to send input to it is via
+the input and inputstring attributes. Also note that <em>since Ant 1.6</em>, any attempt to read
+input in the forked program will receive an EOF (<q>-1</q>). This is a change from Ant 1.5, where
+such an attempt would block.</p>
 
-<p>If you want to execute an executable using a path relative to the
-  project's basedir, you may need to
-  use <code>vmlauncher="false"</code> on some operating systems - but
-  even this may fail (Solaris 8/9 has been reported as problematic).
-  The <code>resolveexecutable</code> attribute should be more
-  reliable, as would be something like
+<p>If you want to execute an executable using a path relative to the project's <var>basedir</var>,
+you may need to use <var>vmlauncher</var>=<q>false</q> on some operating systems&mdash;but even this
+may fail (Solaris 8/9 has been reported as problematic).  The <var>resolveexecutable</var> attribute
+should be more reliable, as would be something like</p>
 <pre>
-  &lt;property name="executable-full-path"
-            location="../relative/path/to/executable"/&gt;
-  &lt;exec executable="${executable-full-path}" ...
-</pre>
-</p>
+&lt;property name="executable-full-path"
+          location="../relative/path/to/executable"/&gt;
+&lt;exec executable="${executable-full-path}" ...</pre>
 
 <h4>Windows Users</h4>
 <p>The <code>&lt;exec&gt;</code> task delegates to <code>Runtime.exec</code> which in turn
-apparently calls <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createprocess.asp">
-<code>::CreateProcess</code></a>. It is the latter Win32 function that defines
-the exact semantics of the call. In particular, if you do not put a file extension
-on the executable, only ".EXE" files are looked for, not ".COM", ".CMD" or other file
-types listed in the environment variable PATHEXT. That is only used by the shell.
-</p>
-  <p>
-    Note that <em>.bat</em> files cannot in general by executed directly.
-    One normally needs to execute the command shell executable <code>cmd</code>
-    using the <code>/c</code> switch.
-  </p>
-  <blockquote>
+apparently
+calls <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx"
+target="_top"><code>::CreateProcess</code></a>. It is the latter Win32 function that defines the
+exact semantics of the call. In particular, if you do not put a file extension on the executable,
+only <samp>.EXE</samp> files are looked for, not <samp>.COM</samp>, <samp>.CMD</samp> or other file
+types listed in the environment variable <code>PATHEXT</code>. That is only used by the shell.</p>
+<p>Note that <samp>.bat</samp> files cannot in general by executed directly.  One normally needs to
+execute the command shell executable <kbd>cmd</kbd> using the <kbd>/c</kbd> switch.</p>
 <pre>
 &lt;target name="help"&gt;
   &lt;exec executable="cmd"&gt;
@@ -69,367 +60,329 @@
     &lt;arg value="ant.bat"/&gt;
     &lt;arg value="-p"/&gt;
   &lt;/exec&gt;
-&lt;/target&gt;
-</pre></blockquote>
+&lt;/target&gt;</pre>
 
-<p>A common problem is not having the executable on the PATH. In case you get an error
-message <tt>Cannot run program "...":CreateProcess error=2. The system cannot find
-the path specified.</tt> have a look at your PATH variable. Just type the command directly on
-the command line and if Windows finds it, Ant should do it too. (Otherwise ask on the user mailinglist for help.) If Windows can not execute the program add the directory of the program
-to the PATH (<tt>set PATH=%PATH%;dirOfProgram</tt>) or specify the absolute path in the
-<tt>executable</tt> attribute in your buildfile.
-</p>
-
+<p>A common problem is not having the executable on the <code>PATH</code>. In case you get an error
+message <code class="output">Cannot run program "...":CreateProcess error=2. The system cannot find
+the path specified.</code> have a look at your <code>PATH</code> variable. Just type the command
+directly on the command line and if Windows finds it, Ant should do it too. (Otherwise ask on the
+user mailinglist for help.) If Windows can not execute the program, add the directory of the program
+to the <code>PATH</code> (<code>set PATH=%PATH%;dirOfProgram</code>) or specify the absolute path in
+the <var>executable</var> attribute in your buildfile.</p>
 
 <h4>Cygwin Users</h4>
-<p>The <code>&lt;exec&gt;</code> task will not understand paths such as /bin/sh
-for the executable parameter.  This is because the Java VM in which Ant is
-running is a standard Windows executable and is not aware of the Cygwin
-environment (i.e., doesn't load <code>cygwin1.dll</code>).  The only
-work-around for this is to compile a JVM under Cygwin (at your own risk).
-See for instance 
-<a href="http://hg.openjdk.java.net/jdk7/build/raw-file/tip/README-builds.html#cygwin">
-OpenJDK build instructions for cygwin</a>.
-</p>
+<p>The <code>&lt;exec&gt;</code> task will not understand paths such as <q>/bin/sh</q> for
+the <var>executable</var> parameter.  This is because JVM in which Ant is running is a standard
+Windows executable and is not aware of the Cygwin environment (i.e., doesn't
+load <samp>cygwin1.dll</samp>).  The only work-around for this is to compile a JVM under Cygwin (at
+your own risk).  See for
+instance <a href="https://cdn.rawgit.com/AdoptOpenJDK/openjdk-jdk9/dev/common/doc/building.html#cygwin"
+target="_top">OpenJDK build instructions for cygwin</a>.</p>
 
 <h4>OpenVMS Users</h4>
-<p>The command specified using <code>executable</code> and
-<code>&lt;arg&gt;</code> elements is executed exactly as specified
-inside a temporary DCL script.  This has some implications:
+<p>The command specified using <var>executable</var> and <code>&lt;arg&gt;</code> elements is
+executed exactly as specified inside a temporary DCL script.  This has some implications:</p>
 <ul>
   <li>the DCL script will be created inside
   the <a href="../running.html#tmpdir">temporary directory</a>.</li>
-<li>paths have to be written in VMS style</li>
-<li>if your <code>executable</code> points to a DCL script remember to
-prefix it with an <code>@</code>-sign
-(e.g. <code>executable="@[FOO]BAR.COM"</code>), just as you would in a
-DCL script</li>
+  <li>paths have to be written in VMS style</li>
+  <li>if your <var>executable</var> points to a DCL script remember to prefix it with
+    an <q>@</q>-sign (e.g. <var>executable</var>=<q>@[FOO]BAR.COM</q>), just as you would in a DCL
+    script</li>
 </ul>
-For <code>&lt;exec&gt;</code> to work in an environment with a Java VM
-older than version 1.4.1-2 it is also <i>required</i> that the logical
-<code>JAVA$FORK_SUPPORT_CHDIR</code> is set to <code>TRUE</code> in
-the job table (see the <i>JDK Release Notes</i>).</p>
 
-<p>Please note that the Java VM provided by HP doesn't follow OpenVMS'
-conventions of exit codes.  If you run a Java VM with this task, the
-task may falsely claim that an error occurred (or silently ignore an
-error).  Don't use this task to run <code>JAVA.EXE</code>, use a
-<code>&lt;java&gt;</code> task with the <code>fork</code> attribute
-set to <code>true</code> instead as this task will follow the VM's
+<p>Please note that JVM provided by HP doesn't follow OpenVMS' conventions of exit codes.  If you
+run a JVM with this task, the task may falsely claim that an error occurred (or silently ignore an
+error).  Don't use this task to run <kbd>JAVA.EXE</kbd>, use a <code>&lt;java&gt;</code> task with
+the <var>fork</var> attribute set to <q>true</q> instead as this task will follow the JVM's
 interpretation of exit codes.</p>
 
 <h4>RedHat S/390 Users</h4>
+<p>It has been <a href="https://www.mail-archive.com/linux-390@vm.marist.edu/msg22223.html"
+target="_top">reported on linux-390</a> that shell scripts invoked via the Ant Exec task must have
+their interpreter specified, i.e., the scripts must start with something like:</p>
 
-<p>It has been <a
-href="http://listserv.uark.edu/scripts/wa.exe?A1=ind0404&L=vmesa-l#33">reported
-on the VMESA-LISTSERV</a> that shell scripts invoked via the Ant Exec
-task must have their interpreter specified, i.e., the scripts must
-start with something like:
-
-<blockquote>
-<pre>
-#!/bin/bash
-</pre>
-</blockquote>
-
-or the task will fail as follows:
-
-<blockquote>
-<pre>
+<pre>#!/bin/bash</pre>
+<p>or the task will fail as follows:</p>
+<pre class="output">
 [exec] Warning: UNIXProcess.forkAndExec native error: Exec format error
-[exec] Result: 255
-</pre>
-</blockquote>
-</p>
+[exec] Result: 255</pre>
 
-<h4><a name="background">Running Ant as a background process on
-    Unix(-like) systems</a></h4>
+<h4 id="background">Running Ant as a background process on Unix(-like) systems</h4>
 
-<p>If you run Ant as a background process (like <code>ant &</code>)
-  and use the <code>&lt;exec&gt;</code> task with <code>spawn</code>
-  set to <code>false</code>, you must provide explicit input to the
-  forked process or Ant will be suspended because it tries to read
-  from the standard input.</p>
+<p>If you run Ant as a background process (like <kbd>ant &amp;</kbd>) and use
+the <code>&lt;exec&gt;</code> task with <var>spawn</var> set to <q>false</q>, you must provide
+explicit input to the forked process or Ant will be suspended because it tries to read from the
+standard input.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">command</td>
-    <td valign="top">the command to execute with all command line
-      arguments. <b>deprecated, use executable and nested
-      <code>&lt;arg&gt;</code> elements instead</b>.</td>
-    <td align="center" rowspan="2">Exactly one of the two.</td>
+    <td>command</td>
+    <td>the command to execute with all command line arguments. <em><u>Deprecated</u>,
+      use <var>executable</var> and nested <code>&lt;arg&gt;</code> elements instead</em>.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">the command to execute without any command line
-      arguments.</td>
+    <td>executable</td>
+    <td class="left">the command to execute without any command line arguments.</td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the directory in which the command should be executed.</td>
-    <td align="center" valign="top">No.<br/>
-      <strong>Note:</strong> the default used when dir has not been
-      specified depends on the <code>vmlauncher</code> attribute.  If
-      <code>vmlauncher</code> is <code>true</code> the task will use
-      the current working directory, otherwise it uses the project's basedir.
-    </td>
+    <td>dir</td>
+    <td>the directory in which the command should be executed.</td>
+    <td>No; if <var>vmlauncher</var> is <q>true</q>, defaults to the current working directory,
+      otherwise the project's <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">os</td>
-    <td valign="top">list of Operating Systems on which the command may be
-      executed. If the current OS's name is contained in this list, the command will
-      be executed. The OS's name is determined by the Java Virtual machine and is set
-      in the &quot;os.name&quot; system property.
+    <td>os</td>
+    <td>list of Operating Systems on which the command may be executed. If the current OS's name is
+      contained in this list, the command will be executed. The OS's name is determined by JVM and
+      is set in the <code>os.name</code> system property.
       </td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">osfamily</td>
-    <td valign="top">OS family as used in the &lt;os&gt; condition.
-    <em>since Ant 1.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>osfamily</td>
+    <td>OS family as used in the <code>&lt;os&gt;</code> condition.  <em>since Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">spawn</td>
-    <td valign="top">whether or not you want the command to be spawned<br>
-    Default is false.<br>
-    If you spawn a command, its output will not be logged by ant.<br>
-    The input, output, error, and result property settings are not active when spawning a process.<br>
-    <em>since Ant 1.6</em>
+    <td>spawn</td>
+    <td>whether or not you want the command to be spawned<br/>If you spawn a command, its output
+    will not be logged by Ant.<br/>The <var>input</var>, <var>output</var>, <var>error</var>,
+    and <var>result</var> property settings are not active when spawning a process.<br/><em>since
+    Ant 1.6</em>
     </td>
-    <td align="center" valign="top">No</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">Name of a file to which to write the output. If the error stream
-      is not also redirected to a file or property, it will appear in this output.</td>
-    <td align="center" valign="top">No</td>
+    <td>output</td>
+    <td>Name of a file to which to write the output. If the error stream is not also redirected to a
+      file or property, it will appear in this output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">error</td>
-    <td valign="top">The file to which the standard error of the
-    command should be redirected.  <em>since Ant 1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>error</td>
+    <td>The file to which the standard error of the command should be redirected.  <em>since Ant
+    1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">logError</td>
-    <td valign="top">This attribute is used when you wish to see error output in Ant's
-                     log and you are redirecting output to a file/property. The error
-                     output will not be included in the output file/property. If you
-                     redirect error with the &quot;error&quot; or &quot;errorProperty&quot;
-                     attributes, this will have no effect.  <em>since Ant 1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>logError</td>
+    <td>This attribute is used when you wish to see error output in Ant's log and you are
+      redirecting output to a file/property. The error output will not be included in the output
+      file/property. If you redirect error with the <var>error</var> or <var>errorProperty</var>
+      attributes, this will have no effect.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Whether output and error files should be appended to or overwritten.
-    Defaults to false.</td>
-    <td align="center" valign="top">No</td>
+    <td>append</td>
+    <td>Whether output and error files should be appended to or overwritten.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">outputproperty</td>
-    <td valign="top">The name of a property in which the output of the
-      command should be stored. Unless the error stream is redirected to a separate
-      file or stream, this property will include the error output.</td>
-    <td align="center" valign="top">No</td>
+    <td>outputproperty</td>
+    <td>The name of a property in which the output of the command should be stored. Unless the error
+      stream is redirected to a separate file or stream, this property will include the error
+      output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property in which the standard error of the
-      command should be stored.  <em>since Ant 1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property in which the standard error of the command should be
+      stored.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">input</td>
-    <td valign="top">A file from which the executed command's standard input
-                     is taken. This attribute is mutually exclusive with the
-                     inputstring attribute.  <em>since Ant 1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>input</td>
+    <td>A file from which the executed command's standard input is taken. This attribute is mutually
+      exclusive with the <var>inputstring</var> attribute.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputstring</td>
-    <td valign="top">A string which serves as the input stream for the
-                     executed command. This attribute is mutually exclusive with the
-                     input attribute.  <em>since Ant 1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>inputstring</td>
+    <td>A string which serves as the input stream for the executed command. This attribute is
+      mutually exclusive with the <var>input</var> attribute.  <em>since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">resultproperty</td>
-    <td valign="top">the name of a property in which the return code of the
-      command should be stored. Only of interest if failonerror=false.</td>
-    <td align="center" valign="top">No</td>
+    <td>resultproperty</td>
+    <td>the name of a property in which the return code of the command should be stored. Only of
+      interest if <var>failonerror</var>=<q>false</q>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Stop the command if it doesn't finish within the
-      specified time (given in milliseconds).</td>
-    <td align="center" valign="top">No</td>
+    <td>timeout</td>
+    <td>Stop the command if it doesn't finish within the specified time (given in
+      milliseconds).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the buildprocess if the command exits with a
-      return code signaling failure. Defaults to false.</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code signaling failure.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failifexecutionfails</td>
-    <td valign="top">Stop the build if we can't start the program.
-      Defaults to true. </td>
-    <td align="center" valign="top">No</td>
-  </tr>  <tr>
-    <td valign="top">newenvironment</td>
-    <td valign="top">Do not propagate old environment when new environment
-      variables are specified.</td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>failifexecutionfails</td>
+    <td>Stop the build if we can't start the program.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">vmlauncher</td>
-    <td valign="top">Run command using the Java VM's execution facilities
-        where available. If set to false the underlying OS's shell,
-        either directly or through the antRun scripts, will be used.
-        Under some operating systems, this gives access to facilities
-        not normally available through the VM including, under Windows,
-        being able to execute scripts, rather than their associated
-        interpreter.  If you want to specify the name of the
-        executable as a relative path to the directory given by the
-        dir attribute, it may become necessary to set vmlauncher to
-        false as well.</td>
-    <td align="center" valign="top">No, default is <i>true</i></td>
+    <td>newenvironment</td>
+    <td>Do not propagate old environment when new environment variables are specified.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">resolveexecutable</td>
-    <td valign="top">When this attribute is true, the name of the executable
-                     is resolved firstly against the project basedir and
-                     if that does not exist, against the execution
-                     directory if specified. On Unix systems, if you only
-                     want to allow execution of commands in the user's path,
-                     set this to false.  <em>since Ant 1.6</em></td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>vmlauncher</td>
+    <td>Run command using the JVM's execution facilities where available. If set to <q>false</q> the
+      underlying OS's shell, either directly or through the <kbd>antRun</kbd> scripts, will be
+      used.  Under some operating systems, this gives access to facilities not normally available
+      through JVM including, under Windows, being able to execute scripts, rather than their
+      associated interpreter.  If you want to specify the name of the executable as a relative path
+      to the directory given by the <var>dir</var> attribute, it may become necessary to
+      set <var>vmlauncher</var> to <q>false</q> as well.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">searchpath</td>
-    <td valign="top">When this attribute is true, then
-                     system path environment variables will
-                     be searched when resolving the location
-                     of the executable. <em>since Ant 1.6.3</em></td>
-    <td align="center" valign="top">No, default is <i>false</i></td>
+    <td>resolveexecutable</td>
+    <td>When this attribute is <q>true</q>, the name of the executable is resolved firstly against
+      the project <var>basedir</var> and if that does not exist, against the execution directory if
+      specified. On Unix systems, if you only want to allow execution of commands in the user's
+      path, set this to <q>false</q>.  <em>since Ant 1.6</em></td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>searchpath</td>
+    <td>When this attribute is <q>true</q>, then system path environment variables will be searched
+      when resolving the location of the executable. <em>since Ant 1.6.3</em></td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>discardOutput</td>
+    <td>Whether output should completely be discarded. This setting is
+      incompatible with any setting that redirects output to files or
+      properties.<br/>
+      If you set this to <q>true</q> error output will be discared as
+      well unless you redirect error output to files, properties or
+      enable <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>discardError</td>
+    <td>Whether error output should completely be discarded. This
+      setting is incompatible with any setting that redirects error
+      output to files or properties as well as <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
 <pre>
 &lt;exec dir=&quot;${src}&quot; executable=&quot;cmd.exe&quot; os=&quot;Windows 2000&quot; output=&quot;dir.txt&quot;&gt;
   &lt;arg line=&quot;/c dir&quot;/&gt;
 &lt;/exec&gt;</pre>
-</blockquote>
+
 <h3>Parameters specified as nested elements</h3>
 <h4>arg</h4>
-<p>Command line arguments should be specified as nested
-<code>&lt;arg&gt;</code> elements. See <a
-href="../using.html#arg">Command line arguments</a>.</p>
-<h4><a name="env">env</a></h4>
-<p>It is possible to specify environment variables to pass to the
-system command via nested <code>&lt;env&gt;</code> elements.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Command line arguments should be specified as nested <code>&lt;arg&gt;</code>
+elements. See <a href="../using.html#arg">Command line arguments</a>.</p>
+<h4 id="env">env</h4>
+<p>It is possible to specify environment variables to pass to the system command via
+nested <code>&lt;env&gt;</code> elements.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">key</td>
-    <td valign="top">
-      The name of the environment variable.
-      <br/>
-      <em>Note: (Since Ant 1.7)</em>
-      For windows, the name is case-insensitive.
-    </td>
-    <td align="center" valign="top">Yes</td>
+    <td>key</td>
+    <td>The name of the environment variable.<br/><strong>Note</strong>: <em>since Ant 1.7</em>, for
+      Windows, the name is case-insensitive.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The literal value for the environment variable.</td>
-    <td align="center" rowspan="3">Exactly one of these.</td>
+    <td>value</td>
+    <td>The literal value for the environment variable.</td>
+    <td rowspan="3">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
-    <td valign="top">The value for a PATH like environment
-      variable. You can use ; or : as path separators and Ant will
-      convert it to the platform's local conventions.</td>
+    <td>path</td>
+    <td class="left">The value for a <code>PATH</code>-like environment variable. You can
+      use <q>;</q> or <q>:</q> as path separators and Ant will convert it to the platform's local
+      conventions.</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The value for the environment variable. Will be
-      replaced by the absolute filename of the file by Ant.</td>
+    <td>file</td>
+    <td class="left">The value for the environment variable. Will be replaced by the absolute
+      filename of the file by Ant.</td>
   </tr>
 </table>
-<a name="redirector"><h4>redirector</h4></a>
-<i><b>Since Ant 1.6.2</b></i>
-<p>A nested <a href="../Types/redirector.html">I/O Redirector</a>
-can be specified.  In general, the attributes of the redirector behave
-as the corresponding attributes available at the task level.  The most
-notable peculiarity stems from the retention of the &lt;exec&gt;
-attributes for backwards compatibility.  Any file mapping is done
-using a <CODE>null</CODE> sourcefile; therefore not all
-<a href="../Types/mapper.html">Mapper</a> types will return
-results.  When no results are returned, redirection specifications
-will fall back to the task level attributes.  In practice this means that
-defaults can be specified for input, output, and error output files.
-</p>
+<h4 id="redirector">redirector</h4>
+<em>Since Ant 1.6.2</em>
+<p>A nested <a href="../Types/redirector.html">I/O Redirector</a> can be specified.  In general, the
+attributes of the redirector behave as the corresponding attributes available at the task level.
+The most notable peculiarity stems from the retention of the <code>&lt;exec&gt;</code> attributes
+for backwards compatibility.  Any file mapping is done using a <code>null</code> sourcefile;
+therefore not all<a href="../Types/mapper.html">Mapper</a> types will return results.  When no
+results are returned, redirection specifications will fall back to the task level attributes.  In
+practice this means that defaults can be specified for input, output, and error output files.</p>
 <h3>Errors and return codes</h3>
-By default the return code of a <code>&lt;exec&gt;</code> is ignored; when you set
-<code>failonerror="true"</code> then any return code signaling failure
-(OS specific) causes the build to fail. Alternatively, you can set
-<code>resultproperty</code> to the name of a property and have it assigned to
-the result code (barring immutability, of course).
-<p>
-If the attempt to start the program fails with an OS dependent error code,
-then <code>&lt;exec&gt;</code> halts the build unless <code>failifexecutionfails</code>
-is set to <code>false</code>. You can use that to run a program if it exists, but
-otherwise do nothing.
-<p>
-What do those error codes mean? Well, they are OS dependent. On Windows
-boxes you have to look at
-<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__0-499_.asp">
-the documentation</a>; error code 2 means 'no such program', which usually means
-it is not on the path. Any time you see such an error from any Ant task, it is
-usually not an Ant bug, but some configuration problem on your machine.
+<p>By default the return code of a <code>&lt;exec&gt;</code> is ignored; when you
+set <var>failonerror</var> to <q>true</q> then any return code signaling failure (OS specific)
+causes the build to fail. Alternatively, you can set <var>resultproperty</var> to the name of a
+property and have it assigned to the result code (barring immutability, of course).</p>
+<p>If the attempt to start the program fails with an OS dependent error code,
+then <code>&lt;exec&gt;</code> halts the build unless <var>failifexecutionfails</var> is set
+to <q>false</q>. You can use that to run a program if it exists, but otherwise do nothing.</p>
+<p>What do those error codes mean? Well, they are OS dependent. On Windows boxes you have to look
+at <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx"
+target="_top">the documentation</a>; <code>error=2</code> means 'no such program', which usually
+means it is not on the path. Any time you see such an error from any Ant task, it is usually not an
+Ant bug, but some configuration problem on your machine.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
+
+<p>Start <kbd>emacs</kbd> on display 1 of the X Window System.</p>
+<pre>
 &lt;exec executable=&quot;emacs&quot;&gt;
   &lt;env key=&quot;DISPLAY&quot; value=&quot;:1.0&quot;/&gt;
 &lt;/exec&gt;
-</pre></blockquote>
-<p>starts <code>emacs</code> on display 1 of the X Window System.</p>
+</pre>
 
-<blockquote><pre>
+<p>Add <samp>${basedir}/bin</samp> to the <code>PATH</code> of the system command.</p>
+<pre>
 &lt;property environment=&quot;env&quot;/&gt;
 &lt;exec ... &gt;
   &lt;env key=&quot;PATH&quot; path=&quot;${env.PATH}:${basedir}/bin&quot;/&gt;
 &lt;/exec&gt;
-</pre></blockquote>
-<p>adds <code>${basedir}/bin</code> to the <code>PATH</code> of the
-system command.</p>
+</pre>
 
-<blockquote><pre>
+<p>Start the <samp>${browser}</samp> with the specified <samp>${file}</samp> and end the Ant
+process. The browser will remain.</p>
+<pre>
 &lt;property name="browser" location="C:/Program Files/Internet Explorer/iexplore.exe"/&gt;
 &lt;property name="file" location="ant/docs/manual/index.html"/&gt;
 
 &lt;exec executable="${browser}" spawn="true"&gt;
     &lt;arg value="${file}"/&gt;
 &lt;/exec&gt;
-</pre></blockquote>
-<p>Starts the <i>${browser}</i> with the specified <i>${file}</i> and end the
-Ant process. The browser will remain.</p>
+</pre>
 
-<blockquote><pre>
+<p>Send the string <q>blah before blah</q> to the <kbd>cat</kbd> executable, using
+an <a href="../Types/filterchain.html">&lt;inputfilterchain&gt;</a> to replace <q>before</q>
+with <q>after</q> on the way in. Output is sent to the file <samp>redirector.out</samp> and stored
+in a property of the same name. Similarly, error output is sent to a file and a property, both
+named <samp>redirector.err</samp>.</p>
+<pre>
 &lt;exec executable=&quot;cat&quot;&gt;
     &lt;redirector outputproperty=&quot;redirector.out&quot;
                 errorproperty=&quot;redirector.err&quot;
@@ -441,27 +394,13 @@
         &lt;errormapper type=&quot;merge&quot; to=&quot;redirector.err&quot;/&gt;
     &lt;/redirector&gt;
 &lt;/exec&gt;
-</pre></blockquote>
+</pre>
 
-Sends the string &quot;blah before blah&quot; to the &quot;cat&quot; executable,
-using an <a href="../Types/filterchain.html">&lt;inputfilterchain&gt;</a>
-to replace &quot;before&quot; with &quot;after&quot; on the way in.
-Output is sent to the file &quot;redirector.out&quot; and stored
-in a property of the same name.  Similarly, error output is sent to
-a file and a property, both named &quot;redirector.err&quot;.
-
-
-<p><b>Note:</b> do not try to specify arguments using
-a simple arg-element and separate them by spaces. This results in
-only a single argument containing the entire string.</p>
-<p>
-<b>Timeouts: </b> If a timeout is specified, when it is reached the
-sub process is killed and a message printed to the log. The return
-value of the execution will be "-1", which will halt the build if
-<tt>failonerror=true</tt>, but be ignored otherwise.
-
-
-
+<p><strong>Note</strong>: do not try to specify arguments using a simple <code>arg</code>-element
+and separate them by spaces. This results in only a single argument containing the entire
+string.</p>
+<p><strong>Timeouts</strong>: If a timeout is specified, when it is reached the sub process is
+killed and a message printed to the log. The return value of the execution will be <q>-1</q>, which
+will halt the build if <var>failonerror</var>=<q>true</q>, but be ignored otherwise.</p>
 </body>
 </html>
-
diff --git a/manual/Tasks/fail.html b/manual/Tasks/fail.html
index eabe30b..edbf76a 100644
--- a/manual/Tasks/fail.html
+++ b/manual/Tasks/fail.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,116 +15,108 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Fail Task</title>
 </head>
 
 <body>
 
-<h2><a name="fail">Fail</a></h2>
+<h2 id="fail">Fail</h2>
 <h3>Description</h3>
-<p>Exits the current build (just throwing a BuildException), optionally printing additional information.</p>
-<p>The message of the Exception can be set via the message attribute
-or character data nested into the element.</p>
+<p>Exits the current build (just throwing a BuildException), optionally printing additional
+information.</p>
+<p>The message of the Exception can be set via the message attribute or character data nested into
+the element.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">message</td>
-    <td valign="top">A message giving further information on why the build exited</td>
-    <td align="center" valign="top">No</td>
+    <td>message</td>
+    <td>A message giving further information on why the build exited</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">Only fail <a href="../properties.html#if+unless">if a property of the given name exists</a>
+    <td>if</td>
+    <td>Only fail <a href="../properties.html#if+unless">if a property of the given name exists</a>
       in the current project</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">Only fail <a href="../properties.html#if+unless">if a property of the given name doesn't
+    <td>unless</td>
+    <td>Only fail <a href="../properties.html#if+unless">if a property of the given name doesn't
       exist</a> in the current project</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">status</td>
-    <td valign="top">Exit using the specified status code;
-      assuming the generated Exception is not caught, the
+    <td>status</td>
+    <td>Exit using the specified status code; assuming the generated Exception is not caught, the
       JVM will exit with this status. <em>Since Apache Ant 1.6.2</em></td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<p>As an alternative to the <i>if</i>/<i>unless</i> attributes,
-  conditional failure can be achieved using a single nested
-  <code>&lt;condition&gt;</code> element, which should contain exactly one
-  core or custom condition.  For information about conditions, see
-  <a href="conditions.html">here</a>.<br><b>Since Ant 1.6.2</b>
+<p>As an alternative to the <var>if</var>/<var>unless</var> attributes, conditional failure can be
+achieved using a single nested <code>&lt;condition&gt;</code> element, which should contain exactly
+one core or custom condition.  For information about conditions,
+see <a href="conditions.html">here</a>.<br/><em>Since Ant 1.6.2</em>
 </p>
 
 <h3>Examples</h3>
 
-<pre>  &lt;fail/&gt;</pre>
-<p>will exit the current build with no further information given.</p>
-<pre>
+<p>Exit the current build with no further information given.</p>
+<pre>&lt;fail/&gt;</pre>
+
+<pre class="output">
 BUILD FAILED
 
-build.xml:4: No message
-</pre>
+build.xml:4: No message</pre>
 
-<pre>  &lt;fail message=&quot;Something wrong here.&quot;/&gt;</pre>
-<p>will exit the current build and print something
-  like the following to wherever your output goes:
-</p>
-<pre>
+<p>Exit the current build and print a message to wherever your output goes:</p>
+<pre>&lt;fail message=&quot;Something wrong here.&quot;/&gt;</pre>
+
+<pre class="output">
 BUILD FAILED
 
-build.xml:4: Something wrong here.
-</pre>
+build.xml:4: Something wrong here.</pre>
 
-<pre>  &lt;fail&gt;Something wrong here.&lt;/fail&gt;</pre>
-<p>will give the same result as above.</p>
+<p>A different way to achieve the same result as above.</p>
+<pre>&lt;fail&gt;Something wrong here.&lt;/fail&gt;</pre>
 
-<pre>  &lt;fail unless=&quot;thisdoesnotexist&quot;/&gt;</pre>
-<p>will exit the current build and print something
-  like the following to wherever your output goes:
-</p>
-<pre>
+<p>Exit the current build and print an explanation to wherever your output goes:</p>
+<pre>&lt;fail unless=&quot;thisdoesnotexist&quot;/&gt;</pre>
+
+<pre class="output">
 BUILD FAILED
 
-build.xml:2: unless=thisdoesnotexist
-</pre>
+build.xml:2: unless=thisdoesnotexist</pre>
 
-Using a condition to achieve the same effect:
-
+<p>Use a condition to achieve the same effect:</p>
 <pre>
-  &lt;fail&gt;
-     &lt;condition&gt;
-       &lt;not&gt;
-         &lt;isset property=&quot;thisdoesnotexist&quot;/&gt;
-       &lt;/not&gt;
-     &lt;/condition&gt;
-   &lt;/fail&gt;
-</pre>
+&lt;fail&gt;
+    &lt;condition&gt;
+        &lt;not&gt;
+            &lt;isset property=&quot;thisdoesnotexist&quot;/&gt;
+        &lt;/not&gt;
+    &lt;/condition&gt;
+&lt;/fail&gt;</pre>
 
-<p>Output:</p>
-<pre>
+<pre class="output">
 BUILD FAILED
 
-build.xml:2: condition satisfied
-</pre>
+build.xml:2: condition satisfied</pre>
 
+<p>Check that both files <samp>one.txt</samp> and <samp>two.txt</samp> are present otherwise the
+build will fail.</p>
 <pre>
 &lt;fail message=&quot;Files are missing.&quot;&gt;
     &lt;condition&gt;
@@ -133,11 +126,7 @@
             &lt;/resourcecount&gt;
         &lt;/not&gt;
     &lt;/condition&gt;
-&lt;/fail&gt;
-</pre>
-<p>Will check that both files <i>one.txt</i> and <i>two.txt</i> are present otherwise the build
-will fail.</p>
+&lt;/fail&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/filter.html b/manual/Tasks/filter.html
index 16ba88c..a6d5a49 100644
--- a/manual/Tasks/filter.html
+++ b/manual/Tasks/filter.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,66 +15,61 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Filter Task</title>
 </head>
 
 <body>
 
-<h2><a name="filter">Filter</a></h2>
+<h2 id="filter">Filter</h2>
 <h3>Description</h3>
-<p>Sets a token filter for this project or read multiple token filter from
-an input file and sets these as filters.
-Token filters are used by all tasks that perform file copying operations
-through the Project commodity methods. See the warning
-<a href="../using.html#filters"><em>here</em></a> before using.</p>
-<p>Note 1: the token string must not contain the separators chars (@).<br>
-Note 2: Either token and value attributes must be provided, or only the
-filtersfile attribute.</p>
+<p>Sets a token filter for this project or reads a properties file as multiple token filter
+definitions and sets them.  Token filters are used by all tasks that perform file copying operations
+through the Project commodity methods. See the
+warning <a href="../using.html#filters"><em>here</em></a> before using.</p>
+<p>The task uses <q>@</q> as token separator. Token strings cannot contain separator characters;
+incorrect tokens are ignored.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">token</td>
-    <td valign="top">the token string without @</td>
-    <td align="center" valign="top">Yes*</td>
+    <td>token</td>
+    <td>the token string without the separator chars (<q>@</q>)</td>
+    <td rowspan="3">Yes; either both <var>token</var> and <var>value</var>, or
+      only <var>filtersfile</var></td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">the string that should be put to replace the token when the 
-      file is copied</td>
-    <td align="center" valign="top">Yes*</td>
+    <td>value</td>
+    <td class="left">the string that should be put to replace the token when the file is copied</td>
   </tr>
   <tr>
-    <td valign="top">filtersfile</td>
-    <td valign="top">The file from which the filters must be read. This file must be a formatted as a property file. </td>
-    <td align="center" valign="top">Yes*</td>
+    <td>filtersfile</td>
+    <td class="left">The file from which the filters must be read. This file must be a formatted as
+      a property file.</td>
   </tr>
 </table>
-<p>* see notes 1 and 2 above parameters table.</p>
 <h3>Examples</h3>
-<pre>  &lt;filter token=&quot;year&quot; value=&quot;2000&quot;/&gt;
-  &lt;copy todir=&quot;${dest.dir}&quot; filtering=&quot;true&quot;&gt;
-    &lt;fileset dir=&quot;${src.dir}&quot;/&gt;
-  &lt;/copy&gt;</pre> 
-<p>will copy recursively all the files from the <i>src.dir</i> directory into
-the <i>dest.dir</i> directory replacing all the occurrences of the string <i>@year@</i>
-with <i>2000.</i></p>
-<pre>  &lt;filter filtersfile=&quot;deploy_env.properties&quot;/&gt;</pre>
-will read all property entries from the <i>deploy_env.properties</i> file
-and set these as filters.
 
+<p>Copy recursively all the files from the <samp>src.dir</samp> directory into
+the <samp>dest.dir</samp> directory replacing all the occurrences of the string <code>@year@</code>
+with <q>2000</q>.</p>
+<pre>
+&lt;filter token=&quot;year&quot; value=&quot;2000&quot;/&gt;
+&lt;copy todir=&quot;${dest.dir}&quot; filtering=&quot;true&quot;&gt;
+  &lt;fileset dir=&quot;${src.dir}&quot;/&gt;
+&lt;/copy&gt;</pre>
 
+<p>Read all property entries from the <samp>deploy_env.properties</samp> file and set these as
+filters.</p>
+<pre>&lt;filter filtersfile=&quot;deploy_env.properties&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/fixcrlf.html b/manual/Tasks/fixcrlf.html
index a616ae7..30e3cec 100644
--- a/manual/Tasks/fixcrlf.html
+++ b/manual/Tasks/fixcrlf.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,45 +15,32 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>FixCRLF Task</title>
 </head>
 
 <body>
 
-<h2><a name="fixcrlf">FixCRLF</a></h2>
+<h2 id="fixcrlf">FixCRLF</h2>
 <h3>Description</h3>
-  <p>
-    Adjusts a text file to local conventions.
-  </p>
+  <p>Adjusts a text file to local conventions.</p>
 
-  <p>
-    The set of files to be adjusted can be refined with the
-    <i>includes</i>, <i>includesfile</i>, <i>excludes</i>,
-    <i>excludesfile</i> and <i>defaultexcludes</i>
-    attributes. Patterns provided through the <i>includes</i> or
-    <i>includesfile</i> attributes specify files to be
-    included. Patterns provided through the <i>exclude</i> or
-    <i>excludesfile</i> attribute specify files to be
-    excluded. Additionally, default exclusions can be specified with
-    the <i>defaultexcludes</i> attribute. See the section on <a
-    href="../dirtasks.html#directorybasedtasks">directory-based
-    tasks</a>, for details of file inclusion/exclusion patterns
-    and their usage.
-  </p>
+  <p>The set of files to be adjusted can be refined with
+    the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+    and <var>defaultexcludes</var> attributes. Patterns provided through the <var>includes</var>
+    or <var>includesfile</var> attributes specify files to be included. Patterns provided through
+    the <var>exclude</var> or <var>excludesfile</var> attribute specify files to be
+    excluded. Additionally, default exclusions can be specified with the <var>defaultexcludes</var>
+    attribute. See the section on <a href="../dirtasks.html#directorybasedtasks">directory-based
+    tasks</a>, for details of file inclusion/exclusion patterns and their usage.</p>
 
-  <p>
-    This task forms an implicit
-    <a href="../Types/fileset.html">FileSet</a> and
-    supports most attributes of <code>&lt;fileset&gt;</code>
-    (<code>dir</code> becomes <code>srcdir</code>) as well as the nested
-    <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-    <code>&lt;patternset&gt;</code> elements.
-  </p>
+  <p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+    attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>srcdir</var>) as well as
+    the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+    and <code>&lt;patternset&gt;</code> elements.</p>
 
   <p>
     The output file is only written if it is a new file, or if it
@@ -63,267 +51,204 @@
     the <a href="../running.html#tmpdir">temporary directory</a>.
   </p>
 
-  <p>
-    Since <b>Apache Ant 1.7</b>, this task can be used in a
-    <a href="../Types/filterchain.html">filterchain</a>.
-  </p>
+  <p><em>Since Apache Ant 1.7</em>, this task can be used in
+    a <a href="../Types/filterchain.html">filterchain</a>.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="center" rowspan="2"><b>Attribute</b></td>
-    <td valign="center" rowspan="2"><b>Description</b></td>
-    <td align="center" valign="top" colspan="2"><b>Required</b></td>
+    <th scope="col" rowspan="2">Attribute</th>
+    <th scope="col" rowspan="2">Description</th>
+    <th scope="col" colspan="2">Required</th>
   </tr>
   <tr>
-    <td valign="center"><b>As Task</b></td>
-    <td valign="center"><b>As Filter</b></td>
+    <th scope="col">As Task</th>
+    <th scope="col">As Filter</th>
   </tr>
   <tr>
-    <td valign="top">srcDir</td>
-    <td valign="top">Where to find the files to be fixed up.</td>
-    <td valign="top" align="center" rowspan="2">One of these</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>srcDir</td>
+    <td>Where to find the files to be fixed up.</td>
+    <td rowspan="2" class="center">One of these</td>
+    <td rowspan="11">N/A</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">Name of a single file to fix. <b>Since Ant 1.7</b></td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>file</td>
+    <td class="left">Name of a single file to fix. <em>Since Ant 1.7</em></td>
   </tr>
   <tr>
-    <td valign="top">destDir</td>
-    <td valign="top">Where to place the corrected files.  Defaults to
-      srcDir (replacing the original file).</td>
-    <td valign="top" align="center">No</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>destDir</td>
+    <td>Where to place the corrected files.</td>
+    <td class="center">No; defaults to <var>srcDir</var> (replace the original files)</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td class="center">No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern.</td>
-    <td valign="top" align="center">No</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern.</td>
+    <td class="center">No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td class="center">No; defaults to default excludes or none if <var>defaultexcludes</var>
+      is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern.</td>
-    <td valign="top" align="center">No</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern.</td>
+    <td class="center">No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.
-    </td>
-    <td valign="top" align="center">No</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td class="center">No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding of the files.</td>
-    <td align="center">No; defaults to default JVM encoding.</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>encoding</td>
+    <td>The encoding of the files.</td>
+    <td class="center">No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">outputencoding</td>
-    <td valign="top">The encoding to use when writing the files.
-                     <b>Since Ant 1.7</b></td>
-    <td align="center">No; defaults to the value of the encoding attribute.</td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>outputencoding</td>
+    <td>The encoding to use when writing the files.  <em>Since Ant 1.7</em></td>
+    <td class="center">No; defaults to <var>encoding</var> if set or default JVM character encoding
+      otherwise</td>
   </tr>
   <tr>
-    <td valign="top">preservelastmodified</td>
-    <td valign="top">Whether to preserve the last modified
-                     date of source files. <b>Since Ant 1.6.3</b></td>
-    <td align="center">No; default is <i>false</i></td>
-    <td bgcolor="#CCCCCC">&nbsp;</td>
+    <td>preservelastmodified</td>
+    <td>Whether to preserve the last modified date of source files. <em>Since Ant 1.6.3</em></td>
+    <td class="center">No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">eol</td>
-    <td valign="top">
-      Specifies how end-of-line (EOL) characters are to be
-      handled.  The EOL characters are CR, LF and the pair CRLF.
-      Valid values for this property are:
+    <td>eol</td>
+    <td>Specifies how end-of-line (EOL) characters are to be handled.  The EOL characters are CR, LF
+      and the pair CRLF.  Valid values for this property are:
       <ul>
-        <li>asis: leave EOL characters alone</li>
-        <li>cr: convert all EOLs to a single CR</li>
-        <li>lf: convert all EOLs to a single LF</li>
-        <li>crlf: convert all EOLs to the pair CRLF</li>
-        <li>mac: convert all EOLs to a single CR</li>
-        <li>unix: convert all EOLs to a single LF</li>
-        <li>dos: convert all EOLs to the pair CRLF</li>
+        <li><q>asis</q>: leave EOL characters alone</li>
+        <li><q>cr</q>: convert all EOLs to a single CR</li>
+        <li><q>lf</q>: convert all EOLs to a single LF</li>
+        <li><q>crlf</q>: convert all EOLs to the pair CRLF</li>
+        <li><q>mac</q>: convert all EOLs to a single CR</li>
+        <li><q>unix</q>: convert all EOLs to a single LF</li>
+        <li><q>dos</q>: convert all EOLs to the pair CRLF</li>
       </ul>
-      Default is based on the platform on which you are running this task.
-      For Unix platforms (including Mac OS X), the default is &quot;lf&quot;.
-      For DOS-based systems (including Windows), the default is
-      &quot;crlf&quot;.
-      For Mac environments other than OS X, the default is &quot;cr&quot;.
-      <p>
-        This is the preferred method for specifying EOL.  The
-        &quot;<i><b>cr</b></i>&quot; attribute (see below) is
-        now deprecated.
-      </p>
-      <p>
-        <i>N.B.</i>: One special case is recognized. The three
-        characters CR-CR-LF are regarded as a single EOL.
-        Unless this property is specified as &quot;asis&quot;,
-        this sequence will be converted into the specified EOL
-        type.
-      </p>
+      <p>This is the preferred method for specifying EOL.  The <var>cr</var> attribute (see below)
+      is now deprecated.</p>
+      <p><strong>Note</strong>: One special case is recognized. The three characters CR-CR-LF are
+        regarded as a single EOL.  Unless this property is specified as <q>asis</q>, this sequence
+        will be converted into the specified EOL type.</p>
     </td>
-    <td valign="top" align="center" colspan="2">No</td>
+    <td colspan="2">No; default is platform-specific: <q>lf</q> for Unix platforms (including Mac OS
+    X/macOS), <q>crlf</q> for DOS-based systems (including Windows), <q>cr</q> for Mac environments
+    other than OS X</td>
   </tr>
   <tr>
-    <td valign="top">cr</td>
-    <td valign="top">
-      <i><b>Deprecated.</b></i> Specifies how CR characters are
-      to be handled at end-of-line (EOL).  Valid values for this
-      property are:
+    <td>cr</td>
+    <td><em><u>Deprecated</u></em>. Specifies how CR characters are to be handled at end-of-line
+      (EOL).  Valid values for this property are:
       <ul>
-        <li>asis: leave EOL characters alone.</li>
-        <li>
-          add: add a CR before any single LF characters. The
-          intent is to convert all EOLs to the pair CRLF.
-        </li>
-        <li>
-          remove: remove all CRs from the file.  The intent is
-          to convert all EOLs to a single LF.
-        </li>
+        <li><q>asis</q>: leave EOL characters alone.</li>
+        <li><q>add</q>: add a CR before any single LF characters. The intent is to convert all EOLs
+          to the pair CRLF.</li>
+        <li><q>remove</q>: remove all CRs from the file.  The intent is to convert all EOLs to a
+          single LF.</li>
       </ul>
-      Default is based on the platform on which you are running
-      this task.  For Unix platforms, the default is &quot;remove&quot;.
-      For DOS based systems (including Windows), the default is
-      &quot;add&quot;.
-      <p>
-        <i>N.B.</i>: One special case is recognized. The three
-        characters CR-CR-LF are regarded as a single EOL.
-        Unless this property is specified as &quot;asis&quot;,
-        this sequence will be converted into the specified EOL
-        type.
-      </p>
+      <p><strong>Note</strong>: One special case is recognized. The three characters CR-CR-LF are
+        regarded as a single EOL.  Unless this property is specified as <q>asis</q>, this sequence
+        will be converted into the specified EOL type.</p>
     </td>
-    <td valign="top" align="center" colspan="2">No</td>
+    <td colspan="2">No; default is platform-specific: <q>remove</q> for Unix platforms, <q>add</q>
+      for DOS based systems (including Windows)</td>
   </tr>
   <tr>
-    <td valign="top">javafiles</td>
-    <td valign="top">
-      Used only in association with the
-      &quot;<i><b>tab</b></i>&quot; attribute (see below), this
-      boolean attribute indicates whether the fileset is a set
-      of java source files
-      (&quot;yes&quot;/&quot;no&quot;). Defaults to
-      &quot;no&quot;.  See notes in section on &quot;tab&quot;.
-    </td>
-    <td valign="top" align="center" colspan="2">No</td>
+    <td>javafiles</td>
+    <td>Used only in association with the <var>tab</var> attribute (see below), this boolean
+      attribute indicates whether the fileset is a set of Java source files (<q>yes|no</q>). See
+      notes in section on <var>tab</var>.</td>
+    <td colspan="2">No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">tab</td>
-    <td valign="top">Specifies how tab characters are to be handled.  Valid
-      values for this property are:
+    <td>tab</td>
+    <td>Specifies how tab characters are to be handled.  Valid values for this property are:
       <ul>
-      <li>add: convert sequences of spaces which span a tab stop to tabs</li>
-      <li>asis: leave tab and space characters alone</li>
-      <li>remove: convert tabs to spaces</li>
+        <li><q>add</q>: convert sequences of spaces which span a tab stop to tabs</li>
+        <li><q>asis</q>: leave tab and space characters alone</li>
+        <li><q>remove</q>: convert tabs to spaces</li>
       </ul>
-      Default for this parameter is &quot;asis&quot;.
-      <p>
-        <i>N.B.</i>: When the attribute
-        &quot;<i><b>javafiles</b></i>&quot; (see above) is
-        &quot;true&quot;, literal TAB characters occurring
-        within Java string or character constants are never
-        modified.  This functionality also requires the
-        recognition of Java-style comments.
-      </p>
-      <p>
-  	<i>N.B.</i>: There is an incompatibility between this
-  	and the previous version in the handling of white
-  	space at the end of lines.  This version does
-  	<i><b>not</b></i> remove trailing whitespace on lines.
-      </p>
+      <p><strong>Note</strong>: When the attribute <var>javafiles</var> (see above) is <q>true</q>,
+        literal TAB characters occurring within Java string or character constants are never
+        modified.  This functionality also requires the recognition of Java-style comments.</p>
+      <p><strong>Note</strong>: There is an incompatibility between this and the previous version in
+        the handling of white space at the end of lines.  This version
+        does <em><strong>not</strong></em> remove trailing whitespace on lines.</p>
     </td>
-    <td valign="top" align="center" colspan="2">No</td>
+    <td colspan="2">No; default is <q>asis</q></td>
   </tr>
   <tr>
-    <td valign="top">tablength</td>
-    <td valign="top">TAB character interval. Valid values are between
-      2 and 80 inclusive.  The default for this parameter is 8.</td>
-    <td valign="top" align="center" colspan="2">No</td>
+    <td>tablength</td>
+    <td>TAB character interval. Valid values are between <q>2</q> and <q>80</q> inclusive.</td>
+    <td colspan="2">No; default is <q>8</q></td>
   </tr>
   <tr>
-    <td valign="top">eof</td>
-    <td valign="top">Specifies how DOS end of file (control-Z) characters are
-      to be handled.  Valid values for this property are:
+    <td>eof</td>
+    <td>Specifies how DOS end of file (control-Z) characters are to be handled.  Valid values for
+      this property are:
       <ul>
-      <li>add: ensure that there is an EOF character at the end of the file</li>
-      <li>asis: leave EOF characters alone</li>
-      <li>remove: remove any EOF character found at the end</li>
+        <li><q>add</q>: ensure that there is an EOF character at the end of the file</li>
+        <li><q>asis</q>: leave EOF characters alone</li>
+        <li><q>remove</q>: remove any EOF character found at the end</li>
       </ul>
-      Default is based on the platform on which you are running this task.
-      For Unix platforms, the default is remove.  For DOS based systems
-      (including Windows), the default is asis.
-      </td>
-    <td valign="top" align="center" colspan="2">No</td>
+    </td>
+    <td colspan="2">No; default is platform-specific: <q>remove</q> for Unix platforms, <q>asis</q>
+      for DOS based systems (including Windows)</td>
   </tr>
   <tr>
-    <td valign="top">fixlast</td>
-    <td valign="top">Whether to add a missing EOL to the last line
-                     of a processed file.<br/>Ignored if EOL is asis.<br/><b>Since Ant 1.6.1</b></td>
-    <td align="center" colspan="2">No; default is <i>true</i></td>
+    <td>fixlast</td>
+    <td>Whether to add a missing EOL to the last line of a processed file.<br/>Ignored
+      if <var>eof</var> is <q>asis</q>.<br/><em>Since Ant 1.6.1</em></td>
+    <td colspan="2">No; default is <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>&lt;fixcrlf srcdir=&quot;${src}&quot; includes=&quot;**/*.sh&quot;
-         eol=&quot;lf&quot; eof=&quot;remove&quot; /&gt;</pre>
-<p>Replaces EOLs with LF characters and removes eof characters from
-  the shell scripts.  Tabs and spaces are left as is.</p>
-<pre>&lt;fixcrlf srcdir=&quot;${src}&quot;
-         includes=&quot;**/*.bat&quot; eol=&quot;crlf&quot; /&gt;</pre>
-<p>Replaces all EOLs with cr-lf pairs in the batch files.
-  Tabs and spaces are left as is.
-  EOF characters are left alone if run on
-  DOS systems, and are removed if run on Unix systems.</p>
-<pre>&lt;fixcrlf srcdir=&quot;${src}&quot;
-         includes=&quot;**/Makefile&quot; tab=&quot;add&quot; /&gt;</pre>
-<p>Sets EOLs according to local OS conventions, and
-  converts sequences of spaces and tabs to the minimal set of spaces and
-  tabs which will maintain spacing within the line.  Tabs are
-  set at 8 character intervals.  EOF characters are left alone if
-  run on DOS systems, and are removed if run on Unix systems.
-  Many versions of make require tabs prior to commands.</p>
-  <pre>&lt;fixcrlf srcdir=&quot;${src}&quot; includes=&quot;**/*.java&quot;
-         tab=&quot;remove&quot; tablength=&quot;3&quot;
-         eol=&quot;lf&quot; javafiles=&quot;yes&quot; /&gt;</pre>
-<p>
-  Converts all EOLs in the included java source files to a
-  single LF.  Replace all TAB characters except those in string
-  or character constants with spaces, assuming a tab width of 3.
-  If run on a unix system, any CTRL-Z EOF characters at the end
-  of the file are removed.  On DOS/Windows, any such EOF
-  characters will be left untouched.
-</p>
-<pre>&lt;fixcrlf srcdir=&quot;${src}&quot;
-         includes=&quot;**/README*&quot; tab=&quot;remove&quot; /&gt;</pre>
-<p>Sets EOLs according to local OS conventions, and
-  converts all tabs to spaces, assuming a tab width of 8.
-  EOF characters are left alone if run on
-  DOS systems, and are removed if run on Unix systems.
-  You never know what editor a user will use to browse READMEs.</p>
+<p>Replace EOLs with LF characters and remove EOF characters from the shell scripts. Tabs and spaces
+are left as is.</p>
+<pre>
+&lt;fixcrlf srcdir=&quot;${src}&quot; includes=&quot;**/*.sh&quot;
+         eol=&quot;lf&quot; eof=&quot;remove&quot;/&gt;</pre>
 
+<p>Replace all EOLs with cr-lf pairs in the batch files. Tabs and spaces are left as is. EOF
+characters are left alone if run on DOS systems, and are removed if run on Unix systems.</p>
+<pre>
+&lt;fixcrlf srcdir=&quot;${src}&quot;
+         includes=&quot;**/*.bat&quot; eol=&quot;crlf&quot;/&gt;</pre>
+
+<p>Set EOLs according to local OS conventions, and convert sequences of spaces and tabs into the
+minimal set of spaces and tabs which will preserve spacing within the line. Tabs are set at 8
+character intervals. EOF characters are left alone if run on DOS systems, and are removed if run on
+Unix systems. Many versions of make require tabs prior to commands.</p>
+<pre>
+&lt;fixcrlf srcdir=&quot;${src}&quot;
+         includes=&quot;**/Makefile&quot; tab=&quot;add&quot;/&gt;</pre>
+
+<p>Convert all EOLs in the included Java source files to a single LF. Replace all tab characters
+except those in string or character constants with spaces, assuming a tab width of 3. If run on a
+Unix system, any CTRL-Z EOF characters at the end of the file are removed. On DOS/Windows, any such
+EOF characters will be left untouched.
+</p>
+<pre>
+&lt;fixcrlf srcdir=&quot;${src}&quot; includes=&quot;**/*.java&quot;
+         tab=&quot;remove&quot; tablength=&quot;3&quot;
+         eol=&quot;lf&quot; javafiles=&quot;yes&quot;/&gt;</pre>
+
+<p>Set EOLs according to local OS conventions, and convert all tabs to spaces, assuming a tab width
+of 8. EOF characters are left alone if run on DOS systems, and are removed if run on Unix
+systems. You never know what editor a user will use to browse READMEs.</p>
+<pre>
+&lt;fixcrlf srcdir=&quot;${src}&quot;
+         includes=&quot;**/README*&quot; tab=&quot;remove&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/ftp.html b/manual/Tasks/ftp.html
index 6ad53af..29dff2c 100644
--- a/manual/Tasks/ftp.html
+++ b/manual/Tasks/ftp.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,716 +15,620 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>FTP Task</title>
 </head>
 
 <body>
 
-<h2><a name="ftp">FTP</a></h2>
+<h2 id="ftp">FTP</h2>
 <h3>Description</h3>
-<p>The ftp task implements a basic FTP client that can send, receive,
-list, delete files, and create directories.  See below for descriptions and examples of how
-to perform each task.</p>
-<p><b>Note:</b> This task depends on external libraries not included in the Apache Ant distribution.
-See <a href="../install.html#commons-net">Library Dependencies</a> for more information.
-<i>Get the latest version of this library, for the best support in Ant</i>
-
-</p>
-<p>The ftp task attempts to determine what file system is in place on the FTP server.
-Supported server types are Unix, NT, OS2, VMS, and OS400.  In addition, NT and OS400 servers
-which have been configured to display the directory in Unix style are also supported correctly.
-Otherwise, the system will default to Unix standards.
-<i>remotedir</i> must be specified in the exact syntax required by the ftp
-server. If the usual Unix conventions are not supported by the server,
-<i>separator</i> can be used to set the file separator that should be used
-instead.</p>
-<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based
-tasks</a>, on how the inclusion/exclusion of files works, and how to
-write patterns.</p>
-<p>
-This task does not currently use the proxy information set by the
-<a href="setproxy.html"><code>&lt;setproxy&gt;</code></a> task, and cannot go through
-a firewall via socks. 
-<p>
-<b>Warning: </b> there have been problems reported concerning the ftp get with the <code>newer</code> attribute.
-Problems might be due to format of ls -l differing from what is expected by commons-net,
-for instance due to specificities of language used by the ftp server in the directory listing.
-If you encounter such a problem, please send an email including a sample directory listing
-coming from your ftp server (ls -l on the ftp prompt).
-</p>
-<p>
-If you can connect but not upload or download, try setting the <code>passive</code>
-attribute to true to use the existing (open) channel, instead of having the server
-try to set up a new connection.</p>
+<p>The <code>ftp</code> task implements a basic FTP client that can send, receive, list, delete
+files, and create directories.  See below for descriptions and examples of how to perform each
+task.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution.  See <a href="../install.html#commons-net">Library Dependencies</a> for more
+information. <em>Get the latest version of this library, for the best support in Ant.</em></p>
+<p>The <code>ftp</code> task attempts to determine what file system is in place on the FTP server.
+Supported server types are Unix, NT, OS2, VMS, and OS400.  In addition, NT and OS400 servers which
+have been configured to display the directory in Unix style are also supported correctly.
+Otherwise, the system will default to Unix standards. <var>remotedir</var> must be specified in the
+exact syntax required by the FTP server. If the usual Unix conventions are not supported by the
+server, <var>separator</var> can be used to set the file separator that should be used instead.</p>
+<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on
+how the inclusion/exclusion of files works, and how to write patterns.</p>
+<p>This task does not currently use the proxy information set by
+the <a href="setproxy.html"><code>&lt;setproxy&gt;</code></a> task, and cannot go through a firewall
+via socks.</p>
+<p><strong>Warning</strong>: there have been problems reported concerning
+the <code>ftp</code> <q>get</q> with the <var>newer</var> attribute.  Problems might be due to
+format of <kbd>ls -l</kbd> differing from what is expected by commons-net, for instance due to
+specifics of language used by the FTP server in the directory listing.  If you encounter such a
+problem, please send an email including a sample directory listing coming from your FTP server
+(<kbd>ls -l</kbd> on the FTP prompt).</p>
+<p>If you can connect but not upload or download, try setting the <var>passive</var> attribute
+to <q>true</q> to use the existing (open) channel, instead of having the server try to set up a new
+connection.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top" width="15%"><b>Attribute</b></td>
-    <td valign="top" width="65%"><b>Description</b></td>
-    <td align="center" valign="top" width="20%"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">server</td>
-    <td valign="top">the address of the remote ftp server.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>server</td>
+    <td>the address of the remote FTP server.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">the port number of the remote ftp server.
-                     Defaults to port 21.</td>
-    <td valign="top" align="center">No</td>
+    <td>port</td>
+    <td>the port number of the remote FTP server.</td>
+    <td>No; defaults to <q>21</q></td>
   </tr>
   <tr>
-    <td valign="top">userid</td>
-    <td valign="top">the login id to use on the ftp server.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>userid</td>
+    <td>the login id to use on the FTP server.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">the login password to use on the ftp server.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>password</td>
+    <td>the login password to use on the FTP server.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">account</td>
-    <td valign="top">the account to use on the ftp server.
-        <em>since Ant 1.7</em>.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>account</td>
+    <td>the account to use on the FTP server.
+    <em>since Ant 1.7</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">remotedir</td>
-    <td valign="top">remote directory on the
-                     ftp server
-                     see table below for detailed usage
-                     </td>
-    <td valign="top" align="center">No</td>
+    <td>remotedir</td>
+    <td>remote directory on the FTP server see table below for detailed usage</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">action</td>
-    <td valign="top">the ftp action to perform, defaulting to "send".
-                     Currently supports "put", "get",
-                     "del", "list", "chmod",
-                     "mkdir", "rmdir", and "site".</td>
-    <td valign="top" align="center">No</td>
+    <td>action</td>
+    <td>FTP action to perform.  Currently
+    supports <q>put</q>, <q>get</q>, <q>del</q>, <q>list</q>, <q>chmod</q>, <q>mkdir</q>, <q>rmdir</q>,
+    and <q>site</q>.</td>
+    <td>No; defaults to <q>send</q></td>
   </tr>
   <tr>
-    <td valign="top">binary</td>
-    <td valign="top">selects binary-mode ("yes") or text-mode
-                     ("no") transfers.
-                     Defaults to "yes"</td>
-    <td valign="top" align="center">No</td>
+    <td>binary</td>
+    <td>selects binary-mode (<q>yes</q>) or text-mode (<q>no</q>) transfers.</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">passive</td>
-    <td valign="top">selects passive-mode ("yes") transfers, for
-                     better through-firewall connectivity, at the price
-                     of performance.
-                     Defaults to "no"</td>
-    <td valign="top" align="center">No</td>
+    <td>passive</td>
+    <td>selects passive-mode (<q>yes</q>) transfers, for better through-firewall connectivity, at
+      the price of performance.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">displays information on each file transferred if set 
-                     to "yes". Defaults to "no".</td>
-    <td valign="top" align="center">No</td>
+    <td>verbose</td>
+    <td>displays information on each file transferred if set to <q>yes</q>.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">depends</td>
-    <td valign="top">transfers only new or changed files if set to 
-                     "yes". Defaults to "no".</td>
-    <td valign="top" align="center">No</td>
+    <td>depends</td>
+    <td>transfers only new or changed files if set to <q>yes</q>.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">newer</td>
-    <td valign="top">a synonym for <i>depends</i>.
-    see timediffauto and timediffmillis</td>
-    <td valign="top" align="center">No</td>
+    <td>newer</td>
+    <td>a synonym for <var>depends</var>.  See <var>timediffauto</var>
+        and <var>timediffmillis</var></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">timediffauto</td>
-    <td valign="top">set to <code>"true"</code>
-    to make ant calculate the time difference between client and server.<br>
-    <em>requires write access in the remote directory</em><br>
-    Since ant 1.6<br/>
+    <td>timediffauto</td>
+    <td>set to <q>true</q> to make Ant calculate the time difference between client and
+    server.<br/><em>requires write access in the remote directory</em><br/><em>Since Ant
+    1.6</em><br/>
     If this is set to <code>true</code> then Ant will create an empty
     file inside of the <a href="../running.html#tmpdir">temporary
     directory</a> and transfer it to the remote server - deleting it on
     both sides once the difference has been determined.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No</td>
   </tr>
-  <a name="timestampGranularity"/>
-  <tr>
-    <td valign="top">timestampGranularity</td>
-    <td valign="top">Specify either <code>MINUTE</code>, <code>NONE</code>,
-     (or you may specify <code>""</code> which is equivalent to not specifying a value,
-     useful for property-file driven scripts).  Allows override of the typical situation 
-     in PUT and GET where local filesystem timestamps are <code>HH:mm:ss</code> 
-     and the typical FTP server's timestamps are <code>HH:mm</code>.  This can throw 
-     off uptodate calculations.  However, the default values should suffice for most
-     applications.<br>
-    Since ant 1.7
-    </td>
-    <td valign="top" align="center">No.  Only applies in "puts" and "gets" where the
-    default values are <code>MINUTE</code> for PUT and <code>NONE</code> for GET.  
-    (It is not as necessary in GET because we have the <b>preservelastmodified</b> option.)</td>
+  <tr id="timestampGranularity">
+    <td>timestampGranularity</td>
+    <td>Specify either <q>MINUTE</q> or <q>NONE</q> (you may specify <q></q> which is equivalent to
+      not specifying a value, useful for property-file driven scripts).  Allows override of the
+      typical situation in <q>put</q> and <q>get</q> where local filesystem timestamps
+      are <code>HH:mm:ss</code> and the typical FTP server's timestamps are <code>HH:mm</code>.
+      This can throw off <var>uptodate</var> calculations.  However, the default values should
+      suffice for most applications.<br/><em>Since Ant 1.7</em></td>
+    <td>No; only applies for <q>put</q> (default is <q>MINUTE</q>) and <q>get</q> (default
+      is <q>NONE</q>; not as necessary because we have the <var>preservelastmodified</var>
+      option)</td>
   </tr>
   <tr>
-    <td valign="top">timediffmillis</td>
-    <td valign="top"><b>Deprecated</b>. Number of milliseconds to add to the time on 
-    the remote machine to get the time on the local machine.  The <b>timestampGranularity</b> 
-    attribute (for which the default values should suffice in most situations), and the 
-    <b>serverTimeZoneConfig</b> option, should make this unnecessary. 
-    <b>serverTimeZoneConfig</b> does the math for you and also knows about 
-    Daylight Savings Time.<br>
-    Since ant 1.6
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>timediffmillis</td>
+    <td><em><u>Deprecated</u></em>. Number of milliseconds to add to the time on the remote machine
+      to get the time on the local machine.  The <var>timestampGranularity</var> attribute (for
+      which the default values should suffice in most situations), and
+      the <var>serverTimeZoneConfig</var> option, should make this
+      unnecessary.  <var>serverTimeZoneConfig</var> does the math for you and also knows about
+      Daylight Savings Time.<br/><em>Since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">separator</td>
-    <td valign="top">sets the file separator used on the ftp server.
-                     Defaults to "/".</td>
-    <td valign="top" align="center">No</td>
+    <td>separator</td>
+    <td>sets the file separator used on the FTP server.</td>
+    <td>No; defaults to <q>/</q></td>
   </tr>
   <tr>
-    <td valign="top">umask</td>
-    <td valign="top">sets the default file permissions for new files,
-                     unix only.</td>
-    <td valign="top" align="center">No</td>
+    <td>umask</td>
+    <td>sets the default file permissions for new files, Unix only.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">chmod</td>
-    <td valign="top">sets or changes file permissions for new or existing files,
-      unix only. If used with a put action, chmod will be issued for each file.</td>
-    <td valign="top" align="center">No</td>
+    <td>chmod</td>
+    <td>sets or changes file permissions for new or existing files, Unix only. If used with
+      a <q>put</q> action, <q>chmod</q> will be issued for each file.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">listing</td>
-    <td valign="top">the file to write results of the "list" action.
-                     Required for the "list" action, ignored otherwise.</td>
-    <td valign="top" align="center">No</td>
+    <td>listing</td>
+    <td>the file to write results of the <q>list</q> action.</td>
+    <td>Yes, for the <q>list</q> action; ignored otherwise</td>
   </tr>
   <tr>
-    <td valign="top">ignoreNoncriticalErrors</td>
-    <td valign="top">flag which permits the task to ignore some non-fatal error
-      codes sent by some servers during directory creation: wu-ftp in particular.
-      Default: false</td>
-    <td valign="top" align="center">No</td>
+    <td>ignoreNoncriticalErrors</td>
+    <td>flag which permits the task to ignore some non-fatal error codes sent by some servers during
+      directory creation: wu-ftp in particular.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">skipFailedTransfers</td>
-    <td valign="top">flag which enables unsuccessful file put, delete
-    and get operations to be skipped with a warning and the
-    remainder of the files still transferred. Default: false</td>
-    <td valign="top" align="center">No</td>
-  </tr>  
-  <tr>
-    <td valign="top">preservelastmodified</td>
-    <td valign="top">Give the copied files the same last modified
-      time as the original source files (applies to getting files only).
-      (<em>Note</em>: Ignored on Java 1.1)</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>skipFailedTransfers</td>
+    <td>flag which enables unsuccessful file <q>put</q>, <q>delete</q> and <q>get</q> operations to
+      be skipped with a warning and the remainder of the files still transferred.</td>
+    <td>No; default to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">retriesAllowed</td>
-    <td valign="top">Set the number of retries allowed on an file-transfer operation.
-    If a number > 0 specified, each file transfer can fail up to that
-    many times before the operation is failed.  If -1 or "forever" specified, the
-    operation will keep trying until it succeeds.</td>
-    <td valign="top" align="center">No; defaults to 0</td>
+    <td>preservelastmodified</td>
+    <td>Give the copied files the same last modified time as the original source files (applies to
+      getting files only).</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">siteCommand</td>
-    <td valign="top">Set the server-specific SITE command to execute if
-    the <code>action</code> attribute has been specified as <code>"site"</code>.
-    <td valign="top" align="center">No</td>
+    <td>retriesAllowed</td>
+    <td>Set the number of retries allowed on an file-transfer operation.  If a positive number is
+      specified, each file transfer can fail up to that many times before the operation is failed.
+      If <q>-1</q> or <q>forever</q> specified, the operation will keep trying until it
+      succeeds.</td>
+    <td>No; defaults to <q>0</q></td>
   </tr>
   <tr>
-    <td valign="top">initialSiteCommand</td>
-    <td valign="top">Set a server-specific SITE command to execute immediately
-      after login.</td>
-    <td valign="top" align="center">No</td>
+    <td>siteCommand</td>
+    <td>Set the server-specific <code>SITE</code> command to execute if the <var>action</var>
+      attribute has been specified as <q>site</q>.
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">enableRemoteVerification</td>
-    <td valign="top">Whether data connection should be verified to
-    connect to the same host as the control connection.  This is a
-    security measure that is enabled by default, but it may be useful
-    to disable it in certain firewall scenarios.
-      <em>since Ant 1.8.0</em></td>
-    <td valign="top" align="center">No, default is true</td>
-  </tr>
-
-    <tr>
-    <td colspan="3">
-    <p><b>The following attributes require <a href=
-    "http://commons.apache.org/net/download_net.cgi">
-    jakarta-commons-net-1.4.0 or greater</a>.</b></p>
-    <p>
-    Use these options when the standard options don't work, because
-    <ul><li>the server is in a different timezone and you need timestamp
-    dependency checking</li>
-    <li>the default timestamp formatting doesn't match the server display and
-    list parsing therefore fails</li></ul>
-    </p><p>
-    If none of these is specified, the default mechanism of letting the system
-    auto-detect the server OS type based on the FTP SYST command and assuming
-    standard formatting for that OS type will be used.
-    </p><p>
-    To aid in property-file-based development where a build script is configured
-    with property files, for any of these attributes, a value of <code>""</code>
-    is equivalent to not specifying it.
-    </p><p>
-    Please understand that these options are incompatible with the autodetection
-    scheme.  If any of these options is specified, (other than with a value of
-    <code>""</code> ) a system type must be chosen and if systemTypeKey is not
-    specified, UNIX will be assumed. The philosophy behind this is that these
-    options are for setting non-standard formats, and a build-script author who
-    knows what system he is dealing with will know what options to need to be
-    set. Otherwise, these options should be left alone and the default
-    autodetection scheme can be used and will work in the majority of cases.
-    </p></td>
-    </tr>
-  <tr>
-    <td valign="top">systemTypeKey</td>
-    <td valign="top">Specifies the type of system in use on the server.
-      Supported values are <code>"UNIX", "VMS", "WINDOWS", "OS/2", "OS/400",
-      "MVS".</code>  If not specified, (or specified as <code>""</code>) and if
-      no other xxxConfig attributes are specified, the autodetection mechanism
-      based on the FTP SYST command will be used.<br>
-      Since ant 1.7
-    </td>
-    <td valign="top" align="center">No, but if any of the following xxxConfig
-        attributes is specified, UNIX will be assumed, even if <code>""</code>
-        is specified here.
-    </td>
-   </tr>
-   <tr>
-    <td valign="top">serverTimeZoneConfig</td>
-    <td valign="top">Specify as a Java
-     <a href="http://docs.oracle.com/javase/7/docs/api//java/util/TimeZone.html">
-     TimeZone</a> identifier, (e.g. <code>GMT</code>, <code>America/Chicago</code> or
-    <code>Asia/Jakarta</code>) the timezone used by the server for timestamps.  This 
-      enables timestamp dependency checking even when the server is in a different 
-      time zone from the client. Time Zones know, also, about daylight savings time, 
-      and do not require you to calculate milliseconds of difference.  If not specified, 
-      (or specified as <code>""</code>), the time zone of the client is assumed.<br>
-      Since ant 1.7
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>initialSiteCommand</td>
+    <td>Set a server-specific <code>SITE</code> command to execute immediately after login.</td>
+    <td>No</td>
   </tr>
   <tr>
-    
-    <td valign="top">defaultDateFormatConfig</td>
-    <td valign="top">Specify in Java 
-    <a href="http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html">
-     SimpleDateFormat</a> notation, (e.g.
-     <code>yyyy-MM-dd</code>), the date format generally used by the FTP server
-      to parse dates.  In some cases this will be the only date format used.
-      In others, (unix for example) this will be used for dates
-      older than a year old. (See <b>recentDateFormatConfig</b>).  If not specified,
-      (or specified as <code>""</code>), the default date format for the system
-      type indicated by the <b>systemTypeKey</b> attribute will be used.<br>
-      Since ant 1.7
-    </td>
-    <td valign="top" align="center">
-    No.
-    </td>
+    <td>enableRemoteVerification</td>
+    <td>Whether data connection should be verified to connect to the same host as the control
+      connection.  This is a security measure that is enabled by default, but it may be useful to
+      disable it in certain firewall scenarios.  <em>since Ant 1.8.0</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">recentDateFormatConfig</td>
-    <td valign="top">Specify in Java 
-    <a href="http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html">
-     SimpleDateFormat</a> notation,
-      (e.g. <code>MMM dd hh:mm</code>) the date format used by the FTP server
-      to parse dates less than a year old.  If not specified (or specified as
-      <code>""</code>), and if the system type indicated by the system key uses
-      a recent date format, its standard format will be used.<br>
-      Since ant 1.7
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>dataTimeout</td>
+    <td>Sets a timeout in milliseconds used when waiting for data on the data connection.
+      A value of 0 means an infinite timeout.<em>since Ant 1.10.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">serverLanguageCodeConfig</td>
-    <td valign="top">a <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
-      two-letter ISO-639 language code</a> used to specify the
-      language used by the server to format month names.  This only needs to be
-      specified when the server uses non-numeric abbreviations for months in its
-      date listings in a language other than English.  This appears to be
-      becoming rarer and rarer, as commonly distributed ftp servers seem
-      increasingly to use English or all-numeric formats.
-      Languages supported are:
+    <td>wakeUpTransferInterval</td>
+    <td>Only use if proved to be necessary, interval in seconds on which a LIST command is triggered
+      trigger a data connection (to avoid timeouts by the ftp server on no data connection).
+      <em>since Ant 1.10.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td colspan="3" class="left">
+      <p><strong>The following attributes
+      require <a href="https://commons.apache.org/net/download_net.cgi"
+      target="_top">jakarta-commons-net-1.4.0 or greater</a>.</strong></p>
+      <p>Use these options when the standard options don't work, because</p>
       <ul>
-      	<li>en - English</li>
-      	<li>fr - French</li>
-      	<li>de - German</li>
-      	<li>it - Italian</li>
-      	<li>es - Spanish</li>
-      	<li>pt - Portuguese</li>
-      	<li>da - Danish</li>
-      	<li>sv - Swedish</li>
-      	<li>no - Norwegian</li>
-      	<li>nl - Dutch</li>
-      	<li>ro - Romanian</li>
-      	<li>sq - Albanian</li>
-      	<li>sh - Serbo-croatian</li>
-      	<li>sk - Slovak</li>
-      	<li>sl - Slovenian</li>
+        <li>the server is in a different timezone and you need timestamp dependency checking</li>
+        <li>the default timestamp formatting doesn't match the server display and list parsing
+          therefore fails</li>
       </ul>
-      If you require a language other than the above, see also the
-      <b>shortMonthNamesConfig</b> attribute.<br>
-      Since ant 1.7
+      <p>If none of these is specified, the default mechanism of letting the system auto-detect the
+      server OS type based on the FTP <code>SYST</code> command and assuming standard formatting
+      for that OS type will be used.</p>
+      <p>To aid in property-file-based development where a build script is configured with property
+      files, for any of these attributes, a value of <q></q> is equivalent to not specifying it.</p>
+      <p>Please understand that these options are incompatible with the autodetection scheme.  If
+      any of these options is specified, (other than with a value of <q></q>) a system type must be
+      chosen and if <var>systemTypeKey</var> is not specified, UNIX will be assumed. The philosophy
+      behind this is that these options are for setting non-standard formats, and a build-script
+      author who knows what system he is dealing with will know what options to need to be
+      set. Otherwise, these options should be left alone and the default autodetection scheme can be
+      used and will work in the majority of cases.</p>
     </td>
-
-    <td valign="top" align="center">No</td>
   </tr>
   <tr>
-    <td valign="top">shortMonthNamesConfig</td>
-    <td valign="top">specify the month abbreviations used on the server in file
-      timestamp dates as a pipe-delimited string for each month. For example,
-      a set of month names used by a hypothetical
-      Icelandic FTP server might conceivably be specified as
-      <code>"jan|feb|mar|apr|ma&#xED;|j&#xFA;n|j&#xFA;l|&#xE1;g&#xFA;|sep|okt|n&#xF3;v|des"</code>.
-      This attribute exists primarily to support languages not supported by
-      the <b>serverLanguageCode</b> attribute.<br>
-      Since ant 1.7
+    <td>systemTypeKey</td>
+    <td>Specifies the type of system in use on the server.  Supported values
+      are <q>UNIX</q>, <q>VMS</q>, <q>WINDOWS</q>, <q>OS/2</q>, <q>OS/400</q>, <q>MVS</q>. If not
+      specified, (or specified as <q></q>) and if no other <var>xxxConfig</var> attributes are
+      specified, the autodetection mechanism based on the FTP <code>SYST</code> command will be
+      used.<br/><em>Since Ant 1.7</em></td>
+    <td>No, but if any of the following <var>xxxConfig</var> attributes is specified, UNIX will be
+      assumed, even if <q></q> is specified here.
     </td>
-    <td valign="top" align="center">No</td>
+  </tr>
+  <tr>
+    <td>serverTimeZoneConfig</td>
+    <td>Specify as a
+      Java <a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html"
+      target="_top">TimeZone</a> identifier, (e.g. <q>GMT</q>, <q>America/Chicago</q>
+      or <q>Asia/Jakarta</q>) the timezone used by the server for timestamps.  This enables
+      timestamp dependency checking even when the server is in a different time zone from the
+      client. Time Zones know, also, about daylight savings time, and do not require you to
+      calculate milliseconds of difference.  If not specified, (or specified as <q></q>), the time
+      zone of the client is assumed.<br/><em>Since Ant 1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>defaultDateFormatConfig</td>
+    <td>Specify in
+      Java <a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html"
+      target="_top">SimpleDateFormat</a> notation, (e.g. <q>yyyy-MM-dd</q>), the date format
+      generally used by the FTP server to parse dates.  In some cases this will be the only date
+      format used.  In others, (<q>unix</q> for example) this will be used for dates older than a
+      year old. (See <var>recentDateFormatConfig</var>).  When specified as <q></q>, default value
+      will be used.<br/><em>Since Ant 1.7</em></td>
+    <td>No; defaults to default date format for the system type indicated
+      by <var>systemTypeKey</var></td>
+  </tr>
+  <tr>
+    <td>recentDateFormatConfig</td>
+    <td>Specify in
+      Java <a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html"
+      target="_top">SimpleDateFormat</a> notation, (e.g. <q>MMM dd hh:mm</q>) the date format used
+      by the FTP server to parse dates less than a year old.  If not specified (or specified
+      as <q></q>), and if the system type indicated by the <var>systemTypeKey</var> uses a recent
+      date format, its standard format will be used.<br/><em>Since Ant 1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>serverLanguageCodeConfig</td>
+    <td>a <a href="http://www.mathguide.de/info/tools/languagecode.html" target="_top">two-letter
+      ISO-639 language code</a> used to specify the language used by the server to format month
+      names.  This only needs to be specified when the server uses non-numeric abbreviations for
+      months in its date listings in a language other than English.  This appears to be becoming
+      rarer and rarer, as commonly distributed FTP servers seem increasingly to use English or
+      all-numeric formats.  Languages supported are:
+      <ul>
+        <li><q>en</q>&mdash;English</li>
+        <li><q>fr</q>&mdash;French</li>
+        <li><q>de</q>&mdash;German</li>
+        <li><q>it</q>&mdash;Italian</li>
+        <li><q>es</q>&mdash;Spanish</li>
+        <li><q>pt</q>&mdash;Portuguese</li>
+        <li><q>da</q>&mdash;Danish</li>
+        <li><q>sv</q>&mdash;Swedish</li>
+        <li><q>no</q>&mdash;Norwegian</li>
+        <li><q>nl</q>&mdash;Dutch</li>
+        <li><q>ro</q>&mdash;Romanian</li>
+        <li><q>sq</q>&mdash;Albanian</li>
+        <li><q>sh</q>&mdash;Serbo-Croatian</li>
+        <li><q>sk</q>&mdash;Slovak</li>
+        <li><q>sl</q>&mdash;Slovenian</li>
+      </ul>
+      If you require a language other than the above, see also the <var>shortMonthNamesConfig</var>
+      attribute.<br/><em>Since Ant 1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>shortMonthNamesConfig</td>
+    <td>specify the month abbreviations used on the server in file timestamp dates as a
+      pipe-delimited string for each month. For example, a set of month names used by a hypothetical
+      Icelandic FTP server might conceivably be specified
+      as <q>jan|feb|mar|apr|ma&iacute;|j&uacute;n|j&uacute;l|&aacute;g&uacute;|sep|okt|n&oacute;v|des</q>.
+      This attribute exists primarily to support languages not supported by
+      the <var>serverLanguageCode</var> attribute.<br/><em>Since Ant 1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>useFtps</td>
+    <td>Whether to use ftps instead of ftp. Boolean, defaults
+      to <var>false</var>.<br/>
+      <em>Since Ant 1.10.13</em></td>
+    <td>No</td>
   </tr>
 </table>
-<h3>Note about remotedir attribute</h3>
-<table  border="1" cellpadding="2" cellspacing="0"
- >
+<h3>Note about <var>remotedir</var> attribute</h3>
+<table>
+  <thead>
+    <tr>
+      <th scope="col">Action</th>
+      <th scope="col">meaning of <var>remotedir</var></th>
+      <th scope="col">use of nested <var>fileset</var>(s)</th>
+    </tr>
+  </thead>
   <tbody>
     <tr>
-      <td style="vertical-align: top;" width="20%">Action<br>
-      </td>
-      <td style="vertical-align: top;" width="40%">meaning of <code>remotedir</code><br>
-      </td>
-      <td style="vertical-align: top;">use of nested <code>fileset</code>
-(s)<br>
-      </td>
+      <td><q>send</q>/<q>put</q></td>
+      <td>base directory to which the files are sent</td>
+      <td>they are used normally and evaluated on the local machine</td>
     </tr>
     <tr>
-      <td style="vertical-align: top;" width="20%">send/put<br>
-      </td>
-      <td style="vertical-align: top;" width="40%">base directory to
-which the files are sent<br>
-      </td>
-      <td style="vertical-align: top;">they are used normally and
-evaluated on the local machine<br>
-      </td>
+      <td><q>recv</q>/<q>get</q></td>
+      <td>base directory from which the files are retrieved</td>
+      <td>the remote files located under the <var>remotedir</var> matching the include/exclude
+        patterns of the <var>fileset</var></td>
     </tr>
     <tr>
-      <td style="vertical-align: top;" width="20%">recv/get<br>
-      </td>
-      <td style="vertical-align: top;" width="40%">base directory from
-which the files are retrieved<br>
-      </td>
-      <td style="vertical-align: top;">the remote files located under
-the <code>remotedir </code>matching the include/exclude patterns of
-the <code>fileset&nbsp;</code></td>
+      <td><q>del</q>/<q>delete</q></td>
+      <td>base directory from which files get deleted</td>
+      <td>the remote files located under the <var>remotedir</var> matching the include/exclude
+        patterns of the <var>fileset</var></td>
     </tr>
     <tr>
-      <td style="vertical-align: top;" width="20%">del/delete<br>
-      </td>
-      <td style="vertical-align: top;" width="40%">base directory from
-which files get deleted<br>
-      </td>
-      <td style="vertical-align: top;">the remote files located under
-the <code>remotedir </code>matching the include/exclude patterns of
-the <code>fileset <br>
-      </code></td>
+      <td><q>list</q></td>
+      <td>base directory from which files are listed</td>
+      <td>the remote files located under the <var>remotedir</var> matching the include/exclude
+        patterns of the <var>fileset</var></td>
     </tr>
     <tr>
-      <td style="vertical-align: top;" width="20%">list<br>
-      </td>
-      <td style="vertical-align: top;" width="40%">base directory from
-which files are listed<br>
-      </td>
-      <td style="vertical-align: top;">the remote files located under
-the <code>remotedir </code>matching the include/exclude patterns of
-the <code>fileset <br>
-      </code></td>
+      <td><q>mkdir</q></td>
+      <td>directory to create</td>
+      <td><em>not used</em></td>
     </tr>
     <tr>
-      <td style="vertical-align: top;" width="20%">mkdir</td>
-      <td style="vertical-align: top;" width="40%">directory to create<br>
-      </td>
-      <td style="vertical-align: top;">not used<br>
-      </td>
+      <td><q>chmod</q></td>
+      <td>base directory from which the mode of files get changed</td>
+      <td>the remote files located under the <var>remotedir</var> matching the include/exclude
+        patterns of the <var>fileset</var></td>
     </tr>
     <tr>
-      <td style="vertical-align: top;" width="20%">chmod</td>
-      <td style="vertical-align: top;" width="40%">base directory from
-which the mode of files get changed<br>
-      </td>
-      <td style="vertical-align: top;">the remote files located under
-the <code>remotedir </code>matching the include/exclude patterns of
-the <code>fileset <br>
-      </code></td>
-    </tr>
-    <tr>
-      <td style="vertical-align: top;" width="20%">rmdir<br>
-      </td>
-      <td style="vertical-align: top;" width="40%">base directory from
-which directories get removed<br>
-      </td>
-      <td style="vertical-align: top;">the remote directories located
-under the <code>remotedir </code>matching the include/exclude
-patterns of the <code>fileset <br>
-      </code></td>
+      <td><q>rmdir</q></td>
+      <td>base directory from which directories get removed</td>
+      <td>the remote directories located under the <var>remotedir</var> matching the include/exclude
+        patterns of the <var>fileset</var></td>
     </tr>
   </tbody>
-</table><h3>Parameters specified as nested elements</h3>
+</table>
+<h3>Parameters specified as nested elements</h3>
 <h4>fileset</h4>
-<p>The ftp task supports any number of nested <a
-href="../Types/fileset.html"><code>&lt;fileset&gt;</code></a> elements to specify
-the files to be retrieved, or deleted, or listed, or whose mode you want to change.</p>
-<p>
-The attribute <code>followsymlinks</code> of <code>fileset</code> is supported on
-local (put) as well as remote (get, chmod, delete, list) filesets.
-<em>Before ant 1.6 there was no support of symbolic links in remote filesets.
-In order to exclude symbolic links (preserve the behavior of ant 1.5.x and older),
-you need to explicitly set <code>followsymlinks</code> to <code>false</code>.</em>
-On remote filesets hidden files are not checked for being symbolic links. Hidden
-files are currently assumed to not be symbolic links.
-</p>
+<p>The <code>ftp</code> task supports any number of
+nested <a href="../Types/fileset.html"><code>&lt;fileset&gt;</code></a> elements to specify the
+files to be retrieved, or deleted, or listed, or whose mode you want to change.</p>
+<p>The attribute <var>followsymlinks</var> of <code>fileset</code> is supported on local
+(<q>put</q>) as well as remote (<q>get</q>, <q>chmod</q>, <q>delete</q>, <q>list</q>) filesets.  <em>Before Ant
+1.6 there was no support of symbolic links in remote filesets.  In order to exclude symbolic links
+(preserve the behavior of Ant 1.5.x and older), you need to explicitly set <var>followsymlinks</var>
+to <q>false</q>.</em>  On remote filesets hidden files are not checked for being symbolic links.
+Hidden files are currently assumed to not be symbolic links.</p>
 
-<h3>Sending Files</h3>
-<p>The easiest way to describe how to send files is with a couple of examples:</p>
+<h3>Sending files</h3>
+<p>The easiest way to describe how to send files is with a couple of examples.</p>
+<p>Log in to <samp>ftp.apache.org</samp> as <samp>anonymous</samp> and upload all files in
+the <samp>htdocs/manual</samp> directory to the default directory for that user.</p>
 <pre>
-  &lt;ftp server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"&gt;
+&lt;ftp server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"&gt;
     &lt;fileset dir="htdocs/manual"/&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>Logs in to <code>ftp.apache.org</code> as <code>anonymous</code> and 
-uploads all files in the <code>htdocs/manual</code> directory 
-to the default directory for that user.</p>
-<pre>  &lt;ftp server="ftp.apache.org"
-       remotedir="incoming"
-       userid="anonymous"
-       password="me@myorg.com"
-       depends="yes"&gt;
+&lt;/ftp&gt;</pre>
+
+<p>Log in to <samp>ftp.apache.org</samp> as <samp>anonymous</samp> and upload all new or changed
+files in the <samp>htdocs/manual</samp> directory to the <samp>incoming</samp> directory relative to
+the default directory for <samp>anonymous</samp>.</p>
+<pre>
+&lt;ftp server="ftp.apache.org"
+     remotedir="incoming"
+     userid="anonymous"
+     password="me@myorg.com"
+     depends="yes"&gt;
     &lt;fileset dir="htdocs/manual"/&gt;
-  &lt;/ftp&gt;</pre>
-<p>Logs in to <code>ftp.apache.org</code> as <code>anonymous</code> and
-uploads all new or changed files in the <code>htdocs/manual</code> directory 
-to the <code>incoming</code> directory relative to the default directory
-for <code>anonymous</code>.</p>
-<pre>  &lt;ftp server="ftp.apache.org"
-       port="2121"
-       remotedir="/pub/incoming"
-       userid="coder"
-       password="java1"
-       passive="yes"
-       depends="yes"
-       binary="no"&gt;
-    &lt;fileset dir="htdocs/manual"&gt;
-      &lt;include name="**/*.html"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;</pre>
-<p>Logs in to <code>ftp.apache.org</code> at port <code>2121</code> as
-<code>coder</code> with password <code>java1</code> and uploads all new or
-changed HTML files in the <code>htdocs/manual</code> directory to the
-<code>/pub/incoming</code> directory. The files are transferred in text mode.
-Passive mode has been switched on to send files from behind a firewall.</p>
-<pre>  &lt;ftp server="ftp.hypothetical.india.org"
-       port="2121"
-       remotedir="/pub/incoming"
-       userid="coder"
-       password="java1"
-       depends="yes"
-       binary="no"
-       systemTypeKey="Windows"
-       serverTimeZoneConfig="India/Calcutta"&gt;
-    &lt;fileset dir="htdocs/manual"&gt;
-      &lt;include name="**/*.html"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;</pre>
-<p>Logs in to a Windows server at <code>ftp.hypothetical.india.org</code>
-at port <code>2121</code> as <code>coder</code> with password <code>java1</code>
-and uploads all new or changed (accounting for timezone differences)
-HTML files in the <code>htdocs/manual</code>
-directory to the <code>/pub/incoming</code> directory. The files are transferred
-in text mode.</p>
-<pre>  &lt;ftp server="ftp.nt.org"
-       remotedir="c:\uploads"
-       userid="coder"
-       password="java1"
-       separator="\"
-       verbose="yes"&gt;
-    &lt;fileset dir="htdocs/manual"&gt;
-      &lt;include name="**/*.html"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;</pre><p>Logs in to the Windows-based <code>ftp.nt.org</code> as 
-<code>coder</code> with password <code>java1</code> and uploads all 
-HTML files in the <code>htdocs/manual</code> directory to the 
-<code>c:\uploads</code> directory.  Progress messages are displayed as each
-file is uploaded.</p>
-<h3>Getting Files</h3>
-<p>Getting files from an FTP server works pretty much the same way as 
-sending them does.  The only difference is that the nested filesets
-use the remotedir attribute as the base directory for the files on the
-FTP server, and the dir attribute as the local directory to put the files
-into.  The file structure from the FTP site is preserved on the local machine.</p>
-<pre>
-  &lt;ftp action="get"
-       server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"&gt;
-    &lt;fileset dir="htdocs/manual"&gt;
-      &lt;include name="**/*.html"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>Logs in to <code>ftp.apache.org</code> as <code>anonymous</code> and 
-recursively downloads all .html files from default directory for that user 
-into the <code>htdocs/manual</code> directory on the local machine.</p>
-<pre>
-  &lt;ftp action="get"
-       server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"
-       systemTypeKey="UNIX"
-       defaultDateFormatConfig="yyyy-MM-dd HH:mm"&gt;
-    &lt;fileset dir="htdocs/manual"&gt;
-      &lt;include name="**/*.html"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>If apache.org ever switches to a unix FTP server that uses the new all-numeric
-format for timestamps, this version would become necessary.  It would accomplish
-the same functionality as the previous example but would successfully handle the
-numeric timestamps.
-The <code>systemTypeKey</code> is not necessary here but helps clarify what is
-going on.</p>
-<pre>
-  &lt;ftp action="get"
-       server="ftp.hypthetical.fr"
-       userid="anonymous"
-       password="me@myorg.com"
-       defaultDateFormatConfig="d MMM yyyy"
-       recentDateFormatConfig="d MMM HH:mm"
-       serverLanguageCodeConfig="fr"&gt;
-     &lt;fileset dir="htdocs/manual"&gt;
-      &lt;include name="**/*.html"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>Logs into a UNIX FTP server at <code>ftp.hypothetical.fr</code> which displays
-dates with French names in Standard European format, as <code>anonymous</code>, and
-recursively downloads all .html files from default directory for that user
-into the <code>htdocs/manual</code> directory on the local machine.</p>
+&lt;/ftp&gt;</pre>
 
-<h3>Deleting Files</h3>
-As you've probably guessed by now, you use nested fileset elements to 
-select the files to delete from the remote FTP server.  Again, the 
-filesets are relative to the remote directory, not a local directory.  In
-fact, the dir attribute of the fileset is ignored completely.
-
+<p>Log in to <samp>ftp.apache.org</samp> at port <samp>2121</samp> as <samp>coder</samp> with
+password <samp>java1</samp> and upload all new or changed HTML files in
+the <samp>htdocs/manual</samp> directory to the <samp>/pub/incoming</samp> directory. The files are
+transferred in text mode.  Passive mode has been switched on to send files from behind a
+firewall.</p>
 <pre>
-  &lt;ftp action="del"
-       server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"&gt;
+&lt;ftp server="ftp.apache.org"
+     port="2121"
+     remotedir="/pub/incoming"
+     userid="coder"
+     password="java1"
+     passive="yes"
+     depends="yes"
+     binary="no"&gt;
+    &lt;fileset dir="htdocs/manual"&gt;
+        &lt;include name="**/*.html"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+
+<p>Log in to a Windows server at <samp>ftp.hypothetical.india.org</samp> at port <samp>2121</samp>
+as <samp>coder</samp> with password <samp>java1</samp> and upload all new or changed (accounting for
+timezone differences) HTML files in the <samp>htdocs/manual</samp> directory to
+the <samp>/pub/incoming</samp> directory. The files are transferred in text mode.</p>
+<pre>
+&lt;ftp server="ftp.hypothetical.india.org"
+     port="2121"
+     remotedir="/pub/incoming"
+     userid="coder"
+     password="java1"
+     depends="yes"
+     binary="no"
+     systemTypeKey="Windows"
+     serverTimeZoneConfig="India/Calcutta"&gt;
+    &lt;fileset dir="htdocs/manual"&gt;
+        &lt;include name="**/*.html"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+
+<p>Log in to the Windows-based <samp>ftp.nt.org</samp> as <samp>coder</samp> with
+password <samp>java1</samp> and upload all HTML files in the <samp>htdocs/manual</samp> directory to
+the <samp>c:\uploads</samp> directory. Progress messages are displayed as each file is uploaded.</p>
+<pre>
+&lt;ftp server="ftp.nt.org"
+     remotedir="c:\uploads"
+     userid="coder"
+     password="java1"
+     separator="\"
+     verbose="yes"&gt;
+    &lt;fileset dir="htdocs/manual"&gt;
+        &lt;include name="**/*.html"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+
+<h3>Getting files</h3>
+<p>Getting files from an FTP server works pretty much the same way as sending them does. The only
+difference is that the nested filesets use the <var>remotedir</var> attribute as the base directory
+for the files on the FTP server, and the <var>dir</var> attribute as the local directory to put the
+files into. The file structure from the FTP site is preserved on the local machine.</p>
+
+<p>Log in to <samp>ftp.apache.org</samp> as <samp>anonymous</samp> and recursively download
+all <samp>.html</samp> files from default directory for that user into
+the <samp>htdocs/manual</samp> directory on the local machine.</p>
+<pre>
+&lt;ftp action="get"
+     server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"&gt;
+    &lt;fileset dir="htdocs/manual"&gt;
+        &lt;include name="**/*.html"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+
+<p>If <samp>apache.org</samp> ever switches to a Unix FTP server that uses the new all-numeric
+format for timestamps, this version would become necessary. It would accomplish the same
+functionality as the previous example but would successfully handle the numeric
+timestamps. The <var>systemTypeKey</var> is not necessary here but helps clarify what is going
+on.</p>
+<pre>
+&lt;ftp action="get"
+     server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"
+     systemTypeKey="UNIX"
+     defaultDateFormatConfig="yyyy-MM-dd HH:mm"&gt;
+    &lt;fileset dir="htdocs/manual"&gt;
+        &lt;include name="**/*.html"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+
+<p>Log into a UNIX FTP server at <samp>ftp.hypothetical.fr</samp> which displays dates with French
+names in Standard European format, as <samp>anonymous</samp>, and recursively download
+all <samp>.html</samp> files from default directory for that user into
+the <samp>htdocs/manual</samp> directory on the local machine.</p>
+<pre>
+&lt;ftp action="get"
+     server="ftp.hypthetical.fr"
+     userid="anonymous"
+     password="me@myorg.com"
+     defaultDateFormatConfig="d MMM yyyy"
+     recentDateFormatConfig="d MMM HH:mm"
+     serverLanguageCodeConfig="fr"&gt;
+    &lt;fileset dir="htdocs/manual"&gt;
+        &lt;include name="**/*.html"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+
+<h3>Deleting files</h3>
+<p>As you've probably guessed by now, you use nested fileset elements to select the files to delete
+from the remote FTP server.  Again, the filesets are relative to the remote directory, not a local
+directory.  In fact, the <var>dir</var> attribute of the fileset is ignored completely.</p>
+
+<p>Log in to <samp>ftp.apache.org</samp> as <samp>anonymous</samp> and try to delete
+all <samp>*.tmp</samp> files from the default directory for that user.  If you don't have permission
+to delete a file, a <code>BuildException</code> is thrown.</p>
+<pre>
+&lt;ftp action="del"
+     server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"&gt;
     &lt;fileset&gt;
-      &lt;include name="**/*.tmp"/&gt;
+        &lt;include name="**/*.tmp"/&gt;
     &lt;/fileset&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>Logs in to <code>ftp.apache.org</code> as <code>anonymous</code> and
-tries to delete all *.tmp files from the default directory for that user.
-If you don't have permission to delete a file, a BuildException is thrown.</p>
+&lt;/ftp&gt;</pre>
+
 <h3>Listing Files</h3>
+<p>Get a file listing in <samp>data/ftp.listing</samp> of all the files on the FTP server relative
+to the default directory of the <samp>anonymous</samp> user. The listing is in whatever format the
+FTP server normally lists files.</p>
 <pre>
-  &lt;ftp action="list"
-       server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"
-       listing="data/ftp.listing"&gt;
-    &lt;fileset&gt;
-      &lt;include name="**"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>This provides a file listing in <code>data/ftp.listing</code> of all the files on
-the FTP server relative to the default directory of the <code>anonymous</code>
-user. The listing is in whatever format the FTP server normally lists files.</p>
-
-<h3>Creating Directories</h3>
-<p>Note that with the mkdir action, the directory to create is specified using the
-remotedir attribute.</p>
-<pre>
-  &lt;ftp action="mkdir"
-       server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"
-       remotedir="some/remote/dir"/&gt;
-</pre>
-<p>This creates the directory <code>some/remote/dir</code> beneath the default root
-directory.  As with all other actions, the directory separator character must be correct
-according to the desires of the FTP server.</p>
-<h3>Removing Directories</h3>
-This action uses nested fileset elements to 
-select the directories to remove from the remote FTP server.  The 
-filesets are relative to the remote directory, not a local directory. 
-The dir attribute of the fileset is ignored completely.
-The directories to be removed must be empty, or contain only
-other directories that have been also selected to be removed by the filesets
-patterns, otherwise a BuildException will be thrown.
-Also, if you don't have permission to remove a directory, a BuildException is 
-thrown.
-
-<pre>
-  &lt;ftp action="rmdir"
-       server="ftp.apache.org"
-       userid="anonymous"
-       password="me@myorg.com"
-       remotedir="/somedir" &gt;
-    &lt;fileset&gt;
-      &lt;include name="dira"/&gt;
-      &lt;include name="dirb/**"/&gt;
-    &lt;/fileset&gt;
-  &lt;/ftp&gt;
-</pre>
-<p>Logs in to <code>ftp.apache.org</code> as <code>anonymous</code> and
-tries to remove <code>/somedir/dira</code> directory and
-all the directories tree starting at, and including, <code>/somedir/dirb</code>.
-When removing the <code>/somedir/dirb</code> tree,
-it will start at the leaves moving up to the root, so that when
-it tries to remove a directory it is sure all the directories under it are
-already removed.
-Obviously all the files in the tree must have been already deleted.
-</p>
-<p>As an example suppose you want to delete everything contained into 
-<code>/somedir</code>, so invoke first the <code>&lt;ftp&gt;</code> task with
-<code>action="delete"</code>, then with
-<code>action="rmdir"</code> specifying in both cases
-<code>remotedir="/somedir"</code> and
-
-<pre>
+&lt;ftp action="list"
+     server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"
+     listing="data/ftp.listing"&gt;
     &lt;fileset&gt;
         &lt;include name="**"/&gt;
     &lt;/fileset&gt;
-</pre>
+&lt;/ftp&gt;</pre>
 
-The directory specified in the <code>remotedir</code> parameter is never
-selected for remove, so if you need to remove it, specify its parent in
-<code>remotedir</code> parameter and include it in the 
-<code>&lt;fileset&gt;</code> pattern, like <code>"somedir/**"</code>.
-</p>
+<h3>Creating directories</h3>
+<p>Note that with the <q>mkdir</q> action, the directory to create is specified using
+the <var>remotedir</var> attribute.</p>
+<p>Create the directory <samp>some/remote/dir</samp> beneath the default root directory. As with all
+other actions, the directory separator character must be correct according to the desires of the FTP
+server.</p>
+<pre>
+&lt;ftp action="mkdir"
+     server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"
+     remotedir="some/remote/dir"/&gt;</pre>
 
+<h3>Removing directories</h3>
+<p>This action uses nested fileset elements to select the directories to remove from the remote FTP
+server. The filesets are relative to the remote directory, not a local directory. The <var>dir</var>
+attribute of the fileset is ignored completely. The directories to be removed must be empty, or
+contain only other directories that have been also selected to be removed by the filesets patterns,
+otherwise a <code>BuildException</code> will be thrown. Also, if you don't have permission to remove
+a directory, a <code>BuildException</code> is thrown.</p>
+
+<p>Log in to <samp>ftp.apache.org</samp> as <samp>anonymous</samp> and try to
+remove <samp>/somedir/dira</samp> directory and all the directory tree starting at, and
+including, <samp>/somedir/dirb</samp>.  When removing the <samp>/somedir/dirb</samp> tree, the task
+starts at the leaves moving up to the root, so that when it tries to remove a directory it is sure
+all the directories under it are already removed.  Obviously all the files in the tree must have
+been already deleted.</p>
+<pre>
+&lt;ftp action="rmdir"
+     server="ftp.apache.org"
+     userid="anonymous"
+     password="me@myorg.com"
+     remotedir="/somedir" &gt;
+    &lt;fileset&gt;
+        &lt;include name="dira"/&gt;
+        &lt;include name="dirb/**"/&gt;
+    &lt;/fileset&gt;
+&lt;/ftp&gt;</pre>
+<p>As an example suppose you want to delete everything contained in <samp>/somedir</samp>, so invoke
+first the <code>&lt;ftp&gt;</code> task with <var>action</var>=<q>delete</q>, then
+with <var>action</var>=<q>rmdir</q> specifying in both cases <var>remotedir</var>=<q>/somedir</q>
+and</p>
+<pre>
+&lt;fileset&gt;
+    &lt;include name="**"/&gt;
+&lt;/fileset&gt;</pre>
+<p>The directory specified in the <var>remotedir</var> parameter is never selected for remove, so if
+you need to remove it, specify its parent in <var>remotedir</var> parameter and include it in the
+<code>&lt;fileset&gt;</code> pattern, like <samp>somedir/**</samp>.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/genkey.html b/manual/Tasks/genkey.html
index e052b43..ad6e451 100644
--- a/manual/Tasks/genkey.html
+++ b/manual/Tasks/genkey.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,108 +15,102 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>GenKey Task</title>
 </head>
 
 <body>
 
-<h2><a name="genkey">GenKey</a></h2>
+<h2 id="genkey">GenKey</h2>
 <h3>Description</h3>
-<p>Generates a key in a keystore. </p>
+<p>Generates a key in a keystore.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">alias</td>
-    <td valign="top">the alias to add under</td>
-    <td valign="top" align="center">Yes.</td>
+    <td>alias</td>
+    <td>the alias to add under</td>
+    <td>Yes.</td>
   </tr>
   <tr>
-    <td valign="top">storepass</td>
-    <td valign="top">password for keystore integrity. Must
-	be at least 6 characters long</td>
-    <td valign="top" align="center">Yes.</td>
+    <td>storepass</td>
+    <td>password for keystore integrity. Must be at least 6 characters long</td>
+    <td>Yes.</td>
   </tr>
   <tr>
-    <td valign="top">keystore</td>
-    <td valign="top">keystore location</td>
-    <td valign="top" align="center">No</td>
+    <td>keystore</td>
+    <td>keystore location</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">storetype</td>
-    <td valign="top">keystore type</td>
-    <td valign="top" align="center">No</td>
+    <td>storetype</td>
+    <td>keystore type</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keypass</td>
-    <td valign="top">password for private key (if different)</td>
-    <td valign="top" align="center">No</td>
+    <td>keypass</td>
+    <td>password for private key (if different)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sigalg</td>
-    <td valign="top">the algorithm to use in signing</td>
-    <td valign="top" align="center">No</td>
+    <td>sigalg</td>
+    <td>the algorithm to use in signing</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keyalg</td>
-    <td valign="top">the method to use when generating name-value pair</td>
-    <td valign="top" align="center">No</td>
+    <td>keyalg</td>
+    <td>the method to use when generating name-value pair</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">(true | false) verbose output when signing</td>
-    <td valign="top" align="center">No</td>
+    <td>verbose</td>
+    <td>(<q>true|false</q>) verbose output when signing</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dname</td>
-    <td valign="top">The distinguished name for entity</td>
-    <td valign="top" align="center">Yes if dname element unspecified</td>
+    <td>dname</td>
+    <td>The distinguished name for entity</td>
+    <td>Yes unless <code>&lt;dname&gt;</code> element is specified</td>
   </tr>
   <tr>
-    <td valign="top">saname</td>
-    <td valign="top">The subject alternative name for entity. Requires
+    <td>saname</td>
+    <td>The subject alternative name for entity. Requires
  Java 7 or higher.</td>
-    <td valign="top" align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">validity</td>
-    <td valign="top">(integer) indicates how many days certificate is valid</td>
-    <td valign="top" align="center">No</td>
+    <td>validity</td>
+    <td>(integer) indicates how many days certificate is valid</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keysize</td>
-    <td valign="top">(integer) indicates the size of key generated</td>
-    <td valign="top" align="center">No</td>
+    <td>keysize</td>
+    <td>(integer) indicates the size of key generated</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p>Alternatively you can specify the distinguished name by creating a
-sub-element named dname and populating it with param elements that
-have a name and a value. When using the subelement it is automatically
-encoded properly and commas (&quot;<code>,</code>&quot;) are replaced
-with &quot;<code>\,</code>&quot;.</p>
-
-<p>The following two examples are identical: </p>
+<p>Alternatively you can specify the distinguished name by creating a <code>&lt;dname&gt;</code>
+sub-element and populating it with <code>&lt;param&gt;</code> elements that have a <var>name</var>
+and a <var>value</var>. When using the subelement, it is automatically encoded properly and commas
+(<q>,</q>) are replaced with <q>\,</q>.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;genkey alias=&quot;apache-group&quot; storepass=&quot;secret&quot; 
-  dname=&quot;CN=Ant Group, OU=Jakarta Division, O=Apache.org, C=US&quot;/&gt;
-</pre></blockquote>
+<p>The following two examples are identical:</p>
+<pre>
+&lt;genkey alias=&quot;apache-group&quot; storepass=&quot;secret&quot;
+        dname=&quot;CN=Ant Group, OU=Jakarta Division, O=Apache.org, C=US&quot;/&gt;</pre>
 
-<blockquote>
-  <pre>
-&lt;genkey alias=&quot;apache-group&quot; storepass=&quot;secret&quot; &gt;
+<pre>
+&lt;genkey alias=&quot;apache-group&quot; storepass=&quot;secret&quot;&gt;
   &lt;dname&gt;
     &lt;param name=&quot;CN&quot; value=&quot;Ant Group&quot;/&gt;
     &lt;param name=&quot;OU&quot; value=&quot;Jakarta Division&quot;/&gt;
@@ -123,9 +118,6 @@
     &lt;param name=&quot;C&quot;  value=&quot;US&quot;/&gt;
   &lt;/dname&gt;
 &lt;/genkey&gt;</pre>
-</blockquote>
-
 
 </body>
 </html>
-
diff --git a/manual/Tasks/get.html b/manual/Tasks/get.html
index 0ca9065..fe7deb4 100644
--- a/manual/Tasks/get.html
+++ b/manual/Tasks/get.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,235 +15,241 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Get Task</title>
 </head>
 
 <body>
 
-<h2><a name="get">Get</a></h2>
+<h2 id="get">Get</h2>
 <h3>Description</h3>
-<p>Gets files from URLs.  When the verbose option is &quot;on&quot;, this task
-displays a '.' for every 100 Kb retrieved. Any URL schema supported by
-the runtime is valid here, including http:, ftp: and jar:; 
-</p>
-The <i>usetimestamp</i> option enables you to control downloads so that the remote file is
-only fetched if newer than the local copy. If there is no local copy, the download always takes 
-place. When a file is downloaded, the timestamp of the downloaded file is set to the remote timestamp. 
-NB: This timestamp facility only works on downloads using the HTTP protocol. 
-<p>
-A username and password can be specified, in which case basic 'slightly encoded
-plain text' authentication is used. This is only secure over an HTTPS link.
-</p>
+<p>Gets files from URLs.  When the <var>verbose</var> option is <q>on</q>, this task displays
+a <q>.</q> for every 100 Kb retrieved. Any URL schema supported by the runtime is valid here,
+including <q>http:</q>, <q>https:</q>, <q>ftp:</q> and <q>jar:</q>.</p>
+<p>The <var>usetimestamp</var> option enables you to control downloads so that the remote file is
+only fetched if newer than the local copy. If there is no local copy, the download always takes
+place. When a file is downloaded, the timestamp of the downloaded file is set to the remote
+timestamp.  <strong>Note</strong>: This timestamp facility only works on downloads using the HTTP
+protocol.</p>
+<p>A username and password can be specified, in which case basic ('slightly encoded plain text')
+authentication is used. This is only secure over an HTTPS link.</p>
 
-<p><b>Proxies</b>. Since Apache Ant 1.7.0, Ant running on Java1.5 or later can
-  <a href="../proxy.html">use the proxy settings of the operating
-    system</a> if enabled with the
-  <code>-autoproxy</code> option. There is also the
-  <a href="../Tasks/setproxy.html">&lt;setproxy&gt;</a> task
-  for earlier Java versions. With proxies turned
-  on, <code>&lt;get&gt;</code> requests against localhost may not work
-  as expected, if the request is relayed to the proxy.</p>
- 
+<p><strong>Proxies</strong>. <em>Since Apache Ant 1.7.0</em>, Ant running on Java 5 or later
+can <a href="../proxy.html">use the proxy settings of the operating system</a> if enabled with
+the <kbd>-autoproxy</kbd> command line option. There is also
+the <a href="../Tasks/setproxy.html">&lt;setproxy&gt;</a> task for earlier Java versions. With
+proxies turned on, <code>&lt;get&gt;</code> requests against localhost may not work as expected, if
+the request is relayed to the proxy.</p>
+
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">the URL from which to retrieve a file.</td>
-    <td align="center" valign="top">Yes or a nested resource collection</td>
+    <td>src</td>
+    <td>the URL from which to retrieve a file.</td>
+    <td>Yes, or a nested resource collection</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">the file or directory where to store the
-      retrieved file(s).</td>
-    <td align="center" valign="top">Yes</td>
+    <td>dest</td>
+    <td>the file or directory where to store the retrieved file(s).</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">show verbose progress information (&quot;on&quot;/&quot;off&quot;).</td>
-    <td align="center" valign="top">No; default "false"</td>
+    <td>verbose</td>
+    <td>show verbose progress information (<q>on|off</q>).</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">Log errors only.(&quot;true&quot;/&quot;false&quot;).</td>
-    <td align="center" valign="top">No; default "false"</td>
-  </tr>
-  <tr>
-    <td valign="top">ignoreerrors</td>
-    <td valign="top">Log errors but don't treat as fatal.</td>
-    <td align="center" valign="top">No; default "false"</td>
-  </tr>
-  <tr>
-    <td valign="top">usetimestamp</td>
-    <td valign="top">conditionally download a file based on the timestamp of the
-    local copy. HTTP only</td>
-    <td align="center" valign="top">No; default "false"</td>
-  </tr>
-  <tr>
-    <td valign="top">username</td>
-    <td valign="top">username for 'BASIC' http authentication</td>
-    <td align="center" valign="top">if password is set</td>
-  </tr>  
-  <tr>
-    <td valign="top">password</td>
-    <td valign="top">password: required </td>
-    <td align="center" valign="top">if username is set</td>
-  </tr>  
-  <tr>
-    <td>authenticateOnRedirect</td>
-    <td>Whether the credentials should also be sent to the new location when a redirect is followed.<br/>
-    <em>since Ant 1.9.17</em></td>
+    <td>quiet</td>
+    <td>Log errors only.(<q>true|false</q>).</td>
     <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">maxtime</td>
-    <td valign="top">Maximum time in seconds a single download may take,
-      otherwise it will be interrupted and treated like a download
-      error.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No: default 0 which means no
-      maximum time</td>
-  </tr>  
-  <tr>
-    <td valign="top">retries</td>
-    <td valign="top">The number of attempts to make for opening the URI.<br/>
-      The name of the attribute is misleading as a value of 1 means
-      "don't retry on error" and a value of 0 meant don't even try to
-      reach the URI at all.<br/>
-      <em>since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No; default "3"</td>
+    <td>ignoreerrors</td>
+    <td>Log errors but don't treat as fatal.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">skipexisting</td>
-    <td valign="top">skip files that already exist on the local filesystem<br/>
-      <em>since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No; default "false"</td>
+    <td>usetimestamp</td>
+    <td>conditionally download a file based on the timestamp of the local copy. HTTP only</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>username</td>
+    <td>username for basic HTTP authentication</td>
+    <td>Yes, if <var>password</var> is set</td>
+  </tr>
+  <tr>
+    <td>password</td>
+    <td>password for basic HTTP authentication</td>
+    <td>Yes if <var>username</var> is set</td>
+  </tr>
+  <tr>
+    <td>authenticateOnRedirect</td>
+    <td>Whether the credentials should also be sent to the new location when a redirect is followed.<br/>
+    <em>since Ant 1.10.13</em></td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>maxtime</td>
+    <td>Maximum time in seconds a single download may take, otherwise it will be interrupted and
+      treated like a download error.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is <q>0</q> which means
+      unlimited</td>
+  </tr>
+  <tr>
+    <td>retries</td>
+    <td>The number of attempts to make for opening the URI.<br/>The name of the attribute is
+      misleading as a value of <q>1</q> means "don't retry on error" and a value of <q>0</q> meant
+      don't even try to reach the URI at all.<br/><em>since Ant 1.8.0</em></td>
+    <td>No; default is <q>3</q></td>
+  </tr>
+  <tr>
+    <td>skipexisting</td>
+    <td>skip files that already exist on the local filesystem<br/><em>since Ant 1.8.0</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
    <tr>
-    <td valign="top">httpusecaches</td>
-    <td valign="top">HTTP only - if true, allow caching at the
-      HttpUrlConnection level.  if false, turn caching off.<br/>
-      <b>Note</b> this is only a hint to the underlying UrlConnection
-      class, implementations and proxies are free to ignore the
-      setting.</td>
-    <td align="center" valign="top">No; default "true"</td>
+    <td>httpusecaches</td>
+    <td>HTTP only&mdash;if <q>true</q>, allow caching at the <code>HttpUrlConnection</code> level,
+    if <q>false</q>, turn caching off.<br/><strong>Note</strong> this is only a hint to the
+    underlying <code>UrlConnection</code> class, implementations and proxies are free to ignore the
+    setting.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">useragent</td>
-    <td valign="top">User-Agent HTTP header to send, starting with Ant
-      1.9.3 Ant will specify a User-Agent header of "Apache Ant VERSION"
-      unless overridden by this attribute<br/>
-      <em>since Ant 1.9.3</em></td>
-    <td align="center" valign="top">No</td>
+    <td>useragent</td>
+    <td><code>User-Agent</code> HTTP header to send.<br/><em>since Ant 1.9.3</em></td>
+    <td>No; defaults to <q>Apache Ant VERSION</q></td>
   </tr>
   <tr>
-    <td valign="top">tryGzipEncoding</td>
-    <td valign="top">When set to true Ant will tell the server it is
-      willing to accept gzip encoding to reduce the amount of data to
-      transfer and uncompress the content transparently.<br/>
-      Setting this to true also means Ant will uncompress
-      <code>.tar.gz</code> and similar files automatically.<br/>
-      <em>since Ant 1.9.5</em></td>
-    <td align="center" valign="top">No; default "false"</td>
+    <td>tryGzipEncoding</td>
+    <td>When set to <q>true</q>, Ant will tell the server it is willing to accept gzip encoding to
+      reduce the amount of data to transfer and uncompress the content transparently.<br/>Setting
+      this to <q>true</q> also means Ant will uncompress <code>.tar.gz</code> and similar files
+      automatically.<br/><em>since Ant 1.9.5</em></td>
+    <td>No; default is <q>false</q></td>
 </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 URLs to download.  If
-    the collection contains more than one resource, the dest attribute
-    must point to a directory if it exists or a directory will be
-    created if it doesn't exist.  The destination file name use the
-    last part of the path of the source URL unless you also specify a
-    mapper.</p>
+<p><a href="../Types/resources.html#collection">resource collections</a> are used to select groups
+of URLs to download.  If the collection contains more than one resource, the <var>dest</var>
+attribute must point to a directory if it exists or a directory will be created if it doesn't exist.
+The destination file name use the last part of the path of the source URL unless you also specify a
+mapper.</p>
 
 <h4>mapper</h4>
 
-<p>You can define name transformations by using a
-  nested <a href="../Types/mapper.html">mapper</a> element.  You
-  can also use any filenamemapper type in place of the mapper
-  element.</p>
+<p>You can define name transformations by using a nested <a href="../Types/mapper.html">mapper</a>
+element.  You can also use any filenamemapper type in place of the mapper element.</p>
 
-<p>The mapper will receive the resource's name as argument.  Any
-  resource for which the mapper returns no or more than one mapped
-  name will be skipped.  If the returned name is a relative path, it
-  will be considered relative to the <em>dest</em> attribute.</p>
+<p>The mapper will receive the resource's name as argument.  Any resource for which the mapper
+returns no or more than one mapped name will be skipped.  If the returned name is a relative path,
+it will be considered relative to the <var>dest</var> attribute.</p>
+
+<h4>header</h4>
+<p>Any arbitrary number of HTTP headers can be added to a request.<br/>The attributes of a
+nested <code>&lt;header/&gt;</code> node are as follows:</p>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>The name or key of this header. Cannot be null or empty. Leading and trailing spaces are
+    removed</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>The value to assign to the header. Cannot be null or empty. Leading and trailing spaces are
+    removed</td>
+    <td>Yes</td>
+  </tr>
+</table>
 
 <h3>Examples</h3>
-<pre>  &lt;get src=&quot;http://ant.apache.org/&quot; dest=&quot;help/index.html&quot;/&gt;</pre>
-<p>Gets the index page of http://ant.apache.org/, and stores it in the file <code>help/index.html</code>.</p>
 
-<pre>  &lt;get src=&quot;http://www.apache.org/dist/ant/KEYS&quot; 
-    dest=&quot;KEYS&quot; 
-    verbose=&quot;true&quot;
-    usetimestamp=&quot;true&quot;/&gt;</pre>
-<p>
-Gets the PGP keys of Ant's (current and past) release managers, if the local copy
-is missing or out of date. Uses the verbose option 
-for progress information.
-</p>
+<p>Get the index page of <samp>https://ant.apache.org/</samp>, and store it in the
+file <samp>help/index.html</samp>.</p>
+<pre>&lt;get src=&quot;https://ant.apache.org/&quot; dest=&quot;help/index.html&quot;/&gt;</pre>
 
-<pre>  &lt;get src=&quot;https://insecure-bank.org/statement/user=1214&quot; 
-    dest=&quot;statement.html&quot; 
-    username="1214";
-    password="secret"/&gt;</pre>
-<p>
-Fetches some file from a server with access control. Because https is being used the
-fact that basic auth sends passwords in plaintext is moot if you
-ignore the fact that it is part of your build file which may be
-readable by third parties.  If you need more security, consider using
-the <a href="input.html">input task</a> to query for a password.</p>
+<p>Get the PGP keys of Ant's (current and past) release managers, if the local copy is missing or
+out of date. Use the <var>verbose</var> option for progress information.</p>
+<pre>
+&lt;get src=&quot;https://www.apache.org/dist/ant/KEYS&quot;
+     dest=&quot;KEYS&quot;
+     verbose=&quot;true&quot;
+     usetimestamp=&quot;true&quot;/&gt;</pre>
+
+<p>Fetch some file from a server with access control. Because HTTPS is being used, the fact that
+basic auth sends passwords in plaintext is moot if you ignore the fact that it is part of your build
+file which may be readable by third parties.  If you need more security, consider using
+the <a href="input.html">input</a> task to query for a password.</p>
+<pre>
+&lt;get src=&quot;https://insecure-bank.org/statement/user=1214&quot;
+     dest=&quot;statement.html&quot;
+     username=&quot;1214&quot;
+     password=&quot;secret&quot;/&gt;</pre>
 
 <p>Using a macro like the following</p>
 
 <pre>
-  &lt;macrodef name="get-and-checksum">
-    &lt;attribute name="url"/>
-    &lt;attribute name="dest"/>
-    &lt;sequential&gt;
-      &lt;local name="destdir"/&gt;
-      &lt;dirname property="destdir" file="@{dest}"/&gt;
-      &lt;get dest="${destdir}"&gt;
-        &lt;url url="@{url}"/&gt;
-        &lt;url url="@{url}.sha1"/&gt;
-        &lt;firstmatchmapper&gt;
-          &lt;globmapper from="@{url}.sha1" to="@{dest}.sha"/&gt;
-          &lt;globmapper from="@{url}" to="@{dest}"/&gt;
-        &lt;/firstmatchmapper&gt;
-      &lt;/get&gt;
-      &lt;local name="checksum.matches"/>
-      &lt;local name="checksum.matches.fail"/>
-      &lt;checksum file="@{dest}" algorithm="sha" fileext=".sha"
-                verifyproperty="checksum.matches"/>
-      &lt;condition property="checksum.matches.fail">
-        &lt;equals arg1="${checksum.matches}" arg2="false"/>
-      &lt;/condition>
-      &lt;fail if="checksum.matches.fail">Checksum error&lt;/fail>
-    &lt;/sequential>
-  &lt;/macrodef>
-</pre>
+&lt;macrodef name="get-and-checksum"&gt;
+  &lt;attribute name="url"/&gt;
+  &lt;attribute name="dest"/&gt;
+  &lt;sequential&gt;
+    &lt;local name="destdir"/&gt;
+    &lt;dirname property="destdir" file="@{dest}"/&gt;
+    &lt;get dest="${destdir}"&gt;
+      &lt;url url="@{url}"/&gt;
+      &lt;url url="@{url}.sha1"/&gt;
+      &lt;firstmatchmapper&gt;
+        &lt;globmapper from="@{url}.sha1" to="@{dest}.sha"/&gt;
+        &lt;globmapper from="@{url}" to="@{dest}"/&gt;
+      &lt;/firstmatchmapper&gt;
+    &lt;/get&gt;
+    &lt;local name="checksum.matches"/&gt;
+    &lt;local name="checksum.matches.fail"/&gt;
+    &lt;checksum file="@{dest}" algorithm="sha" fileext=".sha"
+              verifyproperty="checksum.matches"/&gt;
+    &lt;condition property="checksum.matches.fail"&gt;
+      &lt;equals arg1="${checksum.matches}" arg2="false"/&gt;
+    &lt;/condition&gt;
+    &lt;fail if="checksum.matches.fail"&gt;Checksum error&lt;/fail&gt;
+  &lt;/sequential&gt;
+&lt;/macrodef&gt;</pre>
 
-<p>it is possible to download an artifacts together with its SHA1
-  checksum (assuming a certain naming convention for the checksum
-  file, of course) and validate the checksum on the fly.</p>
+<p>it is possible to download an artifacts together with its SHA1 checksum (assuming a certain
+naming convention for the checksum file, of course) and validate the checksum on the fly.</p>
 
 <pre>
 &lt;get dest=&quot;downloads&quot;&gt;
-  &lt;url url=&quot;http://ant.apache.org/index.html&quot;/&gt; 
-  &lt;url url=&quot;http://ant.apache.org/faq.html&quot;/&gt;
-&lt;/get&gt;
-</pre>
-<p>Gets the index and FAQ pages of http://ant.apache.org/, and stores
-  them in the directory <code>downloads</code> which will be created if
-  necessary.</p>
+  &lt;url url=&quot;https://ant.apache.org/index.html&quot;/&gt;
+  &lt;url url=&quot;https://ant.apache.org/faq.html&quot;/&gt;
+&lt;/get&gt;</pre>
+
+<p>Using custom HTTP headers</p>
+
+<pre>
+&lt;get src=&quot;https://ant.apache.org/index.html&quot; dest=&quot;downloads&quot;&gt;
+  &lt;header name=&quot;header1&quot; value=&quot;headerValue1&quot;/&gt;
+  &lt;header name=&quot;header2&quot; value=&quot;headerValue2&quot;/&gt;
+  &lt;header name=&quot;header3&quot; value=&quot;headerValue3&quot;/&gt;
+&lt;/get&gt;</pre>
+
+<p>get the index and FAQ pages of <samp>https://ant.apache.org/</samp>, and store them in the
+directory <samp>downloads</samp> which will be created if necessary.</p>
 </body>
 </html>
-
diff --git a/manual/Tasks/gunzip.html b/manual/Tasks/gunzip.html
index 32e2cf2..439cffd 100644
--- a/manual/Tasks/gunzip.html
+++ b/manual/Tasks/gunzip.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,16 +15,14 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>GUnZip Task</title>
 </head>
 
 <body>
-This document's new home is <A HREF="unpack.html">here</A>
+This document's new home is <a href="unpack.html">here</a>
 </body>
 </html>
-
diff --git a/manual/Tasks/gzip.html b/manual/Tasks/gzip.html
index 6054d31..481f285 100644
--- a/manual/Tasks/gzip.html
+++ b/manual/Tasks/gzip.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,16 +15,14 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>GZip Task</title>
 </head>
 
 <body>
-This document's new home is <A HREF="pack.html">here</A>
+This document's new home is <a href="pack.html">here</a>
 </body>
 </html>
-
diff --git a/manual/Tasks/hostinfo.html b/manual/Tasks/hostinfo.html
index 851b403..74962d1 100644
--- a/manual/Tasks/hostinfo.html
+++ b/manual/Tasks/hostinfo.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,85 +15,69 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>HostInfo Task</title>
 </head>
 
 <body>
 
-<h2><a name="hostinfo">HostInfo</a></h2>
+<h2 id="hostinfo">HostInfo</h2>
 
 <h3>Description</h3>
 <p>Sets the <code>NAME</code>, <code>DOMAIN</code>, <code>ADDR4</code>, and <code>ADDR6</code>
 properties in the current project.</p>
 <p>
-The <code>NAME</code> contains the host part of the canonical name of the host.<br/>
-If the host is not found, the host will contain the name as provided to the task,
-or <code>localhost</code> if no host was provided, and no name for the local
-host was found.<br/>
-The <code>DOMAIN</code> contains the domain part of the canonical name of the host.<br/>
- If the host is not found, the domain will contain the domain as provided to the task,
- or <code>localdomain</code> if no host / domain was provided.<br/>
-The <code>ADDR4</code> contains the IPv4 address of the host with the widest meaning.<br/>
-If no IPv4 address is found and a host has been provided the address <code>0.0.0.0</code> 
-is returned, when no host was provided the address <code>127.0.0.1</code> is returned.<br/>
-The <code>ADDR6</code> contains the IPv6 address of the host with the widest meaning.<br/> 
-If no IPv6 address is found and a host has been provided the address <code>::</code> 
-is returned, when no host was provided the address <code>::1</code> is returned.<br/>
-</p>
+The <code>NAME</code> contains the host part of the canonical name of the host.<br/>  If the host is
+not found, the host will contain the name as provided to the task, or <code>localhost</code> if no
+host was provided, and no name for the local host was found.<br/>The <code>DOMAIN</code> contains
+the domain part of the canonical name of the host.<br/>If the host is not found, the domain will
+contain the domain as provided to the task, or <code>localdomain</code> if no host / domain was
+provided.<br/>The <code>ADDR4</code> contains the IPv4 address of the host with the widest
+meaning.<br/>If no IPv4 address is found and a host has been provided the
+address <code>0.0.0.0</code> is returned, when no host was provided the
+address <code>127.0.0.1</code> is returned.<br/>The <code>ADDR6</code> contains the IPv6 address of
+the host with the widest meaning.<br/>If no IPv6 address is found and a host has been provided the
+address <code>::</code> is returned, when no host was provided the address <code>::1</code> is
+returned.</p>
 
-<p>These properties can be used in the build-file, for instance, to create
-host-stamped filenames, or used to replace placeholder tags inside documents
-to indicate, for example, the host where the build was performed on.
-The best place for this task is probably in an initialization target.</p>
+<p>These properties can be used in the build-file, for instance, to create host-stamped filenames,
+or used to replace placeholder tags inside documents to indicate, for example, the host where the
+build was performed on.  The best place for this task is probably in an initialization target.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">Prefix used for all properties set. The default is no prefix.</td>
-    <td align="center" valign="top">No</td>
+    <td>prefix</td>
+    <td>Prefix used for all properties set.</td>
+    <td>No; defaults to no prefix</td>
   </tr>
   <tr>
-    <td valign="top">host</td>
-    <td valign="top">
-        The host to retrieve the information for, default is to retrieve
-        information for the host the task is running on.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>host</td>
+    <td>The host to retrieve the information for.</td>
+    <td>No; default is to retrieve information for the host the task is running on</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
 
-<pre>
-  &lt;hostinfo/&gt;
-</pre>
+<p>Set the <code>NAME</code>, <code>DOMAIN</code>, <code>ADDR4</code>, and <code>ADDR6</code> for
+the local host, using the most &quot;global&quot; address available.</p>
+<pre>&lt;hostinfo/&gt;</pre>
 
-<p>
-Sets the <code>NAME</code>, <code>DOMAIN</code>, <code>ADDR4</code>, and 
-<code>ADDR6</code> for the local host, using the most &quot;global&quot; address
-available.</p>
-<pre>
-  &lt;hostinfo prefix=&quot;remotehost&quot; host=&quot;www.apache.org&quot;/&gt;
-</pre>
-<p>
-Sets the properties <code>remotehost.NAME</code> to <code>eos</code>, 
-<code>remotehost.DOMAIN</code> to <code>apache.org</code>, 
-<code>remotehost.ADDR4</code> to <code>140.211.11.130</code> and 
-<code>remotehost.ADDR6</code> to <code>::</code>
-for the host with the name www.apache.org (provided the canonical name and ip 
-addresses do not change).
-</p>
+<p>Set the properties <code>remotehost.NAME</code>
+to <samp>eos</samp>, <code>remotehost.DOMAIN</code>
+to <samp>apache.org</samp>, <code>remotehost.ADDR4</code> to <samp>140.211.11.130</samp>
+and <code>remotehost.ADDR6</code> to <samp>::</samp> for the host with the
+name <samp>www.apache.org</samp> (provided the canonical name and IP addresses do not change).</p>
+<pre>&lt;hostinfo prefix=&quot;remotehost&quot; host=&quot;www.apache.org&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/image.graphml b/manual/Tasks/image.graphml
new file mode 100644
index 0000000..cdc2521
--- /dev/null
+++ b/manual/Tasks/image.graphml
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+   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
+
+       https://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.
+-->
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
+  <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
+  <key for="port" id="d1" yfiles.type="portgraphics"/>
+  <key for="port" id="d2" yfiles.type="portgeometry"/>
+  <key for="port" id="d3" yfiles.type="portuserdata"/>
+  <key attr.name="url" attr.type="string" for="node" id="d4"/>
+  <key attr.name="description" attr.type="string" for="node" id="d5"/>
+  <key for="node" id="d6" yfiles.type="nodegraphics"/>
+  <key for="graphml" id="d7" yfiles.type="resources"/>
+  <key for="edge" id="d8" yfiles.type="portconstraints"/>
+  <key attr.name="url" attr.type="string" for="edge" id="d9"/>
+  <key attr.name="description" attr.type="string" for="edge" id="d10"/>
+  <key for="edge" id="d11" yfiles.type="edgegraphics"/>
+  <graph edgedefault="directed" id="G">
+    <data key="d0" xml:space="preserve"/>
+    <node id="n0">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="47.0" width="245.0" x="207.5" y="-113.12162162162163"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="234.9150390625" x="5.04248046875" xml:space="preserve" y="3.0">org.apache.tools.ant.types.DataType<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve"> </y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n1">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="119.51351351351354" width="155.85546875" x="252.0" y="0.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="105.10546875" x="25.375" xml:space="preserve" y="3.0">ImageOperation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">instructions : Vector</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve">addRotate(Rotate : instr)
+addDraw(Draw : instr)
+addText(Text : instr)
+addScale(Scale : instr)</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n2">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="105.0" width="260.55078125" x="-419.1051056860584" y="469.59294436906373"/>
+          <y:Fill hasColor="false" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="left" autoSizePolicy="content" fontFamily="SansSerif" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="88.796875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="250.55078125" x="5.0" xml:space="preserve" y="8.1015625">The setType() method forces type to
+one of the values of java.awt.geom.Arc2D:
+open = Arc2D.OPEN
+pie = Arc2D.PIE
+chord = Arc2D.CHORD
+Parameter is not case-sensitive.<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n3">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="88.0" width="168.0" x="-24.0" y="106.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="sides" modelPosition="n" textColor="#000000" verticalTextPosition="bottom" visible="true" width="73.37353515625" x="47.313232421875" xml:space="preserve" y="3.0">BasicShape</y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">stroke_width : int = 0
+fill : String = "transparent"
+stroke : String = "black"</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n4">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="76.0" width="366.0" x="537.0" y="105.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="sides" modelPosition="n" textColor="#000000" verticalTextPosition="bottom" visible="true" width="132.33056640625" x="116.834716796875" xml:space="preserve" y="3.0">TransformOperation</y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve">executeTransformOperation(PlanarImage img) : PlanarImage
+addRectangle(Rectangle instr)</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n5">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="83.94054054054055" width="237.505859375" x="209.59510287695048" y="478.2061205031355"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="98.9482421875" x="69.27880859375" xml:space="preserve" y="26.1328125">DrawOperation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="interface" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve">executeDrawOperation() : PlanarImage</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n6">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="75.75675675675677" width="216.060546875" x="220.31775912695048" y="635.8665334262349"/>
+          <y:Fill hasColor="false" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="left" autoSizePolicy="content" fontFamily="SansSerif" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="60.53125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="206.060546875" x="5.0" xml:space="preserve" y="7.612753378378443">The implementing class uses
+ColorMapper to evaluate the color.
+Only the values defined in
+ColorMapper are used.<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n7">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="271.4234234234233" width="251.275390625" x="562.7103372519505" y="541.3371349640008"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="85.34521484375" x="82.965087890625" xml:space="preserve" y="3.0">ColorMapper<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">COLOR_BLACK : String = "black"
+COLOR_BLUE : String = "blue"
+COLOR_CYAN : String = "cyan"
+COLOR_DARKGRAY : String = "darkgray"
+COLOR_GRAY : String = "gray"
+COLOR_LIGHTGRAY : String = "lightgray"
+COLOR_DARKGREY : String = "darkgrey"
+COLOR_GREY : String = "grey"
+COLOR_LIGHTGREY : String = "lightgrey"
+COLOR_GREEN : String = "green"
+COLOR_MAGENTA : String = "magenta"
+COLOR_ORANGE : String = "orange"
+COLOR_PINK : String = "pink"
+COLOR_RED : String = "red"
+COLOR_WHITE : String = "white"
+COLOR_YELLOW : String = "yellow"</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n8">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="130.0" width="146.0" x="257.0" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="32.2978515625" x="56.85107421875" xml:space="preserve" y="3.0">Text<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">string : String = ""
+font : String = "Arial"
+point : int = 10
+bold : boolean = false
+color : String = "black"
+italic : boolean = false</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n9">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="59.0" width="126.0" x="447.0" y="271.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="44.35205078125" x="40.823974609375" xml:space="preserve" y="3.0">Rotate<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">angle : float = 0.0F</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n10">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="88.0" width="212.0" x="614.0" y="271.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="35.83984375" x="88.080078125" xml:space="preserve" y="3.0">Scale<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">width : String = "100%"
+height : String = "100%"
+keepProportions : boolean = false</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n11">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="104.0" width="142.0" x="874.0" y="270.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.25244140625" x="52.873779296875" xml:space="preserve" y="3.0">Draw<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">xloc : int = 0
+yloc : int = 0</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve">addEllipse(Ellipse elip)
+addArc(Arc arc)</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n12">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="102.0" width="120.0" x="3.168249660787012" y="272.5"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.33740234375" x="27.331298828125" xml:space="preserve" y="3.0">Rectangle<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">height : int = 0
+width : int = 0
+archeight : int = 0
+arcwidth : int = 0</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n13">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="74.0" width="120.0" x="-165.13229308005424" y="270.8783783783784"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="44.37109375" x="37.814453125" xml:space="preserve" y="3.0">Ellipse<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">height : int = 0
+width : int = 0</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n14">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="115.0" width="167.0" x="-375.3690637720489" y="270.5"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="24.947265625" x="71.0263671875" xml:space="preserve" y="3.0">Arc<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">height : int = 0
+width : int = 0
+start : int = 0
+stop : int = 0
+type : enumerated = open</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <edge id="e0" source="n1" target="n0">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.11753822740667" xml:space="preserve" y="-42.11074086736787"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e1" source="n3" target="n1">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="50.41847892259207" xml:space="preserve" y="4.406343693110614"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e2" source="n4" target="n1">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="30.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-60.071704848044874" xml:space="preserve" y="-56.61291038197166"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e3" source="n5" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-71.15174118848563" xml:space="preserve" y="-152.95377159050008"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e4" source="n5" target="n9">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="94.22024485236568" xml:space="preserve" y="-80.64710502773585"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e5" source="n5" target="n10">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="140.61508526079365" xml:space="preserve" y="-50.905946341704976"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e6" source="n9" target="n4">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="81.36808268229174" xml:space="preserve" y="-35.51629638671875"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e7" source="n10" target="n4">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.1015625" xml:space="preserve" y="-54.1005859375"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e8" source="n11" target="n4">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-17.583335869279836" xml:space="preserve" y="-58.28909731112401"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e9" source="n8" target="n1">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.08168461626724" xml:space="preserve" y="-85.2969236631651"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e10" source="n5" target="n8">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.446206886230925" xml:space="preserve" y="-47.146909230854135"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e11" source="n6" target="n5">
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#808080" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.101572603512977" xml:space="preserve" y="-45.90001897598199"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e12" source="n7" target="n6">
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#808080" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-67.06248989648702" xml:space="preserve" y="-39.64733927051532"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e13" source="n2" target="n14">
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#808080" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="25.446152710310912" xml:space="preserve" y="-51.156591780311885"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e14" source="n14" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="-50.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="160.70285069869294" xml:space="preserve" y="-37.02040127821758"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e15" source="n13" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="61.78918119362366" xml:space="preserve" y="-30.36348007332839"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e16" source="n12" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="25.390592784586175" xml:space="preserve" y="-48.2745361328125"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+  </graph>
+  <data key="d7">
+    <y:Resources/>
+  </data>
+</graphml>
diff --git a/manual/Tasks/image.html b/manual/Tasks/image.html
index 077b372..58b0bc0 100644
--- a/manual/Tasks/image.html
+++ b/manual/Tasks/image.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,248 +15,570 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Image Task</title>
 </head>
 
 <body>
 
-<h2><a name="image">Image</a></h2>
+<h2 id="image">Image</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>, because Java Advanced Image API depends on internal
+classes which were removed in Java 9. Use the <code>ImageIO</code> task instead.</em></p>
 <h3>Description</h3>
 <p>Applies a chain of image operations on a set of files.</p>
 <p>Requires <a href="../install.html#librarydependencies">Java Advanced Image API</a> from Sun.</p>
 
 <h5>Overview of used datatypes</h5>
-<img src="image-classdiagram.gif" border="0" alt="Class-Diagram">
-
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill-opacity="1"
+     color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black"
+     stroke-linecap="square" viewBox="0 0 1446 937" stroke-miterlimit="10" shape-rendering="auto"
+     stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1"
+     font-family="Sans-Serif" font-style="normal" stroke-linejoin="miter" font-size="12px" role="img"
+     stroke-dashoffset="0" image-rendering="auto" aria-labelledby="diagramTitle diagramDescription">
+  <title id="diagramTitle">ImageOperation class diagram</title>
+  <desc id="diagramDescription">A diagram of Ant DataType classes used by Image task.</desc>
+  <defs id="genericDefs"/>
+  <g>
+    <defs id="defs1">
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath1">
+        <path d="M0 0 L1446 0 L1446 937 L0 937 L0 0 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
+        <path d="M-425 -119 L1021 -119 L1021 818 L-425 818 L-425 -119 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath3">
+        <path d="M207 -113 L207 -66 L452 -66 L452 -113 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath4">
+        <path d="M252 0 L252 119 L407 119 L407 0 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath5">
+        <path d="M-24 106 L-24 194 L144 194 L144 106 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath6">
+        <path d="M537 105 L537 181 L903 181 L903 105 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath7">
+        <path d="M209 478 L209 561 L446 561 L446 478 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath8">
+        <path d="M562 541 L562 812 L813 812 L813 541 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath9">
+        <path d="M257 272 L257 402 L403 402 L403 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath10">
+        <path d="M447 271 L447 330 L573 330 L573 271 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath11">
+        <path d="M614 271 L614 359 L826 359 L826 271 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath12">
+        <path d="M874 270 L874 374 L1016 374 L1016 270 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath13">
+        <path d="M3 272 L3 374 L123 374 L123 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath14">
+        <path d="M-165 270 L-165 344 L-45 344 L-45 270 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath15">
+        <path d="M-375 270 L-375 385 L-208 385 L-208 270 Z"/>
+      </clipPath>
+    </defs>
+    <g fill="rgb(255,204,153)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)" stroke="rgb(255,204,153)">
+      <rect x="208" width="243" height="45" y="-112" clip-path="url(#clipPath2)" stroke="none"/>
+    </g>
+    <g fill="rgb(255,255,218)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)" stroke="rgb(255,255,218)">
+      <rect x="207" width="1" height="47" y="-113" clip-path="url(#clipPath2)" stroke="none"/>
+      <rect x="208" width="243" height="1" y="-113" clip-path="url(#clipPath2)" stroke="none"/>
+      <rect x="208" y="-67" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="244" height="1" stroke="none"/>
+      <rect x="451" y="-113" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="46" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="214.5425" xml:space="preserve" y="-95.5533" clip-path="url(#clipPath3)" stroke="none">org.apache.tools.ant.types.DataType</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="-87" fill="none" x1="208" clip-path="url(#clipPath3)" x2="451" y1="-87"/>
+      <line y2="-77" fill="none" x1="208" clip-path="url(#clipPath3)" x2="451" y1="-77"/>
+      <text stroke-linecap="butt" x="212.5" y="-61.2095" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve"> </text>
+      <rect x="253" y="1" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="153" height="117" stroke="none"/>
+      <rect x="252" y="0" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="119" stroke="none"/>
+      <rect x="253" y="0" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="153" height="1" stroke="none"/>
+      <rect x="253" y="118" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="154" height="1" stroke="none"/>
+      <rect x="406" y="0" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="118" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="279.375" xml:space="preserve" y="17.5684" clip-path="url(#clipPath4)" stroke="none">ImageOperation</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="25" fill="none" x1="253" clip-path="url(#clipPath4)" x2="406" y1="25"/>
+      <text stroke-linecap="butt" x="257" y="41.9121" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">instructions : Vector</text>
+      <line y2="49" fill="none" x1="253" clip-path="url(#clipPath4)" x2="406" y1="49"/>
+      <text stroke-linecap="butt" x="257" y="66.0449" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addRotate(Rotate : instr)</text>
+      <text stroke-linecap="butt" x="257" y="80.1777" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addDraw(Draw : instr)</text>
+      <text stroke-linecap="butt" x="257" y="94.3105" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addText(Text : instr)</text>
+      <text stroke-linecap="butt" x="257" y="108.4434" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addScale(Scale : instr)</text>
+      <path fill="none" stroke-miterlimit="1.45" d="M-419.1051 469.593 L-173.5543 469.593 L-173.5543 484.593 L-158.5543 484.593 L-158.5543 574.593 L-419.1051 574.593 Z" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <path fill="none" stroke-miterlimit="1.45" d="M-173.5543 469.593 L-173.5543 484.593 L-158.5543 484.593 Z" fill-rule="evenodd" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <text stroke-linecap="butt" x="-412.1051" y="491.2961" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">The setType() method forces type to</text>
+      <text stroke-linecap="butt" x="-412.1051" y="505.4289" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">one of the values of java.awt.geom.Arc2D:</text>
+      <text stroke-linecap="butt" x="-412.1051" y="519.5617" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">open = Arc2D.OPEN</text>
+      <text stroke-linecap="butt" x="-412.1051" y="533.6945" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">pie = Arc2D.PIE</text>
+      <text stroke-linecap="butt" x="-412.1051" y="547.8273" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">chord = Arc2D.CHORD</text>
+      <text stroke-linecap="butt" x="-412.1051" y="561.9601" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">Parameter is not case-sensitive.</text>
+      <rect x="-23" y="107" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="166" height="86" stroke="none"/>
+      <rect x="-24" y="106" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="88" stroke="none"/>
+      <rect x="-23" y="106" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="166" height="1" stroke="none"/>
+      <rect x="-23" y="193" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="167" height="1" stroke="none"/>
+      <rect x="143" y="106" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="87" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="25.3132" xml:space="preserve" y="123.5684" clip-path="url(#clipPath5)" stroke="none">BasicShape</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="131" fill="none" x1="-23" clip-path="url(#clipPath5)" x2="143" y1="131"/>
+      <text stroke-linecap="butt" x="-19" y="147.9121" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">stroke_width : int = 0</text>
+      <text stroke-linecap="butt" x="-19" y="162.0449" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">fill : String = "transparent"</text>
+      <text stroke-linecap="butt" x="-19" y="176.1777" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">stroke : String = "black"</text>
+      <line y2="183" fill="none" x1="-23" clip-path="url(#clipPath5)" x2="143" y1="183"/>
+      <rect x="538" y="106" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="364" height="74" stroke="none"/>
+      <rect x="537" y="105" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="76" stroke="none"/>
+      <rect x="538" y="105" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="364" height="1" stroke="none"/>
+      <rect x="538" y="180" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="365" height="1" stroke="none"/>
+      <rect x="902" y="105" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="75" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="655.8347" xml:space="preserve" y="122.5684" clip-path="url(#clipPath6)" stroke="none">TransformOperation</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="130" fill="none" x1="538" clip-path="url(#clipPath6)" x2="902" y1="130"/>
+      <line y2="140" fill="none" x1="538" clip-path="url(#clipPath6)" x2="902" y1="140"/>
+      <text stroke-linecap="butt" x="542" y="156.9121" clip-path="url(#clipPath6)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">executeTransformOperation(PlanarImage img) : PlanarImage</text>
+      <text stroke-linecap="butt" x="542" y="171.0449" clip-path="url(#clipPath6)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addRectangle(Rectangle instr)</text>
+      <rect x="210" y="479" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="235" height="81" stroke="none"/>
+      <rect x="209" y="478" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="83" stroke="none"/>
+      <rect x="210" y="478" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="235" height="1" stroke="none"/>
+      <rect x="210" y="560" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="236" height="1" stroke="none"/>
+      <rect x="445" y="478" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="82" stroke="none"/>
+      <text stroke-linecap="butt" x="283.8344" y="494.8077" clip-path="url(#clipPath7)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">&lt;&lt;interface&gt;&gt;</text>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="280.8739" xml:space="preserve" y="518.9073" clip-path="url(#clipPath7)" stroke="none">DrawOperation</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="526" fill="none" x1="210" clip-path="url(#clipPath7)" x2="446" y1="526"/>
+      <line y2="536" fill="none" x1="210" clip-path="url(#clipPath7)" x2="446" y1="536"/>
+      <text stroke-linecap="butt" x="214.5951" y="553.251" clip-path="url(#clipPath7)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">executeDrawOperation() : PlanarImage</text>
+      <path fill="none" stroke-miterlimit="1.45" d="M220.3178 635.8665 L421.3783 635.8665 L421.3783 650.8665 L436.3783 650.8665 L436.3783 711.6233 L220.3178 711.6233 Z" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <path fill="none" stroke-miterlimit="1.45" d="M421.3783 635.8665 L421.3783 650.8665 L436.3783 650.8665 Z" fill-rule="evenodd" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <text stroke-linecap="butt" x="227.3178" y="657.0809" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">The implementing class uses</text>
+      <text stroke-linecap="butt" x="227.3178" y="671.2137" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">ColorMapper to evaluate the color.</text>
+      <text stroke-linecap="butt" x="227.3178" y="685.3465" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">Only the values defined in</text>
+      <text stroke-linecap="butt" x="227.3178" y="699.4793" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">ColorMapper are used.</text>
+      <rect x="563" y="542" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="249" height="269" stroke="none"/>
+      <rect x="562" y="541" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="271" stroke="none"/>
+      <rect x="563" y="541" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="249" height="1" stroke="none"/>
+      <rect x="563" y="811" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="250" height="1" stroke="none"/>
+      <rect x="812" y="541" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="270" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="647.6754" xml:space="preserve" y="558.9055" clip-path="url(#clipPath8)" stroke="none">ColorMapper</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="566" fill="none" x1="563" clip-path="url(#clipPath8)" x2="812" y1="566"/>
+      <text stroke-linecap="butt" x="567.7103" y="583.2493" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_BLACK : String = "black"</text>
+      <text stroke-linecap="butt" x="567.7103" y="597.3821" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_BLUE : String = "blue"</text>
+      <text stroke-linecap="butt" x="567.7103" y="611.5149" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_CYAN : String = "cyan"</text>
+      <text stroke-linecap="butt" x="567.7103" y="625.6477" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_DARKGRAY : String = "darkgray"</text>
+      <text stroke-linecap="butt" x="567.7103" y="639.7805" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_GRAY : String = "gray"</text>
+      <text stroke-linecap="butt" x="567.7103" y="653.9133" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_LIGHTGRAY : String = "lightgray"</text>
+      <text stroke-linecap="butt" x="567.7103" y="668.0461" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_DARKGREY : String = "darkgrey"</text>
+      <text stroke-linecap="butt" x="567.7103" y="682.179" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_GREY : String = "grey"</text>
+      <text stroke-linecap="butt" x="567.7103" y="696.3118" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_LIGHTGREY : String = "lightgrey"</text>
+      <text stroke-linecap="butt" x="567.7103" y="710.4446" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_GREEN : String = "green"</text>
+      <text stroke-linecap="butt" x="567.7103" y="724.5774" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_MAGENTA : String = "magenta"</text>
+      <text stroke-linecap="butt" x="567.7103" y="738.7102" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_ORANGE : String = "orange"</text>
+      <text stroke-linecap="butt" x="567.7103" y="752.843" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_PINK : String = "pink"</text>
+      <text stroke-linecap="butt" x="567.7103" y="766.9758" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_RED : String = "red"</text>
+      <text stroke-linecap="butt" x="567.7103" y="781.1086" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_WHITE : String = "white"</text>
+      <text stroke-linecap="butt" x="567.7103" y="795.2415" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_YELLOW : String = "yellow"</text>
+      <line y2="802" fill="none" x1="563" clip-path="url(#clipPath8)" x2="812" y1="802"/>
+      <rect x="258" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="144" height="128" stroke="none"/>
+      <rect x="257" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="130" stroke="none"/>
+      <rect x="258" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="144" height="1" stroke="none"/>
+      <rect x="258" y="401" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="145" height="1" stroke="none"/>
+      <rect x="402" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="129" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="315.8511" xml:space="preserve" y="289.5684" clip-path="url(#clipPath9)" stroke="none">Text</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="297" fill="none" x1="258" clip-path="url(#clipPath9)" x2="402" y1="297"/>
+      <text stroke-linecap="butt" x="262" y="313.9121" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">string : String = ""</text>
+      <text stroke-linecap="butt" x="262" y="328.0449" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">font : String = "Arial"</text>
+      <text stroke-linecap="butt" x="262" y="342.1777" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">point : int = 10</text>
+      <text stroke-linecap="butt" x="262" y="356.3105" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">bold : boolean = false</text>
+      <text stroke-linecap="butt" x="262" y="370.4434" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">color : String = "black"</text>
+      <text stroke-linecap="butt" x="262" y="384.5762" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">italic : boolean = false</text>
+      <line y2="392" fill="none" x1="258" clip-path="url(#clipPath9)" x2="402" y1="392"/>
+      <rect x="448" y="272" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="124" height="57" stroke="none"/>
+      <rect x="447" y="271" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="59" stroke="none"/>
+      <rect x="448" y="271" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="124" height="1" stroke="none"/>
+      <rect x="448" y="329" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="125" height="1" stroke="none"/>
+      <rect x="572" y="271" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="58" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="489.824" xml:space="preserve" y="288.5684" clip-path="url(#clipPath10)" stroke="none">Rotate</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="296" fill="none" x1="448" clip-path="url(#clipPath10)" x2="572" y1="296"/>
+      <text stroke-linecap="butt" x="452" y="312.9121" clip-path="url(#clipPath10)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">angle : float = 0.0F</text>
+      <line y2="320" fill="none" x1="448" clip-path="url(#clipPath10)" x2="572" y1="320"/>
+      <rect x="615" y="272" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="210" height="86" stroke="none"/>
+      <rect x="614" y="271" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="88" stroke="none"/>
+      <rect x="615" y="271" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="210" height="1" stroke="none"/>
+      <rect x="615" y="358" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="211" height="1" stroke="none"/>
+      <rect x="825" y="271" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="87" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="704.0801" xml:space="preserve" y="288.5684" clip-path="url(#clipPath11)" stroke="none">Scale</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="296" fill="none" x1="615" clip-path="url(#clipPath11)" x2="825" y1="296"/>
+      <text stroke-linecap="butt" x="619" y="312.9121" clip-path="url(#clipPath11)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">width : String = "100%"</text>
+      <text stroke-linecap="butt" x="619" y="327.0449" clip-path="url(#clipPath11)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">height : String = "100%"</text>
+      <text stroke-linecap="butt" x="619" y="341.1777" clip-path="url(#clipPath11)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">keepProportions : boolean = false</text>
+      <line y2="348" fill="none" x1="615" clip-path="url(#clipPath11)" x2="825" y1="348"/>
+      <rect x="875" y="271" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="140" height="102" stroke="none"/>
+      <rect x="874" y="270" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="104" stroke="none"/>
+      <rect x="875" y="270" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="140" height="1" stroke="none"/>
+      <rect x="875" y="373" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="141" height="1" stroke="none"/>
+      <rect x="1015" y="270" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="103" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="928.8738" xml:space="preserve" y="287.5684" clip-path="url(#clipPath12)" stroke="none">Draw</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="295" fill="none" x1="875" clip-path="url(#clipPath12)" x2="1015" y1="295"/>
+      <text stroke-linecap="butt" x="879" y="311.9121" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">xloc : int = 0</text>
+      <text stroke-linecap="butt" x="879" y="326.0449" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">yloc : int = 0</text>
+      <line y2="333" fill="none" x1="875" clip-path="url(#clipPath12)" x2="1015" y1="333"/>
+      <text stroke-linecap="butt" x="879" y="350.1777" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addEllipse(Ellipse elip)</text>
+      <text stroke-linecap="butt" x="879" y="364.3105" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addArc(Arc arc)</text>
+      <rect x="4" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="118" height="100" stroke="none"/>
+      <rect x="3" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="102" stroke="none"/>
+      <rect x="4" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="118" height="1" stroke="none"/>
+      <rect x="4" y="373" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="119" height="1" stroke="none"/>
+      <rect x="122" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="101" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="32.4995" xml:space="preserve" y="290.0684" clip-path="url(#clipPath13)" stroke="none">Rectangle</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="297" fill="none" x1="4" clip-path="url(#clipPath13)" x2="122" y1="297"/>
+      <text stroke-linecap="butt" x="8.1683" y="314.4121" clip-path="url(#clipPath13)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">height : int = 0</text>
+      <text stroke-linecap="butt" x="8.1683" y="328.5449" clip-path="url(#clipPath13)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">width : int = 0</text>
+      <text stroke-linecap="butt" x="8.1683" y="342.6777" clip-path="url(#clipPath13)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">archeight : int = 0</text>
+      <text stroke-linecap="butt" x="8.1683" y="356.8105" clip-path="url(#clipPath13)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">arcwidth : int = 0</text>
+      <line y2="364" fill="none" x1="4" clip-path="url(#clipPath13)" x2="122" y1="364"/>
+      <rect x="-164" y="271" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="118" height="72" stroke="none"/>
+      <rect x="-165" y="270" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="74" stroke="none"/>
+      <rect x="-164" y="270" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="118" height="1" stroke="none"/>
+      <rect x="-164" y="343" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="119" height="1" stroke="none"/>
+      <rect x="-46" y="270" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="73" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="-125.3178" xml:space="preserve" y="288.4467" clip-path="url(#clipPath14)" stroke="none">Ellipse</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="296" fill="none" x1="-164" clip-path="url(#clipPath14)" x2="-46" y1="296"/>
+      <text stroke-linecap="butt" x="-160.1323" y="312.7905" clip-path="url(#clipPath14)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">height : int = 0</text>
+      <text stroke-linecap="butt" x="-160.1323" y="326.9233" clip-path="url(#clipPath14)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">width : int = 0</text>
+      <line y2="334" fill="none" x1="-164" clip-path="url(#clipPath14)" x2="-46" y1="334"/>
+      <rect x="-374" y="271" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="165" height="113" stroke="none"/>
+      <rect x="-375" y="270" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="115" stroke="none"/>
+      <rect x="-374" y="270" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="165" height="1" stroke="none"/>
+      <rect x="-374" y="384" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="166" height="1" stroke="none"/>
+      <rect x="-209" y="270" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="114" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="-302.3427" xml:space="preserve" y="288.0684" clip-path="url(#clipPath15)" stroke="none">Arc</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,425,119)">
+      <line y2="295" fill="none" x1="-374" clip-path="url(#clipPath15)" x2="-209" y1="295"/>
+      <text stroke-linecap="butt" x="-370.369" y="312.4121" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">height : int = 0</text>
+      <text stroke-linecap="butt" x="-370.369" y="326.5449" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">width : int = 0</text>
+      <text stroke-linecap="butt" x="-370.369" y="340.6777" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">start : int = 0</text>
+      <text stroke-linecap="butt" x="-370.369" y="354.8105" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">stop : int = 0</text>
+      <text stroke-linecap="butt" x="-370.369" y="368.9434" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">type : enumerated = open</text>
+      <line y2="376" fill="none" x1="-374" clip-path="url(#clipPath15)" x2="-209" y1="376"/>
+      <path fill="none" stroke-miterlimit="1.45" d="M329.9567 -0.0165 L329.9814 -51.1265" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+    </g>
+    <g stroke-linecap="butt" transform="matrix(1,0,0,1,425,119)" fill="white" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" stroke="white" stroke-miterlimit="1.45">
+      <path d="M329.9886 -66.1265 L323.9809 -50.1294 L335.9809 -50.1236 Z" stroke="none" clip-path="url(#clipPath2)"/>
+      <path fill="none" d="M329.9886 -66.1265 L323.9809 -50.1294 L335.9809 -50.1236 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="358.0742" xml:space="preserve" y="-28.5257" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M143.99 121.9202 L237.7586 90.5711" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M251.9846 85.815 L234.9077 85.1978 L238.7126 96.5786 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M251.9846 85.815 L234.9077 85.1978 L238.7126 96.5786 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="196.4084" xml:space="preserve" y="139.9281" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M537.0108 119.8758 L422.2672 86.5641" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M407.8619 82.3821 L421.5547 92.605 L424.9003 81.0808 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M407.8619 82.3821 L421.5547 92.605 L424.9003 81.0808 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="478.9391" xml:space="preserve" y="76.8644" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M297.9329 478.2198 L91.9199 194.0324" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="228.7811" xml:space="preserve" y="338.8676" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" stroke-dasharray="6,2" d="M328.348 635.8402 L328.348 562.1666" clip-path="url(#clipPath2)" stroke="gray"/>
+      <text fill="black" x="356.4496" xml:space="preserve" y="603.5417" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" stroke-dasharray="6,2" d="M562.7084 675.8958 L436.4021 674.7366" clip-path="url(#clipPath2)" stroke="gray"/>
+      <text fill="black" x="497.6459" xml:space="preserve" y="649.85" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M328.7267 478.1836 L329.414 401.9734" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="357.1729" xml:space="preserve" y="444.6382" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M329.9831 271.9873 L329.9472 134.5243" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M329.9433 119.5243 L323.9475 135.5259 L335.9475 135.5227 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M329.9433 119.5243 L323.9475 135.5259 L335.9475 135.5227 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="358.0648" xml:space="preserve" y="200.2919" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M363.0508 478.2094 L485.6221 329.9808" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="459.2711" xml:space="preserve" y="411.1639" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M549.3494 270.988 L657.3173 190.0121" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M669.3173 181.0121 L652.9172 185.8121 L660.1172 195.412 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M669.3173 181.0121 L652.9172 185.8121 L660.1172 195.412 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="632.7175" xml:space="preserve" y="249.0732" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M408.4521 478.2119 L635.9901 359.0106" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="551.0673" xml:space="preserve" y="440.9075" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M720 271.0342 L720 195.9789" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M720 180.9789 L714 196.9789 L726 196.9789 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M720 180.9789 L714 196.9789 L726 196.9789 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="748.1016" xml:space="preserve" y="230.5352" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M879.6588 270.0175 L779.488 190.326" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M767.7495 180.9874 L776.5351 195.6439 L784.0059 186.2532 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M767.7495 180.9874 L776.5351 195.6439 L784.0059 186.2532 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="864.0755" xml:space="preserve" y="225.3299" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M62.2362 272.4581 L61.077 208.976" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M60.8031 193.9785 L55.0962 210.0854 L67.0942 209.8663 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M60.8031 193.9785 L55.0962 210.0854 L67.0942 209.8663 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="89.6268" xml:space="preserve" y="237.7852" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M-66.4496 270.8949 L3.1286 204.3732" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M13.9706 194.0074 L-1.7406 200.7274 L6.5521 209.4011 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M13.9706 194.0074 L-1.7406 200.7274 L6.5521 209.4011 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="-2.6604" xml:space="preserve" y="254.133" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" stroke-dasharray="6,2" d="M-289.6512 469.6367 L-290.9686 385.5053" clip-path="url(#clipPath2)" stroke="gray"/>
+      <text fill="black" x="-262.205" xml:space="preserve" y="432.0816" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M-271.2088 270.4844 L-38.071 185.6754" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M-23.9747 180.5476 L-41.0619 180.3788 L-36.9596 191.6558 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M-23.9747 180.5476 L-41.0619 180.3788 L-36.9596 191.6558 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="-108.5059" xml:space="preserve" y="247.0655" clip-path="url(#clipPath2)" stroke="none"> </text>
+    </g>
+  </g>
+</svg>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top"> failonerror </td>
-    <td valign="top"> Boolean value. If false, note errors to the output but keep going. </td>
-    <td align="center"> no (defaults to <i>true</i>) </td>
+    <td>failonerror</td>
+    <td>Boolean value. If <q>false</q>, note errors to the output but keep going.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top"> srcdir </td>
-    <td valign="top"> Directory containing the images. </td>
-    <td align="center"> yes, unless nested fileset is used </td>
+    <td>srcdir</td>
+    <td>Directory containing the images.</td>
+    <td>Yes, unless nested fileset is used</td>
   </tr>
   <tr>
-    <td valign="top"> encoding </td>
-    <td valign="top"> Image encoding type. <br>
-      Valid (caseinsensitive) are: jpg, jpeg, tif, tiff
+    <td>encoding</td>
+    <td>Image encoding type.<br/>Valid (case insensitive)
+      are: <q>jpg</q>, <q>jpeg</q>, <q>tif</q>, <q>tiff</q>
     </td>
-    <td align="center"> no (defaults to <i>JPEG</i>) </td>
+    <td>No; defaults to <q>jpeg</q></td>
   </tr>
   <tr>
-    <td valign="top"> overwrite </td>
-    <td valign="top"> Boolean value. Sets whether or not to overwrite
-      a file if there is naming conflict.
-    </td>
-    <td align="center"> no (defaults to <i>false</i>) </td>
+    <td>overwrite</td>
+    <td>Boolean value. Sets whether or not to overwrite a file if there is naming conflict.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top"> gc </td>
-    <td valign="top"> Boolean value. Enables garbage collection after
-      each image processed.
-    </td>
-    <td align="center"> no (defaults to <i>false</i>) </td>
+    <td>gc</td>
+    <td>Boolean value. Enables garbage collection after each image processed.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top"> destdir </td>
-    <td valign="top"> Directory where the result images are stored. </td>
-    <td align="center"> no (defaults to value of <i>srcdir</i>) </td>
+    <td>destdir</td>
+    <td>Directory where the result images are stored.</td>
+    <td>No; defaults to value of <var>srcdir</var></td>
   </tr>
   <!-- attributes inherited from MatchingTask -->
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top"> excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top"> caseSensitive </td>
-    <td valign="top"> Boolean value. Sets case sensitivity of the file system. </td>
-    <td align="center"> no (defaults to <i>false</i>) </td>
+    <td>caseSensitive</td>
+    <td>Boolean value. Sets case sensitivity of the file system.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top"> followSymlinks </td>
-    <td valign="top"> Boolean value. Sets whether or not symbolic links should be followed. </td>
-    <td align="center"> no (defaults to <i>true</i>) </td>
+    <td>followSymlinks</td>
+    <td>Boolean value. Sets whether or not symbolic links should be followed.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code> as well as the
-nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
 
-
-<h4>ImageOperation</h4>
-<p>Adds an ImageOperation to chain.</p>
-<h5>Nested Elements</h5>
-ImageOperation can handle nested Rotate, Draw, Rectangle, Text and Scale objects.
+<p>The following ImageOperation objects can be specified as nested
+elements: <code>Rotate</code>, <code>Scale</code> and <code>Draw</code>.</p>
 
 <h4>Rotate</h4>
 <p>Adds a Rotate ImageOperation to chain.</p>
 <h5>Parameters</h5>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top"> angle </td>
-    <td valign="top"> Float value. Sets the angle of rotation in degrees. </td>
-    <td align="center"> no (defaults to <i>0.0F</i>) </td>
+    <td>angle</td>
+    <td>Float value. Sets the angle of rotation in degrees.</td>
+    <td>No; defaults to <q>0.0F</q></td>
   </tr>
 </table>
 
 <h4>Scale</h4>
 <p>Adds a Scale ImageOperation to chain.</p>
 <h5>Parameters</h5>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <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>
-    <td valign="top"> proportions </td>
-    <td valign="top"> Sets which dimension to control proportions from. Valid values are:<ul>
-        <li>&quot;ignore&quot; -  treat the dimensions independently.</li>
-        <li>&quot;height&quot; - keep proportions based on the width.</li>
-        <li>&quot;width&quot; - keep proportions based on the height.</li>
-        <li>&quot;cover&quot; - keep proportions and fit in the supplied dimensions.</li>
-        <li>&quot;fit&quot; - keep proportions and cover the supplied dimensions.</li>
-    </ul></td>
-    <td align="center"> no (defaults to <i>ignore</i>) </td>
-  <tr>
-    <td valign="top"> width </td>
-    <td valign="top"> Sets the width of the image, either as an integer or a %. </td>
-        <!-- todo: if integer, what kind? cm, px, inches, ... -->
-    <td align="center"> no (defaults to <i>100%</i>) </td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top"> height </td>
-    <td valign="top"> Sets the height of the image, either as an integer or a %. </td>
-        <!-- todo: if integer, what kind? cm, px, inches, ... -->
-    <td align="center"> no (defaults to <i>100%</i>) </td>
+    <td>proportions</td>
+    <td>Sets which dimension to control proportions from. Valid values are:
+      <ul>
+        <li><q>ignore</q>&mdash;treat the dimensions independently.</li>
+        <li><q>height</q>&mdash;keep proportions based on the width.</li>
+        <li><q>width</q>&mdash;keep proportions based on the height.</li>
+        <li><q>cover</q>&mdash;keep proportions and fit in the supplied dimensions.</li>
+        <li><q>fit</q>&mdash;keep proportions and cover the supplied dimensions.</li>
+      </ul>
+    </td>
+    <td>No; defaults to <q>ignore</q></td>
+  </tr>
+  <tr>
+    <td>width</td>
+    <td>Sets the width of the image, either as an integer (pixels) or a %.</td>
+    <td>No; defaults to <q>100%</q></td>
+  </tr>
+  <tr>
+    <td>height</td>
+    <td>Sets the height of the image, either as an integer (pixels) or a %.</td>
+    <td>No; defaults to <q>100%</q></td>
   </tr>
 </table>
 
 <h4>Draw</h4>
-<p>Adds a Draw ImageOperation to chain. DrawOperation DataType objects can be
-nested inside the Draw object.</p>
+<p>Adds a Draw ImageOperation to chain. DrawOperation DataType objects can be nested inside the Draw
+object.</p>
 <h5>Parameters</h5>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top"> xloc </td>
-    <td valign="top"> X-Position where to draw nested image elements. </td>
-    <td align="center"> no (defaults to <i>0</i>) </td>
+    <td>xloc</td>
+    <td>X-Position where to draw nested image elements.</td>
+    <td>No; defaults to <q>0</q></td>
   </tr>
   <tr>
-    <td valign="top"> yloc </td>
-    <td valign="top"> Y-Position where to draw nested image elements. </td>
-    <td align="center"> no (defaults to <i>0</i>) </td>
+    <td>yloc</td>
+    <td>Y-Position where to draw nested image elements.</td>
+    <td>No; defaults to <q>0</q></td>
   </tr>
 </table>
+<p>For description of nested elements, please see the documentation
+of <a href="imageio.html#draw">ImageIO task</a>.</p>
 
 <h4>mapper</h4>
 <p><em>Since Apache Ant 1.8.0</em></p>
 
 <p>You can define filename transformations by using a
-  nested <a href="../Types/mapper.html">mapper</a> element. The
-  default mapper used by
-  <code>&lt;image&gt;</code> is
-  the <a href="../Types/mapper.html#identity-mapper">identity
-  mapper</a>.</p>
+nested <a href="../Types/mapper.html">mapper</a> element. The default mapper used
+by <code>&lt;image&gt;</code> is the <a href="../Types/mapper.html#identity-mapper">identity
+mapper</a>.</p>
 
-<p>You can also use a filenamemapper type in place of the mapper
-  element.</p>
+<p>You can also use a <code>filenamemapper</code> type in place of the <code>mapper</code>
+element.</p>
 
 <h3>Examples</h3>
 
-<blockquote><pre>
-&nbsp;&lt;image destdir="samples/low" overwrite="yes"&gt;
-&nbsp;&nbsp;&nbsp;&nbsp; &lt;fileset dir="samples/full"&gt;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="**/*.jpg"/&gt;
-&nbsp;&nbsp;&nbsp;&nbsp; &lt;/fileset&gt;
-&nbsp;&nbsp;&nbsp;&nbsp; &lt;scale width="160" height="160" proportions="fit"/&gt;
-&nbsp;&lt;/image&gt;
-</pre></blockquote>
-<p>Create thumbnails of my images and make sure they all fit within the 160x160 size whether the
-image is portrait or landscape.</p>
+<p>Create thumbnails of my images and make sure they all fit within the 160&times;160 pixel size
+whether the image is portrait or landscape.</p>
+<pre>
+&lt;image destdir="samples/low" overwrite="yes"&gt;
+    &lt;fileset dir="samples/full"&gt;
+        &lt;include name="**/*.jpg"/&gt;
+    &lt;/fileset&gt;
+    &lt;scale width="160" height="160" proportions="fit"/&gt;
+&lt;/image&gt;</pre>
 
-<blockquote><pre>
+<p>Create a thumbnail for all PNG files in <samp>src</samp> of the size of 40 pixels keeping the
+proportions and store the <samp>src</samp>.</p>
+<pre>
 &lt;image srcdir="src" includes="*.png"&gt;
     &lt;scale proportions="width" width="40"/&gt;
-&lt;/image&gt;
-</pre></blockquote>
-<p>Creates a thumbnail for all PNG-files in <i>src</i> in the size of 40 pixel keeping the proportions
-and stores the <i>src</i>.</p>
+&lt;/image&gt;</pre>
 
-<blockquote><pre>
+<p>Same as above but store the result in <samp>dest</samp>.</p>
+<pre>
 &lt;image srcdir="src" destdir="dest" includes="*.png"&gt;
     &lt;scale proportions="width" width="40"/&gt;
-&lt;/image&gt;
-</pre></blockquote>
-<p>Same as above but stores the result in <i>dest</i>.</p>
+&lt;/image&gt;</pre>
 
-<blockquote><pre>
+<p>Same as above but store the result to files with original names prefixed
+by <samp>scaled-</samp>.</p>
+<pre>
 &lt;image srcdir="src" destdir="dest" includes="*.png"&gt;
     &lt;scale proportions="width" width="40"/&gt;
     &lt;globmapper from="*" to="scaled-*"/&gt;
-&lt;/image&gt;
-</pre></blockquote>
-<p>Same as above but stores the resulting file names will be prefixed
-  by "scaled-".</p>
-
-<blockquote><pre>
-</pre></blockquote>
-
-
+&lt;/image&gt;</pre>
 
 </body>
 </html>
-
-
diff --git a/manual/Tasks/imageio.graphml b/manual/Tasks/imageio.graphml
new file mode 100644
index 0000000..366636b
--- /dev/null
+++ b/manual/Tasks/imageio.graphml
@@ -0,0 +1,498 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+   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
+
+       https://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.
+-->
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
+  <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
+  <key for="port" id="d1" yfiles.type="portgraphics"/>
+  <key for="port" id="d2" yfiles.type="portgeometry"/>
+  <key for="port" id="d3" yfiles.type="portuserdata"/>
+  <key attr.name="url" attr.type="string" for="node" id="d4"/>
+  <key attr.name="description" attr.type="string" for="node" id="d5"/>
+  <key for="node" id="d6" yfiles.type="nodegraphics"/>
+  <key for="graphml" id="d7" yfiles.type="resources"/>
+  <key for="edge" id="d8" yfiles.type="portconstraints"/>
+  <key attr.name="url" attr.type="string" for="edge" id="d9"/>
+  <key attr.name="description" attr.type="string" for="edge" id="d10"/>
+  <key for="edge" id="d11" yfiles.type="edgegraphics"/>
+  <graph edgedefault="directed" id="G">
+    <data key="d0" xml:space="preserve"/>
+    <node id="n0">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="47.0" width="245.0" x="207.5" y="-113.12162162162163"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="234.9150390625" x="5.04248046875" xml:space="preserve" y="3.0">org.apache.tools.ant.types.DataType<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve"> </y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n1">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="104.0" width="182.0" x="239.0" y="26.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="105.10546875" x="38.447265625" xml:space="preserve" y="3.0">ImageOperation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">instructions : List</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve">addDraw(Draw : instr)
+addRotate(Rotate : instr)
+addScale(Scale : instr)</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n2">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="105.0" width="260.55078125" x="-419.1051056860584" y="469.59294436906373"/>
+          <y:Fill hasColor="false" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="left" autoSizePolicy="content" fontFamily="SansSerif" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="88.796875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="250.55078125" x="5.0" xml:space="preserve" y="8.1015625">The setType() method forces type to
+one of the values of java.awt.geom.Arc2D:
+open = Arc2D.OPEN
+pie = Arc2D.PIE
+chord = Arc2D.CHORD
+Parameter is not case-sensitive.<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n3">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="115.0" width="168.0" x="-24.0" y="106.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="sides" modelPosition="n" textColor="#000000" verticalTextPosition="bottom" visible="true" width="73.37353515625" x="47.313232421875" xml:space="preserve" y="3.0">BasicShape</y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">height : int = 0
+width : int = 0
+strokeWidth : int = 0
+stroke : String = "black"
+fill : String = "transparent"</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n4">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="61.0" width="386.0" x="527.0" y="105.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="sides" modelPosition="n" textColor="#000000" verticalTextPosition="bottom" visible="true" width="132.33056640625" x="126.834716796875" xml:space="preserve" y="3.0">TransformOperation</y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve">executeTransformOperation(BufferedImage img) : BufferedImage</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n5">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="84.0" width="246.0" x="206.0" y="478.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="italic" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="98.9482421875" x="73.52587890625" xml:space="preserve" y="26.1328125">DrawOperation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="interface" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve">executeDrawOperation() : BufferedImage</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n6">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="75.75675675675677" width="216.060546875" x="220.31775912695048" y="635.8665334262349"/>
+          <y:Fill hasColor="false" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="left" autoSizePolicy="content" fontFamily="SansSerif" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="60.53125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="206.060546875" x="5.0" xml:space="preserve" y="7.612753378378443">The implementing class uses
+ColorMapper to evaluate the color.
+Only the values defined in
+ColorMapper are used.<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n7">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="271.4234234234233" width="251.275390625" x="562.7103372519505" y="541.3371349640008"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="85.34521484375" x="82.965087890625" xml:space="preserve" y="3.0">ColorMapper<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">COLOR_BLACK : String = "black"
+COLOR_BLUE : String = "blue"
+COLOR_CYAN : String = "cyan"
+COLOR_DARKGRAY : String = "darkgray"
+COLOR_GRAY : String = "gray"
+COLOR_LIGHTGRAY : String = "lightgray"
+COLOR_DARKGREY : String = "darkgrey"
+COLOR_GREY : String = "grey"
+COLOR_LIGHTGREY : String = "lightgrey"
+COLOR_GREEN : String = "green"
+COLOR_MAGENTA : String = "magenta"
+COLOR_ORANGE : String = "orange"
+COLOR_PINK : String = "pink"
+COLOR_RED : String = "red"
+COLOR_WHITE : String = "white"
+COLOR_YELLOW : String = "yellow"</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n8">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="130.0" width="146.0" x="257.0" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="32.2978515625" x="56.85107421875" xml:space="preserve" y="3.0">Text<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">string : String = ""
+font : String = "Arial"
+point : int = 10
+bold : boolean = false
+color : String = "black"
+italic : boolean = false</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n9">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="59.0" width="122.0" x="449.0" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="44.35205078125" x="38.823974609375" xml:space="preserve" y="3.0">Rotate<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">angle : float = 0.0F</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n10">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="88.0" width="212.0" x="614.0" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="35.83984375" x="88.080078125" xml:space="preserve" y="3.0">Scale<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">width : String = "100%"
+height : String = "100%"
+keepProportions : boolean = false</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n11">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="130.0" width="180.0" x="874.0" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.25244140625" x="71.873779296875" xml:space="preserve" y="3.0">Draw<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">xloc : int = 0
+yloc : int = 0</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve">addText(Text : text)
+addRectangle(Rectangle rect)
+addEllipse(Ellipse elip)
+addArc(Arc arc)</y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n12">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="74.0" width="122.0" x="0.0" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.33740234375" x="28.331298828125" xml:space="preserve" y="3.0">Rectangle<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">archeight : int = 0
+arcwidth : int = 0</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n13">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="45.0" width="122.0" x="-166.13229308005424" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="44.37109375" x="38.814453125" xml:space="preserve" y="3.0">Ellipse<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve"/>
+            <y:MethodLabel xml:space="preserve"> </y:MethodLabel>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n14">
+      <data key="d4" xml:space="preserve"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="88.0" width="167.0" x="-375.3690637720489" y="272.0"/>
+          <y:Fill color="#FFCC99" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="SansSerif" fontSize="13" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="19.310546875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="24.947265625" x="71.0263671875" xml:space="preserve" y="3.0">Arc<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
+          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel xml:space="preserve">start : int = 0
+stop : int = 0
+type : enumerated = open</y:AttributeLabel>
+            <y:MethodLabel xml:space="preserve"/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <edge id="e0" source="n1" target="n0">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.1015625" xml:space="preserve" y="-55.113770252949486"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e1" source="n3" target="n1">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="43.66826814854102" xml:space="preserve" y="7.339041583081126"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e2" source="n4" target="n1">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="24.541169749339424" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-49.40849066634263" xml:space="preserve" y="-49.29658468306819"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e3" source="n5" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-64.77475497688485" xml:space="preserve" y="-139.5514023191172"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e4" source="n5" target="n9">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="93.83537882510757" xml:space="preserve" y="-80.02171272585866"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e5" source="n5" target="n10">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="141.8268161095399" xml:space="preserve" y="-51.25926438261342"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e6" source="n9" target="n4">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="88.76195858042456" xml:space="preserve" y="-44.07133119943154"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e7" source="n10" target="n4">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.1015625" xml:space="preserve" y="-62.0430908203125"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e8" source="n11" target="n4">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-26.439794564087606" xml:space="preserve" y="-66.58883222234243"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e9" source="n8" target="n1">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.1015625" xml:space="preserve" y="-80.0950927734375"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e10" source="n5" target="n8">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.309432546745086" xml:space="preserve" y="-47.024658203125"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e11" source="n6" target="n5">
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#808080" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="26.258473013120465" xml:space="preserve" y="-46.00484363844498"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e12" source="n7" target="n6">
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#808080" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="-67.06248989648702" xml:space="preserve" y="-39.64733927051532"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e13" source="n2" target="n14">
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#808080" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="25.296792915327387" xml:space="preserve" y="-63.858496077186885"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e14" source="n14" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="-39.69264350185832" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="158.34186581905368" xml:space="preserve" y="-29.575788755683107"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e15" source="n13" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="58.336471410972415" xml:space="preserve" y="-20.144000203114217"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e16" source="n12" target="n3">
+      <data key="d9" xml:space="preserve"/>
+      <data key="d11">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="DejaVu Sans Mono" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.796875" x="25.926868159120588" xml:space="preserve" y="-34.5875244140625"> <y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/></y:ModelParameter><y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
+          <y:BendStyle smoothed="true"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+  </graph>
+  <data key="d7">
+    <y:Resources/>
+  </data>
+</graphml>
diff --git a/manual/Tasks/imageio.html b/manual/Tasks/imageio.html
new file mode 100644
index 0000000..1010aa7
--- /dev/null
+++ b/manual/Tasks/imageio.html
@@ -0,0 +1,698 @@
+<!DOCTYPE html>
+<!--
+   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
+
+       https://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">
+
+<head>
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<title>Image Task</title>
+</head>
+
+<body>
+
+<h2 id="imageio">ImageIO</h2>
+<h3>Description</h3>
+<p>Applies a chain of image operations on a set of files.</p>
+<p>Uses AWT and ImageIO; replaces <a href="image.html">image</a> task for Java 9+. The task can be
+used with Java 8 as well, see parameter table for limitations.</p>
+<p><strong>Note</strong>: this task tries to stay as close as possible to syntax and semantics
+of <code>image</code> task. However, it uses <var>format</var> attribute rather
+than <var>encoding</var> attribute, because the latter is a misnomer: almost all tasks use similar
+attributes for character encodings in files, file names or other strings. Also,
+when <var>format</var> is not specified, its value is defined by the format of the first processed
+image file.</p>
+<h5>Overview of used datatypes</h5>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill-opacity="1"
+     color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black"
+     stroke-linecap="square" viewBox="0 0 1504 957" stroke-miterlimit="10" shape-rendering="auto"
+     stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1"
+     font-family="Sans-Serif" font-style="normal" stroke-linejoin="miter" font-size="12px" role="img"
+     stroke-dashoffset="0" image-rendering="auto" aria-labelledby="diagramTitle diagramDescription">
+  <title id="diagramTitle">ImageOperation class diagram</title>
+  <desc id="diagramDescription">A diagram of Ant DataType classes used by ImageIO task.</desc>
+  <defs id="genericDefs"/>
+  <g>
+    <defs id="defs1">
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath1">
+        <path d="M0 0 L1504 0 L1504 957 L0 957 L0 0 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
+        <path d="M-435 -129 L1069 -129 L1069 828 L-435 828 L-435 -129 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath3">
+        <path d="M207 -113 L207 -66 L452 -66 L452 -113 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath4">
+        <path d="M239 26 L239 130 L421 130 L421 26 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath5">
+        <path d="M-24 106 L-24 221 L144 221 L144 106 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath6">
+        <path d="M527 105 L527 166 L913 166 L913 105 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath7">
+        <path d="M206 478 L206 562 L452 562 L452 478 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath8">
+        <path d="M562 541 L562 812 L813 812 L813 541 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath9">
+        <path d="M257 272 L257 402 L403 402 L403 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath10">
+        <path d="M449 272 L449 331 L571 331 L571 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath11">
+        <path d="M614 272 L614 360 L826 360 L826 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath12">
+        <path d="M874 272 L874 402 L1054 402 L1054 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath13">
+        <path d="M0 272 L0 346 L122 346 L122 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath14">
+        <path d="M-166 272 L-166 317 L-44 317 L-44 272 Z"/>
+      </clipPath>
+      <clipPath clipPathUnits="userSpaceOnUse" id="clipPath15">
+        <path d="M-375 272 L-375 360 L-208 360 L-208 272 Z"/>
+      </clipPath>
+    </defs>
+    <g fill="white" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="translate(435,129)" stroke="white">
+      <rect x="-435" width="1504" height="957" y="-129" clip-path="url(#clipPath2)" stroke="none"/>
+    </g>
+    <g fill="rgb(255,204,153)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)" stroke="rgb(255,204,153)">
+      <rect x="208" width="243" height="45" y="-112" clip-path="url(#clipPath2)" stroke="none"/>
+      <rect x="207" y="-113" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="47" stroke="none"/>
+      <rect x="208" y="-113" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="243" height="1" stroke="none"/>
+      <rect x="208" y="-67" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="244" height="1" stroke="none"/>
+      <rect x="451" y="-113" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="46" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="214.5425" xml:space="preserve" y="-95.5533" clip-path="url(#clipPath3)" stroke="none">org.apache.tools.ant.types.DataType</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="-87" fill="none" x1="208" clip-path="url(#clipPath3)" x2="451" y1="-87"/>
+      <line y2="-77" fill="none" x1="208" clip-path="url(#clipPath3)" x2="451" y1="-77"/>
+      <text stroke-linecap="butt" x="212.5" y="-61.2095" clip-path="url(#clipPath3)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve"> </text>
+      <rect x="240" y="27" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="180" height="102" stroke="none"/>
+      <rect x="239" y="26" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="104" stroke="none"/>
+      <rect x="240" y="26" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="180" height="1" stroke="none"/>
+      <rect x="240" y="129" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="181" height="1" stroke="none"/>
+      <rect x="420" y="26" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="103" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="279.4473" xml:space="preserve" y="43.5684" clip-path="url(#clipPath4)" stroke="none">ImageOperation</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="51" fill="none" x1="240" clip-path="url(#clipPath4)" x2="420" y1="51"/>
+      <text stroke-linecap="butt" x="244" y="67.9121" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">instructions : List</text>
+      <line y2="75" fill="none" x1="240" clip-path="url(#clipPath4)" x2="420" y1="75"/>
+      <text stroke-linecap="butt" x="244" y="92.0449" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addDraw(Draw : instr)</text>
+      <text stroke-linecap="butt" x="244" y="106.1777" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addRotate(Rotate : instr)</text>
+      <text stroke-linecap="butt" x="244" y="120.3105" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addScale(Scale : instr)</text>
+      <path fill="none" stroke-miterlimit="1.45" d="M-419.1051 469.593 L-173.5543 469.593 L-173.5543 484.593 L-158.5543 484.593 L-158.5543 574.593 L-419.1051 574.593 Z" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <path fill="none" stroke-miterlimit="1.45" d="M-173.5543 469.593 L-173.5543 484.593 L-158.5543 484.593 Z" fill-rule="evenodd" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <text stroke-linecap="butt" x="-412.1051" y="491.2961" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">The setType() method forces type to</text>
+      <text stroke-linecap="butt" x="-412.1051" y="505.4289" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">one of the values of java.awt.geom.Arc2D:</text>
+      <text stroke-linecap="butt" x="-412.1051" y="519.5617" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">open = Arc2D.OPEN</text>
+      <text stroke-linecap="butt" x="-412.1051" y="533.6945" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">pie = Arc2D.PIE</text>
+      <text stroke-linecap="butt" x="-412.1051" y="547.8273" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">chord = Arc2D.CHORD</text>
+      <text stroke-linecap="butt" x="-412.1051" y="561.9601" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">Parameter is not case-sensitive.</text>
+      <rect x="-23" y="107" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="166" height="113" stroke="none"/>
+      <rect x="-24" y="106" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="115" stroke="none"/>
+      <rect x="-23" y="106" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="166" height="1" stroke="none"/>
+      <rect x="-23" y="220" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="167" height="1" stroke="none"/>
+      <rect x="143" y="106" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="114" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="25.3132" xml:space="preserve" y="123.5684" clip-path="url(#clipPath5)" stroke="none">BasicShape</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="131" fill="none" x1="-23" clip-path="url(#clipPath5)" x2="143" y1="131"/>
+      <text stroke-linecap="butt" x="-19" y="147.9121" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">height : int = 0</text>
+      <text stroke-linecap="butt" x="-19" y="162.0449" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">width : int = 0</text>
+      <text stroke-linecap="butt" x="-19" y="176.1777" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">strokeWidth : int = 0</text>
+      <text stroke-linecap="butt" x="-19" y="190.3105" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">stroke : String = "black"</text>
+      <text stroke-linecap="butt" x="-19" y="204.4434" clip-path="url(#clipPath5)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">fill : String = "transparent"</text>
+      <line y2="211" fill="none" x1="-23" clip-path="url(#clipPath5)" x2="143" y1="211"/>
+      <rect x="528" y="106" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="384" height="59" stroke="none"/>
+      <rect x="527" y="105" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="61" stroke="none"/>
+      <rect x="528" y="105" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="384" height="1" stroke="none"/>
+      <rect x="528" y="165" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="385" height="1" stroke="none"/>
+      <rect x="912" y="105" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="60" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="655.8347" xml:space="preserve" y="122.5684" clip-path="url(#clipPath6)" stroke="none">TransformOperation</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="130" fill="none" x1="528" clip-path="url(#clipPath6)" x2="912" y1="130"/>
+      <line y2="140" fill="none" x1="528" clip-path="url(#clipPath6)" x2="912" y1="140"/>
+      <text stroke-linecap="butt" x="532" y="156.9121" clip-path="url(#clipPath6)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">executeTransformOperation(BufferedImage img) : BufferedImage</text>
+      <rect x="207" y="479" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="244" height="82" stroke="none"/>
+      <rect x="206" y="478" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="84" stroke="none"/>
+      <rect x="207" y="478" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="244" height="1" stroke="none"/>
+      <rect x="207" y="561" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="245" height="1" stroke="none"/>
+      <rect x="451" y="478" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="83" stroke="none"/>
+      <text stroke-linecap="butt" x="284.4863" y="494.6016" clip-path="url(#clipPath7)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">&lt;&lt;interface&gt;&gt;</text>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" font-style="italic" stroke-miterlimit="1.45">
+      <text x="281.5259" xml:space="preserve" y="518.7012" clip-path="url(#clipPath7)" stroke="none">DrawOperation</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="526" fill="none" x1="207" clip-path="url(#clipPath7)" x2="451" y1="526"/>
+      <line y2="536" fill="none" x1="207" clip-path="url(#clipPath7)" x2="451" y1="536"/>
+      <text stroke-linecap="butt" x="211" y="553.0449" clip-path="url(#clipPath7)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">executeDrawOperation() : BufferedImage</text>
+      <path fill="none" stroke-miterlimit="1.45" d="M220.3178 635.8665 L421.3783 635.8665 L421.3783 650.8665 L436.3783 650.8665 L436.3783 711.6233 L220.3178 711.6233 Z" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <path fill="none" stroke-miterlimit="1.45" d="M421.3783 635.8665 L421.3783 650.8665 L436.3783 650.8665 Z" fill-rule="evenodd" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+      <text stroke-linecap="butt" x="227.3178" y="657.0809" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">The implementing class uses</text>
+      <text stroke-linecap="butt" x="227.3178" y="671.2137" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">ColorMapper to evaluate the color.</text>
+      <text stroke-linecap="butt" x="227.3178" y="685.3465" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">Only the values defined in</text>
+      <text stroke-linecap="butt" x="227.3178" y="699.4793" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">ColorMapper are used.</text>
+      <rect x="563" y="542" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="249" height="269" stroke="none"/>
+      <rect x="562" y="541" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="271" stroke="none"/>
+      <rect x="563" y="541" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="249" height="1" stroke="none"/>
+      <rect x="563" y="811" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="250" height="1" stroke="none"/>
+      <rect x="812" y="541" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="270" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="647.6754" xml:space="preserve" y="558.9055" clip-path="url(#clipPath8)" stroke="none">ColorMapper</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="566" fill="none" x1="563" clip-path="url(#clipPath8)" x2="812" y1="566"/>
+      <text stroke-linecap="butt" x="567.7103" y="583.2493" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_BLACK : String = "black"</text>
+      <text stroke-linecap="butt" x="567.7103" y="597.3821" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_BLUE : String = "blue"</text>
+      <text stroke-linecap="butt" x="567.7103" y="611.5149" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_CYAN : String = "cyan"</text>
+      <text stroke-linecap="butt" x="567.7103" y="625.6477" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_DARKGRAY : String = "darkgray"</text>
+      <text stroke-linecap="butt" x="567.7103" y="639.7805" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_GRAY : String = "gray"</text>
+      <text stroke-linecap="butt" x="567.7103" y="653.9133" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_LIGHTGRAY : String = "lightgray"</text>
+      <text stroke-linecap="butt" x="567.7103" y="668.0461" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_DARKGREY : String = "darkgrey"</text>
+      <text stroke-linecap="butt" x="567.7103" y="682.179" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_GREY : String = "grey"</text>
+      <text stroke-linecap="butt" x="567.7103" y="696.3118" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_LIGHTGREY : String = "lightgrey"</text>
+      <text stroke-linecap="butt" x="567.7103" y="710.4446" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_GREEN : String = "green"</text>
+      <text stroke-linecap="butt" x="567.7103" y="724.5774" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_MAGENTA : String = "magenta"</text>
+      <text stroke-linecap="butt" x="567.7103" y="738.7102" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_ORANGE : String = "orange"</text>
+      <text stroke-linecap="butt" x="567.7103" y="752.843" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_PINK : String = "pink"</text>
+      <text stroke-linecap="butt" x="567.7103" y="766.9758" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_RED : String = "red"</text>
+      <text stroke-linecap="butt" x="567.7103" y="781.1086" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_WHITE : String = "white"</text>
+      <text stroke-linecap="butt" x="567.7103" y="795.2415" clip-path="url(#clipPath8)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">COLOR_YELLOW : String = "yellow"</text>
+      <line y2="802" fill="none" x1="563" clip-path="url(#clipPath8)" x2="812" y1="802"/>
+      <rect x="258" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="144" height="128" stroke="none"/>
+      <rect x="257" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="130" stroke="none"/>
+      <rect x="258" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="144" height="1" stroke="none"/>
+      <rect x="258" y="401" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="145" height="1" stroke="none"/>
+      <rect x="402" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="129" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="315.8511" xml:space="preserve" y="289.5684" clip-path="url(#clipPath9)" stroke="none">Text</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="258" clip-path="url(#clipPath9)" x2="402" y1="297"/>
+      <text stroke-linecap="butt" x="262" y="313.9121" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">string : String = ""</text>
+      <text stroke-linecap="butt" x="262" y="328.0449" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">font : String = "Arial"</text>
+      <text stroke-linecap="butt" x="262" y="342.1777" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">point : int = 10</text>
+      <text stroke-linecap="butt" x="262" y="356.3105" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">bold : boolean = false</text>
+      <text stroke-linecap="butt" x="262" y="370.4434" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">color : String = "black"</text>
+      <text stroke-linecap="butt" x="262" y="384.5762" clip-path="url(#clipPath9)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">italic : boolean = false</text>
+      <line y2="392" fill="none" x1="258" clip-path="url(#clipPath9)" x2="402" y1="392"/>
+      <rect x="450" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="120" height="57" stroke="none"/>
+      <rect x="449" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="59" stroke="none"/>
+      <rect x="450" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="120" height="1" stroke="none"/>
+      <rect x="450" y="330" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="121" height="1" stroke="none"/>
+      <rect x="570" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="58" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="489.824" xml:space="preserve" y="289.5684" clip-path="url(#clipPath10)" stroke="none">Rotate</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="450" clip-path="url(#clipPath10)" x2="570" y1="297"/>
+      <text stroke-linecap="butt" x="454" y="313.9121" clip-path="url(#clipPath10)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">angle : float = 0.0F</text>
+      <line y2="321" fill="none" x1="450" clip-path="url(#clipPath10)" x2="570" y1="321"/>
+      <rect x="615" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="210" height="86" stroke="none"/>
+      <rect x="614" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="88" stroke="none"/>
+      <rect x="615" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="210" height="1" stroke="none"/>
+      <rect x="615" y="359" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="211" height="1" stroke="none"/>
+      <rect x="825" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="87" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="704.0801" xml:space="preserve" y="289.5684" clip-path="url(#clipPath11)" stroke="none">Scale</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="615" clip-path="url(#clipPath11)" x2="825" y1="297"/>
+      <text stroke-linecap="butt" x="619" y="313.9121" clip-path="url(#clipPath11)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">width : String = "100%"</text>
+      <text stroke-linecap="butt" x="619" y="328.0449" clip-path="url(#clipPath11)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">height : String = "100%"</text>
+      <text stroke-linecap="butt" x="619" y="342.1777" clip-path="url(#clipPath11)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">keepProportions : boolean = false</text>
+      <line y2="349" fill="none" x1="615" clip-path="url(#clipPath11)" x2="825" y1="349"/>
+      <rect x="875" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="178" height="128" stroke="none"/>
+      <rect x="874" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="130" stroke="none"/>
+      <rect x="875" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="178" height="1" stroke="none"/>
+      <rect x="875" y="401" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="179" height="1" stroke="none"/>
+      <rect x="1053" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="129" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="947.8738" xml:space="preserve" y="289.5684" clip-path="url(#clipPath12)" stroke="none">Draw</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="875" clip-path="url(#clipPath12)" x2="1053" y1="297"/>
+      <text stroke-linecap="butt" x="879" y="313.9121" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">xloc : int = 0</text>
+      <text stroke-linecap="butt" x="879" y="328.0449" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">yloc : int = 0</text>
+      <line y2="335" fill="none" x1="875" clip-path="url(#clipPath12)" x2="1053" y1="335"/>
+      <text stroke-linecap="butt" x="879" y="352.1777" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addText(Text : text)</text>
+      <text stroke-linecap="butt" x="879" y="366.3105" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addRectangle(Rectangle rect)</text>
+      <text stroke-linecap="butt" x="879" y="380.4434" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addEllipse(Ellipse elip)</text>
+      <text stroke-linecap="butt" x="879" y="394.5762" clip-path="url(#clipPath12)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">addArc(Arc arc)</text>
+      <rect x="1" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="120" height="72" stroke="none"/>
+      <rect x="0" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="74" stroke="none"/>
+      <rect x="1" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="120" height="1" stroke="none"/>
+      <rect x="1" y="345" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="121" height="1" stroke="none"/>
+      <rect x="121" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="73" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="30.3313" xml:space="preserve" y="289.5684" clip-path="url(#clipPath13)" stroke="none">Rectangle</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="1" clip-path="url(#clipPath13)" x2="121" y1="297"/>
+      <text stroke-linecap="butt" x="5" y="313.9121" clip-path="url(#clipPath13)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">archeight : int = 0</text>
+      <text stroke-linecap="butt" x="5" y="328.0449" clip-path="url(#clipPath13)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">arcwidth : int = 0</text>
+      <line y2="335" fill="none" x1="1" clip-path="url(#clipPath13)" x2="121" y1="335"/>
+      <rect x="-165" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="120" height="43" stroke="none"/>
+      <rect x="-166" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="45" stroke="none"/>
+      <rect x="-165" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="120" height="1" stroke="none"/>
+      <rect x="-165" y="316" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="121" height="1" stroke="none"/>
+      <rect x="-45" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="44" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="-125.3178" xml:space="preserve" y="289.5684" clip-path="url(#clipPath14)" stroke="none">Ellipse</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="-165" clip-path="url(#clipPath14)" x2="-45" y1="297"/>
+      <line y2="307" fill="none" x1="-165" clip-path="url(#clipPath14)" x2="-45" y1="307"/>
+      <text stroke-linecap="butt" x="-161.1323" y="323.9121" clip-path="url(#clipPath14)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve"> </text>
+      <rect x="-374" y="273" clip-path="url(#clipPath2)" fill="rgb(255,204,153)" width="165" height="86" stroke="none"/>
+      <rect x="-375" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="1" height="88" stroke="none"/>
+      <rect x="-374" y="272" clip-path="url(#clipPath2)" fill="rgb(255,255,218)" width="165" height="1" stroke="none"/>
+      <rect x="-374" y="359" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="166" height="1" stroke="none"/>
+      <rect x="-209" y="272" clip-path="url(#clipPath2)" fill="rgb(178,142,107)" width="1" height="87" stroke="none"/>
+    </g>
+    <g font-size="13px" stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" text-rendering="geometricPrecision" font-family="sans-serif" shape-rendering="geometricPrecision" stroke-miterlimit="1.45">
+      <text x="-302.3427" xml:space="preserve" y="289.5684" clip-path="url(#clipPath15)" stroke="none">Arc</text>
+    </g>
+    <g text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,435,129)">
+      <line y2="297" fill="none" x1="-374" clip-path="url(#clipPath15)" x2="-209" y1="297"/>
+      <text stroke-linecap="butt" x="-370.369" y="313.9121" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">start : int = 0</text>
+      <text stroke-linecap="butt" x="-370.369" y="328.0449" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">stop : int = 0</text>
+      <text stroke-linecap="butt" x="-370.369" y="342.1777" clip-path="url(#clipPath15)" font-family="sans-serif" stroke="none" stroke-miterlimit="1.45" xml:space="preserve">type : enumerated = open</text>
+      <line y2="349" fill="none" x1="-374" clip-path="url(#clipPath15)" x2="-209" y1="349"/>
+      <path fill="none" stroke-miterlimit="1.45" d="M330 25.9866 L330 -51.1105" clip-path="url(#clipPath2)" stroke-linecap="butt"/>
+    </g>
+    <g stroke-linecap="butt" transform="matrix(1,0,0,1,435,129)" fill="white" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" stroke="white" stroke-miterlimit="1.45">
+      <path d="M330 -66.1105 L324 -50.1105 L336 -50.1105 Z" stroke="none" clip-path="url(#clipPath2)"/>
+      <path fill="none" d="M330 -66.1105 L324 -50.1105 L336 -50.1105 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="358.1016" xml:space="preserve" y="-15.5257" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M144.0125 136.8961 L224.6586 111.3581" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M238.9587 106.8297 L221.8939 105.9399 L225.5166 117.3801 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M238.9587 106.8297 L221.8939 105.9399 L225.5166 117.3801 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="189.6807" xml:space="preserve" y="157.8367" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M527.0471 119.4512 L435.6495 100.2246" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M420.9707 97.1368 L435.3929 106.302 L437.8632 94.559 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M420.9707 97.1368 L435.3929 106.302 L437.8632 94.559 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="479.6386" xml:space="preserve" y="83.7562" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M297.296 477.9833 L103.3633 220.9684" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="234.5212" xml:space="preserve" y="352.0335" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" stroke-dasharray="6,2" d="M328.5086 635.8717 L328.8219 562.0092" clip-path="url(#clipPath2)" stroke="gray"/>
+      <text fill="black" x="356.7671" xml:space="preserve" y="603.4684" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" stroke-dasharray="6,2" d="M562.7084 675.8958 L436.4021 674.7366" clip-path="url(#clipPath2)" stroke="gray"/>
+      <text fill="black" x="497.6459" xml:space="preserve" y="649.85" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M329.2297 477.9583 L329.6448 402.0074" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="357.5392" xml:space="preserve" y="444.5352" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M330 272.0287 L330 144.9652" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M330 129.9652 L324 145.9652 L336 145.9652 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M330 129.9652 L324 145.9652 L336 145.9652 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="358.1016" xml:space="preserve" y="205.5352" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M363.7992 477.991 L485.5677 330.9942" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="459.6346" xml:space="preserve" y="411.5709" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M547.2986 272.0164 L669.6319 175.3148" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M681.3994 166.0128 L665.1266 171.2279 L672.5682 180.6419 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M681.3994 166.0128 L665.1266 171.2279 L672.5682 180.6419 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="638.0605" xml:space="preserve" y="241.5466" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M409.4958 478.0022 L635.665 360.0009" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="553.3226" xml:space="preserve" y="440.3445" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M720 271.9767 L720 180.9874" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M720 165.9874 L714 181.9874 L726 181.9874 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M720 165.9874 L714 181.9874 L726 181.9874 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="748.1016" xml:space="preserve" y="223.5352" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M885.2778 271.9897 L768.5073 175.5583" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M756.9413 166.0069 L765.4578 180.8214 L773.0989 171.5687 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M756.9413 166.0069 L765.4578 180.8214 L773.0989 171.5687 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="860.838" xml:space="preserve" y="219.0024" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M60.7458 272.0211 L60.4984 236.019" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M60.3953 221.0194 L54.5054 237.0602 L66.5051 236.9778 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M60.3953 221.0194 L54.5054 237.0602 L66.5051 236.9778 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="88.6727" xml:space="preserve" y="251.0352" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M-76.7703 272.0004 L-24.2436 230.3307" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M-12.4923 221.0084 L-28.756 226.2517 L-21.2981 235.6528 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M-12.4923 221.0084 L-28.756 226.2517 L-21.2981 235.6528 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="-16.4339" xml:space="preserve" y="265.4579" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" stroke-dasharray="6,2" d="M-289.604 469.5886 L-291.2204 359.9842" clip-path="url(#clipPath2)" stroke="gray"/>
+      <text fill="black" x="-262.3073" xml:space="preserve" y="419.3316" clip-path="url(#clipPath2)" stroke="none"> </text>
+      <path fill="none" d="M-278.4248 271.9972 L-38.2704 195.005" clip-path="url(#clipPath2)" stroke="black"/>
+      <path d="M-23.9865 190.4256 L-41.0544 189.5967 L-37.391 201.0238 Z" clip-path="url(#clipPath2)" stroke="none"/>
+      <path fill="none" d="M-23.9865 190.4256 L-41.0544 189.5967 L-37.391 201.0238 Z" clip-path="url(#clipPath2)" stroke="black"/>
+      <text fill="black" x="-118.083" xml:space="preserve" y="256.023" clip-path="url(#clipPath2)" stroke="none"> </text>
+    </g>
+  </g>
+</svg>
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>failonerror</td>
+    <td>Boolean value. If <q>false</q>, note errors to the output but keep going.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>srcdir</td>
+    <td>Directory containing the images.</td>
+    <td>Yes, unless nested fileset is used</td>
+  </tr>
+  <tr>
+    <td>format</td>
+    <td>Image format.<br/>Valid (case insensitive)
+      are: <q>bmp</q>, <q>gif</q>, <q>jpeg</q>, <q>jpg</q>, <q>png</q>, <q>tif</q>, <q>tiff</q>, <q>wbmp</q>
+      (Java 8 VM lacks support for TIFF, which can be provided
+      by <a href="../install.html#librarydependencies">external libraries</a>).</td>
+    <td>No; defaults to the format of the (first) original file</td>
+  </tr>
+  <tr>
+    <td>overwrite</td>
+    <td>Boolean value. Sets whether or not to overwrite a file if there is naming conflict.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>gc</td>
+    <td>Boolean value. Enables garbage collection after each image processed.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>destdir</td>
+    <td>Directory where the result images are stored.</td>
+    <td>No; defaults to value of <var>srcdir</var></td>
+  </tr>
+  <!-- attributes inherited from MatchingTask -->
+  <tr>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
+  </tr>
+  <tr>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
+  </tr>
+  <tr>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
+  </tr>
+  <tr>
+    <td>caseSensitive</td>
+    <td>Boolean value. Sets case sensitivity of the file system.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>followSymlinks</td>
+    <td>Boolean value. Sets whether or not symbolic links should be followed.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+
+<p>The following ImageOperation objects can be specified as nested
+elements: <code>Rotate</code>, <code>Scale</code> and <code>Draw</code>.</p>
+
+<h4>Rotate</h4>
+<p>Adds a Rotate ImageOperation to chain.</p>
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>angle</td>
+    <td>Float value. Sets the angle of rotation in degrees.</td>
+    <td>No; defaults to <q>0.0F</q></td>
+  </tr>
+</table>
+
+<h4>Scale</h4>
+<p>Adds a Scale ImageOperation to chain.</p>
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>proportions</td>
+    <td>Sets which dimension to control proportions from. Valid values are:
+      <ul>
+        <li><q>ignore</q>&mdash;treat the dimensions independently.</li>
+        <li><q>height</q>&mdash;keep proportions based on the width.</li>
+        <li><q>width</q>&mdash;keep proportions based on the height.</li>
+        <li><q>cover</q>&mdash;keep proportions and fit in the supplied dimensions.</li>
+        <li><q>fit</q>&mdash;keep proportions and cover the supplied dimensions.</li>
+      </ul>
+    </td>
+    <td>No; defaults to <q>ignore</q></td>
+  </tr>
+  <tr>
+    <td>width</td>
+    <td>Sets the width of the image, either as an integer (pixels) or a %.</td>
+    <td>No; defaults to <q>100%</q></td>
+  </tr>
+  <tr>
+    <td>height</td>
+    <td>Sets the height of the image, either as an integer (pixels) or a %.</td>
+    <td>No; defaults to <q>100%</q></td>
+  </tr>
+</table>
+
+<h4 id="draw">Draw</h4>
+<p>Adds a Draw ImageOperation to chain. DrawOperation DataType objects can be nested inside the Draw
+object.</p>
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>xloc</td>
+    <td>X-Position where to draw nested image elements.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>yloc</td>
+    <td>Y-Position where to draw nested image elements.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+</table>
+<h5>Nested elements</h5>
+<p>Both Text and BasicShape objects can be nested. Currently supported BasicShape objects are Arc,
+Ellipse and Rectangle.</p>
+<h6>Common parameters of BasicShape objects</h6>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>height</td>
+    <td>Height of a BasicShape.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>width</td>
+    <td>Width of a BasicShape.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>strokewidth</td>
+    <td>Stroke width of a BasicShape.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>color</td>
+    <td>Color of a BasicShape.</td>
+    <td>No; defaults to <q>black</q></td>
+  </tr>
+  <tr>
+    <td>fill</td>
+    <td>Fill of a BasicShape.</td>
+    <td>No; defaults to <q>transparent</q></td>
+  </tr>
+</table>
+<h6>Parameters specific to Arc objects</h6>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>start</td>
+    <td>Start angle of an arc in degrees.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>stop</td>
+    <td>Angle extent of an arc in degrees.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>type</td>
+    <td>One of <q>chord</q>, <q>open</q>, <q>pie</q>.</td>
+    <td>No; defaults to <q>open</q></td>
+  </tr>
+</table>
+<h6>Parameters specific to Ellipse objects</h6>
+<p>None.</p>
+<h6>Parameters specific to Rectangle objects</h6>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>archeight</td>
+    <td>Vertical diameter of the arc at the corners of the rectangle.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+  <tr>
+    <td>arcwidth</td>
+    <td>Horisontal diameter of the arc at the corners of the rectangle.</td>
+    <td>No; defaults to <q>0</q></td>
+  </tr>
+</table>
+<h6>Parameters of Text</h6>
+<table class="attr">
+    <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+    </tr>
+    <tr>
+        <td>string</td>
+        <td>The text string.</td>
+        <td>No; defaults to <q></q></td>
+    </tr>
+    <tr>
+        <td>font</td>
+        <td>The font to set the text in.</td>
+        <td>No; defaults to <q>Arial</q></td>
+    </tr>
+    <tr>
+        <td>point</td>
+        <td>Size of the font in points.</td>
+        <td>No; defaults to <q>10</q></td>
+    </tr>
+    <tr>
+        <td>bold</td>
+        <td>Whether the font is bold.</td>
+        <td>No; defaults to <q>false</q></td>
+    </tr>
+    <tr>
+        <td>color</td>
+        <td>Color of the text.</td>
+        <td>No; defaults to <q>black</q></td>
+    </tr>
+    <tr>
+        <td>italic</td>
+        <td>Whether the font is italic.</td>
+        <td>No; defaults to <q>false</q></td>
+    </tr>
+</table>
+<h4>mapper</h4>
+<p>You can define filename transformations by using a
+nested <a href="../Types/mapper.html">mapper</a> element. The default mapper used
+by <code>&lt;image&gt;</code> is the <a href="../Types/mapper.html#identity-mapper">identity
+mapper</a>.</p>
+
+<p>You can also use a <code>filenamemapper</code> type in place of the <code>mapper</code>
+element.</p>
+
+<h3>Examples</h3>
+
+<p>Create thumbnails of my images and make sure they all fit within the 160&times;160 pixel size
+whether the image is portrait or landscape.</p>
+<pre>
+&lt;image destdir="samples/low" overwrite="yes"&gt;
+    &lt;fileset dir="samples/full"&gt;
+        &lt;include name="**/*.jpg"/&gt;
+    &lt;/fileset&gt;
+    &lt;scale width="160" height="160" proportions="fit"/&gt;
+&lt;/image&gt;</pre>
+
+<p>Create a thumbnail for all PNG files in <samp>src</samp> of the size of 40 pixels keeping the
+proportions and store the <samp>src</samp>.</p>
+<pre>
+&lt;image srcdir="src" includes="*.png"&gt;
+    &lt;scale proportions="width" width="40"/&gt;
+&lt;/image&gt;</pre>
+
+<p>Same as above but store the result in <samp>dest</samp>.</p>
+<pre>
+&lt;image srcdir="src" destdir="dest" includes="*.png"&gt;
+    &lt;scale proportions="width" width="40"/&gt;
+&lt;/image&gt;</pre>
+
+<p>Same as above but store the result to files with original names prefixed
+by <samp>scaled-</samp>.</p>
+<pre>
+&lt;image srcdir="src" destdir="dest" includes="*.png"&gt;
+    &lt;scale proportions="width" width="40"/&gt;
+    &lt;globmapper from="*" to="scaled-*"/&gt;
+&lt;/image&gt;</pre>
+
+</body>
+</html>
diff --git a/manual/Tasks/import.html b/manual/Tasks/import.html
index 4cf8de0..75f3153 100644
--- a/manual/Tasks/import.html
+++ b/manual/Tasks/import.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,270 +15,211 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Import Task</title>
 </head>
 <body>
-  <h2><a name="import">Import</a></h2>
+  <h2 id="import">Import</h2>
   <h3>Description</h3>
-  <p>
-    Imports another build file into the current project.
-  </p>
+  <p>Imports another build file into the current project.</p>
 
-  <p>
-    On execution it will select the proper ProjectHelper to parse the imported
-    file, using the same algorithm as the one executed at
-    <a href="../projecthelper.html">startup</a>. The selected ProjectHelper
-    instance will then be responsible to actually parse the imported file.
-  </p>
+  <p>On execution it will select the proper ProjectHelper to parse the imported file, using the same
+    algorithm as the one executed at <a href="../projecthelper.html">startup</a>. The selected
+    ProjectHelper instance will then be responsible to actually parse the imported file.</p>
 
-  <p>
-    <b>Note</b> as seen above, this task heavily relies on the ProjectHelper
-    implementation and doesn't really perform any work of its own.  If
-    you have configured Apache Ant to use a ProjectHelper other than Ant's
-    default, this task may or may not work.
-  </p>
+  <p><strong>Note</strong> as seen above, this task heavily relies on the ProjectHelper
+    implementation and doesn't really perform any work of its own.  If you have configured Apache
+    Ant to use a ProjectHelper other than Ant's default, this task may or may not work.</p>
 
-  <p>
-    In the common use case where only Ant's default project helper is
-    used, it basically works like the 
-    <a href="http://ant.apache.org/faq.html#xml-entity-include">Entity
-      Includes as explained in the Ant FAQ</a>, as if the imported file was
-    contained in the importing file, minus the top <code>&lt;project&gt;</code>
-    tag.
-  </p>
+  <p>In the common use case where only Ant's default project helper is used, it basically works like
+    the <a href="https://ant.apache.org/faq.html#xml-entity-include" target="_top">Entity Includes
+    as explained in the Ant FAQ</a>, as if the imported file was contained in the importing file,
+    minus the top <code>&lt;project&gt;</code> tag.</p>
 
-  <p>
-    The import task may only be used as a top-level task. This means that
-    it may not be used in a target.
-  </p>
-  <p>
-There are two further functional aspects that pertain to this task and
-that are not possible with entity includes:
-<ul>
-  <li>target overriding</li>
-  <li>special properties</li>
-</ul>
-  </p>
-<h4>Target overriding</h4>
+  <p>The <code>import</code> task may only be used as a top-level task. This means that it may not
+    be used in a target.</p>
 
-<p>If a target in the main file is also present in at least one of the
-imported files, the one from the main file takes precedence.</p>
+  <p>There are two further functional aspects that pertain to this task and that are not possible
+    with entity includes:</p>
+  <ul>
+    <li>target overriding</li>
+    <li>special properties</li>
+  </ul>
+  <h4>Target overriding</h4>
 
-<p>So if I import for example a <i>docsbuild.xml</i> file named <b>builddocs</b>,
-that contains a &quot;<b>docs</b>&quot; target, I can redefine it in my main
-buildfile and that is the one that will be called. This makes it easy to
-keep the same target name, so that the overriding target is still called
-by any other targets--in either the main or imported buildfile(s)--for which
-it is a dependency, with a different implementation. The target from <i>docsbuild.xml</i> is
-made available by the name &quot;<b>builddocs</b><b>.docs</b>&quot;.
-This enables the new implementation to call the old target, thus
-<i>enhancing</i> it with tasks called before or after it.</p>
+  <p>If a target in the main file is also present in at least one of the imported files, the one
+    from the main file takes precedence.</p>
 
-<p>If you use the <i>as</i> attribute of the task, its value will be
-  used to prefix the overridden target's name instead of the name
-  attribute of the project tag.</p>
+  <p>So if I import for example a <samp>docsbuild.xml</samp> file containing a project
+    named <q>builddocs</q> that contains a <q>docs</q> target, I can define a <q>docs</q> target in
+    my main buildfile and that is the one that will be called. This makes it easy to keep the same
+    target name, so that the overriding target is still called by any other targets&mdash;in either
+    the main or imported buildfile(s)&mdash;for which it is a dependency, with a different
+    implementation. The target from <samp>docsbuild.xml</samp> is made available by the
+    name <q>builddocs.docs</q>. This enables the new implementation to call the old target,
+    thus <em>enhancing</em> it with tasks called before or after it.</p>
 
-<h4>Special Properties</h4>
+  <p>If you use the <var>as</var> attribute of the task, its value will be used to prefix the
+    overridden target's name instead of the <var>name</var> attribute of the <code>project</code>
+    tag.</p>
 
-<p>Imported files are treated as they are present in the main
-buildfile. This makes it easy to understand, but it makes it impossible
-for them to reference files and resources relative to their path.
-Because of this, for every imported file, Ant adds a property that
-contains the path to the imported buildfile. With this path, the
-imported buildfile can keep resources and be able to reference them
-relative to its position.</p>
+  <h4>Special properties</h4>
 
-<p>So if I import for example a <i>docsbuild.xml</i> file named <b>builddocs</b>,
-I can get its path as <b>ant.file.builddocs</b>, similarly to the <b>ant.file</b>
-property of the main buildfile.</p>
+  <p>Imported files are treated as they are present in the main buildfile. This makes it easy to
+    understand, but it makes it impossible for them to reference files and resources relative to
+    their path.  Because of this, for every imported file, Ant adds a property that contains the
+    path to the imported buildfile. With this path, the imported buildfile can keep resources and be
+    able to reference them relative to its position.</p>
 
-<p>Note that &quot;builddocs&quot; is not the filename, but the name attribute
-present in the imported project tag.</p>
-  <p>
-    If the imported file does not have a name attribute, the ant.file.projectname
-    property will not be set.
-  </p>
+  <p>So if I import for example a <samp>docsbuild.xml</samp> file named <q>builddocs</q>, I can get
+    its path as <code>ant.file.builddocs</code>, similarly to the <code>ant.file</code> property of
+    the main buildfile.</p>
 
-<p>Since Ant 1.8.0 the task can also import resources from URLs or
-  classpath resources (which are URLs, really).  If you need to know
-  whether the current build file's source has been a file or an URL
-  you can consult the
-  property <b>ant.file.type.<em>projectname</em></b> (using the same
-  example as above <b>ant.file.type.builddocs</b>) which either have
-  the value "file" or "url".</p>
+  <p>Note that <q>builddocs</q> is not the filename, but the <var>name</var> attribute present in
+    the imported <code>project</code> tag.</p>
 
-<h4>Resolving files against the imported file</h4>
+  <p>If the imported file does not have a <var>name</var> attribute,
+    the <code>ant.file.<i>projectname</i></code> property will not be set.</p>
 
-<p>Suppose your main build file called <code>importing.xml</code>
-imports a build file <code>imported.xml</code>, located anywhere on
-the file system, and <code>imported.xml</code> reads a set of
-properties from <code>imported.properties</code>:</p>
+  <p><em>Since Ant 1.8.0</em>, the task can also import resources from URLs or classpath resources
+    (which are URLs, really).  If you need to know whether the current build file's source has been
+    a file or an URL you can consult the property <code>ant.file.type.<i>projectname</i></code>
+    (using the same example as above <code>ant.file.type.builddocs</code>) which either have the
+    value <q>file</q> or <q>url</q>.</p>
 
-<pre>&lt;!-- importing.xml --&gt;
+  <h4>Resolving files against the imported file</h4>
+
+  <p>Suppose your main build file called <samp>importing.xml</samp> imports a build
+    file <samp>imported.xml</samp>, located anywhere on the file system,
+    and <samp>imported.xml</samp> reads a set of properties
+    from <samp>imported.properties</samp>:</p>
+
+  <pre>
+&lt;!-- importing.xml --&gt;
 &lt;project name="importing" basedir="." default="..."&gt;
-&nbsp; &lt;import file="${path_to_imported}/imported.xml"/&gt;
+  &lt;import file="${path_to_imported}/imported.xml"/&gt;
 &lt;/project&gt;
 
 &lt;!-- imported.xml --&gt;
 &lt;project name="imported" basedir="." default="..."&gt;
-&nbsp; &lt;property file="imported.properties"/&gt;
-&lt;/project&gt;
-</pre>
+  &lt;property file="imported.properties"/&gt;
+&lt;/project&gt;</pre>
 
-<p>This snippet however will resolve <code>imported.properties</code>
-against the basedir of <code>importing.xml</code>, because the basedir
-of <code>imported.xml</code> is ignored by Ant. The right way to use
-<code>imported.properties</code> is:</p>
+  <p>This snippet however will resolve <samp>imported.properties</samp> against
+  the <var>basedir</var> of <samp>importing.xml</samp>, because the <var>basedir</var>
+  of <samp>imported.xml</samp> is ignored by Ant. The right way to
+  use <samp>imported.properties</samp> is:</p>
 
-<pre>
+  <pre>
 &lt;!-- imported.xml --&gt;
 &lt;project name="imported" basedir="." default="..."&gt;
-&nbsp; &lt;dirname property="imported.basedir" file="${ant.file.imported}"/&gt;
-&nbsp; &lt;property file="${imported.basedir}/imported.properties"/&gt;
-&lt;/project&gt;
-</pre>
+  &lt;dirname property="imported.basedir" file="${ant.file.imported}"/&gt;
+  &lt;property file="${imported.basedir}/imported.properties"/&gt;
+&lt;/project&gt;</pre>
 
-<p>As explained above <code>${ant.file.imported}</code> stores the
-path of the build script, that defines the project called
-<code>imported</code>, (in short it stores the path to
-<code>imported.xml</code>) and <a
-href="dirname.html"><code>&lt;dirname&gt;</code></a> takes its
-directory. This technique also allows <code>imported.xml</code> to be
-used as a standalone file (without being imported in other
-project).</p>
+  <p>As explained above <code>ant.file.imported</code> stores the path of the build script, that
+    defines the project called <q>imported</q>, (in short it stores the path
+    to <samp>imported.xml</samp>) and <a href="dirname.html"><code>&lt;dirname&gt;</code></a> takes
+    its directory. This technique also allows <samp>imported.xml</samp> to be used as a standalone
+    file (without being imported in other project).</p>
 
-<p>The above description only works for imported files that actually
-  are imported from files and not from URLs.  For files imported from
-  URLs using resources relative to the imported file requires you to
-  use tasks that can work on non-file resources in the first place.
-  To create a relative resource you'd use something like:</p>
+  <p>The above description only works for imported files that actually are imported from files and
+    not from URLs.  For files imported from URLs using resources relative to the imported file
+    requires you to use tasks that can work on non-file resources in the first place.  To create a
+    relative resource you'd use something like:</p>
 
-<pre>
-  &lt;loadproperties&gt;
-    &lt;url baseUrl="${ant.file.imported}"
-         relativePath="imported.properties"/&gt;
-  &lt;/loadproperties&gt;
-</pre>
+  <pre>
+&lt;loadproperties&gt;
+  &lt;url baseUrl="${ant.file.imported}"
+       relativePath="imported.properties"/&gt;
+&lt;/loadproperties&gt;</pre>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <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>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="top">
-        file
-      </td>
-      <td valign="top">
-        The file to import. If this is a relative file name, the file name will be resolved
-        relative to the <i>importing</i> file. <b>Note</b>, this is unlike most other
-        ant file attributes, where relative files are resolved relative to ${basedir}.
-      </td>
-      <td valign="top" align="center">Yes or a nested resource collection</td>
+      <td>file</td>
+      <td>The file to import. If this is a relative file name, the file name will be resolved
+        relative to the <em>importing</em> file. <strong>Note</strong>: this is unlike most other
+        Ant file attributes, where relative files are resolved relative to <var>basedir</var>.</td>
+      <td>Yes or a nested resource collection</td>
     </tr>
     <tr>
-      <td valign="top">
-        optional
-      </td>
-      <td valign="top">
-        If true, do not stop the build if the file does not exist,
-        default is false.
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>optional</td>
+      <td>If <q>true</q>, do not stop the build if the file does not exist.</td>
+      <td>No; default is <q>false</q></td>
     </tr>
     <tr>
-      <td valign="top">
-        as
-      </td>
-      <td valign="top">
-        Specifies the prefix prepended to the target names.  If
-        omitted, the name attribute of the project tag of the
-        imported file will be used.
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>as</td>
+      <td>Specifies the prefix prepended to the target names.</td>
+      <td>No; defaults to <var>name</var> attribute of the <code>project</code> tag of the imported
+        file</td>
     </tr>
     <tr>
-      <td valign="top">
-        prefixSeparator
-      </td>
-      <td valign="top">
-        Specifies the separator to be used between the prefix and the
-        target name.  Defaults to ".".
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>prefixSeparator</td>
+      <td>Specifies the separator to be used between the prefix and the target name.</td>
+      <td>No; defaults to <q>.</q></td>
     </tr>
   </tbody>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>any <a href="../Types/resources.html">resource</a> or resource
-collection</h4>
-
-<p>The specified resources will be imported.  <em>Since Ant
-    1.8.0</em></p>
+<h4>any <a href="../Types/resources.html">resource</a> or resource collection</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>The specified resources will be imported.</p>
 
 <h3>Examples</h3>
-<pre>&nbsp; &lt;import file=&quot;../common-targets.xml&quot;/&gt;
-</pre>
+<pre>&lt;import file=&quot;../common-targets.xml&quot;/&gt;</pre>
 
-<p>Imports targets from the common-targets.xml file that is in a parent
-directory.</p>
+<p>Imports targets from the <samp>common-targets.xml</samp> file that is in a parent directory.</p>
 
-<pre>&nbsp; &lt;import file=&quot;${deploy-platform}.xml&quot;/&gt;
-</pre>
+<pre>&lt;import file=&quot;${deploy-platform}.xml&quot;/&gt;</pre>
 
-<p>Imports the project defined by the property deploy-platform</p>
+<p>Imports the project defined by the property <code>deploy-platform</code></p>
 
 <pre>
-  &lt;import&gt;
-    &lt;javaresource name="common/targets.xml"&gt;
-      &lt;classpath location="common.jar"/&gt;
-    &lt;/javaresource&gt;
-  &lt;/import&gt;
-</pre>
+&lt;import&gt;
+  &lt;javaresource name="common/targets.xml"&gt;
+    &lt;classpath location="common.jar"/&gt;
+  &lt;/javaresource&gt;
+&lt;/import&gt;</pre>
 
-<p>Imports targets from the targets.xml file that is inside the
-  directory common inside the jar file common.jar.</p>
+<p>Imports targets from the <samp>targets.xml</samp> file that is inside the
+directory <samp>common</samp> inside the jar file <samp>common.jar</samp>.</p>
 
-<h3>How is &lt;import&gt; different
-  from <a href="include.html">&lt;include&gt;</a>?</h3>
+<h3>How is &lt;import&gt; different from <a href="include.html">&lt;include&gt;</a>?</h3>
 
-<p>The short version: Use import if you intend to override a target,
-  otherwise use include.</p>
+<p>The short version: Use <code>import</code> if you intend to override a target, otherwise
+use <code>include</code>.</p>
 
-<p>When using import the imported targets are available by up to two
-  names.  Their "normal" name without any prefix and potentially with
-  a prefixed name (the value of the as attribute or the imported
-  project's name attribute, if any).</p>
+<p>When <code>import</code> is used, the imported targets are available by up to two names: their
+"normal" name without any prefix and potentially with a prefixed name (the value of
+the <var>as</var> attribute or the imported project's <var>name</var> attribute, if any).</p>
 
-<p>When using include the included targets are only available in the
-  prefixed form.</p>
+<p>When <code>include</code> is used, the included targets are only available in the prefixed form.</p>
 
-<p>When using import, the imported target's depends attribute
-  remains unchanged, i.e. it uses "normal" names and allows you to
-  override targets in the dependency list.</p>
+<p>When <code>import</code> is used, the imported target's <var>depends</var> attribute remains
+unchanged, i.e. it uses "normal" names and allows you to override targets in the dependency
+list.</p>
 
-<p>When using include, the included targets cannot be overridden and
-  their depends attributes are rewritten so that prefixed names are
-  used.  This allows writers of the included file to control which
-  target is invoked as part of the dependencies.</p>
+<p>When <code>include</code> is used, the included targets cannot be overridden and
+their <var>depends</var> attributes are rewritten so that prefixed names are used.  This allows
+writers of the included file to control which target is invoked as part of the dependencies.</p>
 
-<p>It is possible to include the same file more than once by using
-  different prefixes, it is not possible to import the same file more
-  than once.</p>
+<p>It is possible to <code>include</code> the same file more than once by using different prefixes;
+it is not possible to <code>import</code> the same file more than once.</p>
 
 <h4>Examples</h4>
 
-<p><i>nested.xml</i> shall be:</p>
+<p><samp>nested.xml</samp> shall be:</p>
 
 <pre>
 &lt;project&gt;
@@ -288,10 +230,9 @@
   &lt;target name="echo" depends="setUp"&gt;
     &lt;echo&gt;prop has the value ${prop}&lt;/echo&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>When using import like in</p>
+<p>When using <code>import</code> like in</p>
 
 <pre>
 &lt;project default="test"&gt;
@@ -302,12 +243,11 @@
   &lt;import file="nested.xml" as="nested"/&gt;
 
   &lt;target name="test" depends="nested.echo"/&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>Running the build file will emit:
+<p>Running the build file will emit:</p>
 
-<pre>
+<pre class="output">
 setUp:
 
 nested.echo:
@@ -317,7 +257,7 @@
 
 </pre>
 
-<p>When using include like in</p>
+<p>When using <code>include</code> like in</p>
 
 <pre>
 &lt;project default="test"&gt;
@@ -328,12 +268,11 @@
   &lt;include file="nested.xml" as="nested"/&gt;
 
   &lt;target name="test" depends="nested.echo"/&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>Running the target build file will emit:
+<p>Running the target build file will emit:</p>
 
-<pre>
+<pre class="output">
 nested.setUp:
 
 nested.echo:
@@ -343,7 +282,7 @@
 
 </pre>
 
-<p>and there won't be any target named "echo" on the including build file.</p>
+<p>and there won't be any target named <q>echo</q> on the including build file.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/include.html b/manual/Tasks/include.html
index e210923..814be61 100644
--- a/manual/Tasks/include.html
+++ b/manual/Tasks/include.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,265 +15,206 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Include Task</title>
 </head>
 <body>
-  <h2><a name="include">Include</a></h2>
+  <h2 id="include">Include</h2>
+  <p><em>Since Apache Ant 1.8.0</em></p>
   <h3>Description</h3>
-  <p>
-    Include another build file into the current project.
-  </p>
+  <p>Include another build file into the current project.</p>
 
-  <p><em>since Apache Ant 1.8.0</em></p>
+  <p><strong>Note</strong> this task heavily relies on the ProjectHelper implementation and doesn't
+    really perform any work of its own.  If you have configured Ant to use a ProjectHelper other
+    than Ant's default, this task may or may not work.</p>
 
-  <p>
-    <b>Note</b> this task heavily relies on the ProjectHelper
-    implementation and doesn't really perform any work of its own.  If
-    you have configured Ant to use a ProjectHelper other than Ant's
-    default, this task may or may not work.
-  </p>
+  <p>On execution it will read another Ant file into the same project rewriting the included
+    target <var>name</var>s and <var>depends</var> lists.  This is different
+    from <a href="https://ant.apache.org/faq.html#xml-entity-include" target="_top">Entity Includes
+    as explained in the Ant FAQ</a> insofar as the target names get prefixed by the included
+    project's <var>name</var> or <var>as</var> attribute and do not appear as if the file was
+    contained in the including file.</p>
 
-  <p>
-    On execution it will read another Ant file into the same Project
-    rewriting the included target names and depends lists.  This is
-    different
-    from <a href="http://ant.apache.org/faq.html#xml-entity-include">Entity
-    Includes as explained in the Ant FAQ</a> insofar as the target
-    names get prefixed by the included project's name or the as
-    attribute and do not appear as if the file was contained in the
-    including file.
-  </p>
-  <p>
-    The include task may only be used as a top-level task. This means that
-    it may not be used in a target.
-  </p>
-  <p>
-There are two further functional aspects that pertain to this task and
-that are not possible with entity includes:
-<ul>
-  <li>target rewriting</li>
-  <li>special properties</li>
-</ul>
-  </p>
-<h4>Target rewriting</h4>
+  <p>The <code>include</code> task may only be used as a top-level task. This means that
+    it may not be used in a target.</p>
 
-<p>Any target in the included file will be renamed
-  to <i>prefix.name</i> where <i>name</i> is the original target's
-  name and <i>prefix</i> is either the value of the <i>as</i>
-  attribute or the <i>name</i> attribute of the <i>project</i> tag of
-  the included file.</p>
+  <p>There are two further functional aspects that pertain to this task and that are not possible
+    with entity includes:</p>
+  <ul>
+    <li>target rewriting</li>
+    <li>special properties</li>
+  </ul>
+  <h4>Target rewriting</h4>
 
-<p>The depends attribute of all included targets is rewritten so that
-  all target names are prefixed as well.  This makes the included file
-  self-contained.</p>
+  <p>Any target in the included file will be renamed to <q>prefix.name</q> where <q>name</q> is the
+    original target's name and <q>prefix</q> is either the value of the <var>as</var> attribute or
+    the <var>name</var> attribute of the <code>project</code> tag of the included file.</p>
 
-<p>Note that prefixes nest, so if a build file includes a file with
-  prefix "a" and the included file includes another file with prefix
-  "b", then the targets of that last build file will be prefixed by
-  "a.b.".</p>
+  <p>The <var>depends</var> attribute of all included targets is rewritten so that all target names
+    are prefixed as well.  This makes the included file self-contained.</p>
 
-<p><code>&lt;import&gt;</code> contribute to the prefix as well, but
-  only if their <code>as</code> attribute has been specified.
+  <p>Note that prefixes nest, so if a build file includes a file with prefix <q>q</q> and the
+    included file includes another file with prefix <q>b</q>, then the targets of that last build
+    file will be prefixed by <q>a.b.</q>.</p>
 
-<h4>Special Properties</h4>
+  <p><code>&lt;import&gt;</code> contribute to the prefix as well, but only if their <var>as</var>
+    attribute has been specified.
 
-<p>Included files are treated as they are present in the main
-buildfile. This makes it easy to understand, but it makes it impossible
-for them to reference files and resources relative to their path.
-Because of this, for every included file, Ant adds a property that
-contains the path to the included buildfile. With this path, the
-included buildfile can keep resources and be able to reference them
-relative to its position.</p>
+  <h4>Special properties</h4>
 
-<p>So if I include for example a <i>docsbuild.xml</i> file named <b>builddocs</b>,
-I can get its path as <b>ant.file.builddocs</b>, similarly to the <b>ant.file</b>
-property of the main buildfile.</p>
+  <p>Included files are treated as they are present in the main buildfile. This makes it easy to
+    understand, but it makes it impossible for them to reference files and resources relative to
+    their path.  Because of this, for every included file, Ant adds a property that contains the
+    path to the included buildfile. With this path, the included buildfile can keep resources and be
+    able to reference them relative to its position.</p>
 
-<p>Note that &quot;builddocs&quot; is not the filename, but the name attribute
-present in the included project tag.</p>
-  <p>
-    If the included file does not have a name attribute, the ant.file.projectname
-    property will not be set.
-  </p>
+  <p>So if I include for example a <samp>docsbuild.xml</samp> file named <q>builddocs</q>, I can get
+    its path as <code>ant.file.builddocs</code>, similarly to the <code>ant.file</code> property of
+    the main buildfile.</p>
 
-<p>If you need to know whether the current build file's source has
-  been a file or an URL you can consult the
-  property <b>ant.file.type.<em>projectname</em></b> (using the same
-  example as above <b>ant.file.type.builddocs</b>) which either have
-  the value "file" or "url".</p>
+  <p>Note that <q>builddocs</q> is not the filename, but the <var>name</var> attribute present in
+    the included <code>project</code> tag.</p>
+  <p>If the included file does not have a <var>name</var> attribute,
+    the <code>ant.file.<i>projectname</i></code> property will not be set.</p>
 
-<h4>Resolving files against the included file</h4>
+  <p>If you need to know whether the current build file's source has been a file or an URL you can
+    consult the property <code>ant.file.type.<i>projectname</i></code> (using the same example as
+    above <code>ant.file.type.builddocs</code>) which either have the value <q>file</q>
+    or <q>url</q>.</p>
 
-<p>Suppose your main build file called <code>including.xml</code>
-includes a build file <code>included.xml</code>, located anywhere on
-the file system, and <code>included.xml</code> reads a set of
-properties from <code>included.properties</code>:</p>
+  <h4>Resolving files against the included file</h4>
 
-<pre>&lt;!-- including.xml --&gt;
+  <p>Suppose your main build file called <samp>including.xml</samp> includes a build
+    file <samp>included.xml</samp>, located anywhere on the file system,
+    and <samp>included.xml</samp> reads a set of properties
+    from <samp>included.properties</samp>:</p>
+
+  <pre>
+&lt;!-- including.xml --&gt;
 &lt;project name="including" basedir="." default="..."&gt;
-&nbsp; &lt;include file="${path_to_included}/included.xml"/&gt;
+  &lt;include file="${path_to_included}/included.xml"/&gt;
 &lt;/project&gt;
 
 &lt;!-- included.xml --&gt;
 &lt;project name="included" basedir="." default="..."&gt;
-&nbsp; &lt;property file="included.properties"/&gt;
-&lt;/project&gt;
-</pre>
+  &lt;property file="included.properties"/&gt;
+&lt;/project&gt;</pre>
 
-<p>This snippet however will resolve <code>included.properties</code>
-against the basedir of <code>including.xml</code>, because the basedir
-of <code>included.xml</code> is ignored by Ant. The right way to use
-<code>included.properties</code> is:</p>
+  <p>This snippet however will resolve <samp>included.properties</samp> against
+    the <var>basedir</var> of <samp>including.xml</samp>, because the <var>basedir</var>
+    of <samp>included.xml</samp> is ignored by Ant. The right way to
+    use <samp>included.properties</samp> is:</p>
 
-<pre>
+  <pre>
 &lt;!-- included.xml --&gt;
 &lt;project name="included" basedir="." default="..."&gt;
-&nbsp; &lt;dirname property="included.basedir" file="${ant.file.included}"/&gt;
-&nbsp; &lt;property file="${included.basedir}/included.properties"/&gt;
-&lt;/project&gt;
-</pre>
+  &lt;dirname property="included.basedir" file="${ant.file.included}"/&gt;
+  &lt;property file="${included.basedir}/included.properties"/&gt;
+&lt;/project&gt;</pre>
 
-<p>As explained above <code>${ant.file.included}</code> stores the
-path of the build script, that defines the project called
-<code>included</code>, (in short it stores the path to
-<code>included.xml</code>) and <a
-href="dirname.html"><code>&lt;dirname&gt;</code></a> takes its
-directory. This technique also allows <code>included.xml</code> to be
-used as a standalone file (without being included in other
-project).</p>
+  <p>As explained above <code>ant.file.included</code> stores the path of the build script, that
+    defines the project called <q>included</q>, (in short it stores the path
+    to <samp>included.xml</samp>) and <a href="dirname.html"><code>&lt;dirname&gt;</code></a> takes
+    its directory. This technique also allows <samp>included.xml</samp> to be used as a standalone
+    file (without being included in other project).</p>
 
-<p>The above description only works for included files that actually
-  are included from files and not from URLs.  For files included from
-  URLs using resources relative to the included file requires you to
-  use tasks that can work on non-file resources in the first place.
-  To create a relative resource you'd use something like:</p>
+  <p>The above description only works for included files that actually are included from files and
+    not from URLs.  For files included from URLs using resources relative to the included file
+    requires you to use tasks that can work on non-file resources in the first place.  To create a
+    relative resource you'd use something like:</p>
 
-<pre>
-  &lt;loadproperties&gt;
-    &lt;url baseUrl="${ant.file.included}"
-         relativePath="included.properties"/&gt;
-  &lt;/loadproperties&gt;
-</pre>
+  <pre>
+&lt;loadproperties&gt;
+  &lt;url baseUrl="${ant.file.included}"
+       relativePath="included.properties"/&gt;
+&lt;/loadproperties&gt;</pre>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <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>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="top">
-        file
-      </td>
-      <td valign="top">
-        The file to include. If this is a relative file name, the file name will be resolved
-        relative to the <i>including</i> file. <b>Note</b>, this is unlike most other
-        ant file attributes, where relative files are resolved relative to ${basedir}.
-      </td>
-      <td valign="top" align="center">Yes or a nested resource collection</td>
+      <td>file</td>
+      <td>The file to include. If this is a relative file name, the file name will be resolved
+        relative to the <em>including</em> file. <strong>Note</strong>, this is unlike most other
+        ant file attributes, where relative files are resolved relative to ${basedir}.</td>
+      <td>Yes or a nested resource collection</td>
     </tr>
     <tr>
-      <td valign="top">
-        optional
-      </td>
-      <td valign="top">
-        If true, do not stop the build if the file does not exist,
-        default is false.
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>optional</td>
+      <td>If <q>true</q>, do not stop the build if the file does not exist.</td>
+      <td>No; default is <q>false</q></td>
     </tr>
     <tr>
-      <td valign="top">
-        as
-      </td>
-      <td valign="top">
-        Specifies the prefix prepended to the target names.  If
-        omitted, the name attribute of the project tag of the
-        included file will be used.
-      </td>
-      <td valign="top" align="center">Yes, if the included file's
-        project tag doesn't specify a name attribute.</td>
+      <td>as</td>
+      <td>Specifies the prefix prepended to the target names.</td>
+      <td>Yes, if the included file's <code>project</code> tag doesn't specify a <var>name</var>
+        attribute (which is otherwise taken as default)</td>
     </tr>
     <tr>
-      <td valign="top">
-        prefixSeparator
-      </td>
-      <td valign="top">
-        Specifies the separator to be used between the prefix and the
-        target name.  Defaults to ".".
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>prefixSeparator</td>
+      <td>Specifies the separator to be used between the prefix and the target name.</td>
+      <td>No; defaults to <q>.</q></td>
     </tr>
   </tbody>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>any <a href="../Types/resources.html">resource</a> or resource
-collection</h4>
+<h4>any <a href="../Types/resources.html">resource</a> or resource collection</h4>
 
 <p>The specified resources will be included.</p>
 
 <h3>Examples</h3>
-<pre>&nbsp; &lt;include file=&quot;../common-targets.xml&quot;/&gt;
-</pre>
+<pre>&lt;include file=&quot;../common-targets.xml&quot;/&gt;</pre>
 
-<p>Includes targets from the common-targets.xml file that is in a parent
-directory.</p>
+<p>Includes targets from the <samp>common-targets.xml</samp> file that is in a parent directory.</p>
 
-<pre>&nbsp; &lt;include file=&quot;${deploy-platform}.xml&quot;/&gt;
-</pre>
+<pre>&lt;include file=&quot;${deploy-platform}.xml&quot;/&gt;</pre>
 
 <p>Includes the project defined by the property deploy-platform</p>
 
 <pre>
-  &lt;include&gt;
-    &lt;javaresource name="common/targets.xml"&gt;
-      &lt;classpath location="common.jar"/&gt;
-    &lt;/javaresource&gt;
-  &lt;/include&gt;
-</pre>
+&lt;include&gt;
+  &lt;javaresource name="common/targets.xml"&gt;
+    &lt;classpath location="common.jar"/&gt;
+  &lt;/javaresource&gt;
+&lt;/include&gt;</pre>
 
-<p>Includes targets from the targets.xml file that is inside the
-  directory common inside the jar file common.jar.</p>
+<p>Includes targets from the <samp>targets.xml</samp> file that is inside the
+directory <samp>common</samp> inside the jar file <samp>common.jar</samp>.</p>
 
-<h3>How is <a href="import.html">&lt;import&gt;</a> different
-  from &lt;include&gt;?</h3>
+<h3>How is <a href="import.html">&lt;import&gt;</a> different from &lt;include&gt;?</h3>
 
-<p>The short version: Use import if you intend to override a target,
-  otherwise use include.</p>
+<p>The short version: Use <code>import</code> if you intend to override a target, otherwise
+use <code>include</code>.</p>
 
-<p>When using import the imported targets are available by up to two
-  names.  Their "normal" name without any prefix and potentially with
-  a prefixed name (the value of the as attribute or the imported
-  project's name attribute, if any).</p>
+<p>When <code>import</code> is used, the imported targets are available by up to two names: their
+"normal" name without any prefix and potentially with a prefixed name (the value of
+the <var>as</var> attribute or the imported project's <var>name</var> attribute, if any).</p>
 
-<p>When using include the included targets are only available in the
-  prefixed form.</p>
+<p>When <code>include</code> is used, the included targets are only available in the prefixed form.</p>
 
-<p>When using import, the imported target's depends attribute
-  remains unchanged, i.e. it uses "normal" names and allows you to
-  override targets in the dependency list.</p>
+<p>When <code>import</code> is used, the imported target's <var>depends</var> attribute remains
+unchanged, i.e. it uses "normal" names and allows you to override targets in the dependency
+list.</p>
 
-<p>When using include, the included targets cannot be overridden and
-  their depends attributes are rewritten so that prefixed names are
-  used.  This allows writers of the included file to control which
-  target is invoked as part of the dependencies.</p>
+<p>When <code>include</code> is used, the included targets cannot be overridden and
+their <var>depends</var> attributes are rewritten so that prefixed names are used.  This allows
+writers of the included file to control which target is invoked as part of the dependencies.</p>
 
-<p>It is possible to include the same file more than once by using
-  different prefixes, it is not possible to import the same file more
-  than once.</p>
+<p>It is possible to <code>include</code> the same file more than once by using different prefixes;
+it is not possible to <code>import</code> the same file more than once.</p>
 
 <h4>Examples</h4>
 
-<p><i>nested.xml</i> shall be:</p>
+<p><samp>nested.xml</samp> shall be:</p>
 
 <pre>
 &lt;project&gt;
@@ -283,10 +225,9 @@
   &lt;target name="echo" depends="setUp"&gt;
     &lt;echo&gt;prop has the value ${prop}&lt;/echo&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>When using import like in</p>
+<p>When using <code>import</code> like in</p>
 
 <pre>
 &lt;project default="test"&gt;
@@ -297,12 +238,11 @@
   &lt;import file="nested.xml" as="nested"/&gt;
 
   &lt;target name="test" depends="nested.echo"/&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>Running the build file will emit:
+<p>Running the build file will emit:</p>
 
-<pre>
+<pre class="output">
 setUp:
 
 nested.echo:
@@ -312,7 +252,7 @@
 
 </pre>
 
-<p>When using include like in</p>
+<p>When using <code>include</code> like in</p>
 
 <pre>
 &lt;project default="test"&gt;
@@ -323,12 +263,11 @@
   &lt;include file="nested.xml" as="nested"/&gt;
 
   &lt;target name="test" depends="nested.echo"/&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>Running the target build file will emit:
+<p>Running the target build file will emit:</p>
 
-<pre>
+<pre class="output">
 nested.setUp:
 
 nested.echo:
@@ -338,7 +277,7 @@
 
 </pre>
 
-<p>and there won't be any target named "echo" on the including build file.</p>
+<p>and there won't be any target named <q>echo</q> on the including build file.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/input.html b/manual/Tasks/input.html
index b04affc..6dedb7c 100644
--- a/manual/Tasks/input.html
+++ b/manual/Tasks/input.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,185 +15,166 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Input Task</title>
 </head>
 
 <body>
 
-<h2><a name="input">Input</a></h2>
+<h2 id="input">Input</h2>
 <h3>Description</h3>
 
-<p>Allows user interaction during the build process by prompting for
-input.  To do so, it uses the configured 
-<a href="../inputhandler.html">InputHandler</a>.</p>
+<p>Allows user interaction during the build process by prompting for input.  To do so, it uses the
+configured <a href="../inputhandler.html">InputHandler</a>.</p>
 
-<p>The prompt can be set via the message attribute or as character
-data nested into the element.</p>
+<p>The prompt can be set via the <var>message</var> attribute or as character data nested into the
+element.</p>
 
-<p>Optionally a set of valid input arguments can be defined via the
-validargs attribute. Input task will not accept a value that doesn't match
-one of the predefined.</p>
+<p>Optionally a set of valid input arguments can be defined via the <var>validargs</var>
+attribute. <code>Input</code> task will not accept a value that doesn't match one of the
+predefined.</p>
 
-<p>Optionally a property can be created from the value entered by the
-user. This property can then be used during the following build
-run. Input behaves according to <a href="property.html">property
-task</a> which means that existing properties cannot be overridden.
-Since Apache Ant 1.6, <code>&lt;input&gt;</code> will not prompt for input if
-a property should be set by the task that has already been set in the
-project (and the task wouldn't have any effect).</p>
+<p>Optionally a property can be created from the value entered by the user. This property can then
+be used during the following build run. <code>Input</code> then behaves
+as <a href="property.html">property task</a> which means that existing properties cannot be
+overridden.  <em>Since Apache Ant 1.6</em>, <code>&lt;input&gt;</code> will not prompt for input if
+a property should be set by the task that has already been set in the project (and the task wouldn't
+have any effect).</p>
 
-<p>Historically, a regular complaint about this task has been that it echoes
-characters to the console, this is a critical security defect, we must fix it
-immediately, etc, etc.  This problem was due to the lack in early versions of
-Java of a (fully functional) facility for handling secure console input.
-In Java 1.6 that shortcoming in Java's API was addressed and Ant versions 1.7.1
-and 1.8 have added support for Java 1.6's secure console input feature
-(see <a href="#handler.type">handler type</a>).</p>
+<p>Historically, a regular complaint about this task has been that it echoes characters to the
+console, this is a critical security defect, we must fix it immediately, etc, etc.  This problem was
+due to the lack in early versions of Java of a (fully functional) facility for handling secure
+console input.  In Java 6 that shortcoming in Java's API was addressed and Ant versions 1.7.1 and
+1.8 have added support for Java 6 secure console input feature (see <a href="#handler.type">handler
+type</a>).</p>
 
-<p>
-IDE behaviour depends upon the IDE: some hang waiting for input, some let you
-type it in. For this situation, place the password in a (secured) property
-file and load in before the input task.</p>
+<p>IDE behaviour depends upon the IDE: some hang waiting for input, some let you type it in. For
+this situation, place the password in a (secured) property file and load in before
+the <code>input</code> task.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">message</td>
-    <td valign="top">the Message which gets displayed to the user
-    during the build run.</td>
-    <td valign="top" align="center">No</td>
+    <td>message</td>
+    <td>the Message which gets displayed to the user during the build run.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">validargs</td>
-    <td valign="top">comma separated String containing valid input
-    arguments. If set, input task will reject any input not defined
-    here.  Validargs are compared case sensitive. If you want 'a' and
-    'A' to be accepted you will need to define both arguments within
-    validargs.</td>
-    <td valign="top" align="center">No</td>
+    <td>validargs</td>
+    <td>comma separated String containing valid input arguments. If set, <code>input</code> task
+      will reject any input not defined here. Comparison of input to <var>validargs</var> is case
+      sensitive. If you want <q>a</q> and
+    <q>A</q> to be accepted you will need to define both arguments within <var>validargs</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">addproperty</td>
-    <td valign="top">the name of a property to be created from
-    input. Behaviour is equal to <a href="property.html">property
-    task</a> which means that existing properties cannot be
-    overridden.</td>
-    <td valign="top" align="center">No</td>
+    <td>addproperty</td>
+    <td>the name of a property to be created from input. Behaviour is equal
+      to <a href="property.html">property task</a> which means that existing properties cannot be
+      overridden.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultvalue</td>
-    <td valign="top">Defines the default value of the property to be
-    created from input.  Property value will be set to default if no
-    input is received.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultvalue</td>
+    <td>Defines the default value of the property to be created from input.  Property value will be
+      set to default if no input is received.</td>
+    <td>No</td>
   </tr>
 </table>
-<h3>Parameters Specified as Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 <h4>Handler</h4>
-<p>Since <b>Ant 1.7</b>, a nested &lt;handler&gt; element can be used to
-specify an InputHandler, so that different InputHandlers may be used
-among different Input tasks.
+<p><em>Since Ant 1.7</em>, a nested <code>&lt;handler&gt;</code> element can be used to specify
+an <code>InputHandler</code>, so that different <code>InputHandler</code>s may be used among
+different <code>Input</code> tasks.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr id="handler.type">
+    <td>type</td>
+    <td>one of <q>default</q>, <q>propertyfile</q>, <q>greedy</q>, or <q>secure</q> (<em>since Ant
+      1.8</em>).</td>
+    <td rowspan="3">One of these</td>
   </tr>
   <tr>
-    <td valign="top"><a name="handler.type" />type</td>
-    <td valign="top">one of "default","propertyfile", "greedy", or "secure" (since Ant 1.8).
+    <td>refid</td>
+    <td class="left">Reference to an <code>InputHandler</code> defined elsewhere in the
+      project.</td>
+  </tr>
+  <tr>
+    <td>classname</td>
+    <td class="left">The name of an <code>InputHandler</code> subclass.</td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>The classpath to use with <var>classname</var>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The refid of a classpath to use with <var>classname</var>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>loaderref</td>
+    <td>The refid of a classloader to use with <var>classname</var>.
     </td>
-    <td align="center" valign="top" rowspan="3">One of these</td>
-  </tr>
-  <tr>
-    <td valign="top">refid</td>
-    <td valign="top">Reference to an <code>InputHandler</code>
-        defined elsewhere in the project.
-    </td>
-  </tr>
-  <tr>
-    <td valign="top">classname</td>
-    <td valign="top">The name of an <code>InputHandler</code> subclass.</td>
-  </tr>
-  <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to use with <i>classname</i>.</td>
-    <td valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The refid of a classpath to use with <i>classname</i>.</td>
-    <td valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">loaderref</td>
-    <td valign="top">The refid of a classloader to use with <i>classname</i>.
-    </td>
-    <td valign="top">No</td>
+    <td>No</td>
   </tr>
 </table>
-<br />
-The classpath can also be specified by means of one or more nested
-&lt;classpath&gt; elements.</p>
+<p>The classpath can also be specified by means of one or more nested <code>&lt;classpath&gt;</code>
+elements.</p>
 
 <h3>Examples</h3>
-<pre>  &lt;input/&gt;</pre>
-<p>Will pause the build run until return key is pressed when using the
-<a href="../inputhandler.html#defaulthandler">default
-InputHandler</a>, the concrete behavior is defined by the InputHandler
-implementation you use.</p>
-<pre>  &lt;input&gt;Press Return key to continue...&lt;/input&gt;</pre>
-<p>Will display the message &quot;Press Return key to
-continue...&quot; and pause the build run until return key is pressed
-(again, the concrete behavior is implementation dependent).</p>
-<pre>  &lt;input
-    message=&quot;Press Return key to continue...&quot;
-  /&gt;</pre>
-<p>Will display the message &quot;Press Return key to
-continue...&quot; and pause the build run until return key is pressed
-(see above).</p>
+<p>Pause the build run until return key is pressed when using
+the <a href="../inputhandler.html#defaulthandler">default InputHandler</a>, the concrete behavior is
+defined by the <code>InputHandler</code> implementation you use.</p>
+<pre>&lt;input/&gt;</pre>
+
+<p>Display the message <q>Press Return key to continue...</q> and pause the build run until return
+key is pressed (again, the concrete behavior is implementation dependent).</p>
+<pre>&lt;input&gt;Press Return key to continue...&lt;/input&gt;</pre>
+
+<p>Display the message <q>Press Return key to continue...</q> and pause the build run until return
+key is pressed (see above).</p>
+<pre>&lt;input message=&quot;Press Return key to continue...&quot;/&gt;</pre>
+
+<p>Display the message <q>All data is going to be deleted from DB continue (y/n)?</q> and
+require <q>y</q> to continue build or <q>n</q> to exit build with following message <q>Build aborted
+by user.</q>.</p>
 <pre>
-  &lt;input
-    message=&quot;All data is going to be deleted from DB continue (y/n)?&quot;
-    validargs=&quot;y,n&quot;
-    addproperty=&quot;do.delete&quot;
-  /&gt;
-  &lt;condition property=&quot;do.abort&quot;&gt;
-    &lt;equals arg1=&quot;n&quot; arg2=&quot;${do.delete}&quot;/&gt;
-  &lt;/condition&gt;
-  &lt;fail if=&quot;do.abort&quot;&gt;Build aborted by user.&lt;/fail&gt;
+&lt;input message=&quot;All data is going to be deleted from DB continue (y/n)?&quot;
+       validargs=&quot;y,n&quot;
+       addproperty=&quot;do.delete&quot;/&gt;
+&lt;condition property=&quot;do.abort&quot;&gt;
+  &lt;equals arg1=&quot;n&quot; arg2=&quot;${do.delete}&quot;/&gt;
+&lt;/condition&gt;
+&lt;fail if=&quot;do.abort&quot;&gt;Build aborted by user.&lt;/fail&gt;
 </pre>
-<p>Will display the message &quot;All data is going to be deleted from
-DB continue (y/n)?&quot; and require 'y' to continue build or 'n' to
-exit build with following message &quot;Build aborted by
-user.&quot;.</p>
-<pre>  &lt;input
-    message=&quot;Please enter db-username:&quot;
-    addproperty=&quot;db.user&quot;
-  /&gt;</pre>
-<p>Will display the message &quot;Please enter db-username:&quot; and set the
-property <code>db.user</code> to the value entered by the user.</p>
 
-<pre>  &lt;input
-    message=&quot;Please enter db-username:&quot;
-    addproperty=&quot;db.user&quot;
-    defaultvalue=&quot;Scott-Tiger&quot;
-  /&gt;</pre>
-<p>Same as above, but will set <code>db.user</code> to the value
-<i>Scott- Tiger</i> if the user enters no value (simply types
-&lt;return&gt;).</p>
+<p>Display the message <q>Please enter db-username:</q> and set the property <code>db.user</code> to
+the value entered by the user.</p>
+<pre>
+&lt;input message=&quot;Please enter db-username:&quot;
+       addproperty=&quot;db.user&quot;/&gt;</pre>
 
+<p>Same as above, but set <code>db.user</code> to the value <q>Scott-Tiger</q> if the user enters no
+value (simply presses <q>return</q>).</p>
+<pre>
+&lt;input message=&quot;Please enter db-username:&quot;
+       addproperty=&quot;db.user&quot;
+       defaultvalue=&quot;Scott-Tiger&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/jar.html b/manual/Tasks/jar.html
index f911967..517de8c 100644
--- a/manual/Tasks/jar.html
+++ b/manual/Tasks/jar.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,323 +15,295 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Jar Task</title>
 </head>
 
 <body>
 
-<h2><a name="jar">Jar</a></h2>
+<h2 id="jar">Jar</h2>
 <h3>Description</h3>
 <p>Jars a set of files.</p>
-<p>The <i>basedir</i> attribute is the reference directory from where to jar.</p>
+<p>The <var>basedir</var> attribute is the reference directory from where to jar.</p>
 <p>Note that file permissions will not be stored in the resulting jarfile.</p>
-<p>It is possible to refine the set of files that are being jarred. This can be
-done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and <i>defaultexcludes</i>
-attributes. With the <i>includes</i> or <i>includesfile</i> attribute you specify the files you want to
-have included by using patterns. The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
-the files you want to have excluded. This is also done with patterns. And
-finally with the <i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
-inclusion/exclusion of files works, and how to write patterns.</p>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>basedir</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
-<p>You can also use nested file sets for more flexibility, and specify
-multiple ones to merge together different trees of files into one JAR.
-The extended fileset and groupfileset child elements from the zip task are
-also available in the jar task.
-See the <a href="zip.html">Zip</a> task for more details and examples.</p>
 
-<p>The <code>update</code> parameter controls what happens if the JAR
-file already exists. When set to <code>yes</code>, the JAR file is
-updated with the files specified. When set to <code>no</code> (the
-default) the JAR file is overwritten. An example use of this is
-provided in the <a href="zip.html">Zip task documentation</a>.  Please
-note that ZIP files store file modification times with a granularity
-of two seconds.  If a file is less than two seconds newer than the
-entry in the archive, Ant will not consider it newer.</p>
+<p>It is possible to refine the set of files that are being jarred. This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+and <var>defaultexcludes</var> attributes. With the <var>includes</var> or <var>includesfile</var>
+attribute you specify the files you want to have included by using patterns. The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded. This is
+also done with patterns. And finally with the <var>defaultexcludes</var> attribute, you can specify
+whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+inclusion/exclusion of files works, and how to write patterns.</p>
+
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>basedir</var>) as well as
+the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+<p>You can also use nested file sets for more flexibility, and specify multiple ones to merge
+together different trees of files into one JAR.  The extended <code>fileset</code>
+and <code>groupfileset</code> child elements from the <code>zip</code> task are also available in
+the <code>jar</code> task.  See the <a href="zip.html">Zip</a> task for more details and
+examples.</p>
+
+<p>The <var>update</var> parameter controls what happens if the JAR file already exists. When set
+to <q>yes</q>, the JAR file is updated with the files specified. When set to <q>no</q> (the default)
+the JAR file is overwritten. An example use of this is provided in the <a href="zip.html">Zip task
+documentation</a>.  Please note that ZIP files store file modification times with a granularity of 2
+seconds.  If a file is less than 2 seconds newer than the entry in the archive, Ant will not
+consider it newer.</p>
 
 <p>If the manifest is omitted, a simple one will be supplied by Apache Ant.</p>
 
-<p>The <code>whenmanifestonly</code> parameter controls what happens when no
-files, apart from the manifest file, or nested services, match.
-If <code>skip</code>, the JAR is not created and a warning is issued.
-If <code>fail</code>, the JAR is not created and the build is halted with an error.
-If <code>create</code>, (default) an empty JAR file (only containing a manifest and services)
-is created.</p>
+<p>The <var>whenmanifestonly</var> parameter controls what happens when no files, apart from the
+manifest file, or nested services, match.  If <q>skip</q>, the JAR is not created and a warning is
+issued.  If <q>fail</q>, the JAR is not created and the build is halted with an error.
+If <q>create</q> (default), an empty JAR file (only containing a manifest and services) is
+created.</p>
 
-<p>(The Jar task is a shortcut for specifying the manifest file of a JAR file.
-The same thing can be accomplished by using the <i>fullpath</i>
-attribute of a zipfileset in a Zip task. The one difference is that if the
-<i>manifest</i> attribute is not specified, the Jar task will
-include an empty one for you.)</p>
+<p>(The <code>Jar</code> task has a shortcut for specifying the manifest file of a JAR file.  The
+same thing can be accomplished by using the <var>fullpath</var> attribute of
+a <code>zipfileset</code> in a <code>Zip</code> task. The one difference is that if
+the <var>manifest</var> attribute is not specified, the <code>Jar</code> task will include an empty
+one for you.)</p>
 
-<p>Manifests are processed by the Jar task according to the
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html">Jar file specification.</a>
-Note in particular that this may result in manifest lines greater than 72 bytes
-being wrapped and continued on the next line.</p>
+<p>Manifests are processed by the <code>Jar</code> task according to
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html" target="_top">Jar
+file specification.</a>  Note in particular that this may result in manifest lines greater than 72
+bytes being wrapped and continued on the next line.</p>
 
-<p>The Jar task checks whether you specified package information according to the
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/versioning/spec/versioning2.html#wp90779">
-versioning specification</a>.</p>
+<p>The <code>Jar</code> task checks whether you specified package information according to
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"
+target="_top">versioning specification</a>.</p>
 
-<p><b>Please note that the zip format allows multiple files of the same
-fully-qualified name to exist within a single archive. This has been
-documented as causing various problems for unsuspecting users. If you wish
-to avoid this behavior you must set the <code>duplicate</code> attribute
-to a value other than its default, <code>"add"</code>.</b></p>
+<p><strong>Please note that the ZIP format allows multiple files of the same fully-qualified name to
+exist within a single archive. This has been documented as causing various problems for unsuspecting
+users. If you wish to avoid this behavior you must set the <var>duplicate</var> attribute to a value
+other than its default, <q>add</q>.</strong></p>
 
-<p>To cryptographically sign your JAR file, use the <a href="signjar.html">SignJar task</a> on the JAR that you create from this task.</p>
+<p>To cryptographically sign your JAR file, use the <a href="signjar.html">SignJar task</a> on the
+JAR that you create from this task.</p>
+
+<p>For creating a simple version of a <a href="https://openjdk.java.net/jeps/238" target="_top">JEP
+238 multi-release jar</a>, you don't need any special tools. Just set the
+required <code>manifest</code> entry and place the files where required, as you could see in
+the <a href="#jep238-example">JEP 238 example</a>. If you want to tune this kind of jar,
+e.g. decreasing the size by deleting 'same' classes from the versions-branches, you have to do more
+...</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">the JAR file to create.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>destfile</td>
+    <td>the JAR file to create.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the directory from which to jar the files.</td>
-    <td valign="top" align="center">No</td>
+    <td>basedir</td>
+    <td>the directory from which to jar the files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compress</td>
-    <td valign="top">Not only store data but also compress them,
-    defaults to true.  Unless you set the <em>keepcompression</em>
-    attribute to false, this will apply to the entire archive, not
-    only the files you've added while updating.</td>
-    <td align="center" valign="top">No</td>
+    <td>compress</td>
+    <td>Not only store data but also compress them.  Unless you set the <var>keepcompression</var>
+      attribute to <q>false</q>, this will apply to the entire archive, not only the files you've
+      added while updating.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">keepcompression</td>
-    <td valign="top">For entries coming from existing archives (like
-    nested <em>zipfileset</em>s or while updating the archive), keep
-    the compression as it has been originally instead of using the
-    <em>compress</em> attribute.  Defaults false.  <em>Since Ant
-    1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>keepcompression</td>
+    <td>For entries coming from existing archives (like nested <code>zipfileset</code>s or while
+      updating the archive), keep the compression as it has been originally instead of using the
+    <var>compress</var> attribute.  <em>Since Ant 1.6</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The character encoding to use for filenames
-      inside the archive.  Defaults to UTF8. <strong>It is not
-      recommended to change this value as the created archive will
-      most likely be unreadable for Java otherwise.</strong>
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The character encoding to use for filenames inside the archive. <strong>It is not
+      recommended to change this value as the created archive will most likely be unreadable for
+      Java otherwise.</strong>  <br/>See also the <a href="zip.html#encoding">discussion in the zip
+      task page</a></td>
+    <td>No; defaults to <q>UTF8</q></td>
   </tr>
   <tr>
-    <td valign="top">filesonly</td>
-    <td valign="top">Store only file entries, defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>filesonly</td>
+    <td>Store only file entries</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>)</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">manifest</td>
-    <td valign="top">the manifest file to use.  This can be either the location of a manifest, or the name of a jar added through a fileset.  If its the name of an added jar, the task expects the manifest to be in the jar at META-INF/MANIFEST.MF</td>
-    <td valign="top" align="center">No</td>
+    <td>manifest</td>
+    <td>the manifest file to use.  This can be either the location of a manifest, or the name of a
+      jar added through a fileset.  If its the name of an added jar, the task expects the manifest
+      to be in the jar at <samp>META-INF/MANIFEST.MF</samp></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">filesetmanifest</td>
-    <td valign="top">behavior when a Manifest is found in a zipfileset or zipgroupfileset file is found.  Valid values are &quot;skip&quot;, &quot;merge&quot;, and &quot;mergewithoutmain&quot;.  &quot;merge&quot; will merge all of the manifests together, and merge this into any other specified manifests.  &quot;mergewithoutmain&quot; merges everything but the Main section of the manifests.  Default value is &quot;skip&quot;.
+    <td>filesetmanifest</td>
+    <td>behavior when a manifest is found in a <code>zipfileset</code>
+      or <code>zipgroupfileset</code> file.  Valid values are <q>skip</q>, <q>merge</q>,
+      and <q>mergewithoutmain</q>.  <q>merge</q> will merge all of the manifests together, and merge
+      this into any other specified manifests.  <q>mergewithoutmain</q> merges everything but the
+      Main section of the manifests.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to <q>skip</q></td>
   </tr>
   <tr>
-    <td valign="top">update</td>
-    <td valign="top">indicates whether to update or overwrite
-      the destination file if it already exists.  Default is &quot;false&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>update</td>
+    <td>indicates whether to update or overwrite the destination file if it already exists</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">whenmanifestonly</td>
-    <td valign="top">behavior when no files match.  Valid values are &quot;fail&quot;, &quot;skip&quot;, and &quot;create&quot;.  Default is &quot;create&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>whenmanifestonly</td>
+    <td>behavior when no files match.  Valid values are <q>fail</q>, <q>skip</q>,
+      and <q>create</q>.</td>
+    <td>No; defaults to <q>create</q></td>
   </tr>
   <tr>
-    <td valign="top">duplicate</td>
-    <td valign="top">behavior when a duplicate file is found.  Valid values are &quot;add&quot;, &quot;preserve&quot;, and &quot;fail&quot;.  The default value is &quot;add&quot;.  </td>
-    <td valign="top" align="center">No</td>
+    <td>duplicate</td>
+    <td>behavior when a duplicate file is found.  Valid values are <q>add</q>, <q>preserve</q>,
+      and <q>fail</q>.</td>
+    <td>No; defaults to <q>add</q></td>
   </tr>
   <tr>
-    <td valign="top">index</td>
-    <td valign="top">whether to create an <A
-    HREF="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#JAR_Index">index
-    list</A> to speed up classloading.  This is a JDK 1.3+ specific
-    feature.  Unless you specify additional jars with nested <a
-    href="#indexjars"><code>indexjars</code></a> elements, only the
-    contents of this jar will be included in the index.  Defaults to
-    false.</td>
-    <td valign="top" align="center">No</td>
+    <td>index</td>
+    <td>whether to create
+      an <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Index"
+      target="_top">index list</a> to speed up classloading.
+      Unless you specify additional jars with nested <a href="#indexjars"><code>indexjars</code></a>
+      elements, only the contents of this jar will be included in the index.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">indexMetaInf</td>
-    <td valign="top">whether to include META-INF and its children in
-      the index.  Doesn't have any effect if <em>index</em> is
-      false.<br/>
-      Sun's jar implementation used to skip the META-INF directory and
-      Ant followed that example.  The behavior has been changed with
-      <a href="https://bugs.openjdk.java.net/browse/JDK-4408526">Java
-      5</a>.  In order to avoid problems with Ant generated jars on
-      Java 1.4 or earlier Ant will not include META-INF unless
-      explicitly asked to.<br/>
-      <em>Ant 1.8.0</em> - Defaults to false.</td>
-    <td valign="top" align="center">No</td>
+    <td>indexMetaInf</td>
+    <td>whether to include <samp>META-INF</samp> and its children in the index.  Doesn't have any
+      effect if <var>index</var> is <q>false</q>.<br/>Sun's jar implementation used to skip
+      the <samp>META-INF</samp> directory and Ant followed that example.  The behavior has been
+      changed with <a href="https://bugs.openjdk.java.net/browse/JDK-4408526" target="_top">Java
+      5</a>.  In order to avoid problems with Ant generated jars on Java 1.4 or earlier Ant will not
+      include <samp>META-INF</samp> unless explicitly asked to. <em>Since Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">manifestencoding</td>
-    <td valign="top">The encoding used to read the JAR manifest, when
-      a manifest file is specified.  The task will always use UTF-8
-      when writing the manifest.</td>
-    <td valign="top" align="center">No, defaults to the platform encoding.</td>
+    <td>manifestencoding</td>
+    <td>The encoding used to read the JAR manifest, when a manifest file is specified.  The task
+      will always use UTF-8 when writing the manifest.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">roundup</td>
-    <td valign="top">Whether the file modification times will be
-    rounded up to the next even number of seconds.<br>
-    Zip archives store file modification times with a granularity of
-    two seconds, so the times will either be rounded up or down.  If
-    you round down, the archive will always seem out-of-date when you
-    rerun the task, so the default is to round up.  Rounding up may
-    lead to a different type of problems like JSPs inside a web
-    archive that seem to be slightly more recent than precompiled
-    pages, rendering precompilation useless.<br>
-    Defaults to true.  <em>Since Ant 1.6.2</em></td>
-    <td align="center" valign="top">No</td>
+    <td>roundup</td>
+    <td>Whether the file modification times will be rounded up to the next even number of
+      seconds.<br/>Zip archives store file modification times with a granularity of 2 seconds, so
+      the times will either be rounded up or down.  If you round down, the archive will always seem
+      out-of-date when you rerun the task, so the default is to round up.  Rounding up may lead to a
+      different type of problems like JSPs inside a web archive that seem to be slightly more recent
+      than precompiled pages, rendering precompilation useless. <em>Since Ant 1.6.2</em></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">level</td>
-    <td valign="top">Non-default level at which file compression should be
-    performed. Valid values range from 0 (no compression/fastest) to 9
-    (maximum compression/slowest). <em>Since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
+    <td>level</td>
+    <td>Non-default level at which file compression should be performed. Valid values range
+      from <q>0</q> (no compression/fastest) to <q>9</q> (maximum compression/slowest). <em>Since
+      Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">strict</td>
-    <td valign="top">Configures how to handle breaks of the packaging version
-    specification: <ul>
-    <li><b>fail</b> = throws a BuildException</li>
-    <li><b>warn</b> = logs a message on warn level</li>
-    <li><b>ignore</b> = logs a message on verbose level (default)</li>
-    </ul>
-    <em>Since Ant 1.7.1</em></td>
-    <td valign="top" align="center">No, defaults to <tt>ignore</tt>. </td>
+    <td>strict</td>
+    <td>Configures how to handle breaks of the packaging version specification:
+      <ul>
+        <li><q>fail</q> = throws a BuildException</li>
+        <li><q>warn</q> = logs a message on warn level</li>
+        <li><q>ignore</q> = logs a message on verbose level (default)</li>
+      </ul><em>Since Ant 1.7.1</em></td>
+    <td>No; defaults to <q>ignore</q></td>
   </tr>
   <tr>
-    <td valign="top">preserve0permissions</td>
-    <td valign="top">when updating an archive or adding entries from a
-    different archive Ant will assume that a Unix permissions value of
-    0 (nobody is allowed to do anything to the file/directory) means
-    that the permissions haven't been stored at all rather than real
-    permissions and will instead apply its own default values.<br/>
-    Set this attribute to true if you really want to preserve the
-      original permission field.<em>since Ant 1.8.0</em>
+    <td>preserve0permissions</td>
+    <td>when updating an archive or adding entries from a different archive Ant will assume that a
+      Unix permissions value of 0 (nobody is allowed to do anything to the file/directory) means
+      that the permissions haven't been stored at all rather than real permissions and will instead
+      apply its own default values.<br/>  Set this attribute to <q>true</q> if you really want to
+      preserve the original permission field. <em>since Ant 1.8.0</em>
     </td>
-    <td valign="top" align="center">No, default is false</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">useLanguageEncodingFlag</td>
-    <td valign="top">Whether to set the language encoding flag if the
-      encoding is UTF-8.  This setting doesn't have any effect if the
-      encoding is not UTF-8.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td valign="top" align="center">No, default is true</td>
+    <td>useLanguageEncodingFlag</td>
+    <td>Whether to set the language encoding flag if the encoding is UTF-8.  This setting doesn't
+      have any effect if the encoding is not UTF-8. <em>Since Ant 1.8.0</em>.  <br/>See also
+      the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">createUnicodeExtraFields</td>
-    <td valign="top">Whether to create unicode extra fields to store
-      the file names a second time inside the entry's metadata.
-      <br>Possible values are "never", "always" and "not-encodeable"
-      which will only add Unicode extra fields if the file name cannot
-      be encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
+    <td>createUnicodeExtraFields</td>
+    <td>Whether to create Unicode extra fields to store the file names a second time inside the
+      entry's metadata.<br/>Possible values are <q>never</q>, <q>always</q>
+      and <q>not-encodeable</q> which will only add Unicode extra fields if the file name
+      cannot.<br/>See also the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; defaults to <q>never</q></td>
   </tr>
   <tr>
-    <td valign="top">fallbacktoUTF8</td>
-    <td valign="top">Whether to use UTF-8 and the language encoding
-      flag instead of the specified encoding if a file name cannot be
-      encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>fallbacktoUTF8</td>
+    <td>Whether to use UTF-8 and the language encoding flag instead of the specified encoding if a
+      file name cannot be encoded using the specified encoding. <em>Since Ant 1.8.0</em>.<br/>See
+      also the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">mergeClassPathAttributes</td>
-    <td valign="top">Whether to merge the Class-Path attributes found
-      in different manifests (if merging manifests).  If false, only
-      the attribute of the last merged manifest will be preserved.
-      <em>Since Ant 1.8.0</em>.
-      <br/>unless you also set flattenAttributes to true this may
-      result in manifests containing multiple Class-Path attributes
-      which violates the manifest specification.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>mergeClassPathAttributes</td>
+    <td>Whether to merge the <code>Class-Path</code> attributes found in different manifests (if
+      merging manifests).  If <q>false</q>, only the attribute of the last merged manifest will be
+      preserved.  <em>Since Ant 1.8.0</em>.<br/>Unless you also set <var>flattenAttributes</var>
+      to <q>true</q>, this may result in manifests containing multiple <code>Class-Path</code>
+      attributes which violates the manifest specification.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">flattenAttributes</td>
-    <td valign="top">Whether to merge attributes occurring more than
-      once in a section (this can only happen for the Class-Path
-      attribute) into a single attribute.
-      <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>flattenAttributes</td>
+    <td>Whether to merge attributes occurring more than once in a section (this can only happen for
+      the <code>Class-Path</code> attribute) into a single attribute.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">zip64Mode</td>
-    <td valign="top">When to use Zip64 extensions for entries.  The
-      possible values are "never", "always" and "as-needed".
-      <em>Since Ant 1.9.1</em>.
-      <br/>See also the <a href="zip.html#zip64">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
+    <td>zip64Mode</td>
+    <td>When to use Zip64 extensions for entries.  The possible values
+      are <q>never</q>, <q>always</q> and <q>as-needed</q>.  <em>Since Ant 1.9.1</em>.<br/>See also
+      the <a href="zip.html#zip64">discussion in the zip task page</a></td>
+    <td>No; defaults to <q>never</q></td>
   </tr>
   <tr>
     <td valign="top">modificationtime</td>
@@ -338,220 +311,199 @@
     given time. This can either be a number interpreted as
     milliseconds since 1970-01-01T00:00:00Z or a string that can be
     parsed as a ISO 8601 timestamp with optional timezone.
-      <em>Since Ant 1.9.10</em>.
+      <em>Since Ant 1.10.2</em>.
     </td>
     <td align="center" valign="top">No</td>
   </tr>
 </table>
 
-<h3>Nested elements</h3>
+<h3>Parameters specified as nested elements</h3>
 <h4>metainf</h4>
-<p>The nested <code>metainf</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in this fileset will
-end up in the <code>META-INF</code> directory of the jar file. If this
-fileset includes a file named <code>MANIFEST.MF</code>, the file is
-ignored and you will get a warning.</p>
+<p>The nested <code>metainf</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>. All files included in this fileset will end up in
+the <samp>META-INF</samp> directory of the jar file. If this fileset includes a file
+named <samp>MANIFEST.MF</samp>, the file is ignored and you will get a warning.</p>
 
 <h4>manifest</h4>
-<p>The manifest nested element allows the manifest for the Jar file to
-be provided inline in the build file rather than in an external
-file. This element is identical to the
-<a href="manifest.html">manifest</a> task, but the file and mode
+<p>The nested <code>manifest</code> element allows the manifest for the Jar file to be provided
+inline in the build file rather than in an external file. This element is identical to the
+<a href="manifest.html">manifest</a> task, but the <var>file</var> and <var>mode</var>
 attributes must be omitted.</p>
-<p>
-If both an inline manifest and an external file are both specified, the
-manifests are merged.
-</p>
+<p>If both an inline manifest and an external file are both specified, the manifests are merged.</p>
 
-<p>When using inline manifests, the Jar task will check whether the manifest
-contents have changed (i.e. the manifest as specified is different in any way
-from the manifest that exists in the Jar, if it exists.
-If the manifest values have changed the jar will be updated or rebuilt, as
-appropriate.
-</p>
+<p>When using inline manifests, the <code>Jar</code> task will check whether the manifest contents
+have changed (i.e. the manifest as specified is different in any way from the manifest that exists
+in the jar, if it exists.  If the manifest values have changed, the jar will be updated or rebuilt,
+as appropriate.</p>
 
-<a name="indexjars"><h4>indexjars</h4></a>
+<h4 id="indexjars">indexjars</h4>
 
-<p><em>since ant 1.6.2</em></p>
+<p><em>Since Ant 1.6.2</em></p>
 
-<p>The nested <code>indexjars</code> element specifies a <a
-href="../using.html#path">PATH like structure</a>.  Its content is
-completely ignored unless you set the index attribute of the task to
-true.</p>
+<p>The nested <code>indexjars</code> element specifies a <a href="../using.html#path">path-like
+structure</a>.  Its content is completely ignored unless you set the <var>index</var> attribute of
+the task to <q>true</q>.</p>
 
-<p>The index created by this task will contain indices for the
-archives contained in this path, the names used for the archives
-depend on your manifest:</p>
+<p>The index created by this task will contain indices for the archives contained in this path, the
+names used for the archives depend on your manifest:</p>
 <ul>
-  <li>If the generated jar's manifest contains no Class-Path
-  attribute, the file name without any leading directory path will be
-  used and all parts of the path will get indexed.</li>
-  <li>If the manifest contains a Class-Path attribute, this task will
-  try to guess which part of the Class-Path belongs to a given
-  archive.  If it cannot guess a name, the archive will be skipped,
-  otherwise the name listed inside the Class-Path attribute will be
-  used.</li>
+  <li>If the generated jar's manifest contains no <code>Class-Path</code> attribute, the file name
+  without any leading directory path will be used and all parts of the path will get indexed.</li>
+  <li>If the manifest contains a <code>Class-Path</code> attribute, this task will try to guess
+  which part of the <code>Class-Path</code> belongs to a given archive.  If it cannot guess a name,
+  the archive will be skipped, otherwise the name listed inside the <code>Class-Path</code>
+  attribute will be used.</li>
 </ul>
 
-<p>This task will not create any index entries for archives that are
-  empty or only contain files inside the META-INF directory unless
-  the <code>indexmetainf</code> attribute has been set
-  to <code>true</code>.</p>
+<p>This task will not create any index entries for archives that are empty or only contain files
+inside the <samp>META-INF</samp> directory unless the <var>indexmetainf</var> attribute has been set
+to <q>true</q>.</p>
 
-<a name="service"><h4>service</h4></a>
+<h4 id="indexjarsmapper">indexjarsmapper</h4>
 
-<p><em>since ant 1.7.0</em></p>
+<p><em>Since Ant 1.10.9</em></p>
 
-<p>
-  The nested <code>service</code> element specifies a service.
-  Services are described in the
-  <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Service_Provider">service provider overview</a>.
-  The approach is to have providers JARs include files named by the service
-  provided, for example,
-  META-INF/services/javax.script.ScriptEngineFactory
-  which can include implementation class names, one per line (usually just one per JAR).
+<p>The nested <code>indexjarsmapper</code> element can be used to perform custom filename
+transformations for the archives specified by <code>indexjars</code> if the
+<a href="#indexjars">default filename transformation</a> doesn't suffice.
 
-  The name of the
-  service is set by the "type" attribute. The classname implementing
-  the service is the the "provider" attribute, or it one wants to
-  specify a number of classes that implement the service, by
-  "provider" nested elements.
-</p>
-<p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="service">service</h4>
+
+<p><em>Since Ant 1.7.0</em></p>
+
+<p>The nested <code>service</code> element specifies a service.  Services are described in
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Service_Provider"
+target="_top">service provider overview</a>.  The approach is to have providers JARs include files
+named by the service provided, for
+example, <samp>META-INF/services/javax.script.ScriptEngineFactory</samp> which can include
+implementation class names, one per line (usually just one per JAR).</p>
+
+<p>The name of the service is set by the <var>type</var> attribute. The classname implementing the
+service is the the <var>provider</var> attribute, or if one wants to specify a number of classes
+that implement the service, by <code>provider</code> nested elements.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">The name of the service.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>type</td>
+    <td>The name of the service.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">provider</td>
-    <td valign="top">
-      The classname of the class implementing the service.
-    </td>
-    <td valign="top" align="center">Yes, unless there is a nested
-      <code>&lt;provider&gt;</code> element.</td>
+    <td>provider</td>
+    <td>The classname of the class implementing the service.</td>
+    <td>Yes, unless there is a nested <code>&lt;provider&gt;</code> element.</td>
   </tr>
 </table>
-  <p>
-    The provider classname is specified either by the "provider" attribute, or
-    by a nested &lt;provider&gt; element, which has a single "classname" attribute.
-    If a JAR file has more that one implementation of the service, a number of
-    nested &lt;provider&gt; elements may be used.
-  </p>
-  
-  
+<p>The provider classname is specified either by the <var>provider</var> attribute, or by a
+nested <code>&lt;provider&gt;</code> element, which has a single <var>classname</var> attribute.  If
+a JAR file has more that one implementation of the service, a number of
+nested <code>&lt;provider&gt;</code> elements may be used.</p>
+
 <h3>Examples</h3>
 
 <h4>Simple</h4>
-<blockquote><pre>  &lt;jar destfile=&quot;${dist}/lib/app.jar&quot; basedir=&quot;${build}/classes&quot;/&gt;</pre></blockquote>
-<p>jars all files in the <code>${build}/classes</code> directory into a file
-called <code>app.jar</code> in the <code>${dist}/lib</code> directory.</p>
-
+<p>Jar all files in the <samp>${build}/classes</samp> directory into a file
+called <samp>app.jar</samp> in the <samp>${dist}/lib</samp> directory.</p>
+<pre>&lt;jar destfile=&quot;${dist}/lib/app.jar&quot; basedir=&quot;${build}/classes&quot;/&gt;</pre>
 
 <h4>With filters</h4>
 
-<blockquote><pre>  &lt;jar destfile=&quot;${dist}/lib/app.jar&quot;
-       basedir=&quot;${build}/classes&quot;
-       excludes=&quot;**/Test.class&quot;
-  /&gt;</pre></blockquote>
-<p>jars all files in the <code>${build}/classes</code> directory into a file
-called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Files
-with the name <code>Test.class</code> are excluded.</p>
+<p>Jar all files in the <samp>${build}/classes</samp> directory into a file
+called <samp>app.jar</samp> in the <samp>${dist}/lib</samp> directory. Files with the
+name <samp>Test.class</samp> are excluded.</p>
+<pre>&lt;jar destfile=&quot;${dist}/lib/app.jar&quot;
+     basedir=&quot;${build}/classes&quot;
+     excludes=&quot;**/Test.class&quot;/&gt;</pre>
 
-<blockquote><pre>  &lt;jar destfile=&quot;${dist}/lib/app.jar&quot;
-       basedir=&quot;${build}/classes&quot;
-       includes=&quot;mypackage/test/**&quot;
-       excludes=&quot;**/Test.class&quot;
-  /&gt;</pre></blockquote>
-<p>jars all files in the <code>${build}/classes</code> directory into a file
-called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Only
-files under the directory <code>mypackage/test</code> are used, and files with
-the name <code>Test.class</code> are excluded.</p>
+<p>Jar all files in the <samp>${build}/classes</samp> directory into a file
+called <samp>app.jar</samp> in the <samp>${dist}/lib</samp> directory. Only files under the
+directory <samp>mypackage/test</samp> are used, and files with the name <samp>Test.class</samp> are
+excluded.</p>
+<pre>
+&lt;jar destfile=&quot;${dist}/lib/app.jar&quot;
+     basedir=&quot;${build}/classes&quot;
+     includes=&quot;mypackage/test/**&quot;
+     excludes=&quot;**/Test.class&quot;/&gt;</pre>
 
 <h4>Multiple filesets</h4>
-<blockquote><pre>  &lt;jar destfile=&quot;${dist}/lib/app.jar&quot;&gt;
+<p>Jar all files in the <samp>${build}/classes</samp> directory and also in
+the <samp>${src}/resources</samp> directory together into a file called <samp>app.jar</samp> in
+the <samp>${dist}/lib</samp> directory. Files with the name <samp>Test.class</samp> are excluded. If
+there are files such as <samp>${build}/classes/mypackage/MyClass.class</samp>
+and <samp>${src}/resources/mypackage/image.gif</samp>, they will appear in the same directory in the
+jar (and thus be considered in the same package by Java).</p>
+<pre>
+&lt;jar destfile=&quot;${dist}/lib/app.jar&quot;&gt;
     &lt;fileset dir=&quot;${build}/classes&quot;
-             excludes=&quot;**/Test.class&quot;
-    /&gt;
+             excludes=&quot;**/Test.class&quot;/&gt;
     &lt;fileset dir=&quot;${src}/resources&quot;/&gt;
-  &lt;/jar&gt;</pre></blockquote>
-<p>jars all files in the <code>${build}/classes</code> directory and also
-in the <code>${src}/resources</code> directory together into a file
-called <code>app.jar</code> in the <code>${dist}/lib</code> directory.
-Files with the name <code>Test.class</code> are excluded.
-If there are files such as <code>${build}/classes/mypackage/MyClass.class</code>
-and <code>${src}/resources/mypackage/image.gif</code>, they will appear
-in the same directory in the JAR (and thus be considered in the same package
-by Java).</p>
+&lt;/jar&gt;</pre>
 
 <h4>Merging archives</h4>
 
-<blockquote><pre> &lt;jar destfile="build/main/checksites.jar"&gt;
+<p>Create an executable jar file with a main class <samp>com.acme.checksites.Main</samp>, and embed
+all the classes from the jar <samp>lib/main/some.jar</samp>.</p>
+<pre>
+&lt;jar destfile="build/main/checksites.jar"&gt;
     &lt;fileset dir="build/main/classes"/&gt;
     &lt;zipfileset includes="**/*.class" src="lib/main/some.jar"/&gt;
     &lt;manifest&gt;
       &lt;attribute name="Main-Class"
-            value="com.acme.checksites.Main"/&gt;
+                 value="com.acme.checksites.Main"/&gt;
     &lt;/manifest&gt;
-  &lt;/jar&gt;</pre></blockquote>
-<p>
-  Creates an executable jar file with a main class "com.acme.checksites.Main", and
-  embeds all the classes from the jar <code>lib/main/some.jar</code>.
-</p>
+&lt;/jar&gt;</pre>
 
-<blockquote><pre> &lt;jar destfile="build/main/checksites.jar"&gt;
+<p>Create an executable jar file with a main class <samp>com.acme.checksites.Main</samp>, and embed
+all the classes from all the jars in <samp>lib/main</samp>.</p>
+<pre>
+&lt;jar destfile="build/main/checksites.jar"&gt;
     &lt;fileset dir="build/main/classes"/&gt;
     &lt;restrict&gt;
-     &lt;name name="**/*.class"/&gt;
-     &lt;archives&gt;
-       &lt;zips&gt;
-         &lt;fileset dir="lib/main" includes="**/*.jar"/&gt;
-       &lt;/zips&gt;
-     &lt;/archives&gt;
+       &lt;name name="**/*.class"/&gt;
+       &lt;archives&gt;
+           &lt;zips&gt;
+               &lt;fileset dir="lib/main" includes="**/*.jar"/&gt;
+           &lt;/zips&gt;
+       &lt;/archives&gt;
     &lt;/restrict&gt;
     &lt;manifest&gt;
-      &lt;attribute name="Main-Class"
-            value="com.acme.checksites.Main"/&gt;
+        &lt;attribute name="Main-Class"
+              value="com.acme.checksites.Main"/&gt;
     &lt;/manifest&gt;
-  &lt;/jar&gt;</pre></blockquote>
-<p>
-  Creates an executable jar file with a main class "com.acme.checksites.Main", and
-  embeds all the classes from all the jars in <code>lib/main</code>.
-</p>
+&lt;/jar&gt;</pre>
 
 <h4>Inline manifest</h4>
-<blockquote><pre>  &lt;jar destfile=&quot;test.jar&quot; basedir=&quot;.&quot;&gt;
+<pre>
+&lt;jar destfile=&quot;test.jar&quot; basedir=&quot;.&quot;&gt;
     &lt;include name=&quot;build&quot;/&gt;
     &lt;manifest&gt;
-      &lt;!-- If this is an Applet or Web Start application, include
-           the proper attributes from <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/index.html">http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/index.html</a> --&gt;
-      &lt;attribute name=&quot;Permissions&quot; value=&quot;sandbox&quot;/&gt;
-      &lt;attribute name=&quot;Codebase&quot; value=&quot;example.com&quot;/&gt;
-      &lt;!-- Who is building this jar? --&gt;
-      &lt;attribute name=&quot;Built-By&quot; value=&quot;${user.name}&quot;/&gt;
-      &lt;!-- Information about the program itself --&gt;
-      &lt;attribute name=&quot;Implementation-Vendor&quot; value=&quot;ACME inc.&quot;/&gt;
-      &lt;attribute name=&quot;Implementation-Title&quot; value=&quot;GreatProduct&quot;/&gt;
-      &lt;attribute name=&quot;Implementation-Version&quot; value=&quot;1.0.0beta2&quot;/&gt;
-      &lt;!-- details --&gt;
-      &lt;section name=&quot;common/MyClass.class&quot;&gt;
-        &lt;attribute name=&quot;Sealed&quot; value=&quot;false&quot;/&gt;
-      &lt;/section&gt;
+        &lt;!-- If this is an Applet or Web Start application, include
+             the proper attributes from <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jweb/index.html" target="_top">https://docs.oracle.com/javase/8/docs/technotes/guides/jweb/index.html</a> --&gt;
+        &lt;attribute name=&quot;Permissions&quot; value=&quot;sandbox&quot;/&gt;
+        &lt;attribute name=&quot;Codebase&quot; value=&quot;example.com&quot;/&gt;
+        &lt;!-- Who is building this jar? --&gt;
+        &lt;attribute name=&quot;Built-By&quot; value=&quot;${user.name}&quot;/&gt;
+        &lt;!-- Information about the program itself --&gt;
+        &lt;attribute name=&quot;Implementation-Vendor&quot; value=&quot;ACME inc.&quot;/&gt;
+        &lt;attribute name=&quot;Implementation-Title&quot; value=&quot;GreatProduct&quot;/&gt;
+        &lt;attribute name=&quot;Implementation-Version&quot; value=&quot;1.0.0beta2&quot;/&gt;
+        &lt;!-- details --&gt;
+        &lt;section name=&quot;common/MyClass.class&quot;&gt;
+            &lt;attribute name=&quot;Sealed&quot; value=&quot;false&quot;/&gt;
+        &lt;/section&gt;
     &lt;/manifest&gt;
-  &lt;/jar&gt;</pre></blockquote>
-<p>
-This is an example of an inline manifest specification including the version of the build
-program (Implementation-Version). Note that the Built-By attribute will take the value of the Ant 
-property ${user.name}. The manifest produced by the above would look like this:
-</p>
+&lt;/jar&gt;</pre>
+<p>This is an example of an inline manifest specification including the version of the build program
+(<code>Implementation-Version</code>). Note that the <code>Built-By</code> attribute will take the
+value of the Ant property <code>user.name</code>. The manifest produced by the above would look like
+this:</p>
 
-<blockquote><pre><code>Manifest-Version: 1.0
+<pre>
+Manifest-Version: 1.0
 Permissions: sandbox
 Codebase: example.com
 Built-By: conor
@@ -561,38 +513,52 @@
 Created-By: Apache Ant 1.9.2
 
 Name: common/MyClass.class
-Sealed: false</code></pre></blockquote>
+Sealed: false</pre>
 
 <h4>Service Provider</h4>
 
-<p>
-  The following shows how to create a jar file specifying a service
-  with an implementation of the JDK6 scripting interface:
-</p>
-<blockquote><pre>&lt;jar destfile="pinky.jar"&gt;
-  &lt;fileset dir="build/classes"/&gt;
-  &lt;service type="javax.script.ScriptEngineFactory"
-           provider="org.acme.PinkyLanguage"/&gt;
-&lt;/jar&gt;
-</pre></blockquote>
+<p>The following shows how to create a jar file specifying a service with an implementation of the
+scripting interface:</p>
+<pre>
+&lt;jar destfile="pinky.jar"&gt;
+    &lt;fileset dir="build/classes"/&gt;
+    &lt;service type="javax.script.ScriptEngineFactory"
+             provider="org.acme.PinkyLanguage"/&gt;
+&lt;/jar&gt;</pre>
 
-
-
-<p>
-  The following shows how to create a jar file specifing a service
-  with two implementations of the JDK6 scripting interface:
-</p>
-<blockquote><pre>
+<p>The following shows how to create a jar file specifying a service with two implementations of the
+scripting interface:</p>
+<pre>
 &lt;jar destfile="pinkyandbrain.jar"&gt;
-  &lt;fileset dir="classes"/&gt;
-  &lt;service type="javax.script.ScriptEngineFactory"&gt;
-    &lt;provider classname="org.acme.PinkyLanguage"/&gt;
-    &lt;provider classname="org.acme.BrainLanguage"/&gt;
-  &lt;/service&gt;
-&lt;/jar&gt;
-</pre></blockquote>
+    &lt;fileset dir="classes"/&gt;
+    &lt;service type="javax.script.ScriptEngineFactory"&gt;
+        &lt;provider classname="org.acme.PinkyLanguage"/&gt;
+        &lt;provider classname="org.acme.BrainLanguage"/&gt;
+    &lt;/service&gt;
+&lt;/jar&gt;</pre>
 
-
+<h4 id="jep238-example">JEP 238 example: a Multi-Release JAR Files</h4>
+<p>Here we want to create a <em>Multi-Release JAR File</em> according the
+specification <a href="https://openjdk.java.net/jeps/238" target="_top">JEP 238</a>. It defines on
+top of a JAR the possibility to place additional or overwriting classes in a jar, which are
+available according to the Java version you run.<br/>Basically it says, that you have to set the
+manifest entry <code>Multi-Release: true</code> and place all additional or overwriting classes
+in <samp>META-INF/versions/<i>number</i>/package-structure</samp>,
+e.g. <samp>META-INF/versions/9/org/apache/ant/MyClass.class</samp></p>
+<p>In this example we expect that the normal classes are compiled into <samp>${java.classes}</samp>
+and the Java 9 classes are compiled into <samp>${java9.classes}</samp>.</p>
+<pre>
+&lt;jar destfile=&quot;mrjar.jar&quot;&gt;
+    &lt;manifest&gt;
+        &lt;!-- special mf-entry according to the spec --&gt;
+        &lt;attribute name=&quot;Multi-Release&quot; value=&quot;true&quot;/&gt;
+    &lt;/manifest&gt;
+    &lt;!-- directory structure according to the spec ... --&gt;
+    &lt;!-- ... default classes loadable by old (&lt;Java 9) versions --&gt;
+    &lt;fileset dir=&quot;${java.classes}&quot;/&gt;
+    &lt;!-- ... per release classes, require Java 9+ for loadable via standard ClassLoader --&gt;
+    &lt;zipfileset prefix=&quot;META-INF/versions/9/&quot; dir=&quot;${java9.classes}&quot;/&gt;
+&lt;/jar&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/jarlib-available.html b/manual/Tasks/jarlib-available.html
index adb732f..6c072a1 100644
--- a/manual/Tasks/jarlib-available.html
+++ b/manual/Tasks/jarlib-available.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,121 +15,111 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>jarlib-available Task</title>
 </head>
 
 <body>
 
-<h2><a name="jarlib-available">jarlib-available</a></h2>
+<h2 id="jarlib-available">jarlib-available</h2>
 <h3>Description</h3>
-<p>Check whether an extension is present in a fileset or an extensionSet.
+<p>Check whether an extension is present in a <code>fileset</code> or an <code>extensionSet</code>.
 If the extension is present then a property is set.</p>
 
-<p>Note that this task
-works with extensions as defined by the "Optional Package" specification.
- For more information about optional packages, see the document
-<em>Optional Package Versioning</em> in the documentation bundle for your
-Java Standard Edition package, in file
-<code>guide/extensions/versioning.html</code> or the online
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/extensions/versioning.html">
-Extension and ExtensionSet documentation</a> for further details</p>
+<p>Note that this task works with extensions as defined by the "Optional Package" specification.
+For more information about optional packages, see the document <em>Optional Package Versioning</em>
+in the documentation bundle for your Java Standard Edition package, in
+file <samp>guide/extensions/versioning.html</samp> or the
+online <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html"
+target="_top">Extension and ExtensionSet documentation</a> for further details.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of property to set if extensions is available.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of property to set if extensions is available</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to check for extension</td>
-    <td valign="top" align="center">No, one of file, nested
-    ExtensionSet or nested fileset must be present.</td>
+    <td>file</td>
+    <td>The file to check for extension</td>
+    <td>Yes, unless a nested
+    <code>&lt;extensionSet&gt;</code> or <code>&lt;fileset&gt;</code> is specified</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
 <h4>extension</h4>
- <p><a href="../Types/extension.html">Extension</a> the extension
- to search for.</p>
+<p><a href="../Types/extension.html">Extension</a> the extension to search for.</p>
 
 <h4>fileset</h4>
- <p><a href="../Types/fileset.html">FileSet</a>s are used to select
-sets of files to check for extension.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s are used to select sets of files to check for
+extension.</p>
 
 <h4>extensionSet</h4>
- <p><a href="../Types/extensionset.html">ExtensionSet</a>s is the set
- of extensions to search for extension in.</p>
+<p><a href="../Types/extensionset.html">ExtensionSet</a>s is the set of extensions to search for
+extension in.</p>
 
 <h3>Examples</h3>
-<p><b>Search for extension in single file</b></p>
+<p>Search for extension in single file</p>
 <pre>
-  &lt;jarlib-available property=&quot;myext.present&quot; file=&quot;myfile.jar&quot;&gt;
-    &lt;extension
-      extensionName=&quot;org.apache.tools.ant&quot;
-      specificationVersion=&quot;1.4.9&quot;
-      specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
-  &lt;/jarlib-available&gt;
+&lt;jarlib-available property=&quot;myext.present&quot; file=&quot;myfile.jar&quot;&gt;
+  &lt;extension extensionName=&quot;org.apache.tools.ant&quot;
+             specificationVersion=&quot;1.4.9&quot;
+             specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
+&lt;/jarlib-available&gt;
 </pre>
 
-<p><b>Search for extension in single file referencing external Extension</b></p>
+<p>Search for extension in single file referencing external Extension</p>
 <pre>
-  &lt;extension id=&quot;myext&quot;
-    extensionName=&quot;org.apache.tools.ant&quot;
-    specificationVersion=&quot;1.4.9&quot;
-    specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
+&lt;extension id=&quot;myext&quot;
+           extensionName=&quot;org.apache.tools.ant&quot;
+           specificationVersion=&quot;1.4.9&quot;
+           specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
 
-  &lt;jarlib-available property=&quot;myext.present&quot; file=&quot;myfile.jar&quot;&gt;
-    &lt;extension refid=&quot;myext&quot;/&gt;
-  &lt;/jarlib-available&gt;
-</pre>
-<p><b>Search for extension in fileset</b></p>
+&lt;jarlib-available property=&quot;myext.present&quot; file=&quot;myfile.jar&quot;&gt;
+  &lt;extension refid=&quot;myext&quot;/&gt;
+&lt;/jarlib-available&gt;</pre>
+
+<p>Search for extension in fileset</p>
 <pre>
-  &lt;extension id=&quot;myext&quot;
-    extensionName=&quot;org.apache.tools.ant&quot;
-    specificationVersion=&quot;1.4.9&quot;
-    specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
+&lt;extension id=&quot;myext&quot;
+           extensionName=&quot;org.apache.tools.ant&quot;
+           specificationVersion=&quot;1.4.9&quot;
+           specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
 
-  &lt;jarlib-available property=&quot;myext.present&quot;&gt;
-    &lt;extension refid=&quot;myext&quot;/&gt;
-    &lt;fileset dir="lib"&gt;
-      &lt;include name="*.jar"/&gt;
-    &lt;/fileset&gt;
-  &lt;/jarlib-available&gt;
-</pre>
-<p><b>Search for extension in extensionSet</b></p>
+&lt;jarlib-available property=&quot;myext.present&quot;&gt;
+  &lt;extension refid=&quot;myext&quot;/&gt;
+  &lt;fileset dir="lib"&gt;
+    &lt;include name="*.jar"/&gt;
+  &lt;/fileset&gt;
+&lt;/jarlib-available&gt;</pre>
+
+<p>Search for extension in extensionSet</p>
 <pre>
-  &lt;extension id=&quot;myext&quot;
-    extensionName=&quot;org.apache.tools.ant&quot;
-    specificationVersion=&quot;1.4.9&quot;
-    specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
+&lt;extension id=&quot;myext&quot;
+           extensionName=&quot;org.apache.tools.ant&quot;
+           specificationVersion=&quot;1.4.9&quot;
+           specificationVendor=&quot;Apache Software Foundation&quot;/&gt;
 
-  &lt;jarlib-available property=&quot;myext.present&quot;&gt;
-    &lt;extension refid=&quot;myext&quot;/&gt;
-    &lt;extensionSet id=&quot;exts3&quot;&gt;
-      &lt;libfileset
-        includeUrl=&quot;false&quot;
-        includeImpl=&quot;true&quot;
-        dir=&quot;lib&quot;&gt;
-        &lt;include name=&quot;*.jar&quot;/&gt;
-      &lt;/libfileset&gt;
-    &lt;/extensionSet&gt;
-  &lt;/jarlib-available&gt;
-</pre>
-
-
+&lt;jarlib-available property=&quot;myext.present&quot;&gt;
+  &lt;extension refid=&quot;myext&quot;/&gt;
+  &lt;extensionSet id=&quot;exts3&quot;&gt;
+    &lt;libfileset includeUrl=&quot;false&quot;
+                includeImpl=&quot;true&quot;
+                dir=&quot;lib&quot;&gt;
+      &lt;include name=&quot;*.jar&quot;/&gt;
+    &lt;/libfileset&gt;
+  &lt;/extensionSet&gt;
+&lt;/jarlib-available&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/jarlib-display.html b/manual/Tasks/jarlib-display.html
index 0ddbaa3..b577b5a 100644
--- a/manual/Tasks/jarlib-display.html
+++ b/manual/Tasks/jarlib-display.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,67 +15,57 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>jarlib-display Task</title>
 </head>
 
 <body>
 
-<h2><a name="jarlib-display">jarlib-display</a></h2>
+<h2 id="jarlib-display">jarlib-display</h2>
 <h3>Description</h3>
-<p>Display the "Optional Package" and "Package Specification" information
- contained within the specified jars.</p>
+<p>Display the "Optional Package" and "Package Specification" information contained within the
+specified jars.</p>
 
-<p>Note that this task
-works with extensions as defined by the "Optional Package" specification.
- For more information about optional packages, see the document
-<em>Optional Package Versioning</em> in the documentation bundle for your
-Java Standard Edition package, in file
-<code>guide/extensions/versioning.html</code> or the online
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/extensions/versioning.html">
-Extension and ExtensionSet documentation</a> for further details</p>
+<p>Note that this task works with extensions as defined by the "Optional Package" specification.
+For more information about optional packages, see the document <em>Optional Package Versioning</em>
+in the documentation bundle for your Java Standard Edition package, in
+file <samp>guide/extensions/versioning.html</samp> or the
+online <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html"
+target="_top">Extension and ExtensionSet documentation</a> for further details.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to display extension information about.</td>
-    <td valign="top" align="center">No, but one of file or fileset must be
-    present.</td>
+    <td>file</td>
+    <td>The file to display extension information about</td>
+    <td>Yes, unless a nested <code>&lt;fileset&gt;</code> is specified</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
 <h4>fileset</h4>
- <p><a href="../Types/fileset.html">FileSet</a>s contain list of files to
- display Extension information  about.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s contain list of files to display Extension
+information about.</p>
 
 <h3>Examples</h3>
-<p><b>Display Extension info for a single file</b></p>
+<p>Display Extension info for a single file</p>
+<pre>&lt;jarlib-display file=&quot;myfile.jar&quot;&gt;</pre>
+
+<p>Display Extension info for a fileset</p>
 <pre>
-  &lt;jarlib-display file=&quot;myfile.jar&quot;&gt;
-</pre>
-
-<p><b>Display Extension info for a fileset</b></p>
-<pre>
-  &lt;jarlib-display&gt;
-    &lt;fileset dir="lib"&gt;
-      &lt;include name="*.jar"/&gt;
-    &lt;/fileset&gt;
-  &lt;/jarlib-display&gt;
-</pre>
-
-
+&lt;jarlib-display&gt;
+  &lt;fileset dir="lib"&gt;
+    &lt;include name="*.jar"/&gt;
+  &lt;/fileset&gt;
+&lt;/jarlib-display&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/jarlib-manifest.html b/manual/Tasks/jarlib-manifest.html
index 019b554..ee69790 100644
--- a/manual/Tasks/jarlib-manifest.html
+++ b/manual/Tasks/jarlib-manifest.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,88 +15,79 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>jarlib-manifest Task</title>
 </head>
 
 <body>
 
-<h2><a name="jarlib-manifest">jarlib-manifest</a></h2>
+<h2 id="jarlib-manifest">jarlib-manifest</h2>
 <h3>Description</h3>
-<p>Task to generate a manifest that declares all the dependencies
- in manifest. The dependencies are determined by looking in the
- specified path and searching for Extension / "Optional Package"
- specifications in the manifests of the jars.</p>
+<p>Task to generate a manifest that declares all the dependencies in manifest. The dependencies are
+determined by looking in the specified path and searching for Extension / "Optional Package"
+specifications in the manifests of the jars.</p>
 
-<p>Note that this task
-works with extensions as defined by the "Optional Package" specification.
- For more information about optional packages, see the document
-<em>Optional Package Versioning</em> in the documentation bundle for your
-Java Standard Edition package, in file
-<code>guide/extensions/versioning.html</code> or the online
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/extensions/versioning.html">
-Extension and ExtensionSet documentation</a> for further details</p>
+<p>Note that this task works with extensions as defined by the "Optional Package" specification.
+For more information about optional packages, see the document <em>Optional Package Versioning</em>
+in the documentation bundle for your Java Standard Edition package, in
+file <code>guide/extensions/versioning.html</code> or the
+online <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html"
+target="_top">Extension and ExtensionSet documentation</a> for further details.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">The file to generate Manifest into</td>
-    <td valign="top" align="center">Yes.</td>
+    <td>destfile</td>
+    <td>The file to generate Manifest into</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
 <h4>extension</h4>
- <p><a href="../Types/extension.html">Extension</a> the extension
- that this library implements.</p>
+<p><a href="../Types/extension.html">Extension</a> the extension that this library implements.</p>
 
 <h4>depends</h4>
- <p><a href="../Types/extensionset.html">ExtensionSet</a>s containing
- all dependencies for jar.</p>
+<p><a href="../Types/extensionset.html">ExtensionSet</a>s containing all dependencies for jar.</p>
 
 <h4>options</h4>
- <p><a href="../Types/extensionset.html">ExtensionSet</a>s containing
- all optional dependencies for jar. (Optional dependencies will be used if
- present else they will be ignored)</p>
+<p><a href="../Types/extensionset.html">ExtensionSet</a>s containing all optional dependencies for
+jar. (Optional dependencies will be used if present else they will be ignored)</p>
 
 <h3>Examples</h3>
-<p><b>Basic Manifest generated for single Extension</b></p>
+<p>Basic Manifest generated for single Extension</p>
 <pre>
 &lt;extension id=&quot;e1&quot;
-    extensionName=&quot;MyExtensions&quot;
-    specificationVersion=&quot;1.0&quot;
-    specificationVendor=&quot;Peter Donald&quot;
-    implementationVendorID=&quot;vv&quot;
-    implementationVendor=&quot;Apache&quot;
-    implementationVersion=&quot;2.0&quot;
-    implementationURL=&quot;http://somewhere.com&quot;/&gt;
+           extensionName=&quot;MyExtensions&quot;
+           specificationVersion=&quot;1.0&quot;
+           specificationVendor=&quot;Peter Donald&quot;
+           implementationVendorID=&quot;vv&quot;
+           implementationVendor=&quot;Apache&quot;
+           implementationVersion=&quot;2.0&quot;
+           implementationURL=&quot;https://somewhere.com&quot;/&gt;
 
 &lt;jarlib-manifest destfile=&quot;myManifest.txt&quot;&gt;
     &lt;extension refid=&quot;e1&quot;/&gt;
-&lt;/jarlib-manifest&gt;
-</pre>
+&lt;/jarlib-manifest&gt;</pre>
 
-<p><b>Search for extension in fileset</b></p>
-<p><b>A large example with required and optional dependencies</b></p>
+<p>Search for extension in fileset: a large example with required and optional dependencies</p>
 <pre>
 &lt;extension id=&quot;e1&quot;
-    extensionName=&quot;MyExtensions&quot;
-    specificationVersion=&quot;1.0&quot;
-    specificationVendor=&quot;Peter Donald&quot;
-    implementationVendorID=&quot;vv&quot;
-    implementationVendor=&quot;Apache&quot;
-    implementationVersion=&quot;2.0&quot;
-    implementationURL=&quot;http://somewhere.com&quot;/&gt;
+           extensionName=&quot;MyExtensions&quot;
+           specificationVersion=&quot;1.0&quot;
+           specificationVendor=&quot;Peter Donald&quot;
+           implementationVendorID=&quot;vv&quot;
+           implementationVendor=&quot;Apache&quot;
+           implementationVersion=&quot;2.0&quot;
+           implementationURL=&quot;https://somewhere.com&quot;/&gt;
 
 &lt;extensionSet id=&quot;option.ext&quot;&gt;
     &lt;libfileset dir=&quot;lib/option&quot;&gt;
@@ -113,11 +105,7 @@
     &lt;extension refid=&quot;e1&quot;/&gt;
     &lt;depends refid=&quot;depends.ext&quot;/&gt;
     &lt;options refid=&quot;option.ext&quot;/&gt;
-&lt;/jarlib-manifest&gt;
-</pre>
-
-
+&lt;/jarlib-manifest&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/jarlib-resolve.html b/manual/Tasks/jarlib-resolve.html
index 2ef4f87..31c3acd 100644
--- a/manual/Tasks/jarlib-resolve.html
+++ b/manual/Tasks/jarlib-resolve.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,198 +15,181 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>jarlib-resolve Task</title>
 </head>
 
 <body>
 
-<h2><a name="jarlib-resolve">jarlib-resolve</a></h2>
+<h2 id="jarlib-resolve">jarlib-resolve</h2>
 <h3>Description</h3>
-<p>Try to locate a jar to satisfy an extension and place
- location of jar into property. The task allows you to
- add a number of resolvers that are capable of locating a
- library for a specific extension. Each resolver will be attempted
- in specified order until library is found or no resolvers are left.
- If no resolvers are left and failOnError is true then a BuildException
- will be thrown.</p>
+<p>Try to locate a jar to satisfy an extension and place location of jar into property. The task
+allows you to add a number of resolvers that are capable of locating a library for a specific
+extension. Each resolver will be attempted in specified order until library is found or no resolvers
+are left.  If no resolvers are left and <var>failOnError</var> is true then
+a <code>BuildException</code> will be thrown.</p>
 
-<p>Note that this task
-works with extensions as defined by the "Optional Package" specification.
- For more information about optional packages, see the document
-<em>Optional Package Versioning</em> in the documentation bundle for your
-Java2 Standard Edition package, in file
-<code>guide/extensions/versioning.html</code> or the online
-<a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/guides/extensions/versioning.html">
-Extension and ExtensionSet documentation</a> for further details</p>
+<p>Note that this task works with extensions as defined by the "Optional Package" specification.
+For more information about optional packages, see the document <em>Optional Package Versioning</em>
+in the documentation bundle for your Java Standard Edition package, in
+file <code>guide/extensions/versioning.html</code> or the
+online <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html"
+target="_top">Extension and ExtensionSet documentation</a> for further details.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of property to set to library location.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of property to set to library location.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">failOnError</td>
-    <td valign="top">True if failure to locate library should result in build exception.</td>
-    <td valign="top" align="center">No, defaults to true.</td>
+    <td>failOnError</td>
+    <td><q>true</q> if failure to locate library should result in build exception.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">checkExtension</td>
-    <td valign="top">True if libraries returned by nested resolvers should be checked to see if
-    they supply extension.</td>
-    <td valign="top" align="center">No, defaults to true.</td>
+    <td>checkExtension</td>
+    <td><q>true</q> if libraries returned by nested resolvers should be checked to see if they
+      supply extension.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
 <h4>extension</h4>
- <p><a href="../Types/extension.html">Extension</a> the extension
- to resolve. Must be present</p>
+<p><a href="../Types/extension.html">Extension</a> the extension to resolve. Must be present</p>
 
 <h4>location</h4>
- <p>The location sub element allows you to look for a library in a
- location relative to project directory.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>The <code>location</code> nested element allows you to look for a library in a location relative
+to project directory.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">location</td>
-    <td valign="top">The pathname of library.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>location</td>
+    <td>The pathname of library.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>url</h4>
- <p>The url resolver allows you to download a library from a URL to a
- local file.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>The <code>url</code> resolver allows you to download a library from a URL to a local file.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">The URL to download.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>url</td>
+    <td>The URL to download.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">The file to download URL into.</td>
-    <td valign="top" align="center">No, But one of destfile or
-    destdir must be present</td>
+    <td>destfile</td>
+    <td>The file to download URL into.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">The directory in which to place downloaded file.</td>
-    <td valign="top" align="center">No, But one of destfile or
-    destdir must be present</td>
+    <td>destdir</td>
+    <td class="left">The directory in which to place downloaded file.</td>
   </tr>
 </table>
 
 <h4>ant</h4>
- <p>The ant resolver allows you to run an Apache Ant build file to generate a library.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>The <code>ant</code> resolver allows you to run an Apache Ant build file to generate a
+library.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">antfile</td>
-    <td valign="top">The build file.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>antfile</td>
+    <td>The build file.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">The file that the ant build creates.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>destfile</td>
+    <td>The file that the ant build creates.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">target</td>
-    <td valign="top">The target to run in build file.</td>
-    <td valign="top" align="center">No</td>
+    <td>target</td>
+    <td>The target to run in build file.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<p><b>Resolve Extension to file.</b> If file does not exist or file
-   does not implement extension then throw an exception.</p>
+<p>Resolve Extension to file. If file does not exist or file does not implement extension then throw
+an exception.</p>
 <pre>
-  &lt;extension id=&quot;dve.ext&quot;
-    extensionName=&quot;org.realityforge.dve&quot;
-    specificationVersion=&quot;1.2&quot;
-    specificationVendor=&quot;Peter Donald&quot;/&gt;
+&lt;extension id=&quot;dve.ext&quot;
+           extensionName=&quot;org.realityforge.dve&quot;
+           specificationVersion=&quot;1.2&quot;
+           specificationVendor=&quot;Peter Donald&quot;/&gt;
 
-  &lt;jarlib-resolve property="dve.library"&gt;
-    &lt;extension refid="dve.ext"/&gt;
-    &lt;location location="/opt/jars/dve.jar"/&gt;
-  &lt;/jarlib-resolve&gt;
-</pre>
+&lt;jarlib-resolve property="dve.library"&gt;
+  &lt;extension refid="dve.ext"/&gt;
+  &lt;location location="/opt/jars/dve.jar"/&gt;
+&lt;/jarlib-resolve&gt;</pre>
 
-<p><b>Resolve Extension to url.</b> If url does not exist or can not write
-   to destfile or files does not implement extension then throw an exception.</p>
+<p>Resolve Extension to URL. If URL does not exist or can not write to <var>destfile</var> or file
+does not implement extension then throw an exception.</p>
 <pre>
-  &lt;extension id=&quot;dve.ext&quot;
-    extensionName=&quot;org.realityforge.dve&quot;
-    specificationVersion=&quot;1.2&quot;
-    specificationVendor=&quot;Peter Donald&quot;/&gt;
+&lt;extension id=&quot;dve.ext&quot;
+           extensionName=&quot;org.realityforge.dve&quot;
+           specificationVersion=&quot;1.2&quot;
+           specificationVendor=&quot;Peter Donald&quot;/&gt;
 
-  &lt;jarlib-resolve property="dve.library"&gt;
-    &lt;extension refid="dve.ext"/&gt;
-    &lt;url url="http://www.realityforge.net/jars/dve.jar" destfile="lib/dve.jar"/&gt;
-  &lt;/jarlib-resolve&gt;
-</pre>
+&lt;jarlib-resolve property="dve.library"&gt;
+  &lt;extension refid="dve.ext"/&gt;
+  &lt;url url="https://www.example.com/jars/dve.jar" destfile="lib/dve.jar"/&gt;
+&lt;/jarlib-resolve&gt;</pre>
 
-<p><b>Resolve Extension to file produce by ant build.</b> If file does not get produced
-   or ant file is missing or build fails then throw an exception (Note does not check
-   that library implements extension).</p>
+<p>Resolve Extension to file produce by Ant build. If file does not get produced or Ant file is
+missing or build fails then throw an exception. (<strong>Note</strong>: does not check that library
+implements extension.)</p>
 <pre>
-  &lt;extension id=&quot;dve.ext&quot;
-    extensionName=&quot;org.realityforge.dve&quot;
-    specificationVersion=&quot;1.2&quot;
-    specificationVendor=&quot;Peter Donald&quot;/&gt;
+&lt;extension id=&quot;dve.ext&quot;
+           extensionName=&quot;org.realityforge.dve&quot;
+           specificationVersion=&quot;1.2&quot;
+           specificationVendor=&quot;Peter Donald&quot;/&gt;
 
-  &lt;jarlib-resolve property="dve.library" checkExtension="false"&gt;
-    &lt;extension refid="dve.ext"/&gt;
-    &lt;ant antfile="../dve/build.xml" target="main" destfile="lib/dve.jar"/&gt;
-  &lt;/jarlib-resolve&gt;
-</pre>
+&lt;jarlib-resolve property="dve.library" checkExtension="false"&gt;
+  &lt;extension refid="dve.ext"/&gt;
+  &lt;ant antfile="../dve/build.xml" target="main" destfile="lib/dve.jar"/&gt;
+&lt;/jarlib-resolve&gt;</pre>
 
-<p><b>Resolve Extension via multiple methods.</b> First check local file to see if it implements
-  extension. If it does not then try to build it from source in parallel directory. If that
-  fails then finally try to download it from a website. If all steps fail then throw a build
-  exception.</p>
+<p>Resolve Extension via multiple methods. First check local file to see if it implements
+extension. If it does not then try to build it from source in parallel directory. If that fails then
+finally try to download it from a website. If all steps fail then throw a build exception.</p>
 <pre>
-  &lt;extension id=&quot;dve.ext&quot;
-    extensionName=&quot;org.realityforge.dve&quot;
-    specificationVersion=&quot;1.2&quot;
-    specificationVendor=&quot;Peter Donald&quot;/&gt;
+&lt;extension id=&quot;dve.ext&quot;
+           extensionName=&quot;org.realityforge.dve&quot;
+           specificationVersion=&quot;1.2&quot;
+           specificationVendor=&quot;Peter Donald&quot;/&gt;
 
-  &lt;jarlib-resolve property="dve.library"&gt;
-    &lt;extension refid="dve.ext"/&gt;
-    &lt;location location="/opt/jars/dve.jar"/&gt;
-    &lt;ant antfile="../dve/build.xml" target="main" destfile="lib/dve.jar"/&gt;
-    &lt;url url="http://www.realityforge.net/jars/dve.jar" destfile="lib/dve.jar"/&gt;
-  &lt;/jarlib-resolve&gt;
-</pre>
-
-
+&lt;jarlib-resolve property="dve.library"&gt;
+  &lt;extension refid="dve.ext"/&gt;
+  &lt;location location="/opt/jars/dve.jar"/&gt;
+  &lt;ant antfile="../dve/build.xml" target="main" destfile="lib/dve.jar"/&gt;
+  &lt;url url="https://example.com/jars/dve.jar" destfile="lib/dve.jar"/&gt;
+&lt;/jarlib-resolve&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/java.html b/manual/Tasks/java.html
index 36d50ce..31f4f01 100644
--- a/manual/Tasks/java.html
+++ b/manual/Tasks/java.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,448 +15,421 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Java Task</title>
 </head>
 
 <body>
 
-<h2><a name="java">Java</a></h2>
+<h2 id="java">Java</h2>
 <h3>Description</h3>
-<p>Executes a Java class within the running (Apache Ant) VM or forks another VM if
-specified.</p>
-<p>
-If odd things go wrong when you run this task, set fork="true" to use a new
-JVM.
+<p>Executes a Java class within the running (Apache Ant) JVM or forks another JVM if specified.</p>
+<p>If odd things go wrong when you run this task, set <var>fork</var>=<q>true</q> to use a new
+JVM.</p>
 
-<p>As of Ant 1.6.3, you can interact with a forked VM, as well as
-sending input to it via the <code>input</code> and <code>inputstring</code>
-attributes.</p>
+<p><em>Since Ant 1.6.3</em>, you can interact with a forked JVM, as well as sending input to it via
+the <var>input</var> and <var>inputstring</var> attributes.</p>
 
-<h4><a name="background">Running Ant as a background process on
-    Unix(-like) systems</a></h4>
+<h4 id="background">Running Ant as a background process on Unix(-like) systems</h4>
 
-<p>If you run Ant as a background process (like <code>ant &</code>)
-  and use the <code>&lt;java&gt;</code> task with <code>spawn</code>
-  set to <code>false</code> and <code>fork</code>
-  to <code>true</code>, you must provide explicit input to the forked
-  process or Ant will be suspended because it tries to read from the
-  standard input.</p>
+<p>If you run Ant as a background process (like <kbd>ant &amp;</kbd>) and use
+the <code>&lt;java&gt;</code> task with <var>spawn</var> set to <q>false</q> and <var>fork</var>
+to <q>true</q>, you must provide explicit input to the forked process or Ant will be suspended
+because it tries to read from the standard input.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr id="classname">
+    <td>classname</td>
+    <td>the Java class to execute.</td>
+    <td rowspan="4">Exactly one of the four</td>
   </tr>
   <tr>
-    <td valign="top"><a name="classname">classname</a></td>
-    <td valign="top">the Java class to execute.</td>
-    <td align="center" valign="top">Either <tt>jar</tt>, <tt>classname</tt> or <tt>module</tt></td>
-  </tr>
-  <tr>
-    <td valign="top">jar</td>
-    <td valign="top">the location of the jar file to execute (must have a
-    Main-Class entry in the manifest). Fork must be set to true if this option is selected.
-    See notes below for more details.
+    <td>jar</td>
+    <td class="left">the location of the jar file to execute (must have a <code>Main-Class</code>
+      entry in the manifest). <var>fork</var> must be set to <q>true</q> if this option is selected.
+      See notes <a href="#jar-execute">below</a> for more details.
     </td>
-    <td align="center" valign="top">Either <tt>jar</tt>, <tt>classname</tt> or <tt>module</tt></td>
   </tr>
   <tr>
-    <td valign="top">args</td>
-    <td valign="top">the arguments for the class that is
-      executed. <b>deprecated, use nested <code>&lt;arg&gt;</code>
-      elements instead.</b></td>
-    <td align="center" valign="top">No</td>
+    <td>module</td>
+    <td class="left">The initial or main module to resolve (must have a <code>Main-Class</code>
+      entry in the manifest).  <var>fork</var> must be set to <q>true</q> if this option is
+      selected. <em>since Ant 1.9.7</em></td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use.</td>
-    <td align="center" valign="top">No</td>
+    <td>sourcefile</td>
+    <td class="left">The location of a ".java" file or a file containing shebang with Java source code.
+      Set this attribute to run Java single file source programs, a feature introduced in Java 11.
+      <var>fork</var> must be set to <q>true</q> if this option is selected.
+      <em>since Ant 1.10.5</em></td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">the classpath to use, given as <a
-      href="../using.html#references">reference</a> to a PATH defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>args</td>
+    <td>the arguments for the class that is executed. <em><u>Deprecated</u>, use
+      nested <code>&lt;arg&gt;</code> elements instead.</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">fork</td>
-    <td valign="top">if enabled triggers the class execution in another VM
-      (disabled by default)</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>the classpath to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">spawn</td>
-    <td valign="top">if enabled allows to start a process which will outlive ant.<br>
-    Requires fork=true, and not compatible
-    with timeout, input, output, error, result attributes.<br>
-      (disabled by default)</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>the classpath to use, given as <a href="../using.html#references">reference</a> to
+      a <code>Path</code> defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">jvm</td>
-    <td valign="top">the command used to invoke the Java Virtual Machine,
-      default is 'java'.  The command is resolved by java.lang.Runtime.exec().
-      Ignored if fork is disabled.
+    <td>modulepath</td>
+    <td>Specify where to find application modules. A list of directories of modules, module files or
+      exploded modules.  <em>since Ant 1.9.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>modulepathref</td>
+    <td>The modulepath to use, given as <a href="../using.html#references">reference</a> to
+      a <code>Path</code> defined elsewhere.  <em>since Ant 1.9.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>fork</td>
+    <td>if enabled triggers the class execution in another JVM.</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>spawn</td>
+    <td>if enabled allows to start a process which will outlive Ant.<br/>Requires
+      that <var>fork</var> is <q>true</q>, and not compatible
+      with <var>timeout</var>, <var>input</var>, <var>output</var>, <var>error</var>, <var>result</var>
+      attributes</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>jvm</td>
+    <td>the command used to invoke JVM.  The command is resolved
+      by <code>java.lang.Runtime.exec()</code>.  Ignored if <var>fork</var> is <q>false</q>.
     </td>
-    <td align="center" valign="top">No</td>
+    <td>No, default is <kbd>java</kbd></td>
   </tr>
   <tr>
-    <td valign="top">jvmargs</td>
-    <td valign="top">the arguments to pass to the forked VM (ignored
-      if fork is disabled). <b>deprecated, use nested
-      <code>&lt;jvmarg&gt;</code> elements instead.</b></td>
-    <td align="center" valign="top">No</td>
+    <td>jvmargs</td>
+    <td>the arguments to pass to the forked JVM, ignored if <var>fork</var> is
+      disabled. <em><u>Deprecated</u>, use nested <code>&lt;jvmarg&gt;</code> elements
+      instead.</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Max amount of memory to allocate to the forked VM
-      (ignored if fork is disabled)</td>
-    <td align="center" valign="top">No</td>
+    <td>maxmemory</td>
+    <td>Max amount of memory to allocate to the forked JVM, ignored if <var>fork</var>
+      is <q>false</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">module</td>
-    <td valign="top">The initial or main module to resolve. To specify
-    the module main class use the <a href="#classname">classname</a> attribute.
-    Fork must be set to true if this option is selected.<em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">Either <tt>jar</tt>, <tt>classname</tt> or <tt>module</tt></td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q>.</td>
+    <td>No; default is <q>false</q> (see <a href="#failonerror">note</a>)</td>
   </tr>
   <tr>
-    <td valign="top">modulepath</td>
-    <td valign="top">Specify where to find application modules. A list of directories of modules, module files or exploded modules.<em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>resultproperty</td>
+    <td>The name of a property in which the return code of the command should be stored. Only of
+      interest if <var>failonerror</var> is <q>false</q> and if <var>fork</var> is <q>true</q>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">modulepathref</td>
-    <td valign="top">The modulepath to use, given as <a
-      href="../using.html#references">reference</a> to a PATH defined elsewhere.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>dir</td>
+    <td>The directory to invoke the JVM in, ignored if <var>fork</var> is <q>false</q>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the buildprocess if the command exits with a
-      returncode other than 0. Default is "false" (see <a href="#failonerror">note</a>)</td>
-    <td align="center" valign="top">No</td>
+    <td>output</td>
+    <td>Name of a file to which to write the output. If the error stream is not also redirected to a
+      file or property, it will appear in this output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">resultproperty</td>
-    <td valign="top">The name of a property in which the return code of the
-      command should be stored. Only of interest if failonerror=false
-      and if fork=true.</td>
-    <td align="center" valign="top">No</td>
+    <td>error</td>
+    <td>The file to which the standard error of the command should be redirected.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The directory to invoke the VM in.  (ignored if
-      fork is disabled)</td>
-    <td align="center" valign="top">No</td>
+    <td>logError</td>
+    <td>This attribute is used when you wish to see error output in Ant's log and you are
+      redirecting output to a file/property. The error output will not be included in the output
+      file/property. If you redirect error with the <var>error</var> or <var>errorProperty</var>
+      attributes, this will have no effect.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">Name of a file to which to write the output. If the error stream
-      is not also redirected to a file or property, it will appear in this output.</td>
-    <td align="center" valign="top">No</td>
+    <td>append</td>
+    <td>Whether output and error files should be appended to or overwritten.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">error</td>
-    <td valign="top">The file to which the standard error of the command should be
-      redirected. </td>
-    <td align="center" valign="top">No</td>
+    <td>outputproperty</td>
+    <td>The name of a property in which the output of the command should be stored. Unless the error
+      stream is redirected to a separate file or stream, this property will include the error
+      output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">logError</td>
-    <td valign="top">This attribute is used when you wish to see error output in Ant's
-                     log and you are redirecting output to a file/property. The error
-                     output will not be included in the output file/property. If you
-                     redirect error with the &quot;error&quot; or &quot;errorProperty&quot;
-                     attributes, this will have no effect.</td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property in which the standard error of the command should be stored.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Whether output and error files should be appended to or overwritten.
-    Defaults to false.</td>
-    <td align="center" valign="top">No</td>
+    <td>input</td>
+    <td>A file from which the executed command's standard input is taken. This attribute is mutually
+      exclusive with the <var>inputstring</var> attribute</td>
+    <td>No; default is to take standard input from console
+      unless <var>spawn</var> is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">outputproperty</td>
-    <td valign="top">The name of a property in which the output of the
-      command should be stored. Unless the error stream is redirected to a separate
-      file or stream, this property will include the error output.</td>
-    <td align="center" valign="top">No</td>
+    <td>inputstring</td>
+    <td>A string which serves as the input stream for the executed command. This attribute is
+      mutually exclusive with the <var>input</var> attribute.</td>
+    <td>No; default is to take standard input from console unless <var>spawn</var>
+      is <q>true</q>)</td>
   </tr>
   <tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property in which the standard error of the
-      command should be stored.</td>
-    <td align="center" valign="top">No</td>
+    <td>newenvironment</td>
+    <td>Do not propagate old environment when new environment variables are specified.</td>
+    <td>No; default is <q>false</q>, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">input</td>
-    <td valign="top">A file from which the executed command's standard input
-                     is taken. This attribute is mutually exclusive with the
-                     inputstring attribute</td>
-    <td align="center" valign="top">No; default is to take standard input from console
-        (unless <code>spawn="true"</code>)</td>
+    <td>timeout</td>
+    <td>Stop the command if it doesn't finish within the specified time (given in
+      milliseconds).  <strong>It is highly recommended to use this feature only if <var>fork</var>
+      is <q>true</q>.</strong></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputstring</td>
-    <td valign="top">A string which serves as the input stream for the
-                     executed command. This attribute is mutually exclusive with the
-                     input attribute.</td>
-    <td align="center" valign="top">No; default is to take standard input from console
-        (unless <code>spawn="true"</code>)</td>
+    <td>clonevm</td>
+    <td>If set to <q>true</q>, then all system properties and the <var>bootclasspath</var> of the
+      forked JVM will be the same as those of the JVM running Ant. <em>since Ant 1.7</em></td>
+    <td>No; default is <q>false</q>, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">newenvironment</td>
-    <td valign="top">Do not propagate old environment when new
-      environment variables are specified. Default is &quot;false&quot;
-      (ignored if fork is disabled).</td>
-    <td align="center" valign="top">No</td>
+    <td>discardOutput</td>
+    <td>Whether output should completely be discarded. This setting is
+      incompatible with any setting that redirects output to files or
+      properties.<br/>
+      If you set this to <q>true</q> error output will be discared as
+      well unless you redirect error output to files, properties or
+      enable <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Stop the command if it doesn't finish within the
-    specified time (given in milliseconds).  <strong>It is highly
-    recommended to use this feature only if fork is enabled.</strong></td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">clonevm</td>
-    <td valign="top">If set to true, then all system properties
-      and the bootclasspath of the forked Java Virtual Machine will be
-      the same as those of the Java VM running Ant.  Default is
-      &quot;false&quot; (ignored if fork is disabled).
-      <em>since Ant 1.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>discardError</td>
+    <td>Whether error output should completely be discarded. This
+      setting is incompatible with any setting that redirects error
+      output to files or properties as well as <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>arg and jvmarg</h4>
-<p>Use nested <code>&lt;arg&gt;</code> and <code>&lt;jvmarg&gt;</code>
-elements to specify arguments for the Java class and the forked VM respectively.
-See <a href="../using.html#arg">Command line arguments</a>.</p>
+<p>Use nested <code>&lt;arg&gt;</code> and <code>&lt;jvmarg&gt;</code> elements to specify arguments
+for the Java class and the forked JVM respectively.  See <a href="../using.html#arg">Command line
+arguments</a>.</p>
 <h4>sysproperty</h4>
-<p>Use nested <code>&lt;sysproperty&gt;</code>
-elements to specify system properties required by the class.
-These properties will be made available to the VM during the execution
-of the class (either ANT's VM or the forked VM). The attributes
-for this element are the same as for <a href="exec.html#env">environment
-variables</a>.</p>
+<p>Use nested <code>&lt;sysproperty&gt;</code> elements to specify system properties required by the
+class.  These properties will be made available to JVM during the execution of the class (either
+Ant's JVM or the forked JVM). The attributes for this element are the same as
+for <a href="exec.html#env">environment variables</a>.</p>
 
 <h4>syspropertyset</h4>
 
+<p><em>Since Ant 1.6</em>.</p>
+
 <p>You can specify a set of properties to be used as system properties
 with <a href="../Types/propertyset.html">syspropertyset</a>s.</p>
 
-<p><em>since Ant 1.6</em>.</p>
-
 <h4>classpath</h4>
-<p><code>Java</code>'s <i>classpath</i> attribute is a <a
-href="../using.html#path">PATH like structure</a> and can also be set via a nested
-<i>classpath</i> element.</p>
+<p><code>Java</code>'s <var>classpath</var> attribute is a <a href="../using.html#path">path-like
+structure</a> and can also be set via a nested <code>classpath</code> element.</p>
 
 <h4>bootclasspath</h4>
 
-<p>The location of bootstrap class files can be specified using this
-<a href="../using.html#path">PATH like structure</a> - will be ignored
-if <i>fork</i> is not <code>true</code> or the target VM doesn't
-support it (i.e. Java 1.1).</p>
+<p><em>Since Ant 1.6</em>.</p>
 
-<p><em>since Ant 1.6</em>.</p>
+<p>The location of bootstrap class files can be specified using
+this <a href="../using.html#path">path-like structure</a>&mdash;will be ignored if <var>fork</var>
+is not <q>true</q> or the target JVM doesn't support it (i.e. Java 1.1).</p>
 
 <h4>env</h4>
-<p>It is possible to specify environment variables to pass to the
-forked VM via nested <i>env</i> elements. See the description in the
-section about <a href="exec.html#env">exec</a></p>
-<p>Settings will be ignored if fork is disabled.</p>
+<p>It is possible to specify environment variables to pass to the forked JVM via
+nested <code>env</code> elements. See the description in the section
+about <a href="exec.html#env">exec</a></p>
+<p>Settings will be ignored if <var>fork</var> is <q>false</q>.</p>
 
 <h4>permissions</h4>
-<p>Security permissions can be revoked and granted during the execution of the
-class via a nested <i>permissions</i> element. For more information please
-see <a href="../Types/permissions.html">permissions</a></p>
-<p>When the permission RuntimePermission exitVM has not been granted (or has
-been revoked) the System.exit() call will be intercepted
-and treated like indicated in <i>failonerror</i>.</p>
-<p>Note:<br>
-If you do not specify permissions,
-a set of default permissions will be added to your Java invocation to make
-sure that the ant run will continue or terminated as indicated by
-<i>failonerror</i>. All permissions not granted per default will be
-checked by whatever security manager was already in place. exitVM will be
-disallowed.
-</p>
-<p>Settings will be ignored if fork is enabled.</p>
 
-<p><em>since Ant 1.6</em>.</p>
+<p><em>Since Ant 1.6</em>.</p>
+
+<p>Security permissions can be revoked and granted during the execution of the class via a
+nested <code>permissions</code> element. For more information please
+see <a href="../Types/permissions.html">permissions</a>.</p>
+<p>When the permission <code>RuntimePermission exitVM</code> has not been granted (or has been
+revoked) the <code>System.exit()</code> call will be intercepted and treated like indicated
+in <var>failonerror</var>.</p>
+<p><strong>Note</strong>:<br/> If you do not specify permissions, a set of default permissions will
+be added to your Java invocation to make sure that the Ant run will continue or terminated as
+indicated by <var>failonerror</var>. All permissions not granted per default will be checked by
+whatever security manager was already in place. <code>exitVM</code> will be disallowed.</p>
+<p>Settings will be ignored if <var>fork</var> is <q>true</q>.</p>
 
 <h4>assertions</h4>
 
-<p>You can control enablement of Java 1.4 assertions with an
-<a href="../Types/assertions.html"><tt>&lt;assertions&gt;</tt></a>
-subelement.</p>
+<p><em>Since Ant 1.6</em>.</p>
+
+<p>You can control enablement of Java 1.4 assertions with
+an <a href="../Types/assertions.html"><code>&lt;assertions&gt;</code></a> subelement.</p>
 
 <p>Assertion statements are currently ignored in non-forked mode.</p>
 
-<p><em>since Ant 1.6.</em></p>
+<h4 id="redirector">redirector</h4>
+<em>Since Ant 1.6.2</em>
+<p>A nested <a href="../Types/redirector.html">I/O Redirector</a> can be specified.  In general, the
+attributes of the redirector behave as the corresponding attributes available at the task level.
+The most notable peculiarity stems from the retention of the <code>&lt;java&gt;</code> attributes
+for backwards compatibility.  Any file mapping is done using a <code>null</code> sourcefile;
+therefore not all <a href="../Types/mapper.html">Mapper</a> types will return results.  When no
+results are returned, redirection specifications will fall back to the task level attributes.  In
+practice this means that defaults can be specified for <var>input</var>, <var>output</var>,
+and <var>error</var> output files.</p>
+<h3 id="failonerror">Errors and return codes</h3>
+<p>By default, the return code of a <code>&lt;java&gt;</code> is ignored.  Alternatively, you can
+set <var>resultproperty</var> to the name of a property and have it assigned to the result code
+(barring immutability, of course).  When you set <var>failonerror</var>=<q>true</q>, the only
+possible value for <var>resultproperty</var> is <q>0</q>. Any non-zero response is treated as an
+error and would mean the build exits.</p>
+<p>Similarly, if <var>failonerror</var>=<q>false</q> and <var>fork</var>=<q>false</q>,
+then <code>&lt;java&gt;</code> <em>must</em> return <q>0</q> otherwise the build will exit, as the
+class was run by the build JVM.</p>
 
-<a name="redirector"><h4>redirector</h4></a>
-<i><b>Since Ant 1.6.2</b></i>
-<p>A nested <a href="../Types/redirector.html">I/O Redirector</a>
-can be specified.  In general, the attributes of the redirector behave
-as the corresponding attributes available at the task level.  The most
-notable peculiarity stems from the retention of the <code>&lt;java&gt;</code>
-attributes for backwards compatibility.  Any file mapping is done
-using a <CODE>null</CODE> sourcefile; therefore not all
-<a href="../Types/mapper.html">Mapper</a> types will return
-results.  When no results are returned, redirection specifications
-will fall back to the task level attributes.  In practice this means that
-defaults can be specified for input, output, and error output files.
-</p>
-<a name="failonerror"><h3>Errors and return codes</h3></a>
-By default the return code of a <code>&lt;java&gt;</code> is ignored.
-Alternatively, you can set <code>resultproperty</code> to the name
-of a property and have it assigned to the result code (barring immutability,
-of course).
-When you set <code>failonerror="true"</code>, the only possible value for
-<code>resultproperty</code> is 0. Any non-zero response is treated as an
-error and would mean the build exits.
-<p> Similarly, if <code>failonerror="false"</code> and <code>fork="false"</code>
-, then <code>&lt;java&gt;</code> <b>must</b> return 0 otherwise the build will
-exit, as the class was run by the build JVM.</p>
+<h4 id="modulepath">modulepath</h4>
+<em>Since Ant 1.9.7</em>
+<p><code>Java</code>'s <var>modulepath</var> attribute is a <a href="../using.html#path">path-like
+structure</a> and can also be set via a nested <code>modulepath</code> element.</p>
 
-<a name="modulepath"><h4>modulepath</h4>
-<i><b>Since Ant 1.9.7</b></i>
-<p><code>Java</code>'s <i>modulepath</i> attribute is a <a
-href="../using.html#path">PATH like structure</a> and can also be set via a nested
-<i>modulepath</i> element.</p>
+<h4 id="upgrademodulepath">upgrademodulepath</h4>
+<em>Since Ant 1.9.7</em>
+<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>.</p>
 
-<a name="upgrademodulepath"><h4>upgrademodulepath</h4>
-<i><b>Since Ant 1.9.7</b></i>
-<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>.</p>
+<h3 id="jar-execute">JAR file execution</h3>
 
-
-<h3>JAR file execution</h3>
-
-<p>The parameter of the <tt>jar</tt> attribute is of type <tt>File</tt>;
-that is, the parameter is resolved to an absolute file relative to the
-base directory of the project, <i>not</i> the directory in which the Java
-task is run. If you need to locate a JAR file relative to the directory
-the task will be run in, you need to explicitly create the full path
-to the JAR file.</p>
-<p>When using the <tt>jar</tt> attribute, all classpath settings are 
-ignored according to <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html">Oracle's
-specification</a>. 
-
+<p>The parameter of the <var>jar</var> attribute is of type <code>File</code>; that is, the
+parameter is resolved to an absolute file relative to the base directory of the
+project, <em>not</em> the directory in which the Java task is run. If you need to locate a JAR file
+relative to the directory the task will be run in, you need to explicitly create the full path to
+the JAR file.</p>
+<p>When using the <var>jar</var> attribute, all classpath settings are ignored according
+to <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html"
+target="_top">Oracle's specification</a>.
 
 <h3>Examples</h3>
+<p>Run a class in this JVM with a new jar on the classpath</p>
 <pre>
-       &lt;java classname=&quot;test.Main&quot;&gt;
-         &lt;arg value=&quot;-h&quot;/&gt;
-         &lt;classpath&gt;
-           &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
-           &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
-         &lt;/classpath&gt;
-       &lt;/java&gt;
-</pre>
-Run a class in this JVM with a new jar on the classpath
+&lt;java classname=&quot;test.Main&quot;&gt;
+  &lt;arg value=&quot;-h&quot;/&gt;
+  &lt;classpath&gt;
+    &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
+    &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
+  &lt;/classpath&gt;
+&lt;/java&gt;</pre>
 
+<p>Run the JAR <samp>test.jar</samp> in this project's <samp>dist/lib</samp> directory, using the
+manifest supplied entry point, forking (as required), and with a maximum memory of 128 MB. Any non
+zero return code breaks the build.</p>
 <pre>
-       &lt;java jar=&quot;dist/test.jar&quot;
-           fork="true"
-           failonerror="true"
-           maxmemory="128m"
-           &gt;
-         &lt;arg value=&quot;-h&quot;/&gt;
-         &lt;classpath&gt;
-           &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
-           &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
-         &lt;/classpath&gt;
-       &lt;/java&gt;
-</pre>
-Run the JAR test.jar in this project's dist/lib directory.
-using the manifest supplied entry point, forking (as required),
-and with a maximum memory of 128MB. Any non zero return code breaks the build.
+&lt;java jar=&quot;dist/test.jar&quot;
+      fork="true"
+      failonerror="true"
+      maxmemory="128m"&gt;
+  &lt;arg value=&quot;-h&quot;/&gt;
+  &lt;classpath&gt;
+    &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
+    &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
+  &lt;/classpath&gt;
+&lt;/java&gt;</pre>
 
+<p>Run the JAR <samp>dist/test.jar</samp> relative to the directory <code>${exec.dir}</code>, this
+being the same directory in which JVM is to start up.</p>
 <pre>
-       &lt;java
-           dir="${exec.dir}"
-           jar=&quot;${exec.dir}/dist/test.jar&quot;
-           fork="true"
-           failonerror="true"
-           maxmemory="128m"
-           &gt;
-         &lt;arg value=&quot;-h&quot;/&gt;
-         &lt;classpath&gt;
-           &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
-           &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
-         &lt;/classpath&gt;
-       &lt;/java&gt;
-</pre>
-Run the JAR dist/test.jar relative to the directory
-<tt>${exec.dir}</tt>, this being the same directory into which the JVM
-is to start up.
+&lt;java dir=&quot;${exec.dir}&quot;
+      jar=&quot;${exec.dir}/dist/test.jar&quot;
+      fork=&quot;true&quot;
+      failonerror=&quot;true&quot;
+      maxmemory=&quot;128m&quot;&gt;
+  &lt;arg value=&quot;-h&quot;/&gt;
+  &lt;classpath&gt;
+    &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
+    &lt;pathelement path=&quot;${java.class.path}&quot;/&gt;
+  &lt;/classpath&gt;
+&lt;/java&gt;</pre>
 
-<pre>  &lt;java classname=&quot;test.Main&quot;/&gt;</pre>
-Runs a given class with the current classpath.
+<p>Run a given class with the current classpath.</p>
+<pre>&lt;java classname=&quot;test.Main&quot;/&gt;</pre>
 
+<p>Add system properties and JVM properties to JVM as in <code>java
+-Xrunhprof:cpu=samples,file=log.txt,depth=3 -DDEBUG=true test.Main</code>
 <pre>
-  &lt;java classname=&quot;test.Main&quot;
-        fork=&quot;yes&quot; &gt;
-    &lt;sysproperty key=&quot;DEBUG&quot; value=&quot;true&quot;/&gt;
-    &lt;arg value=&quot;-h&quot;/&gt;
-    &lt;jvmarg value=&quot;-Xrunhprof:cpu=samples,file=log.txt,depth=3&quot;/&gt;
-  &lt;/java&gt;
-</pre>
-Add system properties and JVM-properties to the JVM as in
-<code>java ="-Xrunhprof:cpu=samples,file=log.txt,depth=3 -DDEBUG=true test.Main</code>
+&lt;java classname=&quot;test.Main&quot;
+      fork=&quot;yes&quot; &gt;
+  &lt;sysproperty key=&quot;DEBUG&quot; value=&quot;true&quot;/&gt;
+  &lt;arg value=&quot;-h&quot;/&gt;
+  &lt;jvmarg value=&quot;-Xrunhprof:cpu=samples,file=log.txt,depth=3&quot;/&gt;
+&lt;/java&gt;</pre>
 
-<pre>  &lt;java classname=&quot;ShowJavaVersion&quot; classpath=&quot;.&quot;
-        jvm=&quot;path-to-java14-home/bin/java&quot; fork=&quot;true&quot;
-        taskname=&quot;java1.4&quot; &gt;
-</pre>
-Use a given Java implementation (another the one Ant is currently using) to run the class.
-For documentation in the log <code>taskname</code> is used to change the <code>[java]</code>
-log-prefix to <code>[java1.4]</code>.
+<p>Use a given Java implementation (other than the one Ant is currently using) to run the class. For
+documentation in the log <var>taskname</var> is used to change the <q>[java]</q> log-prefix
+to <q>[java1.4]</q>.</p>
+<pre>
+&lt;java classname=&quot;ShowJavaVersion&quot; classpath=&quot;.&quot;
+      jvm=&quot;path-to-java14-home/bin/java&quot; fork=&quot;true&quot;
+      taskname=&quot;java1.4&quot;/&gt;</pre>
 
-
-<p><strong>Note</strong>: you can not specify the (highly deprecated) MSJVM, "jview.exe" as the
-JVM, as it takes different parameters for other JVMs,
+<p><strong>Note</strong>: you can not specify the (highly deprecated) MS
+JVM, <samp>jview.exe</samp>, as <var>jvm</var>, since it takes different parameters than other JVMs.
 That JVM can be started from <code>&lt;exec&gt;</code> if required.</p>
 
+<p>Run the module <samp>TestModule</samp> resolved on the modulepath <samp>lib/:dist/test.jar</samp>
+with a maximum memory of 128 MB. Any non zero return code breaks the build.</p>
 <pre>
-       &lt;java
-           fork=&quot;true&quot;
-           failonerror=&quot;true&quot;
-           maxmemory=&quot;128m&quot;
-           module=&quot;TestModule&quot;
-           modulepath=&quot;lib:dist/test.jar&quot;/&gt;
-</pre>
-Runs the module TestModule resolved on the modulepath <tt>lib/:dist/test.jar</tt>
-with a maximum memory of 128MB. Any non zero return code breaks the build.
+&lt;java fork=&quot;true&quot;
+      failonerror=&quot;true&quot;
+      maxmemory=&quot;128m&quot;
+      module=&quot;TestModule&quot;
+      modulepath=&quot;lib:dist/test.jar&quot;/&gt;</pre>
 
+<p>Run the class <samp>Main</samp> in module <samp>TestModule</samp> resolved on the
+modulepath <samp>lib/:dist/test.jar</samp> with a maximum memory of 128 MB. Any non zero return code
+breaks the build.</p>
 <pre>
-       &lt;java
-           fork=&quot;true&quot;
-           failonerror=&quot;true&quot;
-           maxmemory=&quot;128m&quot;
-           module=&quot;TestModule&quot;
-           classname=&quot;Main&quot;&gt;
-         &lt;modulepath&gt;
-           &lt;pathelement location=&quot;lib&quot;/&gt;
-           &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
-         &lt;/modulepath&gt;
-       &lt;/java&gt;
-</pre>
-Runs the class Main in module TestModule resolved on the modulepath <tt>lib/:dist/test.jar</tt>
-with a maximum memory of 128MB. Any non zero return code breaks the build.
+&lt;java fork=&quot;true&quot;
+      failonerror=&quot;true&quot;
+      maxmemory=&quot;128m&quot;
+      module=&quot;TestModule&quot;
+      classname=&quot;Main&quot;&gt;
+  &lt;modulepath&gt;
+    &lt;pathelement location=&quot;lib&quot;/&gt;
+    &lt;pathelement location=&quot;dist/test.jar&quot;/&gt;
+  &lt;/modulepath&gt;
+&lt;/java&gt;</pre>
 </body>
 </html>
diff --git a/manual/Tasks/javac.html b/manual/Tasks/javac.html
index 89ec054..ac770a2 100644
--- a/manual/Tasks/javac.html
+++ b/manual/Tasks/javac.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,952 +15,738 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html lang="en-us">
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Javac Task</title>
 </head>
 
 <body>
 
-<h2><a name="javac">Javac</a></h2>
+<h2 id="javac">Javac</h2>
 <h3>Description</h3>
 <p>Compiles a Java source tree.</p>
-<p>The source and destination directory will be recursively scanned for Java
-source files to compile. Only Java files that have no corresponding
-<code>.class</code> file
-or where the class file is older than the
-<code>.java</code> file will be compiled.</p>
-<p>Note: Apache Ant uses only the names of the source and class files to find
-the classes that need a rebuild. It will not scan the source and therefore
-will have no knowledge about nested classes, classes that are named different
-from the source file, and so on. See the
-<a href="../Tasks/depend.html"><code>&lt;depend&gt;</code></a> task
-for dependency checking based on other than just
-existence/modification times.</p>
-<p>When the source files are part of a package, the directory structure of
-the source tree should follow the package
-hierarchy.</p>
-<p>It is possible to refine the set of files that are being compiled.
-This can be done with the <code>includes</code>, <code>includesfile</code>,
-<code>excludes</code>, and <code>excludesfile</code>
-attributes. With the <code>includes</code> or
-<code>includesfile</code> attribute, you specify the files you want to
-have included.
-The <code>exclude</code> or <code>excludesfile</code> attribute is used
-to specify
-the files you want to have excluded. In both cases, the list of files
-can be specified by either the filename, relative to the directory(s) specified
-in the <code>srcdir</code> attribute or nested <code>&lt;src&gt;</code>
-element(s), or by using wildcard patterns. See the section on
-<a href="../dirtasks.html#directorybasedtasks">directory-based tasks</a>,
-for information on how the
-inclusion/exclusion of files works, and how to write wildcard patterns.</p>
-<p>It is possible to use different compilers. This can be specified by
-either setting the global <code>build.compiler</code> property, which will
-affect all <code>&lt;javac&gt;</code> tasks throughout the build, by
-setting the <code>compiler</code> attribute, specific to the current
-<code>&lt;javac&gt;</code> task or by using a nested element of any
-<a href="typedef.html">typedef</a>fed or
-<a href="componentdef.html">componentdef</a>fed type that implements
-<code>org.apache.tools.ant.taskdefs.compilers.CompilerAdapter</code>.
-<a name="compilervalues">Valid values for either the
-<code>build.compiler</code> property or the <code>compiler</code>
-attribute are:</a></p>
+<p>The source and destination directory will be recursively scanned for Java source files to
+compile. Only <code>.java</code> files that have no corresponding <samp>.class</samp> file or where
+the <code>.class</code> file is older than the <samp>.java</samp> file will be compiled.</p>
+<p><strong>Note</strong>: Apache Ant uses only the names of the source and class files to find the
+classes that need a rebuild. It will not scan the source and therefore will have no knowledge about
+nested classes, classes that are named differently from the source file, and so on. See
+the <a href="../Tasks/depend.html"><code>&lt;depend&gt;</code></a> task for dependency checking
+based on other than just existence/modification times.</p>
+<p>When the source files are part of a package, the directory structure of the source tree should
+follow the package hierarchy.</p>
+<p>It is possible to refine the set of files that are being compiled.  This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, and <var>excludesfile</var>
+attributes. With the <var>includes</var> or <var>includesfile</var> attribute, you specify the files
+you want to have included.  The <var>exclude</var> or <var>excludesfile</var> attribute is used to
+specify the files you want to have excluded. In both cases, the list of files can be specified by
+either the filename, relative to the directory(s) specified in the <var>srcdir</var> attribute or
+nested <code>&lt;src&gt;</code> element(s), or by using wildcard patterns. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory-based tasks</a>, for information on how
+the inclusion/exclusion of files works, and how to write wildcard patterns.</p>
+<p id="compilervalues">It is possible to use different compilers. This can be specified by either
+setting the global <code>build.compiler</code> property, which will affect
+all <code>&lt;javac&gt;</code> tasks throughout the build, by setting the <var>compiler</var>
+attribute, specific to the current <code>&lt;javac&gt;</code> task or by using a nested element of
+any <a href="typedef.html">typedef</a>fed or <a href="componentdef.html">componentdef</a>fed type
+that implements <code>org.apache.tools.ant.taskdefs.compilers.CompilerAdapter</code>.  Valid values
+for either the <code>build.compiler</code> property or the <var>compiler</var> attribute are:</p>
 <ul>
-  <li><code>classic</code> (the standard compiler of JDK 1.1/1.2) &ndash;
-      <code>javac1.1</code> and
-      <code>javac1.2</code> can be used as aliases.</li>
-  <li><code>modern</code> (the standard compiler of JDK 1.3 and later) &ndash;
-      <code>javac1.3</code> and
-      <code>javac1.4</code> and
-      <code>javac1.5</code> and
-      <code>javac1.6</code> and
-      <code>javac1.7</code> (<em>since Ant 1.8.2</em>) and
-      <code>javac1.8</code> (<em>since Ant 1.8.3</em>) and
-      <code>javac1.9</code> (<em>since Ant 1.9.5</em>) and
-      <code>javac9</code> (<em>since Ant 1.9.8</em>) and
-      <code>javac10+</code> (<em>since Ant 1.9.10</em>) can be used as aliases.</li>
-  <li><code>jikes</code> (the <a
-    href="http://jikes.sourceforge.net/" target="_top">Jikes</a>
+  <li><q>classic</q> (the standard compiler of JDK 1.1/1.2) &ndash; <q>javac1.1</q>
+    and <q>javac1.2</q> can be used as aliases.</li>
+  <li><q>modern</q> (the standard compiler of JDK 1.3 and later)
+    &ndash; <q>javac1.3</q>, <q>javac1.4</q>, <q>javac1.5</q> and <q>javac1.6</q>, <q>javac1.7</q>
+    (<em>since Ant 1.8.2</em>), <q>javac1.8</q> (<em>since Ant 1.8.3</em>), <q>javac1.9</q>
+    (<em>since Ant 1.9.5</em>), <q>javac9</q> (<em>since Ant 1.9.8</em>) and <q>javac10+</q>
+    (<em>since Ant 1.10.2</em>) can be used as aliases.</li>
+  <li><q>jikes</q> (the <a href="http://jikes.sourceforge.net/" target="_top">Jikes</a>
     compiler).</li>
-  <li><code>jvc</code> (the Command-Line Compiler from Microsoft's SDK
-      for Java / Visual J++) &ndash; <code>microsoft</code> can be used
-      as an alias.</li>
-  <li><code>kjc</code> (the <a href="http://www.dms.at/kopi/" target="_top">kopi</a>
-    compiler).</li>
-  <li><code>gcj</code> (the gcj compiler from gcc).</li>
-  <li><code>sj</code> (Symantec java compiler) &ndash;
-      <code>symantec</code> can be used as an alias.</li>
-  <li><code>extJavac</code> (run either modern or classic in a JVM of
-      its own).</li>
+  <li><q>jvc</q> (the Command-Line Compiler from Microsoft's SDK for Java / Visual J++)
+    &ndash; <q>microsoft</q> can be used as an alias.</li>
+  <li><q>kjc</q>
+    (the <a href="https://web.archive.org/web/20050212025507/http://www.dms.at/kopi/index.html"
+    target="_top">kopi</a> compiler).</li>
+  <li><q>gcj</q> (the <code>gcj</code> compiler
+    from <a href="https://gcc.gnu.org/gcc-7/changes.html#java" target="_top">GCC</a>).</li>
+  <li><q>sj</q> (Symantec Java compiler) &ndash; <q>symantec</q> can be used as an alias.</li>
+  <li><q>extJavac</q> (run either modern or classic in a JVM of its own).</li>
 </ul>
-<p>The default is <code>javac1.x</code> with <code>x</code> depending
-on the JDK version you use while you are running Ant.
-If you wish to use a different compiler interface than those
-supplied, you can write a class that implements the CompilerAdapter interface
-(<code>package org.apache.tools.ant.taskdefs.compilers</code>). Supply the full
-classname in the <code>build.compiler</code> property or the
-<code>compiler</code> attribute.
-</p>
-<p>The fork attribute overrides the <code>build.compiler</code> property
-or <code>compiler</code> attribute setting and
-expects a JDK1.1 or higher to be set in <code>JAVA_HOME</code>.
-</p>
-<p>You can also use the <code>compiler</code> attribute to tell Ant
-which JDK version it shall assume when it puts together the command
-line switches - even if you set <code>fork=&quot;true&quot;</code>.
-This is useful if you want to run the compiler of JDK 1.1 while you
-current JDK is 1.2+.  If you use
-<code>compiler=&quot;javac1.1&quot;</code> and (for example)
-<code>depend=&quot;true&quot;</code> Ant will use the command line
-switch <code>-depend</code> instead of <code>-Xdepend</code>.</p>
-<p>This task will drop all entries that point to non-existent
-files/directories from the classpath it passes to the compiler.</p>
-<p>The working directory for a forked executable (if any) is the
-  project's base directory.</p>
-<p><strong>Windows Note:</strong>When the modern compiler is used
-in unforked mode on Windows, it locks up the files present in the
-classpath of the <code>&lt;javac&gt;</code> task, and does not release them.
-The side effect of this is that you will not be able to delete or move
-those files later on in the build.  The workaround is to fork when
-invoking the compiler.</p>
-<p>If you are using Java 8 or above and your source contains native
-  methods or fields annotated with the <code>@Native</code> annotation
-  you can set the <code>nativeheaderdir</code> attribute in order to
-  use the <code>-h</code> switch of <code>javac</code> to generate the
-  native header files. Note that the logic Ant uses to determine which
-  files to compile does not take native headers into account, i.e. if
-  the <code>.class</code> is more recent than the
-  corresponding <code>.java</code> file the file will not get compiled
-  even if a native header file generated for it would be outdated.</p>
+<p>The default is <q>javacX</q> with <q>X</q> depending on the JDK version you use while you are
+running Ant.  If you wish to use a different compiler interface than those supplied, you can write a
+class that implements the CompilerAdapter interface
+(package <code>org.apache.tools.ant.taskdefs.compilers</code>). Supply the full classname in
+the <code>build.compiler</code> property or the <var>compiler</var> attribute.</p>
+<p>The <var>fork</var> attribute overrides the <code>build.compiler</code> property
+or <var>compiler</var> attribute setting and expects a JDK 1.1 or higher to be set
+in <code>JAVA_HOME</code>.</p>
+<p>You can also use the <var>compiler</var> attribute to tell Ant which JDK version it shall assume
+when it puts together the command line switches&mdash;even if you set <var>fork</var>=<q>true</q>.
+This is useful if you want to run the compiler of JDK 1.1 while your current JDK is 1.2+.  If you
+use <var>compiler</var>=<q>javac1.1</q> and (for example) <var>depend</var>=<q>true</q>, Ant will
+use the command line switch <kbd>-depend</kbd> instead of <kbd>-Xdepend</kbd>.</p>
+<p>This task will drop all entries that point to non-existent files/directories from the classpath
+it passes to the compiler.</p>
+<p>The working directory for a forked executable (if any) is the project's base directory.</p>
+<p><strong>Windows Note</strong>: When the modern compiler is used in unforked mode on Windows, it
+locks up the files present in the classpath of the <code>&lt;javac&gt;</code> task, and does not
+release them.  The side effect of this is that you will not be able to delete or move those files
+later on in the build.  The workaround is to fork when invoking the compiler.</p>
+<p>If your source contains native methods or fields annotated with
+the <code>@Native</code> annotation you can set the <var>nativeheaderdir</var> attribute in order to
+use the <kbd>-h</kbd> switch of <kbd>javac</kbd> to generate the native header files. Note that
+the logic Ant uses to determine which files to compile does not take native headers into account,
+i.e. if the <samp>.class</samp> is more recent than the corresponding <samp>.java</samp> file the
+file will not get compiled even if a native header file generated for it would be outdated.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">srcdir</td>
-    <td valign="top">Location of the java files. (See the
-     <a href="#srcdirnote">note</a> below.)</td>
-    <td align="center" valign="top">Yes, unless nested <code>&lt;src&gt;</code> elements or <code>modulesourcepath</code> attribute or elements are present.</td>
+    <td>srcdir</td>
+    <td>Location of the java files. (See the <a href="#srcdirnote">note</a> below.)</td>
+    <td>Yes, unless nested <code>&lt;src&gt;</code> elements or <var>modulesourcepath</var>
+      attribute or corresponding elements are present</td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">Location to store the class files.</td>
-    <td align="center" valign="top">No</td>
+    <td>destdir</td>
+    <td>Location to store the class files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">Comma- or space-separated list of files (may be specified using
-      wildcard patterns) that must be
-      included; all <code>.java</code> files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>Comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all <samp>.java</samp> files</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">The name of a file that contains a list of files to
-      include (may be specified using wildcard patterns).</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an include pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">Comma- or space-separated list of files (may be specified using
-      wildcard patterns) that must be excluded; no files (except default
-      excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>Comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">The name of a file that contains a list of files to
-      exclude (may be specified using wildcard patterns).</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an exclude pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to use.</td>
-    <td align="center" valign="top">No</td>
+    <td>defaultexcludes</td>
+    <td>Indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">sourcepath</td>
-    <td valign="top">The sourcepath to use; defaults to the value of the srcdir attribute (or nested <code>&lt;src&gt;</code> elements).
-        To suppress the sourcepath switch, use <code>sourcepath=&quot;&quot;</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>The classpath to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">bootclasspath</td>
-    <td valign="top">
-      Location of bootstrap class files. (See <a href="#bootstrap">below</a>
-      for using the -X and -J-X parameters for specifying
-      the bootstrap classpath).
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>sourcepath</td>
+    <td>The sourcepath to use.  To suppress the <code>sourcepath</code> switch,
+      use <var>sourcepath</var>=<q></q>.</td>
+    <td>No; defaults to <var>srcdir</var> unless nested <code>&lt;src&gt;</code> elements are
+      specified</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use, given as a
-      <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>bootclasspath</td>
+    <td>Location of bootstrap class files. (See <a href="#bootstrap">below</a> for using
+      the <kbd>-X</kbd> and <kbd>-J-X</kbd> parameters for specifying the bootstrap
+      classpath).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sourcepathref</td>
-    <td valign="top">The sourcepath to use, given as a
-      <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>The <var>classpath</var> to use, given as a <a href="../using.html#references">reference</a>
+      to a path defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">bootclasspathref</td>
-    <td valign="top">Location of bootstrap class files, given as a
-      <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>sourcepathref</td>
+    <td>The <var>sourcepath</var> to use, given as
+      a <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">extdirs</td>
-    <td valign="top">Location of installed extensions.</td>
-    <td align="center" valign="top">No</td>
+    <td>bootclasspathref</td>
+    <td>The <var>bootstrapclasspath</var> to use, given as
+      a <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">Encoding of source files. (Note: gcj doesn't support
-      this option yet.)</td>
-    <td align="center" valign="top">No</td>
+    <td>extdirs</td>
+    <td>Location of installed extensions.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">nowarn</td>
-    <td valign="top">Indicates whether the <code>-nowarn</code> switch
-      should be passed to the compiler; defaults to <code>off</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>Encoding of source files. (<strong>Note</strong>: <code>gcj</code> doesn't support this
+      option yet.)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">debug</td>
-    <td valign="top">Indicates whether source should be compiled with
-    debug information; defaults to <code>off</code>.  If set to
-    <code>off</code>, <code>-g:none</code> will be passed on the
-    command line for compilers that support it (for other compilers, no
-    command line argument will be used).  If set to <code>true</code>,
-    the value of the <code>debuglevel</code> attribute determines the
-    command line argument.</td>
-    <td align="center" valign="top">No</td>
+    <td>nowarn</td>
+    <td>Indicates whether the <kbd>-nowarn</kbd> switch should be passed to the compiler.</td>
+    <td>No; defaults to <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">debuglevel</td>
-    <td valign="top">Keyword list to be appended to the <code>-g</code>
-      command-line switch.  This will be ignored by all implementations except
-      <code>modern</code>, <code>classic(ver &gt;= 1.2)</code> and <code>jikes</code>.
-      Legal values are <code>none</code> or a comma-separated list of the
-      following keywords:
-      <code>lines</code>, <code>vars</code>, and <code>source</code>.
-      If <code>debuglevel</code> is not specified, by default,
-      nothing will be
-      appended to <code>-g</code>.  If <code>debug</code> is not turned on,
-      this attribute will be ignored.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>debug</td>
+    <td>Indicates whether source should be compiled with debug information.  If set
+      to <q>off</q>, <kbd>-g:none</kbd> will be passed on the command line for compilers that
+      support it (for other compilers, no command line argument will be used).  If set
+      to <q>true</q>, the value of the <var>debuglevel</var> attribute determines the command line
+      argument.</td>
+    <td>No; defaults to <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">optimize</td>
-    <td valign="top">
-      Indicates whether source should be compiled with
-      optimization; defaults to <code>off</code>. <strong>Note</strong>
-      that this flag is just ignored by Sun's <code>javac</code> starting
-      with JDK 1.3 (since compile-time optimization is unnecessary).
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>debuglevel</td>
+    <td>Keyword list to be appended to the <kbd>-g</kbd> command-line switch. Legal values
+      are <q>none</q> or a comma-separated list of the following
+      keywords: <q>lines</q>, <q>vars</q>, and <q>source</q>.</td>
+    <td>No; ignored when <var>debug</var> is <q>false</q> or any implementation other
+      than <q>modern</q>, <q>javac1.2</q> and <q>jikes</q>; by default, nothing will be appended
+      to <kbd>-g</kbd></td>
   </tr>
   <tr>
-    <td valign="top">deprecation</td>
-    <td valign="top">Indicates whether source should be compiled with
-      deprecation information; defaults to <code>off</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>optimize</td>
+    <td>Indicates whether source should be compiled with optimization. <strong>Note</strong> that
+      this flag is just ignored by Sun's <kbd>javac</kbd> since JDK 1.3 (because compile-time
+      optimization is unnecessary).</td>
+    <td>No; defaults to <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">target</td>
-    <td valign="top">Generate class files for specific VM version
-    (e.g., <code>1.1</code> or <code>1.2</code>). <b>Note that the
-    default value depends on the JVM that is running Ant.  In
-    particular, if you use JDK 1.4+ the generated classes will not be
-    usable for a 1.1 Java VM unless you explicitly set this attribute
-    to the value 1.1 (which is the default value for JDK 1.1 to
-    1.3).  We highly recommend to always specify this
-    attribute.</b><br>
-    A default value for this attribute can be provided using the magic
-    <a
-    href="../javacprops.html#target"><code>ant.build.javac.target</code></a>
-    property.</td>
-    <td align="center" valign="top">No</td>
+    <td>deprecation</td>
+    <td>Indicates whether source should be compiled with deprecation information.</td>
+    <td>No; defaults to <code>off</code></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Asks the compiler for verbose output; defaults to
-      <code>no</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>verbose</td>
+    <td>Asks the compiler for verbose output.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">depend</td> <td valign="top">Enables dependency-tracking
-      for compilers that support this (<code>jikes</code> and
-      <code>classic</code>).</td>
-    <td align="center" valign="top">No</td>
+    <td>depend</td>
+    <td>Enables dependency tracking for compilers that support this (<q>jikes</q>
+      and <q>classic</q>).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includeAntRuntime</td>
-    <td valign="top">Whether to include the Ant run-time libraries in the
-      classpath; defaults to <code>yes</code>, unless
-      <a href="../sysclasspath.html"><code>build.sysclasspath</code></a> is set.
-      <em>It is usually best to set this to false</em> so the script's behavior is not
-      sensitive to the environment in which it is run.</td>
-    <td align="center" valign="top">No</td>
+    <td>includeAntRuntime</td>
+    <td>Whether to include the Ant run-time libraries in the classpath. <em>It is usually best</em>
+      to set this to <q>false</q> so the script's behavior is not sensitive to the environment in
+      which it is run.</td>
+    <td>No; defaults to <q>yes</q>,
+      unless <a href="../sysclasspath.html"><code>build.sysclasspath</code></a> property is set</td>
   </tr>
   <tr>
-    <td valign="top">includeJavaRuntime</td>
-    <td valign="top">Whether to include the default run-time
-      libraries from the executing VM in the classpath;
-      defaults to <code>no</code>.<br/>
-      <b>Note:</b> In some setups the run-time libraries may be part
-      of the "Ant run-time libraries" so you may need to explicitly
-      set includeAntRuntime to false to ensure that the Java
-      run-time libraries are not included.</td>
-    <td align="center" valign="top">No</td>
+    <td>includeJavaRuntime</td>
+    <td>Whether to include the default run-time libraries from the executing JVM in the
+      classpath.<br/><strong>Note</strong>: In some setups the run-time libraries may be part of the
+      "Ant run-time libraries" so you may need to explicitly set <var>includeAntRuntime</var>
+      to <q>false</q> to ensure that the Java run-time libraries are not included.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">fork</td>
-    <td valign="top">Whether to execute <code>javac</code> using the
-      JDK compiler externally; defaults to <code>no</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>fork</td>
+    <td>Whether to execute <code>javac</code> using the JDK compiler externally.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">Complete path to the <code>javac</code>
-      executable to use in case of <code>fork=&quot;yes&quot;</code>.
-      Defaults to the compiler of the Java version that is currently
-      running Ant.  Ignored if <code>fork=&quot;no&quot;</code>.<br>
-      Since Ant 1.6 this attribute can also be used to specify the
-      path to the executable when using jikes, jvc, gcj or sj.</td>
-    <td align="center" valign="top">No</td>
+    <td>executable</td>
+    <td>Complete path to the <kbd>javac</kbd> executable to use in case of <var>fork</var>
+      is <q>yes</q>.<br/><em>Since Ant 1.6</em> this attribute can also be used to specify the path
+      to the executable when using <q>jikes</q>, <q>jvc</q>, <q>gcj</q> or <q>sj</q>.</td>
+    <td>No; defaults to the compiler of current JDK, ignored if <var>fork</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">memoryInitialSize</td>
-    <td valign="top">The initial size of the memory for the underlying VM,
-      if <code>javac</code> is run externally; ignored otherwise. Defaults
-      to the standard VM memory setting.
-      (Examples: <code>83886080</code>, <code>81920k</code>, or
-      <code>80m</code>)</td>
-    <td align="center" valign="top">No</td>
+    <td>memoryInitialSize</td>
+    <td>The initial size of the memory for the underlying JVM, if <kbd>javac</kbd> is run
+      externally.  (Examples: <q>83886080</q>, <q>81920k</q>, or <q>80m</q>)</td>
+    <td>No; defaults to the standard JVM memory setting, ignored if <var>fork</var>
+      is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">memoryMaximumSize</td>
-    <td valign="top">The maximum size of the memory for the underlying VM,
-      if <code>javac</code> is run externally; ignored otherwise. Defaults
-      to the standard VM memory setting.
-      (Examples: <code>83886080</code>, <code>81920k</code>, or
-      <code>80m</code>)</td>
-    <td align="center" valign="top">No</td>
+    <td>memoryMaximumSize</td>
+    <td>The maximum size of the memory for the underlying JVM, if <kbd>javac</kbd> is run
+      externally; ignored otherwise.  (Examples: <q>83886080</q>, <q>81920k</q>, or <q>80m</q>)</td>
+    <td>No; defaults to the standard JVM memory setting, ignored if <var>fork</var>
+      is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Indicates whether compilation errors
-        will fail the build; defaults to <code>true</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Indicates whether compilation errors will fail the build>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">errorProperty</td>
-    <td valign="top">
-      The property to set (to the value "true") if compilation fails.
-      <em>Since Ant 1.7.1</em>.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>errorProperty</td>
+    <td>The property to set to <q>true</q> if compilation fails.  <em>Since Ant 1.7.1</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">source</td>
-
-    <td valign="top">Value of the <code>-source</code> command-line
-    switch; will be ignored by all implementations prior to
-    <code>javac1.4</code> (or <code>modern</code> when Ant is not
-    running in a 1.3 VM), <code>gcj</code> and <code>jikes</code>.<br>
-    If you use this attribute together with <code>gcj</code>
-    or <code>jikes</code>, you must make sure that your version
-    supports the <code>-source</code> (or <code>-fsource</code> for
-    gcj)
-    switch.  By default, no <code>-source</code> argument will be used
-    at all.<br>
-    <b>Note that the default value depends on the JVM that is running
-    Ant.  We highly recommend to always specify this
-    attribute.</b><br>
-    A default value for this attribute can be provided using the magic
-    <a
-    href="../javacprops.html#source"><code>ant.build.javac.source</code></a>
-    property.</td>
-
-    <td align="center" valign="top">No</td>
+    <td>source</td>
+    <td>Java language features accepted by compiler, as specified by the <kbd>-source</kbd>
+      command-line switch.  Valid feature versions are <q>1.3</q>, <q>1.4</q>, <q>1.5</q>
+      or <q>5</q>, etc.  The attribute will be ignored by all implementations prior
+      to <q>javac1.4</q> (or <q>modern</q> when Ant is not running in a JVM 1.3), <q>gcj</q>
+      and <q>jikes</q>.<br/>  If you use this attribute together with <q>gcj</q> or <q>jikes</q>, you
+      must make sure that your version supports the <kbd>-source</kbd> (or <kbd>-fsource</kbd>
+      for <kbd>gcj</kbd>) switch.</td>
+    <td>No; by default, no <kbd>-source</kbd> argument will be used at all unless the magic
+      <a href="../javacprops.html#source"><code>ant.build.javac.source</code></a> property is
+      set<br/><strong>Note that the default value depends on JDK that is running Ant.  We highly
+      recommend to always specify this attribute.</strong></td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td valign="top">The compiler implementation to use.
-      If this attribute is not set, the value of the
-      <code>build.compiler</code> property, if set, will be used.
-      Otherwise, the default compiler for the current VM will be used.
-      (See the above <a href="#compilervalues">list</a> of valid
-      compilers.)</td>
-    <td align="center" valign="top">No</td>
+    <td>target</td>
+    <td>Generate class files for specific JVM version (cross-compile).</td>
+    <td>No; by default, no <kbd>-target</kbd> argument will be used at all unless the
+      magic <a href="../javacprops.html#target"><code>ant.build.javac.target</code></a> property is
+      set<br/><strong>Note that the default value depends on JDK that is running Ant and
+      on <var>source</var>
+      (see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html#BHCJDCID"
+      target="_top">Cross-Compilation Options</a>).  We highly recommend to always specify this
+      attribute.</strong></td>
   </tr>
   <tr>
-    <td valign="top">listfiles</td>
-    <td valign="top">Indicates whether the source files to be compiled will
-      be listed; defaults to <code>no</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>compiler</td>
+    <td>The compiler implementation to use.  See the above <a href="#compilervalues">list</a> of
+      valid compilers.</td>
+    <td>No; defaults to the value of the <code>build.compiler</code> property, if set, or default
+      compiler for the current JDK otherwise</td>
   </tr>
   <tr>
-    <td valign="top">tempdir</td>
-    <td valign="top">Where Ant should place temporary files.
-      This is only used if the task is forked and the
-      command line args length exceeds 4k.
-      <em>Since Ant 1.6</em>.</td>
-    <td align="center" valign="top">
-      No; default is <i>java.io.tmpdir</i>.
-    </td>
+    <td>listfiles</td>
+    <td>Indicates whether the source files to be compiled will be listed.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">updatedProperty</td>
-    <td valign="top">
-      The property to set (to the value "true") 
-      if compilation has taken place
-      and has been successful.
-      <em>Since Ant 1.7.1</em>.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>tempdir</td>
+    <td>Where Ant should place temporary files.  This is only used if the task is forked and the
+      command line args length exceeds 4 kB.  <em>Since Ant 1.6</em>.</td>
+    <td>No; default is <code>java.io.tmpdir</code></td>
   </tr>
   <tr>
-    <td valign="top">includeDestClasses</td>
-    <td valign="top">
-      This attribute controls whether to include the
-      destination classes directory in the classpath
-      given to the compiler.
-      The default value of this is "true" and this
-      means that previously compiled classes are on
-      the classpath for the compiler. This means that "greedy" compilers
-      will not recompile dependent classes that are already compiled.
-      In general this is a good thing as it stops the compiler
-      for doing unnecessary work. However, for some edge cases,
-      involving generics, the javac compiler
-      needs to compile the dependent classes to get the generics
-      information. One example is documented in the bug report:
-      <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=40776">
-        Bug 40776 - a problem compiling a Java 5 project with generics</a>.
-      Setting the attribute to "false" will cause the compiler
-      to recompile dependent classes.
-      <em>Since Ant 1.7.1</em>.
-    </td>
-    <td align="center" valign="top">No - default is "true"</td>
+    <td>updatedProperty</td>
+    <td>The property to set to <q>true</q> if compilation has taken place and has been
+      successful.  <em>Since Ant 1.7.1</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">createMissingPackageInfoClass</td>
-    <td valign="top">
-      Some package level annotations in <code>package-info.java</code>
-      files don't create any <code>package-info.class</code> files so
-      Ant would recompile the same file every time.<br/>
-      Starting with Ant 1.8 Ant will create an
-      empty <code>package-info.class</code> for
-      each <code>package-info.java</code> if there isn't one created
-      by the compiler.<br/>
-      In some setups this additional class causes problems and it can
-      be suppressed by setting this attribute to "false".
-      <em>Since Ant 1.8.3</em>.
-    </td>
-    <td align="center" valign="top">No - default is "true"</td>
+    <td>includeDestClasses</td>
+    <td>This attribute controls whether to include the destination classes directory in the
+      classpath given to the compiler.  If set to <q>true</q> (default), previously compiled classes
+      are on the classpath for the compiler. This means that "greedy" compilers will not recompile
+      dependent classes that are already compiled.  In general this is a good thing as it stops the
+      compiler for doing unnecessary work. However, for some edge cases, involving generics,
+      the <kbd>javac</kbd> compiler needs to compile the dependent classes to get the generics
+      information. One example is documented in the bug
+      report: <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=40776" target="_top">Bug
+      40776 - a problem compiling a Java 5 project with generics</a>.  Setting the attribute
+      to <q>false</q> will cause the compiler to recompile dependent classes.  <em>Since Ant
+      1.7.1</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">modulepath</td>
-    <td valign="top">
-      Specify where to find application modules. A list of directories of modules, module files or exploded modules.
-      <em>since Ant 1.9.7</em>
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>createMissingPackageInfoClass</td>
+    <td>Some package level annotations in <samp>package-info.java</samp> files don't create
+      any <samp>package-info.class</samp> files so Ant would recompile the same file every
+      time.<br/><em>Since Ant 1.8</em>, an empty <samp>package-info.class</samp> is created for
+      each <samp>package-info.java</samp> if there isn't one created by the compiler.<br/>In some
+      setups this additional class causes problems and it can be suppressed by setting this
+      attribute to <q>false</q>.  <em>Since Ant 1.8.3</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">modulepathref</td>
-    <td valign="top">
-      The modulepath to use, given as <a href="../using.html#references">reference</a> to a PATH defined elsewhere.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>modulepath</td>
+    <td>Specify where to find application modules. A list of directories of modules, module files or
+    exploded modules.  <em>since Ant 1.9.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">modulesourcepath</td>
-    <td valign="top">
-      Specify where to find input source files for multiple module compilation.
-      <em>since Ant 1.9.7</em>
-    </td>
-    <td align="center" valign="top">Yes, unless <code>srcdir</code> attribute or nested <code>&lt;src&gt;</code> elements are present</td>
+    <td>modulepathref</td>
+    <td>The <var>modulepath</var> to use, given as <a href="../using.html#references">reference</a>
+    to a path defined elsewhere.  <em>since Ant 1.9.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">modulesourcepathref</td>
-    <td valign="top">
-      The modulesourcepath to use, given as <a href="../using.html#references">reference</a> to a PATH defined elsewhere.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>modulesourcepath</td>
+    <td>Specify where to find input source files for multiple module compilation.  <em>since Ant
+      1.9.7</em></td>
+    <td>Yes, unless <var>srcdir</var> attribute or nested <code>&lt;src&gt;</code> elements are
+      present</td>
   </tr>
   <tr>
-    <td valign="top">upgrademodulepath</td>
-    <td valign="top">
-      Specify the location of modules that replace upgradeable modules in the runtime image.
-      <em>since Ant 1.9.7</em>
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>modulesourcepathref</td>
+    <td>The <var>modulesourcepath</var> to use, given
+      as <a href="../using.html#references">reference</a> to a path defined elsewhere.  <em>since
+      Ant 1.9.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">upgrademodulepathref</td>
-    <td valign="top">
-      The upgrademodulepath to use, given as <a href="../using.html#references">reference</a> to a PATH defined elsewhere.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>upgrademodulepath</td>
+    <td>Specify the location of modules that replace upgradeable modules in the runtime
+    image.  <em>since Ant 1.9.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">nativeheaderdir</td>
-    <td valign="top">
-      Specify where to place generated native header files. Ignored
-      when running on JDK &lt; 8.
-      <em>Since Ant 1.9.8</em>.
-    <td align="center" valign="top">No</td>
+    <td>upgrademodulepathref</td>
+    <td>The <var>upgrademodulepath</var> to use, given
+    as <a href="../using.html#references">reference</a> to a path defined elsewhere.  <em>since Ant
+    1.9.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">release</td>
-    <td valign="top">
-      Specify the value for the <code>--release</code> switch. Ignored
-      when running on JDK &lt; 9.<br>
-      When set and running on JDK &gt;= 9 the source and target
-      attributes as well as the bootclasspath will be ignored.
-      <em>Since Ant 1.9.8</em>.
-    <td align="center" valign="top">No</td>
+    <td>nativeheaderdir</td>
+    <td>Specify where to place generated native header files.  <em>Since Ant 1.9.8</em>.
+    <td>No, ignored when compiling on JDK 7 or earlier</td>
+  </tr>
+  <tr>
+    <td>release</td>
+    <td>Specify the value for the <kbd>--release</kbd> switch.<br/>When set and running on JDK 9+
+      the <var>source</var> and <var>target</var> attributes as well as the <var>bootclasspath</var>
+      will be ignored.  <em>Since Ant 1.9.8</em>.
+    <td>No, ignored when compiling on JDK 8 or earlier</td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>srcdir</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
-<h4><code>srcdir</code>, <code>classpath</code>, <code>sourcepath</code>,
-<code>bootclasspath</code>, <code>modulepath</code>, <code>modulesourcepath</code>,
-<code>upgrademodulepath</code> and <code>extdirs</code></h4>
-<p><code>&lt;javac&gt;</code>'s <code>srcdir</code>, <code>classpath</code>,
-<code>sourcepath</code>, <code>bootclasspath</code>,
-<code>extdirs</code>, <code>modulepath</code>, <code>modulesourcepath</code>,
-and <code>upgrademodulepath</code> attributes are
-<a href="../using.html#path">path-like structures</a>
-and can also be set via nested
-<code>&lt;src&gt;</code> (note the different name!),
-<code>&lt;classpath&gt;</code>,
-<code>&lt;sourcepath&gt;</code>,
-<code>&lt;bootclasspath&gt;</code>,
-<code>&lt;extdirs&gt;</code>,
-<code>&lt;modulepath&gt;</code>,
-<code>&lt;modulesourcepath&gt;</code> and
-<code>&lt;upgrademodulepath&gt;</code>
-elements, respectively.</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>srcdir</var>) as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+<h4><code>srcdir</code>, <code>classpath</code>, <code>sourcepath</code>, <code>bootclasspath</code>,
+<code>modulepath</code>, <code>modulesourcepath</code>, <code>upgrademodulepath</code> and <code>extdirs</code></h4>
+<p><code>&lt;javac&gt;</code>'s <var>srcdir</var>, <var>classpath</var>, <var>sourcepath</var>,
+<var>bootclasspath</var>, <var>extdirs</var>, <var>modulepath</var>, <var>modulesourcepath</var>,
+and <var>upgrademodulepath</var> attributes are <a href="../using.html#path">path-like
+structures</a> and can also be set via nested <code>&lt;src&gt;</code> (note the different
+name!), <code>&lt;classpath&gt;</code>, <code>&lt;sourcepath&gt;</code>, <code>&lt;bootclasspath&gt;</code>,
+<code>&lt;extdirs&gt;</code>, <code>&lt;modulepath&gt;</code>, <code>&lt;modulesourcepath&gt;</code>
+and <code>&lt;upgrademodulepath&gt;</code> elements, respectively.</p>
 
 <h4>compilerarg</h4>
 
-<p>You can specify additional command line arguments for the compiler
-with nested <code>&lt;compilerarg&gt;</code> elements.  These elements
-are specified like <a href="../using.html#arg">Command-line
-Arguments</a> but have an additional attribute that can be used to
-enable arguments only if a given compiler implementation will be
-used.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>You can specify additional command line arguments for the compiler with
+nested <code>&lt;compilerarg&gt;</code> elements.  These elements are specified
+like <a href="../using.html#arg">Command-line Arguments</a> but have an additional attribute that
+can be used to enable arguments only if a given compiler implementation will be used.</p>
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">value</td>
-    <td align="center" rowspan="4">See
-    <a href="../using.html#arg">Command-line Arguments</a>.</td>
-    <td align="center" rowspan="4">Exactly one of these.</td>
+    <td>value</td>
+    <td rowspan="4">See <a href="../using.html#arg">Command-line Arguments</a>.</td>
+    <td rowspan="4">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">line</td>
+    <td class="var">line</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
+    <td class="var">file</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
+    <td class="var">path</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td align="center" rowspan="2">See
-    <a href="../using.html#arg">Command-line Arguments</a>.
-    <em>Since Ant 1.8.</em></td>
-    <td valign="top" align="center">No</td>
+    <td>prefix</td>
+    <td rowspan="2">See <a href="../using.html#arg">Command-line Arguments</a>.  <em>Since Ant
+    1.8</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top" align="center">No</td>
+    <td>suffix</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td>Only pass the specified argument if the chosen
-      compiler implementation matches the value of this attribute.
-      Legal values are the
-      same as those in the above <a href="#compilervalues">list</a> of valid
-      compilers.)</td>
-    <td align="center">No</td>
+    <td>compiler</td>
+    <td>Only pass the specified argument if the chosen compiler implementation matches the value of
+      this attribute.  Legal values are the same as those in the
+      above <a href="#compilervalues">list</a> of valid compilers.)</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4>compilerclasspath <em>since Ant 1.8.0</em></h4>
+<h4>compilerclasspath</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>A <a href="../using.html#path">path-like structure</a> holding the classpath to use when loading
+the compiler implementation if a custom class has been specified.  Doesn't have any effect when
+using one of the built-in compilers.</p>
 
-<p>A <a href="../using.html#path">PATH like structure</a> holding the
-  classpath to use when loading the compiler implementation if a
-  custom class has been specified.  Doesn't have any effect when
-  using one of the built-in compilers.</p>
-
-<h4>Any nested element of a type that implements CompilerAdapter
-  <em>since Ant 1.8.0</em></h4>
-
-<p>If a defined type implements the <code>CompilerAdapter</code>
-  interface a nested element of that type can be used as an
-  alternative to the <code>compiler</code> attribute.</p>
+<h4>Any nested element of a type that implements <code>CompilerAdapter</code></h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>If a defined type implements the <code>CompilerAdapter</code> interface a nested element of that
+type can be used as an alternative to the <var>compiler</var> attribute.</p>
 
 <h3>Examples</h3>
-<pre>  &lt;javac srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot;
-         classpath=&quot;xyz.jar&quot;
-         debug=&quot;on&quot;
-         source=&quot;1.4&quot;
-  /&gt;</pre>
-<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. The source level is 1.4,
-so you can use <code>assert</code> statements.</p>
 
-<pre>  &lt;javac srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot;
-         fork=&quot;true&quot;
-         source=&quot;1.2&quot;
-         target=&quot;1.2&quot;
-  /&gt;</pre>
-<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.  This will fork off the javac
-compiler using the default <code>javac</code> executable.
-The source level is 1.2 (similar to 1.1 or 1.3) and
-the class files should be runnable under JDK 1.2+ as well.</p>
+<p>Compile all <samp>.java</samp> files under the <samp>${src}</samp> directory, and store
+the <samp>.class</samp> files in the <samp>${build}</samp> directory. The classpath used
+includes <samp>xyz.jar</samp>, and compiling with debug information is on. The source level
+is <q>1.4</q>, so you can use <code>assert</code> statements.</p>
+<pre>
+&lt;javac srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot;
+       classpath=&quot;xyz.jar&quot;
+       debug=&quot;on&quot;
+       source=&quot;1.4&quot;/&gt;</pre>
 
-<pre>  &lt;javac srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot;
-         fork=&quot;java$$javac.exe&quot;
-         source=&quot;1.5&quot;
-  /&gt;</pre>
-<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.  This will fork off the javac
-compiler, using the executable named <code>java$javac.exe</code>.  Note
-that the <code>$</code> sign needs to be escaped by a second one.
-The source level is 1.5, so you can use generics.</p>
+<p>Compile all <samp>.java</samp> files under the <samp>${src}</samp> directory, and store
+the <samp>.class</samp> files in the <samp>${build}</samp> directory. Java compiler is forked using
+the default <kbd>javac</kbd> executable. The source level is <q>1.2</q> (similar to <q>1.1</q>
+or <q>1.3</q>) and the class files should be runnable under JDK 1.2+ as well.</p>
+<pre>
+&lt;javac srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot;
+       fork=&quot;true&quot;
+       source=&quot;1.2&quot;
+       target=&quot;1.2&quot;/&gt;</pre>
 
-<pre>  &lt;javac srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot;
-         includes=&quot;mypackage/p1/**,mypackage/p2/**&quot;
-         excludes=&quot;mypackage/p1/testpackage/**&quot;
-         classpath=&quot;xyz.jar&quot;
-         debug=&quot;on&quot;
-  /&gt;</pre>
-<p>compiles <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 debug information is on.
-Only files under <code>mypackage/p1</code> and <code>mypackage/p2</code> are
-used. All files in and below the <code>mypackage/p1/testpackage</code>
-directory are excluded from compilation.
-You didn't specify a source or target level,
-so the actual values used will depend on which JDK you ran Ant with.</p>
+<p>Compile all <samp>.java</samp> files under the <samp>${src}</samp> directory, and store
+the <samp>.class</samp> files in the <samp>${build}</samp> directory. Java compiler is forked using
+the executable named <kbd>java$javac.exe</kbd>. Note that the <q>$</q> sign needs to be escaped by a
+second one. The source level is <q>1.5</q>, so you can use generics.</p>
+<pre>
+&lt;javac srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot;
+       fork=&quot;java$$javac.exe&quot;
+       source=&quot;1.5&quot;/&gt;</pre>
 
-<pre>  &lt;javac srcdir=&quot;${src}:${src2}&quot;
-         destdir=&quot;${build}&quot;
-         includes=&quot;mypackage/p1/**,mypackage/p2/**&quot;
-         excludes=&quot;mypackage/p1/testpackage/**&quot;
-         classpath=&quot;xyz.jar&quot;
-         debug=&quot;on&quot;
-  /&gt;</pre>
+<p>Compile <samp>.java</samp> files under the <samp>${src}</samp> directory, and store
+the <samp>.class</samp> files in the <code>${build}</code> directory. The classpath used
+includes <samp>xyz.jar</samp>, and debug information is on. Only files
+under <samp>mypackage/p1</samp> and <samp>mypackage/p2</samp> are used. All files in and below
+the <samp>mypackage/p1/testpackage</samp> directory are excluded from compilation. You didn't
+specify a source or target level, so the actual values used will depend on which JDK you ran Ant
+with.</p>
+<pre>
+&lt;javac srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot;
+       includes=&quot;mypackage/p1/**,mypackage/p2/**&quot;
+       excludes=&quot;mypackage/p1/testpackage/**&quot;
+       classpath=&quot;xyz.jar&quot;
+       debug=&quot;on&quot;/&gt;</pre>
 
-<p>is the same as the previous example, with the addition of a second
-source path, defined by
-the property <code>src2</code>. This can also be represented using nested
-<code>&lt;src&gt;</code> elements as follows:</p>
+<p>This is the same as the previous example, with the addition of a second source path, defined by
+the property <samp>src2</samp>. This can also be represented using nested <code>&lt;src&gt;</code>
+elements as follows:</p>
+<pre>
+&lt;javac destdir=&quot;${build}&quot;
+       classpath=&quot;xyz.jar&quot;
+       debug=&quot;on&quot;&gt;
+  &lt;src path=&quot;${src}&quot;/&gt;
+  &lt;src path=&quot;${src2}&quot;/&gt;
+  &lt;include name=&quot;mypackage/p1/**&quot;/&gt;
+  &lt;include name=&quot;mypackage/p2/**&quot;/&gt;
+  &lt;exclude name=&quot;mypackage/p1/testpackage/**&quot;/&gt;
+&lt;/javac&gt;</pre>
 
-<pre>  &lt;javac destdir=&quot;${build}&quot;
-         classpath=&quot;xyz.jar&quot;
-         debug=&quot;on&quot;&gt;
-    &lt;src path=&quot;${src}&quot;/&gt;
-    &lt;src path=&quot;${src2}&quot;/&gt;
-    &lt;include name=&quot;mypackage/p1/**&quot;/&gt;
-    &lt;include name=&quot;mypackage/p2/**&quot;/&gt;
-    &lt;exclude name=&quot;mypackage/p1/testpackage/**&quot;/&gt;
-  &lt;/javac&gt;</pre>
+<p>If you want to run the <kbd>javac</kbd> compiler of a different JDK, you should tell Ant where to
+find the compiler and which version of JDK you will be using so it can choose the correct command
+line switches. The following example executes a JDK 1.1 <kbd>javac</kbd> in a new process and uses
+the correct command line switches even when Ant is running in a JVM of a different version:</p>
+<pre>
+&lt;javac srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot;
+       fork=&quot;yes&quot;
+       executable=&quot;/opt/java/jdk1.1/bin/javac&quot;
+       compiler=&quot;javac1.1&quot;/&gt;</pre>
 
-<p>If you want to run the javac compiler of a different JDK, you
-should tell Ant, where to find the compiler and which version of JDK
-you will be using so it can choose the correct command line switches.
-The following example executes a JDK 1.1 javac in a new process and
-uses the correct command line switches even when Ant is running in a
-Java VM of a different version:</p>
+<p id="srcdirnote"><strong>Note</strong>: If you wish to compile only source files located in
+certain packages below a common root, use the <var>include</var>/<var>exclude</var> attributes
+or <code>&lt;include&gt;</code>/<code>&lt;exclude&gt;</code> nested elements to filter for these
+packages. Do not include part of your package structure in the <var>srcdir</var> attribute (or
+nested <code>&lt;src&gt;</code> elements), or Ant will recompile your source files every time you
+run your compile target. See the <a href="https://ant.apache.org/faq.html#always-recompiles"
+target="_top">Ant FAQ</a> for additional information.</p>
 
-<pre>  &lt;javac srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot;
-         fork=&quot;yes&quot;
-         executable=&quot;/opt/java/jdk1.1/bin/javac&quot;
-         compiler=&quot;javac1.1&quot;
-  /&gt;</pre>
+<p>If you wish to compile only files explicitly specified and disable <code>javac</code>'s default
+searching mechanism then you can unset the <var>sourcepath</var> attribute:</p>
+<pre>
+&lt;javac sourcepath=&quot;&quot; srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot; &gt;
+  &lt;include name="**/*.java"/&gt;
+  &lt;exclude name="**/Example.java"/&gt;
+&lt;/javac&gt;</pre>
 
-<p><a name="srcdirnote"><b>Note:</b></a>
-If you wish to compile only source files located in certain packages below a
-common root, use the <code>include</code>/<code>exclude</code> attributes
-or <code>&lt;include&gt;</code>/<code>&lt;exclude&gt;</code> nested elements
-to filter for these packages. Do not include part of your package structure
-in the <code>srcdir</code> attribute
-(or nested <code>&lt;src&gt;</code> elements), or Ant will recompile your
-source files every time you run your compile target. See the
-<a href="http://ant.apache.org/faq.html#always-recompiles">Ant FAQ</a>
-for additional information.</p>
+<p>That way the <code>javac</code> will compile all Java source files under <samp>${src}</samp>
+directory but skip the examples. The compiler will even produce errors if some of the non-example
+files refers to them.</p>
 
-<p>
-If you wish to compile only files explicitly specified and disable
-javac's default searching mechanism then you can unset the sourcepath
-attribute:
-<pre>  &lt;javac sourcepath=&quot;&quot; srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot; &gt;
-    &lt;include name="**/*.java"/&gt;
-    &lt;exclude name="**/Example.java"/&gt;
-  &lt;/javac&gt;</pre>
-That way the javac will compile all java source files under &quot;${src}&quot;
-directory but skip the examples. The compiler will even produce errors if some of
-the non-example files refers to them.
-</p>
+<p>If you wish to compile with a special JDK (another than the one Ant is currently using), set
+the <var>executable</var> and <var>fork</var> attribute. Using <var>taskname</var> could show in the
+log, that these settings are fix.</p>
+<pre>
+&lt;javac srcdir=&quot;&quot;
+       destdir=&quot;&quot;
+       executable=&quot;path-to-java14-home/bin/javac&quot;
+       fork=&quot;true&quot;
+       taskname=&quot;javac1.4&quot;/&gt;</pre>
 
-<p>
-If you wish to compile with a special JDK (another than the one Ant is currently using),
-set the <code>executable</code> and <code>fork</code> attribute. Using <code>taskname</code>
-could show in the log, that these settings are fix.
-<pre>  &lt;javac srcdir=&quot;&quot; 
-         destdir=&quot;&quot;
-         executable=&quot;path-to-java14-home/bin/javac&quot; 
-         fork=&quot;true&quot;
-         taskname=&quot;javac1.4&quot; /&gt;</pre>
-</p>
-
-
-<p><b>Note:</b> If you are using Ant on Windows and a new DOS window pops up
-for every use of an external compiler, this may be a problem of the JDK you are
-using.  This problem may occur with all JDKs &lt; 1.2.</p>
-
-
-<p>
-If you want to activate other compiler options like <i>lint</i> you could use
-the <tt>&lt;compilerarg&gt;</tt> element:
-<pre>  &lt;javac srcdir="${src.dir}"
-         destdir="${classes.dir}"
-         classpathref="libraries"&gt;
-    &lt;compilerarg value="-Xlint"/&gt;
-  &lt;/javac&gt; </pre>
-</p>  
-
-<p>If you want to use a custom
-  CompilerAdapter <code>org.example.MyAdapter</code> you can either
-  use the compiler attribute:</p>
+<p>If you want to activate other compiler options like <code>lint</code> you could use
+the <code>&lt;compilerarg&gt;</code> element:</p>
 <pre>
 &lt;javac srcdir="${src.dir}"
        destdir="${classes.dir}"
-       compiler="org.example.MyAdapter"/&gt;
-</pre>
+       classpathref="libraries"&gt;
+  &lt;compilerarg value="-Xlint"/&gt;
+&lt;/javac&gt;</pre>
+
+<p>If you want to use a custom CompilerAdapter <code>org.example.MyAdapter</code> you can either use
+the <var>compiler</var> attribute:</p>
+
+<pre>
+&lt;javac srcdir="${src.dir}"
+       destdir="${classes.dir}"
+       compiler="org.example.MyAdapter"/&gt;</pre>
+
 <p>or a define a type and nest this into the task like in:</p>
+
 <pre>
 &lt;componentdef classname="org.example.MyAdapter"
               name="myadapter"/&gt;
 &lt;javac srcdir="${src.dir}"
        destdir="${classes.dir}"&gt;
   &lt;myadapter/&gt;
-&lt;/javac&gt;
-</pre>
-<p>in which case your compiler adapter can support attributes and
-  nested elements of its own.</p>
+&lt;/javac&gt;</pre>
 
-<pre>  &lt;javac srcdir=&quot;${src}&quot;
-         destdir=&quot;${build}&quot;
-         includeantruntime=&quot;false&quot;
-         modulepath=&quot;modules&quot;
-         source=&quot;9&quot;
-  /&gt;</pre>
-<p>compiles all <code>.java</code> files in a single module under the <code>${src}</code> directory,
-  and stores the <code>.class</code> files in the <code>${build}</code> directory. The compilation uses
-  application modules located in <code>modules</code> folder.The source level is <code>9</code> to enable modules.</p>
+<p>in which case your compiler adapter can support attributes and nested elements of its own.</p>
 
-<pre>  &lt;javac modulesourcepath=&quot;${src}/*/{gen,lin{32,64}}/classes&quot;
-         destdir=&quot;${build}&quot;
-         includeantruntime=&quot;false&quot;
-         modulepath=&quot;modules&quot;
-         source=&quot;9&quot;
-  /&gt;</pre>
-<p>compiles all <code>.java</code> files in <code>gen/classes</code>, <code>lin32/classes</code> and
-  <code>lin64/classes</code> in all source modules under the <code>${src}</code> directory.
-  Generates module directories in the <code>${build}</code> directory. Each generated module directory under
-  the <code>${build}</code> directory contains <code>.class</code> files from corresponding source module.
-  The <code>*</code> is a token representing the name of any of the modules in the compilation module set.
-  The <code>{ ... , ... }</code> express alternates for expansion.
-  The compilation uses application modules located in <code>modules</code> folder.The source level is
-  <code>9</code> to enable modules.</p>
+<p>The following examples demonstrate the use of Java 9+ modules.</p>
 
-<h3>Jikes Notes</h3>
+<p>Compile all <samp>.java</samp> files in a single module under the <samp>${src}</samp> directory,
+and store the <samp>.class</samp> files in the <code>${build}</code> directory. The compilation uses
+application modules located in <samp>modules</samp> folder. The source level is <q>9</q> to enable
+modules.</p>
+<pre>
+&lt;javac srcdir=&quot;${src}&quot;
+       destdir=&quot;${build}&quot;
+       includeantruntime=&quot;false&quot;
+       modulepath=&quot;modules&quot;
+       source=&quot;9&quot;/&gt;</pre>
+
+<p>Compile all <samp>.java</samp> files in <samp>gen/classes</samp>, <samp>lin32/classes</samp>
+and <code>lin64/classes</code> in all source modules under the <code>${src}</code>
+directory. Generate module directories in the <samp>${build}</samp> directory. Each generated module
+directory under the <samp>${build}</samp> directory contains <code>.class</code> files from
+corresponding source module. The <samp>*</samp> is a token representing the name of any of the
+modules in the compilation module set. The <code>{ ... , ... }</code> express alternates for
+expansion. The compilation uses application modules located in <code>modules</code> folder. The
+source level is <q>9</q> to enable modules.</p>
+<pre>
+&lt;javac modulesourcepath=&quot;${src}/*/{gen,lin{32,64}}/classes&quot;
+       destdir=&quot;${build}&quot;
+       includeantruntime=&quot;false&quot;
+       modulepath=&quot;modules&quot;
+       source=&quot;9&quot;/&gt;</pre>
+
+<h3 id="jikes">Jikes notes</h3>
 
 <p>You need Jikes 1.15 or later.</p>
 
-<p>Jikes supports some extra options, which can be set be defining
-the properties shown below prior to invoking the task. The setting
-for each property will be in affect for all <code>&lt;javac&gt;</code>
-tasks throughout the build.
-The Ant developers are aware that
-this is ugly and inflexible &ndash; expect a better solution in the future.
-All the options are boolean, and must be set to <code>true</code> or
-<code>yes</code> to be
-interpreted as anything other than false. By default,
-<code>build.compiler.warnings</code> is <code>true</code>,
-while all others are <code>false</code>.</p>
+<p>Jikes supports some extra options, which can be set be defining the properties shown below prior
+to invoking the task. The setting for each property will be in effect for
+all <code>&lt;javac&gt;</code> tasks throughout the build.  The Ant developers are aware that this
+is ugly and inflexible &ndash; expect a better solution in the future.  All the options are boolean,
+and must be set to <q>true</q> or <q>yes</q> to be interpreted as anything other
+than <q>false</q>. By default, <code>build.compiler.warnings</code> is <q>true</q>, while all others
+are <q>false</q>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>Property</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Default</b></td>
+    <th scope="col">Property</th>
+    <th scope="col">Description</th>
+    <th scope="col">Default</th>
   </tr>
   <tr>
-    <td valign="top">
-	build.compiler.emacs
-	</td>
-	<td valign="top">
-	Enable emacs-compatible error messages.
-    </td>
-    <td valign="top">
-	<code>false</code>
-	</td>
+    <td><code>build.compiler.emacs</code></td>
+    <td>Enable emacs-compatible error messages.</td>
+    <td><q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">
-	build.compiler.fulldepend
-	</td>
-	<td valign="top">
-	Enable full dependency checking; see<br>
-	the <code>+F</code> switch in the Jikes manual.
-    </td>
-    <td valign="top">
-	<code>false</code>
-	</td>
+    <td><code>build.compiler.fulldepend</code></td>
+    <td>Enable full dependency checking; see<br/> the <code>+F</code> switch in the Jikes
+      manual.</td>
+    <td><q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">
-	build.compiler.pedantic
-	</td>
-	<td valign="top">
-	Enable pedantic warnings.
-    </td>
-    <td valign="top">
-	<code>false</code>
-	</td>
+    <td><code>build.compiler.pedantic</code></td>
+    <td>Enable pedantic warnings.</td>
+    <td><q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">
-	build.compiler.warnings<br>
-        <strong>Deprecated</strong>. Use
-  <code>&lt;javac&gt;</code>'s <code>nowarn</code>
-  attribute instead.
-	</td>
-	<td valign="top">
-	Don't disable warning messages.
-    </td>
-    <td valign="top">
-	<code>true</code>
-	</td>
+    <td><code>build.compiler.warnings</code><br/><em><u>Deprecated</u></em>.
+      Use <code>&lt;javac&gt;</code>'s <var>nowarn</var> attribute instead.</td>
+    <td>Don't disable warning messages.</td>
+    <td><q>true</q></td>
   </tr>
 </table>
 
-<h3>Jvc Notes</h3>
+<h3 id="jvc">Jvc notes</h3>
 
-<p>Jvc will enable Microsoft extensions unless you set the property
-<code>build.compiler.jvc.extensions</code> to false before invoking
-<code>&lt;javac&gt;</code>.</p>
+<p><q>Jvc</q> will enable Microsoft extensions unless you set the
+property <code>build.compiler.jvc.extensions</code> to <q>false</q> before
+invoking <code>&lt;javac&gt;</code>.</p>
 
-<h3><a name="bootstrap">Bootstrap Options</h3>
-<p>
-  The Sun javac compiler has a <em>bootclasspath</em> command
-  line option - this corresponds to the "bootclasspath" attribute/element
-  of the &lt;javac&gt; task. The Sun compiler also allows more
-  control over the boot classpath using the -X and -J-X attributes.
-  One can set these by using the &lt;compilerarg&gt;. Since Ant 1.6.0,
-  there is a shortcut to convert path references to strings that
-  can by used in an OS independent fashion (see
-  <a href="../using.html#pathshortcut">pathshortcut</a>). For example:
-</p>
+<h3 id="bootstrap">Bootstrap options</h3>
+<p>The Sun <kbd>javac</kbd> compiler has a <kbd>-bootclasspath</kbd> command line
+option&mdash;this corresponds to the <var>bootclasspath</var> attribute/element of
+the <code>&lt;javac&gt;</code> task. The Sun compiler also allows more control over the boot
+classpath using the <kbd>-X</kbd> and <kbd>-J-X</kbd> attributes.  One can set these by using
+the <code>&lt;compilerarg&gt;</code>. <em>Since Ant 1.6.0</em>, there is a shortcut to convert path
+references to strings that can by used in an OS independent fashion
+(see <a href="../using.html#pathshortcut">pathshortcut</a>). For example:</p>
+
 <pre>
-  &lt;path id="lib.path.ref"&gt;
-    &lt;fileset dir="lib" includes="*.jar"/&gt;
-  &lt;/path&gt;
-  &lt;javac srcdir="src" destdir="classes"&gt;
-    &lt;compilerarg arg="-Xbootclasspath/p:${toString:lib.path.ref}"/&gt;
+&lt;path id="lib.path.ref"&gt;
+  &lt;fileset dir="lib" includes="*.jar"/&gt;
+&lt;/path&gt;
+&lt;javac srcdir="src" destdir="classes"&gt;
+  &lt;compilerarg arg="-Xbootclasspath/p:${toString:lib.path.ref}"/&gt;
+&lt;/javac&gt;</pre>
+
+<h3>OpenJDK notes</h3>
+<p>The <a href="https://openjdk.java.net/" target="_top">OpenJDK</a> project has provided
+the <code>javac</code> <a href="https://openjdk.java.net/groups/compiler/" target="_top">compiler</a>
+as an open source project. The output of this project is a <code>javac.jar</code> which contains
+the <kbd>javac</kbd> compiler.  This compiler may be used with the <code>&lt;javac&gt;</code> task
+with the use of a <kbd>-Xbootclasspath/p</kbd> Java argument. The argument needs to be given to the
+runtime system of the <kbd>javac</kbd> executable, so it needs to be prepended with a <kbd>-J</kbd>,
+for example:</p>
+
+<pre>
+&lt;property name="patched.javac.jar"
+          location="${my.patched.compiler}/dist/lib/javac.jar"/&gt;
+
+&lt;presetdef name="patched.javac"&gt;
+  &lt;javac fork="yes"&gt;
+    &lt;compilerarg value="-J-Xbootclasspath/p:${patched.javac.jar}"/&gt;
   &lt;/javac&gt;
-</pre>
-
-  
-</p>
-
-<h3>OpenJDK Notes</h3>
-<p>
-  The <a href="https://openjdk.dev.java.net/">openjdk</a>
-  project has provided the javac
-  <a href="https://openjdk.dev.java.net/compiler/">compiler</a>
-  as an opensource project. The output of this project is a
-  <code>javac.jar</code> which contains the javac compiler.
-  This compiler may be used with the <code>&lt;javac&gt;</code> task with
-  the use of a <code>-Xbootclasspath/p</code> java argument. The argument needs
-  to be given to the runtime system of the javac executable, so it needs
-  to be prepended with a "-J". For example:
-
-<blockquote><pre>
-  &lt;property name="patched.javac.jar"
-            location="${my.patched.compiler}/dist/lib/javac.jar"/&gt;
-
-  &lt;presetdef name="patched.javac"&gt;
-    &lt;javac fork="yes"&gt;
-      &lt;compilerarg value="-J-Xbootclasspath/p:${patched.javac.jar}"/&gt;
-    &lt;/javac&gt;
-  &lt;/presetdef&gt;
+&lt;/presetdef&gt;
 
 
-  &lt;patched.javac srcdir="src/java" destdir="build/classes"
-                 debug="yes"/&gt;
-</pre></blockquote>
+&lt;patched.javac srcdir="src/java" destdir="build/classes"
+               debug="yes"/&gt;</pre>
 
-  <h3>Note on package-info.java</h3>
-  <p>
-    <code>package-info.java</code> files were introduced in Java5 to
-    allow package level annotations. On compilation, if the java file
-    does not contain runtime annotations, there will be no .class file
-    for the java file. Up to <b>Ant 1.7.1</b>, when the &lt;javac&gt;
-    task is run again, the
-    task will try to compile the package-info java files again.
-  </p>
-  <p>With Ant 1.7.1 a different kind of logic was introduced that
-    involved the timestamp of the directory that would normally
-    contain the .class file.  This logic turned out to lead to Ant not
-    recompiling <code>package-info.java</code> in certain setup.</p>
-  <p>Starting with Ant 1.8.0 Ant will create
-    "empty" <code>package-info.class</code> files if it compiles
-    a <code>package-info.java</code> and
-    no <code>package-info.class</code> file has been created by the
-    compiler itself.</p>
+<h3>Note on package-info.java</h3>
+<p><samp>package-info.java</samp> files were introduced in Java 5 to allow package level
+annotations. On compilation, if the <code>.java</code> file does not contain runtime annotations,
+there will be no corresponding <code>.class</code> file.  Prior to Ant 1.7.1, when
+the <code>&lt;javac&gt;</code> task is run again, the task will try to compile
+the <samp>package-info.java</samp> files again.</p>
+<p>With Ant 1.7.1, a different kind of logic was introduced that involved the timestamp of the
+directory that would normally contain the <samp>.class</samp> file.  This logic turned out to lead
+to Ant not recompiling <samp>package-info.java</samp> in certain setup.</p>
+<p><em>Since Ant 1.8.0</em>, an "empty" <samp>package-info.class</samp> file is created if Ant
+compiles a <samp>package-info.java</samp> and no <samp>package-info.class</samp> file has been
+created by the compiler itself.</p>
 </body>
 </html>
diff --git a/manual/Tasks/javacc.html b/manual/Tasks/javacc.html
index 3c0dcfa..e40c7e8 100644
--- a/manual/Tasks/javacc.html
+++ b/manual/Tasks/javacc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,197 +15,178 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JavaCC Task</title>
 </head>
 
 <body>
 
-<h2><a name="javacc">JavaCC</a></h2>
+<h2 id="javacc">JavaCC</h2>
 <h3>Description</h3>
-<p>
-  Invokes the <a HREF="http://javacc.dev.java.net/" target="_top">JavaCC</a> compiler
-  compiler on a grammar file.
-</p>
-<p>
-  To use the javacc task, set the <i>target</i> attribute to the name of the
-  grammar file to process.  You also need to specify the directory containing
-  the JavaCC installation using the <i>javacchome</i> attribute, so that Apache Ant
-  can find the JavaCC classes.  Optionally, you can also set the
-  <i>outputdirectory</i> to write the generated file to a specific directory.
-  Otherwise javacc writes the generated files to the directory containing
-  the grammar file.
-</p>
-<p>
-  This task only invokes JavaCC if the grammar file is newer than the generated
-  Java files.  javacc assumes that the Java class name of the generated parser
-  is the same as the name of the grammar file, ignoring the .jj.
-  If this is not the case, the javacc task will still work, but it will always
-  generate the output files.
-</p>
+<p>Invokes the <a href="https://javacc.org/" target="_top">JavaCC</a> compiler compiler on a grammar
+file.</p>
+<p>To use the <code>javacc</code> task, set the <var>target</var> attribute to the name of the
+grammar file to process.  You also need to specify the directory containing the JavaCC installation
+using the <var>javacchome</var> attribute, so that Apache Ant can find the JavaCC classes.
+Optionally, you can also set the <var>outputdirectory</var> to write the generated file to a
+specific directory.  Otherwise JavaCC writes the generated files to the directory containing the
+grammar file.</p>
+<p>This task only invokes JavaCC if the grammar file is newer than the generated <samp>.java</samp>
+files.  JavaCC assumes that the Java class name of the generated parser is the same as the name of
+the grammar file, ignoring the <samp>.jj</samp>.  If this is not the case, the <code>javacc</code>
+task will still work, but it will always generate the output files.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">target</td>
-    <td valign="top">The grammar file to process.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>target</td>
+    <td>The grammar file to process.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">javacchome</td>
-    <td valign="top">The directory containing the JavaCC distribution.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>javacchome</td>
+    <td>The directory containing the JavaCC distribution.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">outputdirectory</td>
-    <td valign="top">
-      The directory to write the generated files to.  If not set, the files
-      are written to the directory containing the grammar file.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>outputdirectory</td>
+    <td>The directory to write the generated files to.  If not set, the files are written to the
+      directory containing the grammar file.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">buildparser</td>
-    <td valign="top">Sets the BUILD_PARSER grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>buildparser</td>
+    <td>Sets the BUILD_PARSER grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">buildtokenmanager</td>
-    <td valign="top">Sets the BUILD_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>buildtokenmanager</td>
+    <td>Sets the BUILD_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">cachetokens</td>
-    <td valign="top">Sets the CACHE_TOKENS grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>cachetokens</td>
+    <td>Sets the CACHE_TOKENS grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">choiceambiguitycheck</td>
-    <td valign="top">Sets the CHOICE_AMBIGUITY_CHECK grammar option.  This is an integer option.</td>
-    <td valign="top" align="center">No</td>
+    <td>choiceambiguitycheck</td>
+    <td>Sets the CHOICE_AMBIGUITY_CHECK grammar option.  This is an integer option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">commontokenaction</td>
-    <td valign="top">Sets the COMMON_TOKEN_ACTION grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>commontokenaction</td>
+    <td>Sets the COMMON_TOKEN_ACTION grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">debuglookahead</td>
-    <td valign="top">Sets the DEBUG_LOOKAHEAD grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>debuglookahead</td>
+    <td>Sets the DEBUG_LOOKAHEAD grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">debugparser</td>
-    <td valign="top">Sets the DEBUG_PARSER grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>debugparser</td>
+    <td>Sets the DEBUG_PARSER grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">debugtokenmanager</td>
-    <td valign="top">Sets the DEBUG_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>debugtokenmanager</td>
+    <td>Sets the DEBUG_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errorreporting</td>
-    <td valign="top">Sets the ERROR_REPORTING grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>errorreporting</td>
+    <td>Sets the ERROR_REPORTING grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">forcelacheck</td>
-    <td valign="top">Sets the FORCE_LA_CHECK grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>forcelacheck</td>
+    <td>Sets the FORCE_LA_CHECK grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">ignorecase</td>
-    <td valign="top">Sets the IGNORE_CASE grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>ignorecase</td>
+    <td>Sets the IGNORE_CASE grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">javaunicodeescape</td>
-    <td valign="top">Sets the JAVA_UNICODE_ESCAPE grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>javaunicodeescape</td>
+    <td>Sets the JAVA_UNICODE_ESCAPE grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">jdkversion</td>
-    <td valign="top">Sets the JDK_VERSION option. This is a string option.</td>
-    <td valign="top" align="center">No</td>
-  </tr>  <tr>
-    <td valign="top">keeplinecolumn</td>
-    <td valign="top">Sets the KEEP_LINE_COLUMN grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>jdkversion</td>
+    <td>Sets the JDK_VERSION option. This is a string option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">lookahead</td>
-    <td valign="top">Sets the LOOKAHEAD grammar option.  This is an integer option.</td>
-    <td valign="top" align="center">No</td>
+    <td>keeplinecolumn</td>
+    <td>Sets the KEEP_LINE_COLUMN grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">optimizetokenmanager</td>
-    <td valign="top">Sets the OPTIMIZE_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>lookahead</td>
+    <td>Sets the LOOKAHEAD grammar option.  This is an integer option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">otherambiguitycheck</td>
-    <td valign="top">Sets the OTHER_AMBIGUITY_CHECK grammar option.  This is an integer option.</td>
-    <td valign="top" align="center">No</td>
+    <td>optimizetokenmanager</td>
+    <td>Sets the OPTIMIZE_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sanitycheck</td>
-    <td valign="top">Sets the SANITY_CHECK grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>otherambiguitycheck</td>
+    <td>Sets the OTHER_AMBIGUITY_CHECK grammar option.  This is an integer option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">static</td>
-    <td valign="top">Sets the STATIC grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>sanitycheck</td>
+    <td>Sets the SANITY_CHECK grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unicodeinput</td>
-    <td valign="top">Sets the UNICODE_INPUT grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>static</td>
+    <td>Sets the STATIC grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">usercharstream</td>
-    <td valign="top">Sets the USER_CHAR_STREAM grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>unicodeinput</td>
+    <td>Sets the UNICODE_INPUT grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">usertokenmanager</td>
-    <td valign="top">Sets the USER_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
-    <td valign="top" align="center">No</td>
+    <td>usercharstream</td>
+    <td>Sets the USER_CHAR_STREAM grammar option.  This is a boolean option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Max amount of memory to allocate to the forked
-      VM.  <em>since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No</td>
+    <td>usertokenmanager</td>
+    <td>Sets the USER_TOKEN_MANAGER grammar option.  This is a boolean option.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>maxmemory</td>
+    <td>Max amount of memory to allocate to the forked JVM.  <em>since Ant 1.8.3</em></td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Example</h3>
-<blockquote><pre>
-&lt;javacc
-    target=&quot;src/Parser.jj&quot;
-    outputdirectory=&quot;build/src&quot;
-    javacchome=&quot;c:/program files/JavaCC&quot;
-    static=&quot;true&quot;
-/&gt;
-</pre></blockquote>
-<p>
-  This invokes JavaCC on grammar file src/Parser.jj, writing the generated
-  files to build/src.  The grammar option STATIC is set to true when
-  invoking JavaCC.
-</p>
 
+<p>Invoke JavaCC on grammar file <samp>src/Parser.jj</samp>, writing the generated files
+to <samp>build/src</samp>. The grammar option STATIC is set to <q>true</q> when invoking JavaCC.</p>
+<pre>
+&lt;javacc target=&quot;src/Parser.jj&quot;
+        outputdirectory=&quot;build/src&quot;
+        javacchome=&quot;c:/program files/JavaCC&quot;
+        static=&quot;true&quot;/&gt;</pre>
 
 </body>
 </html>
-
-
diff --git a/manual/Tasks/javadoc.html b/manual/Tasks/javadoc.html
index fe9d8ef..83987d8 100644
--- a/manual/Tasks/javadoc.html
+++ b/manual/Tasks/javadoc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,681 +15,564 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Javadoc Task</title>
 </head>
 
 <body>
 
-<h2><a name="javadoc">Javadoc/<i>Javadoc2</i></a></h2>
+<h2 id="javadoc">Javadoc/<em>Javadoc2</em></h2>
+<p><em><u>Deprecation</u>: the <code>javadoc2</code> task simply points to the <code>javadoc</code>
+task and it's there for backwards compatibility reasons. Since this task will be removed in future
+versions, you are strongly encouraged to use <a href="javadoc.html">javadoc</a> instead.</em></p>
 <h3>Description</h3>
-<p>Generates code documentation using the javadoc tool.</p>
-<p>The source directory will be recursively scanned for Java source files to process
-but only those matching the inclusion rules, and not matching the exclusions rules
-will be passed to the javadoc tool. This
-allows wildcards to be used to choose between package names, reducing verbosity
-and management costs over time. This task, however, has no notion of
-&quot;changed&quot; files, unlike the <a href="javac.html">javac</a> task. This means
-all packages will be processed each time this task is run. In general, however,
-this task is used much less frequently.</p>
-<p>NOTE: since javadoc calls System.exit(), javadoc cannot be run inside the
-same VM as Apache Ant without breaking functionality. For this reason, this task
-always forks the VM. This overhead is not significant since javadoc is normally a heavy
-application and will be called infrequently.</p>
-<p>NOTE: the packagelist attribute allows you to specify the list of packages to
-document outside of the Ant file. It's a much better practice to include everything
-inside the <code>build.xml</code> file. This option was added in order to make it easier to
-migrate from regular makefiles, where you would use this option of javadoc.
-The packages listed in packagelist are not checked, so the task performs even
-if some packages are missing or broken. Use this option if you wish to convert from
-an existing makefile. Once things are running you should then switch to the regular
-notation. </p>
+<p>Generates code documentation using the <kbd>javadoc</kbd> tool.</p>
+<p>The source directory will be recursively scanned for Java source files to process but only those
+matching the inclusion rules, and not matching the exclusions rules will be passed to
+the <kbd>javadoc</kbd> tool. This allows wildcards to be used to choose between package names,
+reducing verbosity and management costs over time. This task, however, has no notion of
+&quot;changed&quot; files, unlike the <a href="javac.html">javac</a> task. This means all packages
+will be processed each time this task is run. In general, however, this task is used much less
+frequently.</p>
+<p><strong>Note</strong>: since <kbd>javadoc</kbd>
+calls <code class="code">System.exit()</code>, <kbd>javadoc</kbd> cannot be run inside the same
+JVM as Apache Ant without breaking functionality. For this reason, this task always forks JVM. This
+overhead is not significant since <kbd>javadoc</kbd> is normally a heavy application and will be
+called infrequently.</p>
+<p><strong>Note</strong>: the <var>packagelist</var> attribute allows you to specify the list of
+packages to document outside of the Ant file. It's a much better practice to include everything
+inside the <code>build.xml</code> file. This option was added in order to make it easier to migrate
+from regular makefiles, where you would use this option of <kbd>javadoc</kbd>.  The packages
+listed in <var>packagelist</var> are not checked, so the task performs even if some packages are
+missing or broken. Use this option if you wish to convert from an existing makefile. Once things are
+running you should then switch to the regular notation.</p>
 
-<p><i><b>DEPRECATION:</b> the javadoc2 task simply points to the javadoc task and it's
-there for back compatibility reasons. Since this task will be removed in future
-versions, you are strongly encouraged to use <a href="javadoc.html">javadoc</a>
-instead.</i></p>
+<p><strong>Note</strong>: When generating the JavaDocs for classes which contains annotations you
+maybe get a <code class="output">java.lang.ClassCastException:
+com.sun.tools.javadoc.ClassDocImpl</code>.  This is
+due <a href="https://bugs.openjdk.java.net/browse/JDK-6442982" target="_top">bug 6442982</a>. The
+cause is that <kbd>javadoc</kbd> cannot find the implementations of used annotations.  The
+workaround is providing the jars with these implementations (like
+JAXBs <code class="code">@XmlType</code>, ...)  to <code>&lt;javadoc&gt;</code>
+using <var>classpath</var>, <var>classpathref</var> attributes or
+nested <code>&lt;classpath&gt;</code> element.</p>
 
-<p>In the table below, 1.2 means available if your current Java VM is
-a 1.2 VM (but not 1.3 or later), 1.4+ for any VM of at least version 1.4, otherwise
-any VM of at least version 1.2 is acceptable. JDKs &lt;1.4 are no longer supported.
-If you specify the <code>executable</code> attribute it is up to you
-to ensure that this command supports the attributes you wish to use.</p>
+<p><strong>Note</strong>: many problems with running <kbd>javadoc</kbd> stem from command lines
+that have become too long&mdash;even though the error message doesn't give the slightest hint this
+may be the problem.  If you encounter problems with the task, try to set
+the <var>useexternalfile</var> attribute to <q>true</q> first.</p>
 
-<p><b>Note:</b><br>When generating the JavaDocs for classes which contains annotations
-you maybe get a <tt>java.lang.ClassCastException: com.sun.tools.javadoc.ClassDocImpl</tt>.
-This is due <a href="https://bugs.openjdk.java.net/browse/JDK-6442982" target="_blank">bug-6442982</a>. The cause is that JavaDoc cannot find the implementations of used annotations.
-The workaround is providing the jars with these implementations (like JAXBs <tt>@XmlType</tt>, ...)
-to &lt;javadoc&gt; using <tt>classpath</tt>, <tt>classpathref</tt> attributes or nested
-&lt;classpath&gt; element.</p>
-
-<p><b>Note:</b> many problems with running javadoc stem from command
-  lines that have become too long - even though the error message
-  doesn't give the slightest hint this may be the problem.  If you
-  encounter problems with the task, try to set
-  the <code>useexternalfile</code> attribute to <code>true</code>
-  first.</p>
-
-<p>If you use multiple ways to specify where javadoc should be looking
-  for sources your result will be the union of all specified
-  documentations.  If you, e.g., specify a sourcepath attribute and
-  also a nested packageset both pointing at the same directory your
-  excludepackagenames attribute won't have any effect unless it agrees
-  with the exclude patterns of the packageset (and vice versa).</p>
+<p>If you use multiple ways to specify where <kbd>javadoc</kbd> should be looking for sources, your
+result will be the union of all specified documentations.  If you, e.g., specify
+a <var>sourcepath</var> attribute and also a nested <code>packageset</code> both pointing at the
+same directory your <var>excludepackagenames</var> attribute won't have any effect unless it agrees
+with the <var>exclude</var> patterns of the <code>packageset</code> (and vice versa).</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Availability on Java</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">sourcepath</td>
-    <td valign="top">Specify where to find source files</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" rowspan="4">At least one of the four or nested
-      <code>&lt;sourcepath&gt;</code>, <code>&lt;fileset&gt;</code>.
+    <td>sourcepath</td>
+    <td>Specify where to find source files</td>
+    <td rowspan="4">At least one of the four or
+      nested <code>&lt;sourcepath&gt;</code>, <code>&lt;fileset&gt;</code>,
       <code>module</code> or <code>&lt;packageset&gt;</code></td>
   </tr>
   <tr>
-    <td valign="top">sourcepathref</td>
-    <td valign="top">Specify where to find source files by <a
-      href="../using.html#references">reference</a> to a PATH defined elsewhere.</td>
-    <td align="center" valign="top">all</td>
+    <td>sourcepathref</td>
+    <td>Specify where to find source files by <a href="../using.html#references">reference</a> to a
+      <var>sourcepath</var> defined elsewhere.</td>
   </tr>
   <tr>
-    <td valign="top">sourcefiles</td>
-    <td valign="top">Comma separated list of source files -- see also
-    the nested <code>source</code> element.</td>
-    <td align="center" valign="top">all</td>
+    <td>sourcefiles</td>
+    <td>Comma separated list of source files&mdash;see also the nested <code>source</code>
+      element.</td>
   </tr>
   <tr>
-    <td valign="top">modulenames</td>
-    <td valign="top">Comma separated list of module names -- see also
-    the nested <code>module</code> element. <em>since Ant 1.9.14</em></td>
-    <td align="center" valign="top">all</td>
+    <td>modulenames</td>
+    <td>Comma separated list of module names -- see also
+    the nested <code>module</code> element. <em>since Ant 1.10.6</em></td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">Destination directory for output files</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">Yes, unless a doclet has been specified.</td>
+    <td>destdir</td>
+    <td>Destination directory for output files</td>
+    <td>Yes, unless a <var>doclet</var> has been specified.</td>
   </tr>
   <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Max amount of memory to allocate to the javadoc VM</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>maxmemory</td>
+    <td>Max amount of memory to allocate to the <kbd>javadoc</kbd> JVM</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">packagenames</td>
-    <td valign="top">Comma separated list of package files (with terminating
-      wildcard) -- see also the nested <code>package</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>packagenames</td>
+    <td>Comma separated list of package files (with terminating wildcard)&mdash;see also the
+      nested <code>package</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">packageList</td>
-    <td valign="top">The name of a file containing the packages to process</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>packageList</td>
+    <td>The name of a file containing the packages to process</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">Specify where to find user class files</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>Specify where to find user class files</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Bootclasspath</td>
-    <td valign="top">Override location of class files loaded by the bootstrap
-      class loader</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Bootclasspath</td>
+    <td>Override location of class files loaded by the bootstrap class loader</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">Specify where to find user class files by <a
-      href="../using.html#references">reference</a> to a PATH defined elsewhere.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>Specify where to find user class files by <a href="../using.html#references">reference</a>
+      to a <var>classpath</var> defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">bootclasspathref</td>
-    <td valign="top">Override location of class files loaded by the
-      bootstrap class loader by <a href="../using.html#references">reference</a> to a
-      PATH defined elsewhere.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>bootclasspathref</td>
+    <td>Override location of class files loaded by the bootstrap class loader
+      by <a href="../using.html#references">reference</a> to a <var>bootclasspath</var> defined
+      elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Extdirs</td>
-    <td valign="top">Override location of installed extensions</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Extdirs</td>
+    <td>Override location of installed extensions</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Overview</td>
-    <td valign="top">Read overview documentation from HTML file</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Overview</td>
+    <td>Read overview documentation from HTML file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">access</td>
-    <td valign="top">Access mode: one of <code>public</code>, <code>protected</code>,
-                     <code>package</code>, or <code>private</code></td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No (default <code>protected</code>)</td>
+    <td>access</td>
+    <td>Access mode: one of <q>public</q>, <q>protected</q>, <q>package</q>, or <q>private</q></td>
+    <td>No; default is <q>protected</q></td>
   </tr>
   <tr>
-    <td valign="top">Public</td>
-    <td valign="top">Show only public classes and members</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Public</td>
+    <td>Show only public classes and members</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Protected</td>
-    <td valign="top">Show protected/public classes and members (default)</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Protected</td>
+    <td>Show protected/public classes and members (default)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Package</td>
-    <td valign="top">Show package/protected/public classes and members</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Package</td>
+    <td>Show package/protected/public classes and members</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Private</td>
-    <td valign="top">Show all classes and members</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Private</td>
+    <td>Show all classes and members</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Old</td>
-    <td valign="top">Generate output using JDK 1.1 emulating
-      doclet.<br>
-      <b>Note:</b> as of Ant 1.8.0 this attribute doesn't have any
-      effect since the javadoc of Java 1.4 (required by Ant 1.8.0)
-      doesn't support the -1.1 switch anymore.</td>
-    <td align="center" valign="top">1.2</td>
-    <td align="center" valign="top">No</td>
+    <td>Old</td>
+    <td>Generate output using JDK 1.1 emulating doclet.<br/><strong>Note</strong>:
+      This attribute has no effect unless you're using an pre jdk 1.4 external <kbd>javadoc</kbd> 
+   </td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Verbose</td>
-    <td valign="top">Output messages about what Javadoc is doing</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Verbose</td>
+    <td>Output messages about what <kbd>javadoc</kbd> is doing</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Locale</td>
-    <td valign="top">Locale to be used, e.g. en_US or en_US_WIN</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Locale</td>
+    <td>Locale to be used, e.g. <q>en_US</q> or <q>en_US_WIN</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Encoding</td>
-    <td valign="top">Source file encoding name</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Encoding</td>
+    <td>Source file encoding name</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Version</td>
-    <td valign="top">Include @version paragraphs</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Version</td>
+    <td>Include <code>@version</code> paragraphs</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Use</td>
-    <td valign="top">Create class and package usage pages</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Use</td>
+    <td>Create class and package usage pages</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Author</td>
-    <td valign="top">Include @author paragraphs</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Author</td>
+    <td>Include <code>@author</code> paragraphs</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Splitindex</td>
-    <td valign="top">Split index into one file per letter</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Splitindex</td>
+    <td>Split index into one file per letter</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Windowtitle</td>
-    <td valign="top">Browser window title for the documentation (text)</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Windowtitle</td>
+    <td>Browser window title for the documentation (text)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Doctitle</td>
-    <td valign="top">Include title for the package index(first) page (html-code)</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Doctitle</td>
+    <td>Include title for the package index (first) page (HTML code)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Header</td>
-    <td valign="top">Include header text for each page (html-code)</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Header</td>
+    <td>Include header text for each page (HTML code)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">Footer</td>
-    <td valign="top">Include footer text for each page (html-code)</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>Footer</td>
+    <td>Include footer text for each page (HTML code)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">bottom</td>
-    <td valign="top">Include bottom text for each page (html-code)</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>bottom</td>
+    <td>Include bottom text for each page (HTML code)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">link</td>
-    <td valign="top">Create links to javadoc output at the given URL
-    -- see also the nested <code>link</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>link</td>
+    <td>Create links to <code>javadoc</code> output at the given URL&mdash;see also the
+      nested <code>link</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">linkoffline</td>
-    <td valign="top">Link to docs at <code>&lt;url&gt;</code> using package list at
-    <code>&lt;url2&gt;</code> - separate the URLs by using a space character -- see
-    also the nested <code>link</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>linkoffline</td>
+    <td>Link to docs at <samp><em>url</em></samp> using package list
+      at <samp><em>alt-url</em></samp> by specifying a
+      value <q><em>url</em>&nbsp;<em>alt-url</em></q> (space as separator). A shorthand for the
+      nested <code>link</code> element with <var>offline</var>=<q>true</q>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">group</td>
-    <td valign="top">Group specified packages together in overview
-    page.  The format is as described <a
-    href="#groupattribute">below</a> -- see also the nested
-    <code>group</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>group</td>
+    <td>Group specified packages together in overview page.  The format is as
+      described <a href="#groupattribute">below</a>&mdash;see also the nested <code>group</code>
+      element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">nodeprecated</td>
-    <td valign="top">Do not include @deprecated information</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>nodeprecated</td>
+    <td>Do not include <code>@deprecated</code> information</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">nodeprecatedlist</td>
-    <td valign="top">Do not generate deprecated list</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>nodeprecatedlist</td>
+    <td>Do not generate deprecated list</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">notree</td>
-    <td valign="top">Do not generate class hierarchy</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>notree</td>
+    <td>Do not generate class hierarchy</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">noindex</td>
-    <td valign="top">Do not generate index</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>noindex</td>
+    <td>Do not generate index</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">nohelp</td>
-    <td valign="top">Do not generate help link</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>nohelp</td>
+    <td>Do not generate help link</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">nonavbar</td>
-    <td valign="top">Do not generate navigation bar</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>nonavbar</td>
+    <td>Do not generate navigation bar</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">serialwarn</td>
-    <td valign="top">Generate warning about @serial tag</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>serialwarn</td>
+    <td>Generate warning about <code>@serial</code> tag</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">helpfile</td>
-    <td valign="top">Specifies the HTML help file to use</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>helpfile</td>
+    <td>Specifies the HTML help file to use</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">stylesheetfile</td>
-    <td valign="top">Specifies the CSS stylesheet to use</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>stylesheetfile</td>
+    <td>Specifies the CSS stylesheet to use</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">charset</td>
-    <td valign="top">Charset for cross-platform viewing of generated
-      documentation</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>charset</td>
+    <td>Charset for cross-platform viewing of generated documentation</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">docencoding</td>
-    <td valign="top">Output file encoding name</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>docencoding</td>
+    <td>Output file encoding name</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">doclet</td>
-    <td valign="top">Specifies the class file that starts the doclet
-    used in generating the documentation -- see also the nested
-    <code>doclet</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>doclet</td>
+    <td>Specifies the class file that starts the doclet used in generating the
+      documentation&mdash;see also the nested <code>doclet</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">docletpath</td>
-    <td valign="top">Specifies the path to the doclet class file that is specified with the -doclet option.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>docletpath</td>
+    <td>Specifies the path to the doclet class file that is specified with the <kbd>-doclet</kbd>
+      option.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">docletpathref</td>
-    <td valign="top">Specifies the path to the doclet class file that
-      is specified with the -doclet option by <a
-      href="../using.html#references">reference</a> to a PATH defined elsewhere.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>docletpathref</td>
+    <td>Specifies the path to the doclet class file that is specified with the <kbd>-doclet</kbd>
+      option by <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">additionalparam</td>
-    <td valign="top">Lets you add additional parameters to the javadoc
-    command line. Useful for doclets. Parameters containing spaces
-    need to be quoted using &amp;quot; -- see also the nested
-    <code>arg</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>additionalparam</td>
+    <td>Lets you add additional parameters to the <kbd>javadoc</kbd> command line. Useful for
+      doclets. Parameters containing spaces need to be quoted using &amp;quot;&mdash;see also the
+      nested <code>arg</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the buildprocess if the command exits with a
-      returncode other than 0.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code other than <q>0</q>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonwarning</td>
-    <td valign="top">Stop the buildprocess if a warning is emitted -
-    i.e. if javadoc's output contains the word "warning".  <em>since
-    Ant 1.9.4</em></td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>failonwarning</td>
+    <td>Stop the build process if a warning is emitted&mdash;i.e. if <kbd>javadoc</kbd>'s output
+      contains the word <q>warning</q>.  <em>since Ant 1.9.4</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludepackagenames</td>
-    <td valign="top">comma separated list of packages you don't want
-      docs for -- see also the nested <code>excludepackage</code> element.</td>
-    <td align="center" valign="top">all</td>
-    <td valign="top" align="center">No</td>
+    <td>excludepackagenames</td>
+    <td>comma separated list of packages you don't want docs for&mdash;see also the
+      nested <code>excludepackage</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used
-      (<code>yes</code> | <code>no</code>); default excludes are used when omitted.</td>
-    <td align="center" valign="top">all</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">useexternalfile</td>
-    <td valign="top">indicates whether the sourcefile name specified
-      in srcfiles or as nested source elements should be written to a
-      temporary file to make the command line shorter. Also applies to
-      the package names specified via the packagenames attribute or
-      nested package elements.  <em>Since Ant 1.7.0</em>, also applies
-      to all the other command line options.
-      (<code>yes</code> | <code>no</code>). Default is no.<br/>
+    <td>useexternalfile</td>
+    <td>indicates whether the source file names specified in <var>srcfiles</var> or as
+      nested <code>source</code> elements should be written to a temporary file to make the command
+      line shorter. Also applies to the package names specified via the <var>packagenames</var>
+      attribute or nested <code>package</code> elements.  <em>Since Ant 1.7.0</em>, also applies to
+      all the other command line options.  (<q>yes|no</q>).<br/>
       If enabled, the file will be written to
       the <a href="../running.html#tmpdir">temporary
-      directory</a>.</p>
-    </td>
-    <td align="center" valign="top">all</td>
-    <td valign="top" align="center">No</td>
+      directory</a>.</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">source</td>
-    <td valign="top">Necessary to enable javadoc to handle assertions
-    present in J2SE v 1.4 source code. Set this to &quot;1.4&quot; to
-    documents code that compiles using <code>&quot;javac -source
-    1.4&quot;</code>.<br>
-    A default value for this attribute can be provided using the magic
-    <a
-    href="../javacprops.html#source"><code>ant.build.javac.source</code></a>
-    property.</td>
-    <td align="center" valign="top">1.4+</td>
-    <td align="center" valign="top">No</td>
+    <td>source</td>
+    <td>Enable <kbd>javadoc</kbd> to handle Java language features.  Set this to <q>1.4</q> to
+      document code that compiles using <kbd>javac -source 1.4</kbd>, etc.</td>
+    <td>No; default can be provided using the magic
+    <a href="../javacprops.html#source"><code>ant.build.javac.source</code></a> property.</td>
   </tr>
   <tr>
-    <td valign="top">linksource</td>
-    <td valign="top">Generate hyperlinks to source files.
-      <em>since Ant 1.6</em>.
-      (<code>yes</code> | <code>no</code>). Default is no.</td>
-    <td align="center" valign="top">1.4+</td>
-    <td align="center" valign="top">No</td>
+    <td>linksource</td>
+    <td>Generate hyperlinks to source files.  <em>since Ant 1.6</em>.  (<q>yes|no</q>).</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">breakiterator</td>
-    <td valign="top">Use the new breakiterator algorithm.
-      <em>since Ant 1.6</em>.
-      (<code>yes</code> | <code>no</code>). Default is no.</td>
-    <td align="center" valign="top">1.4+</td>
-    <td align="center" valign="top">No</td>
+    <td>breakiterator</td>
+    <td>Use the new break iterator algorithm.  <em>since Ant 1.6</em>.  (<q>yes|no</q>).</td>
+    <td>No; default is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">noqualifier</td>
-    <td valign="top">Enables the <code>-noqualifier</code> argument -
-      must be <code>all</code> or a colon separated list of packages.
-      <em>since Ant 1.6</em>.</td>
-    <td align="center" valign="top">1.4+</td>
-    <td align="center" valign="top">No</td>
+    <td>noqualifier</td>
+    <td>Enables the <kbd>-noqualifier</kbd> argument&mdash;must be <q>all</q> or a colon separated
+      list of packages.  <em>since Ant 1.6</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includenosourcepackages</td>
-    <td valign="top">If set to true, packages that don't contain Java
-      source but a package.html will get documented as well.
-      <em>since Ant 1.6.3</em>.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No (default is <code>false</code>)</td>
+    <td>includenosourcepackages</td>
+    <td>If set to <q>true</q>, packages that don't contain Java source but
+      a <samp>package.html</samp> will get documented as well.  <em>since Ant 1.6.3</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">Specify a particular <code>javadoc</code> executable
-      to use in place of the default binary (found in the same JDK as Ant is running in).
-      <em>since Ant 1.6.3</em>.</td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>executable</td>
+    <td>Specify a particular <kbd>javadoc</kbd> executable to use in place of the default binary
+      (found in the same JDK as Ant is running in).  <em>since Ant 1.6.3</em>. <b>Note:</b>
+      <em>It is up to you to ensure that this command supports the attributes you wish to use.</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">docfilessubdirs</td>
-    <td valign="top">Enables deep-copying of <code>doc-files</code>
-      subdirectories.  Defaults to false. <em>since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">1.4</td>
-    <td align="center" valign="top">No</td>
+    <td>docfilessubdirs</td>
+    <td>Enables deep-copying of <samp>doc-files</samp> subdirectories. <em>since Ant
+      1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">excludedocfilessubdir</td>
-    <td valign="top">Colon-separated list of <code>doc-files</code>'
-      subdirectories to exclude if <code>docfilessubdirs</code> is
-      true. <em>since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">1.4</td>
-    <td align="center" valign="top">No</td>
+    <td>excludedocfilessubdir</td>
+    <td>Colon-separated list of <samp>doc-files</samp> subdirectories to exclude
+      if <var>docfilessubdirs</var> is true. <em>since Ant 1.8.0</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">postProcessGeneratedJavadocs</td>
-    <td valign="top">Whether to post-process the generated javadocs in
-      order to mitigate CVE-2013-1571.  Defaults to true.  <em>Since Ant
-      1.9.2</em><br>
-      There is a frame injection attack possible in javadocs generated by Oracle
-      JDKs prior to Java7 Update 25 (<a href="http://www.oracle.com/technetwork/java/javase/7u25-relnotes-1955741.html#jpi-upt" target="_blank">details</a>).  
-      When this flag is set to true, Ant will check whether the docs are vulnerable 
-      and will try to fix them.
-    </td>
-    <td align="center" valign="top">1.4</td>
-    <td align="center" valign="top">No</td>
+    <td>postProcessGeneratedJavadocs</td>
+    <td>Whether to post-process the generated javadocs in order to mitigate
+      CVE-2013-1571.  <em>Since Ant 1.9.2</em><br/> There is a frame injection attack possible in
+      javadocs generated by Oracle JDKs prior to Java 7 update 25
+      (<a href="https://www.oracle.com/technetwork/java/javase/7u25-relnotes-1955741.html#jpi-upt"
+      target="_top">details</a>).  When this flag is set to <q>true</q>, Ant will check whether the
+      docs are vulnerable and will try to fix them.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">modulesourcepath</td>
-    <td valign="top">Specify where to find module source files
-      <em>since Ant 1.9.14</em></td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>modulesourcepath</td>
+    <td>Specify where to find module source files
+      <em>since Ant 1.10.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">modulesourcepathref</td>
-    <td valign="top">Specify where to find module source files by <a
+    <td>modulesourcepathref</td>
+    <td>Specify where to find module source files by <a
       href="../using.html#references">reference</a> to a PATH defined elsewhere.
-      <em>since Ant 1.9.14</em></td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+      <em>since Ant 1.10.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">modulepath</td>
-    <td valign="top">Specify where to find module files
-      <em>since Ant 1.9.14</em></td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+    <td>modulepath</td>
+    <td>Specify where to find module files
+      <em>since Ant 1.10.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">modulepathref</td>
-    <td valign="top">Specify where to find module files by <a
+    <td>modulepathref</td>
+    <td>Specify where to find module files by <a
       href="../using.html#references">reference</a> to a PATH defined elsewhere.
-      <em>since Ant 1.9.14</em></td>
-    <td align="center" valign="top">all</td>
-    <td align="center" valign="top">No</td>
+      <em>since Ant 1.10.6</em></td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="groupattribute">Format of the group attribute</a></h4>
-<p>The arguments are comma-delimited. Each single argument is 2
-space-delimited strings, where the first one is the group's title and
-the second one a colon delimited list of packages.</p>
-<p>If you need to specify more than one group, or a group whose title
-contains a comma or a space character, using <a
-href="#groupelement">nested group elements</a> is highly
+<h4 id="groupattribute">Format of the group attribute</h4>
+<p>The arguments are comma-delimited. Each single argument is 2 space-delimited strings, where the
+first one is the group's title and the second one a colon delimited list of packages.</p>
+<p>If you need to specify more than one group, or a group whose title contains a comma or a space
+character, using <a href="#groupelement">nested <code>group</code> elements</a> is highly
 recommended.</p>
 <p>E.g.:</p>
-<pre>    group=&quot;XSLT_Packages org.apache.xalan.xslt*,XPath_Packages org.apache.xalan.xpath*&quot;</pre>
+<pre>group=&quot;XSLT_Packages org.apache.xalan.xslt*,XPath_Packages org.apache.xalan.xpath*&quot;</pre>
 
 <h3>Parameters specified as nested elements</h3>
 
 <h4>packageset</h4>
 
-<p>A <a href="../Types/dirset.html">DirSet</a>.  All matched
-directories that contain Java source files will be passed to javadoc
-as package names.  Package names are created from the directory names
-by translating the directory separator into dots.  Ant assumes the
-base directory of the packageset points to the root of a package
-hierarchy.</p>
+<p>A <a href="../Types/dirset.html">DirSet</a>.  All matched directories that contain Java source
+files will be passed to <kbd>javadoc</kbd> as package names.  Package names are created from the
+directory names by translating the directory separator into dots.  Ant assumes the base directory of
+the <code>packageset</code> points to the root of a package hierarchy.</p>
 
-<p>The <code>packagenames</code>, <code>excludepackagenames</code> and
-<code>defaultexcludes</code> attributes of the task have no effect on
-the nested <code>&lt;packageset&gt;</code> elements.</p>
+<p>The <var>packagenames</var>, <var>excludepackagenames</var> and <var>defaultexcludes</var>
+attributes of the task have no effect on the nested <code>&lt;packageset&gt;</code> elements.</p>
 
 <h4>fileset</h4>
 
-<p>A <a href="../Types/fileset.html">FileSet</a>.  All matched
-files will be passed to javadoc as source files.  Ant will
-automatically add the include pattern <code>**/*.java</code> (and
-<code>**/package.html</code> if includenosourcepackages is true) to
-these filesets.</p>
+<p>A <a href="../Types/fileset.html">FileSet</a>.  All matched files will be passed
+to <kbd>javadoc</kbd> as source files.  Ant will automatically add the include
+pattern <samp>**/*.java</samp> (and <samp>**/package.html</samp>
+if <var>includenosourcepackages</var> is <q>true</q>) to these filesets.</p>
 
-<p>Nested filesets can be used to document sources that are in the
-default package or if you want to exclude certain files from
-documentation.  If you want to document all source files and don't use
-the default package, packagesets should be used instead as this
-increases javadocs performance.</p>
+<p>Nested filesets can be used to document sources that are in the default package or if you want to
+exclude certain files from documentation.  If you want to document all source files and don't use
+the default package, <code>packageset</code>s should be used instead as this increases performance
+of <kbd>javadoc</kbd>.</p>
 
-<p>The <code>packagenames</code>, <code>excludepackagenames</code> and
-<code>defaultexcludes</code> attributes of the task have no effect on
-the nested <code>&lt;fileset&gt;</code> elements.</p>
+<p>The <var>packagenames</var>, <var>excludepackagenames</var> and <var>defaultexcludes</var>
+attributes of the task have no effect on the nested <code>&lt;fileset&gt;</code> elements.</p>
 
 <h4>sourcefiles</h4>
 
-<p>A container for arbitrary file system based <a
-href="../Types/resources.html#collection">resource
-collections</a>.  All files contained in any of the nested collections
-(this includes nested filesets, filelists or paths) will be passed to
-javadoc as source files.</p>
+<p>A container for arbitrary file system based <a href="../Types/resources.html#collection">resource
+collections</a>.  All files contained in any of the nested collections (this includes nested
+filesets, filelists or paths) will be passed to javadoc as source files.</p>
 
 <h4>package</h4>
-<p>Same as one entry in the list given by <code>packagenames</code>.</p>
+<p>Same as one entry in the list given by <var>packagenames</var>.</p>
 
 <h5>Parameters</h5>
-<table width="90%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The package name (may be a wildcard)</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The package name (may be a wildcard)</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>excludepackage</h4>
-<p>Same as one entry in the list given by <code>excludepackagenames</code>.</p>
+<p>Same as one entry in the list given by <var>excludepackagenames</var>.</p>
 
 <h5>Parameters</h5>
 Same as for <code>package</code>.
 
 <h4>module</h4>
-<p><em>since Ant 1.9.14</em></p>
+<p><em>since Ant 1.10.6</em></p>
 <p>Same as one entry in the list given by <code>modulenames</code>.</p>
 
 <h5>Parameters</h5>
-<table width="90%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The module name</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The module name</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>source</h4>
-<p>Same as one entry in the list given by <code>sourcefiles</code>.</p>
+<p>Same as one entry in the list given by <var>sourcefiles</var>.</p>
 
 <h5>Parameters</h5>
-<table width="90%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The source file to document</td>
-    <td align="center" valign="top">Yes</td>
+    <td>file</td>
+    <td>The source file to document</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>doctitle</h4>
 
-<p>Same as the <code>doctitle</code> attribute, but you can nest text
-inside the element this way.</p>
+<p>Same as the <var>doctitle</var> attribute, but you can nest text inside the element this way.</p>
 
-<p>If the nested text contains line breaks, you must use the
-  useexternalfile attribute and set it to true.</p>
+<p>If the nested text contains line breaks, you must use the <var>useexternalfile</var> attribute
+and set it to <q>true</q>.</p>
 
 <h4>header</h4>
 
@@ -703,188 +587,185 @@
 <p>Similar to <code>&lt;doctitle&gt;</code>.</p>
 
 <h4>link</h4>
-<p>Create link to javadoc output at the given URL. This performs the
-same role as the link and linkoffline attributes. You can use either
-syntax (or both at once), but with the nested elements you can easily
-specify multiple occurrences of the arguments.</p>
-
-<h5>Parameters</h5>
-<table width="90%" 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">href</td>
-    <td valign="top">The URL for the external documentation you wish
-    to link to.  This can be an absolute URL, or a relative file
-    name.</td>
-    <td align="center" valign="top">Yes</td>
-  </tr>
-  <tr>
-    <td valign="top">offline</td>
-    <td valign="top">True if this link is not available online at the time of
-                     generating the documentation</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">packagelistLoc</td>
-    <td valign="top">The location to the directory containing the package-list file for
-                     the external documentation</td>
-    <td align="center" valign="top" rowspan="2">One of the two if the offline attribute is true</td>
-  </tr>
-  <tr>
-    <td valign="top">packagelistURL</td>
-    <td valign="top">The URL of the the directory containing the package-list file for
-                     the external documentation</td>
-  </tr>
-  <tr>
-    <td valign="top">resolveLink</td>
-    <td valign="top">If the link attribute is a relative file name,
-    Ant will first try to locate the file relative to the current
-    project's basedir and if it finds a file there use an absolute URL
-    for the link attribute, otherwise it will pass the file name
-    verbatim to the javadoc command.</td>
-    <td align="center" valign="top">No, default is false.</td>
-  </tr>
-</table>
-
-<h4><a name="groupelement">group</a></h4>
-<p>Separates packages on the overview page into whatever groups you
-specify, one group per table. This performs the same role as the group
-attribute. You can use either syntax (or both at once), but with the
-nested elements you can easily specify multiple occurrences of the
+<p>Create link to <kbd>javadoc</kbd> output at the given URL. This performs the same role as
+the <var>link</var> and <var>linkoffline</var> attributes. You can use either syntax (or both at
+once), but with the nested elements you can easily specify multiple occurrences of the
 arguments.</p>
 
 <h5>Parameters</h5>
-<table width="90%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">title</td>
-    <td valign="top">Title of the group</td>
-    <td align="center" valign="top">Yes, unless nested <code>&lt;title&gt;</code> given</td>
+    <td>href</td>
+    <td>The URL for the external documentation you wish to link to.  This can be an absolute URL, or
+      a relative file name.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">packages</td>
-    <td valign="top">List of packages to include in that group. Multiple packages are separated with ':'.</td>
-    <td align="center" valign="top">Yes, unless nested <code>&lt;package&gt;</code>s given</td>
+    <td>offline</td>
+    <td><q>true</q> if this link is not available online at the time of generating the
+      documentation</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>packagelistLoc</td>
+    <td>The location to the directory containing the package-list file for the external
+      documentation</td>
+    <td rowspan="2">One of the two if the <var>offline</var> attribute is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>packagelistURL</td>
+    <td class="left">The URL of the the directory containing the package-list file for the external
+      documentation</td>
+  </tr>
+  <tr>
+    <td>resolveLink</td>
+    <td>If the <var>link</var> attribute is a relative file name, Ant will first try to locate the
+      file relative to the current project's <var>basedir</var> and if it finds a file there use an
+      absolute URL for the <var>link</var> attribute, otherwise it will pass the file name verbatim
+      to the <kbd>javadoc</kbd> command.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
-<p>The title may be specified as a nested <code>&lt;title&gt;</code> element
-with text contents, and the packages may be listed with nested
-<code>&lt;package&gt;</code> elements as for the main task.</p>
+<h4 id="groupelement">group</h4>
+<p>Separates packages on the overview page into whatever groups you specify, one group per
+table. This performs the same role as the <var>group</var> attribute. You can use either syntax (or
+both at once), but with the nested elements you can easily specify multiple occurrences of the
+arguments.</p>
+
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>title</td>
+    <td>Title of the group</td>
+    <td>Yes, unless nested <code>&lt;title&gt;</code> given</td>
+  </tr>
+  <tr>
+    <td>packages</td>
+    <td>List of packages to include in that group. Multiple packages are separated with <q>:</q>.</td>
+    <td>Yes, unless nested <code>&lt;package&gt;</code>s given</td>
+  </tr>
+</table>
+
+<p>The title may be specified as a nested <code>&lt;title&gt;</code> element with text contents, and
+the packages may be listed with nested <code>&lt;package&gt;</code> elements as for the main
+task.</p>
 
 <h4>doclet</h4>
-<p>The doclet nested element is used to specify the
-<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/doclet/overview.html">doclet</a>
-that javadoc will use to process the input source files. A number of the standard javadoc arguments
-are actually arguments of the standard doclet. If these are specified in the javadoc
-task's attributes, they will be passed to the doclet specified in the
-<code>&lt;doclet&gt;</code> nested element. Such attributes should only be specified,
-therefore, if they can be interpreted by the doclet in use.</p>
+<p>The doclet nested element is used to specify
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/doclet/overview.html"
+target="_top">doclet</a> that <kbd>javadoc</kbd> will use to process the input source files. A
+number of the standard <kbd>javadoc</kbd> arguments are actually arguments of the standard
+doclet. If these are specified in the <code>javadoc</code> task's attributes, they will be passed to
+the doclet specified in the <code>&lt;doclet&gt;</code> nested element. Such attributes should only
+be specified, therefore, if they can be interpreted by the doclet in use.</p>
 
-<p>If the doclet requires additional parameters, these can be specified with
-<code>&lt;param&gt;</code> elements within the <code>&lt;doclet&gt;</code>
-element. These parameters are restricted to simple strings. An example usage
-of the doclet element is shown below:</p>
+<p>If the doclet requires additional parameters, these can be specified
+with <code>&lt;param&gt;</code> elements within the <code>&lt;doclet&gt;</code> element. These
+parameters are restricted to simple strings. An example usage of the <code>doclet</code> element is
+shown below:</p>
 
-<pre>  &lt;javadoc ... &gt;
-     &lt;doclet name=&quot;theDoclet&quot;
-             path=&quot;path/to/theDoclet&quot;&gt;
-        &lt;param name=&quot;-foo&quot; value=&quot;foovalue&quot;/&gt;
-        &lt;param name=&quot;-bar&quot; value=&quot;barvalue&quot;/&gt;
-     &lt;/doclet&gt;
-  &lt;/javadoc&gt;
-</pre>
+<pre>
+&lt;javadoc ... &gt;
+   &lt;doclet name=&quot;theDoclet&quot;
+           path=&quot;path/to/theDoclet&quot;&gt;
+      &lt;param name=&quot;-foo&quot; value=&quot;foovalue&quot;/&gt;
+      &lt;param name=&quot;-bar&quot; value=&quot;barvalue&quot;/&gt;
+   &lt;/doclet&gt;
+&lt;/javadoc&gt;</pre>
 
-<h4><a name="tagelement">tag</a></h4>
+<h4 id="tagelement">tag</h4>
 
-<p>If you want to specify a standard tag using a nested tag element
-because you want to determine the order the tags are output, you must
-not set the description attribute for those tags.</p>
+<p>If you want to specify a standard tag using a nested <code>tag</code> element because you want to
+determine the order the tags are output, you must not set the <var>description</var> attribute for
+those tags.</p>
 
 <h5>Parameters</h5>
-<table width="90%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Name of the tag (e.g. <code>todo</code>)</td>
-    <td align="center" valign="top">Yes, unless the <code>dir</code> attribute is specified.</td>
+    <td>name</td>
+    <td>Name of the tag (e.g. <q>todo</q>)</td>
+    <td>Yes, unless the <var>dir</var> attribute is specified</td>
   </tr>
   <tr>
-    <td valign="top">description</td>
-    <td valign="top">Description for tag (e.g. <code>To do:</code>)</td>
-    <td align="center" valign="top">
-      No, the javadoc executable will pick a default if this is not specified.
+    <td>description</td>
+    <td>Description for tag (e.g. <q>To do:</q>)</td>
+    <td>
+      No, the <kbd>javadoc</kbd> executable will pick a default if this is not specified
     </td>
   </tr>
   <tr>
-    <td valign="top">enabled</td>
-    <td valign="top">Whether or not the tag is enabled (defaults to <code>true</code>)</td>
-    <td align="center" valign="top">No</td>
+    <td>enabled</td>
+    <td>Whether or not the tag is enabled</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">scope</td>
-    <td valign="top">Scope for the tag - the elements in which it can be used. This
-    is a comma separated list of some of the elements: <code>overview</code>,
-    <code>packages</code>, <code>types</code>, <code>constructors</code>,
-    <code>methods</code>, <code>fields</code> or the default, <code>all</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>scope</td>
+    <td>Scope for the tag&mdash;the elements in which it can be used. This is a comma separated list
+      of some of the
+      elements: <q>overview</q>, <q>packages</q>, <q>types</q>, <q>constructors</q>, <q>methods</q>, <q>fields</q>
+      or the default, <q>all</q>.</td>
+    <td>No; defaults to <q>all</q></td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">If this attribute is specified, this element will behave as an implicit
-    <a href="../Types/fileset.html">fileset</a>. The files included by this fileset should
-    contain each tag definition on a separate line, as described in the
-    <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#javadoctags">Javadoc reference guide</a>:
-    <pre>ejb.bean:t:XDoclet EJB Tag
+    <td>dir</td>
+    <td>If this attribute is specified, this element will behave as an
+      implicit <a href="../Types/fileset.html">fileset</a>. The files included by this fileset
+      should contain each tag definition on a separate line, as described in
+      the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#javadoctags"
+      target="_top">Javadoc reference guide</a>:
+      <pre>ejb.bean:t:XDoclet EJB Tag
 todo:a:To Do</pre>
-      <b>Note:</b> The  Javadoc reference quide has double quotes around
-the description part of the definition. This will not work when used in
-a file, as the definition is quoted again when given to
-the javadoc program.
-    <br/>
-      <b>Note:</b> If this attribute is specified, all the other attributes in this
-    element will be ignored.
-    </td>
-    <td align="center" valign="top">No</td>
+      <strong>Note</strong>: The Javadoc reference quide has double quotes around the description
+      part of the definition. This will not work when used in a file, as the definition is quoted
+      again when given to the <kbd>javadoc</kbd> program.<br/>
+      <strong>Note</strong>: If this attribute is specified, all the other attributes in this
+      element will be ignored.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="tagletelement">taglet</a></h4>
-<p>The taglet nested element is used to specify custom
-  <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/taglet/overview.html">taglets</a> beyond <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#javadoctags" target="_blank">the default taglets</a>.</p>
+<h4 id="tagletelement">taglet</h4>
+<p>The taglet nested element is used to specify
+custom <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/taglet/overview.html"
+target="_top">taglets</a>
+beyond <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#javadoctags"
+target="_top">the default taglets</a>.</p>
 
 <h5>Parameters</h5>
-<table width="90%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the taglet class
-              (e.g. <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/taglet/ToDoTaglet.java">
-              <code>com.sun.tools.doclets.ToDoTaglet</code></a>)</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the taglet class
+      (e.g. <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/taglet/ToDoTaglet.java"
+      target="_top"><code>com.sun.tools.doclets.ToDoTaglet</code></a>)</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
-    <td valign="top">A path specifying the search path for the taglet class
-            (e.g. <code>/home/taglets</code>).
-            The path may also be specified by a nested <code>&lt;path&gt;</code> element</td>
-    <td align="center" valign="top">No</td>
+    <td>path</td>
+    <td>A path specifying the search path for the taglet class (e.g. <samp>/home/taglets</samp>).
+      The path may also be specified by a nested <code>&lt;path&gt;</code> element</td>
+    <td>No</td>
   </tr>
 </table>
 
@@ -897,78 +778,75 @@
 and <i>modulesourcepath</i> elements respectively.</p>
 
 <h4>arg</h4>
-
-<p>Use nested <code>&lt;arg&gt;</code> to specify additional
-arguments.  See <a href="../using.html#arg">Command line
-arguments</a>. <em>Since Ant 1.6</em></p>
+<p><em>Since Ant 1.6</em></p>
+<p>Use nested <code>&lt;arg&gt;</code> to specify additional arguments.
+See <a href="../using.html#arg">Command line arguments</a>.</p>
 
 <h3>Example</h3>
-<pre>  &lt;javadoc packagenames=&quot;com.dummy.test.*&quot;
-           sourcepath=&quot;src&quot;
-           excludepackagenames=&quot;com.dummy.test.doc-files.*&quot;
-           defaultexcludes=&quot;yes&quot;
-           destdir=&quot;docs/api&quot;
-           author=&quot;true&quot;
-           version=&quot;true&quot;
-           use=&quot;true&quot;
-           windowtitle=&quot;Test API&quot;&gt;
-    &lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;Test&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;
-    &lt;bottom&gt;&lt;![CDATA[&lt;i&gt;Copyright &amp;#169; 2000 Dummy Corp. All Rights Reserved.&lt;/i&gt;]]&gt;&lt;/bottom&gt;
-    &lt;tag name=&quot;todo&quot; scope=&quot;all&quot; description=&quot;To do:&quot;/&gt;
-    &lt;group title=&quot;Group 1 Packages&quot; packages=&quot;com.dummy.test.a*&quot;/&gt;
-    &lt;group title=&quot;Group 2 Packages&quot; packages=&quot;com.dummy.test.b*:com.dummy.test.c*&quot;/&gt;
-    &lt;link offline=&quot;true&quot; href=&quot;http://docs.oracle.com/javase/7/docs/api/&quot; packagelistLoc=&quot;C:\tmp&quot;/&gt;
-    &lt;link href=&quot;http://docs.oracle.com/javase/7/docs/api/&quot;/&gt;
-  &lt/javadoc&gt;</pre>
+<pre>
+&lt;javadoc packagenames=&quot;com.dummy.test.*&quot;
+         sourcepath=&quot;src&quot;
+         excludepackagenames=&quot;com.dummy.test.doc-files.*&quot;
+         defaultexcludes=&quot;yes&quot;
+         destdir=&quot;docs/api&quot;
+         author=&quot;true&quot;
+         version=&quot;true&quot;
+         use=&quot;true&quot;
+         windowtitle=&quot;Test API&quot;&gt;
+  &lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;Test&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;
+  &lt;bottom&gt;&lt;![CDATA[&lt;i&gt;Copyright &amp;#169; 2000 Dummy Corp. All Rights Reserved.&lt;/i&gt;]]&gt;&lt;/bottom&gt;
+  &lt;tag name=&quot;todo&quot; scope=&quot;all&quot; description=&quot;To do:&quot;/&gt;
+  &lt;group title=&quot;Group 1 Packages&quot; packages=&quot;com.dummy.test.a*&quot;/&gt;
+  &lt;group title=&quot;Group 2 Packages&quot; packages=&quot;com.dummy.test.b*:com.dummy.test.c*&quot;/&gt;
+  &lt;link offline=&quot;true&quot; href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot; packagelistLoc=&quot;C:\tmp&quot;/&gt;
+  &lt;link href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot;/&gt;
+&lt;/javadoc&gt;</pre>
 
 <p>is the same as</p>
 
-<pre>  &lt;javadoc
-           destdir=&quot;docs/api&quot;
-           author=&quot;true&quot;
-           version=&quot;true&quot;
-           use=&quot;true&quot;
-           windowtitle=&quot;Test API&quot;&gt;
+<pre>
+&lt;javadoc destdir=&quot;docs/api&quot;
+         author=&quot;true&quot;
+         version=&quot;true&quot;
+         use=&quot;true&quot;
+         windowtitle=&quot;Test API&quot;&gt;
 
-    &lt;packageset dir=&quot;src&quot; defaultexcludes=&quot;yes&quot;&gt;
-      &lt;include name=&quot;com/dummy/test/**&quot;/&gt;
-      &lt;exclude name=&quot;com/dummy/test/doc-files/**&quot;/&gt;
-    &lt;/packageset&gt;
+  &lt;packageset dir=&quot;src&quot; defaultexcludes=&quot;yes&quot;&gt;
+    &lt;include name=&quot;com/dummy/test/**&quot;/&gt;
+    &lt;exclude name=&quot;com/dummy/test/doc-files/**&quot;/&gt;
+  &lt;/packageset&gt;
 
-    &lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;Test&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;
-    &lt;bottom&gt;&lt;![CDATA[&lt;i&gt;Copyright &amp;#169; 2000 Dummy Corp. All Rights Reserved.&lt;/i&gt;]]&gt;&lt;/bottom&gt;
-    &lt;tag name=&quot;todo&quot; scope=&quot;all&quot; description=&quot;To do:&quot;/&gt;
-    &lt;group title=&quot;Group 1 Packages&quot; packages=&quot;com.dummy.test.a*&quot;/&gt;
-    &lt;group title=&quot;Group 2 Packages&quot; packages=&quot;com.dummy.test.b*:com.dummy.test.c*&quot;/&gt;
-    &lt;link offline=&quot;true&quot; href=&quot;http://docs.oracle.com/javase/7/docs/api/&quot; packagelistLoc=&quot;C:\tmp&quot;/&gt;
-    &lt;link href=&quot;http://docs.oracle.com/javase/7/docs/api/&quot;/&gt;
-  &lt/javadoc&gt;</pre>
+  &lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;Test&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;
+  &lt;bottom&gt;&lt;![CDATA[&lt;i&gt;Copyright &amp;#169; 2000 Dummy Corp. All Rights Reserved.&lt;/i&gt;]]&gt;&lt;/bottom&gt;
+  &lt;tag name=&quot;todo&quot; scope=&quot;all&quot; description=&quot;To do:&quot;/&gt;
+  &lt;group title=&quot;Group 1 Packages&quot; packages=&quot;com.dummy.test.a*&quot;/&gt;
+  &lt;group title=&quot;Group 2 Packages&quot; packages=&quot;com.dummy.test.b*:com.dummy.test.c*&quot;/&gt;
+  &lt;link offline=&quot;true&quot; href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot; packagelistLoc=&quot;C:\tmp&quot;/&gt;
+  &lt;link href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot;/&gt;
+&lt;/javadoc&gt;</pre>
 
 <p>or</p>
 
-<pre>  &lt;javadoc
-           destdir=&quot;docs/api&quot;
-           author=&quot;true&quot;
-           version=&quot;true&quot;
-           use=&quot;true&quot;
-           windowtitle=&quot;Test API&quot;&gt;
+<pre>
+&lt;javadoc destdir=&quot;docs/api&quot;
+         author=&quot;true&quot;
+         version=&quot;true&quot;
+         use=&quot;true&quot;
+         windowtitle=&quot;Test API&quot;&gt;
 
-    &lt;fileset dir=&quot;src&quot; defaultexcludes=&quot;yes&quot;&gt;
-      &lt;include name=&quot;com/dummy/test/**&quot;/&gt;
-      &lt;exclude name=&quot;com/dummy/test/doc-files/**&quot;/&gt;
-    &lt;/fileset&gt;
+  &lt;fileset dir=&quot;src&quot; defaultexcludes=&quot;yes&quot;&gt;
+    &lt;include name=&quot;com/dummy/test/**&quot;/&gt;
+    &lt;exclude name=&quot;com/dummy/test/doc-files/**&quot;/&gt;
+  &lt;/fileset&gt;
 
-    &lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;Test&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;
-    &lt;bottom&gt;&lt;![CDATA[&lt;i&gt;Copyright &amp;#169; 2000 Dummy Corp. All Rights Reserved.&lt;/i&gt;]]&gt;&lt;/bottom&gt;
-    &lt;tag name=&quot;todo&quot; scope=&quot;all&quot; description=&quot;To do:&quot;/&gt;
-    &lt;group title=&quot;Group 1 Packages&quot; packages=&quot;com.dummy.test.a*&quot;/&gt;
-    &lt;group title=&quot;Group 2 Packages&quot; packages=&quot;com.dummy.test.b*:com.dummy.test.c*&quot;/&gt;
-    &lt;link offline=&quot;true&quot; href=&quot;http://docs.oracle.com/javase/7/docs/api/&quot; packagelistLoc=&quot;C:\tmp&quot;/&gt;
-    &lt;link href=&quot;http://docs.oracle.com/javase/7/docs/api/&quot;/&gt;
-  &lt/javadoc&gt;</pre>
-
-
+  &lt;doctitle&gt;&lt;![CDATA[&lt;h1&gt;Test&lt;/h1&gt;]]&gt;&lt;/doctitle&gt;
+  &lt;bottom&gt;&lt;![CDATA[&lt;i&gt;Copyright &amp;#169; 2000 Dummy Corp. All Rights Reserved.&lt;/i&gt;]]&gt;&lt;/bottom&gt;
+  &lt;tag name=&quot;todo&quot; scope=&quot;all&quot; description=&quot;To do:&quot;/&gt;
+  &lt;group title=&quot;Group 1 Packages&quot; packages=&quot;com.dummy.test.a*&quot;/&gt;
+  &lt;group title=&quot;Group 2 Packages&quot; packages=&quot;com.dummy.test.b*:com.dummy.test.c*&quot;/&gt;
+  &lt;link offline=&quot;true&quot; href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot; packagelistLoc=&quot;C:\tmp&quot;/&gt;
+  &lt;link href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot;/&gt;
+&lt;/javadoc&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/javah.html b/manual/Tasks/javah.html
index d1daa7c..ce652aa 100644
--- a/manual/Tasks/javah.html
+++ b/manual/Tasks/javah.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,243 +15,229 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Javah Task</title>
 </head>
 
 <body>
 
-<h2><a name="javah">Javah</a></h2>
+<h2 id="javah">Javah</h2>
 <h3>Description</h3>
 <p>Generates JNI headers from a Java class.</p>
-<p> When this task executes, it will generate the C header and source files that
-are needed to implement native methods. JNI operates differently depending on
-whether <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javah.html">JDK1.2+</a>
-or <a href="http://java.sun.com/products/jdk/1.1/docs/tooldocs/win32/javah.html">pre-JDK1.2</a>
-systems are used.</p>
+<p>When this task executes, it will generate the C header and source files that are needed to
+implement native methods.
 
 <p>If you are building with Java 8 or above consider
-  using <a href="javac.html"><code>javac</code></a>'s <code>nativeheaderdir</code>
-  attribute instead which allows you to compile the classes and
-  generate the native header files with a single step.</p>
+using <a href="javac.html"><code>javac</code></a>'s <var>nativeheaderdir</var> attribute instead
+which allows you to compile the classes and generate the native header files in a single step.</p>
 
-<p><b>Note</b> the <code>javah</code> has been deprecated as of Java 9
-  and removed as of Java 10. Trying to use it with Java10 will
-  fail.</p>
+<p><strong>Note</strong>: <code>javah</code> has been deprecated in Java 9 and removed in Java
+10. Attempts to use it with Java 10 will fail.</p>
 
-<p>It is possible to use different compilers. This can be selected
-with the <code>implementation</code> attribute or a nested element.  <a
-name="implementationvalues">Here are the choices of the attribute</a>:</p>
+<p id="implementationvalues">It is possible to use different compilers. This can be selected with
+the <var>implementation</var> attribute or a nested element. Here are the choices of the
+attribute:</p>
 <ul>
-  <li>default - the default compiler for the platform.</li>
-  <li>sun (the standard compiler of the JDK) - default when not
-    running on Kaffee or gcj/gij or Java9.</li>
-  <li>kaffeh (the native standard compiler of <a href="http://www.kaffe.org" target="_top">Kaffe</a>)</li>
-  <li>gcjh (the native standard compiler
-  of <a href="http://gcc.gnu.org/java/"
-        target="_top">gcj and gij</a>) <em>since Apache Ant 1.8.2</em></li>
-  <li>forking - runs the javah executable via its command line
-    interface in a separate process. Default when running on
-    Java9. <em>since Ant 1.9.8</em></li>
+  <li><q>default</q>&mdash;the default compiler for the platform.</li>
+  <li><q>sun</q>&mdash;the standard compiler of the JDK.</li>
+  <li><q>kaffeh</q>&mdash;the native standard compiler of <a href="https://github.com/kaffe/kaffe"
+    target="_top">Kaffe</a>.</li>
+  <li><q>gcjh</q>&mdash;the native standard compiler
+    of <a href="https://gcc.gnu.org/gcc-7/changes.html#java" target="_top">gcj and
+    gij</a>. <em>Since Apache Ant 1.8.2</em></li>
+  <li><q>forking</q>&mdash;runs the <kbd>javah</kbd> executable via its command line interface in
+    a separate process. Default when not running on Kaffe or gcj/gij <em>since Ant 1.9.8</em></li>
 </ul>
 
-<p><b>Note:</b> if you are using this task to work on multiple files
-  the command line may become too long on some operating systems.
-  Unfortunately the javah command doesn't support command argument
-  files the way javac (for example) does, so all that can be done is
-  breaking the amount of classes to compile into smaller chunks.</p>
+<p><strong>Note</strong>: if you are using this task to work on multiple files the command line may
+become too long on some operating systems.  Unfortunately the <kbd>javah</kbd> command doesn't
+support command argument files the way <kbd>javac</kbd> (for example) does, so all that can be
+done is breaking the amount of classes to compile into smaller chunks.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top" align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">class</td>
-    <td valign="top">the fully-qualified name of the class (or classes,
-      separated by commas)</td>
-    <td align="center" valign="top">Yes</td>
+    <td>class</td>
+    <td>the fully-qualified name of the class (or classes, separated by commas)</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">outputFile</td>
-    <td valign="top">concatenates the resulting header or source files for all the classes listed into this file</td>
-    <td align="center" valign="middle" rowspan="2">Yes</td>
+    <td>outputFile</td>
+    <td>concatenates the resulting header or source files for all the classes listed into this
+      file</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">sets the directory where javah saves the header files or the
-      stub files.</td>
+    <td>destdir</td>
+    <td class="left">sets the directory where <kbd>javah</kbd> saves the header files or the stub
+      files.</td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">specifies that output files should always be written (JDK1.2 only)</td>
-    <td valign="top" align="center">No</td>
+    <td>force</td>
+    <td>specifies that output files should always be written 
+    (only when using an external javah of JDK 1.2)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">old</td>
-    <td valign="top">specifies that old JDK1.0-style header files should be generated
-      (otherwise output file contain JNI-style native method      function prototypes) (JDK1.2 only)</td>
-    <td valign="top" align="center">No</td>
+    <td>old</td>
+    <td>specifies that old JDK 1.0-style header files should be generated (otherwise output file
+      contain JNI-style native method function prototypes) 
+      (only when using an external javah of JDK 1.2)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">stubs</td>
-    <td valign="top">generate C declarations from the Java object file (used with old)</td>
-    <td valign="top" align="center">No</td>
+    <td>stubs</td>
+    <td>generate C declarations from the Java object file (used with <var>old</var>)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">causes Javah to print a message concerning the status     of the generated files</td>
-    <td valign="top" align="center">No</td>
+    <td>verbose</td>
+    <td>causes <kbd>javah</kbd> to print a message concerning the status of the generated files</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>the classpath to use</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">bootclasspath</td>
-    <td valign="top">location of bootstrap class files.</td>
-    <td valign="top" align="center">No</td>
+    <td>bootclasspath</td>
+    <td>location of bootstrap class files</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">extdirs</td>
-    <td valign="top"> location of installed extensions.</td>
-    <td valign="top" align="center">No</td>
+    <td>extdirs</td>
+    <td>location of installed extensions</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">implementation</td>
-    <td valign="top">The compiler implementation to use.  If this
-    attribute is not set, the default compiler for the current VM
-    will be used.  (See the above <a
-    href="#implementationvalues">list</a> of valid compilers.)</td>
-    <td align="center" valign="top">No</td>
+    <td>implementation</td>
+    <td>The compiler implementation to use. (See the above <a href="#implementationvalues">list</a>
+      of valid compilers.)</td>
+    <td>No; defaults to default compiler for the current JDK</td>
   </tr>
 </table>
-<p>Either outputFile or destdir must be supplied, but not both.&nbsp;</p>
 
 <h3>Parameters specified as nested elements</h3>
 
 <h4>arg</h4>
 
-<p>You can specify additional command line arguments for the compiler
-with nested <code>&lt;arg&gt;</code> elements.  These elements are
-specified like <a href="../using.html#arg">Command-line Arguments</a>
-but have an additional attribute that can be used to enable arguments
-only if a given compiler implementation will be used.</p>
+<p>You can specify additional command line arguments for the compiler with
+nested <code>&lt;arg&gt;</code> elements.  These elements are specified
+like <a href="../using.html#arg">Command-line Arguments</a> but have an additional attribute that
+can be used to enable arguments only if a given compiler implementation will be used.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">value</td>
-    <td align="center" rowspan="4">See
-    <a href="../using.html#arg">Command-line Arguments</a>.</td>
-    <td align="center" rowspan="4">Exactly one of these.</td>
+    <td>value</td>
+    <td rowspan="4">See <a href="../using.html#arg">Command-line Arguments</a>.</td>
+    <td rowspan="4">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">line</td>
+    <td class="var">line</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
+    <td class="var">file</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
+    <td class="var">path</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td align="center" rowspan="2">See
-    <a href="../using.html#arg">Command-line Arguments</a>.
-    <em>Since Ant 1.8.</em></td>
-    <td valign="top" align="center">No</td>
+    <td>prefix</td>
+    <td rowspan="2">See <a href="../using.html#arg">Command-line Arguments</a>.  <em>Since Ant
+      1.8</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top" align="center">No</td>
+    <td>suffix</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">implementation</td>
-    <td>Only pass the specified argument if the chosen compiler
-    implementation matches the value of this attribute.  Legal values
-    are the same as those in the above <a
-    href="#implementationvalues">list</a> of valid compilers.)</td>
-    <td align="center">No</td>
+    <td>implementation</td>
+    <td>Only pass the specified argument if the chosen compiler implementation matches the value of
+      this attribute.  Legal values are the same as those in the
+      above <a href="#implementationvalues">list</a> of valid compilers.)</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4>implementationclasspath <em>since Ant 1.8.0</em></h4>
+<h4>implementationclasspath</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>A <a href="../using.html#path">path-like structure</a> holding the classpath to use when loading
+the compiler implementation if a custom class has been specified.  Doesn't have any effect when
+using one of the built-in compilers.</p>
 
-<p>A <a href="../using.html#path">PATH like structure</a> holding the
-  classpath to use when loading the compiler implementation if a
-  custom class has been specified.  Doesn't have any effect when
-  using one of the built-in compilers.</p>
-
-<h4>Any nested element of a type that implements JavahAdapter
-  <em>since Ant 1.8.0</em></h4>
-
-<p>If a defined type implements the <code>JavahAdapter</code>
-  interface a nested element of that type can be used as an
-  alternative to the <code>implementation</code> attribute.</p>
+<h4>Any nested element of a type that implements JavahAdapter</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>If a defined type implements the <code class="code">JavahAdapter</code> interface a nested
+element of that type can be used as an alternative to the <var>implementation</var> attribute.</p>
 
 <h3>Examples</h3>
-<pre>  &lt;javah destdir=&quot;c&quot; class=&quot;org.foo.bar.Wibble&quot;/&gt;</pre>
-<p>makes a JNI header of the named class, using the JDK1.2 JNI model. Assuming
-the directory 'c' already exists, the file <tt>org_foo_bar_Wibble.h</tt>
-is created there. If this file already exists, it is left unchanged.</p>
-<pre>  &lt;javah outputFile=&quot;wibble.h&quot;&gt;
-    &lt;class name=&quot;org.foo.bar.Wibble,org.foo.bar.Bobble&quot;/&gt;
-  &lt;/javah&gt;</pre>
-<p>is similar to the previous example, except the output is written to a file
-called <tt>wibble.h</tt>
-in the current directory.</p>
-<pre>  &lt;javah destdir=&quot;c&quot; force=&quot;yes&quot;&gt;
-    &lt;class name=&quot;org.foo.bar.Wibble&quot;/&gt;
-    &lt;class name=&quot;org.foo.bar.Bobble&quot;/&gt;
-    &lt;class name=&quot;org.foo.bar.Tribble&quot;/&gt;
-  &lt;/javah&gt;</pre>
-<p>writes three header files, one for each of the classes named. Because the
-force option is set, these header files are always written when the Javah task
-is invoked, even if they already exist.</p>
-<pre>  &lt;javah destdir=&quot;c&quot; verbose=&quot;yes&quot; old=&quot;yes&quot; force=&quot;yes&quot;&gt;
-    &lt;class name=&quot;org.foo.bar.Wibble&quot;/&gt;
-    &lt;class name=&quot;org.foo.bar.Bobble&quot;/&gt;
-    &lt;class name=&quot;org.foo.bar.Tribble&quot;/&gt;
-  &lt;/javah&gt;
-  &lt;javah destdir=&quot;c&quot; verbose=&quot;yes&quot; stubs=&quot;yes&quot; old=&quot;yes&quot; force=&quot;yes&quot;&gt;
-    &lt;class name=&quot;org.foo.bar.Wibble&quot;/&gt;
-    &lt;class name=&quot;org.foo.bar.Bobble&quot;/&gt;
-    &lt;class name=&quot;org.foo.bar.Tribble&quot;/&gt;
-  &lt;/javah&gt;</pre>
-<p>writes the headers for the three classes using the 'old' JNI format, then
-writes the corresponding .c stubs. The verbose option will cause Javah to
-describe its progress.</p>
+<p>Make a JNI header of the named class, using the JDK 1.2 JNI model. Assuming the
+directory <samp>c</samp> already exists, the file <samp>org_foo_bar_Wibble.h</samp> is created
+there. If this file already exists, it is left unchanged.</p>
+<pre>&lt;javah destdir=&quot;c&quot; class=&quot;org.foo.bar.Wibble&quot;/&gt;</pre>
 
-<p>If you want to use a custom
-  JavahAdapter <code>org.example.MyAdapter</code> you can either
-  use the implementation attribute:</p>
+<p>This is similar to the previous example, except the output is written to a file
+called <samp>wibble.h</samp> in the current directory.</p>
+<pre>
+&lt;javah outputFile=&quot;wibble.h&quot;&gt;
+  &lt;class name=&quot;org.foo.bar.Wibble,org.foo.bar.Bobble&quot;/&gt;
+&lt;/javah&gt;</pre>
+
+<p>Write three header files, one for each of the classes named. Because the <var>force</var> option
+is set, these header files are always written when the <code>Javah</code> task is invoked, even if
+they already exist.</p>
+<pre>
+&lt;javah destdir=&quot;c&quot; force=&quot;yes&quot;&gt;
+  &lt;class name=&quot;org.foo.bar.Wibble&quot;/&gt;
+  &lt;class name=&quot;org.foo.bar.Bobble&quot;/&gt;
+  &lt;class name=&quot;org.foo.bar.Tribble&quot;/&gt;
+&lt;/javah&gt;</pre>
+
+<p>Write the headers for the three classes using the 'old' JNI format, then write the
+corresponding <samp>.c</samp> stubs. The <var>verbose</var> option will cause <code>Javah</code> to
+describe its progress.</p>
+<pre>
+&lt;javah destdir=&quot;c&quot; verbose=&quot;yes&quot; old=&quot;yes&quot; force=&quot;yes&quot;&gt;
+  &lt;class name=&quot;org.foo.bar.Wibble&quot;/&gt;
+  &lt;class name=&quot;org.foo.bar.Bobble&quot;/&gt;
+  &lt;class name=&quot;org.foo.bar.Tribble&quot;/&gt;
+&lt;/javah&gt;
+&lt;javah destdir=&quot;c&quot; verbose=&quot;yes&quot; stubs=&quot;yes&quot; old=&quot;yes&quot; force=&quot;yes&quot;&gt;
+  &lt;class name=&quot;org.foo.bar.Wibble&quot;/&gt;
+  &lt;class name=&quot;org.foo.bar.Bobble&quot;/&gt;
+  &lt;class name=&quot;org.foo.bar.Tribble&quot;/&gt;
+&lt;/javah&gt;</pre>
+
+<p>If you want to use a
+custom <code class="code">JavahAdapter</code> <code>org.example.MyAdapter</code> you can either use
+the <var>implementation</var> attribute:</p>
 <pre>
 &lt;javah destdir="c" class="org.foo.bar.Wibble"
-       implementation="org.example.MyAdapter"/&gt;
-</pre>
+       implementation="org.example.MyAdapter"/&gt;</pre>
 <p>or a define a type and nest this into the task like in:</p>
 <pre>
 &lt;componentdef classname="org.example.MyAdapter"
               name="myadapter"/&gt;
 &lt;javah destdir="c" class="org.foo.bar.Wibble"&gt;
   &lt;myadapter/&gt;
-&lt;/javah&gt;
-</pre>
-<p>in which case your javah adapter can support attributes and
-  nested elements of its own.</p>
+&lt;/javah&gt;</pre>
+<p>in which case your <code>javah</code> adapter can support attributes and nested elements of its
+own.</p>
 
 </body>
-
 </html>
diff --git a/manual/Tasks/jdepend.html b/manual/Tasks/jdepend.html
index 7a9639d..7aa7f4e 100644
--- a/manual/Tasks/jdepend.html
+++ b/manual/Tasks/jdepend.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,164 +15,143 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-
-<html>
+<html lang="en">
 <head>
    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>JDepend Task</title>
-   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <meta http-equiv="Content-Language" content="en-us">
+   <title>JDepend Task</title>
 </head>
 
 <body>
 
-<h2><a NAME="JDepend"></a>JDepend</h2>
+<h2 id="jdepend">JDepend</h2>
 
 <h3>Description</h3>
 
-<P>Invokes the <a href="http://www.clarkware.com/software/JDepend.html">JDepend</a> parser.</P>
+<p>Invokes the <a href="https://github.com/clarkware/jdepend" target="_top">JDepend</a>
+parser.</p>
 
-<P>This parser &quot;traverses a set of Java source file directories and generates design quality metrics for each Java package&quot;.
-It allows to &quot;automatically measure the quality of a design in terms of its extensibility, reusability, and maintainability to
-effectively manage and control package dependencies.&quot;</P>
+<p>This parser &quot;traverses a set of Java source file directories and generates design quality
+metrics for each Java package&quot;.  It allows to &quot;automatically measure the quality of a
+design in terms of its extensibility, reusability, and maintainability to effectively manage and
+control package dependencies.&quot;</p>
 
-<p>Source file directories are defined by nested
-<code>&lt;sourcespath&gt;</code>; Class file directories are defined
-by nested <code>&lt;classesespath&gt;</code>, see <a
-href="#nested">nested elements</a>.</p>
+<p>Source file directories are defined by nested <code>&lt;sourcespath&gt;</code>. Class file
+directories are defined by nested <code>&lt;classespath&gt;</code>. See <a href="#nested">nested
+elements</a>.</p>
 
-<p>Optionally, you can also set the <code>outputfile</code> name where the output is stored. By default the task writes its report to the standard output.</P>
+<p>Optionally, you can also set the <var>outputfile</var> name where the output is stored. By
+default the task writes its report to the standard output.</p>
 
-<p> The task requires at least the JDepend 1.2 version. </p>
+<p>The task requires at least the JDepend 1.2 version.</p>
 
 <h3>Parameters</h3>
 
-<table BORDER=1 CELLSPACING=0 CELLPADDING=2 >
+<table class="attr">
   <tr>
-    <td VALIGN=TOP><b>Attribute</b></td>
-    <td VALIGN=TOP><b>Description</b></td>
-    <td ALIGN=CENTER VALIGN=TOP><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td VALIGN=TOP>outputfile</td>
-    <td VALIGN=TOP>The output file name. If not set, the output is printed on the standard output.</td>
-    <td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>outputfile</td>
+    <td>The output file name. If not set, the output is printed on the standard output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td VALIGN=TOP>format</td>
-    <td VALIGN=TOP>The format to write the output in. The default is "text", the alternative is "xml"</td>
-    <td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>format</td>
+    <td>The format to write the output in,
+    either <q>text</q> (default) or <q>xml</q></td>
+    <td>No; the default is <q>text</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>fork</td>
-    <td VALIGN=TOP>Run the tests in a separate VM.</td>
-    <td ALIGN=CENTER VALIGN=TOP>No, default is "off"</td>
+    <td>fork</td>
+    <td>Run the tests in a separate JVM.</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>haltonerror</td>
-    <td VALIGN=TOP>Stop the build process if an error occurs during the jdepend analysis.</td>
-    <td ALIGN=CENTER VALIGN=TOP>No, default is "off"</td>
+    <td>haltonerror</td>
+      <td>Stop the build process if an error occurs during the <code>jdepend</code> analysis.</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>timeout</td>
-    <td VALIGN=TOP>Cancel the operation if it doesn't finish in the given time (measured in milliseconds). (Ignored if fork is disabled.)</td>
-    <td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>timeout</td>
+    <td>Cancel the operation if it doesn't finish in the given time (measured in milliseconds).</td>
+    <td>No, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>jvm</td>
-    <td VALIGN=TOP>The command used to invoke the Java Virtual Machine, default is 'java'. The command is resolved by java.lang.Runtime.exec(). (Ignored if fork is disabled.)</td>
-    <td ALIGN=CENTER VALIGN=TOP>No, default "java"</td>
+    <td>jvm</td>
+    <td>The command used to invoke JVM. The command is resolved
+      by <code>java.lang.Runtime.exec()</code>.</td>
+    <td>No; default <kbd>java</kbd>, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>dir</td>
-    <td VALIGN=TOP>The directory to invoke the VM in. (Ignored if fork is disabled)</td>
-    <td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>dir</td>
+    <td>The directory to invoke JVM in.</td>
+    <td>No, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>includeruntime</td>
-    <td VALIGN=TOP>Implicitly add the classes required to run jdepend
-    in forked mode. (Ignored if fork is disabled). Since Apache Ant 1.6.</td>
-    <td ALIGN=CENTER VALIGN=TOP>No, default is "no".</td>
+    <td>includeruntime</td>
+    <td>Implicitly add the classes required to run <code>jdepend</code> in forked mode. <em>Since
+      Apache Ant 1.6</em>.</td>
+    <td>No; default is <q>no</q>, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td VALIGN=TOP>classpathref</td>
-    <td VALIGN=TOP>the classpath to use, given as reference to a PATH defined elsewhere.</td>
-    <td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>classpathref</td>
+    <td>the <var>classpath</var> to use, given as reference to a path defined elsewhere.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3><a name="nested">Nested Elements</a></h3>
+<h3 id="nested">Parameters specified as nested elements</h3>
 
-<p><code>jdepend</code> supports four nested elements:
-<code>&lt;classpath&gt;, &lt;classespath&gt; </code> and
-<code>&lt;sourcespath&gt;</code>, that represent <a
-href="../using.html#path">PATH like structures</a>, and
-<code>&lt;exclude&gt;</code>.</p>
+<p><code>jdepend</code> supports four nested
+elements: <code>&lt;classpath&gt;</code>, <code>&lt;classespath&gt;</code>
+and <code>&lt;sourcespath&gt;</code>, that represent <a href="../using.html#path">path-like
+structures</a>, and <code>&lt;exclude&gt;</code>.</p>
 
-<p><code>&lt;sourcespath&gt;</code> is used to define the paths of the
-source code to analyze, but it is deprecated. With version 2.5 of
-JDepend, only class files are analyzed. The nested element
-<code>&lt;classespath&gt;</code> replaces <code>&lt;sourcespath&gt;</code> and is used to define
-the paths of compiled class code to analyze; the <code>&lt;sourcespath&gt;</code>
-variable is still available in case you are using an earlier version
-of JDepend.  The <code>&lt;exclude&gt;</code> element can be used to set packages
-to ignore (requires JDepend 2.5 or above).</p>
+<p><code>&lt;sourcespath&gt;</code> is used to define the paths of the source code to analyze, but
+it is deprecated. With version 2.5 of JDepend, only class files are analyzed. The nested
+element <code>&lt;classespath&gt;</code> replaces <code>&lt;sourcespath&gt;</code> and is used to
+define the paths of compiled class code to analyze; the <code>&lt;sourcespath&gt;</code> variable is
+still available in case you are using an earlier version of JDepend.
+The <code>&lt;exclude&gt;</code> element can be used to set packages to ignore (requires JDepend 2.5
+or above).</p>
 
 <h3>Examples</h3>
 
-<blockquote>
+<p>Invoke JDepend on the <samp>build</samp> directory, writing the output on the standard
+output. The classpath is defined using a reference.</p>
 <pre>
 &lt;jdepend classpathref="base.path"&gt;
-&nbsp;&nbsp;&nbsp; &lt;classespath&gt;
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="build"/&gt;
-&nbsp;&nbsp;&nbsp; &lt;/classespath&gt;
-&lt;/jdepend&gt;
+    &lt;classespath&gt;
+        &lt;pathelement location="build"/&gt;
+    &lt;/classespath&gt;
+&lt;/jdepend&gt;</pre>
 
-</pre>
-</blockquote>
-
-<p>This invokes JDepend on the <code>build</code> directory, writing
-the output on the standard output. The classpath is defined using a
-classpath reference.</p>
-
-<blockquote>
+<p>This invoke JDepend in a separate JVM on the <samp>src</samp> and <samp>testsrc</samp>
+directories, writing the output to the <samp>docs/jdepend.xml</samp> file in XML format. The
+classpath is defined using nested elements.</p>
 <pre>
 &lt;jdepend outputfile="docs/jdepend.xml" fork="yes" format="xml"&gt;
-&nbsp;&nbsp;&nbsp; &lt;sourcespath&gt;
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="src"/&gt;
-&nbsp;&nbsp;&nbsp; &lt;/sourcespath&gt;
-&nbsp;&nbsp;&nbsp; &lt;classpath&gt;
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="classes"/&gt;
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="lib/jdepend.jar"/&gt;
-&nbsp;&nbsp;&nbsp; &lt;/classpath&gt;
-&lt;/jdepend&gt;
-</pre>
-</blockquote>
+    &lt;sourcespath&gt;
+        &lt;pathelement location="src"/&gt;
+    &lt;/sourcespath&gt;
+    &lt;classpath&gt;
+        &lt;pathelement location="classes"/&gt;
+        &lt;pathelement location="lib/jdepend.jar"/&gt;
+    &lt;/classpath&gt;
+&lt;/jdepend&gt;</pre>
 
-<p>This invokes JDepend in a separate VM on the <code>src</code> and
-<code>testsrc</code> directories, writing the output to the
-<code>&lt;docs/jdepend.xml&gt;</code> file in xml format. The
-classpath is defined using nested elements. </p>
-
-<blockquote>
+<p>Invoke JDepend with the build directory as the base for class files to analyze, and ignore all
+classes in the <samp>java.*</samp> and <samp>javax.*</samp> packages.</p>
 <pre>
 &lt;jdepend classpathref="base.path"&gt;
-&nbsp;&nbsp;&nbsp; &lt;exclude name="java.*&gt;
-&nbsp;&nbsp;&nbsp; &lt;exclude name="javax.*&gt;
-&nbsp;&nbsp;&nbsp; &lt;classespath&gt;
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="build"/&gt;
-&nbsp;&nbsp;&nbsp; &lt;/classespath&gt;
-&lt;/jdepend&gt;
-</pre>
-</blockquote>
-
-<p>This invokes JDepend with the build directory as the base for class
-files to analyze, and will ignore all classes in the java.* and
-javax.* packages.</p>
-
+    &lt;exclude name="java.*&gt;
+    &lt;exclude name="javax.*&gt;
+    &lt;classespath&gt;
+        &lt;pathelement location="build"/&gt;
+    &lt;/classespath&gt;
+&lt;/jdepend&gt;</pre>
 
 </body>
 </html>
-
-
diff --git a/manual/Tasks/jjdoc.html b/manual/Tasks/jjdoc.html
index 52b9225..2aeb114 100644
--- a/manual/Tasks/jjdoc.html
+++ b/manual/Tasks/jjdoc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,110 +15,85 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
+<html lang="en">
 <head>
-   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <meta http-equiv="Content-Language" content="en-us">
-   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JJDoc Task</title>
 </head>
 <body>
 
-<h2>
-<a NAME="jjtree"></a>JJDoc</h2>
+<h2 id="jjtree">JJDoc</h2>
 <p><em>Since Apache Ant 1.6</em></p>
 <h3>Description</h3>
 
-<p>Invokes the <a href="http://javacc.dev.java.net/">JJDoc</a> preprocessor
-for the JavaCC compiler compiler. It takes a JavaCC parser specification
-and produces documentation for the BNF grammar.
-It can operate in three modes, determined by command line options.
-<p>To use the jjdoc task, set the <i>target</i> attribute to the name
-of the JavaCC grammar file to process. You also need to specify the directory
-containing the JavaCC installation using the <i>javacchome</i> attribute,
-so that ant can find the JavaCC classes. Optionally, you can also set the
-<i>outputfile</i> to write the generated BNF documentation file to a specific (directory and) file.
-Otherwise jjdoc writes the generated BNF documentation file as the JavaCC
-grammar file with a suffix .txt or .html.</p>
-<p>This task only invokes JJDoc if the grammar file is newer than the
-generated BNF documentation file.</p>
+<p>Invokes the <a href="https://javacc.org/" target="_top">JJDoc</a> preprocessor for the JavaCC
+compiler compiler. It takes a JavaCC parser specification and produces documentation for the BNF
+grammar.  It can operate in three modes, determined by command line options.
+<p>To use the <code>jjdoc</code> task, set the <var>target</var> attribute to the name of the JavaCC
+grammar file to process. You also need to specify the directory containing the JavaCC installation
+using the <var>javacchome</var> attribute, so that Ant can find the JavaCC classes. Optionally, you
+can also set the <var>outputfile</var> to write the generated BNF documentation file to a specific
+(directory and) file.  Otherwise <code>jjdoc</code> writes the generated BNF documentation file as
+the JavaCC grammar file with a suffix <samp>.txt</samp> or <samp>.html</samp>.</p>
+<p>This task only invokes <code>JJDoc</code> if the grammar file is newer than the generated BNF
+documentation file.</p>
 
 <h3>Parameters</h3>
 
-<table BORDER CELLSPACING=0 CELLPADDING=2 >
+<table class="attr">
 <tr>
-<td VALIGN=TOP><b>Attribute</b></td>
-
-<td VALIGN=TOP><b>Description</b></td>
-
-<td ALIGN=CENTER VALIGN=TOP><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
 </tr>
 
 <tr>
-<td VALIGN=TOP>target</td>
-
-<td VALIGN=TOP>The javacc grammar file to process.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>Yes</td>
+    <td>target</td>
+    <td>The JavaCC grammar file to process.</td>
+    <td>Yes</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>javacchome</td>
-
-<td VALIGN=TOP>The directory containing the JavaCC distribution.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>Yes</td>
+    <td>javacchome</td>
+    <td>The directory containing the JavaCC distribution.</td>
+    <td>Yes</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>outputfile</td>
-
-<td VALIGN=TOP>The file to write the generated BNF documentation file to. If not set,
-the file is written with the same name as the JavaCC grammar file but with a the suffix .html or .txt.&nbsp;</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>outputfile</td>
+    <td>The file to write the generated BNF documentation file to. If not set, the file is written
+      with the same name as the JavaCC grammar file but with a the suffix <samp>.html</samp>
+      or <samp>.txt</samp></td>
+    <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>text</td>
-
-<td VALIGN=TOP>Sets the TEXT BNF documentation option. This is a boolean
-option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>text</td>
+    <td>Sets the TEXT BNF documentation option. This is a boolean option.</td>
+    <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>onetable</td>
-
-<td VALIGN=TOP>Sets the ONE_TABLE BNF documentation option. This is a boolean option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+    <td>onetable</td>
+    <td>Sets the ONE_TABLE BNF documentation option. This is a boolean option.</td>
+    <td>No</td>
 </tr>
-
-  <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Max amount of memory to allocate to the forked
-      VM.  <em>since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No</td>
+<tr>
+    <td>maxmemory</td>
+    <td>Max amount of memory to allocate to the forked JVM.  <em>since Ant 1.8.3</em></td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3>
-Example</h3>
+<h3>Example</h3>
 
-<blockquote>
-<pre>&lt;jjdoc&nbsp;
-&nbsp;&nbsp;&nbsp; target="src/Parser.jj"&nbsp;
-&nbsp;&nbsp;&nbsp; outputfile="doc/ParserBNF.html"
-&nbsp;&nbsp;&nbsp; javacchome="c:/program files/JavaCC"&nbsp;
-/&gt;</pre>
-</blockquote>
-This invokes JJDoc on grammar file src/Parser.jj, writing the generated
-BNF documentation file, ParserBNF.html, file to doc.
-<br>
+<p>Invoke JJDoc on grammar file <samp>src/Parser.jj</samp>, writing the generated BNF documentation
+file, <samp>ParserBNF.html</samp>, to <samp>doc</samp>.</p>
+
+<pre>
+&lt;jjdoc target="src/Parser.jj"
+       outputfile="doc/ParserBNF.html"
+       javacchome="c:/program files/JavaCC"/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/jjtree.html b/manual/Tasks/jjtree.html
index 7fbb2a9..6d4aed5 100644
--- a/manual/Tasks/jjtree.html
+++ b/manual/Tasks/jjtree.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,213 +15,162 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
+<html lang="en">
 <head>
-   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <meta http-equiv="Content-Language" content="en-us">
-   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JJTree Task</title>
 </head>
 <body>
 
-<h2>
-<a NAME="jjtree"></a>JJTree</h2>
+<h2 id="jjtree">JJTree</h2>
 
-<h3>
-Description</h3>
-<p>Invokes the <a href="http://javacc.dev.java.net/">JJTree</a> preprocessor
-for the JavaCC compiler compiler. It inserts parse tree building actions
-at various places in the JavaCC source that it generates. The output of
-JJTree is run through JavaCC to create the parser.
-<p>To use the jjtree task, set the <i>target</i> attribute to the name
-of the JJTree grammar file to process. You also need to specify the directory
-containing the JavaCC installation using the <i>javacchome</i> attribute,
-so that Ant can find the JavaCC classes. Optionally, you can also set the
-<i>outputdirectory</i>
-to write the generated JavaCC grammar and node files to a specific directory.
-Otherwise jjtree writes the generated JavaCC grammar and node files to the directory
-containing the JJTree grammar file. As an extra option, you can also set the
-<i>outputfile</i> to write the generated JavaCC grammar file to a specific (directory and) file.
-Otherwise jjtree writes the generated JavaCC grammar file as the JJTree
-grammar file with a suffix .jj.</p>
-<p>This task only invokes JJTree if the grammar file is newer than the
-generated JavaCC file.</p>
+<h3>Description</h3>
+<p>Invokes the <a href="https://javacc.org/" target="_top">JJTree</a> preprocessor for the JavaCC
+compiler compiler. It inserts parse tree building actions at various places in the JavaCC source
+that it generates. The output of JJTree is run through JavaCC to create the parser.</p>
+<p>To use the <code>jjtree</code> task, set the <var>target</var> attribute to the name of the
+JJTree grammar file to process. You also need to specify the directory containing the JavaCC
+installation using the <var>javacchome</var> attribute, so that Ant can find the JavaCC
+classes. Optionally, you can also set the <var>outputdirectory</var> to write the generated JavaCC
+grammar and node files to a specific directory.  Otherwise <code>jjtree</code> writes the generated
+JavaCC grammar and node files to the directory containing the JJTree grammar file. As an extra
+option, you can also set the <var>outputfile</var> to write the generated JavaCC grammar file to a
+specific (directory and) file.  Otherwise <code>jjtree</code> writes the generated JavaCC grammar
+file as the JJTree grammar file with a suffix <samp>.jj</samp>.</p>
+<p>This task only invokes JJTree if the grammar file is newer than the generated JavaCC file.</p>
 
 <h3>Parameters</h3>
 
-<table BORDER CELLSPACING=0 CELLPADDING=2 >
+<table class="attr">
 <tr>
-<td VALIGN=TOP><b>Attribute</b></td>
-
-<td VALIGN=TOP><b>Description</b></td>
-
-<td ALIGN=CENTER VALIGN=TOP><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
 
 <tr>
-<td VALIGN=TOP>target</td>
-
-<td VALIGN=TOP>The jjtree grammar file to process.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>Yes</td>
+  <td>target</td>
+  <td>The JJTree grammar file to process.</td>
+  <td>Yes</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>javacchome</td>
-
-<td VALIGN=TOP>The directory containing the JavaCC distribution.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>Yes</td>
+  <td>javacchome</td>
+  <td>The directory containing the JavaCC distribution.</td>
+  <td>Yes</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>outputdirectory</td>
-
-<td VALIGN=TOP>The directory to write the generated JavaCC grammar and node files to.
-If not set, the files are written to the directory containing the grammar file.&nbsp;</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>outputdirectory</td>
+  <td>The directory to write the generated JavaCC grammar and node files to.  If not set, the files
+    are written to the directory containing the grammar file.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>outputfile</td>
-
-<td VALIGN=TOP>The file to write the generated JavaCC grammar file
-to. If not set, the file is written with the same name as the JJTree
-grammar file but with a the suffix <code>.jj</code>.  This is a
-filename relative to <em>outputdirectory</em> if specified, the
-project's basedir.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>outputfile</td>
+  <td>The file to write the generated JavaCC grammar file to. If not set, the file is written with
+    the same name as the JJTree grammar file but with a the suffix <code>.jj</code>.  This is a
+    filename relative to <var>outputdirectory</var> if specified, the project's basedir.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>buildnodefiles</td>
-
-<td VALIGN=TOP>Sets the BUILD_NODE_FILES grammar option. This is a boolean
-option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>buildnodefiles</td>
+  <td>Sets the BUILD_NODE_FILES grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>multi</td>
-
-<td VALIGN=TOP>Sets the MULTI grammar option. This is a boolean option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>multi</td>
+  <td>Sets the MULTI grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>nodedefaultvoid</td>
-
-<td VALIGN=TOP>Sets the NODE_DEFAULT_VOID grammar option. This is a boolean
-option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>nodedefaultvoid</td>
+  <td>Sets the NODE_DEFAULT_VOID grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>nodefactory</td>
-
-<td VALIGN=TOP>Sets the NODE_FACTORY grammar option. This is boolean option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>nodefactory</td>
+  <td>Sets the NODE_FACTORY grammar option. This is boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>nodescopehook</td>
-
-<td VALIGN=TOP>Sets the NODE_SCOPE_HOOK grammar option. This is a boolean
-option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>nodescopehook</td>
+  <td>Sets the NODE_SCOPE_HOOK grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>nodeusesparser</td>
-
-<td VALIGN=TOP>Sets the NODE_USES_PARSER grammar option. This is a boolean
-option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>nodeusesparser</td>
+  <td>Sets the NODE_USES_PARSER grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>static</td>
-
-<td VALIGN=TOP>Sets the STATIC grammar option. This is a boolean option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>static</td>
+  <td>Sets the STATIC grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>visitor</td>
-
-<td VALIGN=TOP>Sets the VISITOR grammar option. This is a boolean option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>visitor</td>
+  <td>Sets the VISITOR grammar option. This is a boolean option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>nodepackage</td>
-
-<td VALIGN=TOP>Sets the NODE_PACKAGE grammar option. This is a string option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>nodepackage</td>
+  <td>Sets the NODE_PACKAGE grammar option. This is a string option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>visitorexception</td>
-
-<td VALIGN=TOP>Sets the VISITOR_EXCEPTION grammar option. This is a string
-option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>visitorexception</td>
+  <td>Sets the VISITOR_EXCEPTION grammar option. This is a string option.</td>
+  <td>No</td>
 </tr>
 
 <tr>
-<td VALIGN=TOP>nodeprefix</td>
-
-<td VALIGN=TOP>Sets the NODE_PREFIX grammar option. This is a string option.</td>
-
-<td ALIGN=CENTER VALIGN=TOP>No</td>
+  <td>nodeprefix</td>
+  <td>Sets the NODE_PREFIX grammar option. This is a string option.</td>
+  <td>No</td>
 </tr>
 
-  <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Max amount of memory to allocate to the forked
-      VM.  <em>since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No</td>
-  </tr>
+<tr>
+  <td>maxmemory</td>
+  <td>Max amount of memory to allocate to the forked JVM.  <em>since Ant 1.8.3</em></td>
+  <td>No</td>
+</tr>
 </table>
 
-<h3>
-Example</h3>
+<h3>Example</h3>
 
-<blockquote>
-<pre>&lt;jjtree&nbsp;
-&nbsp;&nbsp;&nbsp; target="src/Parser.jjt"&nbsp;
-&nbsp;&nbsp;&nbsp; outputdirectory="build/src"
-&nbsp;&nbsp;&nbsp; javacchome="c:/program files/JavaCC"&nbsp;
-&nbsp;&nbsp;&nbsp; nodeusesparser="true"
-/&gt;</pre>
-</blockquote>
-This invokes JJTree on grammar file src/Parser.jjt, writing the generated
-grammar file, Parser.jj, file to build/src. The grammar option NODE_USES_PARSER
-is set to true when invoking JJTree.
-<br>
+<p>Invoke JJTree on grammar file <samp>src/Parser.jjt</samp>, writing the generated grammar
+file, <samp>Parser.jj</samp>, to <samp>build/src</samp>. The grammar option NODE_USES_PARSER is set
+to <q>true</q> when invoking JJTree.</p>
+<pre>
+&lt;jjtree target="src/Parser.jjt"
+        outputdirectory="build/src"
+        javacchome="c:/program files/JavaCC"
+        nodeusesparser="true"/&gt;</pre>
 
-<h3>Comparison output locations between command line JJTree and different Ant taskdef versions</h3>
+<h3>Comparison of output locations between command line JJTree and different Ant <code>taskdef</code>
+versions</h3>
 
-<table cellpadding="3" border="1">
+<table>
+  <thead class="no-bold">
 <tr>
-  <td><b>Command Line JJTree options</b>
-    <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>and Generated Files</i> (working directory: <code>/tmp</code>)</td>
-  <td><b>Ant 1.5.3</b> versus command line</td>
-  <td><b>Ant 1.6</b> versus command line</td>
+  <th scope="col"><strong>Command line JJTree options</strong> and <em>generated files</em> (working directory: <samp>/tmp</samp>)</th>
+  <th scope="col"><strong>Ant 1.5.3</strong> versus command line</th>
+  <th scope="col"><strong>Ant 1.6</strong> versus command line</th>
 </tr>
+  </thead>
+  <tbody>
 <tr>
   <td><pre><b>jjtree  grammar.jjt</b>
     /tmp/grammar.jj
@@ -241,7 +191,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree /tmp/absolute/grammar.jjt</b>
     /tmp/grammar.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -252,7 +202,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_DIRECTORY:relative  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_DIRECTORY:relative grammar.jjt</b>
     /tmp/relative/grammar.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -260,7 +210,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
     /tmp/relative/grammar.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -268,7 +218,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
     /tmp/relative/grammar.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -276,7 +226,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
     /tmp/absolute/grammar.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -284,7 +234,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
     /tmp/absolute/grammar.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -292,7 +242,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
     /tmp/absolute/grammar.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -300,7 +250,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj grammar.jjt</b>
     /tmp/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -308,7 +258,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj relative/grammar.jjt</b>
     /tmp/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -316,7 +266,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj /tmp/absolute/grammar.jjt</b>
     /tmp/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -324,7 +274,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:relative  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:relative grammar.jjt</b>
     /tmp/relative/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -332,7 +282,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
     /tmp/relative/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -340,7 +290,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
     /tmp/relative/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -348,7 +298,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
     /tmp/absolute/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -356,7 +306,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
     /tmp/absolute/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -364,7 +314,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
     /tmp/absolute/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -372,7 +322,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -380,7 +330,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj relative/grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -388,7 +338,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj /tmp/absolute/grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -396,7 +346,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:relative  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:relative grammar.jjt</b>
     /tmp/relative/subdir/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -404,7 +354,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
     /tmp/relative/subdir/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -412,7 +362,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
     /tmp/relative/subdir/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -420,7 +370,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
     /tmp/absolute/subdir/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -428,7 +378,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
     /tmp/absolute/subdir/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -436,7 +386,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
     /tmp/absolute/subdir/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -444,7 +394,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -452,7 +402,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj relative/grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
@@ -460,39 +410,39 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj /tmp/absolute/grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
   <td>Not Supported</td>
   <td>Same</td>
 </tr>
-<tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:<i><u>D:</u></i>/tmp/subdir/output.jj  grammar.jjt</b>
+<tr id="footnote-1-back">
+  <td><pre><b>jjtree -OUTPUT_FILE:<i>D:</i>/tmp/subdir/output.jj grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
   <td>Not Supported</td>
-  <td>Not Supported *)</td>
+  <td>Not Supported<a href="#footnote-1"><sup>*</sup></a></td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:<i><u>D:</u></i>/tmp/subdir/output.jj  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:<i>D:</i>/tmp/subdir/output.jj relative/grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
   <td>Not Supported</td>
-  <td>Not Supported *)</td>
+  <td>Not Supported<a href="#footnote-1"><sup>*</sup></a></td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:<i><u>D:</u></i>/tmp/subdir/output.jj  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:<i>D:</i>/tmp/subdir/output.jj /tmp/absolute/grammar.jjt</b>
     /tmp/subdir/output.jj
     /tmp/&lt;generated&gt;.java</pre>
   </td>
   <td>Not Supported</td>
-  <td>Not Supported *)</td>
+  <td>Not Supported<a href="#footnote-1"><sup>*</sup></a></td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:relative  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:relative grammar.jjt</b>
     /tmp/relative/tmp/subdir/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -500,7 +450,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
     /tmp/relative/tmp/subdir/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -508,7 +458,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
     /tmp/relative/tmp/subdir/output.jj
     /tmp/relative/&lt;generated&gt;.java</pre>
   </td>
@@ -516,7 +466,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
     /tmp/absolute/tmp/subdir/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -524,7 +474,7 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
     /tmp/absolute/tmp/subdir/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
@@ -532,32 +482,30 @@
   <td>Same</td>
 </tr>
 <tr>
-  <td><pre><b>jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt</b>
+  <td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
     /tmp/absolute/tmp/subdir/output.jj
     /tmp/absolute/&lt;generated&gt;.java</pre>
   </td>
   <td>Not Supported</td>
   <td>Same</td>
 </tr>
+  </tbody>
 </table>
 
-<p>*) <u>Footnote</u>: When running JJTree with the Ant taskdef <i>jjtree</i> the option <code>-OUTPUT_DIRECTORY</code> must always 
-be set, because the project's basedir and the Ant working directory might differ. So even if you don't specify the jjtree taskdef 
-<i>outputdirectory</i> JJTree will be called with the <code>-OUTPUT_DIRECTORY</code> set to the project's basedirectory. 
-But when the <code>-OUTPUT_DIRECTORY</code> is set, the <code>-OUTPUT_FILE</code> setting is handled as if relative to this 
-<code>-OUTPUT_DIRECTORY</code>. Thus when the <code>-OUTPUT_FILE</code> is absolute or contains a drive letter we have a 
-problem. 
-Therefore absolute <i>outputfile</i>s (when the <i>outputdirectory</i> isn't specified) are made relative to the default directory.
-And for this reason <i>outputfile</i>s that contain a drive letter can't be supported.</p>
+<p id="footnote-1"><a href="#footnote-1-back"><strong>Note</strong></a>: When running JJTree with
+the Ant <code>taskdef jjtree</code> the option <kbd>-OUTPUT_DIRECTORY</kbd> must always be set,
+because the project's <var>basedir</var> and the Ant working directory might differ. So even if you
+don't specify the <var>outputdirectory</var> for <code>taskdef jjtree</code>, JJTree will be called
+with the <kbd>-OUTPUT_DIRECTORY</kbd> set to the project's <var>basedir</var>.  But when
+the <kbd>-OUTPUT_DIRECTORY</kbd> is set, the <kbd>-OUTPUT_FILE</kbd> setting is handled as if
+relative to this <kbd>-OUTPUT_DIRECTORY</kbd>. Thus when the <kbd>-OUTPUT_FILE</kbd> is absolute
+or contains a drive letter we have a problem.  Therefore absolute <var>outputfile</var>s (when
+the <var>outputdirectory</var> isn't specified) are made relative to the default directory.  And for
+this reason <var>outputfile</var>s that contain a drive letter can't be supported.</p>
 
-<p>By the way: specifying a drive letter in the <code>-OUTPUT_FILE</code> when the <code>-OUTPUT_DIRECTORY</code> is set, also 
-results in strange behavior when running JJTree from the command line.</p>
-
-<br>
-
-
-
+<p>By the way: specifying a drive letter in the <kbd>-OUTPUT_FILE</kbd> when
+the <kbd>-OUTPUT_DIRECTORY</kbd> is set, also results in strange behavior when running JJTree from
+the command line.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/jlink.html b/manual/Tasks/jlink.html
index 45ef961..9f84994 100644
--- a/manual/Tasks/jlink.html
+++ b/manual/Tasks/jlink.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,113 +15,93 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JLink Task</title>
 </head>
 <body>
 
-<h2><a name="jlink">Jlink</a></h2>
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated. Use a <a href="../Types/zipfileset.html">zipfileset</a>
- or <a href="../Tasks/zip.html#zipgroupfileset">zipgroupfileset</a> with the
- <a href="../Tasks/jar.html">Jar task</a> or <a href="../Tasks/zip.html">Zip task</a>
- instead.</i></p>
+<h2 id="jlink">Jlink</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>. Use a <a href="../Types/zipfileset.html">zipfileset</a>
+or <a href="../Tasks/zip.html#zipgroupfileset">zipgroupfileset</a> with
+the <a href="../Tasks/jar.html">Jar task</a> or <a href="../Tasks/zip.html">Zip task</a>
+instead.  For a task based on the JDK's jlink tool, see
+<a href="link.html">Link</a>.</em></p>
 
-<h3><b>Description:</b></h3>
+<h3>Description</h3>
+<p><strong>For a task based on the JDK's jlink tool, see
+<a href="link.html">Link</a>.  This task is for something else
+entirely.</strong></p>
+
 <p>Links entries from sub-builds and libraries.</p>
 
-<p>The jlink task can be used to build jar and zip files, similar to 
-the <i>jar</i> task.
-However, jlink provides options for controlling the way entries from 
-input files
-are added to the output file. Specifically, capabilities for merging 
-entries from
-multiple zip or jar files is available.</p>
+<p>The <code>jlink</code> task can be used to build jar and zip files, similar to
+the <code>jar</code> task.  However, <code>jlink</code> provides options for controlling the way
+entries from input files are added to the output file. Specifically, capabilities for merging
+entries from multiple zip or jar files is available.</p>
 
-<p>If a mergefile is specified directly (eg. at the top level of a 
-<i>mergefiles</i>
-pathelement) <i>and</i> the mergefile ends in &quot;.zip&quot; or 
-&quot;.jar&quot;,
-entries in the mergefile will be merged into the outfile. A file with 
-any other extension
-will be added to the output file, even if it is specified in the 
-mergefiles element.
-Directories specified in either the mergefiles or addfiles element 
-are added to the
-output file as you would expect: all files in subdirectories are 
-recursively added to
-the output file with appropriate prefixes in the output file 
-(without merging).
-</p>
+<p>If a mergefile is specified directly (eg. at the top level of a <code>mergefiles</code>
+pathelement) <em>and</em> the mergefile ends in <samp>.zip</samp> or <samp>.jar</samp>, entries in
+the mergefile will be merged into the <var>outfile</var>. A file with any other extension will be
+added to the output file, even if it is specified in the <code>mergefiles</code> element.
+Directories specified in either the <code>mergefiles</code> or <code>addfiles</code> element are
+added to the output file as you would expect: all files in subdirectories are recursively added to
+the output file with appropriate prefixes in the output file (without merging).</p>
 
-<p>
-In the case where duplicate entries and/or files are found among the 
-files to be merged or
-added, jlink merges or adds the first entry and ignores all subsequent entries.
-</p>
+<p>In the case where duplicate entries and/or files are found among the files to be merged or
+added, <code>jlink</code> merges or adds the first entry and ignores all subsequent entries.</p>
 
-<p>
-jlink ignores META-INF directories in mergefiles. Users should supply their
-own manifest information for the output file.
-</p>
+<p><code>jlink</code> ignores <samp>META-INF</samp> directories in <var>mergefiles</var>. Users
+should supply their own manifest information for the output file.</p>
 
-<p>It is possible to refine the set of files that are being jlinked. 
-This can be
-done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, 
-<i>excludesfile</i>,
-and <i>defaultexcludes</i> attributes on the <i>addfiles</i> and 
-<i>mergefiles</i>
-nested elements. With the <i>includes</i> or <i>includesfile</i>
-attribute you specify the files you want to have included by using patterns.
-The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
-the files you want to have excluded. This is also done with patterns. And
-finally with the <i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
-inclusion/exclusion of files works, and how to write patterns. The patterns are
-relative to the <i>base</i> directory.</p>
+<p>It is possible to refine the set of files that are being jlinked.  This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>,
+and <var>defaultexcludes</var> attributes on the <code>addfiles</code> and <code>mergefiles</code>
+nested elements. With the <var>includes</var> or <var>includesfile</var> attribute you specify the
+files you want to have included by using patterns.  The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded. This is
+also done with patterns. And finally with the <var>defaultexcludes</var> attribute, you can specify
+whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+inclusion/exclusion of files works, and how to write patterns. The patterns are relative to
+the <em>base</em> directory.</p>
 
-
-
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters</h3>
+<table class="attr">
    <tr>
-     <td valign="top"><b>Attribute</b></td>
-     <td valign="top"><b>Description</b></td>
-     <td align="center" valign="top"><b>Required</b></td>
+     <th scope="col">Attribute</th>
+     <th scope="col">Description</th>
+     <th scope="col">Required</th>
    </tr>
    <tr>
-     <td valign="top">outfile</td>
-     <td valign="top">the path of the output file.</td>
-     <td valign="top" align="center">Yes</td>
+     <td>outfile</td>
+     <td>the path of the output file.</td>
+     <td>Yes</td>
    </tr>
    <tr>
-     <td valign="top">compress</td>
-     <td valign="top">whether or not the output should be compressed. 
-<i>true</i>,
-                      <i>yes</i>, or <i>on</i> result in compressed output.
-                      If omitted, output will be uncompressed (inflated).</td>
-     <td valign="top" align="center">No</td>
+     <td>compress</td>
+     <td>whether or not the output should be compressed. <q>true</q>, <q>yes</q>, or <q>on</q>
+       result in compressed output.</td>
+     <td>No; defaults to uncompressed (inflated) output</td>
    </tr>
    <tr>
-     <td valign="top">mergefiles</td>
-     <td valign="top">files to be merged into the output, if possible.</td>
-     <td valign="middle" align="center" rowspan="2">At least one of 
-mergefiles or addfiles</td>
+     <td>mergefiles</td>
+     <td>files to be merged into the output, if possible.</td>
+     <td rowspan="2">Exactly one of the two</td>
    </tr>
    <tr>
-     <td valign="top">addfiles</td>
-     <td valign="top">files to be added to the output.</td>
+     <td>addfiles</td>
+     <td class="left">files to be added to the output.</td>
    </tr>
 </table>
 
 <h3>Examples</h3>
 
-<p>The following will merge the entries in mergefoo.jar and mergebar.jar 
-into out.jar.
-mac.jar and pc.jar will be added as single entries to out.jar.</p>
+<p>The following will merge the entries in <samp>mergefoo.jar</samp> and <samp>mergebar.jar</samp>
+into <samp>out.jar</samp>.  <samp>mac.jar</samp> and <samp>pc.jar</samp> will be added as single
+entries to <samp>out.jar</samp>.</p>
 <pre>
 &lt;jlink compress=&quot;false&quot; outfile=&quot;out.jar&quot;&gt;
    &lt;mergefiles&gt;
@@ -134,7 +115,7 @@
 &lt;/jlink&gt;
 </pre>
 
-<p><b>Non-deprecated alternative to the above:</b></p>
+<p><strong>Non-deprecated alternative to the above:</strong></p>
 <pre>
 &lt;jar compress=&quot;false&quot; destfile=&quot;out.jar&quot;&gt;
   &lt;zipgroupfileset dir=&quot;${build.dir}&quot;&gt;
@@ -148,30 +129,25 @@
 &lt;/jar&gt;
 </pre>
 
-<p>Suppose the file foo.jar contains two entries: bar.class and 
-barnone/myClass.zip.
-Suppose the path for file foo.jar is build/tempbuild/foo.jar. The 
-following example
-will provide the entry tempbuild/foo.jar in the out.jar.</p>
+<p>Suppose the file <samp>foo.jar</samp> contains two entries: <samp>bar.class</samp>
+and <samp>barnone/myClass.zip</samp>.  Suppose the path for file <samp>foo.jar</samp>
+is <samp>build/tempbuild/foo.jar</samp>. The following example will provide the
+entry <samp>tempbuild/foo.jar</samp> in the <samp>out.jar</samp>.</p>
 <pre>
 &lt;jlink compress=&quot;false&quot; outfile=&quot;out.jar&quot;&gt;
    &lt;mergefiles&gt;
      &lt;pathelement path=&quot;build/tempbuild&quot;/&gt;
    &lt;/mergefiles&gt;
-&lt;/jlink&gt;
-</pre>
+&lt;/jlink&gt;</pre>
 
-<p>However, the next example would result in two top-level entries in out.jar,
-namely bar.class and barnone/myClass.zip</p>
+<p>However, the next example would result in two top-level entries in <samp>out.jar</samp>,
+namely <samp>bar.class</samp> and <samp>barnone/myClass.zip</samp></p>
 <pre>
 &lt;jlink compress=&quot;false&quot; outfile=&quot;out.jar&quot;&gt;
    &lt;mergefiles&gt;
      &lt;pathelement path=&quot;build/tempbuild/foo.jar&quot;/&gt;
    &lt;/mergefiles&gt;
-&lt;/jlink&gt;
-</pre>
-
+&lt;/jlink&gt;</pre>
 
 </body>
-
 </html>
diff --git a/manual/Tasks/jmod.html b/manual/Tasks/jmod.html
new file mode 100644
index 0000000..8de8bcb
--- /dev/null
+++ b/manual/Tasks/jmod.html
@@ -0,0 +1,332 @@
+<!DOCTYPE html>
+<!--
+   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
+
+       https://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">
+
+<head>
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<title>Jmod Task</title>
+</head>
+
+<body>
+
+<h2 id="jmod">Jmod</h2>
+<p><em>Since Apache Ant 1.10.6</em></p>
+
+<h3>Description</h3>
+<p>Creates a linkable jmod file from a modular jar file, and optionally from
+other application files such as native libraries and license documents.
+Equivalent to the JDK's
+<a href="https://docs.oracle.com/en/java/javase/11/tools/jmod.html">jmod</a>
+tool.</p>
+<p>Requires Java 9 or later.</p>
+
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>destFile</td>
+    <td>jmod file to create.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>Files to be placed in the jmod file.  Usually a single module.</td>
+    <td rowspan="2">One of these is required, unless a nested
+                    <code>&lt;classpath&gt;</code> is present.</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td class="left">Files to be placed in the jmod file, given as a
+        <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+  </tr>
+  <tr>
+    <td>modulepath</td>
+    <td>Locations of modules on which classpath modules depend.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>modulepathref</td>
+    <td>Locations of modules on which classpath modules depend,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>commandpath</td>
+    <td>Directories containing native commands to include in jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>commandpathref</td>
+    <td>Directories containing native commands to include in jmod,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>headerpath</td>
+    <td>Directories containing header files to include in jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>headerpathref</td>
+    <td>Directories containing header files to include in jmod,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>configpath</td>
+    <td>Directories containing user-editable configuration files
+        to include in jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>configpathref</td>
+    <td>Directories containing user-editable configuration files
+        to include in jmod,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>legalpath</td>
+    <td>Directories containing legal licenses and notices to include in jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>legalpathref</td>
+    <td>Directories containing legal licenses and notices to include in jmod,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>nativelibpath</td>
+    <td>Directories containing native libraries to include in jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>nativelibpathref</td>
+    <td>Directories containing native libraries to include in jmod,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>manpath</td>
+    <td>Directories containing man pages to include in jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>manpathref</td>
+    <td>Directories containing man pages to include in jmod,
+        given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>version</td>
+    <td><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">Module version</a> of jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>mainclass</td>
+    <td>Class that acts as executable entry point of module.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>platform</td>
+    <td>The target platform for the jmod.  Typically takes the form
+        <var>OS</var><code>-</code><var>architecture</var>.  A particular JDK's
+        platform can be seen by running a command like
+        <samp>jmod describe $JDK_HOME/jmods/java.base.jmod | grep -i platform</samp></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>hashModulesPattern</td>
+    <td>Regular expression for names of modules in the module path
+        which depend on the jmod being created, and which should have
+        hashes generated for them and included in the new jmod.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>resolveByDefault</td>
+    <td>Boolean indicating whether the jmod should be one of
+        the default resolved modules when it is in a module path
+        searched by tools and applications.</td>
+    <td>No.  Default is true.</td>
+  </tr>
+  <tr>
+    <td>moduleWarnings</td>
+    <td>Whether to emit warnings when resolving modules which are
+        not recommended for use.  Comma-separated list of one of more of
+        the following:
+        <dl>
+        <dt><code>deprecated</code></dt>
+        <dd>Warn if module is deprecated</dd>
+        <dt><code>leaving</code></dt>
+        <dd>Warn if module is deprecated for removal</dd>
+        <dt><code>incubating</code></dt>
+        <dd>Warn if module is an incubating (not yet official) module</dd>
+        </dl>
+    </td>
+    <td>No, default is no warnings.</td>
+  </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+<h4>classpath, modulepath, commandpath, headerpath, configpath, legalpath, nativelibpath, manpath</h4>
+<p>The
+   <code>classpath</code>,
+   <code>modulepath</code>,
+   <code>commandpath</code>,
+   <code>headerpath</code>,
+   <code>configpath</code>,
+   <code>legalpath</code>,
+   <code>nativelibpath</code>, and
+   <code>manpath</code>
+   attributes are <a href="../using.html#path">path-like structures</a>
+   and can also be set via nested
+   <code>&lt;classpath&gt;</code>,
+   <code>&lt;modulepath&gt;</code>,
+   <code>&lt;commandpath&gt;</code>,
+   <code>&lt;headerpath&gt;</code>,
+   <code>&lt;configpath&gt;</code>,
+   <code>&lt;legalpath&gt;</code>,
+   <code>&lt;nativelibpath&gt;</code>, and
+   <code>&lt;manpath&gt;</code>
+   elements, respectively.</p>
+
+<h4>version</h4>
+<p>Fine-grained alternative to the <code>version</code> attribute.  This
+nested element has these attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>number</td>
+    <td>Primary version number.  Can be any text, as long as it does not
+        contain a hyphen (<code>-</code>) or plus (<code>+</code>).</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>preRelease</td>
+    <td>Pre-release version.  Can be any text, as long as it does not
+        contain a plus (<code>+</code>).</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>build</td>
+    <td>Build version.  Can be any text.
+    <td>No</td>
+  </tr>
+</table>
+
+<p>See the <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">ModuleDescriptor.Version documentation</a>
+for a full description of the meaning of each version component.</p>
+
+<h4>moduleWarning</h4>
+<p>Like the <code>moduleWarnings</code> attribute, but only specifies a single
+basis for emitting warnings.  This child element may appear multiple times,
+to specify multiple conditions under which warnings should be emitted by the
+jmod tool.</p>
+
+<p>Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>reason</td>
+    <td>Condition which will cause jmod tool to emit warnings.  One of:
+        <dl>
+        <dt><code>deprecated</code></dt>
+        <dd>Warn if module is deprecated</dd>
+        <dt><code>leaving</code></dt>
+        <dd>Warn if module is deprecated for removal</dd>
+        <dt><code>incubating</code></dt>
+        <dd>Warn if module is an incubating (not yet official) module</dd>
+        </dl>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h3>Examples</h3>
+
+<h4>Basic jmod</h4>
+<p>Create a jmod from a single modular jar file:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+</pre>
+
+<h4>With dependencies</h4>
+<p>Create a jmod from a modular jar file which depends on another module:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"&gt;
+    &lt;modulepath&gt;
+        &lt;pathelement location="libs/thirdpartyutils.jar"/&gt;
+    &lt;/modulepath&gt;
+&lt;/jmod&gt;
+</pre>
+
+<h4>With version</h4>
+<p>Create a jmod with a module version:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"
+      version="1.2.1-ea+29"/&gt;
+</pre>
+
+<p>Create a versioned jmod from module version components:</p>
+<pre>
+&lt;property name="version" value="1.2.1"/&gt;
+&lt;buildnumber/&gt;
+&lt;loadfile property="buildnum" srcFile="build.number"/&gt;
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"&gt;
+    &lt;version number="${version}" build="${buildnum}"/&gt;
+&lt;/jmod&gt;
+</pre>
+
+<h4>Main class</h4>
+<p>Create a jmod with a main class:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"
+      mainclass="com.example.myapp.MainWindow"/&gt;
+</pre>
+
+<h4>Target platform</h4>
+<p>Create a jmod for a specific platform, possibly different from the
+current platform:</p>
+
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"
+      platform="windows-amd64"/&gt;
+</pre>
+
+</body>
+</html>
diff --git a/manual/Tasks/jspc.html b/manual/Tasks/jspc.html
index 8836186..bb040e6 100644
--- a/manual/Tasks/jspc.html
+++ b/manual/Tasks/jspc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,242 +15,209 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JSPC Task</title>
 </head>
 
 <body>
 
-<h2><a name="jspc">jspc (deprecated)</a></h2>
+<h2 id="jspc">jspc</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>If you use this task with Tomcat's Jasper JSP compiler, you should seriously consider using
+the task shipping with Tomcat instead.</em>  This task is only tested against Tomcat 4.x. There are
+known problems with Tomcat 5.x that won't get fixed in Ant, please use Tomcat's <code>jspc</code>
+task instead.<br/>  Instead of relying on container-specific JSP compilers we suggest deploying the
+raw files (<samp>*.jsp</samp>) and use the container build-in functions: after deploying run a test
+suite (e.g. with <a href="https://attic.apache.org/projects/jakarta-cactus.html"
+target="_top">Cactus</a> or <a href="http://httpunit.sourceforge.net/" target="_top">HttpUnit</a>)
+against the deployed web application. So you'll get the test result <em>and</em> the compiled
+JSPs.</p>
 <h3>Description</h3>
 
-<p> Apache Ant task to run the JSP compiler and turn JSP pages into Java source.
+<p>Apache Ant task to run the JSP compiler and turn JSP pages into Java source files.</p>
 
-<p><b>Deprecated</b> if you use this task with Tomcat's Jasper JSP
-compiler, you should seriously consider using the task shipping with
-Tomcat instead.  This task is only tested against Tomcat 4.x. There
-are known problems with Tomcat 5.x that won't get fixed in Ant, please
-use Tomcat's jspc task instead.<br/>
-Instead of relying on container specific JSP-compilers we suggest deploying 
-the raw files (*.jsp) and use the container build-in functions: after deploying run
-a test suite (e.g. with <a href="http://attic.apache.org/projects/jakarta-cactus.html">Cactus</a> or 
-<a href="http://httpunit.sourceforge.net/">HttpUnit</a>) against the deployed web 
-application. So you'll get the test result <i>and</i> the compiled JSPs.
-</p>
+<p>This task can be used to precompile JSP pages for fast initial invocation of JSP pages,
+deployment on a server without the full JDK installed, or simply to syntax check the pages without
+deploying them.  In most cases, a <code>javac</code> task is usually the next stage in the build
+process.  The task does basic dependency checking to prevent unnecessary recompilation&mdash;this
+checking compares source and destination timestamps, and does not factor in class or taglib
+dependencies, or <code>&lt;jsp:include&gt;</code> references.</p>
 
-<p>
+<p>By default the task uses the Jasper JSP compiler. This means the task
+needs <samp>jasper.jar</samp> and <samp>jasper-runtime.jar</samp>, which come with builds of Tomcat
+4/Catalina from the <a href="https://tomcat.apache.org/" target="_top">Apache Tomcat project</a>,
+and any other jar files which may be needed in future versions (it changes).</p>
 
-This task can be used to precompile JSP pages for fast initial invocation
-of JSP pages, deployment on a server without the full JDK installed,
-or simply to syntax check the pages without deploying them.
-In most cases, a javac task is usually the next stage in the build process.
-The task does basic dependency checking to prevent unnecessary recompilation -this
-checking compares source and destination timestamps, and does not factor
-in class or taglib dependencies, or <code>&lt;jsp:include&gt;</code> references.
+<p>We recommend (in March 2003) Tomcat version 4.1.x for the most robust version of Jasper.</p>
 
-<p>
-By default the task uses the Jasper JSP compiler. This
-means the task needs jasper.jar and jasper-runtime.jar, which come with
-builds of Tomcat 4/Catalina from the
-<a href="http://tomcat.apache.org/">Apache Tomcat project</a>,
-and any other Jar files which may be needed in future versions (it changes)
-
-We recommend (in March 2003) Tomcat version 4.1.x for the most robust version
-of Jasper.
-
-<p>
-There are many limitations with this task which partially stem from the
-many versions of Jasper, others from implementation 'issues' in the task
-(i.e. nobody's willingness to radically change large bits of it to work
-around jasper). Because of this and the fact that JSP pages do not have
-to be portable across implementations -or versions of implementations-
-this task is better used for validating JSP pages before deployment,
-rather than precompiling them. For that, just deploy and run your httpunit
-junit tests after deployment to compile and test your pages, all in one
-go.
- 
-</p>
+<p>There are many limitations with this task which partially stem from the many versions of Jasper,
+others from implementation 'issues' in the task (i.e. nobody's willingness to radically change large
+bits of it to work around Jasper). Because of this and the fact that JSP pages do not have to be
+portable across implementations&mdash;or versions of implementations&mdash;this task is better used
+for validating JSP pages before deployment, rather than precompiling them. For the latter, just
+deploy and run your HttpUnit JUnit tests after deployment to compile and test your pages, all in one
+go.</p>
 
 
 <h3>Parameters</h3>
-The Task has the following attributes:<p>
+<p>The Task has the following attributes:</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">Where to place the generated files. They are located
-    under here according to the given package name.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>destdir</td>
+    <td>Where to place the generated files. They are located under here according to the given
+      package name.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">srcdir</td>
-    <td valign="top">Where to look for source jsp files.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>srcdir</td>
+    <td>Where to look for source JSP files.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">The verbosity integer to pass to the compiler. Default="0"</td>
-    <td valign="top" align="center">No</td>
+    <td>verbose</td>
+    <td>The verbosity integer to pass to the compiler.</td>
+    <td>No; default <q>0</q></td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">Name of the destination package for generated java
-    classes.</td>
-    <td valign="top" align="center">No</td>
+    <td>package</td>
+    <td>Name of the destination package for generated Java classes.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td valign="top">class name of a JSP compiler adapter,
-    such as "jasper" or "jasper41"</td>
-    <td valign="top" align="center">No -defaults to "jasper"</td>
+    <td>compiler</td>
+    <td>class name of a JSP compiler adapter, such as <q>jasper</q> or <q>jasper41</q></td>
+    <td>No; defaults to <q>jasper</q></td>
   </tr>
   <tr>
-    <td valign="top">ieplugin</td>
-    <td valign="top">Java Plugin classid for Internet Explorer.</td>
-    <td valign="top" align="center">No</td>
+    <td>ieplugin</td>
+    <td>Java Plugin classid for Internet Explorer.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">mapped</td>
-    <td valign="top">(boolean) Generate separate write() calls for each HTML
-    line in the JSP.</td>
-    <td valign="top" align="center">No</td>
+    <td>mapped</td>
+    <td>(boolean) Generate separate <code>write()</code> calls for each HTML line in the JSP.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to use to run the jsp compiler.
-    This can also be specified
-    by the nested element <code>classpath</code>
-    <a href="../using.html#path">Path</a>).</td>
-    <td valign="top" align="center">No, but it seems to work better when used</td>
+    <td>classpath</td>
+    <td>The classpath to use to run the JSP compiler.</td>
+    <td>No, but it seems to work better when used; can also be specified by the nested
+      element <a href="../using.html#path"><code>classpath</code></a></td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">A <a href="../using.html#references">Reference</a>. As
-    per <code>classpath</code></td>
-    <td valign="top" align="center">No</td>
+    <td>classpathref</td>
+    <td>A <a href="../using.html#references">Reference</a>. As per <var>classpath</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">flag to control action on compile failures: default=yes</td>
-    <td valign="top" align="center">No</td>
+    <td>failonerror</td>
+    <td>flag to control action on compile failures.</td>
+    <td>No; default <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">uribase</td>
-    <td valign="top">
-    The uri context of relative URI
-    references in the JSP pages. If it does not
-    exist then it is derived from the location of the file
-    relative to the declared or derived value of <tt>uriroot.</tt>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>uribase</td>
+    <td>The context of relative URI references in JSP.</td>
+    <td>No; derived from the location of the file relative to the declared or derived value
+      of <var>uriroot</var></td>
   </tr>
   <tr>
-    <td valign="top">uriroot</td>
-    <td valign="top">
-    The root directory that uri files should be resolved
-    against.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>uriroot</td>
+    <td>The root directory that URIs should be resolved against.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td valign="top">
-    Class name of jsp compiler adapter to use.  Defaults to
-    the standard adapter for Jasper.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>compiler</td>
+    <td>Class name of JSP compiler adapter to use.</td>
+    <td>No; defaults to the standard adapter for Jasper</td>
   </tr>
   <tr>
-    <td valign="top">compilerclasspath</td>
-    <td valign="top">The classpath used to find the compiler adapter specified
-    by the <code>compiler</code> attribute.</td>
-    <td valign="top" align="center">No</td>
+    <td>compilerclasspath</td>
+    <td>The classpath used to find the compiler adapter specified by the <var>compiler</var>
+      attribute.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">webinc</td>
-    <td valign="top">Output file name for the fraction of web.xml that lists servlets.</td>
-    <td valign="top" align="center">No</td>
-  </tr>    
+    <td>webinc</td>
+    <td>Output file name for the fraction of <samp>web.xml</samp> that lists servlets.</td>
+    <td>No</td>
+  </tr>
   <tr>
-    <td valign="top">webxml</td>
-    <td valign="top">File name for web.xml to be generated</td>
-    <td valign="top" align="center">No</td>
-  </tr>  
+    <td>webxml</td>
+    <td>File name for <samp>web.xml</samp> to be generated</td>
+    <td>No</td>
+  </tr>
+</table>
 
-  </table>
+<p>The <var>mapped</var> option will, if set to <q>true</q>, split the JSP text content into a one
+line per call format.  There are comments above and below the mapped write calls to localize where
+in the JSP file each line of text comes from.  This can lead to a minor performance degradation (but
+it is bound by a linear complexity).  Without this option all adjacent writes are concatenated into
+a single write.</p>
 
-<P>The <tt>mapped</tt> option will, if set to true, split the JSP text content into a
-one line per call format.  There are comments above and below the mapped
-write calls to localize where in the JSP file each line of text comes
-from.  This can lead to a minor performance degradation (but it is bound
-by a linear complexity).  Without this options all adjacent writes are
-concatenated into a single write.</P>
+<p>The <var>ieplugin</var> option is used by the <code>&lt;jsp:plugin&gt;</code> tags.  If the Java
+Plug-in COM Class-ID you want to use changes then it can be specified here.  This should not need to
+be altered.</p>
 
-<P>The <tt>ieplugin</tt> option is used by the <tt>&lt;jsp:plugin&gt;</tt> tags.
-If the Java Plug-in COM Class-ID you want to use changes then it can be
-specified here.  This should not need to be altered.</P>
+<p><var>uriroot</var> specifies the root of the web application.  This is where all absolute URIs
+will be resolved from.  If it is not specified then the first JSP page will be used to derive it.
+To derive it each parent directory of the first JSP page is searched for a <samp>WEB-INF</samp>
+directory, and the directory closest to the JSP page that has one will be used.  If none can be
+found then the directory Jasperc was called from will be used.  This only affects pages translated
+from an explicitly declared JSP file&mdash;including references to taglibs.</p>
 
-<P><tt>uriroot</tt> specifies the root of the web
-application.  This is where all absolute uris will be resolved from.
-If it is not specified then the first JSP page will be used to derive
-it.  To derive it each parent directory of the first JSP page is
-searched for a <tt>WEB-INF</tt> directory, and the directory closest to
-the JSP page that has one will be used.  If none can be found then the
-directory Jasperc was called from will be used.  This only affects pages
-translated from an explicitly declared JSP file -including references
-to taglibs</P>
-
-<P><tt>uribase</tt> is used to establish the uri context of
-relative URI references in the JSP pages.  If it does not exist then it
-is derived from the location of the file relative to the declared or
-derived value of <tt>uriroot</tt>. This only affects pages
-translated from an explicitly declared JSP file.</P>
+<p><var>uribase</var> is used to establish the context of relative URI references in the JSP pages.
+If it does not exist then it is derived from the location of the file relative to the declared or
+derived value of <var>uriroot</var>. This only affects pages translated from an explicitly declared
+JSP file.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
-This task is a <a href="../dirtasks.html">directory based task</a>, like
-<strong>javac</strong>, so the jsp files to be compiled are located as java
-files are by <strong>javac</strong>. That is, elements such as <tt>includes</tt> and
-<tt>excludes</tt> can be used directly inside the task declaration.
+<p>This task is a <a href="../dirtasks.html">directory based task</a>, like <code>javac</code>, so
+the <samp>.jsp</samp> files to be compiled are located as <samp>.java</samp> files are
+by <code>javac</code>. That is, elements such as <code>includes</code> and <code>excludes</code> can
+be used directly inside the task declaration.</p>
 
-<p>
-
-Elements specific to the jspc task are:-
+<p>Elements specific to the <code>jspc</code> task are:</p>
 
 <h4>classpath</h4>
 
-The classpath used to compile the JSP pages, specified as for any other
-classpath.
+<p>The classpath used to compile the JSP pages, specified as for any other classpath.</p>
 
 <h4>classpathref</h4>
-a reference to an existing classpath
+
+<p>a reference to an existing classpath</p>
 
 <h4>webapp</h4>
-Instructions to jasper to build an entire web application.
-The base directory must have a WEB-INF subdirectory beneath it.
-When used, the task hands off all dependency checking to the compiler.
-<table border="1" cellpadding="2" cellspacing="0">
+
+<p>Instructions to Jasper to build an entire web application.  The base directory must have
+a <samp>WEB-INF</samp> subdirectory beneath it.  When used, the task hands off all dependency
+checking to the compiler.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the base directory of the web application</td>
-    <td valign="top" align="center">Yes</td>
+    <td>basedir</td>
+    <td>the base directory of the web application</td>
+    <td>Yes</td>
   </tr>
 </table>
+
 <h3>Example</h3>
+<p>Build all <samp>.jsp</samp> files under <samp>src/war</samp> into the
+destination <samp>/gensrc</samp>, in a package hierarchy beginning
+with <samp>com.i3sp.jsp</samp>.</p>
 <pre>
 &lt;jspc srcdir="${basedir}/src/war"
       destdir="${basedir}/gensrc"
@@ -257,52 +225,37 @@
       compiler="jasper41"
       verbose="9"&gt;
   &lt;include name="**/*.jsp"/&gt;
-&lt;/jspc&gt;
-</pre>
-Build all jsp pages under src/war into the destination /gensrc, in a
-package hierarchy beginning with com.i3sp.jsp.
+&lt;/jspc&gt;</pre>
+
+<p>Generate <samp>.java</samp> files from <samp>.jsp</samp> files, then <code>javac</code> them down
+to bytecode. Include <samp>lib/taglibs.jar</samp> in the Java compilation. Dependency checking is
+used to scrub the <samp>.java</samp> files if class dependencies indicate it is needed.</p>
 <pre>
-&lt;jspc
-      destdir="interim"
+&lt;jspc destdir="interim"
       verbose="1"
       srcdir="src"
       compiler="jasper41"
       package="com.i3sp.jsp"&gt;
   &lt;include name="**/*.jsp"/&gt;
 &lt;/jspc&gt;
-&lt;depend
-         srcdir="interim"
+&lt;depend srcdir="interim"
          destdir="build"
          cache="build/dependencies"
          classpath="lib/taglibs.jar"/&gt;
-&lt;javac
-         srcdir="interim"
+&lt;javac srcdir="interim"
          destdir="build"
          classpath="lib/taglibs.jar"
-         debug="on"/&gt;
-</pre>
-Generate jsp pages then javac them down to
-bytecodes. Include lib/taglib jar in the java compilation.
- Dependency checking is used to scrub the
-java files if class dependencies indicate it is needed.
+         debug="on"/&gt;</pre>
 
-<p><h4>Notes</h4>
-Using the <code>package</code> attribute it is possible to identify the resulting
-java files and thus do full dependency checking - this task should only rebuild
-java files if their jsp file has been modified. However, this only works
-with some versions of jasper. By default the checking supports tomcat 4.0.x
-with the "jasper" compiler, set the compiler to "jasper41" for the tomcat4.1.x
-dependency checking.
-Even when it does work, changes in
-.TLD imports or in compile time includes do not get picked up.
-
-<p>
-Jasper generates JSP pages against the JSP1.2 specification -a copy of
-version 2.3 of the servlet specification is needed on the classpath to
-compile the Java code.
-
-
-
+<h4>Notes</h4>
+<p>Using the <var>package</var> attribute it is possible to identify the
+resulting <samp>.java</samp> files and thus do full dependency checking&mdash;this task should only
+rebuild <samp>.java</samp> files if their <samp>.jsp</samp> file has been modified. However, this
+only works with some versions of Jasper. By default the checking supports Tomcat 4.0.x with
+the <q>jasper</q> compiler, set the compiler to <q>jasper41</q> for the Tomcat 4.1.x dependency
+checking. Even when it does work, changes in <samp>.tld</samp> imports or in compile time includes
+do not get picked up.</p>
+<p>Jasper generates JSP pages against the JSP 1.2 specification&mdash;a copy of version 2.3 of the
+servlet specification is needed on the classpath to compile the Java code.</p>
 </body>
 </html>
-
diff --git a/manual/Tasks/junit.html b/manual/Tasks/junit.html
index a6879a8..f0e5c95 100644
--- a/manual/Tasks/junit.html
+++ b/manual/Tasks/junit.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,288 +15,228 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JUnit Task</title>
 </head>
 <body>
 
-<h2><a name="junit">JUnit</a></h2>
+<h2 id="junit">JUnit</h2>
 <h3>Description</h3>
 
-<p>This task runs tests from the JUnit testing framework. The latest
-version of the framework can be found at
-<a href="http://www.junit.org">http://www.junit.org</a>.
-This task has been tested with JUnit 3.0 up to JUnit 3.8.2; it won't
-work with versions prior to JUnit 3.0. It also works with JUnit 4.0, including
-"pure" JUnit 4 tests using only annotations and no <code>JUnit4TestAdapter</code>.</p>
-<p><strong>Note:</strong> This task depends on external libraries not included
+<p>This task runs tests from the JUnit testing framework. The latest version of the framework can be
+found at <a href="https://junit.org" target="_top">https://junit.org</a>.  This task has been tested
+with JUnit 3.0 up to JUnit 3.8.2; it won't work with versions prior to JUnit 3.0. It also works with
+JUnit 4.x, including "pure" JUnit 4 tests using only annotations and
+no <code>JUnit4TestAdapter</code>.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included
 in the Apache Ant distribution.  See <a href="../install.html#librarydependencies">
-Library Dependencies</a> for more information.
-</p>
-<p>
-<strong>Note</strong>:
-You must have <code>junit.jar</code> available.
-You can do one of:
-</p>
+Library Dependencies</a> for more information.</p>
+<p><strong>Note</strong>: You must have <samp>junit.jar</samp> available.  You can do one of:</p>
 <ol>
-<li>
-Put both <code>junit.jar</code> and <code>ant-junit.jar</code> in
-<code>ANT_HOME/lib</code>.
-</li>
-<li>
-Do not put either in <code>ANT_HOME/lib</code>, and instead
-include their locations in your <code>CLASSPATH</code> environment variable.
-</li>
-<li>
-Add both JARs to your classpath using <code>-lib</code>.
-</li>
-<li>
-Specify the locations of both JARs using
-a <code>&lt;classpath&gt;</code> element in a <code>&lt;taskdef&gt;</code> in the build file.
-</li>
-<li>
-Leave <code>ant-junit.jar</code> in its default location in <code>ANT_HOME/lib</code>
-but include <code>junit.jar</code> in the <code>&lt;classpath&gt;</code> passed
-to <code>&lt;junit&gt;</code>. <em>(since Ant 1.7)</em>
-</li>
+  <li>Put both <samp>junit.jar</samp> and <samp>ant-junit.jar</samp>
+    in <code>ANT_HOME/lib</code>.</li>
+  <li>Do not put either in <code>ANT_HOME/lib</code>, and instead include their locations in
+    your <code>CLASSPATH</code> environment variable.</li>
+  <li>Add both JARs to your classpath using <kbd>-lib</kbd>.</li>
+  <li>Specify the locations of both JARs using a <code>&lt;classpath&gt;</code> element in
+    a <code>&lt;taskdef&gt;</code> in the build file.</li>
+  <li>Leave <samp>ant-junit.jar</samp> in its default location in <code>ANT_HOME/lib</code> but
+    include <samp>junit.jar</samp> in the <code>&lt;classpath&gt;</code> passed
+    to <code>&lt;junit&gt;</code>. <em>Since Ant 1.7</em></li>
 </ol>
-<p>
-See <a href="http://ant.apache.org/faq.html#delegating-classloader" target="_top">the
-FAQ</a> for details.
-</p>
+<p>See <a href="https://ant.apache.org/faq.html#delegating-classloader" target="_top">the FAQ</a>
+for details.</p>
 
-<p>Tests are defined by nested <code>test</code> or
-<code>batchtest</code> tags (see <a href="#nested">nested
-elements</a>).</p>
+<p>Tests are defined by nested <code>test</code> or <code>batchtest</code> tags
+(see <a href="#nested">nested elements</a>).</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
+<table class="attr">
   <tr>
-    <td valign="top">printsummary</td>
-    <td valign="top">Print one-line statistics for each testcase. Can
-      take the values <code>on</code>,
-      <code>off</code>, and
-      <code>withOutAndErr</code>.
-      <code>withOutAndErr</code> is the same
-      as <code>on</code> but also includes the output of the test
-      as written to <code>System.out</code> and <code>System.err</code>.</td>
-    <td align="center" valign="top">No; default is <code>off</code>.</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">fork</td>
-    <td valign="top">Run the tests in a separate VM.</td>
-    <td align="center" valign="top">No; default is <code>off</code>.</td>
+    <td>printsummary</td>
+    <td>Print one-line statistics for each testcase. Can take the values <q>on</q>, <q>off</q>,
+      and <q>withOutAndErr</q>.  <q>withOutAndErr</q> is the same as <q>on</q> but also includes the
+      output of the test as written to <code>System.out</code> and <code>System.err</code>.</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">forkmode</td>
-    <td valign="top">Controls how many Java Virtual Machines get
-    created if you want to fork some tests.  Possible values are
-    &quot;perTest&quot; (the default), &quot;perBatch&quot; and
-    &quot;once&quot;.  &quot;once&quot; creates only a single Java VM
-    for all tests while &quot;perTest&quot; creates a new VM for each
-    TestCase class.  &quot;perBatch&quot; creates a VM for each nested
-    <code>&lt;batchtest&gt;</code> and one collecting all nested
-    <code>&lt;test&gt;</code>s.  Note that only tests with the same
-    settings of <code>filtertrace</code>, <code>haltonerror</code>,
-    <code>haltonfailure</code>, <code>errorproperty</code> and
-    <code>failureproperty</code> can share a VM, so even if you set
-    <code>forkmode</code> to &quot;once&quot;, Ant may have to create
-    more than a single Java VM.  This attribute is ignored for tests
-    that don't get forked into a new Java VM.  <em>since Ant 1.6.2</em></td>
-    <td align="center" valign="top">No; default is <code>perTest</code>.</td>
+    <td>fork</td>
+    <td>Run the tests in a separate JVM.</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">haltonerror</td>
-    <td valign="top">Stop the build process if an error occurs during the test
-       run.</td>
-    <td align="center" valign="top">No; default is <code>off</code>.</td>
-  </tr>
-<tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property to set in the event of an error.</td>
-    <td align="center" valign="top">No</td>
-</tr>
-  <tr>
-    <td valign="top">haltonfailure</td>
-    <td valign="top">Stop the build process if a test fails (errors are
-      considered failures as well).</td>
-    <td align="center" valign="top">No; default is <code>off</code>.</td>
-  </tr>
-<tr>
-    <td valign="top">failureproperty</td>
-    <td valign="top">The name of a property to set in the event of a failure
-      (errors are considered failures as well).</td>
-    <td align="center" valign="top">No.</td>
-</tr>
-  <tr>
-    <td valign="top">filtertrace</td>
-    <td valign="top">Filter out Junit and Ant stack frames from error and failure stack traces.</td>
-    <td align="center" valign="top">No; default is <code>on</code>.</td>
+    <td>forkmode</td>
+    <td>Controls how many JVMs get created if you want to fork some tests.  Possible values
+      are <q>perTest</q> (the default), <q>perBatch</q> and <q>once</q>.  <q>once</q> creates only a
+      single JVM for all tests while <q>perTest</q> creates a new JVM for each TestCase
+      class.  <q>perBatch</q> creates a JVM for each nested <code>&lt;batchtest&gt;</code> and one
+      collecting all nested <code>&lt;test&gt;</code>s.  Note that only tests with the same settings
+      of <var>filtertrace</var>, <var>haltonerror</var>, <var>haltonfailure</var>, <var>errorproperty</var>
+      and <var>failureproperty</var> can share a JVM, so even if you set <var>forkmode</var>
+      to <q>once</q>, Ant may have to create more than a single JVM.  This attribute is ignored for
+      tests that don't get forked into a new JVM.  <em>Since Ant 1.6.2</em></td>
+    <td>No; default is <q>perTest</q></td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Cancel the individual tests if they don't finish
-      in the given time (measured in milliseconds).  Ignored if
-      <code>fork</code> is disabled.  When running multiple tests
-      inside the same Java VM (see forkMode), timeout applies to the
-      time that all tests use together, not to an individual
-      test.</td>
-    <td align="center" valign="top">No</td>
+    <td>haltonerror</td>
+    <td>Stop the build process if an error occurs during the test run.</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Maximum amount of memory to allocate to the forked VM.
-      Ignored if <code>fork</code> is disabled. <strong>Note</strong>: 
-      If you get <code>java.lang.OutOfMemoryError: Java heap space</code>
-      in some of your tests then you need to raise the size like
-      <code>maxmemory="128m"</code></td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property to set in the event of an error.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">jvm</td>
-    <td valign="top">The command used to invoke the Java Virtual Machine,
-      default is 'java'.  The command is resolved by
-      <code>java.lang.Runtime.exec()</code>.
-      Ignored if <code>fork</code> is disabled.</td>
-    <td align="center" valign="top">No; default is <code>java</code>.</td>
+    <td>haltonfailure</td>
+    <td>Stop the build process if a test fails (errors are considered failures as well).</td>
+    <td>No; default is <q>off</q></td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The directory in which to invoke the VM. Ignored if
-      <code>fork</code> is disabled.</td>
-    <td align="center" valign="top">No</td>
+    <td>failureproperty</td>
+    <td>The name of a property to set in the event of a failure (errors are considered failures as
+      well).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">newenvironment</td>
-    <td valign="top">Do not propagate the old environment when new
-      environment variables are specified. Ignored if <code>fork</code> is
-      disabled.</td>
-    <td align="center" valign="top">No; default is <code>false</code>.</td>
+    <td>filtertrace</td>
+    <td>Filter out JUnit and Ant stack frames from error and failure stack traces.</td>
+    <td>No; default is <q>on</q></td>
   </tr>
   <tr>
-    <td valign="top">includeantruntime</td>
-    <td valign="top">Implicitly add the Ant classes required to run
-      the tests and JUnit to the classpath in forked mode.
-    </td>
-    <td align="center" valign="top">No; default is <code>true</code>.</td>
+    <td>timeout</td>
+    <td>Cancel the individual tests if they don't finish in the given time (measured in
+      milliseconds).  Ignored if <var>fork</var> is <q>off</q>.  When running multiple tests inside
+      the same JVM (see <var>forkMode</var>), <var>timeout</var> applies to the time that all tests
+      use together, not to an individual test.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">showoutput</td>
-    <td valign="top">Send any output generated by tests to Ant's
-      logging system as well as to the formatters.  By default only the
-      formatters receive the output.</td>
-    <td align="center" valign="top">No</td>
+    <td>maxmemory</td>
+    <td>Maximum amount of memory to allocate to the forked JVM.  Ignored if <var>fork</var>
+      is <q>off</q>. <strong>Note</strong>: If you get <code>java.lang.OutOfMemoryError: Java heap
+      space</code> in some of your tests then you need to raise the size
+      like <var>maxmemory</var>=<q>128m</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">outputtoformatters</td>
-    <td valign="top">
-      <em>Since Ant 1.7.0.</em><br/>
-      Send any output generated by tests to the test formatters.
-      This is "true" by default.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>jvm</td>
+    <td>The command used to invoke JVM.  The command is resolved
+      by <code>java.lang.Runtime.exec()</code>.</td>
+    <td>No; default is <kbd>java</kbd>, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">tempdir</td>
-    <td valign="top">Where Ant should place temporary files.
-      <em>Since Ant 1.6</em>.</td>
-    <td align="center" valign="top">No; default is the project's base
-      directory.</td>
+    <td>dir</td>
+    <td>The directory in which to invoke JVM.</td>
+    <td>No, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">reloading</td>
-    <td valign="top">Whether or not a new classloader should be instantiated for each test case.<br>
-    Ignore if <code>fork</code> is set to true.
-      <em>Since Ant 1.6</em>.</td>
-    <td align="center" valign="top">No; default is <code>true</code>.</td>
+    <td>newenvironment</td>
+    <td>Do not propagate the old environment when new environment variables are specified.</td>
+    <td>No; default is <q>false</q>, ignored if <var>fork</var> is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">clonevm</td>
-    <td valign="top">If set to true true, then all system properties
-      and the bootclasspath of the forked Java Virtual Machine will be
-      the same as those of the Java VM running Ant.  Default is
-      &quot;false&quot; (ignored if fork is disabled).
-      <em>since Ant 1.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>includeantruntime</td>
+    <td>Implicitly add the Ant classes required to run the tests and JUnit to the classpath in
+      forked mode.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">logfailedtests</td>
-    <td valign="top">When Ant executes multiple tests and doesn't stop
-      on errors or failures it will log a "FAILED" message for each
-      failing test to its logging system.  If you set this option to
-      false, the message will not be logged and you have to rely on the
-      formatter output to find the failing tests.
-      <em>since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
-  </tr>    
-  <tr>
-    <td valign="top">enableTestListenerEvents</td>
-    <td valign="top">Whether Ant should send fine grained information
-      about the running tests to Ant's logging system at the verbose
-      level.  Such events may be used by custom test listeners to show
-      the progress of tests.<br/>
-      Defaults to <code>false</code>.<br/>
-      Can be overridden by a <a href="#enabletestlistenerevents">magic
-        property</a>.<br/>
-      <em>since Ant 1.8.2</em> - <strong>Ant 1.7.0 to 1.8.1 behave as
-        if this attribute was true by default.</strong></td>
-    <td align="center" valign="top">No</td>
+    <td>showoutput</td>
+    <td>Send any output generated by tests to Ant's logging system as well as to the
+      formatters.</td>
+    <td>No; by default only the formatters receive the output</td>
   </tr>
   <tr>
-    <td valign="top">threads</td>
-    <td valign="top">a number of threads to run the tests in.<br/>
-      When this attribute is specified the tests will be split arbitrarily among the threads.<br/>
-      requires that the tests be forked with the <code>perTest</code>
-      option to be operative.<br/>
-      <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No</td>
+    <td>outputtoformatters</td>
+    <td>Send any output generated by tests to the test formatters.  <em>Since Ant 1.7.0</em>.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>tempdir</td>
+    <td>Where Ant should place temporary files.  <em>Since Ant 1.6</em>.</td>
+    <td>No; default is the project's <var>basedir</var></td>
+  </tr>
+  <tr>
+    <td>reloading</td>
+    <td>Whether or not a new classloader should be instantiated for each test case.<br/>Ignore
+      if <var>fork</var> is set to <q>true</q>.  <em>Since Ant 1.6</em>.</td>
+    <td>No; default is <code>true</code></td>
+  </tr>
+  <tr>
+    <td>clonevm</td>
+    <td>If set to <q>true</q>, then all system properties and the <var>bootclasspath</var> of the
+      forked JVM will be the same as those of the JVM running Ant.  <em>since Ant 1.7</em></td>
+    <td>No; default is <q>false</q>, ignored if <var>fork</var> is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>logfailedtests</td>
+    <td>When Ant executes multiple tests and doesn't stop on errors or failures it will log a
+      "FAILED" message for each failing test to its logging system.  If you set this option
+      to <q>false</q>, the message will not be logged and you have to rely on the formatter output
+      to find the failing tests.  <em>since Ant 1.8.0</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>enableTestListenerEvents</td>
+    <td>Whether Ant should send fine grained information about the running tests to Ant's logging
+      system at the verbose level.  Such events may be used by custom test listeners to show the
+      progress of tests.<br/><em>since Ant 1.8.2</em>&mdash;<strong>Ant 1.7.0 to 1.8.1 behave as if
+      this attribute was <q>true</q> by default.</strong></td>
+    <td>No; defaults to <q>false</q>, can be overridden by
+      a <a href="#enabletestlistenerevents">magic property</a></td>
+  </tr>
+  <tr>
+    <td>threads</td>
+    <td>a number of threads to run the tests in.<br/>When this attribute is specified the tests will
+      be split arbitrarily among the threads.<br/>Requires that the tests be forked with
+      the <q>perTest</q> option to be operative.<br/><em>since Ant 1.9.4</em></td>
+    <td>No</td>
   </tr>
 </table>
 
-<p>By using the <code>errorproperty</code> and <code>failureproperty</code>
-attributes, it is possible to
-perform setup work (such as starting an external server), execute the test,
-clean up, and still fail the build in the event of a failure.</p>
+<p>By using the <var>errorproperty</var> and <var>failureproperty</var> attributes, it is possible
+to perform setup work (such as starting an external server), execute the test, clean up, and still
+fail the build in the event of a failure.</p>
 
-<p>The <code>filtertrace</code> attribute condenses error and failure
-stack traces before reporting them.
-It works with both the plain and XML formatters.  It filters out any lines
-that begin with the following string patterns:<pre>
-   "junit.framework.TestCase"
-   "junit.framework.TestResult"
-   "junit.framework.TestSuite"
-   "junit.framework.Assert."
-   "junit.swingui.TestRunner"
-   "junit.awtui.TestRunner"
-   "junit.textui.TestRunner"
-   "java.lang.reflect.Method.invoke("
-   "sun.reflect."
-   "org.apache.tools.ant."
-   "org.junit."
-   "junit.framework.JUnit4TestAdapter"
-   " more"</pre>
+<p>The <var>filtertrace</var> attribute condenses error and failure stack traces before reporting
+them.  It works with both the plain and XML formatters.  It filters out any lines that begin with
+the following string patterns:</p>
 
-<h3><a name="nested">Nested Elements</a></h3>
+<pre>
+   &quot;junit.framework.TestCase&quot;
+   &quot;junit.framework.TestResult&quot;
+   &quot;junit.framework.TestSuite&quot;
+   &quot;junit.framework.Assert.&quot;
+   &quot;junit.swingui.TestRunner&quot;
+   &quot;junit.awtui.TestRunner&quot;
+   &quot;junit.textui.TestRunner&quot;
+   &quot;java.lang.reflect.Method.invoke(&quot;
+   &quot;sun.reflect.&quot;
+   &quot;org.apache.tools.ant.&quot;
+   &quot;org.junit.&quot;
+   &quot;junit.framework.JUnit4TestAdapter&quot;
+   &quot; more&quot;</pre>
 
-<p>The <code>&lt;junit&gt;</code> task
-supports a nested <code>&lt;classpath&gt;</code>
-element that represents a <a href="../using.html#path">PATH like
-structure</a>.</p>
+<h3 id="nested">Parameters specified as nested elements</h3>
 
-<p>As of Ant 1.7, this classpath may be used to refer to <code>junit.jar</code>
-as well as your tests and the tested code.
+<p>The <code>&lt;junit&gt;</code> task supports a nested <code>&lt;classpath&gt;</code> element that
+represents a <a href="../using.html#path">path-like structure</a>.</p>
+
+<p><em>Since Ant 1.7</em>, this classpath may be used to refer to <samp>junit.jar</samp> as well as
+your tests and the tested code.</p>
 
 <h4>jvmarg</h4>
 
-<p>If <code>fork</code> is enabled, additional parameters may be passed to
-the new VM via nested <code>&lt;jvmarg&gt;</code> elements. For example:</p>
+<p>If <var>fork</var> is <q>true</q>, additional parameters may be passed to the new JVM via
+nested <code>&lt;jvmarg&gt;</code> elements. For example:</p>
 
 <pre>
 &lt;junit fork=&quot;yes&quot;&gt;
@@ -304,18 +245,17 @@
 &lt;/junit&gt;
 </pre>
 
-<p>would run the test in a VM without JIT.</p>
+<p>would run the test in a JVM without JIT.</p>
 
-<p><code>&lt;jvmarg&gt;</code> allows all attributes described in <a
-href="../using.html#arg">Command-line Arguments</a>.</p>
+<p><code>&lt;jvmarg&gt;</code> allows all attributes described
+in <a href="../using.html#arg">Command-line Arguments</a>.</p>
 
 <h4>sysproperty</h4>
 
-<p>Use nested <code>&lt;sysproperty&gt;</code> elements to specify system
-properties required by the class. These properties will be made available
-to the VM during the execution of the test (either ANT's VM or the forked VM,
-if <code>fork</code> is enabled).
-The attributes for this element are the same as for <a href="../Tasks/exec.html#env">environment variables</a>.</p>
+<p>Use nested <code>&lt;sysproperty&gt;</code> elements to specify system properties required by the
+class. These properties will be made available to JVM during the execution of the test (either Ant's
+JVM or the forked JVM, if <var>fork</var>=<q>true</q>).  The attributes for this element are the
+same as for <a href="../Tasks/exec.html#env">environment variables</a>.</p>
 
 <pre>
 &lt;junit fork=&quot;no&quot;&gt;
@@ -324,369 +264,351 @@
 &lt;/junit&gt;
 </pre>
 
-<p>would run the test in ANT's VM and make the <code>basedir</code> property
-available to the test.</p>
+<p>would run the test in Ant's JVM and make the <code>basedir</code> property available to the
+test.</p>
 
 <h4>syspropertyset</h4>
 
+<p><em>Since Ant 1.6</em></p>
+
 <p>You can specify a set of properties to be used as system properties
 with <a href="../Types/propertyset.html">syspropertyset</a>s.</p>
 
-<p><em>since Ant 1.6</em>.</p>
-
 <h4>env</h4>
 
-<p>It is possible to specify environment variables to pass to the
-forked VM via nested <code>&lt;env&gt;</code> elements. For a description
-of the <code>&lt;env&gt;</code> element's attributes, see the
-description in the <a href="../Tasks/exec.html#env">exec</a> task.</p>
+<p>It is possible to specify environment variables to pass to the forked JVM via
+nested <code>&lt;env&gt;</code> elements. For a description of the <code>&lt;env&gt;</code>
+element's attributes, see the description in the <a href="../Tasks/exec.html#env">exec</a> task.</p>
 
-<p>Settings will be ignored if <code>fork</code> is disabled.</p>
+<p>Settings will be ignored if <var>fork</var>=<q>false</q>.</p>
 
 <h4>bootclasspath</h4>
 
-<p>The location of bootstrap class files can be specified using this
-<a href="../using.html#path">PATH like structure</a> - will be ignored
-if <i>fork</i> is not <code>true</code> or the target VM doesn't
-support it (i.e. Java 1.1).</p>
+<p><em>Since Ant 1.6</em>.</p>
 
-<p><em>since Ant 1.6</em>.</p>
+<p>The location of bootstrap class files can be specified using
+this <a href="../using.html#path">path-like structure</a>&mdash;will be ignored if <var>fork</var>
+is <q>false</q> or the target JVM doesn't support it (i.e. Java 1.1).</p>
 
 <h4>permissions</h4>
-<p>Security permissions can be revoked and granted during the execution of the 
-class via a nested <i>permissions</i> element. For more information please
+
+<p><em>Since Ant 1.6</em>.</p>
+
+<p>Security permissions can be revoked and granted during the execution of the class via a
+nested <code>permissions</code> element. For more information please
 see <a href="../Types/permissions.html">permissions</a></p>
 
-<p>Settings will be ignored if fork is enabled.</p>
+<p>Settings will be ignored if <var>fork</var>=<q>true</q>.</p>
 
-<p><em>since Ant 1.6</em>.</p>
- 
 <h4>assertions</h4>
 
-<p>You can control enablement of Java 1.4 assertions with an
-<a href="../Types/assertions.html"><tt>&lt;assertions&gt;</tt></a>
-subelement.</p>
- 
-<p>Assertion statements are currently ignored in non-forked mode.</p>
+<p><em>Since Ant 1.6</em>.</p>
 
-<p><em>since Ant 1.6.</em></p>
+<p>You can control enablement of Java 1.4 assertions with
+an <a href="../Types/assertions.html"><code>&lt;assertions&gt;</code></a> subelement.</p>
+
+<p>Assertion statements are currently ignored in non-forked mode.</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.9.8</em></p>
 
-<p><em>since Ant 1.9.8</em></p>
+<p>The location of modules can be specified using this <a href="../using.html#path">path-like
+structure</a>.<br/>The <code>modulepath</code> requires <var>fork</var> to be set to <q>true</q>.
 
 <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.9.8</em></p>
 
-<p><em>since Ant 1.9.8</em></p>
+<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 <code>upgrademodulepath</code> requires <var>fork</var> to be set
+to <q>true</q>.</p>
 
 <h4>formatter</h4>
 
-<p>The results of the tests can be printed in different
-formats. Output will always be sent to a file, unless you set the
-<code>usefile</code> attribute to <code>false</code>.
-The name of the file is determined by the
-name of the test and can be set by the <code>outfile</code> attribute
+<p>The results of the tests can be printed in different formats. Output will always be sent to a
+file, unless you set the <var>usefile</var> attribute to <q>false</q>.  The name of the file is
+determined by the name of the test and can be set by the <var>outfile</var> attribute
 of <code>&lt;test&gt;</code>.</p>
 
-<p>There are four predefined formatters - one prints the test results
-in XML format, the other emits plain text.  The formatter named
-<code>brief</code> will only print detailed information for testcases
-that failed, while <code>plain</code> gives a little statistics line
-for all test cases.  Custom formatters that need to implement
-<code>org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter</code>
+<p>There are four predefined formatters&mdash;one prints the test results in XML format, the other
+emits plain text.  The formatter named <q>brief</q> will only print detailed information for test
+cases that failed, while <q>plain</q> gives a little statistics line for all test cases.  Custom
+formatters that need to
+implement <code class="code">org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter</code>
 can be specified.</p>
 
-<p>If you use the XML formatter, it may not include the same output
-that your tests have written as some characters are illegal in XML
-documents and will be dropped.</p>
+<p>If you use the XML formatter, it may not include the same output that your tests have written as
+some characters are illegal in XML documents and will be dropped.</p>
 
-<p>The fourth formatter named <code>failure</code> (since Ant 1.8.0) 
-collects all failing <code>testXXX()</code>
-methods and creates a new <code>TestCase</code> which delegates only these
-failing methods. The name and the location can be specified via Java System property or Ant property
-<code>ant.junit.failureCollector</code>. The value has to point to the directory and 
-the name of the resulting class (without suffix). It defaults to <i>java-tmp-dir</i>/FailedTests.</p>
+<p>The fourth formatter named <q>failure</q> (<em>since Ant 1.8.0</em>) collects all
+failing <code class="code">testXXX()</code> methods and creates a
+new <code class="code">TestCase</code> which delegates only these failing methods. The name and the
+location can be specified via Java system property or Ant
+property <code>ant.junit.failureCollector</code>. The value has to point to the directory and the
+name of the resulting class (without suffix). It defaults
+to <samp><i>java-tmp-dir</i>/FailedTests</samp>.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">Use a predefined formatter (either
-      <code>xml</code>, <code>plain</code>, <code>brief</code> or <code>failure</code>).</td>
-    <td align="center" rowspan="2">Exactly one of these.</td>
+    <td>type</td>
+    <td>Use a predefined formatter (either <q>xml</q>, <q>plain</q>, <q>brief</q>
+      or <q>failure</q>).</td>
+    <td rowspan="2">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">Name of a custom formatter class.</td>
+    <td>classname</td>
+    <td class="left">Name of a custom formatter class.</td>
   </tr>
   <tr>
-    <td valign="top">extension</td>
-    <td valign="top">Extension to append to the output filename.</td>
-    <td align="center">Yes, if <code>classname</code> has been used.</td>
+    <td>extension</td>
+    <td>Extension to append to the output filename.</td>
+    <td>Yes, if <var>classname</var> has been used</td>
   </tr>
   <tr>
-    <td valign="top">usefile</td>
-    <td valign="top">Boolean that determines whether output should be
-      sent to a file.</td>
-    <td align="center">No; default is <code>true</code>.</td>
+    <td>usefile</td>
+    <td>Boolean that determines whether output should be sent to a file.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">Only use formatter <a href="../properties.html#if+unless">if the named property is set</a>.</td>
-    <td align="center">No; default is <code>true</code>.</td>
+    <td>if</td>
+    <td>Only use formatter <a href="../properties.html#if+unless">if the named property is
+      set</a>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">Only use formatter <a href="../properties.html#if+unless">if the named property is <b>not</b> set</a>.</td>
-    <td align="center">No; default is <code>true</code>.</td>
-  </tr>  
+    <td>unless</td>
+    <td>Only use formatter <a href="../properties.html#if+unless">if the named property
+      is <strong>not</strong> set</a>.</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
 </table>
 
 <h4>test</h4>
 
 <p>Defines a single test class.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
+<table class="attr">
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Name of the test class.</td>
-    <td align="center">Yes</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">methods</td>
-    <td valign="top">Comma-separated list of names of test case methods to execute.
-      <em>Since 1.8.2</em>
-      <p>The <code>methods</code> attribute can be useful in the following scenarios:</p>
+    <td>name</td>
+    <td>Name of the test class.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>methods</td>
+    <td>Comma-separated list of names of test case methods to execute.  <em>Since 1.8.2</em>
+      <p>The <var>methods</var> attribute can be useful in the followiang scenarios:</p>
       <ul>
-        <li>A test method has failed and you want to re-run the test method
-            to test a fix or re-run the test under the Java debugger without
-            having to wait for the other (possibly long running) test methods
-            to complete.</li>
-        <li>One or more test methods are running slower than expected and you
-            want to re-run them under a Java profiler (without the overhead
-            of running the profiler whilst other test methods are being
-            executed).</li>
+        <li>A test method has failed and you want to re-run the test method to test a fix or re-run
+          the test under the Java debugger without having to wait for the other (possibly long
+          running) test methods to complete.</li>
+        <li>One or more test methods are running slower than expected and you want to re-run them
+          under a Java profiler (without the overhead of running the profiler whilst other test
+          methods are being executed).</li>
       </ul>
-      <p>If the <code>methods</code> attribute is used but no test method
-      is specified, then no test method from the suite will be executed.</p>
+      <p>If the <var>methods</var> attribute is used but no test method is specified, then no test
+        method from the suite will be executed.</p>
     </td>
-    <td align="center">No; default is to run all test methods in the suite.</td>
-  </tr>  
-  <tr>
-    <td valign="top">fork</td>
-    <td valign="top">Run the tests in a separate VM.
-      Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>No; default is to run all test methods in the suite</td>
   </tr>
   <tr>
-    <td valign="top">haltonerror</td>
-    <td valign="top">Stop the build process if an error occurs during the test
-       run. Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-<tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property to set in the event of an error.
-      Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-</tr>
-  <tr>
-    <td valign="top">haltonfailure</td>
-    <td valign="top">Stop the build process if a test fails (errors are
-      considered failures as well).  Overrides value set in
-      <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-<tr>
-    <td valign="top">failureproperty</td>
-    <td valign="top">The name of a property to set in the event of a failure
-      (errors are considered failures as well). Overrides value set in
-      <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-</tr>
-  <tr>
-    <td valign="top">filtertrace</td>
-    <td valign="top">Filter out Junit and Ant stack frames from error and failure stack
-    traces.  Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No; default is <code>on</code>.</td>
+    <td>fork</td>
+    <td>Run the tests in a separate JVM.  Overrides value set in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">Directory to write the reports to.</td>
-    <td align="center" valign="top">No; default is the current directory.</td>
+    <td>haltonerror</td>
+    <td>Stop the build process if an error occurs during the test run. Overrides value set
+       in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">outfile</td>
-    <td valign="top">Base name of the test result. The full filename is
-      determined by this attribute and the extension of
-      <code>formatter</code>.</td>
-    <td align="center" valign="top">No; default is
-      <code>TEST-</code><em>name</em>, where <em>name</em> is the name of
-      the test specified in the <code>name</code> attribute.</td>
+    <td>errorproperty</td>
+    <td>The name of a property to set in the event of an error.  Overrides value set
+      in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">Only run test <a href="../properties.html#if+unless">if the named property is set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>haltonfailure</td>
+    <td>Stop the build process if a test fails (errors are considered failures as well).  Overrides
+      value set in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">Only run test <a href="../properties.html#if+unless">if the named property is <b>not</b> set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>failureproperty</td>
+    <td>The name of a property to set in the event of a failure (errors are considered failures as
+      well). Overrides value set in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">skipNonTests</td>
-    <td valign="top">Do not pass any classes that do not contain JUnit tests to the test runner.
-          This prevents non tests from appearing as test errors in test results.<br />
-          Tests are identified by looking for the <code>@Test</code> annotation on any methods in concrete classes
-          that don't extend <code>junit.framework.TestCase</code>, or for public/protected methods with
-          names starting with 'test' in concrete classes that extend <code>junit.framework.TestCase</code>.
-          Classes marked with the JUnit4 <code>org.junit.runner.RunWith</code> or
-          <code>org.junit.runner.Suite.SuiteClasses</code> annotations are also passed to JUnit for execution,
-          as is any class with a public/protected no-argument <code>suite</code> method.</td>
-    <td align="center" valign="top">No. Default is false.</td>
+    <td>filtertrace</td>
+    <td>Filter out JUnit and Ant stack frames from error and failure stack traces.  Overrides value
+      set in <code>&lt;junit&gt;</code>.</td>
+    <td>No; default is <q>on</q></td>
+  </tr>
+  <tr>
+    <td>todir</td>
+    <td>Directory to write the reports to.</td>
+    <td>No; default is the current directory</td>
+  </tr>
+  <tr>
+    <td>outfile</td>
+    <td>Base name of the test result. The full filename
+    is <var>outfile</var>.<var>formatter</var>.</td>
+    <td>No; default is <samp>TEST-</samp><var>name</var></td>
+  </tr>
+  <tr>
+    <td>if</td>
+    <td>Only run test <a href="../properties.html#if+unless">if the named property is set</a>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>unless</td>
+    <td>Only run test <a href="../properties.html#if+unless">if the named property
+    is <strong>not</strong> set</a>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>skipNonTests</td>
+    <td>Do not pass any classes that do not contain JUnit tests to the test runner.  This prevents
+      non tests from appearing as test errors in test results.<br/>Tests are identified by looking
+      for the <code>@Test</code> annotation on any methods in concrete classes that don't
+      extend <code>junit.framework.TestCase</code>, or for public/protected methods with names
+      starting with <q>test</q> in concrete classes that
+      extend <code>junit.framework.TestCase</code>.  Classes marked with the JUnit
+      4 <code>org.junit.runner.RunWith</code> or <code>org.junit.runner.Suite.SuiteClasses</code>
+      annotations are also passed to JUnit for execution, as is any class with a public/protected
+      no-argument <code>suite()</code> method.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
-<p>Tests can define their own formatters via nested
-<code>&lt;formatter&gt;</code> elements.</p>
+<p>Tests can define their own formatters via nested <code>&lt;formatter&gt;</code> elements.</p>
 
 <h4>batchtest</h4>
 
 <p>Define a number of tests based on pattern matching.</p>
 
-<p><code>batchtest</code> collects the included <a href="../Types/resources.html">resources</a> from any number
-of nested <a
-href="../Types/resources.html#collection">Resource Collection</a>s. It then
-generates a test class name for each resource that ends in
-<code>.java</code> or <code>.class</code>.</p>
+<p><code>batchtest</code> collects the included <a href="../Types/resources.html">resources</a> from
+any number of nested <a href="../Types/resources.html#collection">resource collections</a>. It then
+generates a test class name for each resource that ends in <samp>.java</samp>
+or <samp>.class</samp>.</p>
 
-<p>Any type of Resource Collection is supported as a nested element,
-prior to Ant 1.7 only <code>&lt;fileset&gt;</code> has been
-supported.</p>
+<p>Any type of resource collection is supported as a nested element, prior to Ant 1.7
+only <code>&lt;fileset&gt;</code> has been supported.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
+<table class="attr">
   <tr>
-    <td valign="top">fork</td>
-    <td valign="top">Run the tests in a separate VM.
-      Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">haltonerror</td>
-    <td valign="top">Stop the build process if an error occurs during the test
-       run. Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-<tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property to set in the event of an error.
-      Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-</tr>
-  <tr>
-    <td valign="top">haltonfailure</td>
-    <td valign="top">Stop the build process if a test fails (errors are
-      considered failures as well).  Overrides value set in
-      <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-<tr>
-    <td valign="top">failureproperty</td>
-    <td valign="top">The name of a property to set in the event of a failure
-      (errors are considered failures as well). Overrides value set in
-      <code>&lt;junit&gt;</code></td>
-    <td align="center" valign="top">No</td>
-</tr>
-  <tr>
-    <td valign="top">filtertrace</td>
-    <td valign="top">Filter out Junit and Ant stack frames from error and failure stack
-    traces.  Overrides value set in <code>&lt;junit&gt;</code>.</td>
-    <td align="center" valign="top">No; default is <code>on</code>.</td>
+    <td>fork</td>
+    <td>Run the tests in a separate JVM.  Overrides value set in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">Directory to write the reports to.</td>
-    <td align="center" valign="top">No; default is the current directory.</td>
+    <td>haltonerror</td>
+    <td>Stop the build process if an error occurs during the test run. Overrides value set
+      in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">Only run tests <a href="../properties.html#if+unless">if the named property is set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property to set in the event of an error.  Overrides value set
+      in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">Only run tests <a href="../properties.html#if+unless">if the named property is <strong>not</strong> set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>haltonfailure</td>
+    <td>Stop the build process if a test fails (errors are considered failures as well).  Overrides
+      value set in <code>&lt;junit&gt;</code>.</td>
+    <td>No</td>
   </tr>
   <tr>
-      <td valign="top">skipNonTests</td>
-      <td valign="top">Do not pass any classes that do not contain JUnit tests to the test runner.
-                          This prevents non tests from appearing as test errors in test results.<br />
-                          Tests are identified by looking for the <code>@Test</code> annotation on any methods in concrete classes
-                          that don't extend <code>junit.framework.TestCase</code>, or for public/protected methods with
-                          names starting with 'test' in concrete classes that extend <code>junit.framework.TestCase</code>.
-                          Classes marked with the JUnit4 <code>org.junit.runner.RunWith</code> or
-                          <code>org.junit.runner.Suite.SuiteClasses</code> annotations are also passed to JUnit for execution,
-                          as is any class with a public/protected no-argument <code>suite</code> method.</td>
-      <td align="center" valign="top">No. Default is false.</td>
+    <td>failureproperty</td>
+    <td>The name of a property to set in the event of a failure (errors are considered failures as
+      well). Overrides value set in <code>&lt;junit&gt;</code></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>filtertrace</td>
+    <td>Filter out JUnit and Ant stack frames from error and failure stack traces.  Overrides value
+      set in <code>&lt;junit&gt;</code>.</td>
+    <td>No; default is <q>on</q></td>
+  </tr>
+  <tr>
+    <td>todir</td>
+    <td>Directory to write the reports to.</td>
+    <td>No; default is the current directory</td>
+  </tr>
+  <tr>
+    <td>if</td>
+    <td>Only run tests <a href="../properties.html#if+unless">if the named property is set</a>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>unless</td>
+    <td>Only run tests <a href="../properties.html#if+unless">if the named property
+      is <strong>not</strong> set</a>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>skipNonTests</td>
+    <td>Do not pass any classes that do not contain JUnit tests to the test runner.  This prevents
+      non tests from appearing as test errors in test results.<br/>Tests are identified by looking
+      for the <code>@Test</code> annotation on any methods in concrete classes that don't
+      extend <code>junit.framework.TestCase</code>, or for public/protected methods with names
+      starting with <q>test</q> in concrete classes that
+      extend <code>junit.framework.TestCase</code>.  Classes marked with the JUnit
+      4 <code>org.junit.runner.RunWith</code> or <code>org.junit.runner.Suite.SuiteClasses</code>
+      annotations are also passed to JUnit for execution, as is any class with a public/protected
+      no-argument <code>suite()</code> method.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
-<p>Batchtests can define their own formatters via nested
-<code>&lt;formatter&gt;</code> elements.</p>
+<p>Batch tests can define their own formatters via nested <code>&lt;formatter&gt;</code>
+elements.</p>
 
-<h3>Forked tests and <code>tearDown</code></h3>
+<h3>Forked tests and <code>tearDown()</code></h3>
 
-<p>If a forked test runs into a timeout, Ant will terminate the Java
-  VM process it has created, which probably means the
-  test's <code>tearDown</code> method will never be called.  The same
-  is true if the forked VM crashes for some other reason.</p>
+<p>If a forked test runs into a timeout, Ant will terminate the JVM process it has created, which
+probably means the test's <code class="code">tearDown()</code> method will never be called.  The
+same is true if the forked JVM crashes for some other reason.</p>
 
-<p>Starting with Ant 1.8.0, a special formatter is distributed with
-  Ant that tries to load the testcase that was in the forked VM and
-  invoke that class' <code>tearDown</code> method.  This formatter has
-  the following limitations:</p>
+<p><em>Since Ant 1.8.0</em>, a special formatter is distributed with Ant that tries to load the
+testcase that was in the forked JVM and invoke that class' <code class="code">tearDown()</code>
+method.  This formatter has the following limitations:</p>
 
 <ul>
-  <li>It runs in the same Java VM as Ant itself, this is a different
-    Java VM than the one that was executing the test and it may see a
-    different classloader (and thus may be unable to load the test
+  <li>It runs in the same JVM as Ant itself, this is a different JVM than the one that was executing
+    the test and it may see a different classloader (and thus may be unable to load the test
     class).</li>
-  <li>It cannot determine which test was run when the timeout/crash
-    occurred if the forked VM was running multiple test.  I.e. the
-    formatter cannot work with any <code>forkMode</code> other
-    than <code>perTest</code> and it won't do anything if the test
-    class contains a <code>suite()</code> method.</li>
+  <li>It cannot determine which test was run when the timeout/crash occurred if the forked JVM was
+    running multiple tests.  I.e. the formatter cannot work with any <var>forkMode</var> other
+    than <q>perTest</q> and it won't do anything if the test class contains
+    a <code class="code">suite()</code> method.</li>
 </ul>
 
-<p>If the formatter recognizes an incompatible <code>forkMode</code>
-  or a <code>suite</code> method or fails to load the test class it
-  will silently do nothing.</p>
+<p>If the formatter recognizes an incompatible <var>forkMode</var> or
+a <code class="code">suite()</code> method or fails to load the test class it will silently do
+nothing.</p>
 
-<p>The formatter doesn't have any effect on tests that were not
-  forked or didn't cause timeouts or VM crashes.</p>
+<p>The formatter doesn't have any effect on tests that were not forked or didn't cause timeouts or
+JVM crashes.</p>
 
 <p>To enable the formatter, add a <code>formatter</code> like</p>
 
@@ -697,77 +619,70 @@
 
 <p>to your <code>junit</code> task.</p>
 
-<h3><a name="enabletestlistenerevents"><code>ant.junit.enabletestlistenerevents</code></a>
-  magic property</h3>
+<h3 id="enabletestlistenerevents"><code>ant.junit.enabletestlistenerevents</code> magic property</h3>
 
-<p><em>Since Ant 1.8.2</em> the <code>enableTestListenerEvents</code>
-  attribute of the task controls whether fine grained logging messages
-  will be sent to the task's verbose log.  In addition to this
-  attribute Ant will consult the
-  property <code>ant.junit.enabletestlistenerevents</code> and the
-  value of the property overrides the setting of the attribute.</p>
+<p><em>Since Ant 1.8.2</em> the <var>enableTestListenerEvents</var> attribute of the task controls
+whether fine grained logging messages will be sent to the task's verbose log.  In addition to this
+attribute Ant will consult the property <code>ant.junit.enabletestlistenerevents</code> and the
+value of the property overrides the setting of the attribute.</p>
 
-<p>This property exists so that containers running Ant that depend on
-  the additional logging events can ensure they will be generated even
-  if the build file disables them.</p>
+<p>This property exists so that containers running Ant that depend on the additional logging events
+can ensure they will be generated even if the build file disables them.</p>
 
 <h3>Examples</h3>
 
+<p>Run the test defined in <code>my.test.TestCase</code> in the same VM. No output will be generated
+unless the test fails.</p>
 <pre>
 &lt;junit&gt;
-  &lt;test name="my.test.TestCase"/&gt;
-&lt;/junit&gt;
-</pre>
+    &lt;test name="my.test.TestCase"/&gt;
+&lt;/junit&gt;</pre>
 
-<p>Runs the test defined in <code>my.test.TestCase</code> in the same
-VM. No output will be generated unless the test fails.</p>
-
+<p>Run the test defined in <code>my.test.TestCase</code> in a separate JVM. At the end of the test,
+a one-line summary will be printed. A detailed report of the test can be found
+in <samp>TEST-my.test.TestCase.txt</samp>. The build process will be stopped if the test fails.</p>
 <pre>
 &lt;junit printsummary="yes" fork="yes" haltonfailure="yes"&gt;
-  &lt;formatter type="plain"/&gt;
-  &lt;test name="my.test.TestCase"/&gt;
-&lt;/junit&gt;
-</pre>
+    &lt;formatter type="plain"/&gt;
+    &lt;test name="my.test.TestCase"/&gt;
+&lt;/junit&gt;</pre>
 
-<p>Runs the test defined in <code>my.test.TestCase</code> in a
-separate VM.  At the end of the test, a one-line summary will be
-printed. A detailed report of the test can be found in
-<code>TEST-my.test.TestCase.txt</code>. The build process will be
-stopped if the test fails.</p>
-
+<p>Run <code>my.test.TestCase</code> in the same JVM, ignoring the given <code>CLASSPATH</code>;
+only a warning is printed if this test fails. In addition to the plain text test results, for this
+test a XML result will be output to <samp>result.xml</samp>. Then, for each matching file in the
+directory defined for <samp>${src.tests}</samp>, a test is run in a separate JVM. If a test fails,
+the build process is aborted. Results are collected in files
+named <samp>TEST-</samp><var>name</var><samp>.txt</samp> and written
+to <samp>${reports.tests}</samp>.</p>
 <pre>
 &lt;junit printsummary="yes" haltonfailure="yes"&gt;
-  &lt;classpath&gt;
-    &lt;pathelement location="${build.tests}"/&gt;
-    &lt;pathelement path="${java.class.path}"/&gt;
-  &lt;/classpath&gt;
+    &lt;classpath&gt;
+        &lt;pathelement location="${build.tests}"/&gt;
+        &lt;pathelement path="${java.class.path}"/&gt;
+    &lt;/classpath&gt;
 
-  &lt;formatter type="plain"/&gt;
+    &lt;formatter type="plain"/&gt;
 
-  &lt;test name="my.test.TestCase" haltonfailure="no" outfile="result"&gt;
-    &lt;formatter type="xml"/&gt;
-  &lt;/test&gt;
+    &lt;test name="my.test.TestCase" haltonfailure="no" outfile="result"&gt;
+        &lt;formatter type="xml"/&gt;
+    &lt;/test&gt;
 
-  &lt;batchtest fork="yes" todir="${reports.tests}"&gt;
-    &lt;fileset dir="${src.tests}"&gt;
-      &lt;include name="**/*Test*.java"/&gt;
-      &lt;exclude name="**/AllTests.java"/&gt;
-    &lt;/fileset&gt;
-  &lt;/batchtest&gt;
-&lt;/junit&gt;
-</pre>
+    &lt;batchtest fork="yes" todir="${reports.tests}"&gt;
+        &lt;fileset dir="${src.tests}"&gt;
+            &lt;include name="**/*Test*.java"/&gt;
+            &lt;exclude name="**/AllTests.java"/&gt;
+        &lt;/fileset&gt;
+    &lt;/batchtest&gt;
+&lt;/junit&gt;</pre>
 
-<p>Runs <code>my.test.TestCase</code> in the same VM, ignoring the
-given CLASSPATH; only a warning is printed if this test fails. In
-addition to the plain text test results, for this test a XML result
-will be output to <code>result.xml</code>.  
-Then, for each matching file in the directory defined for
-<code>${src.tests}</code> a
-test is run in a separate VM. If a test fails, the build process is
-aborted. Results are collected in files named
-<code>TEST-</code><em>name</em><code>.txt</code> and written to
-<code>${reports.tests}</code>.</p>
-
+<p>On the first run, all tests are collected via the <code>&lt;batchtest/&gt;</code>
+element. Its <var>plain</var> formatter shows the output on the console. The <var>failure</var>
+formatter creates a Java source file in <samp>${build.dir}/failingTests/FailedTests.java</samp>
+which extends <code class="code">junit.framework.TestCase</code> and returns from
+a <code class="code">suite()</code> method a test suite for the failing tests.<br/>On a second run
+the collector class exists and instead of the <code>&lt;batchtest/&gt;</code> the
+single <code>&lt;test/&gt;</code> will run. So only the failing test cases are re-run. The two
+nested formatters are for displaying (for the user) and for updating the collector class.</p>
 <pre>
 &lt;target name=&quot;test&quot;&gt;
     &lt;property name=&quot;collector.dir&quot; value=&quot;${build.dir}/failingTests&quot;/&gt;
@@ -776,7 +691,7 @@
     &lt;delete&gt;
         &lt;fileset dir=&quot;${collector.dir}&quot; includes=&quot;${collector.class}*.class&quot;/&gt;
     &lt;/delete&gt;
-    &lt;!-- compile the FailedTests class if present --&gt; 
+    &lt;!-- compile the FailedTests class if present --&gt;
     &lt;javac srcdir=&quot;${collector.dir}&quot; destdir=&quot;${collector.dir}&quot;/&gt;
     &lt;available file=&quot;${collector.dir}/${collector.class}.class&quot; property=&quot;hasFailingTests&quot;/&gt;
     &lt;junit haltonerror=&quot;false&quot; haltonfailure=&quot;false&quot;&gt;
@@ -798,60 +713,52 @@
             &lt;formatter type=&quot;plain&quot; usefile=&quot;false&quot;/&gt;
         &lt;/test&gt;
     &lt;/junit&gt;
-&lt;/target&gt;
-</pre>
-<p>On the first run all tests are collected via the <code>&lt;batchtest/&gt;</code>
-element. Its <code>plain</code> formatter shows the output on the console. The
-<code>failure</code> formatter creates a java source file in 
-<code>${build.dir}/failingTests/FailedTests.java</code> which extends 
-<code>junit.framework.TestCase</code> and returns from a <code>suite()</code>
-method a test suite for the failing tests. <br/>
-On a second run the collector class exists and instead of the <code>&lt;batchtest/&gt;</code>
-the single <code>&lt;test/&gt;</code> will run. So only the failing test cases are re-run.
-The two nested formatters are for displaying (for the user) and for updating the collector
-class.
-</p>
+&lt;/target&gt;</pre>
+
+<p>Run <code>my.test.TestCase</code> as a white-box test in the forked JVM 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 <kbd>--patch-module</kbd> Java option executes the tests built
+into <samp>${build.test.classes}</samp> in a module given by <code>module.name</code>
+property.<br/>The <kbd>--add-modules</kbd> Java option enables the tested
+module.<br/>The <kbd>--add-reads</kbd> Java option makes the unnamed module containing JUnit
+readable by tested module.<br/>The <kbd>--add-exports</kbd> Java option makes the non-exported test
+package <code>my.test</code> accessible from the unnamed module containing JUnit.</p>
 <pre>
-    &lt;junit fork="true"
-        jvm="${platform.java}"&gt;
-        &lt;jvmarg line="--patch-module ${module.name}=${build.test.classes}"/&gt;
-        &lt;jvmarg line="--add-modules ${module.name}"/&gt;
-        &lt;jvmarg line="--add-reads ${module.name}=ALL-UNNAMED"/&gt;
-        &lt;jvmarg line="--add-exports ${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>--patch-module</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>--add-modules</code> java option enables the tested module.<br/>
-The <code>--add-reads</code> java option makes the unnamed module containing the junit readable by tested module.<br/>
-The <code>--add-exports</code> java option makes the non-exported test package <code>my.test</code> accessible from the unnamed module containing the junit.<br/>
+&lt;junit fork="true"
+       jvm="${platform.java}"&gt;
+    &lt;jvmarg line="--patch-module ${module.name}=${build.test.classes}"/&gt;
+    &lt;jvmarg line="--add-modules ${module.name}"/&gt;
+    &lt;jvmarg line="--add-reads ${module.name}=ALL-UNNAMED"/&gt;
+    &lt;jvmarg line="--add-exports ${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>Run <code>my.test.TestCase</code> as a black-box test in the forked JVM 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 <kbd>--add-modules</kbd> Java
+option enables the test module.<br/>The <kbd>--add-exports</kbd> 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.</p>
 <pre>
-    &lt;junit fork="true"
-        jvm="${platform.java}"&gt;
-        &lt;jvmarg line="--add-modules ${test.module.name}"/&gt;
-        &lt;jvmarg line="--add-exports ${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>--add-modules</code> java option enables the test module.<br/>
-The <code>--add-exports</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/>
+&lt;junit fork="true"
+       jvm="${platform.java}"&gt;
+    &lt;jvmarg line="--add-modules ${test.module.name}"/&gt;
+    &lt;jvmarg line="--add-exports ${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>
 </body>
 </html>
diff --git a/manual/Tasks/junitlauncher.html b/manual/Tasks/junitlauncher.html
new file mode 100644
index 0000000..0f20648
--- /dev/null
+++ b/manual/Tasks/junitlauncher.html
@@ -0,0 +1,794 @@
+<!DOCTYPE html>
+<!--
+   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
+
+       https://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">
+<head>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+    <title>JUnitLauncher Task</title>
+</head>
+<body>
+
+<h2 id="junitlauncher">JUnitLauncher</h2>
+<h3>Description</h3>
+
+<p>
+    This task allows tests to be launched and run using the JUnit 5 framework.
+</p>
+<p>
+    JUnit 5 introduced a newer set of APIs to write and launch tests. It also introduced the concept
+    of test engines. Test engines decide which classes are considered as testcases and how they are
+    executed. JUnit 5 supports running tests that have been written using JUnit 4 constructs as well
+    as tests that have been written using JUnit 5 constructs.  For more details about JUnit 5
+    itself, please refer to the JUnit 5 project's documentation
+    at <a href="https://junit.org/junit5/">https://junit.org/junit5/</a>.
+</p>
+<p>
+    The goal of this <code>junitlauncher</code> task is to allow launching the JUnit 5 test launcher
+    and building the test requests so that the selected tests can then be parsed and executed by the
+    test engine(s) supported by JUnit 5. This task in itself does <i>not</i> understand what a test
+    case is nor does it execute the tests itself.
+</p>
+<p>
+    This task captures testoutput and configuration data inside of
+    the <a href="../running.html#tmpdir">temporary directory</a>.
+</p>
+<p>
+    <strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+    distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for
+    more information.
+</p>
+<p>
+    <strong>Note</strong>: You must have the necessary JUnit 5 libraries in the classpath of the
+    tests. At the time of writing this documentation, the list of JUnit 5 platform libraries that
+    are necessary to run the tests are:
+</p>
+
+<ul id="junit-platform-libraries">
+    <li>
+        <samp>junit-platform-commons.jar</samp>
+    </li>
+    <li>
+        <samp>junit-platform-engine.jar</samp>
+    </li>
+    <li>
+        <samp>junit-platform-launcher.jar</samp>
+    </li>
+    <li>
+        <samp>opentest4j.jar</samp>
+    </li>
+</ul>
+
+<p>
+    Depending on the test engine(s) that you want to use in your tests, you will further need the
+    following libraries in the classpath
+</p>
+
+<p id="junit-vintage-engine-libraries">
+    For <q>junit-vintage</q> engine:
+</p>
+
+<ul>
+    <li>
+        <samp>junit-vintage-engine.jar</samp>
+    </li>
+    <li>
+        <samp>junit.jar</samp> (JUnit 4.x version)
+    </li>
+</ul>
+
+<p id="junit-jupiter-engine-libraries">
+    For <q>junit-jupiter</q> engine:
+</p>
+
+<ul>
+    <li>
+        <samp>junit-jupiter-api.jar</samp>
+    </li>
+    <li>
+        <samp>junit-jupiter-engine.jar</samp>
+    </li>
+</ul>
+
+<p>
+    To have these in the test classpath, you can follow <em>either</em> of the following approaches:
+</p>
+
+<ul id="setup">
+    <li id="setup-recommended"><b>Recommended approach since Ant 1.10.6</b>: Place the <samp>ant-junitlauncher.jar</samp> in <samp>ANT_HOME/lib</samp> directory
+    and use the nested <code>&lt;classpath&gt;</code> element to specify the location of the
+    the rest of the JUnit specific jars (noted above). Please read the
+    <a href=#nested-classpath>using classpath element</a> section for more details.</li>
+
+    <li>OR Put all these relevant jars along with the <samp>ant-junitlauncher.jar</samp>
+        in <samp>ANT_HOME/lib</samp> directory</li>
+
+    <li>OR Put <samp>ant-junitlauncher.jar</samp> in the <samp>ANT_HOME/lib</samp> directory and
+        include all other relevant jars in the classpath by passing them as a <kbd>-lib</kbd>
+        option, while invoking Ant</li>
+</ul>
+
+<p>
+    Tests are defined by nested elements like <code>test</code>, <code>testclasses</code> tags
+    (see <a href="#nested">nested elements</a>).
+</p>
+
+<h3>Parameters</h3>
+<table class="attr">
+    <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+    </tr>
+    <tr>
+        <td>includeTags</td>
+        <td>A comma separated list of <a href="https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations">JUnit 5 tags</a>, describing the tests to include.
+            <p><em>Since Ant 1.10.7</em></p>
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>excludeTags</td>
+        <td>A comma separated list of <a href="https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations">JUnit 5 tags</a>, describing the tests to exclude.
+            <p><em>Since Ant 1.10.7</em></p>
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>haltOnFailure</td>
+        <td>A value of <q>true</q> implies that build has to stop if any failure occurs in any of
+            the tests. JUnit 4+ classifies failures as both assertion failures as well as exceptions
+            that get thrown during test execution. As such, this task too considers both these cases
+            as failures and doesn't distinguish one from another.
+        </td>
+        <td>No; default is <q>false</q></td>
+    </tr>
+    <tr>
+        <td>failureProperty</td>
+        <td>The name of a property to set in the event of a failure
+            (exceptions in tests are considered failures as well).
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>printSummary</td>
+        <td>If the value is set to <code>true</code> then this task, upon completion of the test execution,
+            prints the summary of the execution to <code>System.out</code>. Starting Ant 1.10.10, unlike
+            in previous versions, this task itself generates the summary instead of using the one generated
+            by the JUnit 5 platform.
+        </td>
+        <td>No; defaults to <code>false</code></td>
+    </tr>
+</table>
+
+<h3 id="nested">Nested Elements</h3>
+
+<h4 id="nested-classpath">classpath</h4>
+<p>
+    The nested <code>&lt;classpath&gt;</code> element that represents
+    a <a href="../using.html#path">PATH like structure</a> can be used to configure the task to use
+    this classpath for finding and running the tests. This classpath will be used for:
+</p>
+<ul>
+    <li>Finding the test classes to execute</li>
+    <li>Finding test engines that run the tests</li>
+    <li>If <a href="#setup-recommended">configured to do so</a>, finding all necessary JUnit libraries</li>
+</ul>
+<p>
+    If the <code>classpath</code> element isn't configured for the task, then the classpath of Ant
+    itself will be used for finding the test classes and the JUnit libraries.
+</p>
+
+<p>
+    Below is an example of setting up the classpath to include the Jupiter test engine and
+    the JUnit platform libraries during the execution of the tests.
+</p>
+    <pre>
+&lt;project&gt;
+
+    &lt;property name="output.dir" value="${basedir}/build"/&gt;
+    &lt;property name="src.test.dir" value="${basedir}/src/test"/&gt;
+    &lt;property name="build.classes.dir" value="${output.dir}/classes"/&gt;
+
+    &lt;target name="init"&gt;
+        &lt;mkdir dir="${output.dir}"/&gt;
+    &lt;/target&gt;
+
+    &lt;path id="junit.platform.libs.classpath"&gt;
+        &lt;fileset dir="${basedir}/src/lib/junit-platform/"/&gt;
+    &lt;/path&gt;
+
+    &lt;path id="junit.engine.jupiter.classpath"&gt;
+        &lt;fileset dir="${basedir}/src/lib/jupiter/"/&gt;
+    &lt;/path&gt;
+
+    &lt;target name="compile-test" depends="init"&gt;
+        &lt;mkdir dir="${build.classes.dir}"/&gt;
+        &lt;javac srcdir="${src.test.dir}"
+           destdir="${build.classes.dir}"&gt;
+           &lt;!-- our tests only need JUnit Jupiter engine
+           libraries in our compile classpath for the tests --&gt;
+           &lt;classpath refid="junit.engine.jupiter.classpath"/&gt;
+        &lt;/javac&gt;
+    &lt;/target&gt;
+
+    &lt;target name="test" depends="compile-test"&gt;
+        &lt;junitlauncher&gt;
+            &lt;!-- include the JUnit platform related libraries
+            required to run the tests --&gt;
+            &lt;classpath refid="junit.platform.libs.classpath"/&gt;
+
+            &lt;!-- include the JUnit Jupiter engine libraries --&gt;
+            &lt;classpath refid="junit.engine.jupiter.classpath"/&gt;
+
+            &lt;classpath&gt;
+                &lt;!-- the test classes themselves --&gt;
+                &lt;pathelement location="${build.classes.dir}"/&gt;
+            &lt;/classpath&gt;
+            &lt;testclasses outputdir="${output.dir}"&gt;
+                &lt;fileset dir="${build.classes.dir}"/&gt;
+                &lt;listener type="legacy-brief" sendSysOut="true"/&gt;
+                &lt;listener type="legacy-xml" sendSysErr="true" sendSysOut="true"/&gt;
+
+            &lt;/testclasses&gt;
+        &lt;/junitlauncher&gt;
+    &lt;/target&gt;
+&lt;/project&gt;
+    </pre>
+<p>
+    In the example above,
+</p>
+    <ul>
+        <li>The <code>src/lib/jupiter</code> directory is expected to contain
+        the Jupiter test engine related jars (which have been
+        <a href="#junit-jupiter-engine-libraries">listed in an earlier section of this
+        document</a>).</li>
+        <li>The <code>src/lib/junit-platform</code> directory is expected to
+        contain the JUnit platform jars (which have been
+        <a href="#junit-platform-libraries">listed in an earlier section of this
+        document</a>)</li>
+    </ul>
+<p>
+    In the <code>test</code> target we use the <code>classpath</code> nested element
+    to point to the <code>junit.engine.jupiter.classpath</code> and <code>junit.platform.libs.classpath</code>
+    containing those jars.
+    In this <code>test</code> target we also use another <code>classpath</code> element to point to
+    the location containing our test classes. If required, all these classpaths can be combined
+    into one.
+</p>
+
+<h4>listener</h4>
+
+<p>
+    The <code>junitlauncher</code> task can be configured with <code>listener</code>(s) to listen to
+    test execution events (such as a test execution starting, completing etc...). The listener is
+    expected to be a class which implements
+    the <code class="code">org.junit.platform.launcher.TestExecutionListener</code>.
+    This <code class="code">TestExecutionListener</code> interface is an API exposed by the JUnit 5
+    platform APIs and isn't specific to Ant. As such, you can use any existing implementation
+    of <code class="code">TestExecutionListener</code> in this task.
+</p>
+
+<h5>Test result formatter</h5>
+<p>
+    <code>junitlauncher</code> provides a way where the test execution results can be formatted and
+    presented in a way that's customizable. The task allows for configuring test result formatters,
+    through the use of <code>listener</code> element. As noted previously, the <code>listener</code>
+    element expects the listener to implement
+    the <code class="code">org.junit.platform.launcher.TestExecutionListener</code>
+    interface. Typically, result formatters need a bit more configuration details to be fed to them,
+    during the test execution&mdash;details like where to write out the formatted result. Any such
+    listener can optionally implement
+    the <code class="code">org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code>
+    interface. This interface is specific to Ant <code>junitlauncher</code> task and it extends
+    the <code class="code">org.junit.platform.launcher.TestExecutionListener</code> interface
+</p>
+<p>
+    The <code>junitlauncher</code> task comes with the following pre-defined test result formatter
+    types:
+</p>
+<ul>
+    <li>
+        <q>legacy-plain</q> : This formatter prints a short statistics line for all test
+        cases.
+    </li>
+    <li>
+        <q>legacy-brief</q> : This formatter prints information for tests that failed or were
+        skipped.
+    </li>
+    <li>
+        <q>legacy-xml</q> : This formatter prints statistics for the tests in XML format.
+    </li>
+</ul>
+<p>
+    <strong>Note</strong>: Each of these formatters named <q>legacy</q> try to format the results
+    similar to what the <code>junit</code> task's formatters used to do. Furthermore,
+    the <q>legacy-xml</q> formatter generates the XML to comply with the same schema that
+    the <code>junit</code> task's XML formatter used to follow.  As a result, the XML generated by
+    this formatter, can be used as-is by the <code>junitreport</code> task.
+</p>
+<p>
+    The <code>listener</code> element supports the following attributes:
+</p>
+<table class="attr">
+    <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+    </tr>
+    <tr>
+        <td>type</td>
+        <td>Use a predefined formatter (either <q>legacy-xml</q>, <q>legacy-plain</q>
+            or <q>legacy-brief</q>).</td>
+        <td rowspan="2">Exactly one of these</td>
+    </tr>
+    <tr>
+        <td>classname</td>
+        <td class="left">Name of a listener class which
+            implements <code>org.junit.platform.launcher.TestExecutionListener</code> or
+            the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code>
+            interface
+        </td>
+    </tr>
+    <tr>
+        <td>resultFile</td>
+        <td>
+            The file name to which the formatted result needs to be written to. This attribute is
+            only relevant when the listener class implements
+            the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code>
+            interface.
+            <p>
+                If no value is specified for this attribute and the listener implements
+                the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code>
+                then the file name will be defaulted to and will be of the
+                form <code>TEST-<i>testname</i>.<i>extension</i></code>
+                (ex: <samp>TEST-org.myapp.SomeTest.xml</samp> for the <q>legacy-xml</q> type
+                formatter)
+            </p>
+            <p>
+                This file is considered relative to the <code>outputDir</code> configured on the listener.
+                If no <code>outputDir</code> is set on the listener, then the file is considered relative to the
+                <code>outputDir</code> of the test in context of which this listener is being run.
+            </p>
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>extension</td>
+        <td>Extension to append to the output filename.
+            <p><em>Since Ant 1.10.13</em></p>
+        </td>
+        <td>No; defaults to <q>xml</q> for the <q>legacy-xml</q> formatter and to <q>txt</q> for the rest</td>
+    </tr>
+    <tr>
+        <td>outputDir</td>
+        <td>Directory into which to create the output of the listener.
+            <p><em>Since Ant 1.10.6</em></p>
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>sendSysOut</td>
+        <td>If set to <q>true</q> then the listener will be passed the <code>stdout</code> content
+            generated by the test(s). This attribute is relevant only if the listener class
+            implements
+            the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code>
+            interface.</td>
+        <td>No; defaults to <q>false</q></td>
+    </tr>
+    <tr>
+        <td>sendSysErr</td>
+        <td>If set to <q>true</q> then the listener will be passed the <code>stderr</code> content
+            generated by the test(s). This attribute is relevant only if the listener class
+            implements
+            the <code>org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter</code>
+            interface.</td>
+        <td>No; defaults to <q>false</q></td>
+    </tr>
+    <tr>
+        <td>if</td>
+        <td>Only use this listener <a href="../properties.html#if+unless">if the named property is
+            set</a>.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>unless</td>
+        <td>Only use this listener <a href="../properties.html#if+unless">if the named property
+            is <strong>not</strong> set</a>.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>useLegacyReportingName</td>
+        <td>Set to true, if the test identifiers reported by this listener should use legacy (JUnit4
+            style) names. Else set to false.
+            <p><em>Since Ant 1.10.10</em></p>
+        </td>
+        <td>No; defaults to <q>true</q></td>
+    </tr>
+</table>
+
+<h4>test</h4>
+
+<p>Defines a single test class.</p>
+
+<table class="attr">
+    <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+    </tr>
+    <tr>
+        <td>name</td>
+        <td>Fully qualified name of the test class.</td>
+        <td>Yes</td>
+    </tr>
+    <tr>
+        <td>methods</td>
+        <td>Comma-separated list of names of test case methods to execute.  If this is specified,
+            then only these test methods from the test class will be executed.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>haltOnFailure</td>
+        <td>Stop the build process if a failure occurs during the test run (exceptions are
+            considered as failures too).  Overrides value set on <code>junitlauncher</code>
+            element.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>failureProperty</td>
+        <td>The name of a property to set in the event of a failure (exceptions are considered
+            failures as well). Overrides value set on <code>junitlauncher</code> element.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>outputDir</td>
+        <td>Directory to write the reports to.</td>
+        <td>No; default is the base directory of the project.</td>
+    </tr>
+    <tr>
+        <td>if</td>
+        <td>Only run this test <a href="../properties.html#if+unless">if the named property is
+            set</a>.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>unless</td>
+        <td>Only run this test <a href="../properties.html#if+unless">if the named property
+            is <strong>not</strong> set</a>.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>includeEngines</td>
+        <td>A comma separated set of test engine ids. If specified, only these test engine(s)
+            will be used for running the tests.
+            <br/>
+            For example: <code>includeEngines="junit-jupiter"</code> will only use the Jupiter
+            test engine for execution of the tests and will ignore any other engines that might
+            have been found in the classpath.
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>excludeEngines</td>
+        <td>A comma separated set of test engine ids. If specified, these test engine(s)
+            will be excluded when running the tests.
+            <br/>
+            For example: <code>excludeEngines="junit-vintage"</code> will exclude the vintage
+            test engine during execution of the tests and will use any other engines that might
+            have been found in the classpath.
+        </td>
+        <td>No</td>
+    </tr>
+</table>
+
+<p>
+    Tests can define their own listeners via nested <code>listener</code> elements.
+</p>
+
+<p>
+    The <a href="#fork">fork</a> nested element can be used to run the test in a newly forked
+    JVM.
+</p>
+
+<h4>testclasses</h4>
+
+<p>Define a number of tests based on pattern matching.</p>
+
+<p>
+    <code>testclasses</code> collects the included <a href="../Types/resources.html">resources</a>
+    from any number of nested <a href="../Types/resources.html#collection">Resource
+    Collection</a>s. It then selects each resource whose name ends in <code>.class</code>. These
+    classes are then passed on to the JUnit 5 platform for it to decide and run them as tests.
+</p>
+
+<table class="attr">
+    <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+    </tr>
+    <tr>
+        <td>haltOnFailure</td>
+        <td>Stop the build process if a failure occurs during the test run (exceptions are
+            considered as failures too).  Overrides value set on <code>junitlauncher</code>
+            element.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>failureProperty</td>
+        <td>The name of a property to set in the event of a failure (exceptions are considered
+            failures as well). Overrides value set on <code>junitlauncher</code> element.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>outputDir</td>
+        <td>Directory to write the reports to.</td>
+        <td>No; default is the base directory of the project.</td>
+    </tr>
+    <tr>
+        <td>if</td>
+        <td>Only run the tests <a href="../properties.html#if+unless">if the named property is
+            set</a>.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>unless</td>
+        <td>Only run the tests <a href="../properties.html#if+unless">if the named property
+            is <strong>not</strong> set</a>.</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>includeEngines</td>
+        <td>A comma separated set of test engine ids. If specified, only these test engine(s)
+            will be used for running the tests.
+            <br/>
+            For example: <code>includeEngines="junit-jupiter"</code> will only use the Jupiter
+            test engine for execution of the tests and will ignore any other engines that might
+            have been found in the classpath.
+        </td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>excludeEngines</td>
+        <td>A comma separated set of test engine ids. If specified, these test engine(s)
+            will be excluded when running the tests.
+            <br/>
+            For example: <code>excludeEngines="junit-vintage"</code> will exclude the vintage
+            test engine during execution of the tests and will use any other engines that might
+            have been found in the classpath.
+        </td>
+        <td>No</td>
+    </tr>
+</table>
+
+<p>
+    <code>testclasses</code> can define their own listeners via nested <code>listener</code>
+    elements.
+</p>
+
+<p>
+    The <a href="#fork">fork</a> nested element can be used to run the tests in a newly forked
+    JVM. All tests that are part of this <code>testclasses</code> element will run in one single
+    instance of the newly forked JVM.
+</p>
+
+<h4 id="fork">fork</h4>
+
+<p><em>Since Ant 1.10.6</em></p>
+
+Tests launched using the <code>junitlauncher</code> task, by default, run in the same JVM that
+initiates the task. This behaviour can be changed using the <code>fork</code> element.
+The <code>fork</code> element and its attributes define the characteristics of
+the new JVM instance that will be created to launch the tests.
+
+<table class="attr">
+    <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+    </tr>
+    <tr>
+        <td>dir</td>
+        <td>The user working directory that will be used for the forked JVM</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>timeout</td>
+        <td>A value in milliseconds, specifying a maximum duration, the test
+            running in this forked JVM is allowed to run. If the test runs longer
+            than this configured value, then the JVM is killed</td>
+        <td>No</td>
+    </tr>
+    <tr>
+        <td>includeJUnitPlatformLibraries</td>
+        <td>If set to <code>true</code>, then the jar files that make up the
+        JUnit platform, will be included in the runtime classpath of the forked
+        JVM. If set to <code>false</code>, then the <a href="#nested-classpath">configured classpath</a>
+        of this task, which will be made available to the runtime classpath of the forked
+        JVM, is expected to contain the JUnit platform library jars</td>
+        <td>No. Value defaults to <code>true</code>.</td>
+    </tr>
+    <tr>
+        <td>includeAntRuntimeLibraries</td>
+        <td>If set to <code>true</code>, then the jar files that make up the
+            Ant runtime, will be included in the runtime classpath of the forked
+            JVM. If set to <code>false</code>, then the <a href="#nested-classpath">configured classpath</a>
+            of this task, which will be made available to the runtime classpath of the forked
+            JVM, is expected to contain the Ant runtime jars</td>
+        <td>No. Value defaults to <code>true</code>.</td>
+    </tr>
+</table>
+
+The <code>fork</code> element allows the following nested elements:
+
+<h5>jvmarg</h5>
+<p>
+    Additional JVM arguments may be passed to the forked JVM via the <code>jvmarg</code> elements.
+    For example:
+</p>
+    <pre>
+    &lt;fork ...&gt;
+      &lt;jvmarg value="-Djava.compiler=NONE"/&gt;
+      ...
+    &lt;/fork&gt;
+    </pre>
+
+<p>
+    <code>jvmarg</code> allows all attributes described in <a href="../using.html#arg">Command-line Arguments</a>
+</p>
+
+<h5>sysproperty</h5>
+<p>
+    The <code>sysproperty</code> elements allow passing Java system properties to the forked JVM:
+</p>
+    <pre>
+    &lt;fork&gt;
+        &lt;sysproperty key="greeting" value="hello world"/&gt;
+    ...
+    &lt;/fork&gt;
+    </pre>
+<p>
+    The attributes for this element are the same as for <a href="../Tasks/exec.html#env">environment variables</a>
+</p>
+
+<h5>syspropertyset</h5>
+
+<p>
+    You can specify a set of properties to be used as system properties with
+    <a href="../Types/propertyset.html">syspropertyset</a>(s)
+</p>
+
+
+<h5>env</h5>
+
+<p>
+    It is possible to specify environment variables to pass to the forked JVM via
+    nested <code>env</code> elements. For a description of the <code>env</code>
+    element's attributes, see the description in the <a href="../Tasks/exec.html#env">exec</a> task.
+</p>
+
+<h5>modulepath</h5>
+
+<p>
+    The location of Java modules can be specified using the <code>modulepath</code> element,
+    which is a <a href="../using.html#path">path-like structure</a>.
+</p>
+For example:
+<pre>
+&lt;fork&gt;
+  &lt;modulepath&gt;
+    &lt;pathelement location="lib"/&gt;
+    &lt;pathelement location="dist/test.jar"/&gt;
+  &lt;/modulepath&gt;
+  ...
+&lt;/fork&gt;
+</pre>
+
+<h5>upgrademodulepath</h5>
+
+<p>
+    The location of Java modules, that replace upgradeable modules in the runtime, can be specified
+    using the <code>upgrademodulepath</code> element, which is a <a href="../using.html#path">path-like
+    structure</a>.
+</p>
+
+
+<h3>Examples</h3>
+
+<p>
+    Launch the JUnit 5 platform to run the <samp>org.myapp.SimpleTest</samp> test
+</p>
+
+<pre>
+&lt;path id="test.classpath"&gt;
+    ...
+&lt;/path&gt;
+
+&lt;junitlauncher&gt;
+    &lt;classpath refid="test.classpath"/&gt;
+    &lt;test name="org.myapp.SimpleTest"/&gt;
+&lt;/junitlauncher&gt;</pre>
+
+<p>
+    Launch the JUnit 5 platform to run the <samp>org.myapp.SimpleTest</samp> and
+    the <samp>org.myapp.AnotherTest</samp> tests. The build process will be stopped if any test, in
+    the <samp>org.myapp.SimpleTest</samp>, fails.
+</p>
+
+<pre>
+&lt;junitlauncher&gt;
+    &lt;classpath refid="test.classpath"/&gt;
+    &lt;test name="org.myapp.SimpleTest" haltOnFailure="true"/&gt;
+    &lt;test name="org.myapp.AnotherTest"/&gt;
+&lt;/junitlauncher&gt;
+</pre>
+
+<p>
+    Launch the JUnit 5 platform to run only the <samp>testFoo</samp> and <samp>testBar</samp>
+    methods of the <samp>org.myapp.SimpleTest</samp> test class.
+</p>
+
+<pre>
+&lt;junitlauncher&gt;
+    &lt;classpath refid="test.classpath"/&gt;
+    &lt;test name="org.myapp.SimpleTest" methods="testFoo, testBar"/&gt;
+&lt;/junitlauncher&gt;</pre>
+
+<p>
+    Select any <samp>.class</samp> files that match
+    the <samp>org/example/**/tests/**/</samp> <code>fileset</code> filter, under
+    the <samp>${build.classes.dir}</samp> and passes those classes to the JUnit 5 platform for
+    execution as tests.
+</p>
+
+<pre>
+&lt;junitlauncher&gt;
+    &lt;classpath refid="test.classpath"/&gt;
+
+    &lt;testclasses outputdir="${output.dir}"&gt;
+        &lt;fileset dir="${build.classes.dir}"&gt;
+            &lt;include name="org/example/**/tests/**/"/&gt;
+        &lt;/fileset&gt;
+    &lt;/testclasses&gt;
+&lt;/junitlauncher&gt;</pre>
+
+<p>
+    Select any <samp>.class</samp> files that match
+    the <samp>org/example/**/tests/**/</samp> <code>fileset</code> filter, under
+    the <samp>${build.classes.dir}</samp> and pass those classes to the JUnit 5 platform for
+    execution as tests. Test results will be written out to the <samp>${output.dir}</samp> by
+    the <q>legacy-xml</q> and <q>legacy-plain</q> formatters, in separate files. Furthermore, both
+    the <q>legacy-xml</q> and the <q>legacy-plain</q> listeners, above, are configured to receive
+    the standard output content generated by the tests. The <q>legacy-xml</q> listener is configured
+    to receive standard error content as well.
+</p>
+
+<pre>
+&lt;junitlauncher&gt;
+    &lt;classpath refid="test.classpath"/&gt;
+
+    &lt;testclasses outputdir="${output.dir}"&gt;
+        &lt;fileset dir="${build.classes.dir}"&gt;
+            &lt;include name="org/example/**/tests/**/"/&gt;
+        &lt;/fileset&gt;
+        &lt;listener type="legacy-xml" sendSysOut="true" sendSysErr="true"/&gt;
+        &lt;listener type="legacy-plain" sendSysOut="true" /&gt;
+    &lt;/testclasses&gt;
+&lt;/junitlauncher&gt;</pre>
+
+</body>
+</html>
diff --git a/manual/Tasks/junitreport.html b/manual/Tasks/junitreport.html
index 9712014..27448e4 100644
--- a/manual/Tasks/junitreport.html
+++ b/manual/Tasks/junitreport.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>JUnitReport Task</title>
@@ -22,195 +23,169 @@
 
 <body>
 
-<h2><a name="junitreport">JUnitReport</a></h2>
+<h2 id="junitreport">JUnitReport</h2>
 <h3>Description</h3>
-Merge the individual XML files generated by the JUnit task and eventually apply
-a stylesheet on the resulting merged document to provide a browsable report of
-the testcases results.
+<p>Merge the individual XML files generated by the <code>JUnit</code> task and eventually apply a
+stylesheet on the resulting merged document to provide a browsable report of the testcases
+results.</p>
 
-<p><strong>Note:</strong> This task depends on external libraries not
-included in the Apache Ant distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a>
-for more information.</p>
-
-<h3>Requirements</h3>
-
-<p>The task needs Apache <a
-href="http://xml.apache.org/xalan-j/">Xalan 2.4.1+ or Xalan XSLTC</a>
-(JDK 1.4 contains a version of Xalan-J 2.x while JDK 1.5 ships with a
-version of XSLTC). Starting from JDK 1.4.2-01 it ships with a bundled
-Xalan-J 2.4.1+, meaning that JDK version prior to 1.4.2-01 won't work
-out of the box. The table below summarize the compatibility status. 
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr><th>Xalan</th><th>Sun JDK Bundle</th><th>Status<th></tr> 
-<tr><td>2.4.1+</td><td>JDK 1.4.2-01+</td><td>OK</td></tr>
-<tr><td>XSLTC</td><td>JDK 1.5.x</td><td>OK</td></tr>
-<tr><td>2.x</td><td>JDK 1.4.x</td><td>DEPRECATED<br><i>Use ${ant.home}/etc/junit-frames-xalan1.xsl
-<br> Upgrade Xalan using the JDK endorsement mechanism</i></td></tr>
-</table>
-
-<p>With Ant 1.6.2 we had to decide between supporting Xalan-J 1/Xalan J 2.4.1-
-and Xalan 2.4.1+/XSLTC, since there was no way to support both couples at the same
-time.</p>
-<p>With Ant 1.7 we had to drop support Xalan-J 1, since Xalan-J 1 has not 
-available anymore for quite some time.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">tofile</td>
-    <td valign="top">The name of the XML file that will aggregate all individual
-      XML testsuite previously generated by the JUnit task.</td>
-    <td align="center" valign="top">No. Default to TESTS-TestSuites.xml</td>
+    <td>tofile</td>
+    <td>The name of the XML file that will aggregate all individual XML testsuites previously
+      generated by the <code>JUnit</code> task.</td>
+    <td>No; defaults to <samp>TESTS-TestSuites.xml</samp></td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">The directory where should be written the file resulting
-      from the individual XML testsuite aggregation.</td>
-    <td align="center" valign="top">No. Default to current directory</td>
+    <td>todir</td>
+    <td>The directory where the file resulting from the individual XML testsuite aggregation should
+      be written.</td>
+    <td>No; defaults to current directory</td>
   </tr>
 </table>
-<h3><a name="nested">Nested Elements</a></h3>
+<h3 id="nested">Parameters specified as nested elements</h3>
 <h4>fileset</h4>
-<p><code>junitreport</code> collects individual xml files generated by the JUnit
-task using the nested <a href="../Types/fileset.html"><code>&lt;FileSet&gt;</code></a>
-element.</p>
+<p><code>junitreport</code> collects individual xml files generated by the <code>JUnit</code> task
+using the nested <a href="../Types/fileset.html"><code>&lt;FileSet&gt;</code></a> element.</p>
 <h4>report</h4>
 <p>Generate a browsable report based on the document created by the merge.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td width="12%" valign="top"><b>Attribute</b></td>
-    <td width="78%" valign="top"><b>Description</b></td>
-    <td width="10%" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">format</td>
-    <td valign="top">The format of the generated report. Must be &quot;noframes&quot;
-      or &quot;frames&quot;.</td>
-    <td align="center" valign="top">No, default to &quot;frames&quot;</td>
+    <td>format</td>
+    <td>The format of the generated report. Must be either <q>noframes</q> or <q>frames</q>.</td>
+    <td>No; defaults to <q>frames</q></td>
   </tr>
   <tr>
-    <td valign="top">styledir</td>
-    <td valign="top">The directory where the stylesheets are defined. They must
-      be conforming to the following conventions:
+    <td>styledir</td>
+    <td>The directory where the stylesheets are defined. They must be conforming to the following
+      conventions:
       <ul>
-        <li>frames format: the stylesheet must be named <i>junit-frames.xsl</i>.</li>
-        <li>noframes format: the stylesheet must be named <i>junit-noframes.xsl</i>.</li>
+        <li><q>frames</q> format: the stylesheet must be named <samp>junit-frames.xsl</samp>,
+          or <samp>junit-frames-saxon.xsl</samp> if you are using Saxon 9+.</li>
+        <li><q>noframes</q> format: the stylesheet must be named <samp>junit-noframes.xsl</samp>,
+          or <samp>junit-noframes-saxon.xsl</samp> if you are using Saxon 9+.</li>
       </ul>
     </td>
-    <td align="center" valign="top">No. Default to embedded stylesheets.</td>
+    <td>No; defaults to embedded stylesheets</td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">The directory where the files resulting from the
-      transformation should be written to.</td>
-    <td align="center" valign="top">No. Default to current directory</td>
+    <td>todir</td>
+    <td>The directory where the files resulting from the transformation should be written to.</td>
+    <td>No; defaults to current directory</td>
   </tr>
 </table>
-<p> Ant assumes the following concerning the <tt>frames</tt> and <tt>noframes</tt> formats :</p>
-<p>The <tt>frames</tt> format uses
-a stylesheet which is generating output <em>only</em> by redirecting.</p>
-<p>The
-<tt>noframes</tt> format does not use redirecting and generates one
-file called <tt>junit-noframes.html</tt>.</p>
-<p>Custom versions of <tt>junit-frames.xsl</tt> or <tt>junit-noframes.xsl</tt> must adhere to the above conventions.</p>
+<p>Ant assumes the following concerning the <q>frames</q> and <q>noframes</q> formats:</p>
+<ul>
+  <li>The <q>frames</q> format uses a stylesheet which is generating output <em>only</em> by
+    redirecting.</li>
+  <li>The <q>noframes</q> format does not use redirecting and generates one file
+    called <samp>junit-noframes.html</samp>.</li>
+</ul>
+<p>Custom versions of <samp>junit-frames.xsl</samp> or <samp>junit-noframes.xsl</samp> must adhere
+to the above conventions.</p>
 
-<h3>Nested Element of the report tag</h3>
+<h3>Nested element of the report tag</h3>
 <h4>param</h4>
-<em>Since Ant 1.7</em>the report tag supports nested param tags.
-These tags can pass XSL parameters to the stylesheet.
+<p><em>Since Ant 1.7</em>, the <var>report</var> tag supports nested <code>param</code> tags.  These
+tags can pass XSL parameters to the stylesheet.</p>
 <h3>Parameters</h3>
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Name of the XSL parameter</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>Name of the XSL parameter</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">expression</td>
-    <td valign="top">Text value to be placed into the param.<br>
-    Was originally intended to be an XSL expression.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>expression</td>
+    <td>Text value to be placed into the <code>param</code>.<br/>Was originally intended to be an
+      XSL expression.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">The param will only be passed <a href="../properties.html#if+unless">if this property is set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>if</td>
+    <td>The <code>param</code> will only be passed <a href="../properties.html#if+unless">if this
+      property is set</a>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">The param will not be passed <a href="../properties.html#if+unless">if this property is set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>unless</td>
+    <td>The <code>param</code> will not be passed <a href="../properties.html#if+unless">if this
+      property is set</a>.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <p>The built-in stylesheets support the following parameters:</p>
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>XSL-Parameter</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">XSL Parameter</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">TITLE</td>
-    <td valign="top">Title used in &lt;title&gt; and &lt;h1&gt; tags</td>
-    <td align="center" valign="top">No. Defaults to <i>Unit Test Results.</i></td>
+    <td>TITLE</td>
+    <td>Title used in <code>&lt;title&gt;</code> and <code>&lt;h1&gt;</code> tags</td>
+    <td>No; defaults to <q>Unit Test Results</q></td>
   </tr>
 </table>
 
 <h4>classpath</h4>
-<p><em>Since Ant 1.9.5.</em>
-Like for the <a href="../Tasks/style.html#classpath">XSLT task</a>,
-a nested &lt;classpath&gt; will be used to load the processor.</p>
+<p><em>Since Ant 1.9.5</em>. Like for the <a href="../Tasks/style.html#classpath">XSLT task</a>, a
+nested <code>&lt;classpath&gt;</code> will be used to load the processor.</p>
 
 <h4>factory</h4>
-<p><em>Since Ant 1.9.5.</em>
-Like for the <a href="../Tasks/style.html#factory">XSLT task</a>,
-a nested &lt;factory&gt; can be used to specify factory settings.</p>
+<p><em>Since Ant 1.9.5</em>. Like for the <a href="../Tasks/style.html#factory">XSLT task</a>, a
+nested <code>&lt;factory&gt;</code> can be used to specify factory settings.</p>
 
+<h3>Examples</h3>
 
-<h3>Example of report</h3>
-<blockquote>
-  <pre>&lt;junitreport todir=&quot;./reports&quot;&gt;
-  &lt;fileset dir=&quot;./reports&quot;&gt;
-    &lt;include name=&quot;TEST-*.xml&quot;/&gt;
-  &lt;/fileset&gt;
-  &lt;report format=&quot;frames&quot; todir=&quot;./report/html&quot;/&gt;
-&lt;/junitreport&gt;
-</pre>
-</blockquote>
-<p>would generate a <tt>TESTS-TestSuites.xml</tt> file in the directory <tt>reports</tt> and
-generate the default framed report in the directory <tt>report/html</tt>.</p>
-<h3>Example of report with xsl params</h3>
-<blockquote>
-  <pre>
+<p>Generate a <samp>TESTS-TestSuites.xml</samp> file in the directory <samp>reports</samp> and
+generate the default framed report in the directory <samp>report/html</samp>.</p>
+
+<pre>
+&lt;junitreport todir=&quot;./reports&quot;&gt;
+    &lt;fileset dir=&quot;./reports&quot;&gt;
+        &lt;include name=&quot;TEST-*.xml&quot;/&gt;
+    &lt;/fileset&gt;
+    &lt;report format=&quot;frames&quot; todir=&quot;./report/html&quot;/&gt;
+&lt;/junitreport&gt;</pre>
+
+<p>This example requires a file called <samp>junitreport/junit-frames.xsl</samp>. The XSL
+parameters <q>key1</q> and <q>key2</q> will be passed to the XSL transformation.</p>
+
+<pre>
 &lt;junitreport todir="${outputdir}"&gt;
     &lt;fileset dir="${jrdir}"&gt;
         &lt;include name="TEST-*.xml"/&gt;
     &lt;/fileset&gt;
     &lt;report todir="${outputdir}/html"
-        styledir="junitreport"
-        format="frames"&gt;
+            styledir="junitreport"
+            format="frames"&gt;
         &lt;param name="key1" expression="value1"/&gt;
         &lt;param name="key2" expression="value2"/&gt;
     &lt;/report&gt;
-&lt;/junitreport&gt;
-  </pre>
-  </blockquote>
-<p>This example requires a file called <tt>junitreport/junit-frames.xsl</tt>.
-    The XSL parameters key1 and key2 will be passed to the XSL transformation.</p>
+&lt;/junitreport&gt;</pre>
 
 </body>
-
 </html>
diff --git a/manual/Tasks/length.html b/manual/Tasks/length.html
index 18c62c7..a9d1cd1 100644
--- a/manual/Tasks/length.html
+++ b/manual/Tasks/length.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Length Task</title>
 </head>
@@ -25,103 +25,100 @@
 <body>
 
 <h2>Length</h2>
+<p><em>Since Apache Ant 1.6.3</em></p>
 <h3>Description</h3>
-<p>Display or set a property containing length information for
-   a string, a file, or one or more nested
-   <a href="../Types/resources.html#collection">Resource Collection</a>s.
-   Can also be used as a condition. <b>Since Apache Ant 1.6.3</b></p>
+<p>Display or set a property containing length information for a string, a file, or one or more
+nested <a href="../Types/resources.html#collection">resource collections</a>.  Can also be used as
+a <code>condition</code>.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col" rowspan="2">Attribute</th>
+    <th scope="col" rowspan="2">Description</th>
+    <th scope="col" colspan="2">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The property to set.  If omitted
-      the results are written to the log. Ignored when
-      processing as a condition.</td>
-    <td valign="top" align="center">No</td>
+    <th scope="col">Task</th>
+    <th scope="col">Condition</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">Single file whose length to report.</td>
-    <td valign="top" align="center" rowspan="3">One of these,
-      or one or more nested filesets</td>
+    <td>property</td>
+    <td>The property to set.</td>
+    <td class="center">No; by default, output value to the log</td>
+    <td rowspan="2">Ignored</td>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top">Single resource whose length to report (using extended
-      <a href="../properties.html#propertyHelper">properties handling</a>).
-      <em>Since Ant 1.8.1</em>
+    <td>mode</td>
+    <td>File length mode; when <q>all</q> the resulting value is the sum of all included resources'
+      lengths; when <q>each</q> the task outputs the absolute path and length of each included
+      resource, one per line.</td>
+    <td class="center">No; default is <q>all</q></td>
+  </tr>
+  <tr>
+    <td>file</td>
+    <td>Single file whose length to report.</td>
+    <td rowspan="3" colspan="2">One of these, or one or more nested filesets</td>
+  </tr>
+  <tr>
+    <td>resource</td>
+    <td class="left">Single resource whose length to report (using
+      extended <a href="../properties.html#propertyHelper">properties handling</a>).  <em>Since Ant
+      1.8.1</em>
     </td>
   </tr>
   <tr>
-    <td valign="top">string</td>
-    <td valign="top">The string whose length to report.</td>
+    <td>string</td>
+    <td class="left">The string whose length to report.</td>
   </tr>
   <tr>
-    <td valign="top">mode</td>
-    <td valign="top">File length mode; when &quot;all&quot; the resulting
-      value is the sum of all included resources' lengths; when &quot;each&quot;
-      the task outputs the absolute path and length of each included resource,
-      one per line. Ignored when processing as a condition.</td>
-    <td valign="top" align="center">No; default is &quot;all&quot;</td>
+    <td>trim</td>
+    <td>Whether to trim when operating on a string.</td>
+    <td colspan="2">No; default is <q>false</q>, ignored unless <var>string</var> is set</td>
   </tr>
   <tr>
-    <td valign="top">trim</td>
-    <td valign="top">Whether to trim when operating on a string. Default <i>false</i>.</td>
-    <td valign="top" align="center">No; only valid when string is set</td>
+    <td>length</td>
+    <td>Comparison length.</td>
+    <td class="center" rowspan="2">Ignored</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">length</td>
-    <td valign="top">Comparison length for processing as a condition.</td>
-    <td valign="top" align="center">Yes, in condition mode</td>
-  </tr>
-  <tr>
-    <td valign="top">when</td>
-    <td valign="top">Comparison type: "equal", "eq", "greater", "gt", "less",
-      "lt", "ge" (greater or equal), "ne" (not equal), "le" (less or equal)
-      for use when operating as a condition.</td>
-    <td valign="top" align="center">No; default is "equal"</td>
+    <td>when</td>
+    <td>Comparison
+      type: <q>equal</q>, <q>eq</q>, <q>greater</q>, <q>gt</q>, <q>less</q>, <q>lt</q>, <q>ge</q>
+      (greater or equal), <q>ne</q> (not equal), <q>le</q> (less or equal).</td>
+    <td>No; default is <q>equal</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>Resource Collections</h4>
-<p>You can include resources via nested
-  <a href="../Types/resources.html#collection">Resource Collection</a>s.</p>
+<h4>resource collections</h4>
+<p>You can include resources via nested <a href="../Types/resources.html#collection">resource
+collection</a>s.</p>
 
 <h3>Examples</h3>
 
-<pre>&lt;length string=&quot;foo&quot; property=&quot;length.foo&quot; /&gt;
-</pre>
-<p>Stores the length of the string &quot;foo&quot; in the property named
-<i>length.foo</i>.</p>
+<p>Store the length of the string <q>foo</q> in the property named <code>length.foo</code>.</p>
+<pre>&lt;length string=&quot;foo&quot; property=&quot;length.foo&quot;/&gt;</pre>
 
-<pre>&lt;length file=&quot;bar&quot; property=&quot;length.bar&quot; /&gt;
-</pre>
-<p>Stores the length of file &quot;bar&quot; in the property named
-<i>length.bar</i>.</p>
+<p>Store the length of file <samp>bar</samp> in the property named <code>length.bar</code>.</p>
+<pre>&lt;length file=&quot;bar&quot; property=&quot;length.bar&quot;/&gt;</pre>
 
+<p>Store the file paths of <samp>foo</samp> and <samp>bar</samp> and their length into the
+property <code>length</code>.</p>
 <pre>
 &lt;length property=&quot;length&quot; mode=&quot;each&quot;&gt;
     &lt;fileset dir=&quot;.&quot; includes=&quot;foo,bar&quot;/&gt;
 &lt;/length&gt;
 </pre>
-<p>Writes the file paths of <i>foo</i> and <i>bar</i> and their length into 
-the property <i>length</i>.</p>
 
+<p>Add the length of <samp>foo</samp> and <samp>bar</samp> and store the result in
+property <code>length</code>.</p>
 <pre>
 &lt;length property=&quot;length&quot; mode=&quot;all&quot;&gt;
     &lt;fileset dir=&quot;.&quot; includes=&quot;foo,bar&quot;/&gt;
 &lt;/length&gt;
 </pre>
-<p>Adds the length of <i>foo</i> and <i>bar</i> and stores the result in property <i>length</i>.</p>
-
 
 </body>
 </html>
-
diff --git a/manual/Tasks/link.html b/manual/Tasks/link.html
new file mode 100644
index 0000000..a441357
--- /dev/null
+++ b/manual/Tasks/link.html
@@ -0,0 +1,580 @@
+<!DOCTYPE html>
+<!--
+   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
+
+       https://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">
+
+<head>
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<title>Link Task</title>
+</head>
+
+<body>
+
+<h2 id="link">Link</h2>
+<p><em>Since Apache Ant 1.10.6</em></p>
+
+<h3>Description</h3>
+<p>Assembles jmod files into an executable image.  Equivalent to the JDK's
+<a href="https://docs.oracle.com/en/java/javase/11/tools/jlink.html">jlink</a>
+tool.
+</p>
+<p>Requires Java 9 or later.</p>
+
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>destDir</td>
+    <td>Root directory of created image.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>modulepath</td>
+    <td>Path-like sequence of jmod files to link in order to create image.</td>
+    <td rowspan="2">One of these is required, unless a nested
+        <code>&lt;modulepath&gt;</code> is present.</td>
+  </tr>
+  <tr>
+    <td>modulepathref</td>
+    <td class="left">Path-like sequence of jmod files to link in order to
+        create image, given as a <a href="../using.html#references">reference</a>
+        to a path defined elsewhere.</td>
+  </tr>
+  <tr>
+    <td>modules</td>
+    <td>Comma-separated list of modules to place in the linked image.</td>
+    <td>Yes, unless one or more nested <code>&lt;module&gt;</code> elements
+        are present.</td>
+  </tr>
+  <tr>
+    <td>observableModules</td>
+    <td>Comma-separated list of explicit modules that comprise
+        "universe" visible to link tool while linking.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>launchers</td>
+    <td>Comma-separated list of commands, each of the form
+        <var>name</var><code>=</code><var>module</var> or
+        <var>name</var><code>=</code><var>module</var><code>/</code><var>mainclass</var></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>locales</td>
+    <td>Comma-separated list of extra locales, or wildcard patterns matching
+        multiple locale names, to include.
+        Requires <code>jdk.localedata</code> module.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>excludeResources</td>
+    <td>Comma-separated list of patterns specifying resources to exclude
+        from source jmods.  Each is either a
+        <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        or <code>@</code><var>filename</var>, indicating a text file with
+        one resource name per line.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>excludeFiles</td>
+    <td>Comma-separated list of patterns specifying files to exclude
+        from linked image.  Each is either a
+        <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        or <code>@</code><var>filename</var>, indicating a text file with
+        one file name per line.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>resourceOrder</td>
+    <td>Comma-separated list of patterns specifying resource search order.
+        Each is either a
+        <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        or <code>@</code><var>filename</var>, indicating a text file with
+        one resource name per line.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>bindServices</td>
+    <td>Boolean, whether to include in linked image any service providers
+        found in module path corresponding to service provider interfaces
+        used by explicitly linked modules.</td>
+    <td>No, default is false</td>
+  </tr>
+  <tr>
+    <td>ignoreSigning</td>
+    <td>Boolean, whether to allow signed jar files.
+        (Note: As of Java 11, this is ignored and is always treated as true.)</td>
+    <td>No, default is false</td>
+  </tr>
+  <tr>
+    <td>includeHeaders</td>
+    <td>Boolean, whether to include header files in linked image.</td>
+    <td>No, default is true</td>
+  </tr>
+  <tr>
+    <td>includeManPages</td>
+    <td>Boolean, whether to include man pages in linked image.</td>
+    <td>No, default is true</td>
+  </tr>
+  <tr>
+    <td>includeNativeCommands</td>
+    <td>Boolean, whether to include native executables in linked image.</td>
+    <td>No, default is true</td>
+  </tr>
+  <tr>
+    <td>debug</td>
+    <td>Boolean, whether to include debug information.</td>
+    <td>No, default is true</td>
+  </tr>
+  <tr>
+    <td>verboseLevel</td>
+    <td>If set, the linker will produce verbose output, which will be logged at
+        the specified Ant log level (<code>DEBUG</code>, <code>VERBOSE</code>,
+        <code>INFO</code>, <code>WARN</code>, or <code>ERR</code>).</td>
+    <td>No, default is no verbose output</td>
+  </tr>
+  <tr>
+    <td>compress</td>
+    <td>Compression level of linked image. One of:
+        <dl>
+        <dt><code>0</code> or
+            <code>none</code></dt>
+        <dd>no compression (default)</dd>
+        <dt><code>1</code> or
+            <code>strings</code></dt>
+        <dd>constant string sharing</dd>
+        <dt><code>2</code> or
+            <code>zip</code></dt>
+        <dd>zip compression</dd>
+        </dl>
+    </td>
+    <td>No, default is no compression</td>
+  </tr>
+  <tr>
+    <td>endianness</td>
+    <td>Byte order of linked image, must be <code>little</code> or <code>big</code>
+    <td>No, default is native byte order</td>
+  </tr>
+  <tr>
+    <td>checkDuplicateLegal</td>
+    <td>Boolean.  When merging legal notices from different modules
+        because they have the same name, verify that their contents
+        are identical.</td>
+    <td>No, default is false, which means any license files
+        with the same name are assumed to have the same content, and no
+        checking is done.</td>
+  </tr>
+  <tr>
+    <td>vmType</td>
+    <td>Hotspot VM in image. One of:
+        <ul>
+        <li><code>client</code>
+        <li><code>server</code>
+        <li><code>minimal</code>
+        <li><code>all</code>
+        </ul>
+    </td>
+    <td>No, default is <code>all</code></td>
+  </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+
+<p><code>&lt;link&gt;</code> can have the following nested elements:</p>
+<ul>
+<li><a href="#nested-modulepath">modulepath</a></li>
+<li><a href="#nested-module">module</a></li>
+<li><a href="#nested-observableModule">observableModule</a></li>
+<li><a href="#nested-launcher">launcher</a></li>
+<li><a href="#nested-locale">locale</a></li>
+<li><a href="#nested-resourceOrder">resourceOrder</a></li>
+<li><a href="#nested-excludeResources">excludeResources</a></li>
+<li><a href="#nested-excludeFiles">excludeFiles</a></li>
+<li><a href="#nested-compress">compress</a></li>
+<li><a href="#nested-releaseInfo">releaseInfo</a></li>
+</ul>
+
+<h4 id="nested-modulepath">modulepath</h4>
+<p><a href="../using.html#path">Path-like structure</a> pointing to
+    jmod files to link into image.</p>
+
+<h4 id="nested-module">module</h4>
+<p>Names a single module to be placed in the linked image.  This may be
+specified multiple times.</p>
+<p>Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>Name of module to add.</td>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h4 id="nested-observableModule">observableModule</h4>
+<p>Names a module visible to the linking process, instead of every module
+in the module path being considered.  This may be specified multiple times.
+<p>Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>Name of module to add to list of observable modules.</td>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h4 id="nested-launcher">launcher</h4>
+<p>Specifies an executable file which will be added to the linked image,
+which executes a particular module's main class.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>Name of launcher.  This typically is used for the name of the
+        executable file.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>module</td>
+    <td>Name of module to execute.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>mainClass</td>
+    <td>Name of entry point class in module to execute.</td>
+    <td>Required unless module has its own main class defined.</td>
+  </tr>
+</table>
+
+<h4 id="nested-locale">locale</h4>
+<p>Specifies locales to include in linked image.  May be specified multiple
+times.  Requires <code>jdk.localedata</code> module.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>Name of locale, or wildcard pattern with <q><code>*</code></q>
+        that matches multiple locale names.</td>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h4 id="nested-resourceOrder">resourceOrder</h4>
+<p>Explicit resource search order in linked image.  May be specified multiple
+times.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>pattern</td>
+    <td>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        for matching resources</td>
+    <td rowspan="2">Exactly one of these</td>
+  </tr>
+  <tr>
+    <td>listFile</td>
+    <td class="left">Text file containing list of resource names (not patterns),
+        one per line</td>
+  </tr>
+</table>
+
+<p>If the <code>resourceOrder</code> attribute is also present on the task, its
+patterns are treated as if they occur before patterns in nested
+<code>&lt;resourceOrder&gt;</code> elements.</p>
+
+<h4 id="nested-excludeResources">excludeResources</h4>
+<p>Excludes files from linked image tree.  May be specified multiple times.
+   Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>pattern</td>
+    <td>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        for matching resources</td>
+    <td rowspan="2">Exactly one of these</td>
+  </tr>
+  <tr>
+    <td>listFile</td>
+    <td class="left">Text file containing list of resource names (not patterns),
+        one per line</td>
+  </tr>
+</table>
+
+<h4 id="nested-excludeFiles">excludeFiles</h4>
+<p>Excludes files from linked image.  May be specified multiple times.
+   Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>pattern</td>
+    <td>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        for matching files</td>
+    <td rowspan="2">Exactly one of these</td>
+  </tr>
+  <tr>
+    <td>listFile</td>
+    <td class="left">Text file containing list of file names (not patterns),
+        one per line</td>
+  </tr>
+</table>
+
+<h4 id="nested-compress">compress</h4>
+<p>Describes how image should be compressed.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>level</td>
+    <td>Compression level of linked image. One of:
+        <dl>
+        <dt><code>0</code> or
+            <code>none</code></dt>
+        <dd>no compression (default)</dd>
+        <dt><code>1</code> or
+            <code>strings</code></dt>
+        <dd>constant string sharing</dd>
+        <dt><code>2</code> or
+            <code>zip</code></dt>
+        <dd>zip compression</dd>
+        </dl>
+    </td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>files</td>
+    <td>Comma-separated list of patterns matching files to compress.
+        Each pattern either a
+        <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        or <code>@</code><var>filename</var>, indicating a text file with
+        one file name per line.</td>
+    <td>No</td>
+  </tr>
+</table>
+
+<p><code>&lt;compress&gt;</code> can also have any number of nested
+<code>&lt;files&gt;</code> elements, with these attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>pattern</td>
+    <td>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+        for matching files</td>
+    <td rowspan="2">Exactly one of these</td>
+  </tr>
+  <tr>
+    <td>listFile</td>
+    <td class="left">Text file containing list of file names (not patterns),
+        one per line</td>
+  </tr>
+</table>
+
+<h4 id="nested-releaseInfo">releaseInfo</h4>
+<p>Replaces, augments, or trims the image's release info properties.
+Can be specified multiple times.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>file</td>
+    <td>Java properties file containing new release info properties
+        that will entirely replace the current ones.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>delete</td>
+    <td>Comma-separated property keys to remove from application's
+        release info
+    <td>No</td>
+  </tr>
+</table>
+
+<p><code>&lt;releaseInfo&gt;</code> can also have any number of these nested elements:</p>
+<h5>add</h5>
+<p>Specifies additional release info properties.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>key</td>
+    <td>Key of single property to add.</td>
+    <td rowspan="2">Yes, unless <code>file</code> is specified</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td class="left">Value of single property to add.</td>
+  </tr>
+  <tr>
+    <td>file</td>
+    <td>Java property file containing any number of properties to add.</td>
+    <td>Yes, unless <code>key</code> and <code>value</code> are specified</td>
+  </tr>
+  <tr>
+    <td>charset</td>
+    <td>Character set of property file.</td>
+    <td>No, default is <code>ISO_8859_1</code>, in accordance with
+        java.util.Properties class.</td>
+  </tr>
+</table>
+
+<h5>delete</h5>
+<p>Property keys to remove from applicaiton's release info.  Attributes:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>key</td>
+    <td>Key of property to remove.</td>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h3>Examples</h3>
+<h4>Basic linking</h4>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+&lt;link destDir="build/image" modulepath="MyApp.jmod"
+      modules="com.example.myapp"/&gt;
+</pre>
+
+<h4>Custom binaries</h4>
+<p>This will cause a <samp>bin/MyEditor</samp> script to appear in the
+image:
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+&lt;link destDir="build/image" modulepath="MyApp.jmod"
+      modules="com.example.myapp"
+      launchers="MyEditor=com.example.myapp/com.example.myapp.editors.EditorMain"/&gt;
+</pre>
+
+<p>Same thing, using a nested launcher element:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+&lt;link destDir="build/image" modulepath="MyApp.jmod"
+      modules="com.example.myapp"&gt;
+
+    &lt;launcher name="MyEditor" module="com.example.myapp"
+              mainClass="com.example.myapp.editors.EditorMain"/&gt;
+
+&lt;/link&gt;
+</pre>
+
+<h4>Limiting locales</h4>
+<p>Include just the locales needed by the application from the <a href="https://docs.oracle.com/en/java/javase/11/docs/api/jdk.localedata/module-summary.html">jdk.localedata</a> module:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+&lt;link destDir="build/image" modulepath="MyApp.jmod"
+      modules="com.example.myapp,jdk.localedata"
+      locales="zh,jp-*"/&gt;
+</pre>
+
+<h4>Compressed image</h4>
+<p>Compress entire image:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+&lt;link destDir="build/image" modulepath="MyApp.jmod"
+      modules="com.example.myapp,jdk.localedata"
+      compress="zip"/&gt;
+</pre>
+
+<p>Compress only some files in the image:</p>
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar"/&gt;
+&lt;link destDir="build/image" modulepath="MyApp.jmod"
+      modules="com.example.myapp,jdk.localedata"&gt;
+
+    &lt;compress level="zip" files=".*\.xml"/&gt;
+
+&lt;/link&gt;
+</pre>
+
+<h4>Cross-compiling</h4>
+<p>To create an image for a different platform:
+
+<ul>
+<li>Download the JDK for that platform, and expand the archive manually into
+a directory of your choice.  (Downloading a zip or tar.gz version of a JDK
+instead of an installer will make this easier.)</li>
+<li>Determine the foreign JDK's platform string.  This can be done with
+a command that examines the JDK's <samp>jmods/java.base.jmod</samp> file:
+<pre>
+jmod describe "$FOREIGN_JDK_HOME"/jmods/java.base.jmod | grep '^platform'
+</pre>
+</li>
+<li>Create your jmod using the foreign JDK's platform string:
+<pre>
+&lt;jmod destfile="MyApp.jmod" classpath="build/myapp.jar" platform="windows-amd64"/&gt;
+</pre>
+</li>
+<li>Link with the foreign JDK's <samp>jmods</samp> directory in the module path:
+<pre>
+&lt;link destDir="build/image"
+      modulepath="MyApp.jmod;${foreign-jdk-home}/jmods"
+      modules="com.example.myapp"/&gt;
+</pre>
+</li>
+</ul>
+
+</body>
+</html>
diff --git a/manual/Tasks/loadfile.html b/manual/Tasks/loadfile.html
index 59291ed..0c8c216 100644
--- a/manual/Tasks/loadfile.html
+++ b/manual/Tasks/loadfile.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>LoadFile Task</title>
@@ -22,112 +23,98 @@
 
 <body>
 
-
-<h2><a name="loadfile">LoadFile</a></h2>
+<h2 id="loadfile">LoadFile</h2>
 <h3>Description</h3>
-<p>
-Specialization of <a href="loadresource.html">loadresource</a> that
-works on files exclusively and provides a srcFile attribute for
-convenience.  Unless an encoding is specified, the encoding of the
-current locale is used.
-</p>
-<p>If the resource content is empty (maybe after processing a filterchain) 
-the property is not set.</p>
-
+<p>Specialization of <a href="loadresource.html">loadresource</a> that works on files exclusively
+and provides a <var>srcFile</var> attribute for convenience.  Unless an <var>encoding</var> is
+specified, the encoding of the current locale is used.</p>
+<p>If the resource content is empty (maybe after processing a <code>filterchain</code>) the property
+is not set.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">srcFile</td>
-    <td valign="top">source file</td>
-    <td valign="top" align="center">Yes</td>
+    <td>srcFile</td>
+    <td>source file</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">property to save to</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>property to save to</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">encoding to use when loading the file</td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>encoding to use when loading the file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Whether to halt the build on failure</td>
-    <td align="center" valign="top">No, default "true"</td>
+    <td>failonerror</td>
+    <td>Whether to halt the build on failure</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">Do not display a diagnostic message (unless Apache Ant has been 
-    invoked with the <code>-verbose</code> or <code>-debug</code>
-    switches) or modify the exit status to reflect an error. Setting this to 
-    "true" implies setting failonerror to "false".
-      <em>Since Ant 1.7.0.</em>
+    <td>quiet</td>
+    <td>Do not display a diagnostic message (unless Apache Ant has been invoked with
+      the <kbd>-verbose</kbd> or <kbd>-debug</kbd> switches) or modify the exit status to
+      reflect an error. Setting this to <q>true</q> implies setting <var>failonerror</var>
+      to <q>false</q>. <em>Since Ant 1.7.0</em>.
     </td>
-    <td align="center" valign="top">No, default "false"</td>
+    <td>No; default <q>false</q></td>
   </tr>
 
 </table>
-<p>
-The LoadFile task supports nested <a href="../Types/filterchain.html">
-FilterChain</a>s.
+<p>The LoadFile task supports nested <a href="../Types/filterchain.html">FilterChain</a>s.</p>
 
 <h3>Examples</h3>
-<pre>    &lt;loadfile property="message"
-      srcFile="message.txt"/&gt;
-</pre>
-Load file message.txt into property "message"; an <tt>&lt;echo&gt;</tt>
-can print this.  This is identical to
-<pre>    &lt;loadresource property="message"&gt;
-       &lt;file file="message.txt"/&gt;
-    &lt;/loadresource&gt;
-</pre>
-</p>
+<p>Load file <samp>message.txt</samp> into property <code>message</code>;
+an <code>&lt;echo&gt;</code> can print this.</p>
+<pre>
+&lt;loadfile property="message"
+          srcFile="message.txt"/&gt;</pre>
 
-<pre>    &lt;loadfile property="encoded-file"
-      srcFile="loadfile.xml"
-      encoding="ISO-8859-1"/&gt;
-</pre>
-Load a file using the latin-1 encoding
+<p>The above is identical to</p>
+<pre>
+&lt;loadresource property="message"&gt;
+    &lt;file file="message.txt"/&gt;
+&lt;/loadresource&gt;</pre>
 
-<pre>    &lt;loadfile
-      property="optional.value"
-      srcFile="optional.txt"
-      failonerror="false"/&gt;
-</pre>
-Load a file, don't fail if it is missing (a message is printed, though)
+<p>Load a file using the Latin-1 encoding</p>
+<pre>
+&lt;loadfile property="encoded-file"
+          srcFile="loadfile.xml"
+          encoding="ISO-8859-1"/&gt;</pre>
 
-<pre>    &lt;loadfile
-      property="mail.recipients"
-      srcFile="recipientlist.txt"&gt;
-      &lt;filterchain&gt;
+<p>Load a file, don't fail if it is missing (a message is printed, though)</p>
+<pre>
+&lt;loadfile property="optional.value"
+          srcFile="optional.txt"
+          failonerror="false"/&gt;</pre>
+
+<p>Load a property which can be used as a parameter for another task (in this
+case <code>mail</code>), merging lines to ensure this happens.</p>
+<pre>
+&lt;loadfile property="mail.recipients"
+          srcFile="recipientlist.txt"&gt;
+    &lt;filterchain&gt;
         &lt;<a href="../Types/filterchain.html#striplinebreaks">striplinebreaks</a>/&gt;
-      &lt;/filterchain&gt;
-    &lt;/loadfile&gt;
-</pre>
-Load a property which can be used as a parameter for another task (in this case mail),
-merging lines to ensure this happens.
+    &lt;/filterchain&gt;
+&lt;/loadfile&gt;</pre>
 
-<pre>    &lt;loadfile
-      property="system.configuration.xml"
-      srcFile="configuration.xml"&gt;
-        &lt;filterchain&gt;
-          &lt;<a href="../Types/filterchain.html#expandproperties">expandproperties</a>/&gt;
-        &lt;/filterchain&gt;
-    &lt;/loadfile&gt;
-</pre>
-Load an XML file into a property, expanding all properties declared
-in the file in the process.
-
-
-
+<p>Load an XML file into a property, expanding all properties declared in the file in the
+process.</p>
+<pre>
+&lt;loadfile property="system.configuration.xml"
+          srcFile="configuration.xml"&gt;
+    &lt;filterchain&gt;
+        &lt;<a href="../Types/filterchain.html#expandproperties">expandproperties</a>/&gt;
+    &lt;/filterchain&gt;
+&lt;/loadfile&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/loadproperties.html b/manual/Tasks/loadproperties.html
index 69fa23a..7d9eccc 100644
--- a/manual/Tasks/loadproperties.html
+++ b/manual/Tasks/loadproperties.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>LoadProperties Task</title>
@@ -23,68 +24,60 @@
 <body>
 
 
-<h2><a name="loadproperties">LoadProperties</a></h2>
+<h2 id="loadproperties">LoadProperties</h2>
 <h3>Description</h3>
-<p>
-Load a file's contents as Apache Ant properties.  This is equivalent
-to <code>&lt;property file|resource=&quot;...&quot;/&gt;</code> except that it
-supports nested <code>&lt;filterchain&gt;</code> elements.
-Also if the file is missing, the build is halted with an error, rather
-than a warning being printed.
-</p>
+<p>Load a file's contents as Apache Ant properties.  This is equivalent to <code>&lt;property
+file|resource=<q>...</q>/&gt;</code> except that it supports nested <code>&lt;filterchain&gt;</code>
+elements.  Also if the file is missing, the build is halted with an error, rather than a warning
+being printed.</p>
 
-<p><strong>Note:</strong> the default value of this
-task's <code>prefixValues</code> attribute is different from the
-default value of the same attribute in
-the <a href="property.html"><code>&lt;property&gt;</code></a>
-task.</p>
+<p><strong>Note</strong>: the default value of this task's <var>prefixValues</var> attribute is
+different from the default value of the same attribute in
+the <a href="property.html"><code>&lt;property&gt;</code></a> task.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">srcFile</td>
-    <td valign="top">source file</td>
-    <td valign="top" rowspan="2" align="center">One of these or a
-          nested resource</td>
+    <td>srcFile</td>
+    <td>source file</td>
+    <td rowspan="2">One of these or a nested resource</td>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top">the resource name of the property file</td>
+    <td>resource</td>
+    <td class="left">the resource name of the property file</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">encoding to use when loading the file</td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>encoding to use when loading the file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use when looking up a resource.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>the classpath to use when looking up a resource.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">the classpath to use when looking up a resource,
-      given as <a href="../using.html#references">reference</a>
-      to a <code>&lt;path&gt;</code> defined elsewhere..</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>the classpath to use when looking up a resource, given
+      as <a href="../using.html#references">reference</a> to a <code>&lt;path&gt;</code> defined
+      elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">Prefix to apply to loaded properties;
-      a "." is appended to the prefix if not specified. <em>Since Ant 1.8.1</em></td>
-    <td align="center" valign="top">No</td>
+    <td>prefix</td>
+    <td>Prefix to apply to loaded properties. <em>Since Ant 1.8.1</em></td>
+    <td>No; default is <q>.</q></td>
   </tr>
   <tr>
-    <td valign="top">prefixValues</td>
-    <td valign="top">Whether to apply the prefix when expanding the
-      right hand side of the properties.
-      <em>Since Ant 1.8.2</em></td>
-    <td align="center" valign="top">No (default=<tt>true</tt>)</td>
+    <td>prefixValues</td>
+    <td>Whether to apply the prefix when expanding the right hand side of the properties.  <em>Since
+      Ant 1.8.2</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
@@ -93,48 +86,45 @@
 <h4>any <a href="../Types/resources.html">resource</a> or single element
 resource collection</h4>
 
-<p>The specified resource will be used as src. <em>Since Ant 1.7</em></p>
+<p><em>Since Ant 1.7</em></p>
+
+<p>The specified resource will be used as <var>srcFile</var> or <var>resource</var>.</p>
 
 <h4><a href="../Types/filterchain.html">FilterChain</a></h4>
 
 <h4>classpath</h4>
 
-<p>for use with the <i>resource</i> attribute.</p>
+<p>for use with the <var>resource</var> attribute.</p>
 
 <h3>Examples</h3>
-<pre>    &lt;loadproperties srcFile="file.properties"/&gt;
-</pre>
-or
-<pre>
-    &lt;loadproperties&gt;
-      &lt;file file="file.properties"/&gt;
-    &lt;/loadproperties&gt;
-</pre>
-Load contents of file.properties as Ant properties.
 
-<pre>    &lt;loadproperties srcFile="file.properties"&gt;
-      &lt;filterchain&gt;
+<p>Load contents of <samp>file.properties</samp> as Ant properties.</p>
+<pre>&lt;loadproperties srcFile="file.properties"/&gt;</pre>
+<p>or</p>
+<pre>
+&lt;loadproperties&gt;
+    &lt;file file="file.properties"/&gt;
+&lt;/loadproperties&gt;</pre>
+
+<p>Read the lines that contain the string <q>import.</q> from the file <samp>file.properties</samp>
+and load them as Ant properties.</p>
+<pre>
+&lt;loadproperties srcFile="file.properties"&gt;
+    &lt;filterchain&gt;
         &lt;<a href="../Types/filterchain.html#linecontains">linecontains</a>&gt;
-          &lt;contains value=&quot;import.&quot;/&gt;
+            &lt;contains value=&quot;import.&quot;/&gt;
         &lt;/linecontains&gt;
-      &lt;/filterchain&gt;
-    &lt;/loadproperties&gt;
-</pre>
-Read the lines that contain the string &quot;import.&quot;
-from the file &quot;file.properties&quot; and load them as
-Ant properties.
+    &lt;/filterchain&gt;
+&lt;/loadproperties&gt;</pre>
 
+<p>Load contents of <samp>https://example.org/url.properties.gz</samp>, uncompress it on the fly and
+load the contents as Ant properties.</p>
 <pre>
-    &lt;loadproperties&gt;
-      &lt;<a href="../Types/resources.html#gzipresource">gzipresource</a>&gt;
-        &lt;<a href="../Types/resources.html#url">url</a> url="http://example.org/url.properties.gz"/&gt;
-      &lt;/gzipresource&gt;
-    &lt;/loadproperties&gt;
-</pre>
-Load contents of http://example.org/url.properties.gz, uncompress it
-on the fly and load the contents as Ant properties.
-
-
+&lt;loadproperties&gt;
+    &lt;<a href="../Types/resources.html#gzipresource">gzipresource</a>&gt;
+        &lt;<a href="../Types/resources.html#url">url</a> url="https://example.org/url.properties.gz"/&gt;
+    &lt;/gzipresource&gt;
+&lt;/loadproperties&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/loadresource.html b/manual/Tasks/loadresource.html
index f2b20c0..28b6a45 100644
--- a/manual/Tasks/loadresource.html
+++ b/manual/Tasks/loadresource.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>LoadResource Task</title>
@@ -23,71 +24,62 @@
 <body>
 
 
-<h2><a name="loadresource">LoadResource</a></h2>
+<h2 id="loadresource">LoadResource</h2>
 
 <p><em>Since Apache Ant 1.7</em></p>
 
 <h3>Description</h3>
-<p>
-Load a text resource into a single property. Unless an encoding is
-specified, the encoding of the current locale is used.  Resources to
-load are specified as nested <a
-href="../Types/resources.html">resource</a> elements or single
-element resource collections. If the resource content is empty (maybe after
-processing a filterchain) the property is not set.
-</p>
+<p>Load a text resource into a single property. Unless an encoding is specified, the encoding of the
+current locale is used.  Resources to load are specified as
+nested <a href="../Types/resources.html">resource</a> elements or single element resource
+collections. If the resource content is empty (maybe after processing a <code>filterchain</code>)
+the property is not set.</p>
 
-<p>Since properties are immutable, the task will not change the value
-  of an existing property.</p>
+<p>Since properties are immutable, the task will not change the value of an existing property.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">property to save to</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>property to save to</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">encoding to use when loading the resource</td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>encoding to use when loading the resource</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Whether to halt the build on failure</td>
-    <td align="center" valign="top">No, default "true"</td>
+    <td>failonerror</td>
+    <td>Whether to halt the build on failure</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">Do not display a diagnostic message (unless Ant has been 
-    invoked with the <code>-verbose</code> or <code>-debug</code>
-    switches) or modify the exit status to reflect an error. Setting this to 
-    "true" implies setting failonerror to "false".
-    </td>
-    <td align="center" valign="top">No, default "false"</td>
+    <td>quiet</td>
+    <td>Do not display a diagnostic message (unless Ant has been invoked with
+      the <kbd>-verbose</kbd> or <kbd>-debug</kbd> switches) or modify the exit status to
+      reflect an error. Setting this to <q>true</q> implies setting <var>failonerror</var>
+      to <q>false</q>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
-<p>
-The LoadResource task supports nested <a href="../Types/filterchain.html">
-FilterChain</a>s.
+<p>The LoadResource task supports nested <a href="../Types/filterchain.html">FilterChain</a>s.</p>
 
 <h3>Examples</h3>
+
+<p>Load the entry point of Ant's homepage into property <code>homepage</code>;
+an <code>&lt;echo&gt;</code> can print this.</p>
 <pre>
 &lt;loadresource property="homepage"&gt;
-  &lt;url url="http://ant.apache.org/index.html"/&gt;
-&lt;/loadresource&gt;
-</pre>
-Load the entry point of Ant's homepage into property "homepage"; an
-<tt>&lt;echo&gt;</tt> can print this.
+    &lt;url url="https://ant.apache.org/index.html"/&gt;
+&lt;/loadresource&gt;</pre>
 
 <p>For more examples see the <a href="loadfile.html">loadfile</a> task.</p>
 
-
 </body>
 </html>
-
diff --git a/manual/Tasks/local.html b/manual/Tasks/local.html
index c7ed8fc..940622a 100644
--- a/manual/Tasks/local.html
+++ b/manual/Tasks/local.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Local Task</title>
 </head>
@@ -25,162 +25,167 @@
 <body>
 
 <h2>Local</h2>
+<p><em>Since Ant 1.8</em></p>
 <h3>Description</h3>
-<p>Adds a local property to the current scope. Property scopes exist at Apache Ant's
-various "block" levels. These include targets as well as the
-<a href="parallel.html">Parallel</a> and <a href="sequential.html">Sequential</a>
-task containers (including <a href="macrodef.html">Macrodef</a> bodies). A local
-property at a given scope "shadows" properties of the same name at higher scopes,
-including the global scope. Note that using the Local task at the global
-level effectively makes the property local to the "anonymous target" in which
-top-level operations are carried out; it will not be defined for other targets
-in the buildfile. <b>Since Ant 1.8</b></p>
+<p>Adds a local property to the current scope. Property scopes exist at Apache Ant's various "block"
+levels. These include targets as well as the <a href="parallel.html">Parallel</a>
+and <a href="sequential.html">Sequential</a> task containers
+(including <a href="macrodef.html">Macrodef</a> bodies). A local property at a given scope "shadows"
+properties of the same name at higher scopes, including the global scope. Note that using
+the <code>Local</code> task at the global level effectively makes the property local to the
+"anonymous target" in which top-level operations are carried out; it will not be defined for other
+targets in the buildfile.</p>
 
-<p>A property is made local if the <code>&lt;local&gt;</code> task
-  precedes its definition.  See the examples section.</p>
+<p>A property is made local if the <code>&lt;local&gt;</code> task precedes its definition.  See the
+examples section.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0"> 
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The property to declare in the current scope</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>The property to declare in the current scope</td>
+    <td>Yes</td>
   </tr>
 </table>
 
+<h3>Parameters specified as nested elements</h3>
+<h4>Name</h4>
+<p>As an alternative to (or in conjunction with) the <code>name</code> attribute, the nested text of
+each of one or more nested <code>&lt;name&gt;</code> elements specifies a property name to declare in
+the local scope. <em>Since Ant 1.10.13</em></p>
+
 <h3>Examples</h3>
 
 <h4>Temporarily shadow a global property's value</h4>
 
 <pre>
-    &lt;property name="foo" value="foo"/&gt;
+&lt;property name="foo" value="foo"/&gt;
 
-    &lt;target name="step1"&gt;
-        &lt;echo&gt;Before local: foo is ${foo}&lt;/echo&gt;
-        &lt;local name="foo"/&gt;
-        &lt;property name="foo" value="bar"/&gt;
-        &lt;echo&gt;After local: foo is ${foo}&lt;/echo&gt;
-    &lt;/target&gt;
+&lt;target name="step1"&gt;
+    &lt;echo&gt;Before local: foo is ${foo}&lt;/echo&gt;
+    &lt;local name="foo"/&gt;
+    &lt;property name="foo" value="bar"/&gt;
+    &lt;echo&gt;After local: foo is ${foo}&lt;/echo&gt;
+&lt;/target&gt;
 
-    &lt;target name="step2" depends="step1"&gt;
-        &lt;echo&gt;In step2: foo is ${foo}&lt;/echo&gt;
-    &lt;/target&gt;
-</pre>
+&lt;target name="step2" depends="step1"&gt;
+    &lt;echo&gt;In step2: foo is ${foo}&lt;/echo&gt;
+&lt;/target&gt;</pre>
 
 <p>outputs</p>
 
-<pre>
+<pre class="output">
 step1:
      [echo] Before local: foo is foo
      [echo] After local: foo is bar
 
 step2:
-     [echo] In step2: foo is foo
-</pre>
+     [echo] In step2: foo is foo</pre>
 
-<p>here the local-task shadowed the global definition
-  of <code>foo</code> for the remainder of the target step1.</p>
+<p>here the <code>local</code> task shadowed the global definition of <code>foo</code> for the
+remainder of the target <q>step1</q>.</p>
 
 <h4>Creating thread local properties</h4>
 
 <pre>
-    &lt;property name="foo" value="foo"/&gt;
+&lt;property name="foo" value="foo"/&gt;
 
-    &lt;parallel&gt;
-        &lt;echo&gt;global 1: foo is ${foo}&lt;/echo&gt;
-        &lt;sequential&gt;
-            &lt;local name="foo"/&gt;
-            &lt;property name="foo" value="bar.1"/&gt;
-            &lt;echo&gt;First sequential: foo is ${foo}&lt;/echo&gt;
-        &lt;/sequential&gt;
-        &lt;sequential&gt;
-            &lt;sleep seconds="1"/&gt;
-            &lt;echo&gt;global 2: foo is ${foo}&lt;/echo&gt;
-        &lt;/sequential&gt;
-        &lt;sequential&gt;
-            &lt;local name="foo"/&gt;
-            &lt;property name="foo" value="bar.2"/&gt;
-            &lt;echo&gt;Second sequential: foo is ${foo}&lt;/echo&gt;
-        &lt;/sequential&gt;
-        &lt;echo&gt;global 3: foo is ${foo}&lt;/echo&gt;
-    &lt;/parallel&gt;
-</pre>
+&lt;parallel&gt;
+    &lt;echo&gt;global 1: foo is ${foo}&lt;/echo&gt;
+    &lt;sequential&gt;
+        &lt;local name="foo"/&gt;
+        &lt;property name="foo" value="bar.1"/&gt;
+        &lt;echo&gt;First sequential: foo is ${foo}&lt;/echo&gt;
+    &lt;/sequential&gt;
+    &lt;sequential&gt;
+        &lt;sleep seconds="1"/&gt;
+        &lt;echo&gt;global 2: foo is ${foo}&lt;/echo&gt;
+    &lt;/sequential&gt;
+    &lt;sequential&gt;
+        &lt;local name="foo"/&gt;
+        &lt;property name="foo" value="bar.2"/&gt;
+        &lt;echo&gt;Second sequential: foo is ${foo}&lt;/echo&gt;
+    &lt;/sequential&gt;
+    &lt;echo&gt;global 3: foo is ${foo}&lt;/echo&gt;
+&lt;/parallel&gt;</pre>
 
 <p>outputs something similar to</p>
 
-<pre>
-     [echo] global 3: foo is foo
-     [echo] global 1: foo is foo
-     [echo] First sequential: foo is bar.1
-     [echo] Second sequential: foo is bar.2
-     [echo] global 2: foo is foo
-</pre>
+<pre class="output">
+    [echo] global 3: foo is foo
+    [echo] global 1: foo is foo
+    [echo] First sequential: foo is bar.1
+    [echo] Second sequential: foo is bar.2
+    [echo] global 2: foo is foo</pre>
 
-<h4>Use inside macrodef</h4>
+<h4>Use inside <code>macrodef</code></h4>
 
-<p>This probably is where local can be applied in the most useful
-  way.  If you needed a "temporary property" inside a macrodef in Ant
-  prior to Ant 1.8.0 you had to try to come up with a property name
-  that would be unique across macro invocations.</p>
+<p>This probably is where <code>local</code> can be applied in the most useful way.  If you needed a
+"temporary property" inside a <code>macrodef</code> in Ant prior to Ant 1.8.0 you had to try to come
+up with a property name that would be unique across macro invocations.</p>
 
-<p>Say you wanted to write a macro that created the parent directory
-  of a given file.  A naive approach would be:</p>
+<p>Say you wanted to write a macro that created the parent directory of a given file.  A naive
+approach would be:</p>
 
 <pre>
-    &lt;macrodef name="makeparentdir"&gt;
-        &lt;attribute name="file"/&gt;
-        &lt;sequential&gt;
-            &lt;dirname property="parent" file="@{file}"/&gt;
-            &lt;mkdir dir="${parent}"/&gt;
-        &lt;/sequential&gt;
-    &lt;/macrodef&gt;
-    &lt;makeparentdir file="some-dir/some-file"/&gt;
-</pre>
+&lt;macrodef name="makeparentdir"&gt;
+    &lt;attribute name="file"/&gt;
+    &lt;sequential&gt;
+        &lt;dirname property="parent" file="@{file}"/&gt;
+        &lt;mkdir dir="${parent}"/&gt;
+    &lt;/sequential&gt;
+&lt;/macrodef&gt;
+&lt;makeparentdir file="some-dir/some-file"/&gt;</pre>
 
-<p>but this would create a global property "parent" on the first
-  invocation - and since properties are not mutable, any subsequent
-  invocation will see the same value and try to create the same
-  directory as the first invocation.</p>
+<p>but this would create a global property <code>parent</code> on the first invocation&mdash;and
+since properties are not mutable, any subsequent invocation will see the same value and try to
+create the same directory as the first invocation.</p>
 
-<p>The recommendation prior to Ant 1.8.0 was to use a property name
-  based on one of the macro's attributes, like</p>
+<p>The recommendation prior to Ant 1.8.0 was to use a property name based on one of the macro's
+attributes, like</p>
 
 <pre>
-    &lt;macrodef name="makeparentdir"&gt;
-        &lt;attribute name="file"/&gt;
-        &lt;sequential&gt;
-            &lt;dirname property="parent.@{file}" file="@{file}"/&gt;
-            &lt;mkdir dir="${parent.@{file}}"/&gt;
-        &lt;/sequential&gt;
-    &lt;/macrodef&gt;
-</pre>
+&lt;macrodef name="makeparentdir"&gt;
+    &lt;attribute name="file"/&gt;
+    &lt;sequential&gt;
+        &lt;dirname property="parent.@{file}" file="@{file}"/&gt;
+        &lt;mkdir dir="${parent.@{file}}"/&gt;
+    &lt;/sequential&gt;
+&lt;/macrodef&gt;</pre>
 
-<p>Now invocations for different files will set different properties
-  and the directories will get created.  Unfortunately this "pollutes"
-  the global properties space.  In addition it may be hard to come up
-  with unique names in some cases.</p>
+<p>Now invocations for different files will set different properties and the directories will get
+created.  Unfortunately this "pollutes" the global properties space.  In addition, it may be hard to
+come up with unique names in some cases.</p>
 
 <p>Enter <code>&lt;local&gt;</code>:</p>
 
 <pre>
-    &lt;macrodef name="makeparentdir"&gt;
-        &lt;attribute name="file"/&gt;
-        &lt;sequential&gt;
-            &lt;local name="parent"/&gt;
-            &lt;dirname property="parent" file="@{file}"/&gt;
-            &lt;mkdir dir="${parent}"/&gt;
-        &lt;/sequential&gt;
-    &lt;/macrodef&gt;
+&lt;macrodef name="makeparentdir"&gt;
+    &lt;attribute name="file"/&gt;
+    &lt;sequential&gt;
+        &lt;local name="parent"/&gt;
+        &lt;dirname property="parent" file="@{file}"/&gt;
+        &lt;mkdir dir="${parent}"/&gt;
+    &lt;/sequential&gt;
+&lt;/macrodef&gt;</pre>
+
+<p>Each invocation gets its own property named <code>parent</code> and there will be no global
+property of that name at all.</p>
+
+<h4>Use of nested name elements</h4>
+This style declares and executes a single task, as compensation for requiring more lines of XML than
+would individual invocations using <code>@name</code>:
+<pre>
+&lt;local&gt;
+  &lt;name&gt;foo&lt;/name&gt;
+  &lt;name&gt;bar&lt;/name&gt;
+  &lt;name&gt;baz&lt;/name&gt;
+&lt;/local&gt;
 </pre>
-
-<p>Each invocation gets its own property name "parent" and there will
-  be no global property of that name at all.</p>
-
 </body>
 </html>
-
diff --git a/manual/Tasks/macrodef.html b/manual/Tasks/macrodef.html
index 60b3072..a3f0064 100644
--- a/manual/Tasks/macrodef.html
+++ b/manual/Tasks/macrodef.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,284 +15,215 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
   <head>
-    <meta http-equiv="Content-Language" content="en-us"></meta>
     <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
     <title>MacroDef Task</title>
   </head>
 
   <body>
 
-    <h2><a name="macrodef">MacroDef</a></h2>
+    <h2 id="macrodef">MacroDef</h2>
+    <p><em>Since Apache Ant 1.6</em></p>
     <h3>Description</h3>
-    <p>
-      This defines a new task using a <code>&lt;sequential&gt;</code>
-      nested task as a template. Nested elements <code>&lt;attribute&gt;</code> and
-      <code>&lt;element&gt;</code> are used to specify attributes and elements of
-      the new task. These get substituted into the <code>&lt;sequential&gt;</code>
-      task when the new task is run.
-    </p>
+    <p>This defines a new task using a <code>&lt;sequential&gt;</code> nested task as a
+      template. Nested elements <code>&lt;attribute&gt;</code> and <code>&lt;element&gt;</code> are
+      used to specify attributes and elements of the new task. These get substituted into
+      the <code>&lt;sequential&gt;</code> task when the new task is run.</p>
     <h3>Note</h3>
-    <p>
-      You can also use <i>prior defined</i> attributes for default-values in
-      other attributes. See the examples.
-    </p>
-    <p>
-      <em>since Apache Ant 1.6</em>
-    </p>
+    <p>You can also use <em>prior defined</em> attributes for <var>default</var> values in other
+      attributes. See the examples.</p>
     <h3>Parameters</h3>
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">name</td>
-        <td valign="top">The name of the new definition.</td>
-        <td valign="top" align="center">Yes</td>
+        <td>name</td>
+        <td>The name of the new definition.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">uri</td>
-        <td valign="top">
+        <td>uri</td>
+        <td>
           The uri that this definition should live in.
         </td>
-        <td valign="top" align="center">No</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">description</td>
-        <td valign="top">A description of the macrodef
+        <td>description</td>
+        <td>A description of the macrodef
           (for documentation purposes only).
         </td>
-        <td valign="top" align="center">No</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">backtrace</td>
-        <td valign="top">
-          This controls the error traceback if there is an
-          error detected when running the macro. If this is
-          set to true, there will be an error trackback, if false
-          there will not be one. <em>Since Ant 1.7</em>.
-        </td>
-        <td valign="top" align="center">No; default <em>true</em></td>
+        <td>backtrace</td>
+        <td>This controls the error traceback if there is an error detected when running the
+          macro. If this is set to <q>true</q>, there will be an error trackback, if <q>false</q>
+          there will be none. <em>Since Ant 1.7</em>.</td>
+        <td>No; default <q>true</q></td>
       </tr>
     </table>
-      <h3>Parameters specified as nested elements</h3>
+    <h3>Parameters specified as nested elements</h3>
     <h4>attribute</h4>
-    <p>
-      This is used to specify attributes of the new task. The values
-      of the attributes get substituted into the templated task.
-      The attributes will be required attributes unless a default
-      value has been set.
-    </p>
-    <p>
-      This attribute is placed in the body of the templated
-      task using a notation similar to the ant property notation
-      - @{attribute name}. (May be remembered as "put the substitution
-      AT this location").
-    </p>
-    <p>
-      The escape sequence @@ is used to escape @. This allows @{x} to be
-      placed in the text without substitution of x by using @@{x}.
-      This corresponds to the $$ escape sequence for properties.
-    </p>
-    <p>
-      The case of the attribute is ignored, so @{myAttribute} is treated the
-      same as @{MyAttribute}.
-    </p>
-    <h3>Parameters</h3>
-    <table border="1" cellpadding="2" cellspacing="0">
+    <p>This is used to specify attributes of the new task. The values of the attributes get
+      substituted into the templated task.  The attributes will be required attributes unless a
+      default value has been set.</p>
+    <p>This attribute is placed in the body of the templated task using a notation similar to the
+      Ant property notation&mdash;<code>@{attribute name}</code>. (May be remembered as "put the
+      substitution AT this location").</p>
+    <p>The escape sequence <code>@@</code> is used to escape <code>@</code>. This
+      allows <code>@{x}</code> to be placed in the text without substitution of <code>x</code> by
+      using <code>@@{x}</code>.  This corresponds to the <code>$$</code> escape sequence for
+      properties.</p>
+    <p>The case of the attribute is ignored, so <code>@{myAttribute}</code> is treated the same
+      as <code>@{MyAttribute}</code>.</p>
+    <h5>Parameters</h5>
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">name</td>
-        <td valign="top">The name of the new attribute</td>
-        <td valign="top" align="center">Yes</td>
+        <td>name</td>
+        <td>The name of the new attribute</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">default</td>
-        <td valign="top">
-          The default value of the attribute.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>default</td>
+        <td>The default value of the attribute.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">description</td>
-        <td valign="top">
-          This contains a description of the attribute.
-          <em>since ant 1.6.1</em>
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>description</td>
+        <td>This contains a description of the attribute.  <em>Since Ant 1.6.1</em></td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">doubleexpanding</td>
-        <td valign="top">
-          Controls whether or not property references in the attribute are expanded twice or just once.
-          See the <a href="http://ant.apache.org/faq.html#macrodef-property-expansion">FAQ</a> for details.
-          <em>since Ant 1.8.3</em>
-        </td>
-        <td valign="top" align="center">No; default true</td>
+        <td>doubleexpanding</td>
+        <td>Controls whether or not property references in the attribute are expanded twice or just
+          once.  See the <a href="https://ant.apache.org/faq.html#macrodef-property-expansion"
+          target="_top">FAQ</a> for details.  <em>Since Ant 1.8.3</em></td>
+        <td>No; default is <q>true</q></td>
       </tr>
     </table>
     <h4>element</h4>
-    <p>
-      This is used to specify nested elements of the new task.
-      The contents of the nested elements of the task instance
-      are placed in the templated task at the tag name.
-    </p>
-    <p>
-      The case of the element name is ignored.
-    </p>
-    <h3>Parameters</h3>
-    <table border="1" cellpadding="2" cellspacing="0">
+    <p>This is used to specify nested elements of the new task.  The contents of the nested elements
+      of the task instance are placed in the templated task at the tag name.</p>
+    <p>The case of the <code>element</code> name is ignored.</p>
+    <h5>Parameters</h5>
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">name</td>
-        <td valign="top">The name of the element</td>
-        <td valign="top" align="center">Yes</td>
+        <td>name</td>
+        <td>The name of the element.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">optional</td>
-        <td valign="top">
-          If true this nested element is optional. Default is
-          false - i.e the nested element is required in
-          the new task.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>optional</td>
+        <td>If <q>true</q> this nested element is optional.</td>
+        <td>No; default is <q>false</q>&mdash;the nested element is required in the new task</td>
       </tr>
       <tr>
-        <td valign="top">implicit</td>
-        <td valign="top">
-          If true this nested element is implicit. This means that
-          any nested elements of the macrodef instance will be placed
-          in the element indicated by the name of this element.
-          There can only be one element if an element is implicit.
-          The default value is false. <em>since ant 1.6.2</em>
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>implicit</td>
+        <td>If <q>true</q> this nested element is implicit. This means that any nested elements of
+          the <code>macrodef</code> instance will be placed in the element indicated by the name of
+          this element.  There can only be one element if an element is implicit.  <em>Since Ant
+          1.6.2</em></td>
+        <td>No; default is <q>false</q></td>
       </tr>
       <tr>
-        <td valign="top">description</td>
-        <td valign="top">
-          This contains a description
-          informing the user what the contents of the element are expected to be.
-          <em>since ant 1.6.1</em>
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>description</td>
+        <td>This contains a description informing the user what the contents of the element are
+          expected to be.  <em>Since Ant 1.6.1</em></td>
+        <td>No</td>
       </tr>
     </table>
     <h4>text</h4>
-    <p>
-      This is used to specify the treatment of text contents of the macro invocation.
-      If this element is not present, then any nested text in the macro invocation
-      will be an error. If the text element is present, then the name
-      becomes an attribute that gets set to the nested text of the macro invocation.
-      <em>Since ant 1.6.1.</em>
-    </p>
-    <p>
-      The case of the text name is ignored.
-    </p>
-    <h3>Parameters</h3>
-    <table border="1" cellpadding="2" cellspacing="0">
+    <p>This is used to specify the treatment of text contents of the macro invocation.  If this
+      element is not present, then any nested text in the macro invocation will be an error. If
+      the <code>text</code> element is present, then the name becomes an attribute that gets set to
+      the nested text of the macro invocation.  <em>Since Ant 1.6.1</em>.</p>
+    <p>The case of the <code>text</code> name is ignored.</p>
+    <h5>Parameters</h5>
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">name</td>
-        <td valign="top">The name of the text attribute</td>
-        <td valign="top" align="center">Yes</td>
+        <td>name</td>
+        <td>The name of the text attribute.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">optional</td>
-        <td valign="top">
-          If true nested text in the macro is optional, default is "false".
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>optional</td>
+        <td>If <q>true</q> nested text in the macro is optional.</td>
+        <td>No; default is <q>false</q></td>
       </tr>
       <tr>
-        <td valign="top">trim</td>
-        <td valign="top">
-          If true, the nested text is trimmed of white space,
-          default is "false".
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>trim</td>
+        <td>If <q>true</q>, the nested text is trimmed of white space.</td>
+        <td>No; default is <q>false</q></td>
       </tr>
       <tr>
-        <td valign="top">description</td>
-        <td valign="top">
-          This contains a description
-          informing the user what the nested text of the macro is expected
-          to be.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>description</td>
+        <td>This contains a description informing the user what the nested text of the macro is
+          expected to be.</td>
+        <td>No</td>
       </tr>
     </table>
 
     <h3>Examples</h3>
-    <p>
-      The following example defined a task called testing and
-      runs it.
-    </p>
-    <blockquote>
-<pre class=code>
+    <p>The following example defined a task called testing and runs it.</p>
+    <pre>
 &lt;macrodef name="testing"&gt;
-   &lt;attribute name="v" default="NOT SET"/&gt;
-   &lt;element name="some-tasks" optional="yes"/&gt;
-   &lt;sequential&gt;
-      &lt;echo&gt;v is @{v}&lt;/echo&gt;
-      &lt;some-tasks/&gt;
-   &lt;/sequential&gt;
+    &lt;attribute name="v" default="NOT SET"/&gt;
+    &lt;element name="some-tasks" optional="yes"/&gt;
+    &lt;sequential&gt;
+        &lt;echo&gt;v is @{v}&lt;/echo&gt;
+        &lt;some-tasks/&gt;
+    &lt;/sequential&gt;
 &lt;/macrodef&gt;
 
 &lt;testing v="This is v"&gt;
-   &lt;some-tasks&gt;
-      &lt;echo&gt;this is a test&lt;/echo&gt;
-   &lt;/some-tasks&gt;
-&lt;/testing&gt;
-</pre>
-    </blockquote>
-    <p>
-      The following fragment defines a task called <code>&lt;call-cc&gt;</code> which
-      take the attributes "target", "link" and "target.dir" and the
-      nested element "cc-elements". The body of the task
-      uses the <code>&lt;cc&gt;</code> task from the
-      <a href="http://ant-contrib.sourceforge.net/">ant-contrib</a> project.
-    </p>
-    <blockquote>
-<pre class="code">
+    &lt;some-tasks&gt;
+        &lt;echo&gt;this is a test&lt;/echo&gt;
+    &lt;/some-tasks&gt;
+&lt;/testing&gt;</pre>
+    <p>The following fragment defines a task called <code>&lt;call-cc&gt;</code> which take the
+      attributes <var>target</var>, <var>link</var> and <var>target.dir</var> and the nested
+      element <code>cc-elements</code>. The body of the task uses the <code>&lt;cc&gt;</code> task
+      from the <a href="http://ant-contrib.sourceforge.net/" target="_top">ant-contrib</a>
+      project.</p>
+    <pre>
 &lt;macrodef name="call-cc"&gt;
-   &lt;attribute name="target"/&gt;
-   &lt;attribute name="link"/&gt;
-   &lt;attribute name="target.dir"/&gt;
-   &lt;element name="cc-elements"/&gt;
-   &lt;sequential&gt;
-      &lt;mkdir dir="${obj.dir}/@{target}"/&gt;
-      &lt;mkdir dir="@{target.dir}"/&gt;
-         &lt;cc link="@{link}" objdir="${obj.dir}/@{target}"
-             outfile="@{target.dir}/@{target}"&gt;
+    &lt;attribute name="target"/&gt;
+    &lt;attribute name="link"/&gt;
+    &lt;attribute name="target.dir"/&gt;
+    &lt;element name="cc-elements"/&gt;
+    &lt;sequential&gt;
+        &lt;mkdir dir="${obj.dir}/@{target}"/&gt;
+        &lt;mkdir dir="@{target.dir}"/&gt;
+        &lt;cc link="@{link}" objdir="${obj.dir}/@{target}"
+            outfile="@{target.dir}/@{target}"&gt;
             &lt;compiler refid="compiler.options"/&gt;
             &lt;cc-elements/&gt;
-         &lt;/cc&gt;
-      &lt;/sequential&gt;
-&lt;/macrodef&gt;
-</pre>
-    </blockquote>
-    <p>
-      This then can be used as follows:
-    </p>
-    <blockquote>
-<pre class="code">
+        &lt;/cc&gt;
+    &lt;/sequential&gt;
+&lt;/macrodef&gt;</pre>
+    <p>This then can be used as follows:</p>
+    <pre>
 &lt;call-cc target="unittests" link="executable"
          target.dir="${build.bin.dir}"&gt;
    &lt;cc-elements&gt;
@@ -301,16 +233,11 @@
       &lt;fileset dir="${gen.dir}" includes = "*.cpp"/&gt;
       &lt;linker refid="linker-libs"/&gt;
    &lt;/cc-elements&gt;
-&lt;/call-cc&gt;
-</pre>
-    </blockquote>
-    <p>
-      The following fragment shows &lt;call-cc&gt;, but this time
-      using an implicit element and with the link and target.dir arguments
-      having default values.
-    </p>
-    <blockquote>
-<pre class="code">
+&lt;/call-cc&gt;</pre>
+    <p>The following fragment shows <code>&lt;call-cc&gt;</code>, but this time using an implicit
+      element and with the <var>link</var> and <var>target.dir</var> arguments having default
+      values.</p>
+    <pre>
 &lt;macrodef name="call-cc"&gt;
    &lt;attribute name="target"/&gt;
    &lt;attribute name="link" default="executable"/&gt;
@@ -321,19 +248,14 @@
       &lt;mkdir dir="@{target.dir}"/&gt;
          &lt;cc link="@{link}" objdir="${obj.dir}/@{target}"
              outfile="@{target.dir}/@{target}"&gt;
-            &lt;compiler refid="compiler.options"/&gt;
-            &lt;cc-elements/&gt;
+             &lt;compiler refid="compiler.options"/&gt;
+             &lt;cc-elements/&gt;
          &lt;/cc&gt;
       &lt;/sequential&gt;
-&lt;/macrodef&gt;
-</pre>
-    </blockquote>
-    <p>
-      This then can be used as follows, note that &lt;cc-elements&gt;
-      is not specified.
-    </p>
-    <blockquote>
-<pre class="code">
+&lt;/macrodef&gt;</pre>
+    <p>This then can be used as follows, note that <code>&lt;cc-elements&gt;</code> is not
+    specified.</p>
+    <pre>
 &lt;call-cc target="unittests"&gt;
    &lt;includepath location="${gen.dir}"/&gt;
    &lt;includepath location="test"/&gt;
@@ -341,13 +263,9 @@
    &lt;fileset dir="${gen.dir}" includes = "*.cpp"/&gt;
    &lt;linker refid="linker-libs"/&gt;
 &lt;/call-cc&gt;
-</pre>
-    </blockquote>
-    <p>
-      The following shows the use of the <code>text</code> element.
-    </p>
-    <blockquote>
-<pre class="code">
+    </pre>
+    <p>The following shows the use of the <code>text</code> element.</p>
+    <pre>
 &lt;macrodef name="echotest"&gt;
    &lt;text name="text"/&gt;
    &lt;sequential&gt;
@@ -357,29 +275,20 @@
 &lt;echotest&gt;
    Hello world
 &lt;/echotest&gt;
-</pre>
-    </blockquote>
-    <p>
-      The following uses a prior defined attribute for setting the
-      default value of another. The output would be
-      <tt>one=test two=test</tt>. If you change the order of lines
-      *1 and *2 the output would be <tt>one=test two=@{one}</tt>,
-      because while processing the <i>two</i>-line the value for
-      <i>one</i> is not set.
-    </p>
-    <blockquote>
-<pre class="code">
+    </pre>
+    <p>The following uses a prior defined attribute for setting the default value of another. The
+      output would be <code class="output">one=test two=test</code>. If you change the order of
+      lines *1 and *2 the output would be <code class="output">one=test two=@{one}</code>, because
+      while processing the <var>two</var>-line the value for <var>one</var> is not set.</p>
+    <pre>
 &lt;macrodef name="test"&gt;
-   &lt;attribute name="one"/&gt;                     <b>*1</b>
-   &lt;attribute name="two" default="@{one}"/&gt;    <b>*2</b>
+   &lt;attribute name="one"/&gt;                     <strong>*1</strong>
+   &lt;attribute name="two" default="@{one}"/&gt;    <strong>*2</strong>
    &lt;sequential&gt;
       &lt;echo&gt;one=@{one}   two=@{two}&lt;/echo&gt;
    &lt;/sequential&gt;
 &lt;/macrodef&gt;
-&lt;test one="test"/&gt;
-</pre>
-    </blockquote>
-
+&lt;test one="test"/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/mail.html b/manual/Tasks/mail.html
index b59633d..3b51a64 100644
--- a/manual/Tasks/mail.html
+++ b/manual/Tasks/mail.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,314 +15,284 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Mail Task</title>
 </head>
 
 <body>
 
-<h2><a name="mail">Mail</a></h2>
+<h2 id="mail">Mail</h2>
 <h3>Description</h3>
-  <p>
-    A task to send SMTP email.
-  </p>
-  <p>
-    This task can send mail using either plain
-    text, UU encoding, or MIME format mail, depending on what is available.
-  </p>
-  <p>
-    SMTP auth and SSL/TLS require JavaMail and are only available in MIME format.
-  </p>
-  <p>
-    Attachments may be sent using nested
-    <code>&lt;attachments&gt;</code> elements, which are <a
-    href="../using.html#path">path-like structures</a>.  This means
-    any filesystem based <a
-    href="../Types/resources.html">resource</a> or resource
-    collection can be used to point to attachments.  Prior to Apache Ant 1.7
-    only <code>&lt;fileset&gt;</code> has been supported as a nested
-    element, you can still use this directly without an
-    <code>&lt;attachments&gt;</code> container.
-  </p>
-  <p>
-    <strong>Note:</strong> This task may depend on external libraries
-    that are not included in the Ant distribution. 
-    See <a href="../install.html#librarydependencies">Library Dependencies</a>
-    for more information.
-  </p>
+<p>A task to send SMTP email.</p>
+<p>This task can send mail using either plain text, UU encoding, or MIME format mail, depending on
+what is available.</p>
+<p>SMTP auth and SSL/TLS require JavaMail or JakartaMail and are only available in MIME format.</p>
+<p>Attachments may be sent using nested <code>&lt;attachments&gt;</code> elements, which
+are <a href="../using.html#path">path-like structures</a>.  This means any filesystem
+based <a href="../Types/resources.html">resource</a> or resource collection can be used to point to
+attachments.  Prior to Apache Ant 1.7 only <code>&lt;fileset&gt;</code> has been supported as a
+nested element, you can still use this directly without an <code>&lt;attachments&gt;</code>
+container.</p>
+<p><strong>Note</strong>: This task may depend on external libraries that are not included in the
+Ant distribution.  See <a href="../install.html#librarydependencies">Library Dependencies</a> for
+more information.</p>
+<p>Starting with Ant 1.10.13 Ant supports either the modern <code>jakarta.mail</code> as well as the
+  older <code>javax.mail</code> implementations and will prefer <code>jakarta.mail</code> if both are available.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">from</td>
-    <td valign="top">Email address of sender.</td>
-    <td align="center" valign="top">Either a <code>from</code> attribute, or a <code>&lt;from&gt;</code>
-    element.</td>
+    <td>from</td>
+    <td>Email address of sender.</td>
+    <td>Either a <var>from</var> attribute, or a <code>&lt;from&gt;</code> element.</td>
   </tr>
   <tr>
-    <td valign="top">replyto</td>
-    <td valign="top">Replyto email address.</td>
-    <td align="center" valign="top">No</td>
+    <td>replyto</td>
+    <td>Reply-to email address.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">tolist</td>
-    <td valign="top">Comma-separated list of recipients.</td>
-    <td align="center" valign="middle" rowspan="3">At least one of these, or the
-       equivalent elements.</td>
+    <td>tolist</td>
+    <td>Comma-separated list of recipients.</td>
+    <td rowspan="3">At least one of these, or the equivalent nested elements</td>
   </tr>
   <tr>
-    <td valign="top">cclist</td>
-    <td valign="top">Comma-separated list of recipients to carbon copy</td>
+    <td>cclist</td>
+    <td class="left">Comma-separated list of recipients to carbon copy</td>
     </tr>
   <tr>
-    <td valign="top">bcclist</td>
-    <td valign="top">Comma-separated list of recipients to blind carbon copy
+    <td>bcclist</td>
+    <td class="left">Comma-separated list of recipients to blind carbon copy
     </td>
   </tr>
   <tr>
-    <td valign="top">message</td>
-    <td valign="top">Message to send in the body of the email.</td>
-    <td align="center" valign="middle" rowspan="2">One of these or a
-    <code>&lt;message&gt;</code> element.</td>
+    <td>message</td>
+    <td>Message to send in the body of the email.</td>
+    <td rowspan="2">One of these or a <code>&lt;message&gt;</code> element.</td>
   </tr>
   <tr>
-    <td valign="top">messagefile</td>
-    <td valign="top">File to send as the body of the email. Property
-    values in the file will be expanded.</td>
+    <td>messagefile</td>
+    <td class="left">File to send as the body of the email. Property values in the file will be
+      expanded.</td>
   </tr>
   <tr>
-    <td valign="top">messagefileinputencoding</td>
-    <td valign="top">
-      Specifies the encoding of the input file. Please see
-      <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">
-        Supported Encodings</a> for a list of possible
-      values. Defaults to the platform's default character
-      encoding. <em>Since Ant 1.9.4</em>
+    <td>messagefileinputencoding</td>
+    <td>Specifies the encoding of the input file. Please
+      see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+      target="_top">Supported Encodings</a> for a list of possible values. <em>Since Ant 1.9.4</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">messagemimetype</td>
-    <td valign="top">The content type of the message.  The default is
-    <code>text/plain</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>messagemimetype</td>
+    <td>The content type of the message.</td>
+    <td>No; default is <q>text/plain</q></td>
   </tr>
   <tr>
-    <td valign="top">files</td>
-    <td valign="top">Files to send as attachments to the email.  Separate multiple
-    file names using a comma or space.  You can also use <code>&lt;fileset&gt;</code>
-    elements to specify files.</td>
-    <td align="center" valign="top">No</td>
+    <td>files</td>
+    <td>Files to send as attachments to the email.  Separate multiple file names using a comma or
+      space.  You can also use <code>&lt;fileset&gt;</code> elements to specify files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">flag to indicate whether to halt the build on
-    any error.  The default value is <code>true</code>.</td>
-    <td align="center" valign="top">No.</td>
+    <td>failonerror</td>
+    <td>flag to indicate whether to halt the build on any error.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">includefilenames</td>
-    <td valign="top">Include filename(s) before file contents.
-    Valid only when the <code>plain</code> encoding is used.  The default
-    value is <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>includefilenames</td>
+    <td>Include filename(s) before file contents.</td>
+    <td>No; default is <q>false</q>, ignored unless <q>plain</q> encoding is used</td>
   </tr>
   <tr>
-    <td valign="top">mailhost</td>
-    <td valign="top">Host name of the SMTP server.  The default value is
-    <code>localhost</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>mailhost</td>
+    <td>Host name of the SMTP server.</td>
+    <td>No; default is <q>localhost</q></td>
   </tr>
   <tr>
-    <td valign="top">mailport</td>
-    <td valign="top">TCP port of the SMTP server.  The default value is 25.</td>
-    <td align="center" valign="top">No</td>
+    <td>mailport</td>
+    <td>TCP port of the SMTP server.</td>
+    <td>No; default is <q>25</q></td>
   </tr>
   <tr>
-    <td valign="top">user</td>
-    <td valign="top">user name for SMTP auth</td>
-    <td valign="center">Yes, if SMTP auth is required on your SMTP server<br></br>
-    the email message will be then sent using Mime and requires JavaMail</td>
+    <td>user</td>
+    <td>user name for SMTP auth</td>
+    <td>Yes, if SMTP auth is required on your SMTP server;<br/>the email message will be then sent
+      using MIME and requires JavaMail</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">password for SMTP auth</td>
-    <td valign="center">Yes, if SMTP auth is required on your SMTP server<br></br>
-    the email message will be then sent using Mime and requires JavaMail</td>
+    <td>password</td>
+    <td>password for SMTP auth</td>
+    <td>Yes, if SMTP auth is required on your SMTP server;<br/>the email message will be then sent
+      using MIME and requires JavaMail</td>
   </tr>
   <tr>
-    <td valign="top">ssl</td>
-    <td valign="top">"true", "on" or "yes" accepted here<br></br>
-    indicates whether you need TLS/SSL</td>
-    <td align="center" valign="top">No</td>
+    <td>ssl</td>
+    <td><q>true</q>, <q>on</q>, or <q>yes</q> accepted here<br/>indicates whether you need
+      TLS/SSL</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">Specifies the encoding to use for the content of the email.
-    Values are <code>mime</code>, <code>uu</code>, <code>plain</code>, or
-      <code>auto</code>.  The default value is <code>auto</code>.
-      <code>uu</code> or <code>plain</code> are not compatible with SMTP auth</td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>Specifies the encoding to use for the content of the email.  Values
+      are <q>mime</q>, <q>uu</q>, <q>plain</q>, or <q>auto</q>. <q>uu</q> or <q>plain</q> are not
+      compatible with SMTP auth</td>
+    <td>No; default is <q>auto</q></td>
   </tr>
   <tr>
-    <td valign="top">charset</td>
-    <td valign="top">Character set of the email.<br>
-    You can also set the charset in the message nested element.<br>
-    These options are mutually exclusive.</td>
-    <td align="center" valign="top">No</td>
+    <td>charset</td>
+    <td>Character set of the email.<br/>You can also set the <var>charset</var> in
+      the <code>message</code> nested element.<br/>  These options are mutually exclusive.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">subject</td>
-    <td valign="top">Email subject line.</td>
-    <td align="center" valign="top">No</td>
+    <td>subject</td>
+    <td>Email subject line.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">ignoreInvalidRecipients</td>
-    <td valign="top">Boolean.  Whether the task should try to send
-      the message to as many recipients as possible and should only
-      fail if neither is reachable.  <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>ignoreInvalidRecipients</td>
+    <td>(boolean) Whether the task should try to send the message to as many recipients as possible
+      and should only fail if neither is reachable.  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">enableStartTLS</td>
-    <td valign="top">"true", "on" or "yes" accepted here<br></br>
-      whether the STARTTLS command used to switch to an encrypted
-      connection for authentication should be supported.  Requires
-      JavaMail.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>enableStartTLS</td>
+    <td>(boolean) Whether the <code>STARTTLS</code> command used to switch to an encrypted
+      connection for authentication should be supported.  Requires JavaMail.  <em>Since Ant
+      1.8.0</em></td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Note regarding the attributes containing email addresses</h3>
-Since Ant 1.6, the attributes from, replyto, tolist, cclist, bcclist
-can contain email addresses of the form :
+<p><em>Since Ant 1.6</em>, the
+attributes <var>from</var>, <var>replyto</var>, <var>tolist</var>, <var>cclist</var>, <var>bcclist</var>
+can contain email addresses of the form:</p>
 <ul>
-<li>address@xyz.com</li>
-<li>name &lt;address@xyz.com&gt;</li>
-<li>&lt;address@xyz.com&gt; name</li>
-<li>(name) address@xyz.com</li>
-<li>address@xyz.com (name)</li>
+  <li><samp>address@xyz.com</samp></li>
+  <li><samp>name &lt;address@xyz.com&gt;</samp></li>
+  <li><samp>&lt;address@xyz.com&gt; name</samp></li>
+  <li><samp>(name) address@xyz.com</samp></li>
+  <li><samp>address@xyz.com (name)</samp></li>
 </ul>
-<p>You need to enter the angle brackets as XML entities
-<code>&amp;gt;</code> and <code>&amp;lt;</code>.</p>
+<p>You need to enter the angle brackets as XML entities <q>&amp;gt;</q> and <q>&amp;lt;</q>.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>to / cc / bcc / from/ replyto </h4>
+<h4>to / cc / bcc / from/ replyto</h4>
 <p>Adds an email address element.  It takes the following attributes:</p>
 
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The display name for the address.</td>
-    <td align="center" valign="top">No</td>
+    <td>name</td>
+    <td>The display name for the address.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">address</td>
-    <td valign="top">The email address.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>address</td>
+    <td>The email address.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>message</h4>
 
-<p>Specifies the message to include in the email body.  It takes the following
-attributes:</p>
+<p>Specifies the message to include in the email body.  It takes the following attributes:</p>
 
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">The file to use as the message.</td>
-    <td align="center" valign="top">No</td>
+    <td>src</td>
+    <td>The file to use as the message.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">mimetype</td>
-    <td valign="top">The content type to use for the message.</td>
-    <td align="center" valign="top">No</td>
+    <td>mimetype</td>
+    <td>The content type to use for the message.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">charset</td>
-    <td valign="top">Character set of the message<br>
-    You can also set the charset as attribute of the enclosing mail task.<br>
-    These options are mutually exclusive.</td>
-    <td align="center" valign="top">No</td>
+    <td>charset</td>
+    <td>Character set of the message<br/>You can also set the <var>charset</var> as attribute of the
+      enclosing <code>mail</code> task.<br/>  These options are mutually exclusive.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputencoding</td>
-    <td valign="top">
-      Specifies the encoding of the input file. Please see
-      <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">
-        Supported Encodings</a> for a list of possible
-      values. Defaults to the platform's default character
-      encoding. <em>Since Ant 1.9.4</em>
+    <td>inputencoding</td>
+    <td>
+      Specifies the encoding of the input file. Please
+      see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+      target="_top">Supported Encodings</a> for a list of possible values. <em>Since Ant 1.9.4</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
 </table>
 
-<p>If the <code>src</code> attribute is not specified, then text can be added
-inside the <code>&lt;message&gt;</code> element. Property expansion will occur
-in the message, whether it is specified as an external file or as text within
-the <code>&lt;message&gt;</code> element.</p>
+<p>If the <var>src</var> attribute is not specified, then text can be added inside
+the <code>&lt;message&gt;</code> element. Property expansion will occur in the message, whether it
+is specified as an external file or as text within the <code>&lt;message&gt;</code> element.</p>
 
 <h4>header</h4>
-<p><strong>Since Ant 1.7</strong>, arbitrary mail headers can be added by
-  specifying these attributes on one or more nested header elements:</p>
+<p><em>Since Ant 1.7</em>, arbitrary mail headers can be added by specifying these attributes on one
+or more nested header elements:</p>
 
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name associated with this mail header.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name associated with this mail header.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The value to assign to this mail header.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>value</td>
+    <td>The value to assign to this mail header.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<p>It is permissible to duplicate the name attribute amongst multiple headers.
-</p>
+<p>It is permissible to duplicate the name attribute amongst multiple headers.</p>
 
 <h3>Examples</h3>
 
-<blockquote><pre>
+<p>Send an email from <q>me</q> to <q>you</q> with a subject of <q>Results of nightly build</q> and
+include the contents of the file <samp>build.log</samp> in the body of the message.</p>
+
+<pre>
 &lt;mail from=&quot;me&quot;
       tolist=&quot;you&quot;
       subject=&quot;Results of nightly build&quot;
-      files=&quot;build.log&quot;/&gt;
-</pre></blockquote>
+      files=&quot;build.log&quot;/&gt;</pre>
 
-<p>Sends an email from <i>me</i> to <i>you</i> with a subject of
-<i>Results of nightly build</i> and includes the contents of the file
-<i>build.log</i> in the body of the message.</p>
+<p>Send an email from <q>config@myisp.com</q> to <q>all@xyz.com</q> with a subject of <q>Test
+Build</q>. Replies to this email will go to <q>me@myisp.com</q>. Any zip files from
+the <samp>dist</samp> directory are attached. The task will attempt to use JavaMail and fall back to
+UU encoding or no encoding in that order depending on what support classes are
+available. <samp>${buildname}</samp> will be replaced with the <code>buildname</code> property's
+value.</p>
 
-<blockquote><pre>
+<pre>
 &lt;mail mailhost=&quot;smtp.myisp.com&quot; mailport=&quot;1025&quot; subject=&quot;Test build&quot;&gt;
   &lt;from address=&quot;config@myisp.com&quot;/&gt;
   &lt;replyto address=&quot;me@myisp.com&quot;/&gt;
@@ -332,17 +303,12 @@
       &lt;include name=&quot;**/*.zip&quot;/&gt;
     &lt;/fileset&gt;
   &lt;/attachments&gt;
-&lt;/mail&gt;
-</pre></blockquote>
+&lt;/mail&gt;</pre>
 
-<p>Sends an eMail from <i>config@myisp.com</i> to <i>all@xyz.com</i> with a subject of
-<i>Test Build</i>. Replies to this email will go to <i>me@myisp.com</i>.
-Any zip files from the dist directory are attached.&nbsp; The
-task will attempt to use JavaMail and fall back to UU encoding or no encoding in
-that order depending on what support classes are available. <code>${buildname}</code>
-will be replaced with the <code>buildname</code> property's value.</p>
+<p>Send an email from <q>me@myisp.com</q> to <q>all@xyz.com</q> with a subject of <q>Test Build</q>,
+the message body being coded in UTF-8.
 
-<blockquote><pre>
+<pre>
 &lt;property name=&quot;line2&quot; value=&quot;some_international_message&quot;/&gt;
 &lt;echo message=&quot;${line2}&quot;/&gt;
 
@@ -350,13 +316,7 @@
   &lt;from address=&quot;me@myist.com&quot;/&gt;
   &lt;to address=&quot;all@xyz.com&quot;/&gt;
   &lt;message&gt;some international text:${line2}&lt;/message&gt;
-&lt;/mail&gt;
-</pre></blockquote>
-
-<p>Sends an eMail from <i>me@myisp.com</i> to <i>all@xyz.com</i> with a subject of
-<i>Test Build</i>, the message body being coded in UTF-8
-
-
+&lt;/mail&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/makeurl.html b/manual/Tasks/makeurl.html
index b20f94a..ea33992 100644
--- a/manual/Tasks/makeurl.html
+++ b/manual/Tasks/makeurl.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,221 +15,73 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-    
-<html>
+
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
+  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Makeurl Task</title>
 </head>
 
-<body bgcolor="#ffffff" text="#000000" link="#525D76"
-      alink="#525D76" vlink="#525D76">
+<body>
 
-<table border="0" width="100%" cellspacing="4">
-
-  <!-- PAGE HEADER -->
+<h2>Makeurl Task</h2>
+<h3 id="description">Description</h3>
+<p>This task takes one or more filenames and turns them into URLs, which it then assigns to a
+property.  Useful when setting up RMI or JNLP codebases, for example.  Nested filesets are
+supported; if present, these are turned into the URLs with the supplied <var>separator</var> between
+them.</p>
+<h3 id="attributes">Parameters</h3>
+<table class="attr">
   <tr>
-    <td>
-      <table border="0" width="100%"><tr>
-          <td valign="bottom">
-            <font size="+3" face="arial,helvetica,sanserif"><strong>Makeurl Task</strong></font>
-          </td>
-          <td>
-            <!-- PROJECT LOGO -->
-            <a href="http://ant.apache.org/">
-              <img src="../images/ant_logo_large.gif" align="right" alt="Apache Ant" border="0"/>
-            </a>
-          </td>
-      </tr></table>
-    </td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Type</th>
+    <th scope="col">Required</th>
   </tr>
-
-  <!-- START RIGHT SIDE MAIN BODY -->
   <tr>
-    <td  valign="top" align="left">
-
-          <!-- Applying task/long-description -->
-    <!-- Start Description -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="description">
-          <strong>Description</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-This task takes one or more filenames and turns them into URLs, which it then assigns to a property.
-Useful when setting up RMI or JNLP codebases, for example.
-Nested filesets are supported; if present, these are turned into the URLs with the supplied separator between them (default: space).
-<p/>
-<p>Examples:</p>
-<pre>
-&lt;makeurl file="${user.home}/.m2/repository" property="m2.repository.url"/&gt;
-</pre>
-Sets the property <code>m2.repository.url</code> to the file: URL of the local Maven2 repository.
-<pre>
-&lt;makeurl property="codebase"&gt;&lt;fileset dir="lib includes="*.jar"/&gt;&lt;/makeurl&gt;
-</pre>
-Set the property <code>codebase</code> to the three URLs of the files provided as nested elements.
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Description -->
-
- <!-- Ignore -->
-
-
-
-    <!-- Start Attributes -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="attributes">
-          <strong>Parameters</strong></a></font>
-      </td></tr>
-      <tr><td><blockquote>
-        <table>
-          <tr>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Attribute</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Description</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Type</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Requirement</b></font>
-        </td>
-          </tr>
-    <!-- Attribute Group -->    
-    
-    <!-- Attribute Group -->    
-        <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">file</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">name of a file to be converted into a URL</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">File</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">optional, if a nested fileset or path is supplied</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">property</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">name of a property to set to the URL</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">required</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">separator</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">separator for the multi-URL option</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">optional</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">validate</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">validate that every named file exists</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">optional; default: true</font>
-        </td>
-    </tr>
-
-
-        </table>
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Attributes -->
-
-    <!-- Start Elements -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="elements">
-          <strong>Parameters as nested elements</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>fileset</strong> (org.apache.tools.ant.types.FileSet)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        A fileset of JAR files to include in the URL list, each separated by the separator.
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>path</strong> (org.apache.tools.ant.types.Path)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Add a path to the URL. All elements in the path will be converted to individual URL entries.
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Elements -->
-
-
-    </td>
+    <td>file</td>
+    <td>name of a file to be converted into a URL</td>
+    <td>File</td>
+    <td>No, if a nested fileset or path is supplied</td>
   </tr>
-  <!-- END RIGHT SIDE MAIN BODY -->
-
+  <tr>
+    <td>property</td>
+    <td>name of a property to set to the URL</td>
+    <td>String</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>separator</td>
+    <td>separator for the multi-URL option</td>
+    <td>String</td>
+    <td>No; default is space</td>
+  </tr>
+  <tr>
+    <td>validate</td>
+    <td>validate that every named file exists</td>
+    <td>boolean</td>
+    <td>No; default is <q>true</q></td>
+  </tr>
 </table>
+<h3 id="elements">Parameters as nested elements</h3>
+<h4><strong>fileset</strong> (org.apache.tools.ant.types.FileSet)</h4>
 
+<p>A fileset of JAR files to include in the URL list, each separated by the separator.</p>
+
+<h4><strong>path</strong> (org.apache.tools.ant.types.Path)</h4>
+
+<p>Add a path to the URL. All elements in the path will be converted to individual URL entries.</p>
+
+<h3>Examples</h3>
+
+<p>Set the property <code>m2.repository.url</code> to the file: URL of the local Maven2
+repository.</p>
+<pre>&lt;makeurl file="${user.home}/.m2/repository" property="m2.repository.url"/&gt;</pre>
+
+<p>Set the property <code>codebase</code> to the three URLs of the files provided as nested
+elements.</p>
+<pre>&lt;makeurl property="codebase"&gt;
+  &lt;fileset dir="lib includes="*.jar"/&gt;
+&lt;/makeurl&gt;</pre>
 </body>
 </html>
diff --git a/manual/Tasks/manifest.html b/manual/Tasks/manifest.html
index 7a5b98b..0e8937d 100644
--- a/manual/Tasks/manifest.html
+++ b/manual/Tasks/manifest.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,167 +15,149 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Manifest Task</title>
 </head>
 
 <body>
 
-<h2><a name="manifest">Manifest</a></h2>
+<h2 id="manifest">Manifest</h2>
 <h3>Description</h3>
 <p>Creates a manifest file.</p>
 
-<p>This task can be used to write a Manifest file, optionally
-replacing or updating an existing file.</p>
+<p>This task can be used to write a Manifest file, optionally replacing or updating an existing
+file.</p>
 
+<p>Manifests are processed according to
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html" target="_top">Jar
+file specification</a>. Specifically, a manifest element consists of a set of attributes and
+sections. These sections in turn may contain attributes. Note in particular that this may result in
+manifest lines greater than 72 bytes being wrapped and continued on the next line.</p>
 
+<p>The Apache Ant team regularly gets complaints that this task in generating invalid manifests. By
+and large, this is not the case: we believe that we are following the specification to the
+letter. The usual problem is that some third party manifest reader is not following the same
+specification as well as they think they should; we cannot generate invalid manifest files just
+because one single application is broken. Java ME runtimes appear to be particularly
+troublesome.</p>
 
-<p>Manifests are processed according to the 
-<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html">Jar
-file specification.</a>. Specifically, a manifest element consists of
-a set of attributes and sections. These sections in turn may contain
-attributes. Note in particular that this may result in manifest lines
-greater than 72 bytes being wrapped and continued on the next
-line.</p>
-
-<p>
-  The Apache Ant team regularly gets complaints that this task in generating invalid
-  manifests. By and large, this is not the case: we believe that we are following
-  the specification to the letter. The usual problem is that some third party
-  manifest reader is not following the same specification as well as they think
-  they should; we cannot generate invalid manifest files just because one
-  single application is broken. J2ME runtimes appear to be particularly troublesome.
-</p>
-
-<p>
-  If you find that Ant generates manifests incompatible with your runtime, take
-  a manifest it has built, fix it up however you need and switch to using the &lt;zip&gt
-  task to create the JAR, feeding in the hand-crafted manifest.
-</p>
-
-
+<p>If you find that Ant generates manifests incompatible with your runtime, take a manifest it has
+built, fix it up however you need and switch to using the <a href="zip.html">zip</a> task to create
+the JAR, feeding in the hand-crafted manifest.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the manifest-file to create/update.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>file</td>
+    <td>the manifest-file to create/update.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">mode</td>
-    <td valign="top">One of "update" or "replace", default is "replace".</td>
-    <td valign="top" align="center">No</td>
+    <td>mode</td>
+    <td>One of <q>update</q> or <q>replace</q>.</td>
+    <td>No; default is <q>replace</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding used to read the existing manifest
-      when updating.  The task will always use UTF-8 when writing the
-      manifest.</td>
-    <td valign="top" align="center">No, defaults to UTF-8 encoding.</td>
+    <td>encoding</td>
+    <td>The encoding used to read the existing manifest when updating.  The task will always use
+      UTF-8 when writing the manifest.</td>
+    <td>No; defaults to UTF-8 encoding</td>
   </tr>
   <tr>
-    <td valign="top">mergeClassPathAttributes</td>
-    <td valign="top">Whether to merge the Class-Path attributes found
-      in different manifests (if updating).  If false, only the
-      attribute of the most recent manifest will be preserved.
-      <em>Since Ant 1.8.0</em>.
-      <br/>unless you also set flattenAttributes to true this may
-      result in manifests containing multiple Class-Path attributes
-      which violates the manifest specification.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>mergeClassPathAttributes</td>
+    <td>Whether to merge the <code>Class-Path</code> attributes found in different manifests (if
+      updating).  If <q>false</q>, only the attribute of the most recent manifest will be
+      preserved.  <em>Since Ant 1.8.0</em>.<br/>Unless you also set <var>flattenAttributes</var>
+      to <q>true</q> this may result in manifests containing multiple <code>Class-Path</code>
+      attributes which violates the manifest specification.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">flattenAttributes</td>
-    <td valign="top">Whether to merge attributes occurring more than
-      once in a section (this can only happen for the Class-Path
-      attribute) into a single attribute.
-      <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>flattenAttributes</td>
+    <td>Whether to merge attributes occurring more than once in a section (this can only happen for
+      the <code>Class-Path</code> attribute) into a single attribute.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
-<h3>Nested elements</h3>
-<h4><a name="attribute">attribute</a></h4>
-<p>One attribute for the manifest file.  Those attributes that are
-not nested into a section will be added to the "Main" section.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters specified as nested elements</h3>
+<h4 id="attribute">attribute</h4>
+<p>One attribute for the manifest file.  Those attributes that are not nested into a section will be
+added to the main section.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the attribute, <br>
-        must match the regexp <tt>[A-Za-z0-9][A-Za-z0-9-_]*</tt>.
+    <td>name</td>
+    <td>the name of the attribute, must match the regexp <q>[A-Za-z0-9][A-Za-z0-9-_]*</q>.
     </td>
-    <td valign="top" align="center">Yes</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">the value of the attribute.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>value</td>
+    <td>the value of the attribute.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-
 <h4>section</h4>
-<p>A manifest section - you can nest <a
-href="#attribute">attribute</a> elements into sections.</p>
+<p>A manifest section&mdash;you can nest <a href="#attribute">attribute</a> elements into
+sections.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the section.</td>
-    <td valign="top" align="center">No, if omitted it will be assumed
-       to be the main section.</td>
+    <td>name</td>
+    <td>the name of the section.</td>
+    <td>No, defaults to the main section</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
 
-<pre>
-  &lt;manifest file=&quot;MANIFEST.MF&quot;&gt;
-    &lt;attribute name=&quot;Built-By&quot; value=&quot;${user.name}&quot;/&gt;
-    &lt;section name=&quot;common&quot;&gt;
-      &lt;attribute name=&quot;Specification-Title&quot; value=&quot;Example&quot;/&gt;
-      &lt;attribute name=&quot;Specification-Version&quot; value=&quot;${version}&quot;/&gt;
-      &lt;attribute name=&quot;Specification-Vendor&quot; value=&quot;Example Organization&quot;/&gt;
-      &lt;attribute name=&quot;Implementation-Title&quot; value=&quot;common&quot;/&gt;
-      &lt;attribute name=&quot;Implementation-Version&quot; value=&quot;${version} ${TODAY}&quot;/&gt; 
-      &lt;attribute name=&quot;Implementation-Vendor&quot; value=&quot;Example Corp.&quot;/&gt;
-    &lt;/section&gt;
-    &lt;section name=&quot;common/class1.class&quot;&gt;
-      &lt;attribute name=&quot;Sealed&quot; value=&quot;false&quot;/&gt;
-    &lt;/section&gt;
-  &lt;/manifest&gt;
-</pre>
+<p>Create or replace the file <samp>MANIFEST.MF</samp>. Note that the <code>Built-By</code>
+attribute will take the value of the Ant property <code>${user.name}</code>. The same is true for
+the <code>${version}</code> and <code>${TODAY}</code> properties. This example produces
+a <samp>MANIFEST.MF</samp> that
+contains <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"
+target="_top">package version identification</a> for the package <samp>common</samp>.</p>
 
-<p>Creates or replaces the file MANIFEST.MF.  Note that the Built-By
-attribute will take the value of the Ant property ${user.name}.  The
-same is true for the ${version} and ${TODAY} properties.  This example
-produces a MANIFEST.MF that contains 
-<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/versioning/spec/versioning2.html#wp90779">package
-version identification</a> for the package <code>common</code>.</p>
+<pre>
+&lt;manifest file=&quot;MANIFEST.MF&quot;&gt;
+  &lt;attribute name=&quot;Built-By&quot; value=&quot;${user.name}&quot;/&gt;
+  &lt;section name=&quot;common&quot;&gt;
+    &lt;attribute name=&quot;Specification-Title&quot; value=&quot;Example&quot;/&gt;
+    &lt;attribute name=&quot;Specification-Version&quot; value=&quot;${version}&quot;/&gt;
+    &lt;attribute name=&quot;Specification-Vendor&quot; value=&quot;Example Organization&quot;/&gt;
+    &lt;attribute name=&quot;Implementation-Title&quot; value=&quot;common&quot;/&gt;
+    &lt;attribute name=&quot;Implementation-Version&quot; value=&quot;${version} ${TODAY}&quot;/&gt;
+    &lt;attribute name=&quot;Implementation-Vendor&quot; value=&quot;Example Corp.&quot;/&gt;
+  &lt;/section&gt;
+  &lt;section name=&quot;common/class1.class&quot;&gt;
+    &lt;attribute name=&quot;Sealed&quot; value=&quot;false&quot;/&gt;
+  &lt;/section&gt;
+&lt;/manifest&gt;</pre>
 
 <p>The manifest produced by the above would look like this:</p>
 
-<pre><code>Manifest-Version: 1.0
+<pre>
+Manifest-Version: 1.0
 Built-By: bodewig
 Created-By: Apache Ant 1.9
 
@@ -187,11 +170,7 @@
 Implementation-Title: common
 
 Name: common/class1.class
-Sealed: false
-
-</code></pre>
-
+Sealed: false</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/manifestclasspath.html b/manual/Tasks/manifestclasspath.html
index 2c193b8..7527078 100644
--- a/manual/Tasks/manifestclasspath.html
+++ b/manual/Tasks/manifestclasspath.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,104 +15,86 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ManifestClassPath Task</title>
 </head>
 
 <body>
 
-<h2><a name="manifestclasspath">Manifestclasspath</a></h2>
+<h2 id="manifestclasspath">Manifestclasspath</h2>
+<p><em>Since Apache Ant 1.7</em></p>
 
 <h3>Description</h3>
-<p>Converts a <a href="../using.html#path">Path</a> into a property
-whose value is appropriate for a <a href="manifest.html">Manifest</a>'s
-<code>Class-Path</code> attribute.</p>
+<p>Converts a <a href="../using.html#path">Path</a> into a property whose value is appropriate for
+a <a href="manifest.html">Manifest</a>'s <code>Class-Path</code> attribute.</p>
 
-<p>This task is often used to work around command line limitations on Windows
-when using very long class paths when launching an application. The long class
-path normally specified on the command line is replaced by a single (possibly
-empty) jar file which an in-manifest Class-Path attribute whose value lists
-all the jar and zip files the class path should contain. The files referenced
-from this attribute must be found relatively to the jar file itself, usually
-in the same directory. The Java VM automically uses all file entries listed
-in the Class-Path attributes of a jar to locate/load classes. Note though that
-it silently ignores entries for which it cannot find any corresponding file.</p>
+<p>This task is often used to work around command line limitations on Windows when using very long
+class paths when launching an application. The long class path normally specified on the command
+line is replaced by a single (possibly empty) jar file which an in-manifest <code>Class-Path</code>
+attribute whose value lists all the jar and zip files the classpath should contain. The files
+referenced from this attribute must be found relatively to the jar file itself, usually in the same
+directory. JVM automatically uses all file entries listed in the <code>Class-Path</code> attributes
+of a jar to locate/load classes. Note though that it silently ignores entries for which it cannot
+find any corresponding file.</p>
 
-<p>Note that the property value created may be longer than a manifest's maximum
-72 characters per line, but will be properly wrapped as per the Jar
-specification by the <code>&lt;manifest&gt;</code> element, where the
-defined property is re-referenced.</p>
+<p>Note that the property value created may be longer than a manifest's maximum 72 characters per
+line, but will be properly wrapped as per the Jar specification by the <code>&lt;manifest&gt;</code>
+element, where the defined property is re-referenced.</p>
 
-<p>For this task to work properly the relative path from the file
-  given in the <code>jarfile</code> attribute to the elements of the
-  nested <code>classpath</code> must be the same as you expect them to
-  be when deploying the jar.</p>
-
-<p><em>since Apache Ant 1.7</em></p>
+<p>For this task to work properly the relative path from the file given in the <code>jarfile</code>
+attribute to the elements of the nested <code>classpath</code> must be the same as you expect them
+to be when deploying the jar.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">the name of the property to set. This property must
-                     not already be set.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>the name of the property to set. This property must not already be set.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">jarfile</td>
-    <td valign="top">
-      the filename for the Jar which will contain the manifest that will
-      use the property this task will set. This file need not exist yet,
-      but its parent directory must exist.
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>jarfile</td>
+    <td>the filename for the Jar which will contain the manifest that will use the property this
+      task will set. This file need not exist yet, but its parent directory must exist.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">maxParentLevels</td>
-    <td valign="top">
-      The maximum number of parent directories one is allowed to traverse
-      to navigate from the jar file to the path entry. Put differently, the
-      maximum number of .. which is allowed in the relative path from the
-      jar file to a given class path entry. Specify 0 to enforce a path
-      entry to be in the same directory (or one of its sub-directories)
-      as the jar file itself.  Defaults to 2 levels.</td>
-    <td valign="top" align="center">No</td>
+    <td>maxParentLevels</td>
+    <td>The maximum number of parent directories one is allowed to traverse to navigate from the jar
+      file to the path entry. Put differently, the maximum number of <q>..</q> which is allowed in
+      the relative path from the jar file to a given class path entry. Specify <q>0</q> to enforce a
+      path entry to be in the same directory (or one of its sub-directories) as the jar file
+      itself.</td>
+    <td>No; defaults to <q>2</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 <h4>classpath</h4>
-<p>A <a href="../using.html#path">Path-like</a> element, which can be
-defined in-place, or refer to a path defined elsewhere using the
-<code>&lt;classpath refid="<em>pathid</em>" /&gt;</code> syntax.
+<p>A <a href="../using.html#path">path-like</a> element, which can be defined in-place, or refer to
+a path defined elsewhere using the <code>&lt;classpath refid=&quot;pathid&quot;/&gt;</code> syntax.
 This classpath must not be empty, and is required.</p>
 
 <h3>Examples</h3>
-<div id="example1">
-  <blockquote><pre>
-    &lt;manifestclasspath property="jar.classpath"
-                       jarfile="build/acme.jar"&gt;
-      &lt;classpath refid="classpath" /&gt;
-    &lt;/manifestclasspath&gt;
-  </pre></blockquote>
-  <p>Assuming a path of id "classpath" was already defined, convert this
-  path relatively to the build/ directory that will contain acme.jar, which
-  can later be created with <code>&lt;jar&gt;</code> with a nested 
-  <code>&lt;manifest&gt;</code> element that lists an
-  <code>&lt;attribute name="Class-Path" value="${jar.classpath}" /&gt;</code>.
-  </p>
-</div>
 
+<p>Assuming a path with <var>id</var>=<q>classpath</q> was already defined, convert this path
+relatively to the <samp>build/</samp> directory that will contain <samp>acme.jar</samp>, which can
+later be created with <code>&lt;jar&gt;</code> with a nested <code>&lt;manifest&gt;</code> element
+that lists an <code>&lt;attribute name="Class-Path" value="${jar.classpath}"/&gt;</code>.</p>
 
+<pre>
+&lt;manifestclasspath property="jar.classpath"
+                   jarfile="build/acme.jar"&gt;
+    &lt;classpath refid="classpath"/&gt;
+&lt;/manifestclasspath&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/mimemail.html b/manual/Tasks/mimemail.html
index 5188273..3bd6b98 100644
--- a/manual/Tasks/mimemail.html
+++ b/manual/Tasks/mimemail.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,106 +15,102 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>MimeMail Task</title>
 </head>
 
 <body>
 
-<h2><a name="mimemail">MimeMail</a></h2>
+<h2 id="mimemail">MimeMail</h2>
 
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated.  Use the <a href="../Tasks/mail.html">mail</a> task instead.</i></p>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>.  Use the <a href="../Tasks/mail.html">mail</a> task instead.</em></p>
 
 <h3>Description</h3>
-<p>Sends SMTP mail with MIME attachments.
-<a href="https://javaee.github.io/javamail/">JavaMail</a>
-and <a href="https://github.com/javaee/activation">Java
-Activation Framework</a> are required for this task. The Java
+<p>Sends SMTP mail with MIME
+attachments.  <a href="https://eclipse-ee4j.github.io/mail/"
+target="_top">Jakarta Mail</a>
+and <a href="https://eclipse-ee4j.github.io/jaf/" target="_top">Jakarta
+Activation</a> are required for this task. The Java
 Activation Framework is part of the standard class library for Java 6
 to Java 10 but the <code>java.activation</code> module has been
 deprecated in Java 9 and must be enabled explicitly when running on
-Java 10. Alternatively it can be provided as an external library.</p>
+Java 10. Alternatively it can be provided as an external
+library. Javamail has become Jakarta Mail and the Java activation
+Framework has become Jakarta Activation and both are part of the
+Jakarta effort at Eclipse.</p>
 <p>Multiple files can be attached using <a href="../Types/fileset.html">FileSets.</a></p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">message</td>
-    <td valign="top">The message body</td>
-    <td valign="top" align="center" rowspan="2">No, but only one of of 'message' or
-      'messageFile' may be specified.&nbsp; If not specified, a fileset must be
-      provided.</td>
+    <td>message</td>
+    <td>The message body</td>
+    <td rowspan="2">Exactly one of these, or a nested fileset</td>
   </tr>
   <tr>
-    <td valign="top">messageFile</td>
-    <td valign="top">A filename to read and used as the message body</td>
+    <td>messageFile</td>
+    <td class="left">A filename to read and used as the message body</td>
   </tr>
   <tr>
-    <td valign="top">messageMimeType</td>
-    <td valign="top">MIME type to use for 'message' or 'messageFile' when
-      attached.</td>
-    <td align="center" valign="top">No, defaults to "text/plain"</td>
+    <td>messageMimeType</td>
+    <td>MIME type to use for <var>message</var> or <var>messageFile</var> when attached.</td>
+    <td>No; defaults to <q>text/plain</q></td>
   </tr>
   <tr>
-    <td valign="top">tolist</td>
-    <td valign="top">Comma-separated list of To: recipients</td>
-    <td valign="top" align="center" rowspan="3">Yes, at least one of 'tolist', 'cclist',
-      or 'bcclist' must be specified.</td>
+    <td>tolist</td>
+    <td>Comma-separated list of <code>To:</code> recipients</td>
+    <td rowspan="3">Yes, at least one of these</td>
   </tr>
   <tr>
-    <td valign="top">cclist</td>
-    <td valign="top">Comma-separated list of CC: recipients</td>
-    <td valign="top" align="center">&nbsp;</td>
+    <td>cclist</td>
+    <td class="left">Comma-separated list of <code>CC:</code> recipients</td>
   </tr>
   <tr>
-    <td valign="top">bcclist</td>
-    <td valign="top">Comma-separated list of BCC: recipients</td>
-    <td valign="top" align="center">&nbsp;</td>
+    <td>bcclist</td>
+    <td class="left">Comma-separated list of <code>BCC:</code> recipients</td>
   </tr>
   <tr>
-    <td valign="top">mailhost</td>
-    <td valign="top">Host name of the mail server.</td>
-    <td valign="top" align="center">No, default to &quot;localhost&quot;</td>
+    <td>mailhost</td>
+    <td>Host name of the mail server.</td>
+    <td>No; default to <q>localhost</q></td>
   </tr>
   <tr>
-    <td valign="top">subject</td>
-    <td valign="top">Email subject line.</td>
-    <td valign="top" align="center">No</td>
+    <td>subject</td>
+    <td>Email subject line.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">from</td>
-    <td valign="top">Email address of sender.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>from</td>
+    <td>Email address of sender.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the build process if an error occurs sending the
-      e-mail.</td>
-    <td valign="top" align="center">No, default to &quot;true&quot;</td>
+    <td>failonerror</td>
+    <td>Stop the build process if an error occurs sending the e-mail.</td>
+    <td>No; default to <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<p><b>Send a single HTML file as the body of a message</b></p>
-<pre>    &lt;mimemail messageMimeType=&quot;text/html&quot; messageFile=&quot;overview-summary.html&quot;
-        tolist=&quot;you&quot; subject=&quot;JUnit Test Results: ${TODAY}&quot; from=&quot;me&quot;/&gt;</pre>
-<p><b>Sends all files in a directory as attachments</b></p>
-<pre>    &lt;mimemail message=&quot;See attached files&quot; tolist=&quot;you&quot; subject=&quot;Attachments&quot; from=&quot;me&quot;&gt;
-        &lt;fileset dir=&quot;.&quot;&gt;
-            &lt;include name=&quot;dist/*.*&quot;/&gt;
-        &lt;/fileset&gt;
-    &lt;/mimemail&gt;
-</pre>
+<p>Send a single HTML file as the body of a message</p>
+<pre>
+&lt;mimemail messageMimeType=&quot;text/html&quot; messageFile=&quot;overview-summary.html&quot;
+          tolist=&quot;you&quot; subject=&quot;JUnit Test Results: ${TODAY}&quot; from=&quot;me&quot;/&gt;</pre>
 
+<p>Send all files in a directory as attachments</p>
+<pre>
+&lt;mimemail message=&quot;See attached files&quot; tolist=&quot;you&quot; subject=&quot;Attachments&quot; from=&quot;me&quot;&gt;
+    &lt;fileset dir=&quot;.&quot;&gt;
+       &lt;include name=&quot;dist/*.*&quot;/&gt;
+    &lt;/fileset&gt;
+&lt;/mimemail&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/mkdir.html b/manual/Tasks/mkdir.html
index 5d945c0..4dc3865 100644
--- a/manual/Tasks/mkdir.html
+++ b/manual/Tasks/mkdir.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,39 +15,40 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Mkdir Task</title>
 </head>
 
 <body>
 
-<h2><a name="mkdir">Mkdir</a></h2>
+<h2 id="mkdir">Mkdir</h2>
 <h3>Description</h3>
-<p>Creates a directory. Also non-existent parent directories are created, when
-necessary. Does nothing if the directory already exist.</p>
+<p>Creates a directory. Also non-existent parent directories are created, when necessary. Does
+nothing if the directory already exists.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the directory to create.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>dir</td>
+    <td>the directory to create.</td>
+    <td>Yes</td>
   </tr>
 </table>
-<h3>Examples</h3>
-<pre>&lt;mkdir dir=&quot;${dist}&quot;/&gt;</pre>
-<p>creates a directory <code>${dist}</code>.</p>
-<pre>&lt;mkdir dir=&quot;${dist}/lib&quot;/&gt;</pre>
-<p>creates a directory <code>${dist}/lib</code>.</p>
 
+<h3>Examples</h3>
+
+<p>Create a directory <code>${dist}</code>.</p>
+<pre>&lt;mkdir dir=&quot;${dist}&quot;/&gt;</pre>
+
+<p>Create a directory <code>${dist}/lib</code>.</p>
+<pre>&lt;mkdir dir=&quot;${dist}/lib&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/move.html b/manual/Tasks/move.html
index 3692c9d..5ea337a 100644
--- a/manual/Tasks/move.html
+++ b/manual/Tasks/move.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,247 +15,201 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Move Task</title>
 </head>
 
 <body>
 
-<h2><a name="move">Move</a></h2>
+<h2 id="move">Move</h2>
 <h3>Description</h3>
-<p>Moves a file to a new file or directory, or collections of files to
-a new directory.  By default, the
-destination file is overwritten if it already exists.  When <var>overwrite</var> is
-turned off, then files are only moved if the source file is newer than
-the destination file, or when the destination file does not exist
-- please see the <code>granularity</code> attribute for Ant's idea
-of <em>newer</em>.</p>
+<p>Moves a file to a new file or directory, or collections of files to a new directory.  By default,
+the destination file is overwritten if it already exists.  When <var>overwrite</var> is turned off,
+then files are only moved if the source file is newer than the destination file, or when the
+destination file does not exist
+- please see the <var>granularity</var> attribute for Ant's idea of <em>newer</em>.</p>
 
-<p><a href="../Types/resources.html#collection">Resource
-Collection</a>s are used to select a group of files to move.  Only
-file system based resource collections are supported, this includes <a
-href="../Types/fileset.html">fileset</a>s, <a
-href="../Types/filelist.html">filelist</a> and <a
-href="../using.html#path">path</a>.  Prior to Apache Ant 1.7 only
-<code>&lt;fileset&gt;</code> has been supported as a nested element.
-To use a resource collection, the <code>todir</code> attribute must be
-set.</p>
+<p><a href="../Types/resources.html#collection">Resource collections</a> are used to select a group
+of files to move.  Only file system based resource collections are supported, this
+includes <a href="../Types/fileset.html">fileset</a>s, <a href="../Types/filelist.html">filelist</a>
+and <a href="../using.html#path">path</a>.  Prior to Apache Ant 1.7
+only <code>&lt;fileset&gt;</code> has been supported as a nested element.  To use a resource
+collection, the <var>todir</var> attribute must be set.</p>
 
-<p><b>Since Ant 1.6.3</b>, the <i>file</i> attribute may be used to move
-(rename) an entire directory.  If <i>tofile</i> denotes an existing file, or
-there is a directory by the same name in <i>todir</i>, the action will fail.
-</p>
+<p><em>Since Ant 1.6.3</em>, the <var>file</var> attribute may be used to move (rename) an entire
+directory.  If <var>tofile</var> denotes an existing file, or there is a directory by the same name
+in <var>todir</var>, the action will fail.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file or directory to move</td>
-    <td valign="top" align="center">One of <var>file</var> or
-     at least one nested resource collection element</td>
+    <td>file</td>
+    <td>the file or directory to move</td>
+    <td>One of <var>file</var> or at least one nested resource collection element</td>
   </tr>
   <tr>
-    <td valign="top">preservelastmodified</td>
-    <td valign="top">Give the moved files the same last modified
-      time as the original source files.
-      (<em>Note</em>: Ignored on Java 1.1)</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>preservelastmodified</td>
+    <td>Give the moved files the same last modified time as the original source files.
+      (<strong>Note</strong>: Ignored on Java 1.1)</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">tofile</td>
-    <td valign="top">the file to move to</td>
-    <td valign="top" align="center" rowspan="2">With the <var>file</var> attribute,
-    either <var>tofile</var> or <var>todir</var> can be used.  With nested filesets,
-    if the fileset size is greater than 1 or if the only entry in the fileset is a
-    directory or if the <var>file</var> attribute is already specified, only
-    <var>todir</var> is allowed</td>
+    <td>tofile</td>
+    <td>the file to move to</td>
+    <td rowspan="2">With the <var>file</var> attribute, either <var>tofile</var> or <var>todir</var>
+      can be used.  With nested filesets, if the fileset size is greater than 1 or if the only entry
+      in the fileset is a directory or if the <var>file</var> attribute is already specified,
+      only <var>todir</var> is allowed</td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">the directory to move to</td>
+    <td>todir</td>
+    <td class="left">the directory to move to</td>
   </tr>
   <tr>
-    <td valign="top">overwrite</td>
-    <td valign="top">overwrite existing files even if the destination
-      files are newer (default is &quot;true&quot;)</td>
-    <td valign="top" align="center">No</td>
+    <td>overwrite</td>
+    <td>overwrite existing files even if the destination files are newer</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">Overwrite read-only destination
-      files.  <em>since Ant 1.8.2</em></td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>force</td>
+    <td>Overwrite read-only destination files.  <em>since Ant 1.8.2</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">filtering</td>
-    <td valign="top">indicates whether token filtering should take place during
-      the move.  See the <a href="filter.html">filter</a> task for a description of
-      how filters work.</td>
-    <td valign="top" align="center">No</td>
+    <td>filtering</td>
+    <td>indicates whether token filtering should take place during the move.  See
+      the <a href="filter.html">filter</a> task for a description of how filters work.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">flatten</td>
-    <td valign="top">ignore directory structure of source directory,
-      copy all files into a single directory, specified by the <var>todir</var>
-      attribute (default is &quot;false&quot;).Note that you can achieve the
-      same effect by using a <a href="../Types/mapper.html#flatten-mapper">flatten mapper</a></td>
-    <td valign="top" align="center">No</td>
+    <td>flatten</td>
+    <td>ignore directory structure of source directory, copy all files into a single directory,
+      specified by the <var>todir</var> attribute. Note that you can achieve the same effect by
+      using a <a href="../Types/mapper.html#flatten-mapper">flatten mapper</a></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includeEmptyDirs</td>
-	 <td valign="top">Copy empty directories included with the nested FileSet(s).
-	   Defaults to &quot;yes&quot;.</td>
-	 <td valign="top" align="center">No</td>
+    <td>includeEmptyDirs</td>
+    <td>Copy empty directories included with the nested FileSet(s).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-     <td valign="top">If false, log a warning message, but do not stop the
-       build, when the file to copy does not exist or one of the nested
-       filesets points to a directory that doesn't exist or an error occurs
-       while moving.
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>failonerror</td>
+    <td>If false, log a warning message, but do not stop the build, when the file to copy does not
+      exist or one of the nested filesets points to a directory that doesn't exist or an error
+      occurs while moving.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-      <td valign="top">If true and failonerror is false, then do not log a
-       warning message when the file to copy does not exist or one of the nested
-       filesets points to a directory that doesn't exist or an error occurs
-       while copying. <em>since Ant 1.8.3</em>.
-     </td>
-     <td valign="top" align="center">No; defaults to false.</td>
+    <td>quiet</td>
+    <td>If <q>true</q> and <var>failonerror</var> is <q>false</q>, then do not log a warning message
+      when the file to copy does not exist or one of the nested filesets points to a directory that
+      doesn't exist or an error occurs while copying. <em>since Ant 1.8.3</em>.</td>
+     <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-     <td valign="top">Log the files that are being moved.</td>
-     <td valign="top" align="center">No; defaults to false.</td>
+    <td>verbose</td>
+    <td>Log the files that are being moved.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding to assume when filter-copying the
-    files. <em>since Ant 1.5</em>.</td>
-    <td align="center">No - defaults to default JVM encoding</td>
+    <td>encoding</td>
+    <td>The encoding to assume when filter-copying the files. <em>since Ant 1.5</em>.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">outputencoding</td>
-    <td valign="top">The encoding to use when writing the files.
-    <em>since Ant 1.6</em>.</td>
-    <td align="center">No - defaults to the value of the encoding
-    attribute if given or the default JVM encoding otherwise.</td>
+    <td>outputencoding</td>
+    <td>The encoding to use when writing the files.  <em>since Ant 1.6</em>.</td>
+    <td>No; defaults to <var>encoding</var> if set or default JVM character encoding otherwise</td>
   </tr>
   <tr>
-    <td valign="top">enablemultiplemappings</td>
-    <td valign="top">
-      If true the task will process to all the mappings for a
-      given source path. If false the task will only process
-      the first file or directory. This attribute is only relevant
-      if there is a mapper subelement.
-      <em>since Ant 1.6</em>.</td>
-    <td align="center">No - defaults to false.</td>
+    <td>enablemultiplemappings</td>
+    <td>If <q>true</q> the task will process to all the mappings for a given source
+      path. If <q>false</q> the task will only process the first file or directory. This attribute
+      is only relevant if there is a <code>mapper</code> subelement.  <em>since Ant 1.6</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">granularity</td>
-    <td valign="top">The number of milliseconds leeway to give before
-    deciding a file is out of date. This is needed because not every
-    file system supports tracking the last modified time to the
-    millisecond level. Default is 0 milliseconds, or 2 seconds on DOS
-    systems.  This can also be useful if source and target files live
-    on separate machines with clocks being out of sync.  <em>since Ant
-    1.6</em>.</td>
+    <td>granularity</td>
+    <td>The number of milliseconds leeway to give before deciding a file is out of date. This is
+      needed because not every file system supports tracking the last modified time to the
+      millisecond level.  This can also be useful if source and target files live on separate
+      machines with clocks being out of sync.  <em>since Ant 1.6</em>.</td>
+    <td>No; default is 0 milliseconds, or 2 seconds on DOS systems</td>
   </tr>
   <tr>
-    <td valign="top">performGCOnFailedDelete</td>
-    <td valign="top">
-      If Ant fails to delete a file or directory it will retry the
-      operation once.  If this flag is set to true it will perform a
-      garbage collection before retrying the delete.<br/>
-      Setting this flag to true is known to resolve some problems on
-      Windows (where it defaults to true) but also for directory trees
-      residing on an NFS share.
-      <em>Since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No, default &quot;true&quot; on
-      Windows and &quot;true&quot; on any other OS.</td>
+    <td>performGCOnFailedDelete</td>
+    <td>If Ant fails to delete a file or directory it will retry the operation once.  If this flag
+      is set to <q>true</q> it will perform a garbage collection before retrying the delete.<br/>
+      Setting this flag to <q>true</q> is known to resolve some problems on Windows (where it
+      defaults to <q>true</q>) but also for directory trees residing on an NFS share.  <em>Since Ant
+      1.8.3</em></td>
+    <td>No; defaults to <q>true</q> on Windows and <q>false</q> on any other OS</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>mapper</h4>
-<p>You can define file name transformations by using a nested <a
-href="../Types/mapper.html">mapper</a> element. The default mapper used by
-<code>&lt;move&gt;</code> is the <a
-href="../Types/mapper.html#identity-mapper">identity</a>.</p>
-<p>Note that the source name handed to the mapper depends on the
-resource collection you use.  If you use <code>&lt;fileset&gt;</code>
-or any other collection that provides a base directory, the name
-passed to the mapper will be a relative filename, relative to the base
-directory.  In any other case the absolute filename of the source will
-be used.</p>
+<p>You can define file name transformations by using a
+nested <a href="../Types/mapper.html">mapper</a> element. The default mapper used
+by <code>&lt;move&gt;</code> is the <a href="../Types/mapper.html#identity-mapper">identity</a>.</p>
+<p>Note that the source name handed to the mapper depends on the resource collection you use.  If
+you use <code>&lt;fileset&gt;</code> or any other collection that provides a base directory, the
+name passed to the mapper will be a relative filename, relative to the base directory.  In any other
+case the absolute filename of the source will be used.</p>
 <h4>filterchain</h4>
-<p>The Move task supports nested <a href="../Types/filterchain.html">
-FilterChain</a>s.</p>
-
-<p>
-If <code>&lt;filterset&gt;</code> and <code>&lt;filterchain&gt;</code> elements are used inside the
-same <code>&lt;move&gt;</code> task, all <code>&lt;filterchain&gt;</code> elements are processed first
-followed by <code>&lt;filterset&gt;</code> elements.
-</p>
+<p>The Move task supports nested <a href="../Types/filterchain.html">FilterChain</a>s.</p>
+<p>If <code>&lt;filterset&gt;</code> and <code>&lt;filterchain&gt;</code> elements are used inside
+the same <code>&lt;move&gt;</code> task, all <code>&lt;filterchain&gt;</code> elements are processed
+first followed by <code>&lt;filterset&gt;</code> elements.</p>
 
 <h3>Examples</h3>
-<p><b>Move a single file (rename a file)</b></p>
-<pre>
-  &lt;move file=&quot;file.orig&quot; tofile=&quot;file.moved&quot;/&gt;
-</pre>
-<p><b>Move a single file to a directory</b></p>
-<pre>
-  &lt;move file=&quot;file.orig&quot; todir=&quot;dir/to/move/to&quot;/&gt;
-</pre>
-<p><b>Move a directory to a new directory</b></p>
-<pre>
-  &lt;move todir=&quot;new/dir/to/move/to&quot;&gt;
-    &lt;fileset dir=&quot;src/dir&quot;/&gt;
-  &lt;/move&gt;
-</pre>
-  <i>or, since Ant 1.6.3:</i>
-<pre>
-  &lt;move file=&quot;src/dir&quot; tofile=&quot;new/dir/to/move/to&quot;/&gt;
-</pre>
-<p><b>Move a set of files to a new directory</b></p>
-<pre>
-  &lt;move todir=&quot;some/new/dir&quot;&gt;
-    &lt;fileset dir=&quot;my/src/dir&quot;&gt;
-      &lt;include name=&quot;**/*.jar&quot;/&gt;
-      &lt;exclude name=&quot;**/ant.jar&quot;/&gt;
-    &lt;/fileset&gt;
-  &lt;/move&gt;
-</pre>
-<p><b>Move a list of files to a new directory</b></p>
-<pre>
-  &lt;move todir=&quot;some/new/dir&quot;&gt;
-    &lt;filelist dir=&quot;my/src/dir&quot;&gt;
-      &lt;file name="file1.txt"/&gt;
-      &lt;file name="file2.txt"/&gt;
-    &lt;/filelist&gt;
-  &lt;/move&gt;
-</pre>
-<p><b>Append <code>&quot;.bak&quot;</code> to the names of all files
-in a directory.</b></p>
-<pre>
-  &lt;move todir=&quot;my/src/dir&quot; includeemptydirs=&quot;false&quot;&gt;
-    &lt;fileset dir=&quot;my/src/dir&quot;&gt;
-      &lt;exclude name=&quot;**/*.bak&quot;/&gt;
-    &lt;/fileset&gt;
-    &lt;mapper type=&quot;glob&quot; from=&quot;*&quot; to=&quot;*.bak&quot;/&gt;
-  &lt;/move&gt;
-</pre>
+<p>Move a single file (rename a file)</p>
+<pre>&lt;move file=&quot;file.orig&quot; tofile=&quot;file.moved&quot;/&gt;</pre>
 
+<p>Move a single file to a directory</p>
+<pre>&lt;move file=&quot;file.orig&quot; todir=&quot;dir/to/move/to&quot;/&gt;</pre>
+
+<p>Move a directory to a new directory</p>
+<pre>
+&lt;move todir=&quot;new/dir/to/move/to&quot;&gt;
+  &lt;fileset dir=&quot;src/dir&quot;/&gt;
+&lt;/move&gt;</pre>
+<p>or, <em>since Ant 1.6.3</em>:</p>
+<pre>&lt;move file=&quot;src/dir&quot; tofile=&quot;new/dir/to/move/to&quot;/&gt;</pre>
+
+<p>Move a set of files to a new directory</p>
+<pre>
+&lt;move todir=&quot;some/new/dir&quot;&gt;
+  &lt;fileset dir=&quot;my/src/dir&quot;&gt;
+    &lt;include name=&quot;**/*.jar&quot;/&gt;
+    &lt;exclude name=&quot;**/ant.jar&quot;/&gt;
+  &lt;/fileset&gt;
+&lt;/move&gt;</pre>
+
+<p>Move a list of files to a new directory</p>
+<pre>
+&lt;move todir=&quot;some/new/dir&quot;&gt;
+  &lt;filelist dir=&quot;my/src/dir&quot;&gt;
+    &lt;file name="file1.txt"/&gt;
+    &lt;file name="file2.txt"/&gt;
+  &lt;/filelist&gt;
+&lt;/move&gt;</pre>
+
+<p>Append <code>&quot;.bak&quot;</code> to the names of all files in a directory.</p>
+<pre>
+&lt;move todir=&quot;my/src/dir&quot; includeemptydirs=&quot;false&quot;&gt;
+  &lt;fileset dir=&quot;my/src/dir&quot;&gt;
+    &lt;exclude name=&quot;**/*.bak&quot;/&gt;
+  &lt;/fileset&gt;
+  &lt;mapper type=&quot;glob&quot; from=&quot;*&quot; to=&quot;*.bak&quot;/&gt;
+&lt;/move&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/native2ascii.html b/manual/Tasks/native2ascii.html
index ecc065a..183858a 100644
--- a/manual/Tasks/native2ascii.html
+++ b/manual/Tasks/native2ascii.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,136 +15,112 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
-  <head><link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>Native2Ascii Task</title></head>
+<html lang="en">
+  <head>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+    <title>Native2Ascii Task</title>
+  </head>
   <body>
     <h2>Native2Ascii</h2>
 
-    <h3>Description:</h3>
+    <h3>Description</h3>
 
-    <p>
-      Converts files from native encodings to ASCII with escaped Unicode.
-      A common usage is to convert source files maintained in a native
-      operating system encoding, to ASCII prior to compilation.
-    </p>
+    <p>Converts files from native encodings to ASCII with escaped Unicode.  A common usage is to
+      convert source files maintained in a native operating system encoding, to ASCII prior to
+      compilation.</p>
 
-    <p>
-      Files in the directory <em>src</em>
-      are converted from a native encoding to ASCII.
-      By default, all files in the directory are converted.
-      However, conversion may be limited to selected files using
-      <em>includes</em> and <em>excludes</em> attributes.
-      For more information on file matching patterns,
-      see the section on
-      <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>.
-      If no <em>encoding</em> is specified,
-      the default encoding for the JVM is used.
-      If <em>ext</em> is specified, then output files are renamed
-      to use it as a new extension.
-      More sophisticated file name translations can be achieved using a nested
-      <em><code>&lt;mapper&gt;</code></em> element. By default an
-      <a href="../Types/mapper.html#identity-mapper">identity mapper</a> will be used.
-      If <em>dest</em> and <em>src</em> point to the same directory,
-      the <em>ext</em> attribute or a nested <em><code>&lt;mapper&gt;</code></em>
-      is required.
-    </p>
+    <p>Files in the directory <var>src</var> are converted from a native encoding to ASCII.  By
+      default, all files in the directory are converted.  However, conversion may be limited to
+      selected files using <var>includes</var> and <var>excludes</var> attributes.  For more
+      information on file matching patterns, see the section
+      on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>.  If
+      no <var>encoding</var> is specified, the default encoding for the JVM is used.
+      If <var>ext</var> is specified, then output files are renamed to use it as a new extension.
+      More sophisticated file name translations can be achieved using a
+      nested <code>&lt;mapper&gt;</code> element. By default
+      an <a href="../Types/mapper.html#identity-mapper">identity mapper</a> will be used.
+      If <var>dest</var> and <var>src</var> point to the same directory, the <var>ext</var>
+      attribute or a nested <code>&lt;mapper&gt;</code> is required.</p>
 
-    <p>
-      This task forms an implicit <a href="../Types/fileset.html">File Set</a>,
-      and supports most attributes of <code>&lt;fileset&gt;</code>
-      (<code>dir</code> becomes <code>src</code>) as well as
+    <p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a>, and supports most
+      attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>src</var>) as well as
       nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>,
-      and <code>&lt;patternset&gt;</code> elements.
-    </p>
+      and <code>&lt;patternset&gt;</code> elements.</p>
 
-    <p>It is possible to use different converters. This can be selected
-      with the <code>implementation</code> attribute or a nested element.
-      <a name="implementationvalues">Here are the choices of the attribute</a>:</p>
+    <p id="implementationvalues">It is possible to use different converters. This can be selected
+      with the <var>implementation</var> attribute or a nested element. Here are the choices of the
+      attribute:</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>
-      <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><q>default</q>&mdash;the default converter for the platform: kaffe when run on Kaffe,
+        builtin otherwise.</li>
+      <li><q>sun</q>&mdash;used to be the standard converter of the JDK 8 or earlier</li>
+      <li><q>kaffe</q>&mdash;the standard converter of <a href="https://github.com/kaffe/kaffe"
+        target="_top">Kaffe</a></li>
+      <li><q>builtin</q>&mdash;Ant's internal implementation. <em>Since Ant 1.9.8</em></li>
     </ul>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td><b>Attribute</b></td>
-        <td><b>Description</b></td>
-        <td><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
         <td>reverse</td>
-        <td>Reverse the sense of the conversion,
-          i.e. convert from ASCII to native <b>only supported by the
-            sun and builtin converters</b></td>
-        <td align="center">No</td>
+        <td>Reverse the sense of the conversion, i.e. convert from ASCII to native<br/><strong>Only
+          supported by the <q>sun</q> and <q>builtin</q> converters</strong></td>
+        <td>No</td>
       </tr>
       <tr>
         <td>encoding</td>
-        <td>The native encoding the files are in
-          (default is the default encoding for the JVM)</td>
-        <td align="center">No</td>
+        <td>The native encoding the files are in</td>
+        <td>No; defaults to default JVM character encoding</td>
       </tr>
       <tr>
         <td>src</td>
-        <td>The directory to find files in (default is <em>basedir</em>)</td>
-        <td align="center">No</td>
+        <td>The directory to find files in; default is <var>basedir</var></td>
+        <td>No</td>
       </tr>
       <tr>
         <td>dest</td>
         <td>The directory to output file to</td>
-        <td align="center">Yes</td>
+        <td>Yes</td>
       </tr>
       <tr>
         <td>ext</td>
         <td>File extension to use in renaming output files</td>
-        <td align="center">No</td>
-      </tr>
-      <tr>
-        <td>defaultexcludes</td>
-        <td>indicates whether default excludes should be used or not
-          (&quot;yes&quot;/&quot;no&quot;).
-          Default excludes are used when omitted.
-        </td>
-        <td align="center">No</td>
+        <td>No</td>
       </tr>
       <tr>
         <td>includes</td>
-        <td>comma- or space-separated list of patterns of files that must be
-          included. All files are included when omitted.</td>
-        <td align="center">No</td>
+        <td>Comma- or space-separated list of patterns of files that must be included.</td>
+        <td>No; defaults to all (<q>**</q>)</td>
       </tr>
       <tr>
         <td>includesfile</td>
-        <td>the name of a file. Each line of this file is
-          taken to be an include pattern</td>
-        <td align="center">No</td>
+        <td>Name of a file. Each line of this file is taken to be an include pattern</td>
+        <td>No</td>
       </tr>
       <tr>
         <td>excludes</td>
-        <td>comma- or space-separated list of patterns of files that must be excluded.
-          No files (except default excludes) are excluded when omitted.</td>
-        <td align="center">No</td>
+        <td>Comma- or space-separated list of patterns of files that must be excluded.</td>
+        <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
       </tr>
       <tr>
         <td>excludesfile</td>
-        <td>the name of a file. Each line of this file is
-          taken to be an exclude pattern</td>
-        <td align="center">No</td>
+        <td>Name of a file. Each line of this file is taken to be an exclude pattern</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">implementation</td>
-        <td valign="top">The converter implementation to use.
-          If this attribute is not set, the default converter for the
-          current VM will be used.  (See the above <a
-          href="#implementationvalues">list</a> of valid converters.)</td>
-        <td align="center" valign="top">No</td>
+        <td>defaultexcludes</td>
+        <td>Indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+        <td>No; defaults to <q>yes</q></td>
+      </tr>
+      <tr>
+        <td>implementation</td>
+        <td>The converter implementation to use.  (See the
+          above <a href="#implementationvalues">list</a> of valid converters.)</td>
+        <td>No; defaults to default converter for the current JVM</td>
       </tr>
     </table>
 
@@ -151,101 +128,83 @@
 
 <h4>arg</h4>
 
-<p>You can specify additional command line arguments for the converter
-with nested <code>&lt;arg&gt;</code> elements.  These elements are
-specified like <a href="../using.html#arg">Command-line Arguments</a>
-but have an additional attribute that can be used to enable arguments
-only if a given converter implementation will be used.</p>
+<p>You can specify additional command line arguments for the converter with
+nested <code>&lt;arg&gt;</code> elements.  These elements are specified
+like <a href="../using.html#arg">Command-line Arguments</a> but have an additional attribute that
+can be used to enable arguments only if a given converter implementation will be used.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">value</td>
-    <td align="center" rowspan="4">See
-    <a href="../using.html#arg">Command-line Arguments</a>.</td>
-    <td align="center" rowspan="4">Exactly one of these.</td>
+    <td>value</td>
+    <td rowspan="4">See <a href="../using.html#arg">Command-line Arguments</a>.</td>
+    <td rowspan="4">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">line</td>
+    <td class="var">line</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
+    <td class="var">file</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
+    <td class="var">path</td>
   </tr>
   <tr>
-    <td valign="top">implementation</td>
-    <td>Only pass the specified argument if the chosen converter
-    implementation matches the value of this attribute.  Legal values
-    are the same as those in the above <a
-    href="#implementationvalues">list</a> of valid compilers.)</td>
-    <td align="center">No</td>
+    <td>implementation</td>
+    <td>Only pass the specified argument if the chosen converter implementation matches the value of
+    this attribute.  Legal values are the same as those in the
+    above <a href="#implementationvalues">list</a> of valid compilers.)</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4>implementationclasspath <em>since Apache Ant 1.8.0</em></h4>
+<h4>implementationclasspath</h4>
+<p><em>Since Apache Ant 1.8.0</em></p>
+<p>A <a href="../using.html#path">path-like structure</a> holding the classpath to use when loading
+the converter implementation if a custom class has been specified.  Doesn't have any effect when
+using one of the built-in converters.</p>
 
-<p>A <a href="../using.html#path">PATH like structure</a> holding the
-  classpath to use when loading the converter implementation if a
-  custom class has been specified.  Doesn't have any effect when
-  using one of the built-in converters.</p>
+<h4>Any nested element of a type that implements Native2AsciiAdapter</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>If a defined type implements the <code class="code">Native2AsciiAdapter</code> interface a nested
+element of that type can be used as an alternative to the <var>implementation</var> attribute.</p>
 
-<h4>Any nested element of a type that implements Native2AsciiAdapter
-  <em>since Ant 1.8.0</em></h4>
+<h3>Examples</h3>
 
-<p>If a defined type implements the <code>Native2AsciiAdapter</code>
-  interface a nested element of that type can be used as an
-  alternative to the <code>implementation</code> attribute.</p>
-
-    <h3>Examples</h3>
-
-    <pre>
+<p>Convert all files in the directory <samp>srcdir</samp> ending in <samp>.eucjis</samp> from the
+EUCJIS encoding to ASCII and rename them to end in <samp>.java</samp>.</p>
+<pre>
 &lt;native2ascii encoding=&quot;EUCJIS&quot; src=&quot;srcdir&quot; dest=&quot;srcdir&quot;
-   includes=&quot;**/*.eucjis&quot; ext=&quot;.java&quot;/&gt;
-    </pre>
+              includes=&quot;**/*.eucjis&quot; ext=&quot;.java&quot;/&gt;</pre>
 
-    <p>
-      Converts all files in the directory <em>srcdir</em>
-      ending in <code>.eucjis</code> from the EUCJIS encoding to ASCII
-      and renames them to end in <code>.java</code>.
-    </p>
-
+<p>Convert all the files ending in <samp>.java</samp> in the directory <samp>native/japanese</samp>
+to ASCII, placing the results in the directory <samp>src</samp>.  The names of the files remain the
+same.</p>
 <pre>
 &lt;native2ascii encoding=&quot;EUCJIS&quot; src=&quot;native/japanese&quot; dest=&quot;src&quot;
-   includes=&quot;**/*.java&quot;/&gt;
-</pre>
+              includes=&quot;**/*.java&quot;/&gt;</pre>
 
-    <p>
-      Converts all the files ending in <code>.java</code>
-      in the directory <em>native/japanese</em> to ASCII,
-      placing the results in the directory <em>src</em>.
-      The names of the files remain the same.
-    </p>
-
-<p>If you want to use a custom
-  Native2AsciiAdapter <code>org.example.MyAdapter</code> you can either
-  use the implementation attribute:</p>
+<p>If you want to use a
+custom <code class="code">Native2AsciiAdapter</code> <code>org.example.MyAdapter</code> you can
+either use the implementation attribute:</p>
 <pre>
 &lt;native2ascii encoding="EUCJIS" src="srcdir" dest="srcdir"
-       includes="**/*.eucjis" ext=".java"
-       implementation="org.example.MyAdapter"/&gt;
-</pre>
+              includes="**/*.eucjis" ext=".java"
+              implementation="org.example.MyAdapter"/&gt;</pre>
 <p>or a define a type and nest this into the task like in:</p>
 <pre>
 &lt;componentdef classname="org.example.MyAdapter"
               name="myadapter"/&gt;
 &lt;native2ascii encoding="EUCJIS" src="srcdir" dest="srcdir"
-       includes="**/*.eucjis" ext=".java"&gt;
-  &lt;myadapter/&gt;
-&lt;/native2ascii&gt;
-</pre>
-<p>in which case your native2ascii adapter can support attributes and
-  nested elements of its own.</p>
-  </body>
+              includes="**/*.eucjis" ext=".java"&gt;
+    &lt;myadapter/&gt;
+&lt;/native2ascii&gt;</pre>
+<p>in which case your <code>native2ascii</code> adapter can support attributes and nested elements
+of its own.</p>
 
+</body>
 </html>
diff --git a/manual/Tasks/netrexxc.html b/manual/Tasks/netrexxc.html
index efdfa4d..ed367a2 100644
--- a/manual/Tasks/netrexxc.html
+++ b/manual/Tasks/netrexxc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,328 +15,288 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>NetRexxC Task</title>
 </head>
 
 <body>
 
-<h2><a name="netrexxc">NetRexxC</a></h2>
+<h2 id="netrexxc">NetRexxC</h2>
 <h3>Description</h3>
-<p>Compiles a <a href="http://www2.hursley.ibm.com/netrexx" target="_top">NetRexx</a>
-source tree within the running (Apache Ant) VM.</p>
-<p>The source and destination directory will be recursively scanned for
-NetRexx source files to compile.  Only NetRexx files that have no corresponding
-class file or where the class file is older than the java file will be compiled.</p>
-<p>Files in the source tree are copied to the destination directory,
-allowing support files to be located properly in the classpath. The source
-files are copied because the NetRexx compiler cannot produce class files in a
-specific directory via parameters</p>
-<p>The directory structure of the source tree should follow the package
-hierarchy.</p>
-<p>It is possible to refine the set of files that are being compiled/copied.
-This can be done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and
-<i>defaultexcludes</i> attributes. With the <i>includes</i> or <i>includesfile</i> attribute you
-specify the files you want to have included by using patterns. The
-<i>exclude</i> or <i>excludesfile</i> attribute is used to specify the files you want to have
-excluded.  This is also done with patterns.  And finally with the
-<i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+<p>Compiles a <a href="https://www.ibm.com/software/awdtools/netrexx/library.html"
+target="_top">NetRexx</a> source tree within the running (Apache Ant) JVM.</p>
+<p>The source and destination directory will be recursively scanned for NetRexx source files to
+compile.  Only NetRexx files that have no corresponding class file or where the class file is older
+than the java file will be compiled.</p>
+<p>Files in the source tree are copied to the destination directory, allowing support files to be
+located properly in the classpath. The source files are copied because the NetRexx compiler cannot
+produce class files in a specific directory via parameters</p>
+<p>The directory structure of the source tree should follow the package hierarchy.</p>
+<p>It is possible to refine the set of files that are being compiled/copied.  This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+and <var>defaultexcludes</var> attributes. With the <var>includes</var> or <var>includesfile</var>
+attribute you specify the files you want to have included by using patterns. The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded.  This
+is also done with patterns.  And finally with the <var>defaultexcludes</var> attribute, you can
+specify whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
 inclusion/exclusion of files works, and how to write patterns.</p>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>srcdir</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
-<p>All properties except classpath, srcdir and destDir are also available as properties in the form
-<code>ant.netrexxc.<i>attributename</i></code>, eg.<br>
-<code>&lt;property name="ant.netrexxc.verbose" value="noverbose"/&gt;</code><br>
-or from the command line as<br>
-<code>ant -Dant.netrexxc.verbose=noverbose ...</code>
-</p>
-<p><strong>Note:</strong> This task depends on external libraries not
-included in the Apache Ant distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a>
-for more information.</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>srcdir</var>) as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+<p>All attributes except <var>classpath</var>, <var>srcdir</var> and <var>destDir</var> are also
+available as properties in the form <code>ant.netrexxc.<i>attributename</i></code>,
+eg.<br/><code class="code">&lt;property name="ant.netrexxc.verbose"
+value="noverbose"/&gt;</code><br/> or from the command line as<br/><kbd>ant
+-Dant.netrexxc.verbose=noverbose ...</kbd></p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">binary</td>
-    <td valign="top">Whether literals are treated as the java binary
-      type rather than the NetRexx types</td>
-    <td valign="top" align="center">No</td>
+    <td>binary</td>
+    <td>Whether literals are treated as the Java binary type rather than the NetRexx types</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to use during compilation</td>
-    <td valign="top" align="center">No</td>
+    <td>classpath</td>
+    <td>The classpath to use during compilation</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">comments</td>
-    <td valign="top">Whether comments are passed through to the
-      generated java source</td>
-    <td valign="top" align="center">No</td>
+    <td>comments</td>
+    <td>Whether comments are passed through to the generated Java source file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compact</td>
-    <td valign="top">Whether error messages come out in compact or
-      verbose format. Default is the compact format.</td>
-    <td valign="top" align="center">No</td>
+    <td>compact</td>
+    <td>Whether error messages come out in compact or verbose format.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">compile</td>
-    <td valign="top">Whether the NetRexx compiler should compile the
-      generated java code</td>
-    <td valign="top" align="center">No</td>
+    <td>compile</td>
+    <td>Whether the NetRexx compiler should compile the generated Java code</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">console</td>
-    <td valign="top">Whether or not messages should be displayed on the
-      'console'. Note that this task will rely on the default value for filtering compile messages.</td>
-    <td valign="top" align="center">No</td>
+    <td>console</td>
+    <td>Whether or not messages should be displayed on the 'console'. Note that this task will rely
+      on the default value for filtering compile messages.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">crossref</td>
-    <td valign="top">Whether variable cross references are generated</td>
-    <td valign="top" align="center">No</td>
+    <td>crossref</td>
+    <td>Whether variable cross references are generated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">decimal</td>
-    <td valign="top">Whether decimal arithmetic should be used for the
-      NetRexx code. Setting this to off will report decimal arithmetic
-      as an error, for performance critical applications.</td>
-    <td valign="top" align="center">No</td>
+    <td>decimal</td>
+    <td>Whether decimal arithmetic should be used for the NetRexx code. Setting this to <q>off</q>
+      will report decimal arithmetic as an error, for performance critical applications.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when
-      omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>Whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">destDir</td>
-    <td valign="top">the destination directory into which the NetRexx
-      source files should be copied and then compiled</td>
-    <td valign="top" align="center">Yes</td>
+    <td>destDir</td>
+    <td>the destination directory into which the NetRexx source files should be copied and then
+      compiled</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">diag</td>
-    <td valign="top">Whether diagnostic information about the compile is
-      generated</td>
-    <td valign="top" align="center">No</td>
+    <td>diag</td>
+    <td>Whether diagnostic information about the compile is generated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when
-      omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>Comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">explicit</td>
-    <td valign="top">Whether variables must be declared explicitly
-      before use</td>
-    <td valign="top" align="center">No</td>
+    <td>explicit</td>
+    <td>Whether variables must be declared explicitly before use</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">format</td>
-    <td valign="top">Whether the generated java code is formatted nicely
-      or left to match NetRexx line numbers for call stack debugging</td>
-    <td valign="top" align="center">No</td>
+    <td>format</td>
+    <td>Whether the generated Java code is formatted nicely or left to match NetRexx line numbers
+      for call stack debugging</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>Comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">java</td>
-    <td valign="top">Whether the generated java code is produced</td>
-    <td valign="top" align="center">No</td>
+    <td>java</td>
+    <td>Whether the generated Java code is produced</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keep</td>
-    <td valign="top">Sets whether the generated java source file should be kept
-      after compilation. The generated files will have an extension of
-      .java.keep, <b>not</b> .java. Use removeKeepExtension to change that.</td>
-    <td valign="top" align="center">No</td>
+    <td>keep</td>
+    <td>Sets whether the generated java source file should be kept after compilation. The generated
+      files will have an extension
+      of <samp>.java.keep</samp>, <strong>not</strong> <samp>.java</samp>. Use <q>removeKeepExtension</q>
+      to change that.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">logo</td>
-    <td valign="top">Whether the compiler text logo is displayed when
-      compiling</td>
-    <td valign="top" align="center">No</td>
+    <td>logo</td>
+    <td>Whether the compiler text logo is displayed when compiling</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">removeKeepExtension</td>
-    <td valign="top">Tells whether the trailing .keep in nocompile-mode should
-      be removed so that the resulting java source really ends on .java. This
-      facilitates the use of the javadoc tool lateron.</td>
-    <td valign="top" align="center">No</td>
+    <td>removeKeepExtension</td>
+    <td>Tells whether the trailing <samp>.keep</samp> in <var>compile</var>=<q>false</q> mode should
+      be removed so that the resulting Java source file really ends on <samp>.java</samp>. This
+      facilitates the use of the <kbd>javadoc</kbd> tool later on.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">replace</td>
-    <td valign="top">Whether the generated .java file should be replaced
-      when compiling</td>
-    <td valign="top" align="center">No</td>
+    <td>replace</td>
+    <td>Whether the generated <samp>.java</samp> files should be replaced when compiling</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">savelog</td>
-    <td valign="top">Whether the compiler messages will be written to
-      NetRexxC.log as well as to the console</td>
-    <td valign="top" align="center">No</td>
+    <td>savelog</td>
+    <td>Whether the compiler messages will be written to <samp>NetRexxC.log</samp> as well as to the
+      console</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sourcedir</td>
-    <td valign="top">Tells the NetRexx compiler to store the class files in the
-      same directory as the source files. The alternative is the working
-      directory</td>
-    <td valign="top" align="center">No</td>
+    <td>sourcedir</td>
+    <td>Tells the NetRexx compiler to store the class files in the same directory as the source
+      files. The alternative is the working directory</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">srcDir</td>
-    <td valign="top">Set the source dir to find the source NetRexx
-      files</td>
-    <td valign="top" align="center">Yes</td>
+    <td>srcDir</td>
+    <td>Sets the directory to find the source NetRexx files in</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">strictargs</td>
-    <td valign="top">Tells the NetRexx compiler that method calls always
-      need parentheses, even if no arguments are needed, e.g.
-      <code>aStringVar.getBytes</code> vs.
-      <code>aStringVar.getBytes()</code></td>
-    <td valign="top" align="center">No</td>
+    <td>strictargs</td>
+    <td>Tells the NetRexx compiler that method calls always need parentheses, even if no arguments
+      are needed, e.g. <code>aStringVar.getBytes</code> vs. <code>aStringVar.getBytes()</code></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">strictassign</td>
-    <td valign="top">Tells the NetRexx compile that assignments must
-      match exactly on type</td>
-    <td valign="top" align="center">No</td>
+    <td>strictassign</td>
+    <td>Tells the NetRexx compile that assignments must match exactly on type</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">strictcase</td>
-    <td valign="top">Specifies whether the NetRexx compiler should be
-      case sensitive or not</td>
-    <td valign="top" align="center">No</td>
+    <td>strictcase</td>
+    <td>Specifies whether the NetRexx compiler should be case sensitive or not</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">strictimport</td>
-    <td valign="top">Whether classes need to be imported explicitly using an
-      <code>import</code> statement.  By default the NetRexx compiler will
-      import certain packages automatically</td>
-    <td valign="top" align="center">No</td>
+    <td>strictimport</td>
+    <td>Whether classes need to be imported explicitly using an <code>import</code> statement</td>
+    <td>No; by default the NetRexx compiler will import certain packages automatically</td>
   </tr>
   <tr>
-    <td valign="top">strictprops</td>
-    <td valign="top">Whether local properties need to be qualified
-      explicitly using <code>this</code></td>
-    <td valign="top" align="center">No</td>
+    <td>strictprops</td>
+    <td>Whether local properties need to be qualified explicitly using <code>this</code></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">strictsignal</td>
-    <td valign="top">Whether the compiler should force catching of
-      exceptions by explicitly named types</td>
-    <td valign="top" align="center">No</td>
+    <td>strictsignal</td>
+    <td>Whether the compiler should force catching of exceptions by explicitly named types</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">symbols</td>
-    <td valign="top">Whether debug symbols should be generated into the
-      class file</td>
-    <td valign="top" align="center">No</td>
+    <td>symbols</td>
+    <td>Whether debug symbols should be generated into the class file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">time</td>
-    <td valign="top">Asks the NetRexx compiler to print compilation
-      times to the console</td>
-    <td valign="top" align="center">No</td>
+    <td>time</td>
+    <td>Asks the NetRexx compiler to print compilation times to the console</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">trace</td>
-    <td valign="top">Turns on or off tracing and directs the resultant
-      trace output</td>
-    <td valign="top" align="center">No</td>
+    <td>trace</td>
+    <td>Turns on or off tracing and directs the resultant trace output</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">utf8</td>
-    <td valign="top">Tells the NetRexx compiler that the source is in UTF8</td>
-    <td valign="top" align="center">No</td>
+    <td>utf8</td>
+    <td>Tells the NetRexx compiler that the source is in UTF8</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether lots of warnings and error messages should
-      be generated</td>
-    <td valign="top" align="center">No</td>
+    <td>verbose</td>
+    <td>Tells whether lots of warnings and error messages should be generated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suppressMethodArgumentNotUsed</td>
-    <td valign="top">Tells whether we should filter out the
-      &amp;Method argument not used&amp; messages in strictargs mode.</td>
-    <td valign="top" align="center">No</td>
+    <td>suppressMethodArgumentNotUsed</td>
+    <td>Tells whether we should filter out the <q>Method argument not used</q> messages
+      in <var>strictargs</var> mode.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suppressPrivatePropertyNotUsed</td>
-    <td valign="top">Tells whether we should filter out the
-      &amp;Private Property defined, but not used&amp; messages in strictargs mode.</td>
-    <td valign="top" align="center">No</td>
+    <td>suppressPrivatePropertyNotUsed</td>
+    <td>Tells whether we should filter out the <q>Private Property defined, but not used</q>
+      messages in <var>strictargs</var> mode.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suppressVariableNotUsed</td>
-    <td valign="top">Tells whether we should filter out the
-      &amp;Variable set but not used&amp; messages in strictargs mode.
-      Please be careful with this one, as you can hide errors behind it!</td>
-    <td valign="top" align="center">No</td>
+    <td>suppressVariableNotUsed</td>
+    <td>Tells whether we should filter out the <q>Variable set but not used</q> messages
+      in <var>strictargs</var> mode.  Please be careful with this one, as you can hide errors behind
+      it!</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suppressExceptionNotSignalled</td>
-    <td valign="top">Tells whether we should filter out the
-      &amp;Exception is declared, but not signalled within the method&amp;
-      messages in strictsignal mode.</td>
-    <td valign="top" align="center">No</td>
+    <td>suppressExceptionNotSignalled</td>
+    <td>Tells whether we should filter out the <q>Exception is declared, but not signalled within
+      the method</q> messages in <var>strictsignal</var> mode.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suppressDeprecation</td>
-    <td valign="top">Tells whether we should filter out any deprecation-messages
-      of the compiler out.</td>
-    <td valign="top" align="center">No</td>
+    <td>suppressDeprecation</td>
+    <td>Tells whether we should filter out any deprecation messages of the compiler output</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-  <p><code>&lt;netrexxc srcDir=&quot;/source/project&quot;
-           includes=&quot;vnr/util/*&quot;
-           destDir=&quot;/source/project/build&quot;
-           classpath=&quot;/source/project2/proj.jar&quot;
-           comments=&quot;true&quot;
-           crossref=&quot;false&quot; replace=&quot;true&quot;
-           keep=&quot;true&quot;/&gt;</code>
-  </p>
-</blockquote>
 
+<pre>
+&lt;netrexxc srcDir=&quot;/source/project&quot;
+          includes=&quot;vnr/util/*&quot;
+          destDir=&quot;/source/project/build&quot;
+          classpath=&quot;/source/project2/proj.jar&quot;
+          comments=&quot;true&quot;
+          crossref=&quot;false&quot; replace=&quot;true&quot;
+          keep=&quot;true&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/nice.html b/manual/Tasks/nice.html
index 03c0eaa..1e12867 100644
--- a/manual/Tasks/nice.html
+++ b/manual/Tasks/nice.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,57 +15,51 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Nice Task</title>
 </head>
 
 <body>
 
-<h2><a name="echo">Nice</a></h2>
+<h2 id="echo">Nice</h2>
 <h3>Description</h3>
-<p>Provide "nice-ness" to the current thread
-   and/or query the current value.</p>
+<p>Provide &quot;nice-ness&quot; to the current thread and/or query the current value.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">currentpriority</td>
-    <td valign="top">the name of the property whose value should be
-                     set to the current &quot;nice-ness&quot; level.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>currentpriority</td>
+    <td>name of the property whose value should be set to the current &quot;nice-ness&quot;
+      level.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">newpriority</td>
-    <td valign="top">the value to which the
-                     &quot;nice-ness&quot; level should be set.
-                     Must be a valid Java Thread priority.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>newpriority</td>
+    <td>value to which the &quot;nice-ness&quot; level should be set.  Must be a valid Java Thread
+      priority.</td>
+    <td>No</td>
   </tr>
 </table>
-<h3>Examples</h3>
-<pre>   &lt;nice newpriority=&quot;10&quot;/&gt;</pre>
-Set the Thread priority to 10 (highest).
-<pre>   &lt;nice currentpriority=&quot;priority&quot;/&gt;</pre>
-Store the current Thread priority in the user property "priority".
-<pre>
-   &lt;nice currentpriority=&quot;currentpriority&quot; newpriority=&quot;1&quot;/&gt;
-</pre>
-<p>Set the current Thread priority to 1 (lowest), storing the original
-priority in the user property "currentpriority".  This
-can be used to set the priority back to its original value later.
-</p>
 
+<h3>Examples</h3>
+
+<p>Set the Thread priority to 10 (highest).</p>
+<pre>&lt;nice newpriority=&quot;10&quot;/&gt;</pre>
+
+<p>Store the current Thread priority in the user property <code>priority</code>.</p>
+<pre>&lt;nice currentpriority=&quot;priority&quot;/&gt;</pre>
+
+<p>Set the current Thread priority to 1 (lowest), storing the original priority in the user
+property <code>currentpriority</code>. This can be used to set the priority back to its original
+value later.</p>
+<pre>&lt;nice currentpriority=&quot;currentpriority&quot; newpriority=&quot;1&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/pack.html b/manual/Tasks/pack.html
index 60ae1e5..6f6dad1 100644
--- a/manual/Tasks/pack.html
+++ b/manual/Tasks/pack.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,63 +15,62 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>GZip/BZip2 Tasks</title>
+<title>GZip/BZip2/XZ Tasks</title>
 </head>
 
 <body>
 
-<h2><a name="pack">GZip/BZip2</a></h2>
+<h2 id="pack">GZip/BZip2/XZ</h2>
 <h3>Description</h3>
-<p>Packs a resource using the GZip or BZip2 algorithm.
-The output file is only generated if it doesn't exist or the source
-resource is newer.</p>
+<p>Packs a resource using the GZip, BZip2 or XZ algorithm.  The output file is only generated if it
+doesn't exist or the source resource is newer.</p>
+
+<p>XZ compression support has been added <em>since Apache Ant 1.10.1</em> and depends on external
+libraries not included in the Ant distribution.
+See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information.</p>
+
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">the file to gzip/bzip.</td>
-    <td align="center" valign="top">Yes, or a nested resource collection.</td>
+    <td>src</td>
+    <td>the file to gzip/bzip/xz.</td>
+    <td>Yes, or a nested resource collection</td>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">the destination file to create.</td>
-    <td align="center" valign="top" rowspan="2">Exactly one of the two.</td>
+    <td>destfile</td>
+    <td>the destination file to create.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">zipfile</td>
-    <td valign="top">the <i>deprecated</i> old name of destfile.</td>
+    <td>zipfile</td>
+    <td class="left"><em><u>deprecated</u></em> old name of <var>destfile</var>.</td>
   </tr>
 </table>
-<h4>any <a href="../Types/resources.html">resource</a> or single element
-resource collection</h4>
-
-<p>The specified resource will be used as src. <em>Since Apache Ant 1.7</em></p>
+<h3>Parameters specified as nested elements</h3>
+<h4>any <a href="../Types/resources.html">resource</a> or single element resource collection</h4>
+<p><em>Since Apache Ant 1.7</em></p>
+<p>The specified resource will be used as <var>src</var>.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;gzip src=&quot;test.tar&quot; destfile=&quot;test.tar.gz&quot;/&gt;
-</pre></blockquote>
-<blockquote><pre>
-&lt;bzip2 src=&quot;test.tar&quot; destfile=&quot;test.tar.bz2&quot;/&gt;
-</pre></blockquote>
-<blockquote><pre>
-&lt;gzip destfile=&quot;archive.tar.gz&quot;&gt;
-  &lt;url url="http://example.org/archive.tar"/&gt;
-&lt;/gzip&gt;
-</pre></blockquote>
-<p>downloads <i>http://example.org/archive.tar</i> and compresses it
-to <i>archive.tar.gz</i> in the project's basedir on the fly.</p>
+<pre>&lt;gzip src=&quot;test.tar&quot; destfile=&quot;test.tar.gz&quot;/&gt;</pre>
+<pre>&lt;bzip2 src=&quot;test.tar&quot; destfile=&quot;test.tar.bz2&quot;/&gt;</pre>
+<pre>&lt;xz src=&quot;test.tar&quot; destfile=&quot;test.tar.xz&quot;/&gt;</pre>
 
+<p>Download <samp>https://example.org/archive.tar</samp> and compress it
+to <samp>archive.tar.gz</samp> in the project's <var>basedir</var> on the fly.</p>
+<pre>
+&lt;gzip destfile=&quot;archive.tar.gz&quot;&gt;
+  &lt;url url="https://example.org/archive.tar"/&gt;
+&lt;/gzip&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/parallel.html b/manual/Tasks/parallel.html
index 362daf3..da4b457 100644
--- a/manual/Tasks/parallel.html
+++ b/manual/Tasks/parallel.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Parallel Task</title>
 </head>
@@ -26,138 +26,126 @@
 
 <h2>Parallel</h2>
 <h3>Description</h3>
-<p>
-    Executes nested tasks in parallel with no guarantees of thread safety.
-    Every task will run in its own thread, with the likelihood of 
-    concurrency problems scaling with the number of CPUs on the host system.
-</p>
-<p><b>Warning:</b> While the Apache Ant core is believed to be thread safe, no such 
-    guarantees are made about tasks, which are not tested for thread safety during
-    Ant's test process. 
-    Third party tasks may or may not be thread safe, and some of Ant's core tasks, such as
-    <code>&lt;javac&gt;</code> are definitely not re-entrant. This is because they use libraries that
-    were never designed to be used in a multithreaded environment.
-</p>
-<p>
-    The primary use case for <code>&lt;parallel&gt;</code> is to run external programs
-    such as an application server, and the JUnit or TestNG test suites at the
-    same time. Anyone trying to run large Ant task sequences in parallel, such
-    as javadoc and javac at the same time, is implicitly taking on the task
-    of identifying and fixing all concurrency bugs the tasks that they run.
-    
-</p>
-<p>
-    Accordingly, while this task has uses, it should be considered an advanced
-    task which should be used in certain batch-processing or testing situations,
-    rather than an easy trick to speed up build times on a multiway CPU. 
-</p>
+<p>Executes nested tasks in parallel with no guarantees of thread safety.  Every task will run in
+its own thread, with the likelihood of concurrency problems scaling with the number of CPUs on the
+host system.</p>
+<p><strong>Warning</strong>: While the Apache Ant core is believed to be thread safe, no such
+guarantees are made about tasks, which are not tested for thread safety during Ant's test process.
+Third party tasks may or may not be thread safe, and some of Ant's core tasks, such
+as <code>&lt;javac&gt;</code> are definitely not re-entrant. This is because they use libraries that
+were never designed to be used in a multithreaded environment.</p>
+<p>The primary use case for <code>&lt;parallel&gt;</code> is to run external programs such as an
+application server, and the JUnit or TestNG test suites at the same time. Anyone trying to run large
+Ant task sequences in parallel, such as <code>javadoc</code> and <code>javac</code> at the same
+time, is implicitly taking on the task of identifying and fixing all concurrency bugs the tasks that
+they run.</p>
+<p>Accordingly, while this task has uses, it should be considered an advanced task which should be
+used in certain batch processing or testing situations, rather than an easy trick to speed up build
+times on a multicore CPU.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">threadCount</td>
-    <td valign="top">Maximum numbers of thread to use.</td>
-    <td align="center" valign="top">No</td>
+    <td>threadCount</td>
+    <td>Maximum numbers of thread to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">threadsPerProcessor</td>
-    <td valign="top">Maximum number of threads to use per available processor
-(Java 1.4+)</td>
-    <td align="center" valign="top">No, defers to threadCount</td>
+    <td>threadsPerProcessor</td>
+    <td>Maximum number of threads to use per available processor (Java 1.4+)</td>
+    <td>No; defers to <var>threadCount</var></td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Number of milliseconds before execution is terminated</td>
-    <td align="center" valign="top">No</td>
+    <td>timeout</td>
+    <td>Number of milliseconds before execution is terminated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failonany</td>
-    <td valign="top">If any of the nested tasks fails, execution of the task completes
-                     at that point without waiting for any other tasks to complete.</td>
-    <td align="center" valign="top">No, default is false.</td>
+    <td>failonany</td>
+    <td>If any of the nested tasks fails, execution of the task completes at that point without
+      waiting for any other tasks to complete.</td>
+    <td>No; default is <q>false</q>.</td>
   </tr>
   <tr>
-    <td valign="top">pollInterval</td>
-    <td valign="top">Currently has no effect</td>
-    <td align="center" valign="top">No, default is 1000</td>
+    <td>pollInterval</td>
+    <td>Currently has no effect</td>
+    <td>No; default is <q>1000</q></td>
   </tr>
 </table>
 
 <p>Parallel tasks have a number of uses in an Ant build file including:</p>
 <ul>
-<li>Taking advantage of available processing resources to execute external
- programs simultaneously.</li>
-<li>Testing servers, where the server can be run in one thread and the test
-harness is run in another thread.</li>
+  <li>Taking advantage of available processing resources to execute external programs
+    simultaneously.</li>
+  <li>Testing servers, where the server can be run in one thread and the test harness is run in
+    another thread.</li>
 </ul>
 
-<p>Any valid Ant task may be embedded within a
-parallel task, including other parallel tasks, though there is no guarantee that
-the tasks will be thread safe in such an environment.</p>
+<p>Any valid Ant task may be embedded within a <code>parallel</code> task, including
+other <code>parallel</code> tasks, though there is no guarantee that the tasks will be thread safe
+in such an environment.</p>
 
-<p>While the tasks within the parallel task are being run, the main
-thread will be blocked waiting for all the child threads to complete. If
-execution is terminated by a timeout or a nested task failure when the
-<code>failonany</code>
-flag is set, the parallel task will complete without waiting for other nested
-tasks to complete in other threads.
-</p>
+<p>While the tasks within the <code>parallel</code> task are being run, the main thread will be
+blocked waiting for all the child threads to complete. If execution is terminated by a timeout or a
+nested task failure when the <var>failonany</var> flag is set, the <code>parallel</code> task will
+complete without waiting for other nested tasks to complete in other threads.</p>
 
-<p>If any of the tasks within the <code>&lt;parallel&gt;</code> task fails and failonany is
-not set, the remaining tasks in other threads will continue to run until
-all threads have completed. In this situation, the parallel task will also fail.</p>
+<p>If any of the tasks within the <code>&lt;parallel&gt;</code> task fails and <var>failonany</var>
+is not set, the remaining tasks in other threads will continue to run until all threads have
+completed. In this situation, the <code>parallel</code> task will also fail.</p>
 
-<p>The parallel task may be combined with the <a href="sequential.html">
-sequential</a> task to define sequences of tasks to be executed on each thread
-within the parallel block</p>
+<p>The <code>parallel</code> task may be combined with the <a href="sequential.html">sequential</a>
+task to define sequences of tasks to be executed on each thread within the parallel block.</p>
 
-<p>The <code>threadCount</code> attribute can be used to place a maximum number of available
-threads for the execution.  When not present all child tasks will be executed at
-once.  When present then the maximum number of concurrently executing tasks will
-not exceed the number of threads specified.  Furthermore, each task will be
-started in the order they are given.  But no guarantee is made as to the speed
-of execution or the order of completion of the tasks, only that each will be
-started before the next.<p>
+<p>The <var>threadCount</var> attribute can be used to place a maximum number of available threads
+for the execution.  When not present all child tasks will be executed at once.  When present then
+the maximum number of concurrently executing tasks will not exceed the number of threads specified.
+Furthermore, each task will be started in the order they are given.  But no guarantee is made as to
+the speed of execution or the order of completion of the tasks, only that each will be started
+before the next.<p>
 
-<p>If you are using Java 1.4 or later you can also use the <code>threadsPerProcessor</code>
-and the number of available threads will be the stated multiple of the number of
-processors (there is no affinity to a particular processor however).  This will
-override the value in <code>threadCount</code>.  If <code>threadsPerProcessor</code>
-is specified on any older JVM, then the value in <code>threadCount</code> will be used as is.</p>
+<p>If you are using Java 1.4 or later you can also use the <var>threadsPerProcessor</var> and the
+number of available threads will be the started multiple of the number of processors (there is no
+affinity to a particular processor, however).  This will override the value
+in <var>threadCount</var>.  If <var>threadsPerProcessor</var> is specified on any older JVM, then
+the value in <var>threadCount</var> will be used as is.</p>
 
-<p>When using <code>threadCount</code> and  <code>threadsPerProcessor</code> 
-    care should be taken to ensure that the build does not deadlock.  
-    This can be caused by tasks such as <code>waitfor</code>
-    taking up all available threads before the tasks that would unlock the 
-    <code>waitfor</code>
-would occur.  This is not a replacement for Java Language level thread
-semantics and is best used for "embarassingly parallel" tasks.</p>
-
+<p>When using <var>threadCount</var> and <var>threadsPerProcessor</var> care should be taken to
+ensure that the build does not deadlock.  This can be caused by tasks such as <code>waitfor</code>
+taking up all available threads before the tasks that would unlock the <code>waitfor</code> would
+occur.  This is not a replacement for Java Language level thread semantics and is best used for
+"embarrassingly parallel" tasks.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
 <h4>daemons</h4>
-<p>
-The parallel task supports a <code>&lt;daemons&gt;</code> nested element. This is a list of tasks
-which are to be run in parallel daemon threads. The parallel task will not wait for
-these tasks to complete. Being daemon threads, however, they will not prevent Ant from
-completing, whereupon the threads are terminated. Failures in daemon threads which
-occur before the parallel task itself finishes will be reported and can cause
-parallel to throw an exception. Failures which occur after parallel has completed are not
-reported.
-</p>
+<p>The <code>parallel</code> task supports a <code>&lt;daemons&gt;</code> nested element. This is a
+list of tasks which are to be run in parallel daemon threads. The <code>parallel</code> task will
+not wait for these tasks to complete. Being daemon threads, however, they will not prevent Ant from
+completing, whereupon the threads are terminated. Failures in daemon threads which occur before
+the <code>parallel</code> task itself finishes will be reported and can cause <code>parallel</code>
+to throw an exception. Failures which occur after <code>parallel</code> has completed are not
+reported.</p>
 
-<p>Daemon tasks can be used, for example, to start test servers which might not be easily
-terminated from Ant. By using <code>&lt;daemons&gt;</code> such servers do not halt the build.
-</p>
-
+<p>Daemon tasks can be used, for example, to start test servers which might not be easily terminated
+from Ant. By using <code>&lt;daemons&gt;</code> such servers do not halt the build.</p>
 
 <h3>Examples</h3>
+<p>This is a typical pattern for testing a server application. In one thread the server is started
+(the <code>&lt;wlrun&gt;</code> task). The other thread consists of a three tasks which are
+performed in sequence. The <code>&lt;sleep&gt;</code> task is used to give the server time to come
+up. Another task which is capable of validating that the server is available could be used in place
+of the <code>&lt;sleep&gt;</code> task. The <code>&lt;junit&gt;</code> test harness then runs, again
+in its own JVM. Once the tests are complete, the server is stopped
+(using <code>&lt;wlstop&gt;</code> in this example), allowing both threads to
+complete. The <code>&lt;parallel&gt;</code> task will also complete at this time and the build will
+then continue.</p>
+
 <pre>
 &lt;parallel&gt;
   &lt;wlrun ... &gt;
@@ -166,70 +154,50 @@
     &lt;junit fork="true" forkmode="once" ... &gt;
     &lt;wlstop/&gt;
   &lt;/sequential&gt;
-&lt;/parallel&gt;
-</pre>
-<p>This example represents a typical pattern for testing a server application.
-In one thread the server is started (the <code>&lt;wlrun&gt;</code> task). 
-The other thread consists
-of a three tasks which are performed in sequence. The <code>&lt;sleep&gt;</code> task is used to
-give the server time to come up. Another task which is capable of validating
-that the server is available could be used in place of the <code>&lt;sleep&gt;</code> task. The
-<code>&lt;junit&gt;</code> test harness then runs, again in its own JVM. Once the tests are complete, the server is stopped
-(using <code>&lt;wlstop&gt;</code> in this example), allowing both threads to complete. The
-<code>&lt;parallel&gt;</code> task will also complete at this time and the build will then
-continue.</p>
+&lt;/parallel&gt;</pre>
+
+<p>Here, two independent tasks run to achieve better resource utilization during the build. In this
+instance, some servlets are being compiled in one thread and a set of JSPs is being precompiled in
+another. Developers need to be careful that the two tasks are independent, both in terms of their
+dependencies and in terms of their potential interactions in Ant's external environment. Here we
+set <var>fork</var>=<q>true</q> for the <code>&lt;javac&gt;</code> task, so that it runs in a new
+process; if the <code>&lt;wljspc&gt;</code> task used the <kbd>javac</kbd> compiler in-VM (it may),
+concurrency problems may arise.</p>
 
 <pre>
 &lt;parallel&gt;
   &lt;javac fork="true"...&gt; &lt;!-- compiler servlet code --&gt;
   &lt;wljspc ...&gt; &lt;!-- precompile JSPs --&gt;
-&lt;/parallel&gt;
-</pre>
+&lt;/parallel&gt;</pre>
 
-<p>This example shows two independent tasks being run to achieve better
-resource utilization during the build. In this instance, some servlets are being
-compiled in one thead and a set of JSPs is being precompiled in another. Developers
-need to be careful that the two tasks are independent, both in
-terms of their dependencies and in terms of their potential interactions in
-Ant's external environment. Here we set <code>fork="true"</code> for the 
-<code>&lt;javac&gt;</code> task, so that it runs in a new process; 
-if the <code>&lt;wljspc&gt;</code> task used the javac compiler in-VM
-(it may), concurrency problems may arise.
-</p>
+<p>This example represents a typical need for use of the <var>threadCount</var>
+and <var>threadsPerProcessor</var> attributes. Spinning up all 40 of those tasks could cripple the
+system for memory and CPU time. By limiting the number of concurrent executions you can reduce
+contention for CPU, memory and disk IO, and so actually finish faster. This is also a good candidate
+for use of <var>threadCount</var> (and possibly <var>threadsPerProcessor</var>) because each task is
+independent (every new JVM is forked) and has no dependencies on the other tasks.</p>
 
 <pre>
  &lt;macrodef name="dbpurge"&gt;
     &lt;attribute file="file"/&gt;
    &lt;sequential&gt;
       &lt;java jar="utils/dbpurge.jar" fork="true" &gt;
-        &lt;arg file="@{file} /&gt;
+        &lt;arg file="@{file}/&gt;
       &lt;/java&gt;
    &lt;/sequential&gt;
 &lt;/macrodef&gt;
-    
+
 &lt;parallel threadCount="4"&gt;
-  &lt;dbpurge file="db/one" /&gt;
-  &lt;dbpurge file="db/two" /&gt;
-  &lt;dbpurge file="db/three" /&gt;
-  &lt;dbpurge file="db/four" /&gt;
-  &lt;dbpurge file="db/five" /&gt;
-  &lt;dbpurge file="db/six" /&gt;
-  &lt;dbpurge file="db/seven" /&gt;
-  &lt;dbpurge file="db/eight" /&gt;
+  &lt;dbpurge file="db/one"/&gt;
+  &lt;dbpurge file="db/two"/&gt;
+  &lt;dbpurge file="db/three"/&gt;
+  &lt;dbpurge file="db/four"/&gt;
+  &lt;dbpurge file="db/five"/&gt;
+  &lt;dbpurge file="db/six"/&gt;
+  &lt;dbpurge file="db/seven"/&gt;
+  &lt;dbpurge file="db/eight"/&gt;
   &lt;!-- repeated about 40 times --&gt;
-&lt;/parallel&gt;
-</pre>
-
-<p>This example represents a typical need for use of the threadCount and
-threadsPerProcessor attributes.  Spinning up all 40 of those tasks could cripple
-the system for memory and CPU time.  By limiting the number of
-concurrent executions you can reduce contention for CPU, memory and disk IO, 
-and so actually finish faster.  This is also a good
-candidate for use of threadCount (and possibly threadsPerProcessor) because
-each task is independent (every new JVM is forked) and has no dependencies on
-the other tasks.</p>
-
+&lt;/parallel&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/patch.html b/manual/Tasks/patch.html
index 96a5ee9..e769512 100644
--- a/manual/Tasks/patch.html
+++ b/manual/Tasks/patch.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,98 +15,91 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Patch Task</title>
 </head>
 
 <body>
 
-<h2><a name="patch">Patch</a></h2>
+<h2 id="patch">Patch</h2>
 <h3>Description</h3>
-<p>Applies a diff file to originals. ; requires "patch" to be
- on the execution path.  </p>
+<p>Applies a diff file to originals. Requires <kbd>patch</kbd> to be on the execution path.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">patchfile</td> 
-    <td valign="top">the file that includes the diff output</td>
-    <td align="center" valign="top">Yes</td>
+    <td>patchfile</td>
+    <td>the file that includes the diff output</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">originalfile</td> 
-    <td valign="top">the file to patch</td>
-    <td align="center" valign="top">No, tries to guess it from the diff 
-      file</td>
+    <td>originalfile</td>
+    <td>the file to patch</td>
+    <td>No; tries to guess it from the diff file</td>
   </tr>
   <tr>
-    <td valign="top">destfile</td> 
-    <td valign="top">the file to send the output to instead of
-      patching the file(s) in place.  <em>since Apache Ant 1.6</em></td>
-    <td align="center" valign="top">No.</td>
+    <td>destfile</td>
+    <td>the file to send the output to instead of patching the file(s) in place.  <em>since Apache
+      Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">backups</td> 
-    <td valign="top">Keep backups of the unpatched files</td>
-    <td align="center" valign="top">No</td>
+    <td>backups</td>
+    <td>Keep backups of the unpatched files</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">quiet</td> 
-    <td valign="top">Work silently unless an error occurs</td>
-    <td align="center" valign="top">No</td>
+    <td>quiet</td>
+    <td>Work silently unless an error occurs</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">reverse</td> 
-    <td valign="top">Assume patch was created with old and new files 
-      swapped.</td>
-    <td align="center" valign="top">No</td>
+    <td>reverse</td>
+    <td>Assume patch was created with old and new files swapped.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">ignorewhitespace</td> 
-    <td valign="top">Ignore whitespace differences.</td>
-    <td align="center" valign="top">No</td>
+    <td>ignorewhitespace</td>
+    <td>Ignore whitespace differences.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">strip</td> 
-    <td valign="top">Strip the smallest prefix containing <i>num</i> leading 
-      slashes from filenames.</td>
-    <td align="center" valign="top">No</td>
+    <td>strip</td>
+    <td>Strip the smallest prefix containing <q>num</q> leading slashes from filenames.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">dir</td> 
-    <td valign="top">The directory in which to run the patch command.</td>
-    <td align="center" valign="top">No, default is the project's basedir.</td>
+    <td>dir</td>
+    <td>The directory in which to run the <code>patch</code> command.</td>
+    <td>No; default is the project's <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Stop the buildprocess if the command exits with a
-      return code signaling failure. Defaults to false.
-      <em>since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>Stop the build process if the command exits with a return code signaling failure. <em>since
+      Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;patch patchfile=&quot;module.1.0-1.1.patch&quot;/&gt;</pre>
-<p>applies the diff included in <i>module.1.0-1.1.patch</i> to the
-files in base directory guessing the filename(s) from the diff output.</p>
-<pre>  &lt;patch patchfile=&quot;module.1.0-1.1.patch&quot; strip=&quot;1&quot;/&gt;</pre>
-<p>like above but one leading directory part will be removed. i.e. if
-the diff output looked like</p>
-<pre>
---- a/mod1.0/A	Mon Jun  5 17:28:41 2000
-+++ a/mod1.1/A	Mon Jun  5 17:28:49 2000
-</pre> 
-the leading <i>a/</i> will be stripped.
 
+<p>Apply the diff included in <samp>module.1.0-1.1.patch</samp> to the files in base directory
+guessing the filename(s) from the diff output.</p>
+<pre>&lt;patch patchfile=&quot;module.1.0-1.1.patch&quot;/&gt;</pre>
+
+<p>Here, one leading directory part will be removed:</p>
+<pre>&lt;patch patchfile=&quot;module.1.0-1.1.patch&quot; strip=&quot;1&quot;/&gt;</pre>
+<p>i.e. if the diff output looked like</p>
+<pre>
+--- a/mod1.0/A  Mon Jun  5 17:28:41 2000
++++ a/mod1.1/A  Mon Jun  5 17:28:49 2000</pre>
+<p>the leading <samp>a/</samp> will be stripped.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/pathconvert.html b/manual/Tasks/pathconvert.html
index 41f56f4..8503ddf 100644
--- a/manual/Tasks/pathconvert.html
+++ b/manual/Tasks/pathconvert.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,211 +15,175 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>PathConvert Task</title>
 </head>
 
 <body>
 
-<h2><a name="pathconvert">Pathconvert</a></h2>
+<h2 id="pathconvert">Pathconvert</h2>
 <h3>Description</h3>
-<p>Converts nested <a href="../Types/resources.html#collection">
-ResourceCollection</a>s, or a reference to just one, into a path
-form for a particular platform, optionally storing the result into
-a given property. It can also be used when you need
-to convert a Resource Collection into a list, separated by a given
-character, such as a comma or space, or, conversely, e.g. to convert a list
-of files in a FileList into a path.
-</p>
-<p>Nested <code>&lt;map&gt;</code> elements can be specified to map Windows
-drive letters to Unix paths, and vice-versa.</p>
-<p>More complex transformations can be achieved using a nested
-<a href="../Types/mapper.html"><code>&lt;mapper&gt;</code></a>
-(since Apache Ant 1.6.2).
-</p>
+<p>Converts nested <a href="../Types/resources.html#collection">resource collections</a>, or a
+reference to just one, into a path form for a particular platform, optionally storing the result
+into a property or writing to an Ant <a href="../Types/resources.html">resource</a>.
+It can also be used when you need to convert a resource collection into a
+list, separated by a given character, such as a comma or space, or, conversely, e.g. to convert a
+list of files in a FileList into a path.</p>
+<p>Nested <code>&lt;map&gt;</code> elements can be specified to map Windows drive letters to Unix
+paths, and vice-versa.</p>
+<p>More complex transformations can be achieved using a
+nested <a href="../Types/mapper.html"><code>&lt;mapper&gt;</code></a> (<em>since Apache Ant
+1.6.2</em>).</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">targetos</td>
-    <td valign="top">
-        The target architecture.  Must be one of 'unix', 'windows', 
-        'netware', 'tandem' or 'os/2'.
-        This is a shorthand mechanism for specifying both
-        <code>pathsep</code> and <code>dirsep</code>
-        according to the specified target architecture.
+    <td>targetos</td>
+    <td>The target architecture.  Must be one
+        of <q>unix</q>, <q>windows</q>, <q>netware</q>, <q>tandem</q> or <q>os/2</q>.  This is a
+        shorthand mechanism for specifying both <var>pathsep</var> and <var>dirsep</var> according
+        to the specified target architecture.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>dirsep</td>
+    <td>The character(s) to use as the directory separator in the generated paths.</td>
+    <td>No; defaults to current JVM <code>File.separator</code></td>
+  </tr>
+  <tr>
+    <td>pathsep</td>
+    <td>The character(s) to use as the path-element separator in the generated paths.</td>
+    <td>No; defaults to current JVM <code>File.pathSeparator</code></td>
+  </tr>
+  <tr>
+    <td>property</td>
+    <td>The name of the property in which to place the converted path.</td>
+    <td>No, result will be logged if neither <code>@property</code> nor <code>@dest</code> is set</td>
+  </tr>
+  <tr>
+    <td>dest</td>
+    <td>A destination resource into which to write the converted path (Ant interprets this as a
+        <code>File</code> by default). <em>Since Ant 1.10.13</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No, result will be logged if neither <code>@property</code> nor <code>@dest</code> is set</td>
   </tr>
   <tr>
-    <td valign="top">dirsep</td>
-    <td valign="top">
-       The character(s) to use as the directory separator in the
-       generated paths.
-    </td>
-    <td valign="top" align="center">No, defaults to current JVM <tt>File.separator</tt></td>
+    <td>refid</td>
+    <td>What to convert, given as a <a href="../using.html#references">reference</a> to
+      a <code>&lt;path&gt;</code>, <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code>,
+      or <code>&lt;filelist&gt;</code> defined elsewhere</td>
+    <td>Yes, unless a nested <code>&lt;path&gt;</code> element is supplied</td>
   </tr>
   <tr>
-    <td valign="top">pathsep</td>
-    <td valign="top">
-       The character(s) to use as the path-element separator in the
-       generated paths.
-    </td>
-    <td valign="top" align="center">No, defaults to current JVM <tt>File.pathSeparator</tt></td>
+    <td>setonempty</td>
+    <td>Should the property be set, even if the result is the empty string?</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property in which to place the converted path.</td>
-    <td valign="top" align="center">No, result will be logged if unset</td>
-  </tr>
-  <tr>
-    <td valign="top">refid</td>
-    <td valign="top">What to convert, given as a
-        <a href="../using.html#references">reference</a> to a
-        <code>&lt;path&gt;</code>, <code>&lt;fileset&gt;</code>,
-        <code>&lt;dirset&gt;</code>, or <code>&lt;filelist&gt;</code>
-        defined elsewhere</td>
-    <td valign="top" align="center">No; if omitted, a nested
-        <code>&lt;path&gt;</code> element must be supplied.</td>
-  </tr>
-  <tr>
-    <td valign="top">setonempty</td>
-    <td valign="top">Should the property be set, even if the result
-      is the empty string?
-    <td valign="top" align="center">No; default is &quot;true&quot;.
-  </tr>
-  <tr>
-    <td valign="top">preserveduplicates</td>
-    <td valign="top">Whether to preserve duplicate resources. <b>Since Ant 1.8</b></td>
-    <td valign="top" align="center">No; default &quot;false&quot;.
+    <td>preserveduplicates</td>
+    <td>Whether to preserve duplicate resources. <em>Since Ant 1.8</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>map</h4>
 <p>Specifies the mapping of path prefixes between Unix and Windows.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">from</td>
-    <td valign="top">
-      The prefix to match.  Note that this value is case-insensitive when
-      the build is running on a Windows platform and case-sensitive 
-      when running on a Unix platform.
-      <em>Since Ant 1.7.0</em>, on Windows this value is also insensitive
-      to the slash style used for directories, one can use '/' or '\'.
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>from</td>
+    <td>The prefix to match.  Note that this value is case-insensitive when the build is running on
+      a Windows platform and case-sensitive when running on a Unix platform.  <em>Since Ant
+      1.7.0</em>, on Windows this value is also insensitive to the slash style used for directories,
+      one can use <q>/</q> or <q>\</q>.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">to</td>
-    <td valign="top">The replacement text to use when <code>from</code> is matched.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>to</td>
+    <td>The replacement text to use when <var>from</var> is matched.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<p>Each map element specifies a single replacement map to be applied to the elements of
-   the path being processed.  If no map entries are specified, then no path prefix mapping
-   is performed.
-</p>
-<p><strong>Note</strong>: The map elements are applied in the order specified,
-and only the first matching map element is applied.  So, the ordering of
-your map elements can be important, if any <code>from</code> values are
-prefixes of other <code>from</code> values.</i>
-</p>   
-<h4>Resource Collections</h4>
-<p>If the <code>refid</code> attribute is not specified, then one or more
-   nested <a href="../Types/resources.html#collection">Resource
-Collection</a>s must be supplied.</p>
+<p>Each map element specifies a single replacement map to be applied to the elements of the path
+being processed.  If no map entries are specified, then no path prefix mapping is performed.</p>
+<p><strong>Note</strong>: The map elements are applied in the order specified, and only the first
+matching map element is applied.  So, the ordering of your map elements can be important, if
+any <var>from</var> values are prefixes of other <var>from</var> values.</p>
+<h4>resource collections</h4>
+<p>If the <var>refid</var> attribute is not specified, then one or more
+nested <a href="../Types/resources.html#collection">resource collections</a> must be supplied.</p>
 <h4>mapper</h4>
-<p>A single nested <a href="../Types/mapper.html">
-<code>&lt;mapper&gt;</code></a> element can be specified
-to perform any of various filename transformations (since Ant 1.6.2).
-</p>
+<p>A single nested <a href="../Types/mapper.html"><code>&lt;mapper&gt;</code></a> element can be
+specified to perform any of various filename transformations (<em>since Ant 1.6.2</em>).</p>
 
 <h3>Examples</h3>
-<p>In the examples below, assume that the <code>${wl.home}</code> property
-has the value
-<code>d:\weblogic</code>, and <code>${wl.home.unix}</code> has the value
-<code>/weblogic</code>.</p>
+<p>In the examples below, assume that the <samp>${wl.home}</samp> property has the
+value <samp>d:\weblogic</samp>, and <samp>${wl.home.unix}</samp> has the
+value <samp>/weblogic</samp>.</p>
 <h4>Example 1</h4>
+<p>Here, the task</p>
 <pre>
-    &lt;path id="wl.path"&gt;
-      &lt;pathelement location=&quot;${wl.home}/lib/weblogicaux.jar&quot;/&gt;
-      &lt;pathelement location=&quot;${wl.home}/classes&quot;/&gt;
-      &lt;pathelement location=&quot;${wl.home}/mssqlserver4/classes&quot;/&gt;
-      &lt;pathelement location=&quot;c:\winnt\System32&quot;/&gt;
-    &lt;/path&gt;
-    
-    &lt;pathconvert targetos=&quot;unix&quot; property=&quot;wl.path.unix&quot; refid=&quot;wl.path&quot;&gt;
-      &lt;map from=&quot;${wl.home}&quot; to=&quot;${wl.home.unix}&quot;/&gt;
-      &lt;map from=&quot;c:&quot; to=&quot;&quot;/&gt;
-    &lt;/pathconvert&gt;
-</pre>
-<p> will generate the path shown below
-and store it in the property named <code>wl.path.unix</code>.
-</p>   
-<pre>
-/weblogic/lib/weblogicaux.jar:/weblogic/classes:/weblogic/mssqlserver4/classes:/WINNT/SYSTEM32
-</pre>
+&lt;path id="wl.path"&gt;
+  &lt;pathelement location=&quot;${wl.home}/lib/weblogicaux.jar&quot;/&gt;
+  &lt;pathelement location=&quot;${wl.home}/classes&quot;/&gt;
+  &lt;pathelement location=&quot;${wl.home}/mssqlserver4/classes&quot;/&gt;
+  &lt;pathelement location=&quot;c:\winnt\System32&quot;/&gt;
+&lt;/path&gt;
+
+&lt;pathconvert targetos=&quot;unix&quot; property=&quot;wl.path.unix&quot; refid=&quot;wl.path&quot;&gt;
+  &lt;map from=&quot;${wl.home}&quot; to=&quot;${wl.home.unix}&quot;/&gt;
+  &lt;map from=&quot;c:&quot; to=&quot;&quot;/&gt;
+&lt;/pathconvert&gt;</pre>
+<p>will generate the path shown below and store it in the property
+named <code>wl.path.unix</code>.</p>
+<pre class="output">/weblogic/lib/weblogicaux.jar:/weblogic/classes:/weblogic/mssqlserver4/classes:/WINNT/SYSTEM32</pre>
 
 <h4>Example 2</h4>
-Given a FileList defined as:
+<p>Given a FileList defined as:</p>
 <pre>
-  &lt;filelist id=&quot;custom_tasks.jars&quot;
-        dir=&quot;${env.HOME}/ant/lib&quot;
-        files=&quot;njavac.jar,xproperty.jar&quot;/&gt;
-</pre>
-then:
+&lt;filelist id=&quot;custom_tasks.jars&quot;
+          dir=&quot;${env.HOME}/ant/lib&quot;
+          files=&quot;njavac.jar,xproperty.jar&quot;/&gt;</pre>
+<p>then:</p>
 <pre>
-    &lt;pathconvert targetos=&quot;unix&quot; property=&quot;custom_tasks.jars&quot; refid=&quot;custom_tasks.jars&quot;&gt;
-      &lt;map from=&quot;${env.HOME}&quot; to=&quot;/usr/local&quot;/&gt;
-    &lt;/pathconvert&gt;
-</pre>
-will convert the list of files to the following Unix path:
-<pre>
-/usr/local/ant/lib/njavac.jar:/usr/local/ant/lib/xproperty.jar
-</pre>
+&lt;pathconvert targetos=&quot;unix&quot; property=&quot;custom_tasks.jars&quot; refid=&quot;custom_tasks.jars&quot;&gt;
+  &lt;map from=&quot;${env.HOME}&quot; to=&quot;/usr/local&quot;/&gt;
+&lt;/pathconvert&gt;</pre>
+<p>will convert the list of files to the following Unix path:</p>
+<pre class="output">/usr/local/ant/lib/njavac.jar:/usr/local/ant/lib/xproperty.jar</pre>
 
 <h4>Example 3</h4>
+<p>Here, the names of files determined by the fileset (all files ending in <samp>.java</samp>) are
+joined separated by comma, and the resulting list is placed into the
+property <code>javafiles</code>. The directory separator is not specified, so it defaults to the
+appropriate character for the current platform. Such a list could then be used in another task,
+like <code>javadoc</code>, that requires a comma separated list of files.</p>
 <pre>
-    &lt;fileset dir=&quot;${src.dir}&quot; id=&quot;src.files&quot;&gt;
-      &lt;include name=&quot;**/*.java&quot;/&gt;
-    &lt;/fileset&gt;
-  
-    &lt;pathconvert pathsep=&quot;,&quot; property=&quot;javafiles&quot; refid=&quot;src.files&quot;/&gt;
-</pre>
-<p>This example takes the set of files determined by the fileset (all files ending
-in <tt>.java</tt>), joins them together separated by commas, and places the resulting
-list into the property <tt>javafiles</tt>.  The directory separator is not specified, so
-it defaults to the appropriate character for the current platform.  Such a list could
-then be used in another task, like <tt>javadoc</tt>, that requires a comma separated
-list of files.
-</p>
+&lt;fileset dir=&quot;${src.dir}&quot; id=&quot;src.files&quot;&gt;
+  &lt;include name=&quot;**/*.java&quot;/&gt;
+&lt;/fileset&gt;
+
+&lt;pathconvert pathsep=&quot;,&quot; property=&quot;javafiles&quot; refid=&quot;src.files&quot;/&gt;</pre>
+
 <h4>Example 4</h4>
+<p>This task sets the property <code>prop</code> to <q>def|ghi</q> on Windows and on Unix.</p>
 <pre>
-    &lt;pathconvert property="prop" dirsep="|"&gt;
-      &lt;map from="${basedir}/abc/" to=''/&gt;
-      &lt;path location="abc/def/ghi"/&gt;
-    &lt;/pathconvert&gt;
-</pre>
-  <p>
-    This example sets the property "prop" to "def|ghi" on
-    Windows and on Unix.
-  </p>
+&lt;pathconvert property="prop" dirsep="|"&gt;
+  &lt;map from="${basedir}/abc/" to=&quot;&quot;/&gt;
+  &lt;path location="abc/def/ghi"/&gt;
+&lt;/pathconvert&gt;</pre>
 </body>
 </html>
-
- 
diff --git a/manual/Tasks/presetdef.html b/manual/Tasks/presetdef.html
index c7f381c..1251fb7 100644
--- a/manual/Tasks/presetdef.html
+++ b/manual/Tasks/presetdef.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,96 +15,66 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
-  
+<html lang="en">
+
   <head>
-    <meta http-equiv="Content-Language" content="en-us"></meta>
     <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>PreSetDef Task</title>
-    <style type="text/css">
-      <!--
-           .code { background: #EFEFEF; margin-top: }
-           -->
-    </style>
+    <title>PreSetDef Task</title>
   </head>
-  
+
   <body>
-    
-    <h2><a name="presetdef">PreSetDef</a></h2>
+
+    <h2 id="presetdef">PreSetDef</h2>
+    <p><em>Since Apache Ant 1.6</em></p>
     <h3>Description</h3>
-    <p>
-      The preset definition generates a new definition
-      based on a current definition with some attributes
-      or elements preset.
-    </p>
-    <p>
-      <em>since Apache Ant 1.6</em>
-    </p>
-    <p>
-      The resolution of properties in any of the attributes or
-      nested text takes place with the definition is used and <em>not</em>
-      when the preset definition is defined.
-    </p>
+    <p>The preset definition generates a new definition based on a current definition with some
+      attributes or elements preset.</p>
+    <p>The resolution of properties in any of the attributes or nested text takes place with the
+      definition is used and <em>not</em> when the preset definition is defined.</p>
     <h3>Parameters</h3>
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">name</td>
-        <td valign="top">the name of the new definition</td>
-        <td valign="top" align="center">Yes</td>
+        <td>name</td>
+        <td>the name of the new definition</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">uri</td>
-        <td valign="top">
-          The uri that this definition should live in.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>uri</td>
+        <td>The URI that this definition should live in.</td>
+        <td>No</td>
       </tr>
     </table>
     <h3>Parameters specified as nested elements</h3>
     <h4>another type with attributes or elements set</h4>
-    <p>The <code>&lt;presetdef&gt;</code> task takes one nested element as a parameter.
-      This nested element can be any other type or task. The attributes
-      and elements that need to be preset are placed here.
-    </p>
-    
+    <p>The <code>&lt;presetdef&gt;</code> task takes one nested element as a parameter.  This nested
+      element can be any other type or task. The attributes and elements that need to be preset are
+      placed here.</p>
+
     <h3>Examples</h3>
-      The following fragment defines a javac task with the debug, deprecation
-      srcdir and destdir
-      attributes set. It also has a src element to source files from a generated
-      directory.
-    <blockquote>
-<pre class="code">
+    <p>The following fragment defines a <code>javac</code> task with
+      the <var>debug</var>, <var>deprecation</var>, <var>srcdir</var> and <var>destdir</var>
+      attributes set. It also has a <code>src</code> element to source files from a generated
+      directory.</p>
+    <pre>
 &lt;presetdef name="my.javac"&gt;
    &lt;javac debug="${debug}" deprecation="${deprecation}"
           srcdir="${src.dir}" destdir="${classes.dir}"&gt;
       &lt;src path="${gen.dir}"/&gt;
    &lt;/javac&gt;
-&lt;/presetdef&gt;
-</pre>
-    </blockquote>
-      This can be used as a normal javac task - example:
-    <blockquote>
-<pre class="code">
-&lt;my.javac/&gt;
-</pre>
-    </blockquote>
-      The attributes specified in the preset task may be overridden - i.e.
-      they may be seen as optional attributes - example:
-    <blockquote>
-<pre class="code">
-&lt;my.javac srcdir="${test.src}" deprecation="no"/&gt;
-</pre>
-    </blockquote>
-      One may put a presetdef definition in an antlib.
-      For example suppose the jar file antgoodies.jar has
-      the antlib.xml as follows:
-    <blockquote>
-<pre class="code">
+&lt;/presetdef&gt;</pre>
+    <p>This can be used as a normal <code>javac</code> task&mdash;for example:</p>
+    <pre>&lt;my.javac/&gt;</pre>
+    <p>The attributes specified in the preset task may be overridden&mdash;i.e.  they may be seen as
+      optional attributes&mdash;for example:</p>
+    <pre>&lt;my.javac srcdir="${test.src}" deprecation="no"/&gt;</pre>
+    <p>One may put a <code>presetdef</code> definition in an antlib.  For example suppose the jar
+      file <samp>antgoodies.jar</samp> has the <samp>antlib.xml</samp> as follows:</p>
+    <pre>
 &lt;antlib&gt;
    &lt;taskdef resource="com/acme/antgoodies/tasks.properties"/&gt;
    &lt;!-- Implement the common use of the javac command --&gt;
@@ -111,12 +82,9 @@
       &lt;javac deprecation="${deprecation}" debug="${debug}"
              srcdir="src" destdir="classes"/&gt;
    &lt;/presetdef&gt;
-&lt;/antlib&gt;
-</pre>
-    </blockquote>
-      One may then use this in a build file as follows:
-    <blockquote>
-<pre class="code">
+&lt;/antlib&gt;</pre>
+    <p>One may then use this in a build file as follows:</p>
+    <pre>
 &lt;project default="example" xmlns:antgoodies="antlib:com.acme.antgoodies"&gt;
    &lt;target name="example"&gt;
       &lt;!-- Compile source --&gt;
@@ -124,15 +92,9 @@
       &lt;!-- Compile test code --&gt;
       &lt;antgoodies:javac srcdir="src/test"/&gt;
    &lt;/target&gt;
-&lt;/project&gt;
-</pre>
-    </blockquote>
-    <p>
-      The following is an example of evaluation of properties when the
-      definition is used:
-    </p>
-     <blockquote>
-<pre class="code">
+&lt;/project&gt;</pre>
+    <p>The following is an example of evaluation of properties when the definition is used:</p>
+    <pre>
 &lt;target name="defineandcall"&gt;
    &lt;presetdef name="showmessage"&gt;
       &lt;echo&gt;message is '${message}'&lt;/echo&gt;
@@ -146,39 +108,26 @@
 &lt;/target&gt;
 &lt;target name="called"&gt;
    &lt;showmessage/&gt;
-&lt;/target&gt;
-</pre>
-     </blockquote>
-     <p>
-        The command ant defineandcall results in the output:
-     </p>
-     <blockquote>
-<pre class="code">
+&lt;/target&gt;</pre>
+    <p>The command <kbd>ant defineandcall</kbd> results in the output:</p>
+    <pre class="output">
 defineandcall:
 [showmessage] message is '${message}'
 [showmessage] message is 'Message 1'
 
 called:
-[showmessage] message is 'Message 2'
-</pre>
-     </blockquote>
-<p>
-It is possible to use a trick to evaluate properties when the definition is
-<em>made</em> rather than used. This can be useful if you do not expect some
-properties to be available in child builds run with
-<code>&lt;ant ... inheritall="false"&gt;</code>:
-</p>
-<blockquote><pre class="code">
+[showmessage] message is 'Message 2'</pre>
+    <p>It is possible to use a trick to evaluate properties when the definition is <em>made</em>
+      rather than used. This can be useful if you do not expect some properties to be available in
+      child builds run with <code>&lt;ant ... inheritall="false"&gt;</code>:</p>
+    <pre>
 &lt;macrodef name="showmessage-presetdef"&gt;
   &lt;attribute name="messageval"/&gt;
   &lt;presetdef name="showmessage"&gt;
     &lt;echo&gt;message is '@{messageval}'&lt;/echo&gt;
   &lt;/presetdef&gt;
 &lt;/macrodef&gt;
-&lt;showmessage-presetdef messageval="${message}"/&gt;
-</pre></blockquote>
-    <hr></hr>
-    
+&lt;showmessage-presetdef messageval="${message}"/&gt;</pre>
+
   </body>
 </html>
-
diff --git a/manual/Tasks/projecthelper.html b/manual/Tasks/projecthelper.html
index ea78eb2..1f48947 100644
--- a/manual/Tasks/projecthelper.html
+++ b/manual/Tasks/projecthelper.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ProjectHelper Task</title>
 </head>
@@ -25,30 +25,28 @@
 <body>
 
 <h2>ProjectHelper</h2>
+<p><em>Since Ant 1.8.2</em></p>
 <h3>Description</h3>
-<p>This task is provided for the purpose of allowing the user to install a different
-ProjectHelper at runtime.
-</p>
-<p>The helpers will be added after all the already registered helpers, but before
-the default one (ProjectHelper2)
-</p>
-<p>See the description of Apache Ant's
-<a href="../projecthelper.html">Project Helper</a> for more information.
-</p>
-<p><b>Since Ant 1.8.2</b></p>
+<p>This task is provided for the purpose of allowing the user to install a different ProjectHelper
+at run time.</p>
+<p>The helpers will be added after all the already registered helpers, but before the default one
+(<code>ProjectHelper2</code>)</p>
+<p>See the description of Apache Ant's <a href="../projecthelper.html">Project Helper</a> for more
+information.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
-You may specify many configured <code>org.apache.tools.ant.ProjectHelper</code> instances.
+<p>You may specify many configured <code class="code">org.apache.tools.ant.ProjectHelper</code>
+instances.</p>
 
 <h3>Example</h3>
 
-<p>Install a custom ProjectHelper implementation
-  (assuming <code>MyProjectHelper extends ProjectHelper</code>):</p>
+<p>Install a custom ProjectHelper implementation (assuming <code class="code">MyProjectHelper
+extends ProjectHelper</code>):</p>
 
 <pre>
 &lt;typedef classname="org.example.MyProjectHelper"
-              name="myprojecthelper"/>
+         name="myprojecthelper"/>
 &lt;projecthelper>
   &lt;myprojecthelper/>
 &lt;/projecthelper>
@@ -56,4 +54,3 @@
 
 </body>
 </html>
-
diff --git a/manual/Tasks/property.html b/manual/Tasks/property.html
index df406b0..9fb1cec 100644
--- a/manual/Tasks/property.html
+++ b/manual/Tasks/property.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,362 +15,328 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Property Task</title>
 </head>
 
 <body>
 
-<h2><a name="property">Property</a></h2>
+<h2 id="property">Property</h2>
 <h3>Description</h3>
-<p>Sets a <a href="../using.html#properties">property</a>
-(by name and value), or set of properties (from file or
-resource) in the project.  Properties are case sensitive.</p>
- Properties are immutable: whoever sets a property first freezes it for the
- rest of the build; they are most definitely not variables.
+<p>Sets a <a href="../using.html#properties">property</a> (by name and value), or set of properties
+(from file or resource) in the project.  Properties are case sensitive.</p>
+<p>Properties are immutable: whoever sets a property first freezes it for the rest of the build;
+they are most definitely not variables.</p>
 <p>There are seven ways to set properties:</p>
 <ul>
-  <li>By supplying both the <i>name</i> and one of <i>value</i> or <i>location</i> attribute.</li>
-  <li>By supplying the <i>name</i> and nested text.</li>
-  <li>By supplying both the <i>name</i> and <i>refid</i> attribute.</li>
-  <li>By setting the <i>file</i> attribute with the filename of the property
-    file to load. This property file has the format as defined by the file used
-    in the class java.util.Properties, with the same rules about how
-    non-ISO8859-1 characters must be escaped.</li>
-  <li>By setting the <i>url</i> attribute with the url from which to load the
-    properties. This url must be directed to a file that has the format as defined
-    by the file used in the class java.util.Properties.</li>
-  <li>By setting the <i>resource</i> attribute with the resource name of the
-    property file to load. A resource is a property file on the current
-    classpath, or on the specified classpath.</li>
-  <li>By setting the <i>environment</i> attribute with a prefix to use.
-    Properties will be defined for every environment variable by
-    prefixing the supplied name and a period to the name of the variable.</li>
-  <li>By setting the <i>runtime</i> attribute with a prefix to use.
-    Properties <code>prefix.availableProcessors</code>,
-    <code>prefix.freeMemory</code>, <code>prefix.totalMemory</code>
-    and <code>prefix.maxMemory</code> will be defined with values
-    returned by the corresponding methods of
+  <li>By supplying both the <var>name</var> and one of <var>value</var> or <var>location</var>
+    attributes.</li>
+  <li>By supplying the <var>name</var> and nested text.</li>
+  <li>By supplying both the <var>name</var> and <var>refid</var> attributes.</li>
+  <li>By setting the <var>file</var> attribute with the filename of the property file to load. This
+    property file has the format as defined by the file used in the
+    class <code class="code">java.util.Properties</code>, with the same rules about how
+    non-ISO-8859-1 characters must be escaped.</li>
+  <li>By setting the <var>url</var> attribute with the URL from which to load the properties. This
+    URL must be directed to a file that has the format as defined by the file used in the
+    class <code class="code">java.util.Properties</code>.</li>
+  <li>By setting the <var>resource</var> attribute with the resource name of the property file to
+    load. A resource is a property file on the current classpath, or on the specified
+    classpath.</li>
+  <li>By setting the <var>environment</var> attribute with a prefix to use.  Properties will be
+    defined for every environment variable by prefixing the supplied name and a period to the name
+    of the variable.</li>
+  <li>By setting the <var>runtime</var> attribute with a prefix to use.
+    Properties <code>prefix.availableProcessors</code>, <code>prefix.freeMemory</code>, <code>prefix.totalMemory</code>
+    and <code>prefix.maxMemory</code> will be defined with values returned by the
+    corresponding methods of
     the <a href="https://docs.oracle.com/javase/10/docs/api/java/lang/Runtime.html">Runtime</a>
     class.</li>
 </ul>
-<p>Although combinations of these ways are possible, only one should be used
-at a time. Problems might occur with the order in which properties are set, for
-instance.</p>
-<p>The value part of the properties being set, might contain references to other
-properties. These references are resolved at the time these properties are set.
-This also holds for properties loaded from a property file.</p>
-<p>A list of predefined properties can be found <a
-href="../properties.html#built-in-props">here</a>.</p>
-<p>Since Apache Ant 1.8.0 it is possible to load properties defined in xml
-according to <a href="http://java.sun.com/dtd/properties.dtd">Suns DTD</a>,
-if Java5+ is present. For this the name of the file, resource or url has 
-to end with <tt>.xml</tt>.</p>
+<p>Although combinations of these ways are possible, only one should be used at a time. Problems
+might occur with the order in which properties are set, for instance.</p>
+<p>The value part of the properties being set might contain references to other properties. These
+references are resolved at the time these properties are set.  This also holds for properties loaded
+from a property file.</p>
+<p>A list of predefined properties can be
+found <a href="../properties.html#built-in-props">here</a>.</p>
+<p><em>Since Apache Ant 1.8.0</em>, it is possible to load properties defined in XML according
+to <a href="https://java.sun.com/dtd/properties.dtd" target="_top">Sun DTD</a>, when running on Java
+5+. For this the name of the file, resource or url has to end with <samp>.xml</samp>.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the property to set.</td>
-    <td valign="top" align="center">No</td>
+    <td>name</td>
+    <td>the name of the property to set.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">the value of the property.</td>
-    <td valign="middle" align="center" rowspan="3">One of these or
-       nested text, when using the name attribute</td>
+    <td>value</td>
+    <td>the value of the property.</td>
+    <td rowspan="3">One of these or nested text, when the <var>name</var> attribute is set</td>
   </tr>
   <tr>
-    <td valign="top">location</td>
-    <td valign="top">Sets the property to the absolute filename of the
-      given file. If the value of this attribute is an absolute path, it
-      is left unchanged (with / and \ characters converted to the
-      current platforms conventions). Otherwise it is taken as a path
-      relative to the project's basedir and expanded.</td>
+    <td>location</td>
+    <td class="left">Sets the property to the absolute filename of the given file. If the value of
+      this attribute is an absolute path, it is left unchanged (with <q>/</q> and <q>\</q>
+      characters converted to the current platforms conventions). Otherwise it is taken as a path
+      relative to the project's <var>basedir</var> and expanded.</td>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top"><a href="../using.html#references">Reference</a> to an object
-      defined elsewhere. Only yields reasonable results for references
-      to <a href="../using.html#path">PATH like structures</a> or properties.</td>
+    <td>refid</td>
+    <td class="left"><a href="../using.html#references">Reference</a> to an object defined
+      elsewhere. Only yields reasonable results for references
+      to <a href="../using.html#path">path-like structures</a> or properties.</td>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top"> the name of the classpath resource containing
-      properties settings in properties file format.</td>
-    <td valign="middle" align="center" rowspan="5">One of these, when
-      <b>not</b> using the name attribute</td>
+    <td>resource</td>
+    <td>the name of the classpath resource containing properties settings in properties file
+      format.</td>
+    <td rowspan="5">One of these, <strong>unless</strong> the <var>name</var> attribute is set</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the location of the properties file to load.</td>
+    <td>file</td>
+    <td class="left">the location of the properties file to load.</td>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">a url containing properties-format settings.</td>
+    <td>url</td>
+    <td class="left">a URL containing properties-format settings.</td>
   </tr>
   <tr>
-    <td valign="top">environment</td>
-    <td valign="top">the prefix to use when retrieving environment variables. Thus
-    if you specify environment=&quot;myenv&quot; you will be able to access OS-specific
-    environment variables via property names &quot;myenv.PATH&quot; or
-    &quot;myenv.TERM&quot;. Note that if you supply a property name with a final
-    &quot;.&quot; it will not be doubled; i.e. environment=&quot;myenv.&quot; will still
-    allow access of environment variables through &quot;myenv.PATH&quot; and
-    &quot;myenv.TERM&quot;. This functionality is currently only implemented
-    on <a href="#notes-env">select platforms</a>. Feel free to send patches to increase the
-    number of platforms on which this functionality is supported ;).<br>
-    Note also that properties are case-sensitive, even if the
-    environment variables on your operating system are not; e.g. Windows 2000's
-    system path variable is set to an Ant property named "env.Path"
-    rather than "env.PATH".</td>
+    <td>environment</td>
+    <td class="left">the prefix to use when retrieving environment variables. Thus if you
+      specify <var>environment</var>=<q>myenv</q> you will be able to access OS-specific environment
+      variables via property names <code>myenv.PATH</code> or <code>myenv.TERM</code>. Note that if
+      you supply a property <var>name</var> with a final <q>.</q> it will not be doubled;
+      i.e. <var>environment</var>=<q>myenv.</q> will still allow access of environment variables
+      through <code>myenv.PATH</code> and <code>myenv.TERM</code>. This functionality is currently
+      only implemented on <a href="#notes-env">select platforms</a>. Feel free to send patches to
+      increase the number of platforms on which this functionality is supported ;-).<br/>Note also
+      that properties are case-sensitive, even if the environment variables on your operating system
+      are not; e.g. Windows 2000 or later system path variable is set to an Ant property
+      named <code>env.Path</code> rather than <code>env.PATH</code>.</td>
   </tr>
   <tr>
-    <td valign="top">runtime</td>
-    <td valign="top">the prefix to use when retrieving runtime properties. Thus
-    if you specify runtime=&quot;myrt&quot; you will be able to access
-    runtime values corresponding to methods in
+    <td>runtime</td>
+    <td class="left">the prefix to use when retrieving runtime properties. Thus if you
+    specify <var>runtime</var>=<q>myrt</q> you will be able to access runtime values corresponding
+    to methods in
     the <a href="https://docs.oracle.com/javase/10/docs/api/java/lang/Runtime.html">Runtime</a>
-    class via property names &quot;myrt.availableProcessors&quot;,
-    &quot;myrt.maxMemory&quot;, &quot;myrt.totalMemory&quot; or
-    &quot;myrt.freeMemory&quot;. Note that if you supply a property name with a final
-    &quot;.&quot; it will not be doubled; i.e. runtime=&quot;myrt.&quot; will still
-    allow access of runtime properties as e.g. &quot;myrt.maxMemory&quot;.<br>
-    Note also that the property values are snapshots taken at the point in time
-    when the <code>property</code> has been executed.
-    <em>Since Ant 1.9.12</em>
+    class via property
+    names <code>myrt.availableProcessors</code>, <code>myrt.maxMemory</code>, <code>myrt.totalMemory</code>
+    or <code>myrt.freeMemory</code>. Note that if you supply a property name with a final <q>.</q>
+    it will not be doubled; i.e. <var>runtime</var>=<q>myrt.</q> will still allow access of runtime
+    properties as e.g. <code>myrt.maxMemory</code>.<br>  Note also that the property values are
+    snapshots taken at the point in time when the <code>property</code> has been executed. <em>Since
+    Ant 1.10.4</em>
     </td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use when looking up a resource.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>the classpath to use when looking up a resource.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">the classpath to use when looking up a resource,
-      given as <a href="../using.html#references">reference</a> to a <code>&lt;path&gt;</code> defined
+    <td>classpathref</td>
+    <td>the classpath to use when looking up a resource, given
+      as <a href="../using.html#references">reference</a> to a <code>&lt;path&gt;</code> defined
       elsewhere..</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">Prefix to apply to properties loaded using <code>file</code>,
-    <code>resource</code>, or <code>url</code>.
-      A "." is appended to the prefix if not specified.</td>
-    <td align="center" valign="top">No</td>
+    <td>prefix</td>
+    <td>Prefix to apply to properties loaded using <var>file</var>, <var>resource</var>,
+      or <var>url</var>.  A <q>.</q> is appended to the prefix if not specified.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">prefixValues</td>
-    <td valign="top">Whether to apply the prefix when expanding the
-      right hand side of properties loaded using <code>file</code>,
-      <code>resource</code>, or <code>url</code>.
-      <em>Since Ant 1.8.2</em></td>
-    <td align="center" valign="top">No (default=<tt>false</tt>)</td>
+    <td>prefixValues</td>
+    <td>Whether to apply the prefix when expanding the right hand side of properties loaded
+      using <var>file</var>, <var>resource</var>, or <var>url</var>.  <em>Since Ant 1.8.2</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">relative</td>
-    <td valign="top">If set to <tt>true</tt> the relative path
-      to <tt>basedir</tt> is set.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No (default=<tt>false</tt>)</td>
+    <td>relative</td>
+    <td>If set to <q>true</q> the relative path to <var>basedir</var> is set.  <em>Since Ant
+      1.8.0</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">The basedir to calculate the relative path
-      from.  <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No (default=<tt>${basedir}</tt>)</td>
+    <td>basedir</td>
+    <td>The <var>basedir</var> to calculate the relative path from.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is project's <var>basedir</var></td>
   </tr>
 </table>
 
 <h4>OpenVMS Users</h4>
-<p>With the <code>environment</code> attribute this task will load all defined
-logicals on an OpenVMS system.  Logicals with multiple equivalence names get
-mapped to a property whose value is a comma separated list of all equivalence
-names.  If a logical is defined in multiple tables, only the most local
-definition is available (the table priority order being PROCESS, JOB, GROUP,
-SYSTEM).
-</p>
+<p>With the <var>environment</var> attribute this task will load all defined logicals on an OpenVMS
+system.  Logicals with multiple equivalence names get mapped to a property whose value is a comma
+separated list of all equivalence names.  If a logical is defined in multiple tables, only the most
+local definition is available (the table priority order being PROCESS, JOB, GROUP, SYSTEM).</p>
 
 <h4>Any OS except OpenVMS</h4>
-<p>Starting with Ant 1.8.2 if Ant detects it is running of a Java 1.5
-  VM (or better) Ant will use <code>System.getenv</code> rather than
-  its own OS dependent native implementation.  For some OSes this
-  causes minor differences when compared to older versions of Ant.
-  For a full list
-  see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=49366">Bugzilla
-  Issue 49366</a>.  In particular:</p>
+<p><em>Since Ant 1.8.2</em>, if Ant detects it is running on a Java 5 or newer, Ant will
+use <code class="code">System.getenv()</code> rather than its own OS dependent native
+implementation.  For some OSes this causes minor differences when compared to older versions of Ant.
+For a full list see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=49366"
+target="_top">Bugzilla Issue 49366</a>.  In particular:</p>
 <ul>
-  <li>On Windows Ant will now return additional "environment
-    variables" that correspond to the drive specific current working
-    directories when Ant is run from the command line.  The keys of
+  <li>On Windows, Ant will now return additional "environment variables" that correspond to the
+    drive specific current working directories when Ant is run from the command line.  The keys of
     these variables starts with an equals sign.</li>
-  <li>Some users reported that some Cygwin specific variables (in
-    particular PROMPT) was no longer present.</li>
-  <li>On OS/2 Ant no longer returns the BEGINLIBPATH variable.</li>
+  <li>Some users reported that some Cygwin specific variables (in particular <code>PROMPT</code>)
+    were no longer present.</li>
+  <li>On OS/2, Ant no longer returns the <code>BEGINLIBPATH</code> variable.</li>
 </ul>
 
 <h3>Parameters specified as nested elements</h3>
 <h4>classpath</h4>
-<p><code>Property</code>'s <i>classpath</i> attribute is a <a
-href="../using.html#path">PATH like structure</a> and can also be set via a nested
-<i>classpath</i> element.</p>
+<p><code>Property</code>'s <var>classpath</var> attribute is
+a <a href="../using.html#path">path-like structure</a> and can also be set via a
+nested <code>classpath</code> element.</p>
 
 <h3>Examples</h3>
-<pre>  &lt;property name=&quot;foo.dist&quot; value=&quot;dist&quot;/&gt;</pre>
-<p>sets the property <code>foo.dist</code> to the value &quot;dist&quot;.</p>
+<p>Set the property <code>foo.dist</code> to the value <q>dist</q>.</p>
+<pre>&lt;property name=&quot;foo.dist&quot; value=&quot;dist&quot;/&gt;</pre>
 
-<pre>  &lt;property name=&quot;foo.dist&quot;&gt;dist&lt;/property&gt;</pre>
-<p>sets the property <code>foo.dist</code> to the value &quot;dist&quot;.</p>
+<p>Set the property <code>foo.dist</code> to the value <q>dist</q>.</p>
+<pre>&lt;property name=&quot;foo.dist&quot;&gt;dist&lt;/property&gt;</pre>
 
-<pre>  &lt;property file=&quot;foo.properties&quot;/&gt;</pre>
-<p>reads a set of properties from a file called &quot;foo.properties&quot;.</p>
+<p>Read a set of properties from a file called <samp>foo.properties</samp>.</p>
+<pre>&lt;property file=&quot;foo.properties&quot;/&gt;</pre>
 
-<pre>  &lt;property url=&quot;http://www.mysite.com/bla/props/foo.properties&quot;/&gt;</pre>
-<p>reads a set of properties from the address &quot;http://www.mysite.com/bla/props/foo.properties&quot;.</p>
+<p>Read a set of properties from the
+address <samp>https://www.mysite.com/bla/props/foo.properties</samp>.</p>
+<pre>&lt;property url=&quot;https://www.mysite.com/bla/props/foo.properties&quot;/&gt;</pre>
 
-<pre>  &lt;property resource=&quot;foo.properties&quot;/&gt;</pre>
-<p>reads a set of properties from a resource called &quot;foo.properties&quot;.</p>
-<p>Note that you can reference a global properties file for all of your Ant
-builds using the following:</p>
+<p>Read a set of properties from a resource called <samp>foo.properties</samp>.</p>
+<pre>&lt;property resource=&quot;foo.properties&quot;/&gt;</pre>
 
-<pre>  &lt;property file=&quot;${user.home}/.ant-global.properties&quot;/&gt;</pre>
-<p>since the &quot;user.home&quot; property is defined by the Java virtual machine
-to be your home directory.  Where the &quot;user.home&quot; property resolves to in
-the file system depends on the operating system version and the JVM implementation.
-On Unix based systems, this will map to the user's home directory. On modern Windows
-variants, this will most likely resolve to the user's directory in the &quot;Documents
-and Settings&quot; or &quot;Users&quot; folder. Older windows variants such as Windows 98/ME are less
-predictable, as are other operating system/JVM combinations.</p>
+<p>Note that you can reference a global properties file for all of your Ant builds using the
+following:</p>
+<pre>&lt;property file=&quot;${user.home}/.ant-global.properties&quot;/&gt;</pre>
+<p>since the <code>user.home</code> property is defined by JVM to be your home directory. Where
+the <code>user.home</code> property resolves to in the file system depends on the operating system
+version and the JVM implementation.  On Unix based systems, this will map to the user's home
+directory. On modern Windows variants, this will most likely resolve to the user's directory in
+the <samp>Documents and Settings</samp> or <samp>Users</samp> folder. Older Windows variants such as
+Windows 98/ME are less predictable, as are other operating system/JVM combinations.</p>
 
+<p>Read the system environment variables and stores them in properties, prefixed
+with <q>env</q>. Note that this only works on <em>select</em> operating systems. Two of the values
+are shown being echoed.</p>
 <pre>
-  &lt;property environment=&quot;env&quot;/&gt;
-  &lt;echo message=&quot;Number of Processors = ${env.NUMBER_OF_PROCESSORS}&quot;/&gt;
-  &lt;echo message=&quot;ANT_HOME is set to = ${env.ANT_HOME}&quot;/&gt;
-</pre>
-<p>reads the system environment variables and stores them in properties, prefixed with &quot;env&quot;.
-Note that this only works on <em>select</em> operating systems.
-Two of the values are shown being echoed.
-</p>
+&lt;property environment=&quot;env&quot;/&gt;
+&lt;echo message=&quot;Number of Processors = ${env.NUMBER_OF_PROCESSORS}&quot;/&gt;
+&lt;echo message=&quot;ANT_HOME is set to = ${env.ANT_HOME}&quot;/&gt;</pre>
 
+<p>This buildfile uses the properties defined in <samp>build.properties</samp>. Regarding to the
+environment variable <code>STAGE</code> some or all values could be overwritten,
+e.g. having <code>STAGE=test</code> and a <samp>test.properties</samp> you have special values for
+that (like another name for the test server). Finally all these values could be overwritten by
+personal settings with a file per user.</p>
 <pre>
-  &lt;property environment=&quot;env&quot;/&gt;
-  &lt;property file=&quot;${user.name}.properties&quot;/&gt;
-  &lt;property file=&quot;${env.STAGE}.properties&quot;/&gt;
-  &lt;property file=&quot;build.properties&quot;/&gt;
-</pre>
-<p>This buildfile uses the properties defined in <tt>build.properties</tt>. Regarding to the
-environment variable <tt>STAGE</tt> some or all values could be overwritten, e.g. having
-<tt>STAGE=test</tt> and a <tt>test.properties</tt> you have special values for that (like another
-name for the test server). Finally all these values could be overwritten by personal settings with
-a file per user.</p>
+&lt;property environment=&quot;env&quot;/&gt;
+&lt;property file=&quot;${user.name}.properties&quot;/&gt;
+&lt;property file=&quot;${env.STAGE}.properties&quot;/&gt;
+&lt;property file=&quot;build.properties&quot;/&gt;</pre>
 
-<pre>
-  &lt;property name=&quot;foo&quot; location=&quot;my/file.txt&quot; relative=&quot;true&quot; basedir=&quot;..&quot;/&gt;
-</pre>
-<p>Stores the relative path in <tt>foo</tt>: projectbasedir/my/file.txt</p>
+<p>Store the relative path in <code>foo</code>: <samp>../my/file.txt</samp></p>
+<pre>&lt;property name=&quot;foo&quot; location=&quot;my/file.txt&quot; relative=&quot;true&quot; basedir=&quot;..&quot;/&gt;</pre>
 
-<pre>
-  &lt;property name=&quot;foo&quot; location=&quot;my/file.txt&quot; relative=&quot;true&quot; basedir=&quot;cvs&quot;/&gt;
-</pre>
-<p>Stores the relative path in <tt>foo</tt>: ../my/file.txt</p>
+<p>Store the relative path in <code>foo</code>: <samp>cvs/my/file.txt</samp></p>
+<pre>&lt;property name=&quot;foo&quot; location=&quot;my/file.txt&quot; relative=&quot;true&quot; basedir=&quot;cvs&quot;/&gt;</pre>
 
+<h3>Property files</h3>
 
-<h3>Property Files</h3>
-
-As stated, this task will load in a properties file stored in the file
-system, or as a resource on a classpath. Here are some interesting facts
-about this feature
+<p>As stated, this task will load in a properties file stored in the file system, or as a resource
+on a classpath. Here are some interesting facts about this feature</p>
 <ol>
-<li>If the file is not there, nothing is printed except at -verbose log
-level. This lets you have optional configuration files for every
-project, that team members can customize.
-<li>The rules for this format match <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.InputStream%29">java.util.Properties</a>.</li>
-<li>Trailing spaces are not stripped. It may have been what you wanted.</li>
-<li>Want unusual characters? Escape them \u0456 or \&quot; style.</li>
-<li>Ant Properties are expanded in the file</li>
-<li>If you want to expand properties defined inside the same file and
-  you use the prefix attribute of the task, you must use the same
-  prefix when expanding the properties or
-  set <code>prefixValues</code> to true.</li>
+  <li>If the file is not there, nothing is printed except at <kbd>-verbose</kbd> log level. This
+    lets you have optional configuration files for every project, that team members can customize.
+  <li>The rules for this format
+    match <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.InputStream-"
+    target="_top">java.util.Properties</a>.</li>
+  <li>Trailing spaces are not stripped. It may have been what you wanted.</li>
+  <li>Want unusual characters? Escape them <code>\u0456</code> or <code>\&quot;</code> style.</li>
+  <li>Ant Properties are expanded in the file</li>
+  <li>If you want to expand properties defined inside the same file and you use
+    the <var>prefix</var> attribute of the task, you must use the same prefix when expanding the
+    properties or set <var>prefixValues</var> to <q>true</q>.</li>
 </ol>
-In-file property expansion is very cool. Learn to use it.
-<p>
-Example:
+<p>In-file property expansion is very cool. Learn to use it.</p>
+<p>Example:</p>
 <pre>
 build.compiler=jikes
 deploy.server=lucky
-deploy.port=8080
-deploy.url=http://${deploy.server}:${deploy.port}/
-</pre>
+deploy.port=8443
+deploy.url=https://${deploy.server}:${deploy.port}/</pre>
 
-
-<a name="notes-env"></a>
-<h3>Notes about environment variables</h3>
+<h3 id="notes-env">Notes about environment variables</h3>
 <p>
   When Ant started to support setting properties from environment
-  variables it ran on Java 1.2 where <code>System.getEnv</code> didn't
+  variables it ran on Java 1.2 where <code class="code">System.getEnv</code> didn't
   work. So we decided to start a command in a new process which prints
   the environment variables, analyzes the output and creates the
   properties. With Ant 1.9.0 when we started to require Java 5 we switched back
-  to <code>System.getEnv</code> even though it returned different results on some
+  to <code class="code">System.getEnv</code> even though it returned different results on some
   platforms. The commands described below are still used on OpenVMS or
-  if <code>System.getEnv</code> throws an exception.
+  if <code class="code">System.getEnv</code> throws an exception.
 </p>
 <p>
   There are commands for the following operating systems implemented in
   <a href="https://gitbox.apache.org/repos/asf?p=ant.git;a=blob;f=src/main/org/apache/tools/ant/taskdefs/Execute.java;h=2f29256ed8ee964d78718fd0d7929659008482e6;hb=HEAD">
-  Execute.java</a> (method <tt>getProcEnvCommand()</tt>):
+  Execute.java</a> (method <code class="code">getProcEnvCommand()</code>):
   <table>
     <tr>
-      <th>OS</th>
-      <th>command</th>
+      <th scope="col">OS</th>
+      <th scope="col">command</th>
     </tr>
     <tr>
-      <td> os/2 </td>
-      <td> cmd /c set </td>
+      <td>os/2</td>
+      <td><code>cmd /c set</code></td>
     </tr>
     <tr>
-      <td colspan="2"> windows </td>
+      <td colspan="2">windows</td>
     </tr>
     <tr>
-      <td> * win9x </td>
-      <td> command.com /c set </td>
+      <td>* win9x</td>
+      <td><code>command.com /c set</code></td>
     </tr>
     <tr>
-      <td> * other </td>
-      <td> cmd /c set </td>
+      <td>* other</td>
+      <td><code>cmd /c set</code></td>
     </tr>
     <tr>
-      <td> z/os </td>
-      <td> /bin/env <b>OR</b> /usr/bin/env <b>OR</b> env   <i>(depending on read rights)</i> </td>
+      <td>z/os</td>
+      <td><code>/bin/env</code> <strong>OR</strong> <code>/usr/bin/env</code> <strong>OR</strong> <code>env</code> (<em>depending on read rights</em>)</td>
     </tr>
     <tr>
-      <td> unix </td>
-      <td> /bin/env <b>OR</b> /usr/bin/env <b>OR</b> env   <i>(depending on read rights)</i> </td>
+      <td>unix</td>
+      <td><code>/bin/env</code> <strong>OR</strong> <code>/usr/bin/env</code> <strong>OR</strong> <code>env</code> (<em>depending on read rights</em>)</td>
     </tr>
     <tr>
-      <td> netware </td>
-      <td> env </td>
+      <td>netware</td>
+      <td><code>env</code></td>
     </tr>
     <tr>
-      <td> os/400 </td>
-      <td> env </td>
+      <td>os/400</td>
+      <td><code>env</code></td>
     </tr>
     <tr>
-      <td> openvms </td>
-      <td> show logical </td>
+      <td>openvms</td>
+      <td><code>show logical</code></td>
     </tr>
   </table>
-</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/propertyfile.html b/manual/Tasks/propertyfile.html
index e4030f8..5f21962 100644
--- a/manual/Tasks/propertyfile.html
+++ b/manual/Tasks/propertyfile.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,9 +15,8 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>PropertyFile Task</title>
 </head>
@@ -24,143 +24,140 @@
 <body>
 
 <h1>PropertyFile</h1>
+<hr/>
+<h2 id="introduction">Introduction</h2>
+<p>Apache Ant provides an optional task for editing property files. This is very useful when wanting
+to make unattended modifications to configuration files for application servers and
+applications. Currently, the task maintains a working property file with the ability to add
+properties or make changes to existing ones. <em>Since Ant 1.8.0</em> comments and layout of the
+original properties file are preserved.</p>
 
-<hr>
-<h2><a name="introduction">Introduction</a></h2>
-<p>Apache Ant provides an optional task for editing property files. This is
-very useful when wanting to make unattended modifications to
-configuration files for application servers and
-applications. Currently, the task maintains a working property file
-with the ability to add properties or make changes to existing
-ones. <em>Since Ant 1.8.0</em> comments and layout of the original properties
-file are preserved.</p>
+<p><em>Since Ant 1.8.2</em> the linefeed-style of the original file will be preserved as well, as
+long as style used to be consistent.  In general, linefeeds of the updated file will be the same as
+the first linefeed found when reading it.</p>
 
-<p><em>Since Ant 1.8.2</em> the linefeed-style of the original file
-  will be preserved as well, as long as style used to be consistent.
-  In general, linefeeds of the updated file will be the same as the
-  first linefeed found when reading it.</p>
+<hr/>
 
-<hr>
-<h2><a name="proptask">PropertyFile Task</a></h2>
+<h2 id="proptask">PropertyFile Task</h2>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
 <tr>
-  <td width="12%" valign="top">file</td>
-  <td width="78%" valign="top">Location of the property file to be edited</td>
-  <td width="10%" valign="top">Yes</td>
+  <td>file</td>
+  <td>Location of the property file to be edited</td>
+  <td>Yes</td>
 </tr>
 <tr>
-  <td width="12%" valign="top">comment</td>
-  <td width="78%" valign="top">Header for the file itself</td>
-  <td width="10%" valign="top">no</td>
+  <td>comment</td>
+  <td>Header for the file itself</td>
+  <td>No</td>
 </tr>
 <tr>
-  <td width="12%" valign="top">jdkproperties</td>
-  <td width="78%" valign="top">Use java.lang.Properties, which will
-    loose comments and layout of file (default is 'false').  <em>since
+  <td>jdkproperties</td>
+  <td>Use <code>java.lang.Properties</code>, which will lose comments and layout of file.  <em>since
     Ant 1.8.0</em></td>
-  <td width="10%" valign="top">no</td>
+  <td>No; default is <q>false</q></td>
 </tr>
 </table>
 
-<p>The boolean attribute 'jdkproperties' is provided to recover the
-previous behaviour of the task, in which the layout and any comments
-in the properties file were lost by the task.</p>
+<p>The boolean attribute <var>jdkproperties</var> is provided to recover the previous behaviour of
+the task, in which the layout and any comments in the properties file were lost by the task.</p>
 
 <h3>Parameters specified as nested elements</h3>
-<h4><a name="entryElement">Entry</a></h4>
-<p>Use nested <code>&lt;entry&gt;</code>
-elements to specify actual modifications to the property file itself.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h4 id="entryElement">Entry</h4>
+<p>Use nested <code>&lt;entry&gt;</code> elements to specify actual modifications to the property
+file itself.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">key</td>
-    <td valign="top">Name of the property name/value pair</td>
-    <td valign="top" align="center">Yes</td>
+    <td>key</td>
+    <td>Name of the property name/value pair</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">Value to set (=), to add (+) or subtract (-)</td>
-    <td valign="top" align="center" rowspan="2">At least one must be specified, if <i>operation</i> is not <i>delete</i></td>
+    <td>value</td>
+    <td>Value to set (<q>=</q>), to add (<q>+</q>) or subtract (<q>-</q>)</td>
+    <td rowspan="2">At least one must be specified, if <var>operation</var> is not <q>del</q></td>
   </tr>
   <tr>
-    <td valign="top">default</td>
-    <td valign="top">Initial value to set for a property if it is not
-                     already defined in the property file.<br>
-                     For type date, an additional keyword is allowed: &quot;now&quot;</td>
-    </tr>
+    <td>default</td>
+    <td class="left">Initial value to set for a property if it is not already defined in the
+      property file.<br/>For type <var>date</var>, an additional keyword is
+      allowed: <q>now</q></td></tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">Regard the value as : int, date or string (default)</td>
-    <td valign="top" align="center">No</td>
+    <td>type</td>
+    <td>Regard the value as: <q>int</q>, <q>date</q> or <q>string</q> (default)</td>
+    <td>No; defaults to <q>string</q></td>
   </tr>
   <tr>
-    <td valign="top">operation</td>
-    <td valign="top">One of the following operations:<br><br>
-    <b>for all datatypes:</b><ul>
-      <li>&quot;del&quot; : deletes an entry</li>
-      <li>&quot;+&quot; : adds a value to the existing value</li>
-      <li>&quot;=&quot; : sets a value instead of the existing value (default)</li>
-    </ul><br><b>for date and int only:</b><ul>
-      <li>&quot;-&quot; : subtracts a value from the existing value</li>
-    </ul>
+    <td>operation</td>
+    <td>One of the following operations:<br/>
+      <strong>for all datatypes:</strong>
+      <ul>
+        <li><q>del</q> : deletes an entry</li>
+        <li><q>+</q> : adds a value to the existing value</li>
+        <li><q>=</q> : sets a value instead of the existing value (default)</li>
+      </ul>
+      <strong>for <var>date</var> and <var>int</var> only:</strong>
+      <ul>
+        <li><q>-</q> : subtracts a value from the existing value</li>
+      </ul>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to <q>=</q></td>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">For int and date type only. If present, Values will
-                     be parsed and formatted accordingly.</td>
-    <td valign="top" align="center">No</td>
+    <td>pattern</td>
+    <td>For <var>int</var> and <var>date</var> type only. If present, values will be parsed and
+      formatted accordingly.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unit</td>
-    <td valign="top">The unit of the value to be applied to date +/- operations.
-                     Valid Values are:
-                     <ul>
-                        <li>millisecond</li>
-                        <li>second</li>
-                        <li>minute</li>
-                        <li>hour</li>
-                        <li>day (default)</li>
-                        <li>week</li>
-                        <li>month</li>
-                        <li>year</li>
-                     </ul>
-                     This only applies to date types using a +/- operation.
+    <td>unit</td>
+    <td>The unit of the value to be applied to <var>date</var> <q>+</q>/<q>-</q> operations.  Valid
+      Values are:
+      <ul>
+        <li><q>millisecond</q></li>
+        <li><q>second</q></li>
+        <li><q>minute</q></li>
+        <li><q>hour</q></li>
+        <li><q>day</q> (default)</li>
+        <li><q>week</q></li>
+        <li><q>month</q></li>
+        <li><q>year</q></li>
+      </ul>
+      This only applies to <var>date</var> types using a <q>+</q>/<q>-</q> operation.
     </td>
-    <td align="center" valign="top">No</td>
+    <td>No; defaults to <q>day</q></td>
   </tr>
 </table>
-<p>The rules used when setting a property value are shown below.&nbsp; The
-operation occurs <b>after</b> these rules are considered.</p>
+<p>The rules used when setting a property value are shown below. The operation
+occurs <strong>after</strong> these rules are considered.</p>
 
 <ul>
-  <li>If only value is specified, the property is set to it regardless of its
-  previous value.</li>
-  <li>If only default is specified and the property previously existed in the
-  property file, it is unchanged.</li>
-  <li>If only default is specified and the property did not exist in the
-  property file, the property is set to default.</li>
-  <li>If value and default are both specified and the property previously
-  existed in the property file, the property is set to value.</li>
-  <li>If value and default are both specified and the property did not exist in
-  the property file, the property is set to default.</li>
+  <li>If only <var>value</var> is specified, the property is set to it regardless of its previous
+    value.</li>
+  <li>If only <var>default</var> is specified and the property previously existed in the property
+    file, it is unchanged.</li>
+  <li>If only <var>default</var> is specified and the property did not exist in the property file,
+    the property is set to <var>default</var>.</li>
+  <li>If <var>value</var> and <var>default</var> are both specified and the property previously
+    existed in the property file, the property is set to <var>value</var>.</li>
+  <li>If <var>value</var> and <var>default</var> are both specified and the property did not exist
+    in the property file, the property is set to <var>default</var>.</li>
 </ul>
-<p>&nbsp;</p>
 
 <h3>Examples</h3>
 
-<p>The following changes the my.properties file.  Assume my.properties look like:</p>
+<p>The following changes the <samp>my.properties</samp> file.  Assume <samp>my.properties</samp>
+looks like:</p>
 
 <pre># A string value
 akey=original value
@@ -169,8 +166,7 @@
 # each time the build is run.
 anint=1</pre>
 
-<p>After running, the file would now look like
-</p>
+<p>After running, the file would now look like</p>
 <pre>#My properties
 #Wed Aug 31 13:47:19 BST 2005
 # A string value
@@ -185,65 +181,55 @@
 formated.int=0014
 
 formated.date=243 13\:47</pre>
-<p>
-The slashes conform to the expectations of the Properties class.  The file will be stored in a manner so that each character is examined and escaped if necessary. 
-</p>
+<p>The slashes conform to the expectations of the Properties class.  The file will be stored in a
+manner so that each character is examined and escaped if necessary.</p>
 
-<p>
-The layout and comment of the original file is preserved. New properties are added at the end of the file. Existing properties are overwritten in place.
-</p>
+<p>The layout and comment of the original file is preserved. New properties are added at the end of
+the file. Existing properties are overwritten in place.</p>
 
-<blockquote><pre>&lt;propertyfile
-    file=&quot;my.properties&quot;
-    comment=&quot;My properties&quot;&gt;
-  &lt;entry  key=&quot;akey&quot; value=&quot;avalue&quot;/&gt;
-  &lt;entry  key=&quot;adate&quot; type=&quot;date&quot; value=&quot;now&quot;/&gt;
-  &lt;entry  key=&quot;anint&quot; type=&quot;int&quot; default=&quot;0&quot; operation=&quot;+&quot;/&gt;
-  &lt;entry  key=&quot;formated.int&quot; type=&quot;int&quot; default=&quot;0013&quot; operation=&quot;+&quot; pattern=&quot;0000&quot;/&gt;
-  &lt;entry  key=&quot;formated.date&quot; type=&quot;date&quot; value=&quot;now&quot; pattern=&quot;DDD HH:mm&quot;/&gt;
-&lt;/propertyfile&gt;
-</pre></blockquote>
-<p>
-To produce dates relative from today :</p>
-<blockquote><pre>&lt;propertyfile
-    file=&quot;my.properties&quot;
-    comment=&quot;My properties&quot;&gt;
-  &lt;entry  key=&quot;formated.date-1&quot;
-      type=&quot;date&quot; default=&quot;now&quot; pattern=&quot;DDD&quot;
-      operation=&quot;-&quot; value=&quot;1&quot;/&gt;
-  &lt;entry  key=&quot;formated.tomorrow&quot;
-      type=&quot;date&quot; default=&quot;now&quot; pattern=&quot;DDD&quot;
-      operation=&quot;+&quot; value=&quot;1&quot;/&gt;
-&lt;/propertyfile&gt;
-</pre></blockquote>
+<pre>
+&lt;propertyfile file=&quot;my.properties&quot;
+              comment=&quot;My properties&quot;&gt;
+    &lt;entry key=&quot;akey&quot; value=&quot;avalue&quot;/&gt;
+    &lt;entry key=&quot;adate&quot; type=&quot;date&quot; value=&quot;now&quot;/&gt;
+    &lt;entry key=&quot;anint&quot; type=&quot;int&quot; default=&quot;0&quot; operation=&quot;+&quot;/&gt;
+    &lt;entry key=&quot;formated.int&quot; type=&quot;int&quot; default=&quot;0013&quot; operation=&quot;+&quot; pattern=&quot;0000&quot;/&gt;
+    &lt;entry key=&quot;formated.date&quot; type=&quot;date&quot; value=&quot;now&quot; pattern=&quot;DDD HH:mm&quot;/&gt;
+&lt;/propertyfile&gt;</pre>
+<p>To produce dates relative from today:</p>
+<pre>
+&lt;propertyfile file=&quot;my.properties&quot;
+              comment=&quot;My properties&quot;&gt;
+    &lt;entry key=&quot;formated.date-1&quot;
+           type=&quot;date&quot; default=&quot;now&quot; pattern=&quot;DDD&quot;
+           operation=&quot;-&quot; value=&quot;1&quot;/&gt;
+    &lt;entry key=&quot;formated.tomorrow&quot;
+           type=&quot;date&quot; default=&quot;now&quot; pattern=&quot;DDD&quot;
+           operation=&quot;+&quot; value=&quot;1&quot;/&gt;
+&lt;/propertyfile&gt;</pre>
 
-<p>
-Concatenation of strings :</p>
-<blockquote><pre>&lt;propertyfile
-    file=&quot;my.properties&quot;
-    comment=&quot;My properties&quot;&gt;
-  &lt;entry  key=&quot;progress&quot; default=&quot;&quot; operation=&quot;+&quot; value=&quot;.&quot;/&gt;
-&lt;/propertyfile&gt;
-</pre></blockquote>
-<p>Each time called, a &quot;.&quot; will be appended to &quot;progress&quot;
-</p>
+<p>Concatenation of strings:</p>
+<pre>
+&lt;propertyfile file=&quot;my.properties&quot;
+              comment=&quot;My properties&quot;&gt;
+    &lt;entrykey=&quot;progress&quot; default=&quot;&quot; operation=&quot;+&quot; value=&quot;.&quot;/&gt;
+&lt;/propertyfile&gt;</pre>
+<p>Each time called, a <q>.</q> will be appended to <code>progress</code></p>
 
-<p>Pumps the project version to the next minor version (increase minor and set path=0):
-<blockquote><pre>&lt;target name="nextMinorVersion"&gt;
-   &lt;property
-     name="header"
-     value="##Generated file - do not modify!"/&gt;
-   &lt;propertyfile file="version.properties" comment="${header}"&gt;
-     &lt;entry key="product.build.major"   type="int"  value="3" /&gt;
-     &lt;entry key="product.build.minor"   type="int"  operation="+" /&gt;
-     &lt;entry key="product.build.patch"   type="int"  value="0" /&gt;
-     &lt;entry key="product.build.date"    type="date" value="now" /&gt;
-  &lt;/propertyfile&gt;
-&lt;/target&gt;
-</pre></blockquote>
-After running this target the version changed e.g. from 3.2.2 to 3.3.0.
-</p>
-
+<p>Pumps the project version to the next minor version (increase minor and
+set <code>patch=0</code>):</p>
+<pre>
+&lt;target name="nextMinorVersion"&gt;
+    &lt;property name="header"
+              value="##Generated file - do not modify!"/&gt;
+    &lt;propertyfile file="version.properties" comment="${header}"&gt;
+        &lt;entry key="product.build.major" type="int"  value="3"/&gt;
+        &lt;entry key="product.build.minor" type="int"  operation="+"/&gt;
+        &lt;entry key="product.build.patch" type="int"  value="0"/&gt;
+        &lt;entry key="product.build.date"  type="date" value="now"/&gt;
+    &lt;/propertyfile&gt;
+&lt;/target&gt;</pre>
+<p>After running this target the version changed e.g. from 3.2.2 to 3.3.0.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/propertyhelper.html b/manual/Tasks/propertyhelper.html
index 6c73b0b..e043972 100644
--- a/manual/Tasks/propertyhelper.html
+++ b/manual/Tasks/propertyhelper.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>PropertyHelper Task</title>
 </head>
@@ -25,49 +25,52 @@
 <body>
 
 <h2>PropertyHelper</h2>
+<p><em>Since Ant 1.8.0</em></p>
 <h3>Description</h3>
-<p>This task is provided for the purpose of allowing the user to
-<b>(a)</b> install a different PropertyHelper at runtime, or
-<b>(b)</b> (hopefully more often) install one or more PropertyHelper Delegates into the
-PropertyHelper active on the current Project. This is somewhat advanced Apache Ant usage and
-assumes a working familiarity with the modern Ant APIs. See the description of Ant's
-<a href="../properties.html#propertyHelper">Property Helper</a> for more information.
-<b>Since Ant 1.8.0</b></p>
+<p>This task is provided for the purpose of allowing the user to <strong>(a)</strong> install a
+different <code>PropertyHelper</code> at run time, or <strong>(b)</strong> (hopefully more often)
+install one or more <code class="code">PropertyHelper</code> Delegates into
+the <code class="code">PropertyHelper</code> active on the
+current <code class="code">Project</code>. This is somewhat advanced Apache Ant usage and assumes a
+working familiarity with the modern Ant APIs. See the description of
+Ant's <a href="../properties.html#propertyHelper">Property Helper</a> for more information.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
 <h4>PropertyHelper</h4>
-You may specify exactly one configured <code>org.apache.tools.ant.PropertyHelper</code> instance.
+<p>You may specify exactly one configured <code>org.apache.tools.ant.PropertyHelper</code>
+instance.</p>
 
 <h4>PropertyHelper.Delegate</h4>
-You may specify, either in conjunction with a new <code>PropertyHelper</code> or not, one or
-more configured implementations of the <code>org.apache.tools.ant.PropertyHelper.Delegate</code>
-interface. A deeper understanding of the API is required here, however, as <code>Delegate</code>
-is a marker interface only: the nested arguments must implement a <code>Delegate</code>
-subinterface in order to do anything meaningful.
+<p>You may specify, either in conjunction with a new <code class="code">PropertyHelper</code> or
+not, one or more configured implementations of
+the <code class="code">org.apache.tools.ant.PropertyHelper.Delegate</code> interface. A deeper
+understanding of the API is required here, however, as <code class="code">Delegate</code> is a
+marker interface only: the nested arguments must implement a <code class="code">Delegate</code>
+subinterface in order to do anything meaningful.</p>
 
 <h4>delegate</h4>
-<p>A generic &lt;delegate&gt; element which can use project references
-is also provided:</p>
+<p>A generic <code>&lt;delegate&gt;</code> element which can use project references is also
+provided:</p>
 
 <h5>Parameters</h5>
-<table border="1" cellpadding="2" cellspacing="0"> 
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">The <i>id</i> of a <code>PropertyHelper.Delegate</code> to install.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>refid</td>
+    <td>The <var>id</var> of a <code>PropertyHelper.Delegate</code> to install.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
 
-<p>Install a completely different PropertyHelper implementation
-  (assuming <code>MyPropertyHelper extends PropertyHelper</code>):</p>
+<p>Install a completely different <code class="code">PropertyHelper</code> implementation
+(assuming <code class="code">MyPropertyHelper extends PropertyHelper</code>):</p>
 
 <pre>
 &lt;componentdef classname="org.example.MyPropertyHelper"
@@ -77,12 +80,11 @@
 &lt;/propertyhelper>
 </pre>
 
-<p>Add a new PropertyEvaluator delegate
-  (assuming <code>MyPropertyEvaluator implements
-  PropertyHelper.PropertyEvaluator</code>).  Note that PropertyHelper
-  uses the configured delegates in LIFO order.  I.e. the delegate
-  added by this task will be consulted before any previously defined
-  delegate and in particular before the built-in ones.</p>
+<p>Add a new <code class="code">PropertyEvaluator</code> delegate
+(assuming <code class="code">MyPropertyEvaluator implements
+PropertyHelper.PropertyEvaluator</code>).  Note that <code class="code">PropertyHelper</code> uses
+the configured delegates in LIFO order.  I.e. the delegate added by this task will be consulted
+before any previously defined delegate and in particular before the built-in ones.</p>
 
 <pre>
 &lt;componentdef classname="org.example.MyPropertyEvaluator"
@@ -92,7 +94,8 @@
 &lt;/propertyhelper>
 </pre>
 
-<p>Add a new PropertyEvaluator delegate using the refid syntax:</p>
+<p>Add a new <code class="code">PropertyEvaluator</code> delegate using the <var>refid</var>
+syntax:</p>
 
 <pre>
 &lt;typedef classname="org.example.MyPropertyEvaluator"
@@ -105,4 +108,3 @@
 
 </body>
 </html>
-
diff --git a/manual/Tasks/pvcstask.html b/manual/Tasks/pvcstask.html
index a95b32e..275d536 100644
--- a/manual/Tasks/pvcstask.html
+++ b/manual/Tasks/pvcstask.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,234 +15,185 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
+<html lang="en">
 <head>
-   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <meta http-equiv="Content-Language" content="en-us">
-   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>PVCS task</title>
 </head>
 <body>
 
-<h1>
-Apache Ant Pvcs Task User Manual</h1>
+<h1>Apache Ant Pvcs Task User Manual</h1>
 
-<p><b>Note:</b>
-Before using this task, the user running Ant must have access to the
-commands of PVCS (get and pcli) and must have access to the
-repository. Note that the way to specify the repository is platform
-dependent so use property to specify location of repository.
-</p>
-
-by
-<br><!-- Names are in alphabetical order, on last name -->
+<p><strong>Note</strong>: Before using this task, the user running Ant must have access to the
+commands of PVCS (<kbd>get</kbd> and <kbd>pcli</kbd>) and must have access to the
+repository. Note that the way to specify the repository is platform dependent so use property to
+specify location of repository.</p>
+<p>by</p>
+<!-- Names are in alphabetical order, on last name -->
 <ul>
   <li>Thomas Christensen (<a href="mailto:tchristensen@nordija.com">tchristensen@nordija.com</a>)</li>
   <li>Don Jeffery (<a href="mailto:donj@apogeenet.com">donj@apogeenet.com</a>)</li>
   <li>Jon Dickinson (<a href="mailto:dickinson.j@ucles.org.uk">dickinson.j@ucles.org.uk</a>)</li>
 </ul>
-Version 1.1 - 2001/06/27<br>
-<p>Problems with UNC pathnames and the use of () in paths are fixed and an updateonly
-  argument introduced.</p>
-Version 1.0 - 2001/01/31<br>
+<p>Version 1.1&mdash;2001/06/27</p>
+<p>Problems with UNC pathnames and the use of <q>()</q> in paths are fixed and
+an <var>updateonly</var> argument introduced.</p>
+<p>Version 1.0&mdash;2001/01/31</p>
 <p>Initial release.</p>
-<hr>
-<h2>
-Table of Contents</h2>
+
+<hr/>
+
+<h2>Table of Contents</h2>
 <ul>
   <li><a href="#introduction">Introduction</a></li>
   <li><a href="#pvcs">Pvcs Task</a></li>
 </ul>
-<hr>
 
-<h2><a NAME="introduction">Introduction</a></h2>
-The pvcs task allows the user of Ant to extract the latest edition
-of the source code from a PVCS repository. PVCS is a version control system
-developed by <a href="http://www.merant.com/products/pvcs">Merant</a>.
-<br>
-This version has been tested against PVCS version 6.5 and 6.6 under Windows and Solaris.
+<hr/>
 
-<hr>
-<h2><a NAME="pvcs">Pvcs Task</a></h2>
+<h2 id="introduction">Introduction</h2>
+<p>The <code>pvcs</code> task allows the user of Ant to extract the latest edition of the source
+code from a <a href="https://en.wikipedia.org/wiki/PVCS" target="_top">PVCS</a> (Polytron Version
+Control System) repository. It is currently owned
+by <a href="https://www.microfocus.com/products/pvcs/" target="_top">MicroFocus</a>.</p>
+<p>This version has been tested against PVCS version 6.5 and 6.6 under Windows and Solaris.</p>
+
+<hr/>
+
+<h2 id="pvcs">Pvcs Task</h2>
 <h3>Description</h3>
-The pvcs task is set to point at a PVCS repository and optionally a project
-within that repository, and can from that specification get the latest
-version of the files contained by the repository.
-<h3>
-Parameters</h3>
-
-<table BORDER CELLSPACING=0 CELLPADDING=2 >
-<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 WIDTH="12%">repository</td>
-
-<td VALIGN=TOP WIDTH="78%">The location of the repository (see your PVCS
-manuals)</td>
-
-<td VALIGN=TOP WIDTH="10%">Yes</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">pvcsproject</td>
-
-<td VALIGN=TOP WIDTH="78%">The project within the PVCS repository to extract
-files from (&quot;/&quot; is root project and that is default if this attribute isn't
-specified)</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">label</td>
-
-<td VALIGN=TOP WIDTH="78%">Only files marked with this label are extracted.</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">promotiongroup</td>
-
-<td VALIGN=TOP WIDTH="78%">Only files within this promotion group are extracted. Using
-both the <i>label</i> and the <i>promotiongroup</i> tag will cause the files in the
-promotion group and with that label to be extracted.
-</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">config</td>
-
-<td VALIGN=TOP WIDTH="78%">path of a non default .cfg file.
-Can be given absolute or relative to Ant's base directory.
-</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">force</td>
-
-<td VALIGN=TOP WIDTH="78%">If set to <i>yes</i> all files that exists and are writable are overwritten. Default <i>no</i> causes the files that are writable to be ignored. This stops the PVCS command <i>get</i> to stop asking questions!</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">workspace</td>
-
-<td VALIGN=TOP WIDTH="78%">By specifying a workspace, the files are extracted to that location. A PVCS workspace is a
-name for a location of the workfiles and isn't as such the location itself. You define the location for a workspace
-using the PVCS GUI clients. If this isn't specified the default workspace for the current user is used.</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-
-<tr>
-<td VALIGN=TOP WIDTH="12%">pvcsbin</td>
-
-<td VALIGN=TOP WIDTH="78%">On some systems the PVCS executables <i>pcli</i>
-and <i>get</i> are not found in the PATH. In such cases this attribute
-should be set to the bin directory of the PVCS installation containing
-the executables mentioned before. If this attribute isn't specified the
-tag expects the executables to be found using the PATH environment variable.</td>
-
-<td VALIGN=TOP WIDTH="10%">No</td>
-</tr>
-    <tr>
-      <td VALIGN=TOP WIDTH="12%">ignorereturncode</td>
-      <td VALIGN=TOP WIDTH="78%">If set to <i>true</i> the return value from executing
-        the pvcs commands are ignored.</td>
-      <td VALIGN=TOP WIDTH="10%">No</td>
-    </tr>
-    <tr>
-      <td VALIGN=TOP WIDTH="12%">updateonly</td>
-      <td VALIGN=TOP WIDTH="78%">If set to <i>true</i> files are gotten only if
-        newer than existing local files.</td>
-      <td VALIGN=TOP WIDTH="10%">No</td>
-    </tr>
-    <tr>
-      <td valign="TOP">filenameformat</td>
-      <td valign="TOP">The format of your folder names in a
-          format suitable for <code>java.text.MessageFormat</code>.
-          Defaults to <code>{0}-arc({1})</code>.  Repositories where
-          the archive extension is not  <code>-arc</code> should set
-          this.</td>
-      <td valign="TOP">No</td>
-    </tr>
-    <tr>
-      <td valign="TOP">linestart</td>
-        <td valign="TOP">Used to parse the output of the pcli
-          command. It defaults to <code>&quot;P:</code>.  The parser already
-          knows about / and \\, this property is useful in cases where the
-          repository is accessed on a Windows platform via a drive letter
-          mapping.</td>
-      <td valign="TOP">No</td>
-    </tr>
-    <tr>
-      <td valign="TOP">revision</td>
-      <td valign="TOP">Retrieve the specified revision.</td>
-      <td valign="TOP">No</td>
-    </tr>
-    <tr>
-      <td valign="TOP">userid</td>
-      <td valign="TOP">Use the specified userid.</td>
-      <td valign="TOP">No</td>
-    </tr>
-</table>
-<h3><a name="nested">Nested Elements</a></h3>
-
-<h3>pvcsproject element</h3>
-<p><code>pvcs</code> supports a nested
-<code>&lt;pvcsproject&gt;</code> element, that represents a project
-within the PVCS repository to extract files from.  By nesting multiple
-<code>&lt;pvcsproject&gt;</code> elements under the
-<code>&lt;pvcs&gt;</code> task, multiple projects can be
-specified.</p>
-
+<p>The <code>pvcs</code> task is set to point at a PVCS repository and optionally a project within
+that repository, and can from that specification get the latest version of the files contained by
+the repository.</p>
 <h3>Parameters</h3>
 
-<table BORDER CELLSPACING=0 CELLPADDING=2 >
-<tr>
-<td VALIGN=TOP WIDTH="12%"><b>Attribute</b></td>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>repository</td>
+    <td>The location of the repository (see your PVCS manuals).</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>pvcsproject</td>
+    <td>The project within the PVCS repository to extract files from.</td>
+    <td>No; defaults to root project, <q>/</q></td>
+  </tr>
+  <tr>
+    <td>label</td>
+    <td>Only files marked with this label are extracted.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>promotiongroup</td>
+    <td>Only files within this promotion group are extracted. Using both the <var>label</var> and
+      the <var>promotiongroup</var> tag will cause the files in the promotion group and with that
+      label to be extracted.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>config</td>
+    <td>path of a non default <samp>.cfg</samp> file.  Can be given absolute or relative to
+      project's base directory.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>force</td>
+    <td>If set to <q>yes</q> all files that exists and are writable are
+      overwritten. Default <q>no</q> causes the files that are writable to be ignored. This stops
+      the PVCS command <code>get</code> to stop asking questions!</td>
+    <td>No; default is <q>no</q></td>
+  </tr>
+  <tr>
+    <td>workspace</td>
+    <td>By specifying a <var>workspace</var>, the files are extracted to that location. A PVCS
+      workspace is a name for a location of the workfiles and isn't as such the location itself. You
+      define the location for a workspace using the PVCS GUI clients.</td>
+    <td>No; defaults to default workspace for the current user</td>
+  </tr>
+  <tr>
+    <td>pvcsbin</td>
+    <td>On some systems the PVCS executables <kbd>pcli</kbd> and <kbd>get</kbd> are not found in
+      the <code>PATH</code>. In such cases this attribute should be set to the <code>bin</code>
+      directory of the PVCS installation containing the executables mentioned before. If this
+      attribute isn't specified the tag expects the executables to be found using
+      the <code>PATH</code> environment variable.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>ignorereturncode</td>
+    <td>If set to <q>true</q> the return value from executing the PVCS commands are ignored.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>updateonly</td>
+    <td>If set to <q>true</q> files are gotten only if newer than existing local files.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>filenameformat</td>
+    <td>The format of your folder names in a format suitable
+      for <code>java.text.MessageFormat</code>.  Repositories where the archive extension is
+      not <samp>-arc</samp> should set this.</td>
+    <td>No; defaults to <q>{0}-arc({1})</q></td>
+  </tr>
+  <tr>
+    <td>linestart</td>
+    <td>Used to parse the output of the <code>pcli</code> command.  The parser already knows
+      about <q>/</q> and <q>\\</q>, this property is useful in cases where the repository is
+      accessed on a Windows platform via a drive letter mapping.</td>
+    <td>No; defaults to <code>&quot;P:</code></td>
+  </tr>
+  <tr>
+    <td>revision</td>
+    <td>Retrieve the specified revision.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>userid</td>
+    <td>Use the specified userid.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h3 id="nested">Parameters specified as nested elements</h3>
 
-<td VALIGN=TOP WIDTH="78%"><b>Description</b></td>
+<h4>pvcsproject element</h4>
+<p>The task supports a nested <code>&lt;pvcsproject&gt;</code> element, that represents a
+project within the PVCS repository to extract files from.  By nesting
+multiple <code>&lt;pvcsproject&gt;</code> elements under the <code>&lt;pvcs&gt;</code> task,
+multiple projects can be specified.</p>
 
-<td VALIGN=TOP WIDTH="10%"><b>Required</b></td>
-</tr>
+<h5>Parameters</h5>
 
-<tr>
-<td VALIGN=TOP WIDTH="12%">name</td>
-
-<td VALIGN=TOP WIDTH="78%">The name of the pvcs project</td>
-
-<td VALIGN=TOP WIDTH="10%">Yes</td>
-</tr>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>The name of the PVCS project</td>
+    <td>Yes</td>
+  </tr>
 </table>
 
 <h3>Examples</h3>
-The following set-up extracts the latest version of the files in the pvcs repository.
+<p>The following set-up extracts the latest version of the files in the pvcs repository.</p>
 <pre>
-  &lt;!-- =================================================================== --&gt;
-  &lt;!-- Get the latest version                                              --&gt;
-  &lt;!-- =================================================================== --&gt;
-  &lt;target name=&quot;getlatest&quot;&gt;
-    &lt;pvcs repository=&quot;/mnt/pvcs&quot; pvcsproject=&quot;/myprj&quot;/&gt;
-  &lt;/target&gt;</ul>
-</pre>
-<p>Now run:</p>
-<code>ant getlatest</code>
+&lt;!-- =================================================================== --&gt;
+&lt;!-- Get the latest version                                              --&gt;
+&lt;!-- =================================================================== --&gt;
+&lt;target name=&quot;getlatest&quot;&gt;
+  &lt;pvcs repository=&quot;/mnt/pvcs&quot; pvcsproject=&quot;/myprj&quot;/&gt;
+&lt;/target&gt;</pre>
+<p>Now run: <kbd>ant getlatest</kbd></p>
 <p>This will cause the following output to appear:</p>
-<pre>
+<pre class="output">
   getlatest:
   [pvcs] PVCS Version Manager (VMGUI) v6.6.10 (Build 870) for Windows NT/80x86
   [pvcs] Copyright 1985-2000 MERANT. All rights reserved.
@@ -256,23 +208,21 @@
 
   Total time: 19 seconds</pre>
 
-This next example extracts the latest version of the files in the pvcs
-repository from two projects using nested <code>&lt;pvcsproject&gt;</code> elements.
+<p>This next example extracts the latest version of the files in the pvcs repository from two
+projects using nested <code>&lt;pvcsproject&gt;</code> elements.</p>
 <pre>
-  &lt;!-- ===================================================================--&gt;
-  &lt;!-- Get latest from myprj and myprj2                                   --&gt;
-  &lt;!-- ===================================================================--&gt;
-  &lt;target name=&quot;getlatest2&quot;&gt;
-    &lt;pvcs repository=&quot;/mnt/pvcs&quot;&gt;
-      &lt;pvcsproject name=&quot;/myprj&quot;/&gt;
-      &lt;pvcsproject name=&quot;/myprj2&quot;/&gt;
-    &lt;/pvcs&gt;
-  &lt;/target&gt;</ul>
-</pre>
-<p>Now run:</p>
-<code>ant getlatest2</code>
+&lt;!-- ===================================================================--&gt;
+&lt;!-- Get latest from myprj and myprj2                                   --&gt;
+&lt;!-- ===================================================================--&gt;
+&lt;target name=&quot;getlatest2&quot;&gt;
+  &lt;pvcs repository=&quot;/mnt/pvcs&quot;&gt;
+    &lt;pvcsproject name=&quot;/myprj&quot;/&gt;
+    &lt;pvcsproject name=&quot;/myprj2&quot;/&gt;
+  &lt;/pvcs&gt;
+&lt;/target&gt;</pre>
+<p>Now run: <kbd>ant getlatest2</kbd></p>
 <p>This will cause the following output to appear:</p>
-<pre>
+<pre class="output">
   getlatest2:
   [pvcs] PVCS Version Manager (VMGUI) v6.6.10 (Build 870) for Windows NT/80x86
   [pvcs] Copyright 1985-2000 MERANT.  All rights reserved.
@@ -289,7 +239,5 @@
 
   Total time: 22 seconds</pre>
 
-<hr WIDTH="100%">
-<p>PVCS is a registered trademark of MERANT.</p>
 </body>
 </html>
diff --git a/manual/Tasks/recorder.html b/manual/Tasks/recorder.html
index dfbfc0d..17f59ae 100644
--- a/manual/Tasks/recorder.html
+++ b/manual/Tasks/recorder.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,83 +15,75 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Recorder Task</title>
 </head>
 
 <body>
 
-<h2><a name="log">Record</a></h2>
+<h2 id="log">Record</h2>
 <h3>Description</h3>
-<p>A recorder is a listener to the current build process that records the
-output to a file.</p>
+<p>A recorder is a listener to the current build process that records the output to a file.</p>
 
-<p>Several recorders can exist at the same time.  Each recorder is
-associated with a file.  The filename is used as a unique identifier for
-the recorders.  The first call to the recorder task with an unused filename
-will create a recorder (using the parameters provided) and add it to the
-listeners of the build.  All subsequent calls to the recorder task using
-this filename will modify that recorders state (recording or not) or other
-properties (like logging level).</p>
+<p>Several recorders can exist at the same time.  Each recorder is associated with a file.  The
+filename is used as a unique identifier for the recorders.  The first call to
+the <code>record</code> task with an unused filename will create a recorder (using the parameters
+provided) and add it to the listeners of the build.  All subsequent calls to the <code>record</code>
+task using this filename will modify that recorder's state (recording or not) or other properties
+(like logging level).</p>
 
-<p>Some technical issues: the file's print stream is flushed for &quot;finished&quot;
-events (buildFinished, targetFinished and taskFinished), and is closed on
-a buildFinished event.</p>
+<p>Some technical issues: the file's print stream is flushed for <q>finished</q> events
+(<q>buildFinished</q>, <q>targetFinished</q> and <q>taskFinished</q>), and is closed on
+a <q>buildFinished</q> event.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the file this logger is associated with.</td>
-    <td align="center" valign="middle">yes</td>
+    <td>name</td>
+    <td>The name of the file this logger is associated with.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">action</td>
-    <td valign="top">This tells the logger what to do: should it start
-    recording or stop?  The first time that the recorder task is called for
-    this logfile, and if this attribute is not provided, then the default
-    for this attribute is &quot;start&quot;.  If this attribute is not provided on
-    subsequent calls, then the state remains as previous.
-    [Values = {start|stop}, Default = no state change]</td>
-    <td align="center" valign="middle">no</td>
+    <td>action</td>
+    <td>This tells the logger what to do: should it start recording or stop?  The first time that
+      the recorder task is called for this logfile, and if this attribute is not provided, then the
+      default for this attribute is <q>start</q>.  If this attribute is not provided on subsequent
+      calls, then the state remains as previous.</td>
+    <td>No [values = <q>start|stop</q>, default = no state change]</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Should the recorder append to a file, or create a new
-    one? This is only applicable the first time this task is called for
-    this file.  [Values = {yes|no}, Default=no]</td>
-    <td align="center" valign="middle">no</td>
+    <td>append</td>
+    <td>Should the recorder append to a file, or create a new one? This is only applicable the first
+      time this task is called for this file.</td>
+    <td>No [values = <q>start|stop</q>, default = no state change]</td>
   </tr>
   <tr>
-    <td valign="top">emacsmode</td>
-    <td valign="top">Removes <code>[task]</code> banners like Apache Ant's
-    <code>-emacs</code> command line switch if set to
-    <em>true</em>.</td>
-    <td align="center" valign="middle">no, default is <em>false</em></td>
+    <td>emacsmode</td>
+    <td>Removes <code>[task]</code> banners like Apache Ant's <kbd>-emacs</kbd> command line
+      switch if set to <q>true</q>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">loglevel</td>
-    <td valign="top">At what logging level should this recorder instance
-    record to?  This is not a once only parameter (like <code>append</code>
-    is) -- you can increase or decrease the logging level as the build process
-    continues.  [Values= {error|warn|info|verbose|debug}, Default = no change]
+    <td>loglevel</td>
+    <td>At what logging level should this recorder instance record to?  This is not a once only
+      parameter (like <var>append</var> is)&mdash;you can increase or decrease the logging level as
+      the build process continues.
     </td>
-    <td align="center" valign="middle">no</td>
+    <td>No [values = <q>error|warn|info|verbose|debug</q>, default = no change]</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<p>The following build.xml snippet is an example of how to use the recorder
-to record just the <code>&lt;javac&gt;</code> task:</p>
+<p>The following <samp>build.xml</samp> snippet is an example of how to use the recorder to record
+just the <code>&lt;javac&gt;</code> task:</p>
 <pre>
     ...
     &lt;compile &gt;
@@ -101,10 +94,9 @@
     ...
 </pre>
 
-<p>The following two calls to <code>&lt;record&gt;</code> set up two
-recorders: one to file &quot;records-simple.log&quot; at logging level <code>info</code>
-(the default) and one to file &quot;ISO.log&quot; using logging level of
-<code>verbose</code>.</p>
+<p>The following two calls to <code>&lt;record&gt;</code> set up two recorders: one to
+file <samp>records-simple.log</samp> at logging level <q>info</q> (the default) and one to
+file <samp>ISO.log</samp> using logging level of <q>verbose</q>.</p>
 <pre>
     ...
     &lt;record name=&quot;records-simple.log&quot;/&gt;
@@ -113,60 +105,49 @@
 </pre>
 
 <h3>Notes</h3>
-<p>There is some functionality that I would like to be able to add in the
-future.  They include things like the following:</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>There is some functionality that I would like to be able to add in the future.  They include
+things like the following:</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">listener</td>
-    <td valign="top">A classname of a build listener to use from this point
-    on instead of the default listener.</td>
-    <td align="center" valign="middle">no</td>
+    <td>listener</td>
+    <td>A classname of a build listener to use from this point on instead of the default
+      listener.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includetarget</td>
-    <td valign="top" rowspan=2>A comma-separated list of targets to automatically
-    record.  If this value is &quot;all&quot;, then all targets are recorded.
-    [Default = all]</td>
-    <td align="center" valign="middle">no</td>
+    <td>includetarget</td>
+    <td rowspan="2">A comma-separated list of targets to automatically record.  If this value
+      is <q>all</q>, then all targets are recorded.</td>
+    <td>No; default is <q>all</q></td>
   </tr>
   <tr>
-    <td valign="top">excludetarget</td>
-    <td align="center" valign="middle">no</td>
+    <td>excludetarget</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includetask</td>
-    <td valign="top" rowspan=2>A comma-separated list of task to automatically
-    record or not.  This could be difficult as it could conflict with the
-    <code>includetarget/excludetarget</code>.  (e.g.:
-    <code>includetarget=&quot;compile&quot; excludetask=&quot;javac&quot;</code>, what should
-    happen?)</td>
-    <td align="center" valign="middle">no</td>
+    <td>includetask</td>
+    <td rowspan="2">A comma-separated list of tasks to automatically record or not.  This could be
+      difficult as it may conflict with the <code>includetarget/excludetarget</code>.
+      (e.g.: <code>includetarget=&quot;compile&quot; excludetask=&quot;javac&quot;</code>, what
+      should happen?)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludetask</td>
-    <td align="center" valign="middle">no</td>
+    <td>excludetask</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">action</td>
-    <td valign="top">add greater flexibility to the action attribute.  Things
-    like <code>close</code> to close the print stream.</td>
-    <td align="center" valign="top">no</td>
-  </tr>
-  <tr>
-    <td valign="top"></td>
-    <td valign="top"></td>
-    <td align="center" valign="top"></td>
+    <td>action</td>
+    <td>add greater flexibility to the <var>action</var> attribute.  Things like <q>close</q> to
+      close the print stream.</td>
+    <td>No</td>
   </tr>
 </table>
 
-
-
-
-
 </body>
 </html>
diff --git a/manual/Tasks/rename.html b/manual/Tasks/rename.html
index 330fbe3..e9b3e1f 100644
--- a/manual/Tasks/rename.html
+++ b/manual/Tasks/rename.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,51 +15,50 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Rename Task</title>
 </head>
 
 <body>
 
-<h2><a name="rename">Rename</a></h2>
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated.  Use the Move task instead.</i></p>
+<h2 id="rename">Rename</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>.  Use the <code>Move</code> task instead.</em></p>
 <h3>Description</h3>
 <p>Renames a given file.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">file to rename.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>src</td>
+    <td>file to rename.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">new name of the file.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dest</td>
+    <td>new name of the file.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">replace</td>
-    <td valign="top">Enable replacing of existing file (default: on).</td>
-    <td valign="top" align="center">No</td>
+    <td>replace</td>
+    <td>Enable replacing of existing file.</td>
+    <td>No; default is <q>on</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;rename src=&quot;foo.jar&quot; dest=&quot;${name}-${version}.jar&quot;/&gt;</pre> 
-<p>Renames the file <code>foo.jar</code> to <code>${name}-${version}.jar</code> (assuming <code>name</code>
- and <code>version</code> being predefined properties). If a file named <code>${name}-${version}.jar</code>
- already exists, it will be removed prior to renaming <code>foo.jar</code>.</p>
 
+<p>Rename the file <samp>foo.jar</samp> to <samp>${name}-${version}.jar</samp>
+(assuming <code>name</code> and <code>version</code> being predefined properties). If a file
+named <samp>${name}-${version}.jar</samp> already exists, it will be removed prior to
+renaming <samp>foo.jar</samp>.</p>
+<pre>&lt;rename src=&quot;foo.jar&quot; dest=&quot;${name}-${version}.jar&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/renameextensions.html b/manual/Tasks/renameextensions.html
index ed3bfbb..c864ac0 100644
--- a/manual/Tasks/renameextensions.html
+++ b/manual/Tasks/renameextensions.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,110 +15,91 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>RenameExtensions Task</title>
 </head>
 
 <body>
 
-<h2><a name="renameexts">RenameExtensions</a></h2>
-<h3><i>Deprecated</i></h3>
-<p><i>This task has been deprecated.  Use the <a href="../Tasks/move.html">move</a>
-task with a <a href="../Types/mapper.html#glob-mapper">glob mapper</a> instead.</i></p>
+<h2 id="renameexts">RenameExtensions</h2>
+<h3><em><u>Deprecated</u></em></h3>
+<p><em>This task has been <u>deprecated</u>.  Use the <a href="../Tasks/move.html">move</a> task
+with a <a href="../Types/mapper.html#glob-mapper">glob mapper</a> instead.</em></p>
 <h3>Description</h3>
-<p>Renames files in the <code>srcDir</code> directory ending with the
-<code>fromExtension</code> string so that they end with the
-<code>toExtension</code> string. Files are only replaced if
-<code>replace</code> is true
-</p>
-<p>See the section on
-<a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
-inclusion/exclusion of files works, and how to write patterns.
-This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>srcDir</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
+<p>Renames files in the <var>srcDir</var> directory ending with the <var>fromExtension</var> string
+so that they end with the <var>toExtension</var> string. Files are only replaced
+if <var>replace</var> is <q>true</q>.</p>
+<p>See the section on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on
+how the inclusion/exclusion of files works, and how to write patterns.  This task forms an
+implicit <a href="../Types/fileset.html">FileSet</a> and supports most attributes
+of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>srcDir</var>) as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when
-      omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when
-      omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">fromExtension</td>
-    <td valign="top">The string that files must end in to be renamed</td>
-    <td valign="top" align="center">Yes</td>
+    <td>fromExtension</td>
+    <td>The string that files must end in to be renamed</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">replace</td>
-    <td valign="top">Whether the file being renamed to should be
-      replaced if it already exists</td>
-    <td valign="top" align="center">No</td>
+    <td>replace</td>
+    <td>Whether the file being renamed to should be replaced if it already exists</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">srcDir</td>
-    <td valign="top">The starting directory for files to search in</td>
-    <td valign="top" align="center">Yes</td>
+    <td>srcDir</td>
+    <td>The starting directory for files to search in</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">toExtension</td>
-    <td valign="top">The string that renamed files will end with on
-      completion</td>
-    <td valign="top" align="center">Yes</td>
+    <td>toExtension</td>
+    <td>The string that renamed files will end with on completion</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-  <p><code>&lt;renameext srcDir=&quot;/source/project1&quot;
-              includes=&quot;**&quot;
-              excludes=&quot;**/samples/*&quot;
-              fromExtension=&quot;.java.keep&quot;
-              toExtension=&quot;.java&quot;
-              replace=&quot;true&quot;/&gt;
-</code>
-  </p>
-</blockquote>
 
-
+<pre>
+&lt;renameext srcDir=&quot;/source/project1&quot;
+           includes=&quot;**&quot;
+           excludes=&quot;**/samples/*&quot;
+           fromExtension=&quot;.java.keep&quot;
+           toExtension=&quot;.java&quot;
+           replace=&quot;true&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/replace.html b/manual/Tasks/replace.html
index 36204d0..2d65a20 100644
--- a/manual/Tasks/replace.html
+++ b/manual/Tasks/replace.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,229 +15,214 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Replace Task</title>
 </head>
 
 <body>
 
-<h2><a name="replace">Replace</a></h2>
+<h2 id="replace">Replace</h2>
 <h3>Description</h3>
-<p>Replace is a directory based task for replacing the occurrence of a given string with another string 
-in selected file.</p>
-<p>If you want to replace a text that crosses line boundaries, you
-must use a nested <code>&lt;replacetoken&gt;</code> element.</p>
+<p><code>Replace</code> is a directory based task for replacing the occurrence of a given string
+with another string in selected file.</p>
+<p>If you want to replace a text that crosses line boundaries, you must use a
+nested <code>&lt;replacetoken&gt;</code> element.</p>
 
-<p>The output file is only written if it differs from the existing
-file.  This prevents spurious rebuilds based on unchanged files which
-have been regenerated by this task.</p> 
+<p>The output file is only written if it differs from the existing file.  This prevents spurious
+rebuilds based on unchanged files which have been regenerated by this task.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">file for which the token should be replaced.</td>
-    <td align="center" rowspan="2">Exactly one of the two.</td>
+    <td>file</td>
+    <td>file for which the token should be replaced.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The base directory to use when replacing a token in 
-      multiple files.</td>
+    <td>dir</td>
+    <td class="left">The base directory to use when replacing a token in multiple files.</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding of the files upon which replace operates.</td>
-    <td align="center">No - defaults to default JVM encoding</td>
+    <td>encoding</td>
+    <td>The encoding of the files upon which replace operates.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">token</td>
-    <td valign="top">the token which must be replaced.</td>
-    <td valign="top" align="center">Yes, unless a nested
-    <code>replacetoken</code> element or the replacefilterfile
-    attribute is used.</td>
+    <td>token</td>
+    <td>the token which must be replaced.</td>
+    <td>Yes, unless a nested <code>replacetoken</code> element or the <var>replacefilterfile</var>
+      attribute is used.</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">the new value for the token. When omitted, an empty string
-      (&quot;&quot;) is used.</td>
-    <td valign="top" align="center">No</td>
+    <td>value</td>
+    <td>the new value for the token.</td>
+    <td>No; defaults to empty string (<q></q>)</td>
   </tr>
   <tr>
-    <td valign="top">summary</td>
-    <td valign="top">Indicates whether a summary of the replace operation 
-                     should be produced, detailing how many token occurrences 
-                     and files were processed
-                     </td>
-    <td valign="top" align="center">No, by default no summary is produced</td>
+    <td>summary</td>
+    <td>Indicates whether a summary of the replace operation should be produced, detailing how many
+      token occurrences and files were processed</td>
+    <td>No; defaults to no summary</td>
   </tr>
   <tr>
-    <td valign="top">propertyFile</td>
-    <td valign="top">valid property file from which properties specified using nested <code>&lt;replacefilter&gt;</code> elements are drawn.</td>
-    <td valign="top" align="center">Yes only if <i>property</i> attribute of <code>&lt;replacefilter&gt;</code> is used.</td>
+    <td>propertyFile</td>
+    <td>valid property file from which properties specified using
+      nested <code>&lt;replacefilter&gt;</code> elements are drawn.</td>
+    <td>Yes, only if <var>property</var> attribute of <code>&lt;replacefilter&gt;</code> is
+      used.</td>
   </tr>
   <tr>
-    <td valign="top">replacefilterfile</td>
-    <td valign="top">valid property file.  Each property will be
-    treated as a replacefilter where <code>token</code> is the name of
-    the property and <code>value</code> is the properties value.
-    <td valign="top" align="center">No.</td>
+    <td>replacefilterfile</td>
+    <td>valid property file.  Each property will be treated as a <code>replacefilter</code>
+      where <var>token</var> is the name of the property and <var>value</var> is the property's
+      value.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">preserveLastModified</td>
-    <td valign="top">Keep the file timestamp(s) even if the file(s)
-      is(are) modified.  <em>since Apache Ant 1.8.0.</em></td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>preserveLastModified</td>
+    <td>Keep the file timestamp(s) even if the file(s) is(are) modified.  <em>since Apache Ant
+      1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failOnNoReplacements</td>
-    <td valign="top">Whether to fail the build if the task didn't do
-      anything.  <em>since Ant 1.8.0.</em></td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>failOnNoReplacements</td>
+    <td>Whether to fail the build if the task didn't do anything.  <em>since Ant 1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>  &lt;replace file=&quot;${src}/index.html&quot; token=&quot;@@@&quot; value=&quot;wombat&quot;/&gt;</pre>
-<p>replaces occurrences of the string &quot;@@@&quot; with the string
-&quot;wombat&quot;, in the file <code>${src}/index.html</code>.</p>
+<pre>&lt;replace file=&quot;${src}/index.html&quot; token=&quot;@@@&quot; value=&quot;wombat&quot;/&gt;</pre>
+<p>replaces occurrences of the string <q>@@@</q> with the string <q>wombat</q>, in the
+file <samp>${src}/index.html</samp>.</p>
 <h3>Parameters specified as nested elements</h3>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code> as well as the
-nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
-<p>Since Ant 1.8.0 this task supports any filesystem
-  based <a href="../Types/resources.html#collection">resource
-    collections</a> as nested elements.</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+<p><em>Since Ant 1.8.0</em>, this task supports any filesystem
+based <a href="../Types/resources.html#collection">resource collections</a> as nested elements.</p>
 <h4>replacetoken and replacevalue</h4>
-<p>If either the text you want to replace or the replacement text
-cross line boundaries, you can use nested elements to specify
-them.</p>
+<p>If either the text you want to replace or the replacement text cross line boundaries, you can use
+nested elements to specify them.</p>
 <p>The elements support attributes:</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">expandProperties</td>
-    <td valign="top">Whether to expand properties in the nested text.
-      <em>since Ant 1.8.0.</em></td>
-    <td align="center">No, defaults to true.</td>
+    <td>expandProperties</td>
+    <td>Whether to expand properties in the nested text.  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote><pre>
+<pre>
 &lt;replace dir=&quot;${src}&quot; value=&quot;wombat&quot;&gt;
   &lt;include name=&quot;**/*.html&quot;/&gt;
   &lt;replacetoken&gt;&lt;![CDATA[multi line
 token]]&gt;&lt;/replacetoken&gt;
-&lt;/replace&gt;
-</pre></blockquote>
-<p>replaces occurrences of the string &quot;multi
-line<i>\n</i>token&quot; with the string &quot;wombat&quot;, in all
-HTML files in the directory <code>${src}</code>.Where <i>\n</i> is
-the platform specific line separator.</p>
-<blockquote><pre>
+&lt;/replace&gt;</pre>
+<p>replaces occurrences of the string <q>multi line<i>\n</i>token</q> with the string <q>wombat</q>,
+in all HTML files in the directory <samp>${src}</samp>. Here, <q><i>\n</i></q> is the platform
+specific line separator.</p>
+<pre>
 &lt;replace file=&quot;${src}/index.html&quot;&gt;
   &lt;replacetoken&gt;&lt;![CDATA[two line
 token]]&gt;&lt;/replacetoken&gt;
   &lt;replacevalue&gt;&lt;![CDATA[two line
 token]]&gt;&lt;/replacevalue&gt;
-&lt;/replace&gt;
-</pre></blockquote>
+&lt;/replace&gt;</pre>
 <h4>replacefilter</h4>
-<p>In addition to allowing for multiple replacements, optional nested <code>&lt;replacefilter&gt;</code> elements allow replacement values to be extracted from a property file. The name of this file is specified using the <code>&lt;replace&gt;</code> attribute <i>propertyFile</i>.
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>In addition to allowing for multiple replacements, optional
+nested <code>&lt;replacefilter&gt;</code> elements allow replacement values to be extracted from a
+property file. The name of this file is specified using the <code>&lt;replace&gt;</code>
+attribute <var>propertyFile</var>.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">token</td>
-    <td valign="top">The string to search for.</td>
-    <td align="center" valign="top">Yes unless a nested replacetoken
+    <td>token</td>
+    <td>The string to search for.</td>
+    <td>Yes, unless a nested <code>replacetoken</code>
       is specified</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The replacement string.</td>
-    <td align="center" rowspan="2">Either may be specified, but not both. Both can be omitted, if desired.</td>
+    <td>value</td>
+    <td>The replacement string.</td>
+    <td rowspan="2">Either may be specified, but not both. Both can be omitted, if desired.</td>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">Name of the property whose value is to serve as the replacement value.</td>
+    <td>property</td>
+    <td class="left">Name of the property whose value is to serve as the replacement value.</td>
   </tr>
 </table>
-<p>Since Ant 1.8.0 token and value can be specified as nested elements
-  just like in the task itself.</p>
-<p>If neither <i>value</i> nor <i>property</i> is used, the value provided using the <code>&lt;replace&gt;</code> attribute <i>value</i> and/or the <code>&lt;replacevalue&gt;</code> element is used. If no value was specified using either of these options, the token is replaced with an empty string.
-</p>
+<p><em>Since Ant 1.8.0</em>, <var>token</var> and <var>value</var> can be specified as nested
+elements just like in the task itself.</p>
+<p>If neither <var>value</var> nor <var>property</var> is used, the value provided using
+the <code>&lt;replace&gt;</code> attribute <var>value</var> and/or
+the <code>&lt;replacevalue&gt;</code> element is used. If no value was specified using either of
+these options, the token is replaced with an empty string.</p>
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;replace 
-    file=&quot;configure.sh&quot;
-    value=&quot;defaultvalue&quot;
-    propertyFile=&quot;src/name.properties&quot;&gt;
-  &lt;replacefilter 
-    token=&quot;@token1@&quot;/&gt;
-  &lt;replacefilter 
-    token=&quot;@token2@&quot; 
-    value=&quot;value2&quot;/&gt;
-  &lt;replacefilter 
-    token=&quot;@token3@&quot; 
-    property=&quot;property.key&quot;/&gt;
+<p>In file <samp>configure.sh</samp>, replace all instances of <q>@token1@</q>
+with <q>defaultvalue</q>, all instances of <q>@token2@</q> with <q>value2</q>, and all instances
+of <q>@token3@</q> with the value of the property <code>property.key</code>, as it appears in
+property file <samp>src/name.properties</samp>.</p>
+<pre>
+&lt;replace file=&quot;configure.sh&quot;
+         value=&quot;defaultvalue&quot;
+         propertyFile=&quot;src/name.properties&quot;&gt;
+  &lt;replacefilter token=&quot;@token1@&quot;/&gt;
+  &lt;replacefilter token=&quot;@token2@&quot;
+                 value=&quot;value2&quot;/&gt;
+  &lt;replacefilter token=&quot;@token3@&quot;
+                 property=&quot;property.key&quot;/&gt;
   &lt;replacefilter&gt;
-    &lt;replacetoken&gt;@token4@&lt;/replacetoken&gt; 
+    &lt;replacetoken&gt;@token4@&lt;/replacetoken&gt;
     &lt;replacevalue&gt;value4&lt;/replacevalue&gt;
   &lt;/replacefilter&gt;
-&lt;/replace&gt;
-</pre></blockquote>
-<p>In file <code>configure.sh</code>, replace all instances of &quot;@token1@&quot; with &quot;defaultvalue&quot;, all instances of &quot;@token2@&quot; with &quot;value2&quot;, and all instances of &quot;@token3@&quot; with the value of the property &quot;property.key&quot;, as it appears in property file <code>src/name.properties</code>.</p>
-<p><b>Note:</b> It is possible to use either the <i>token</i>/<code>&lt;replacetoken&gt;</code> and <i>value</i>/<code>&lt;replacevalue&gt;</code> attributes/elements, the nested replacefilter elements, or both in the same operation.
-</p>
-
+&lt;/replace&gt;</pre>
+<p><strong>Note</strong>: It is possible to use either
+the <var>token</var>/<code>&lt;replacetoken&gt;</code>
+and <var>value</var>/<code>&lt;replacevalue&gt;</code> attributes/elements, the
+nested <code>replacefilter</code> elements, or both in the same operation.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/replaceregexp.html b/manual/Tasks/replaceregexp.html
index 7a091de..5077fbc 100644
--- a/manual/Tasks/replaceregexp.html
+++ b/manual/Tasks/replaceregexp.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,20 +15,18 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ReplaceRegExp Task</title>
 </head>
 <body>
 
-<h2><a name="replaceregexp">ReplaceRegExp</a></h2>
+<h2 id="replaceregexp">ReplaceRegExp</h2>
 <h3>Description</h3>
-<p>ReplaceRegExp is a directory based task for replacing the
-occurrence of a given regular expression with a substitution pattern
-in a selected file or set of files.</p>
+<p><code>ReplaceRegExp</code> is a directory based task for replacing the occurrence of a given
+regular expression with a substitution pattern in a selected file or set of files.</p>
 
 <p>The output file is only written if it differs from the existing
 file.  This prevents spurious rebuilds based on unchanged files which
@@ -36,65 +35,65 @@
 source file inside of the <a href="../running.html#tmpdir">temporary
 directory</a>.</p>
 
-<p>Similar to <a href="../Types/mapper.html#regexp-mapper">regexp
-type mappers</a> this task needs a supporting regular expression
-library and an implementation of
-<code>org.apache.tools.ant.util.regexp.Regexp</code>.
-See details in the documentation of the <a href="../Types/regexp.html#implementation">Regexp Type</a>. </p>
+<p>Similar to <a href="../Types/mapper.html#regexp-mapper">regexp type mappers</a> this task needs a
+supporting regular expression library and an implementation
+of <code class="code">org.apache.tools.ant.util.regexp.Regexp</code>.  See details in the
+documentation of the <a href="../Types/regexp.html#implementation">Regexp Type</a>.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">file for which the regular expression should be replaced.</td>
-    <td align="center">Yes if no nested <code>&lt;fileset&gt;</code> is used</td>
+    <td>file</td>
+    <td>file for which the regular expression should be replaced.</td>
+    <td>Yes, unless nested <code>&lt;fileset&gt;</code> is used</td>
   </tr>
   <tr>
-    <td valign="top">match</td>
-    <td valign="top">The regular expression pattern to match in the file(s)</td>
-    <td align="center">Yes, if no nested <code>&lt;regexp&gt;</code> is used</td>
+    <td>match</td>
+    <td>The regular expression pattern to match in the file(s)</td>
+    <td>Yes, unless nested <code>&lt;regexp&gt;</code> is used</td>
   </tr>
   <tr>
-    <td valign="top">replace</td>
-    <td valign="top">The substitution pattern to place in the file(s) in place
-                     of the regular expression.</td>
-    <td align="center">Yes, if no nested <code>&lt;substitution&gt;</code> is used</td>
+    <td>replace</td>
+    <td>The substitution pattern to place in the file(s) in place of the regular expression.</td>
+    <td>Yes, unless nested <code>&lt;substitution&gt;</code> is used</td>
   </tr>
   <tr>
-    <td valign="top">flags</td>
-    <td valign="top">The flags to use when matching the regular expression.  For more
-                     information, consult the Perl5 syntax<br>
-                     g : Global replacement.  Replace all occurrences found<br>
-                     i : Case Insensitive.  Do not consider case in the match<br>
-                     m : Multiline.  Treat the string as multiple lines of input, using "^" and "$" as the start or end of any line, respectively, rather than start or end of string.<br>
-                     s : Singleline.  Treat the string as a single line of input, using "." to match any character, including a newline, which normally, it would not match.<br>
+    <td>flags</td>
+    <td>The flags to use when matching the regular expression.  For more information, consult the
+      Perl 5 syntax<br/>
+      <q>g</q> : Global replacement.  Replace all occurrences found<br/>
+      <q>i</q> : Case Insensitive.  Do not consider case in the match<br/>
+      <q>m</q> : Multiline.  Treat the string as multiple lines of input, using <q>^</q>
+      and <q>$</q> as the start or end of any line, respectively, rather than start or end of
+      string.<br/>
+      <q>s</q> : Singleline.  Treat the string as a single line of input, using <q>.</q> to match
+      any character, including a newline, which normally, it would not match.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">byline</td>
-    <td valign="top">Process the file(s) one line at a time, executing the replacement
-                     on one line at a time (<i>true/false</i>).  This is useful if you
-                     want to only replace the first occurrence of a regular expression on
-                     each line, which is not easy to do when processing the file as a whole.
-                     Defaults to <i>false</i>.</td>
-    <td valign="top" align="center">No</td>
+    <td>byline</td>
+    <td>Process the file(s) one line at a time, executing the replacement on one line at a time
+      (<q>true|false</q>).  This is useful if you want to only replace the first occurrence of a
+      regular expression on each line, which is not easy to do when processing the file as a
+      whole.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding of the file. <em>since Apache Ant 1.6</em></td>
-    <td align="center">No - defaults to default JVM encoding</td>
+    <td>encoding</td>
+    <td>The encoding of the file. <em>since Apache Ant 1.6</em></td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">preserveLastModified</td>
-    <td valign="top">Keep the file timestamp(s) even if the file(s)
-      is(are) modified.  <em>since Ant 1.8.0.</em></td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>preserveLastModified</td>
+    <td>Keep the file timestamp(s) even if the file(s) is(are) modified.  <em>since Ant
+      1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
@@ -102,107 +101,79 @@
 &lt;replaceregexp file=&quot;${src}/build.properties&quot;
                match=&quot;OldProperty=(.*)&quot;
                replace=&quot;NewProperty=\1&quot;
-               byline=&quot;true&quot;
-/&gt;
-</pre>
-<p>replaces occurrences of the property name &quot;OldProperty&quot;
- with &quot;NewProperty&quot; in a properties file, preserving the existing
-value, in the file <code>${src}/build.properties</code></p>
+               byline=&quot;true&quot;/&gt;</pre>
+<p>replaces occurrences of the property name <q>OldProperty</q> with <q>NewProperty</q> in a
+properties file, preserving the existing value, in the file <samp>${src}/build.properties</samp></p>
 
 <h3>Parameters specified as nested elements</h3>
-<p>This task supports a nested <a href="../Types/fileset.html">FileSet</a>
-   element.</p>
-<p>Since Ant 1.8.0 this task supports any filesystem
-  based <a href="../Types/resources.html#collection">resource
-    collections</a> as nested elements.</p>
-<p>This task supports a nested <i><a href="../Types/regexp.html">Regexp</a></i> element to specify
-   the regular expression.  You can use this element to refer to a previously
-   defined regular expression datatype instance.</p>
-<blockquote>
-     &lt;regexp id="id" pattern="alpha(.+)beta"/&gt;<br>
-     &lt;regexp refid="id"/&gt;
-</blockquote>
-<p>This task supports a nested <i>Substitution</i> element to specify
-   the substitution pattern.  You can use this element to refer to a previously
-   defined substitution pattern datatype instance.</p>
-<blockquote>
-     &lt;substitution id="id" expression="beta\1alpha"/&gt;<br>
-     &lt;substitution refid="id"/&gt;
-</blockquote>
+<p>This task supports a nested <a href="../Types/fileset.html">FileSet</a> element.</p>
+<p><em>Since Ant 1.8.0</em>, this task supports any filesystem
+based <a href="../Types/resources.html#collection">resource collections</a> as nested elements.</p>
+<p>This task supports a nested <a href="../Types/regexp.html">Regexp</a> element to specify the
+regular expression.  You can use this element to refer to a previously defined regular expression
+datatype instance.</p>
 
+<pre>
+&lt;regexp id="id" pattern="alpha(.+)beta"/&gt;
+&lt;regexp refid="id"/&gt;</pre>
+
+<p>This task supports a nested <code>substitution</code> element to specify the substitution
+pattern.  You can use this element to refer to a previously defined substitution pattern datatype
+instance.</p>
+
+<pre>
+&lt;substitution id="id" expression="beta\1alpha"/&gt;<br/>
+&lt;substitution refid="id"/&gt;</pre>
 
 <h3>Examples</h3>
 
-<blockquote>
-  <pre>
+<p>Replace occurrences of the property name <q>OldProperty</q> with <q>NewProperty</q> in a
+properties file, preserving the existing value, in all files ending in <samp>.properties</samp> in
+the current directory:</p>
+<pre>
 &lt;replaceregexp byline=&quot;true&quot;&gt;
-  &lt;regexp pattern=&quot;OldProperty=(.*)&quot;/&gt;
-  &lt;substitution expression=&quot;NewProperty=\1&quot;/&gt;
-  &lt;fileset dir=&quot;.&quot;&gt;
-    &lt;include name=&quot;*.properties&quot;/&gt;
-  &lt;/fileset&gt;
-&lt;/replaceregexp&gt;
-</pre></blockquote>
-<p>replaces occurrences of the property name &quot;OldProperty&quot;
- with &quot;NewProperty&quot; in a properties file, preserving the existing
-value, in all files ending in <code>.properties</code> in the current directory</p>
+    &lt;regexp pattern=&quot;OldProperty=(.*)&quot;/&gt;
+    &lt;substitution expression=&quot;NewProperty=\1&quot;/&gt;
+    &lt;fileset dir=&quot;.&quot;&gt;
+        &lt;include name=&quot;*.properties&quot;/&gt;
+    &lt;/fileset&gt;
+&lt;/replaceregexp&gt;</pre>
 
-<br>
-<blockquote>
-<pre>&lt;replaceregexp match="\s+" replace=" " flags="g" byline="true"&gt;
+<p>Replace all whitespaces (blanks, tabs, etc) by one blank remaining the line separator:</p>
+<pre>
+&lt;replaceregexp match="\s+" replace=" " flags="g" byline="true"&gt;
     &lt;fileset dir="${html.dir}" includes="**/*.html"/&gt;
-&lt;/replaceregexp&gt;
-</pre></blockquote>
-<p>replaces all whitespaces (blanks, tabs, etc) by one blank remaining the
-line separator. So with input
-<blockquote>
+&lt;/replaceregexp&gt;</pre>
+<p>Then, input</p>
 <pre>
 &lt;html&gt;    &lt;body&gt;
-&lt;&lt;TAB&gt;&gt;&lt;h1&gt;    T E S T   &lt;/h1&gt;  &lt;&lt;TAB&gt;&gt;    
-&lt;&lt;TAB&gt;&gt; &lt;/body&gt;&lt;/html&gt;
-</pre></blockquote>
-would converted to
-<blockquote>
+&lt;&lt;TAB&gt;&gt;&lt;h1&gt;    T E S T   &lt;/h1&gt;  &lt;&lt;TAB&gt;&gt;
+&lt;&lt;TAB&gt;&gt; &lt;/body&gt;&lt;/html&gt;</pre>
+<p>is converted to</p>
 <pre>
 &lt;html&gt; &lt;body&gt;
- &lt;h1&gt; T E S T &lt;/h1&gt; &lt;/body&gt;&lt;/html&gt;
-</pre>
-</blockquote>
-</p>
+ &lt;h1&gt; T E S T &lt;/h1&gt; &lt;/body&gt;&lt;/html&gt;</pre>
 
-<br><!-- small distance from code of the previous example -->
-<blockquote>
-<pre>&lt;replaceregexp match="\\n" replace="${line.separator}" flags="g" byline="true"&gt;
-    &lt;fileset dir="${dir}"/&gt;
-&lt;/replaceregexp&gt;
-</pre></blockquote>
-<p>replaces all <tt>\n</tt> markers (beware the quoting of the backslash) by a line break.
-So with input
-<blockquote>
+<p>The task</p>
 <pre>
-one\ntwo\nthree
-</pre></blockquote>
-would converted to
-<blockquote>
+&lt;replaceregexp match="\\n" replace="${line.separator}" flags="g" byline="true"&gt;
+    &lt;fileset dir="${dir}"/&gt;
+&lt;/replaceregexp&gt;</pre>
+<p>replaces all <q>\n</q> markers (beware the quoting of the backslash) by a line break. Then,
+input</p>
+<pre>one\ntwo\nthree</pre>
+<p>is converted to</p>
 <pre>
 one
 two
-three
-</pre>
-</blockquote>
-Beware that inserting line breaks could break file syntax. For example in xml:
-<blockquote>
+three</pre>
+
+<p>Beware that inserting line breaks could break file syntax. For example in XML:</p>
 <pre>
 &lt;root&gt;
-  &lt;text&gt;line breaks \n should work in text&lt;/text&gt;
-  &lt;attribute value=&quot;but breaks \n attributes&quot; /&gt;
-&lt;/root&gt;
-</pre>
-</blockquote>
-</p>
-
-
+    &lt;text&gt;line breaks \n should work in text&lt;/text&gt;
+    &lt;attribute value=&quot;but breaks \n attributes&quot;/&gt;
+&lt;/root&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/resourcecount.html b/manual/Tasks/resourcecount.html
index a34506b..04c5781 100644
--- a/manual/Tasks/resourcecount.html
+++ b/manual/Tasks/resourcecount.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ResourceCount Task</title>
 </head>
@@ -25,61 +25,64 @@
 <body>
 
 <h2>ResourceCount</h2>
-
+<p><em>Since Apache Ant 1.7</em></p>
 <h3>Description</h3>
-<p>Display or set a property containing the size of a nested
-   <a href="../Types/resources.html#collection">Resource Collection</a>.
-   Can also be used as a condition. <b>Since Apache Ant 1.7</b></p>
+<p>Display or set a property containing the size of a
+nested <a href="../Types/resources.html#collection">resource collection</a>.  Can also be used as
+a <code>condition</code>.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col" rowspan="2">Attribute</th>
+    <th scope="col" rowspan="2">Description</th>
+    <th scope="col" colspan="2">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The property to set. If omitted the results are written
-      to the log. Ignored when processing as a condition.</td>
-    <td valign="top" align="center">No</td>
+    <th scope="col">Task</th>
+    <th scope="col">Condition</th>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">A <a href="../using.html#references">reference</a>
-      to a Resource Collection.</td>
-    <td valign="top" align="center">
-      Yes, unless a nested Resource Collection is supplied
-    </td>
+    <td>property</td>
+    <td>The property to set.</td>
+    <td class="center">No; by default, output value to the log</td>
+    <td>Ignored</td>
   </tr>
   <tr>
-    <td valign="top">count</td>
-    <td valign="top">Comparison count for processing as a condition.</td>
-    <td valign="top" align="center">Yes, in condition mode</td>
+    <td>refid</td>
+    <td>A <a href="../using.html#references">reference</a> to a resource collection.</td>
+    <td colspan="2">Yes, unless a nested resource collection is supplied</td>
   </tr>
   <tr>
-    <td valign="top">when</td>
-    <td valign="top">Comparison type: "equal", "eq", "greater", "gt", "less",
-      "lt", "ge" (greater or equal), "ne" (not equal), "le" (less or equal)
-      for use when operating as a condition.</td>
-    <td valign="top" align="center">No; default is "equal"</td>
+    <td>count</td>
+    <td>Comparison count.</td>
+    <td class="center" rowspan="2">Ignored</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>when</td>
+    <td>Comparison
+    type: <q>equal</q>, <q>eq</q>, <q>greater</q>, <q>gt</q>, <q>less</q>, <q>lt</q>, <q>ge</q>
+    (greater or equal), <q>ne</q> (not equal), <q>le</q> (less or equal).</td>
+    <td>No; default is <q>equal</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
-<h4>Resource Collection</h4>
-<p>A single
-  <a href="../Types/resources.html#collection">Resource Collection</a>
-should be specified via a nested element or the <code>refid</code> attribute.
-</p>
+<h4>resource collection</h4>
+<p>A single <a href="../Types/resources.html#collection">resource collection</a> should be specified
+via a nested element or the <var>refid</var> attribute.</p>
 
 <h3>Examples</h3>
-<pre>&lt;resourcecount property=&quot;count.foo&quot;&gt;
-  &lt;filelist dir=&quot;.&quot; files=&quot;foo,bar&quot; /&gt;
-&lt;/resourcecount&gt;
-</pre>
-<p>Stores the number of resources in the specified filelist (two)
-in the property named <i>count.foo</i>.</p>
+<p>Store the number of resources in the specified filelist (two files) in the property
+named <samp>count.foo</samp>.</p>
+<pre>
+&lt;resourcecount property=&quot;count.foo&quot;&gt;
+  &lt;filelist dir=&quot;.&quot; files=&quot;foo,bar&quot;/&gt;
+&lt;/resourcecount&gt;</pre>
 
+<p>Store the number of lines of the current buildfile in the
+property <code>file.lines</code>. Requires Ant 1.7.1+ as <code>&lt;concat&gt;</code> has to be a
+resource.</p>
 <pre>
 &lt;project&gt;
   &lt;property name=&quot;file&quot; value=&quot;${ant.file}&quot;/&gt;
@@ -96,12 +99,7 @@
     &lt;/tokens&gt;
   &lt;/resourcecount&gt;
   &lt;echo&gt;The file '${file}' has ${file.lines} lines.&lt;/echo&gt;
-&lt;/project&gt;
-</pre>
-<p>Stores the number of lines of the current buildfile in the property <tt>file.lines</tt>.
-Requires Ant 1.7.1+ as &lt;concat&gt; has to be resource.</p>
-
+&lt;/project&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/retry.html b/manual/Tasks/retry.html
index af68d40..f8167e4 100644
--- a/manual/Tasks/retry.html
+++ b/manual/Tasks/retry.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,48 +15,48 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Retry Task</title>
 </head>
 <body>
 <h2>Retry</h2>
+<p><em>Since Apache Ant 1.7.1</em></p>
 <h3>Description</h3>
-<p>Retry is a container which executes a single nested task until either: there is no failure; or:
-its <em>retrycount</em> has been exceeded. If this happens a BuildException is thrown.
-<em>Since Apache Ant 1.7.1</em></p>
+<p><code>Retry</code> is a container which executes a single nested task until either: there is no
+failure; or: its <var>retrycount</var> has been exceeded. If this happens
+a <code>BuildException</code> is thrown.</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>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
-  <tr> 
-    <td valign="top">retrycount</td>
-    <td valign="top">number of times to attempt to execute the nested task</td>
-    <td valign="top" align="center">Yes</td>
+  <tr>
+    <td>retrycount</td>
+    <td>number of times to attempt to execute the nested task</td>
+    <td>Yes</td>
   </tr>
-  <tr> 
-    <td valign="top">retrydelay</td>
-    <td valign="top">number of milliseconds to wait between retry attempts
-    task. <em>Since Apache Ant 1.8.3</em></td>
-    <td valign="top" align="center">No, defaults to no delay</td>
+  <tr>
+    <td>retrydelay</td>
+    <td>number of milliseconds to wait between retry attempts task. <em>Since Apache Ant
+    1.8.3</em></td>
+    <td>No; defaults to no delay</td>
   </tr>
 </table>
 <p>Any valid Ant task may be embedded within the retry task.</p>
 
 <h3>Example</h3>
+<p>This example shows how to use <code>&lt;retry&gt;</code> to wrap a task which must interact with
+an unreliable network resource.</p>
 <pre>
 &lt;retry retrycount="3"&gt;
-  &lt;get src="http://www.unreliable-server.com/unreliable.tar.gz" 
-       dest="/home/retry/unreliable.tar.gz" /&gt;
-&lt;/retry&gt;
-</pre>
-<p>This example shows how to use <code>&lt;retry&gt;</code> to wrap a task which must interact with an unreliable network resource.</p>
+  &lt;get src="https://www.unreliable-server.com/unreliable.tar.gz"
+       dest="/home/retry/unreliable.tar.gz"/&gt;
+&lt;/retry&gt;</pre>
 </body>
 </html>
diff --git a/manual/Tasks/rexec.html b/manual/Tasks/rexec.html
index 02f6fe2..2609bfb 100644
--- a/manual/Tasks/rexec.html
+++ b/manual/Tasks/rexec.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,36 +15,36 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>RExec Task</title>
 </head>
 
 <body>
 
-<h2><a name="rexec">RExec</a></h2>
+<h2 id="rexec">RExec</h2>
 <h3>Description</h3>
-Task to automate a remote rexec session. Just like the Telnet task,
-it uses nested <tt>&lt;read&gt;</tt> to indicate strings to wait for, and
-<tt>&lt;write&gt;</tt> tags to specify text to send to the remote process.
+<p>Task to automate a remote rexec session. Just like the <code>Telnet</code> task, it uses
+nested <code>&lt;read&gt;</code> to indicate strings to wait for, and
+<code>&lt;write&gt;</code> tags to specify text to send to the remote
+process.</p>
 
-<p><b>Note:</b> This task depends on external libraries not included in the Apache Ant distribution.
-See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution.  See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
 
-<p>You can specify the commands you want to execute as nested elements
-or via the command attribute, we recommend you use the command
-attribute.  If you use the command attribute, you must use the
-username and password attributes as well.</p>
+<p>You can specify the commands you want to execute as nested elements or via the <var>command</var>
+attribute, we recommend you use the <var>command</var> attribute.  If you use the <var>command</var>
+attribute, you must use the <var>username</var> and <var>password</var> attributes as well.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
      <td>userid</td>
@@ -67,50 +68,40 @@
   </tr>
   <tr>
      <td>port</td>
-     <td>the port number of the remote rexec server. Defaults to port 512 in BSD Unix systems.</td>
-     <td>No</td>
+      <td>the port number of the remote rexec server.</td>
+     <td>No; defaults to <q>512</q> in Unix</td>
   </tr>
   <tr>
      <td>timeout</td>
-     <td>set a default timeout to wait for a response. Specified in seconds. Default is no timeout.</td>
-     <td>No</td>
+     <td>set a default timeout to wait for a response, specified in seconds.</td>
+     <td>No; default is no timeout</td>
   </tr>
 </table>
-<h3><a name="nested">Nested Elements</a></h3>
-The input to send to the server, and responses to wait for, are
-described as nested elements.  
+<h3 id="nested">Parameters specified as nested elements</h3>
+<p>The input to send to the server, and responses to wait for, are described as nested elements.</p>
 
 <h4>read</h4>
 
-<p>declare (as a text child of this element) a string to wait for.
-The element supports the timeout attribute, which overrides any
-timeout specified for the task as a whole. It also has a <tt>string</tt>
-attribute, which is an alternative to specifying the string as 
-a text element.
-</p>
-<i>It is not necessary to declare a closing <code>&lt;read&gt;</code> element like for the Telnet task. The connection is not broken until the command has completed and
-the input stream (output of the command) is terminated.
-</i>
+<p>declare (as a text child of this element) a string to wait for.  The element supports
+the <var>timeout</var> attribute, which overrides any timeout specified for the task as a whole. It
+also has a <var>string</var> attribute, which is an alternative to specifying the string as a text
+element.</p>
+<p><em>It is not necessary to declare a closing <code>&lt;read&gt;</code> element like for
+the <code>Telnet</code> task. The connection is not broken until the command has completed and the
+input stream (output of the command) is terminated.</em></p>
+
 <h4>write</h4>
 
-<p>describes the text to send to the server. The <tt>echo</tt> boolean
-attribute controls whether the string is echoed to the local log; 
-this is "true" by default
-</p>
+<p>describes the text to send to the server. The <var>echo</var> boolean attribute controls whether
+the string is echoed to the local log; this is <q>true</q> by default.</p>
 <h3>Example</h3>
-A simple example of connecting to a server and running a command.
+<p>A simple example of connecting to a server and running a command.</p>
 
-<blockquote><pre>
-&lt;rexec userid=&quot;bob&quot; password=&quot;badpass&quot; server=&quot;localhost&quot; command=&quot;ls&quot;/&gt;
-</pre></blockquote>
+<pre>&lt;rexec userid=&quot;bob&quot; password=&quot;badpass&quot; server=&quot;localhost&quot; command=&quot;ls&quot;/&gt;</pre>
 
-The task can be used with other ports as well:
-<blockquote><pre>
-&lt;rexec port=&quot;80&quot; userid=&quot;bob&quot; password=&quot;badpass&quot; server=&quot;localhost&quot; command=&quot;ls&quot;/&gt;
-</pre></blockquote>
+<p>The task can be used with other ports as well:</p>
 
-
+<pre>&lt;rexec port=&quot;80&quot; userid=&quot;bob&quot; password=&quot;badpass&quot; server=&quot;localhost&quot; command=&quot;ls&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/rmic.html b/manual/Tasks/rmic.html
index 226b54b..c56153f 100644
--- a/manual/Tasks/rmic.html
+++ b/manual/Tasks/rmic.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,349 +15,309 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Rmic Task</title>
 </head>
 
 <body>
 
-<h2><a name="rmic">Rmic</a></h2>
+<h2 id="rmic">Rmic</h2>
 <h3>Description</h3>
-<p>Runs the rmic compiler for a certain class.</p>
+<p>Runs the <kbd>rmic</kbd> compiler for a certain class.</p>
 
-<p><b>Note</b> <code>rmic</code> has been deprecated as of Java 13 and
+<p><b>Note</b> <kbd>rmic</kbd> has been deprecated as of Java 13 and
   removed as of Java 15. Trying to use it with Java15 will fail unless
-  you specifiy the execxutable or rmic-adapter explicitly.</p>
+  you specify the executable or rmic-adapter explicitly.</p>
 
-<p>Rmic can be run on a single class (as specified with the classname
-attribute) or a number of classes at once (all classes below base that
-are neither _Stub nor _Skel classes).  If you want to rmic a single
-class and this class is a class nested into another class, you have to
-specify the classname in the form <code>Outer$$Inner</code> instead of
-<code>Outer.Inner</code>.</p>
-<p>It is possible to refine the set of files that are being rmiced. This can be
-done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and <i>defaultexcludes</i>
-attributes. With the <i>includes</i> or <i>includesfile</i> attribute you specify the files you want to
-have included by using patterns. The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
-the files you want to have excluded. This is also done with patterns. And
-finally with the <i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+<p><code>Rmic</code> can be run on a single class (as specified with the classname attribute) or a
+number of classes at once (all classes below base that are neither <code>_Stub</code>
+nor <code>_Skel</code> classes).  If you want to <code>rmic</code> a single class and this class is
+a class nested into another class, you have to specify the classname in the
+form <code>Outer$$Inner</code> instead of <code>Outer.Inner</code>.</p>
+<p>It is possible to refine the set of files that are being <code>rmic</code>ed. This can be done
+with the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+and <var>defaultexcludes</var> attributes. With the <var>includes</var> or <var>includesfile</var>
+attribute you specify the files you want to have included by using patterns. The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded. This is
+also done with patterns. And finally with the <var>defaultexcludes</var> attribute, you can specify
+whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
 inclusion/exclusion of files works, and how to write patterns.</p>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>base</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
-<p>It is possible to use different compilers. This can be selected
-with the &quot;build.rmic&quot; property, the <code>compiler</code>
-attribute. or a nested element.
-<a name="compilervalues">Here are the choices</a>:</p>
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>base</var>) as well as the
+nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+<p id="compilervalues">It is possible to use different compilers. This can be selected with
+the <code>build.rmic</code> property, the <var>compiler</var> attribute, or a nested element. Here
+are the choices:</p>
 <ul>
-  <li>default -the default compiler (kaffe, sun or forking) for the platform.
-  <li>sun (the standard compiler of the JDK &lt; JDK 9)</li>
-  <li>kaffe (the standard compiler of <a href="http://www.kaffe.org" target="_top">Kaffe</a>)</li>
-  <li>weblogic</li>
-  <li>forking - the sun compiler forked into a separate process (since
-    Apache Ant 1.7). Starting with Ant 1.9.8 this is the default when
-    running on JDK 9+.</li>
-  <li>xnew - the sun compiler forked into a separate process,
-      with the -Xnew option (since Ant 1.7).
-    This is the most reliable way to use -Xnew.
-    <br></br>JDK9 has removed support for -Xnew and starting with Ant
-    1.9.8 this option will be rejected by ant when running on JDK9.</li>
-    <li> "" (empty string). This has the same behaviour as not setting the compiler attribute.
-    First the value of <tt>build.rmic</tt> is used if defined, and if not, the default
-    for the platform is chosen. If build.rmic is set to this, you get the default.
-
+  <li><q>default</q>&mdash;the default compiler (<q>kaffe</q>, <q>sun</q> or <q>forking</q>) for the
+    platform.
+  <li><q>sun</q>&mdash;the standard compiler prior to JDK 9</li>
+  <li><q>kaffe</q>&mdash;the standard compiler of <a href="https://github.com/kaffe/kaffe"
+    target="_top">Kaffe</a></li>
+  <li><q>weblogic</q></li>
+  <li><q>forking</q>&mdash;(<em>since Apache Ant 1.7</em>) the <q>sun</q> compiler forked into a
+    separate process.  <em>Since Ant 1.9.8</em>, this is the default when running on JDK 9+.</li>
+  <li><q>xnew</q>&mdash;(<em>since Ant 1.7</em>) the <q>sun</q> compiler forked into a separate
+    process, with the <kbd>-Xnew</kbd> option. This is the most reliable way to
+    use <kbd>-Xnew</kbd>.<br/>JDK 9 has removed support for <kbd>-Xnew</kbd> and <em>since Ant
+    1.9.8</em> this option will be rejected when running on JDK 9+.</li>
+  <li><q></q> (empty string). This has the same behaviour as not setting the compiler attribute.
+    First the value of <code>build.rmic</code> is used if defined, and if not, the default for the
+    platform is chosen. If <code>build.rmic</code> is set to this, you get the default.</li>
 </ul>
 
-<p>The <a href="http://dione.zcu.cz/~toman40/miniRMI/">miniRMI</a>
-project contains a compiler implementation for this task as well,
-please consult miniRMI's documentation to learn how to use it.</p>
+<p>The <a href="https://web.archive.org/web/20131225023602/http://dione.zcu.cz/~toman40/miniRMI/"
+target="_top">miniRMI</a> project contains a compiler implementation for this task as well, please
+consult miniRMI's documentation to learn how to use it.</p>
 
 <h4>CORBA support</h4>
 
-<p>Java 11 removes the CORBA and JavaEE packages and rmic no longer
-  supports either <code>iiop</code> nor <code>idl</code>. Starting
-  with Ant 1.9.11 the rmic task will fail when using either while
-  running Java11+ unless you fork the task and explicitly specify an
-  executable.</p>
+<p>Java 11 <a href="https://openjdk.java.net/jeps/320" target="_top">removes</a> the Java EE and
+CORBA packages and <kbd>rmic</kbd> no longer supports either <kbd>-iiop</kbd>
+or <kbd>-idl</kbd> options. Starting with Ant 1.10.3, the <kbd>rmic</kbd> task will fail when using
+either while running Java 11+ unless you fork the task and explicitly specify an executable.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr id="footnote-1-back">
+    <td>base</td>
+    <td>the location to store the compiled files.  Also serves as the parent directory for any
+      non-Fileset includes, etc.  (This functionality has remained unchanged.)</td>
+    <td rowspan="2">See <a href="#footnote-1">note</a></td>
   </tr>
   <tr>
-    <td valign="top">base</td>
-    <td valign="top">the location to store the compiled files.
-      Also serves as the parent directory for any non-Fileset includes, etc.
-      (This functionality has remained unchanged.)</td>
-    <td valign="top" align="center" rowspan="2"><a href="#footnote-1">*1</a></td>
+    <td>destdir</td>
+    <td class="left">the location to store the compiled files.</td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">the location to store the compiled files.</td>
+    <td>classname</td>
+    <td>the class for which to run <kbd>rmic</kbd>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">the class for which to run <code>rmic</code>.</td>
-    <td valign="top" align="center">No</td>
+    <td>filtering</td>
+    <td>indicates whether token filtering should take place</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">filtering</td>
-    <td valign="top">indicates whether token filtering should take place</td>
-    <td valign="top" align="center">No</td>
+    <td>sourcebase</td>
+    <td>Pass the <kbd>-keepgenerated</kbd> flag to <kbd>rmic</kbd> and move the generated source
+      file to the given <var>sourcebase</var> directory.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sourcebase</td>
-    <td valign="top">Pass the &quot;-keepgenerated&quot; flag to rmic and
- move the generated source file to the given sourcebase directory.</td>
-    <td align="center" valign="top">No</td>
+    <td>stubversion</td>
+    <td>Specify the JDK version for the generated stub code.  Specify <q>1.1</q> to pass
+      the <kbd>-v1.1</kbd> option to <kbd>rmic</kbd>, <q>1.2</q>
+      for <kbd>-v1.2</kbd>, <q>compat</q> for <kbd>-vcompat</kbd>.<br/><em>Since Ant 1.7</em>, if
+      you do not specify a version, and do not ask for <samp>.iiop</samp> or <samp>.idl</samp>
+      files, <q>compat</q> is selected.</td>
+    <td>No; default is <q>compat</q></td>
   </tr>
   <tr>
-    <td valign="top">stubversion</td>
-    <td valign="top">Specify the JDK version for the generated stub code.
- Specify &quot;1.1&quot; to pass the &quot;-v1.1&quot; option to rmic,
- "1.2" for -v12, compat for -vcompat. <br>
-        Since Ant1.7, if you do not specify a version, and do not ask
-        for iiop or idl files, "compat" is selected.
- 
- </td>
-    <td align="center" valign="top">No, default="compat"</td>
+    <td>classpath</td>
+    <td>The classpath to use during compilation</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to use during compilation</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>The classpath to use during compilation, given
+      as <a href="../using.html#references">reference</a> to a path defined elsewhere</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use during compilation, given as <a
-      href="../using.html#references">reference</a> to a PATH defined elsewhere</td>
-    <td align="center" valign="top">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>verify</td>
+    <td>check that classes implement <code>Remote</code> before handing them to <kbd>rmic</kbd></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verify</td>
-    <td valign="top">check that classes implement Remote before handing them 
-        to rmic (default is false)</td>
-    <td align="center" valign="top">No</td>
+    <td>iiop</td>
+    <td>indicates that portable (RMI/IIOP) stubs should be generated.<br/>  See the note on CORBA
+      support above.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">iiop</td>
-    <td valign="top">indicates that portable (RMI/IIOP) stubs should
-      be generated.<br/>
-      See the note on CORBA support above.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>iiopopts</td>
+    <td>additional arguments for IIOP class generation</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">iiopopts</td>
-    <td valign="top">additional arguments for IIOP class generation</td>
-    <td align="center" valign="top">No</td>
+    <td>idl</td>
+    <td>indicates that IDL output files should be generated.<br/>  See the note on CORBA support
+      above.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">idl</td>
-    <td valign="top">indicates that IDL output files should be
-      generated.<br/>  See the note on CORBA support above.</td>
-    <td align="center" valign="top">No</td>
+    <td>idlopts</td>
+    <td>additional arguments for IDL file generation</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">idlopts</td>
-    <td valign="top">additional arguments for IDL file generation</td>
-    <td align="center" valign="top">No</td>
+    <td>debug</td>
+    <td>generate debug info (passes <kbd>-g</kbd> to <kbd>rmic</kbd>)</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">debug</td>
-    <td valign="top">generate debug info (passes -g to rmic). Defaults to false.</td>
-    <td align="center" valign="top">No</td>
+    <td>includeAntRuntime</td>
+    <td>whether to include the Ant run-time libraries</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">includeAntRuntime</td> 
-    <td valign="top">whether to include the Ant run-time libraries;
-      defaults to <code>yes</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>includeJavaRuntime</td>
+    <td>whether to include the default run-time libraries from the executing JVM</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">includeJavaRuntime</td> 
-    <td valign="top">whether to include the default run-time
-      libraries from the executing VM; defaults to <code>no</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>extdirs</td>
+    <td>location of installed extensions</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">extdirs</td>
-    <td valign="top">location of installed extensions.</td>
-    <td align="center" valign="top">No</td>
+    <td>compiler</td>
+    <td>The compiler implementation to use.  (See the above <a href="#compilervalues">list</a> of
+      valid compilers.)</td>
+    <td>No; defaults to the value of the <code>build.rmic</code> property, if set, and the default
+      compiler for the current JDK otherwise</td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td valign="top">The compiler implementation to use.
-      If this attribute is not set, the value of the
-      <code>build.rmic</code> property, if set, will be used.
-      Otherwise, the default compiler for the current VM will be used.
-      (See the above <a href="#compilervalues">list</a> of valid
-      compilers.)</td>
-    <td align="center" valign="top">No</td>
+    <td>executable</td>
+    <td>Complete path to the <kbd>rmic</kbd> executable to use in case of the <q>forking</q>
+      or <q>xnew</q> compiler. <em>Since Ant 1.8.0</em>.</td>
+    <td>No; defaults to the <kbd>rmic</kbd> compiler of JDK that is currently running Ant</td>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">Complete path to the <code>rmic</code>
-      executable to use in case of the <code>forking</code>
-      or <code>xnew</code> compiler.
-      Defaults to the rmic compiler of the Java version that is currently
-      running Ant.<br/>
-      <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">listfiles</td>
-    <td valign="top">Indicates whether the source files to be compiled will
-      be listed; defaults to <code>no</code>.<br/>
-      <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No</td>
+    <td>listfiles</td>
+    <td>Indicates whether the source files to be compiled will be listed. <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
 </table>
 
-<p><a name="footnote-1">*1</a>:
+<p id="footnote-1"><a href="#footnote-1-back">Note</a>:</p>
 <ul>
-  <li>Maintaining compatibility, <code>base</code>, when specified by
-    itself, serves as both the parent directory for any source files
-    AND the output directory.</li>
-  <li><code>destdir</code> can be used to specify the output
-    directory, allowing for <code>base</code> to be used as the parent
-    directory for any source files.</li>
-  <li>At least one of either <code>base</code> or <code>destdir</code>
-    must be specified and exist, or a runtime error will
-    occur.</li>
+  <li>Maintaining compatibility, <var>base</var>, when specified by itself, serves as both the
+    parent directory for any source files AND the output directory.</li>
+  <li><var>destdir</var> can be used to specify the output directory, allowing for <var>base</var>
+    to be used as the parent directory for any source files.</li>
+  <li>At least one of either <var>base</var> or <var>destdir</var> must be specified and exist, or
+    an error will occur at run time.</li>
 </ul>
-</p>
 
 <h3>Parameters specified as nested elements</h3>
 <h4>classpath and extdirs</h4>
-<p><code>Rmic</code>'s <i>classpath</i> and <i>extdirs</i> attributes are <a
-href="../using.html#path">PATH like structure</a> and can also be set via a nested
-<i>classpath</i> and <i>extdirs</i> elements.</p>
+<p><code>Rmic</code>'s <var>classpath</var> and <var>extdirs</var> attributes
+are <a href="../using.html#path">path-like structure</a> and can also be set via a nested
+<code>classpath</code> and <code>extdirs</code> elements.</p>
 
 <h4>compilerarg</h4>
 
-<p>You can specify additional command line arguments for the compiler
-with nested <code>&lt;compilerarg&gt;</code> elements.  These elements
-are specified like <a href="../using.html#arg">Command-line
-Arguments</a> but have an additional attribute that can be used to
-enable arguments only if a given compiler implementation will be
-used.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>You can specify additional command line arguments for the compiler with
+nested <code>&lt;compilerarg&gt;</code> elements.  These elements are specified
+like <a href="../using.html#arg">Command-line Arguments</a> but have an additional attribute that
+can be used to enable arguments only if a given compiler implementation will be used.</p>
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">value</td>
-    <td align="center" rowspan="4">See
-    <a href="../using.html#arg">Command-line Arguments</a>.</td>
-    <td align="center" rowspan="4">Exactly one of these.</td>
+    <td>value</td>
+    <td rowspan="4">See <a href="../using.html#arg">Command-line Arguments</a>.</td>
+    <td rowspan="4">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">line</td>
+    <td class="var">line</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
+    <td class="var">file</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
+    <td class="var">path</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td align="center" rowspan="2">See
+    <td>prefix</td>
+    <td rowspan="2">See
     <a href="../using.html#arg">Command-line Arguments</a>.
-    <em>Since Ant 1.8.</em></td>
-    <td valign="top" align="center">No</td>
+    <em>Since Ant 1.8</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top" align="center">No</td>
+    <td>suffix</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compiler</td>
-    <td>Only pass the specified argument if the chosen
-      compiler implementation matches the value of this attribute.
-      Legal values are the
-      same as those in the above <a href="#compilervalues">list</a> of valid
-      compilers.)</td>
-    <td align="center">No</td>
+    <td>compiler</td>
+    <td>Only pass the specified argument if the chosen compiler implementation matches the value of
+      this attribute.  Legal values are the same as those in the
+      above <a href="#compilervalues">list</a> of valid compilers.)</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4>compilerclasspath <em>since Ant 1.8.0</em></h4>
+<h4>compilerclasspath</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>A <a href="../using.html#path">path-like structure</a> holding the classpath to use when loading
+the compiler implementation if a custom class has been specified.  Doesn't have any effect when
+using one of the built-in compilers.</p>
 
-<p>A <a href="../using.html#path">PATH like structure</a> holding the
-  classpath to use when loading the compiler implementation if a
-  custom class has been specified.  Doesn't have any effect when
-  using one of the built-in compilers.</p>
-
-<h4>Any nested element of a type that implements RmicAdapter
-  <em>since Ant 1.8.0</em></h4>
-
-<p>If a defined type implements the <code>RmicAdapter</code>
-  interface a nested element of that type can be used as an
-  alternative to the <code>compiler</code> attribute.</p>
+<h4>Any nested element of a type that implements RmicAdapter</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>If a defined type implements the <code>RmicAdapter</code> interface a nested element of that type
+can be used as an alternative to the <var>compiler</var> attribute.</p>
 
 <h3>Examples</h3>
-<pre>  &lt;rmic classname=&quot;com.xyz.FooBar&quot; base=&quot;${build}/classes&quot;/&gt;</pre>
-<p>runs the rmic compiler for the class <code>com.xyz.FooBar</code>. The
-compiled files will be stored in the directory <code>${build}/classes</code>.</p>
-<pre>  &lt;rmic base=&quot;${build}/classes&quot; includes=&quot;**/Remote*.class&quot;/&gt;</pre>
-<p>runs the rmic compiler for all classes with <code>.class</code>
-files below <code>${build}/classes</code> whose classname starts with
-<i>Remote</i>. The compiled files will be stored in the directory
-<code>${build}/classes</code>.</p>
 
-<p>If you want to use a custom
-  RmicAdapter <code>org.example.MyAdapter</code> you can either
-  use the compiler attribute:</p>
+<p>Run the <kbd>rmic</kbd> compiler for the class <code>com.xyz.FooBar</code>. The compiled files
+will be stored in the directory <samp>${build}/classes</samp>.</p>
+<pre>&lt;rmic classname=&quot;com.xyz.FooBar&quot; base=&quot;${build}/classes&quot;/&gt;</pre>
+
+<p>Run the <kbd>rmic</kbd> compiler for all classes with <samp>.class</samp> files
+below <samp>${build}/classes</samp> whose classname starts with <code>Remote</code>. The compiled
+files will be stored in the directory <samp>${build}/classes</samp>.</p>
+<pre>&lt;rmic base=&quot;${build}/classes&quot; includes=&quot;**/Remote*.class&quot;/&gt;</pre>
+
+<p>If you want to use a custom RmicAdapter <code>org.example.MyAdapter</code> you can either use
+the <var>compiler</var> attribute:</p>
 <pre>
 &lt;rmic classname=&quot;com.xyz.FooBar&quot;
       base=&quot;${build}/classes&quot;
-      compiler="org.example.MyAdapter"/&gt;
-</pre>
+      compiler="org.example.MyAdapter"/&gt;</pre>
 <p>or a define a type and nest this into the task like in:</p>
 <pre>
 &lt;componentdef classname="org.example.MyAdapter"
@@ -364,11 +325,8 @@
 &lt;rmic classname=&quot;com.xyz.FooBar&quot;
       base=&quot;${build}/classes&quot;&gt;
   &lt;myadapter/&gt;
-&lt;/rmic&gt;
-</pre>
-<p>in which case your compiler adapter can support attributes and
-  nested elements of its own.</p>
+&lt;/rmic&gt;</pre>
+<p>in which case your compiler adapter can support attributes and nested elements of its own.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/rpm.html b/manual/Tasks/rpm.html
index 691d391..36a6cb0 100644
--- a/manual/Tasks/rpm.html
+++ b/manual/Tasks/rpm.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -15,7 +16,7 @@
    limitations under the License.
 -->
 
-<html>
+<html lang="en">
 
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
@@ -24,100 +25,86 @@
 
 <body>
 
-<h2><a name="rpm">Rpm</a></h2>
+<h2 id="rpm">Rpm</h2>
 <h3>Description</h3>
-<p>
-  A basic task for invoking the rpm executable to build a RedHat Package Manager Linux installation
-  file. The task currently only works on Linux or other Unix platforms with rpm support.
-</p>
+<p> A basic task for invoking the <code>rpm</code> executable to build a RedHat Package Manager
+Linux installation file. The task currently only works on Linux or other Unix platforms
+with <code>rpm</code> support.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">specFile</td>
-    <td valign="top">The name of the spec file to be used. This must be relative to the SPECS directory
-    under the root of the RPM set in the topDir attribute.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>specFile</td>
+    <td>The name of the spec file to be used. This must be relative to the <samp>SPECS</samp>
+      directory under the root of the RPM set in the <var>topDir</var> attribute.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">topDir</td>
-    <td valign="top">
-      This is the directory which will have the expected
-      subdirectories, SPECS, SOURCES, BUILD, SRPMS.  If this isn't specified,
-      the default RPM directory of the system (or user, if ~/.rpmmacros defines it) is used (often
-      /usr/src/rpm.<br>
-      Defining a topdir will set <tt>%_topdir</tt> to the specified directory -there is no need
-      to edit your .rpmmacros file.
-    </td>
-    <td valign="top" align="center">No, but your build file is very brittle if it is not set.</td>
+    <td>topDir</td>
+    <td>This is the directory which will have the expected
+      subdirectories, <samp>SPECS</samp>, <samp>SOURCES</samp>, <samp>BUILD</samp>, <samp>SRPMS</samp>.
+      If this isn't specified, the default RPM directory of the system (or user,
+      if <samp>~/.rpmmacros</samp> defines it) is used (often <samp>/usr/src/rpm</samp>.<br/>
+      Defining a <var>topdir</var> will set <code>%_topdir</code> to the specified
+      directory&mdash;there is no need to edit your <samp>.rpmmacros</samp> file.</td>
+    <td>No, but your build file is very brittle if it is not set.</td>
   </tr>
   <tr>
-    <td valign="top">cleanBuildDir</td>
-    <td valign="top">This will remove the generated files in the BUILD
-      directory.
-      See the the <tt>--clean</tt> option of rpmbuild.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>cleanBuildDir</td>
+    <td>This will remove the generated files in the <samp>BUILD</samp> directory.  See the
+      the <kbd>--clean</kbd> option of <kbd>rpmbuild</kbd>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">removeSpec</td>
-    <td valign="top">This will remove the spec file from SPECS.
-      See the the <tt>--rmspec</tt> option of rpmbuild.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>removeSpec</td>
+    <td>This will remove the spec file from <samp>SPECS</samp>.  See the the <kbd>--rmspec</kbd>
+      option of <kbd>rpmbuild</kbd>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">removeSource</td>
-    <td valign="top">Flag (optional, default=false) 
-        to remove the sources after the build.
-        See the the <tt>--rmsource</tt> option of rpmbuild.</td>
-    <td align="center" valign="top">No</td>
+    <td>removeSource</td>
+    <td>Flag to remove the sources after the build.  See the <kbd>--rmsource</kbd> option
+      of <kbd>rpmbuild</kbd>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">rpmBuildCommand</td>
-    <td valign="top">The executable to use for building the RPM.
-      Defaults to <code>rpmbuild</code> if it can be found or
-      <code>rpm</code> otherwise.  Set this if you don't have either on
-      your PATH or want to use a different executable.  <em>Since Apache Ant
-      1.6</em>.</td>
-    <td valign="top" align="center">No</td>
+    <td>rpmBuildCommand</td>
+    <td>The executable to use for building the RPM. Set this if default executables are not on
+      <code>PATH</code> or a different executable is needed.  <em>Since Apache Ant 1.6</em>.</td>
+    <td>No; defaults to <kbd>rpmbuild</kbd> if it can be found or <kbd>rpm</kbd> otherwise</td>
   </tr>
   <tr>
-    <td valign="top">command</td>
-    <td valign="top">The command to pass to the rpmbuild program. The default is "-bb"</td>
-    <td align="center" valign="top">No</td>
+    <td>command</td>
+    <td>The command to pass to the <code>rpmbuild</code> program.</td>
+    <td>No; default is <kbd>-bb</kbd></td>
   </tr>
   <tr>
-    <td valign="top">quiet</td>
-    <td valign="top">Suppress output. Defaults to false.</td>
-    <td align="center" valign="top">No</td>
+    <td>quiet</td>
+    <td>Suppress output.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">output/error</td>
-    <td valign="top">Where standard output and error go</td>
-    <td align="center" valign="top">No</td>
+    <td>output/error</td>
+    <td>Where standard output and error go.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">failOnError</td>
-    <td valign="top">Stop the buildprocess if the RPM build command exits with 
-       a non-zero returncode. Defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>failOnError</td>
+    <td>Stop the build process if the RPM build command exits with a non-zero return code.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
 <pre>
-    &lt;rpm
-        specFile="example.spec"
-        topDir="build/rpm"
-        cleanBuildDir="true"
-        failOnError="true"/&gt;
-</pre>
+&lt;rpm specFile="example.spec"
+     topDir="build/rpm"
+     cleanBuildDir="true"
+     failOnError="true"/&gt;</pre>
 </body>
 </html>
-
diff --git a/manual/Tasks/schemavalidate.html b/manual/Tasks/schemavalidate.html
index 1aac2ef..adef1d9 100644
--- a/manual/Tasks/schemavalidate.html
+++ b/manual/Tasks/schemavalidate.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
@@ -23,261 +24,226 @@
 
 <body>
 
-<h2><a name="schemavalidate">SchemaValidate</a></h2>
+<h2 id="schemavalidate">SchemaValidate</h2>
 <h3>Description</h3>
 
-<p>This <tt>schemavalidate</tt> task validates XML files described by an XML Schema.
-The task extends the XmlValidate task with XSD-specific features.</p>
+<p>This <code>schemavalidate</code> task validates XML files described by an XML Schema.  The task
+extends the <code>XmlValidate</code> task with XSD-specific features.</p>
 <ol>
-<li>The parser is created validating and namespace aware
-</li>
-<li>Validation is turned on.</li>
-<li>Schema validation is turned on.</li>
-<li>Any no-namespace schema URL or file supplied is used as the no-namespace schema
-<li>All nested schema declarations are turned into the list of namespace-url
-bindings for schema lookup.
+  <li>The parser is created validating and namespace aware.</li>
+  <li>Validation is turned on.</li>
+  <li>Schema validation is turned on.</li>
+  <li>Any no-namespace schema URL or file supplied is used as the no-namespace schema.</li>
+  <li>All nested schema declarations are turned into the list of namespace-url bindings for schema
+    lookup.</li>
 </ol>
 
-Note that nested catalogs are still used for lookup of the URLs given as the
-sources of schema documents, so you can still delegate lookup to a catalog, you
-just need to list all schema URIs and their URL equivalents.
+<p>Note that nested catalogs are still used for lookup of the URLs given as the sources of schema
+documents, so you can still delegate lookup to a catalog, you just need to list all schema URIs and
+their URL equivalents.</p>
 
-<p>This task supports the use of nested
-  <li><a href="../Types/xmlcatalog.html"><tt>&lt;xmlcatalog&gt;</tt></a> elements</li>
-  <li> <tt>&lt;schema&gt;</tt> elements, that bind a namespace URI to a URL or a
-  local filename.
-  <li><tt>&lt;dtd&gt;</tt> elements which are used to resolve DTDs and entities.</li>
-  <li><tt>&lt;attribute&gt;</tt> elements which are used to set features on the parser.
-      These can be any number of
-      <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"><tt>http://xml.org/sax/features/</tt></a>
-      or other features that your parser may support.</li>
-  <li><tt>&lt;property&gt;</tt> elements, containing string properties
-</p>
+<p>This task supports the use of nested</p>
+<ul>
+  <li><a href="../Types/xmlcatalog.html"><code>&lt;xmlcatalog&gt;</code></a> elements</li>
+  <li><code>&lt;schema&gt;</code> elements, that bind a namespace URI to a URL or a local
+    filename.</li>
+  <li><code>&lt;dtd&gt;</code> elements which are used to resolve DTDs and entities.</li>
+  <li><code>&lt;attribute&gt;</code> elements which are used to set features on the parser.  These
+    can be any number
+    of <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
+    target="_top"><code>http://xml.org/sax/features/</code></a> or other features that your parser
+    may support.</li>
+  <li><code>&lt;property&gt;</code> elements, containing string properties</li>
+</ul>
 
-<p>
-The task only supports SAX2 or later parsers: it is an error to specify a SAX1
-parser. 
-
+<p>The task only supports SAX2 or later parsers: it is an error to specify a SAX1 parser.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">the parser to use.</td>
-    <td align="center" valign="top">No</td>
+    <td>classname</td>
+    <td>the parser to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">where to find the parser class. 
-    Optionally can use an embedded <tt>&lt;classpath&gt;</tt> element.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>where to find the parser class.  Optionally can use an
+      embedded <code>&lt;classpath&gt;</code> element.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">disableDTD</td>
-    <td valign="top">
-      Flag to disable DTD support. DTD support is needed to 
-      validate XSD files themselves, amongst others.
-    </td>
-    <td valign="top" align="center">No - default false</td>
+    <td>disableDTD</td>
+    <td>Flag to disable DTD support. DTD support is needed to validate XSD files themselves, amongst
+      others.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">fails on a error if set to true (defaults to true).</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>fails on a error if set to <q>true</q>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file(s) you want to check. (optionally can use an embedded fileset)</td>
-    <td valign="top" align="center">No</td>
+    <td>file</td>
+    <td>the file(s) you want to check (optionally use an embedded fileset).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">fullchecking</td>
-    <td valign="top">
-      enable full schema checking. Slow but strict.
-    </td>
-    <td valign="top" align="center">No - default true</td>
-  </tr>
-  
-  <tr>
-    <td valign="top">lenient</td>
-    <td valign="top">
-      if true, only check the XML document is well formed
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>fullchecking</td>
+    <td>enable full schema checking. Slow but strict.</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">noNamespaceFile</td>
-    <td valign="top">
-      filename of a no-namespace XSD file to provide the 
-      schema for no-namespace XML content.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>lenient</td>
+    <td>if <q>true</q>, only check the XML document is well formed</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">noNamespaceURL</td>
-    <td valign="top">
-      URL of a no-namespace XSD file to provide the 
-      schema for no-namespace XML content.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>noNamespaceFile</td>
+    <td>filename of a no-namespace XSD file to provide the schema for no-namespace XML content</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">warn</td>
-    <td valign="top">log parser warn events.</td>
-    <td align="center" valign="top">No</td>
+    <td>noNamespaceURL</td>
+    <td>URL of a no-namespace XSD file to provide the schema for no-namespace XML content</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>warn</td>
+    <td>log parser warn events</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3><a name="nested">Nested Elements</a></h3>
-
+<h3 id="nested">Parameters specified as nested elements</h3>
 
 <h4>schema</h4>
-<p>
-Identify the name and location of a schema that may be used in validating
-the document(s).
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Identify the name and location of a schema that may be used in validating the document(s).</p>
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">namespace</td>
-    <td valign="top">URI of the schema namespace</td>
-    <td align="center" valign="top">Yes</td>
+    <td>namespace</td>
+    <td>URI of the schema namespace</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">URL of the schema</td>
-    <td align="center" valign="top">One of url or file is required</td>
+    <td>url</td>
+    <td>URL of the schema</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">file of the schema</td>
-    <td align="center" valign="top">One of url or file is required</td>
+    <td>file</td>
+    <td class="left">file of the schema</td>
   </tr>
 </table>
 
 <h4>dtd</h4>
-<p>
-<tt>&lt;dtd&gt;</tt> is used to specify different locations for DTD resolution.
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p><code>&lt;dtd&gt;</code> is used to specify different locations for DTD resolution.</p>
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">publicId</td>
-    <td valign="top">Public ID of the DTD to resolve</td>
-    <td align="center" valign="top">Yes</td>
+    <td>publicId</td>
+    <td>Public ID of the DTD to resolve</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">location</td>
-    <td valign="top">Location of the DTD to use, which can be a file,
+    <td>location</td>
+    <td>Location of the DTD to use, which can be a file,
     a resource, or a URL</td>
-    <td align="center" valign="top">Yes</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h4>xmlcatalog</h4>
-<p>The <a href="../Types/xmlcatalog.html"><tt>&lt;xmlcatalog&gt;</tt></a>
-element is used to perform entity resolution.</p>
+<p>The <a href="../Types/xmlcatalog.html"><code>&lt;xmlcatalog&gt;</code></a> element is used to
+perform entity resolution.</p>
 <h4>attribute</h4>
-<p>The <tt>&lt;attribute&gt;</tt> element is used to set parser features.<br>
-Features usable with the xerces parser are defined here :
- <a href="http://xml.apache.org/xerces-j/features.html">Setting features</a><br>
-
-SAX features are defined here:
- <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"><tt>http://xml.org/sax/features/</tt></a><br>
- </p>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+<p>The <code>&lt;attribute&gt;</code> element is used to set parser features.<br/>Features usable
+with the Xerces parser are defined here: <a href="https://xml.apache.org/xerces-j/features.html"
+target="_top">Setting features</a><br/>SAX features are defined
+here: <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
+target="_top"><code>http://xml.org/sax/features/</code></a></p>
+<table class="attr">
+  <tr>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the feature</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The boolean value of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <td>value</td>
+    <td>The boolean value of the feature</td>
+    <td>Yes</td>
   </tr>
 </table>
-</p>
 
 <h4>property</h4>
-<p>The <tt>&lt;property&gt;</tt> element is used to set properties.
-These properties are defined here for the xerces XML parser implementation :
- <a href="http://xml.apache.org/xerces-j/properties.html">XML Parser properties</a>
-Properties can be used to set the schema used to validate the XML file.
+<p>The <code>&lt;property&gt;</code> element is used to set properties.  These properties are
+defined here for the Xerces XML parser
+implementation: <a href="https://xml.apache.org/xerces-j/properties.html" target="_top">XML Parser
+properties</a>. Properties can be used to set the schema used to validate the XML file.
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the feature</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The string value of the property</td>
-    <td align="center" valign="top">Yes</td>
+    <td>value</td>
+    <td>The string value of the property</td>
+    <td>Yes</td>
   </tr>
 </table>
-</p>
-
 
 <h3>Examples</h3>
+<p>Validate a document against an XML schema. The document does not declare any schema itself, which
+is why the <var>noNamespaceFile</var> is needed.</p>
 <pre>
-    &lt;schemavalidate
-      noNamespaceFile="document.xsd"
-      file="xml/endpiece.xml"&gt;
-    &lt;/schemavalidate&gt;
-</pre>
-Validate a document against an XML schema. The document does not declare
-any schema itself, which is why the <tt>noNamespaceFile</tt> is needed. 
-<pre>
-    &lt;presetdef name="validate-soap"&gt;
-      &lt;schemavalidate&gt;
-        &lt;schema namespace="http://schemas.xmlsoap.org/ws/2003/03/addressing"
-          file="${soap.dir}/ws-addressing.xsd" /&gt;
-        &lt;schema namespace="http://www.w3.org/2003/05/soap-envelope"
-          file="${soap.dir}/soap12.xsd" /&gt;
-        &lt;schema namespace="http://schemas.xmlsoap.org/wsdl/"
-          file="${soap.dir}/wsdl.xsd" /&gt;
-        &lt;schema namespace="http://www.w3.org/2001/XMLSchema"
-          file="${soap.dir}/XMLSchema.xsd" /&gt;
-        &lt;/schemavalidate&gt;
-    &lt;/presetdef&gt;
-</pre>
-Declare a new preset task, <tt>&lt;validate-soap&gt;</tt>, that validates
-XSD and WSDL documents against the relevant specifications. 
-To validate XSD documents, you also need XMLSchema.dtd and datatypes.dtd in 
-the same directory as XMLSchema.xsd, or pointed to via the catalog. All
-these files can be fetched from <a href="http://www.w3.org/2001/XMLSchema">
-the W3C</a>. 
-<pre>
-    &lt;validate-soap file="xml/test.xsd"/&gt;
-</pre>
-Use the preset task defined above to validate an XML Schema document.
-<br>
+&lt;schemavalidate noNamespaceFile="document.xsd"
+                file="xml/endpiece.xml"/&gt;</pre>
 
+<p>Declare a new preset task, <code>&lt;validate-soap&gt;</code>, that validates XSD and WSDL
+documents against the relevant specifications. To validate XSD documents, you also
+need <samp>XMLSchema.dtd</samp> and <samp>datatypes.dtd</samp> in the same directory
+as <samp>XMLSchema.xsd</samp>, or pointed to via the catalog. All these files can be fetched
+from <a href="https://www.w3.org/2001/XMLSchema" target="_top">W3C</a>.</p>
+<pre>
+&lt;presetdef name="validate-soap"&gt;
+  &lt;schemavalidate&gt;
+    &lt;schema namespace="http://schemas.xmlsoap.org/ws/2003/03/addressing"
+            file="${soap.dir}/ws-addressing.xsd"/&gt;
+    &lt;schema namespace="http://www.w3.org/2003/05/soap-envelope"
+            file="${soap.dir}/soap12.xsd"/&gt;
+    &lt;schema namespace="http://schemas.xmlsoap.org/wsdl/"
+            file="${soap.dir}/wsdl.xsd"/&gt;
+    &lt;schema namespace="http://www.w3.org/2001/XMLSchema"
+            file="${soap.dir}/XMLSchema.xsd"/&gt;
+    &lt;/schemavalidate&gt;
+&lt;/presetdef&gt;</pre>
+
+<p>Use the preset task defined above to validate an XML Schema document.</p>
+<pre>&lt;validate-soap file="xml/test.xsd"/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/scp.html b/manual/Tasks/scp.html
index 47a3cee..e9e4a33 100644
--- a/manual/Tasks/scp.html
+++ b/manual/Tasks/scp.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,313 +15,296 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>SCP Task</title>
 </head>
 
 <body>
 
-<h2><a name="scp">SCP</a></h2>
+<h2 id="scp">SCP</h2>
+<p><em>Since Apache Ant 1.6</em></p>
 <h3>Description</h3>
 
-<p><em>since Apache Ant 1.6</em></p>
-
 <p>Copies a file or FileSet to or from a (remote) machine running an SSH daemon.
-FileSet <i>only</i> works for copying files from the local machine to a
-remote machine.</p>
+FileSet <em>only</em> works for copying files from the local machine to a remote machine.</p>
 
-<p><b>Note:</b> This task depends on external libraries not included
-in the Ant distribution.  See <a
-href="../install.html#librarydependencies">Library Dependencies</a>
-for more information.  This task has been tested with jsch-0.1.2 and later.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Ant
+distribution.  See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.  This task has been tested with <code>jsch-0.1.2</code> and later.</p>
 
 <p>See also the <a href="sshexec.html">sshexec task</a></p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to copy.  This can be a local path or a
-    remote path of the form <i>user[:password]@host:/directory/path</i>.
-    <i>:password</i> can be omitted if you use key based
-    authentication or specify the password attribute.  The way remote
-    path is recognized is whether it contains @ character or not. This
-    will not work if your localPath contains @ character.</td>
-    <td valign="top" align="center">Yes, unless a nested
-    <code>&lt;fileset&gt;</code> element is used.</td>
+    <td>file</td>
+    <td>The file to copy.  This can be a local path or a remote path of the
+      form <samp>user[:password]@host:/directory/path</samp>.  <samp>:password</samp> can be omitted
+      if you use key based authentication or specify the <var>password</var> attribute.  The way
+      remote path is recognized is whether it contains <q>@</q> character or not. This will not work
+      if your <var>localPath</var> contains <q>@</q> character.</td>
+    <td>Yes, unless a nested <code>&lt;fileset&gt;</code> element is used</td>
   </tr>
   <tr>
-    <td valign="top">localFile</td>
-    <td valign="top">This is an alternative to the file attribute. But
-    this must always point to a local file. The reason this was added
-    was that when you give file attribute it is treated as remote if
-    it contains @ character. This character can exist also in local
+    <td>localFile</td>
+    <td>This is an alternative to the <var>file</var> attribute. But this must always point to a
+      local file. The reason this was added was that when you give file attribute it is treated as
+      remote if it contains <q>@</q> character. This character can exist also in local
+      paths.  <em>since Ant 1.6.2</em></td>
+    <td>Alternative to <var>file</var> attribute</td>
+  </tr>
+  <tr>
+    <td>remoteFile</td>
+    <td>This is an alternative to the <var>file</var> attribute. But this must always point to a
+      remote file.  <em>since Ant 1.6.2</em></td>
+    <td>Alternative to <var>file</var> attribute</td>
+  </tr>
+  <tr>
+    <td>todir</td>
+    <td>The directory to copy to.  This can be a local path or a remote path of the
+      form <samp>user[:password]@host:/directory/path</samp>.  <samp>:password</samp> can be omitted
+      if you use key based authentication or specify the <var>password</var> attribute.  The way
+      remote path is recognized is whether it contains <q>@</q> character or not. This will not work
+      if your <var>localPath</var> contains <q>@</q> character.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>localTodir</td>
+    <td>This is an alternative to the <var>todir</var> attribute. But this must always point to a
+    local directory. The reason this was added was that when you give <var>todir</var> attribute it
+    is treated as remote if it contains <q>@</q> character. This character can exist also in local
     paths.  <em>since Ant 1.6.2</em></td>
-    <td valign="top" align="center">Alternative to file attribute.</td>
+    <td>Alternative to <var>todir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">remoteFile</td>
-    <td valign="top">This is an alternative to the file attribute. But
-    this must always point to a remote file.  <em>since Ant 1.6.2</em></td>
-    <td valign="top" align="center">Alternative to file attribute.</td>
+    <td>localTofile</td>
+    <td>Changes the file name to the given name while receiving it, only useful if receiving a
+      single file.  <em>since Ant 1.6.2</em></td>
+    <td>Alternative to <var>todir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">The directory to copy to.  This can be a local path
-    or a remote path of the form <i>user[:password]@host:/directory/path</i>.
-    <i>:password</i> can be omitted if you use key based
-    authentication or specify the password attribute.  The way remote
-    path is recognized is whether it contains @ character or not. This
-    will not work if your localPath contains @ character.</td>
-    <td valian="top" align="center">Yes</td>
+    <td>remoteTodir</td>
+    <td>This is an alternative to the <var>todir</var> attribute. But this must always point to a
+      remote directory.  <em>since Ant 1.6.2</em></td>
+    <td>Alternative to <var>todir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">localTodir</td>
-    <td valign="top">This is an alternative to the todir
-    attribute. But this must always point to a local directory. The
-    reason this was added was that when you give todir attribute it is
-    treated as remote if it contains @ character. This character can
-    exist also in local paths.  <em>since Ant 1.6.2</em></td>
-    <td valian="top" align="center">Alternative to todir attribute.</td>
+    <td>remoteTofile</td>
+    <td>Changes the file name to the given name while sending it, only useful if sending a single
+      file.  <em>since Ant 1.6.2</em></td>
+    <td>Alternative to <var>todir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">localTofile</td>
-    <td valign="top">Changes the file name to the given name while
-    receiving it, only useful if receiving a single file.  <em>since
-    Ant 1.6.2</em></td>
-    <td valian="top" align="center">Alternative to todir attribute.</td>
+    <td>port</td>
+    <td>The port to connect to on the remote host.</td>
+    <td>No; defaults to <q>22</q></td>
   </tr>
   <tr>
-    <td valign="top">remoteTodir</td>
-    <td valign="top">This is an alternative to the todir
-    attribute. But this must always point to a remote directory.
-    <em>since Ant 1.6.2</em></td>
-    <td valian="top" align="center">Alternative to todir attribute.</td>
+    <td>trust</td>
+    <td>This trusts all unknown hosts if set to <q>yes</q>
+      or <q>true</q>.<br/><strong>Note</strong>: If you set this to <q>false</q> (the default), the
+      host you connect to must be listed in your <var>knownhosts</var> file, this also implies that
+      the file exists.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">remoteTofile</td>
-    <td valign="top">Changes the file name to the given name while
-    sending it, only useful if sending a single file.  <em>since
-    Ant 1.6.2</em></td>
-    <td valian="top" align="center">Alternative to todir attribute.</td>
+    <td>knownhosts</td>
+    <td>This sets the known hosts file to use to validate the identity of the remote host.  This
+      must be a SSH2 format file.  SSH1 format is not supported.</td>
+    <td>No; defaults to <samp>${user.home}/.ssh/known_hosts</samp></td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">The port to connect to on the remote host.</td>
-    <td valian="top" align="center">No, defaults to 22.</td>
+    <td>failonerror</td>
+    <td>Whether to halt the build if the transfer fails.</td>
+     <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">trust</td>
-    <td valign="top">This trusts all unknown hosts if set to yes/true.<br>
-      <strong>Note</strong> If you set this to false (the default), the
-      host you connect to must be listed in your knownhosts file, this
-      also implies that the file exists.</td>
-    <td valian="top" align="center">No, defaults to No.</td>
+    <td>password</td>
+    <td>The password.</td>
+    <td>Yes, unless you are using key based authentication or the password has been given in the
+     file or <var>todir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">knownhosts</td>
-    <td valign="top">This sets the known hosts file to use to validate
-    the identity of the remote host.  This must be a SSH2 format file.
-    SSH1 format is not supported.</td>
-    <td valian="top" align="center">No, defaults to
-    ${user.home}/.ssh/known_hosts.</td>
+    <td>keyfile</td>
+    <td>Location of the file holding the private key.</td>
+    <td>Yes, if you are using key based authentication</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-     <td valign="top">Whether to halt the build if the transfer fails.
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>passphrase</td>
+    <td>Passphrase for your private key.</td>
+    <td>No; defaults to an empty string</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-     <td valign="top">The password.</td>
-     <td valign="top" align="center">Not if you are using key based
-     authentication or the password has been given in the file or
-     todir attribute.</td>
+    <td>sshConfig</td>
+    <td>Location of the file holding the OpenSSH style configuration (e.g. <code>${user.home}/.ssh/config</code>).
+        The username and the key file are read from the configuration file,
+        unless they are already specified in the task parameters.
+        <em>since Ant 1.10.8</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keyfile</td>
-     <td valign="top">Location of the file holding the private key.</td>
-     <td valign="top" align="center">Yes, if you are using key based
-     authentication.</td>
+    <td>verbose</td>
+    <td>Determines whether SCP outputs verbosely to the user. Currently this means outputting
+      dots/stars showing the progress of a file transfer.  <em>since Ant 1.6.2</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">passphrase</td>
-     <td valign="top">Passphrase for your private key.</td>
-     <td valign="top" align="center">No, defaults to an empty string.</td>
+    <td>sftp</td>
+    <td>Determines whether SCP uses the sftp protocol.  The sftp protocol is the file transfer
+      protocol of SSH2.  It is recommended that this be set to <q>true</q> if you are copying to/from
+      a server that doesn't support scp1. <em>since Ant 1.7</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Determines whether SCP outputs verbosely to the
-    user. Currently this means outputting dots/stars showing the
-    progress of a file transfer.  <em>since Ant 1.6.2</em></td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>preserveLastModified</td>
+    <td>Determines whether the last modification timestamp of downloaded files is preserved.  It
+      only works when transferring from a remote to a local system and probably doesn't work with a
+      server that doesn't support SSH2.  <em>since Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">sftp</td>
-    <td valign="top">Determines whether SCP uses the sftp protocol.
-    The sftp protocol is the file transfer protocol of SSH2.  It is
-    recommended that this be set to true if you are copying to/from a
-    server that doesn't support scp1. <em>since Ant 1.7</em></td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>filemode</td>
+    <td>A 3 digit octal string, specify the user, group and other modes in the standard Unix
+      fashion.  Only applies to uploaded files.  Note the actual permissions of the remote file will
+      be governed by this setting and the <code>UMASK</code> on the remote server. <em>since Ant
+      1.9.5</em>.</td>
+    <td>No; default is <q>644</q></td>
   </tr>
   <tr>
-    <td valign="top">preserveLastModified</td>
-    <td valign="top">Determines whether the last modification
-    timestamp of downloaded files is preserved.  It only works when
-    transferring from a remote to a local system and probably doesn't
-    work with a server that doesn't support SSH2.  <em>since Ant
-    1.8.0</em></td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>dirmode</td>
+    <td>A 3 digit octal string, specify the user, group and other modes in the standard Unix
+      fashion.  Only applies to uploaded dirs.  Note the actual permissions of the remote dir will
+      be governed by this setting and the <code>UMASK</code> on the remote server. <em>since Ant
+      1.9.5</em>.</td>
+    <td>No; default is <q>755</q></td>
   </tr>
   <tr>
-    <td valign="top">filemode</td>
-    <td valign="top">A 3 digit octal string, specify the user, group
-      and other modes in the standard Unix fashion.  Only applies to
-      uploaded files.  Note the actual permissions of the remote
-      file will be governed by this setting and the UMASK on the
-      remote server. Default is 644. <em>since Ant 1.9.5</em>.</td>
-    <td align="center" valign="top">No</td>
+    <td>serverAliveIntervalSeconds</td>
+    <td>Sets a timeout interval in seconds after which if no data has been received from the server,
+      the task will send a message through the encrypted channel to request a response from the
+      server.  <em>since Ant 1.9.7</em></td>
+    <td>No, the default is <q>0</q>, indicating that these messages will not be sent to the
+      server</td>
   </tr>
   <tr>
-    <td valign="top">dirmode</td>
-    <td valign="top">A 3 digit octal string, specify the user, group
-      and other modes in the standard Unix fashion.  Only applies to
-      uploaded dirs.  Note the actual permissions of the remote
-      dir will be governed by this setting and the UMASK on the
-      remote server. Default is 755. <em>since Ant 1.9.5</em>.</td>
-    <td align="center" valign="top">No</td>
+    <td>serverAliveCountMax</td>
+    <td>The number of server alive messages which may be sent without receiving any messages back
+      from the server. Only used if <var>serverAliveIntervalSeconds</var> is
+      not <q>0</q>.  <em>since Ant 1.9.7</em></td>
+    <td>No; defaults to <q>3</q></td>
   </tr>
   <tr>
-    <td valign="top">serverAliveIntervalSeconds</td>
-    <td valign="top">Sets a timeout interval in seconds after which if no data has
-      been received from the server, the task will send a message through
-      the encrypted channel to request a response from the server.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No, the default is 0, indicating
-      that these messages will not be sent to the server</td>
-  </tr>
-  <tr>
-    <td valign="top">serverAliveCountMax</td>
-    <td valign="top">The number of server alive messages which may be
-      sent without receiving any messages back from the server. Only
-      used if serverAliveIntervalSeconds is not 0.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No, defaults to 3</td>
-  </tr>
-  <tr>
-    <td valign="top">compressed</td>
-    <td valign="top">Whether to enable compression during transfer.
-      <em>since Ant 1.9.8</em></td>
-    <td align="center" valign="top">No, defaults to false</td>
+    <td>compressed</td>
+    <td>Whether to enable compression during transfer.  <em>since Ant 1.9.8</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
-<h4>fileset or resource collections</h4>
- <p><a href="../Types/fileset.html">FileSet</a>s or <a href="../Types/resources.html#collection">Resource Collection</a>s are used to select
- groups of files to copy. To use a fileset or a resource collection, the <code>todir</code> attribute must be set.</p>
+<h4>resource collections</h4>
+<p><a href="../Types/fileset.html">FileSet</a>s
+or other <a href="../Types/resources.html#collection">resource collections</a> are used to select groups
+of files to copy. To use a fileset or a resource collection, the <var>todir</var> attribute must be
+set.</p>
 
-Prior to Ant 1.9.7 only &lt;fileset&gt; has been supported as a nested element.
+<p>Prior to Ant 1.9.7 only <code>&lt;fileset&gt;</code> has been supported as a nested element.</p>
+
+<h4 id="additionalConfig">additionalConfig</h4>
+
+<p><em>since Ant 1.10.10</em></p>
+
+<p>Adds configuration settings for the JSch Session created that are
+  not directly supported by specific Ant attributes.</p>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>key</td>
+    <td>The key of the configuration setting.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>The value of the configuration setting.</td>
+    <td>Yes</td>
+  </tr>
+</table>
 
 <h3>Examples</h3>
-<p><b>Copy a single local file to a remote machine</b></p>
-<pre>
-  &lt;scp file=&quot;myfile.txt&quot; todir=&quot;user:password@somehost:/home/chuck&quot;/&gt;
-</pre>
+<p>Copy a single local file to a remote machine:</p>
+<pre>&lt;scp file=&quot;myfile.txt&quot; todir=&quot;user:password@somehost:/home/chuck&quot;/&gt;</pre>
 
-<p><b>Copy a single local file to a remote machine with separate
-password attribute</b></p>
-<pre>
-  &lt;scp file=&quot;myfile.txt&quot; todir=&quot;user@somehost:/home/chuck&quot; password=&quot;password&quot;/&gt;
-</pre>
+<p>Copy a single local file to a remote machine with separate <var>password</var>
+attribute:</p>
+<pre>&lt;scp file=&quot;myfile.txt&quot; todir=&quot;user@somehost:/home/chuck&quot; password=&quot;password&quot;/&gt;</pre>
 
-<p><b>Copy a single local file to a remote machine using key base
-authentication.</b></p>
+<p>Copy a single local file to a remote machine using key base authentication:</p>
 <pre>
-  &lt;scp file=&quot;myfile.txt&quot;
-       todir=&quot;user@somehost:/home/chuck&quot; 
-       keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
-       passphrase=&quot;my extremely secret passphrase&quot;
-  /&gt;
-</pre>
+&lt;scp file=&quot;myfile.txt&quot;
+     todir=&quot;user@somehost:/home/chuck&quot;
+     keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
+     passphrase=&quot;my extremely secret passphrase&quot;/&gt;</pre>
 
-<p><b>Copy a single remote file to a local directory</b></p>
-<pre>
-  &lt;scp file=&quot;user:password@somehost:/home/chuck/myfile.txt&quot; todir=&quot;../some/other/dir&quot;/&gt;
-</pre>
+<p>Copy a single remote file to a local directory:</p>
+<pre>&lt;scp file=&quot;user:password@somehost:/home/chuck/myfile.txt&quot; todir=&quot;../some/other/dir&quot;/&gt;</pre>
 
-<p><b>Copy a remote directory to a local directory</b></p>
-<pre>
-  &lt;scp file=&quot;user:password@somehost:/home/chuck/*&quot; todir=&quot;/home/sara&quot;/&gt;
-</pre>
+<p>Copy a remote directory to a local directory:</p>
+<pre>&lt;scp file=&quot;user:password@somehost:/home/chuck/*&quot; todir=&quot;/home/sara&quot;/&gt;</pre>
 
-<p><b>Copy a local directory to a remote directory</b></p>
+<p>Copy a local directory to a remote directory:</p>
 <pre>
-  &lt;scp todir=&quot;user:password@somehost:/home/chuck/&quot;&gt;
-    &lt;fileset dir=&quot;src_dir&quot;/&gt;
-  &lt;/scp&gt;
-</pre>
-<p><b>Copy a set of files to a directory</b></p>
+&lt;scp todir=&quot;user:password@somehost:/home/chuck/&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot;/&gt;
+&lt;/scp&gt;</pre>
+
+<p>Copy a set of files to a directory:</p>
 <pre>
-  &lt;scp todir=&quot;user:password@somehost:/home/chuck&quot;&gt;
+&lt;scp todir=&quot;user:password@somehost:/home/chuck&quot;&gt;
+  &lt;fileset dir=&quot;src_dir&quot;&gt;
+    &lt;include name=&quot;**/*.java&quot;/&gt;
+  &lt;/fileset&gt;
+&lt;/scp&gt;</pre>
+
+<p>Copy a set of files to a remote directory in reverse last-modified order:</p>
+<pre>
+&lt;scp todir=&quot;user:password@somehost:/home/chuck&quot;&gt;
+  &lt;sort&gt;
+    &lt;reverse&gt;
+      &lt;date/&gt;
+    &lt;/reverse&gt;
     &lt;fileset dir=&quot;src_dir&quot;&gt;
-      &lt;include name=&quot;**/*.java&quot;/&gt;
+      &lt;include name=&quot;**/*&quot;/&gt;
     &lt;/fileset&gt;
-  &lt;/scp&gt;
-</pre>
-<p><b>Copy a set of files to a remote directory in reverse last-modified order</b></p>
-<pre>
-  &lt;scp todir=&quot;user:password@somehost:/home/chuck&quot;&gt;
-    &lt;sort&gt;
-      &lt;reverse&gt;
-        &lt;date /&gt;
-      &lt;/reverse&gt;
-      &lt;fileset dir=&quot;src_dir&quot;&gt;
-        &lt;include name=&quot;**/*&quot; /&gt;
-      &lt;/fileset&gt;
-    &lt;/sort&gt;
-  &lt;/scp&gt;
-</pre>
+  &lt;/sort&gt;
+&lt;/scp&gt;</pre>
 
-<p><strong>Security Note:</strong>  Hard coding passwords and/or usernames
-in scp task can be a serious security hole.  Consider using variable
-substitution and include the password on the command line.  For example:
-<p>
-<pre>
-    &lt;scp todir=&quot;${username}:${password}@host:/dir&quot; ...&gt;
-</pre>
-Invoking ant with the following command line:
-<pre>
-    ant -Dusername=me -Dpassword=mypassword target1 target2
-</pre>
+<p><strong>Security Note</strong>: Hardcoding passwords and/or usernames in <code>scp</code> task
+can be a serious security hole.  Consider using variable substitution and include the password on
+the command line.  For example:</p>
+<pre>&lt;scp todir=&quot;${username}:${password}@host:/dir&quot; ...&gt;</pre>
 
-Is slightly better, but the username/password is exposed to all users on an Unix
-system (via the ps command). The best approach is to use the
-<code>&lt;input&gt;</code> task and/or retrieve the password from a (secured)
-.properties file.
+<p>Invoking Ant with the following command line:</p>
+<pre class="input">ant -Dusername=me -Dpassword=mypassword target1 target2</pre>
+<p>is slightly better, but the username/password is exposed to all users on an Unix system (via
+the <kbd>ps</kbd> command). The best approach is to use the <code>&lt;input&gt;</code> task and/or
+retrieve the password from a (secured) <samp>.properties</samp> file.</p>
 
-<p>
-
-<p><strong>Unix Note:</strong> File permissions are not retained when files
-are downloaded; they end up with the default <code>UMASK</code> permissions
-instead. This is caused by the lack of any means to query or set file
-permissions in the current Java runtimes. If you need a permission-
-preserving copy function, use <code>&lt;exec executable="scp" ... &gt;</code>
-instead.
-</p>
-
-
+<p><strong>Unix Note</strong>: File permissions are not retained when files are downloaded; they end
+up with the default <code>UMASK</code> permissions instead. This is caused by the lack of any means
+to query or set file permissions in the current Java runtimes. If you need a permission-preserving
+copy function, use <code>&lt;exec executable="scp" ... &gt;</code> instead.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/script.html b/manual/Tasks/script.html
index fb00822..043d4c6 100644
--- a/manual/Tasks/script.html
+++ b/manual/Tasks/script.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,150 +15,127 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"></meta>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Script Task</title>
 </head>
 
 <body>
 
-<h2><a name="script">Script</a></h2>
+<h2 id="script">Script</h2>
 <h3>Description</h3>
-  <p>Execute a script in a
-    <a href="http://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
-    or
-    <a href="https://scripting.dev.java.net">JSR 223</a>  supported language.
-  </p>
-  <p><b>Note:</b>
-    This task depends on external libraries not included in the Apache Ant distribution.
-    See <a href="../install.html#librarydependencies">Library Dependencies</a>
-    for more information.
-  </p>
-  <p>
-    The task may use the BSF scripting manager or the JSR 223 manager that
-    is included in JDK6 and higher. This is controlled by the <code>manager</code>
-    attribute. The JSR 223 scripting manager is indicated by "javax".
-  </p>
-  <p>All items (tasks, targets, etc) of the running project are
-    accessible from the script, using either their <code>name</code> or
-    <code>id</code> attributes (as long as their names are considered
-    valid Java identifiers, that is).
-    This is controlled by the "setbeans" attribute of the task.
-    The name "project" is a pre-defined reference to the Project, which can be
-    used instead of the project name. The name "self" is a pre-defined reference to the actual
-    <code>&lt;script&gt;</code>-Task instance.<br>From these objects you have access to the Ant Java API, see the
-<a href="../api/index.html">JavaDoc</a> (especially for
-<a href="../api/org/apache/tools/ant/Project.html">Project</a> and
-<a href="../api/org/apache/tools/ant/taskdefs/optional/Script.html">Script</a>) for more information.</p>
-<p>If you are using JavaScript under BSF, a good resource is <a target="_blank" href="http://www.mozilla.org/rhino/doc.html">
-http://www.mozilla.org/rhino/doc.html</a> as we are using their JavaScript interpreter.</p>
+<p>Execute a script in a <a href="https://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
+or <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr223/223ChangeLog.html"
+target="_top">JSR 223</a> supported language.
+</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution.  See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
+<p>The task may use the BSF scripting manager or the JSR 223 manager that is included in the JDK.
+This is controlled by the <var>manager</var> attribute. The JSR 223 scripting manager is
+indicated by <q>javax</q>.</p>
+<p>All items (tasks, targets, etc) of the running project are accessible from the script, using
+either their <var>name</var> or <var>id</var> attributes (as long as their names are considered
+valid Java identifiers, that is).  This is controlled by the <var>setbeans</var> attribute of the
+task.  The name <code class="code">project</code> is a pre-defined reference to the Project, which
+can be used instead of the project name. The name <code class="code">self</code> is a pre-defined
+reference to the actual <code>&lt;script&gt;</code>-Task instance.<br/>From these objects you have
+access to the Ant Java API, see the <a href="../api/index.html">JavaDoc</a> (especially
+for <a href="../api/org/apache/tools/ant/Project.html">Project</a>
+and <a href="../api/org/apache/tools/ant/taskdefs/optional/Script.html">Script</a>) for more
+information.</p>
+<p>If you are using JavaScript under BSF, a good resource
+is <a href="https://www.mozilla.org/rhino/doc.html"
+target="_top">https://www.mozilla.org/rhino/doc.html</a> as we are using their JavaScript
+interpreter.</p>
 <p>Scripts can do almost anything a task written in Java could do.</p>
-<p>Rhino provides a special construct - the <i>JavaAdapter</i>. With that you can
-create an object which implements several interfaces, extends classes and for which you
-can overwrite methods. Because this is an undocumented feature (yet), here is the link
-to an explanation: <a href="http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&newwindow=1&frame=right&th=610d2db45c0756bd&seekm=391EEC3C.5236D929%40yahoo.com#link2">
-Groups@Google: "Rhino, enum.js, JavaAdapter?"</a> by Norris Boyd in the newsgroup
-<i>netscape.public.mozilla.jseng</i>.</p>
+<p>Rhino provides a special construct&mdash;the <code>JavaAdapter</code>. With that you can create
+an object which implements several interfaces, extends classes and for which you can overwrite
+methods. Because this is an undocumented feature (yet), here is the link to an
+explanation: <a href="https://groups.google.com/forum/#!msg/netscape.public.mozilla.jseng/YlRQE0OvM8c/F8Mvq-XkpxcJ"
+target="_top">Google Groups: "Rhino, enum.js, JavaAdapter?"</a>  by Norris Boyd in the
+newsgroup <em>netscape.public.mozilla.jseng</em>.</p>
 
-<p>If you are creating Targets programmatically, make sure you set the
-Location to a useful value.  In particular all targets should have
-different location values.</p>
+<p>If you are creating Targets programmatically, make sure you set the Location to a useful value.
+In particular all targets should have different location values.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">language</td>
-    <td valign="top">The programming language the script is written in.
-      Must be a supported Apache BSF or JSR 223 language</td>
-    <td valign="top" align="center">Yes</td>
+    <td>language</td>
+    <td>The programming language the script is written in.  Must be a supported Apache BSF or JSR
+      223 language</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">manager</td>
-    <td valign="top">
-      <em>Since: Ant 1.7. </em>
-      The script engine manager to use. This can have
-      one of three values ("auto", "bsf" or "javax").
-      The default value is "auto".
-      <dl>
-        <li>"bsf" use the BSF scripting manager to run
-          the language.</li>
-        <li>"javax" use the <em>javax.scripting</em> manager
-          to run the language. (This will only work for JDK6 and higher).</li>
-        <li>"auto" use the BSF engine if it exists,
-          otherwise use the <em>javax.scripting</em> manager.</li>
-      </dl>
+    <td>manager</td>
+    <td>
+      <em>Since Ant 1.7</em>.  The script engine manager to use. This can have one of three
+      values: <q>auto</q>, <q>bsf</q> or <q>javax</q>.
+      <ul>
+        <li><q>bsf</q> use the BSF scripting manager to run the language.</li>
+        <li><q>javax</q> use the <code>javax.scripting</code> manager to run the language.</li>
+        <li><q>auto</q> use the BSF engine if it exists, otherwise use
+          the <code>javax.scripting</code> manager.</li>
+      </ul>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; default is <q>auto</q></td>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">The location of the script as a file, if not inline</td>
-    <td valign="top" align="center">No</td>
+    <td>src</td>
+    <td>The location of the script as a file, if not inline</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">setbeans</td>
-    <td valign="top">
-      This attribute controls whether to set variables for
-      all properties, references and targets in the running script.
-      If this attribute is false, only the the "project" and "self" variables are set.
-      If this attribute is true all the variables are set. The default value of this
-      attribute is "true".  <em>Since Ant 1.7</em>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>encoding</td>
+    <td>The encoding of the script as a file. <em>Since Ant 1.10.2</em>.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">
-      The classpath to pass into the script. <em>Since Ant 1.7</em>
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>setbeans</td>
+    <td>This attribute controls whether to set variables for all properties, references and targets
+      in the running script.  If this attribute is <q>false</q>, only the <code>project</code> and
+      <code>self</code> variables are set.  If this attribute is <q>true</q> all the variables are
+      set. <em>Since Ant 1.7</em></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use, given as a
-       <a href="../using.html#references">reference</a> to a path defined elsewhere.
+    <td>classpath</td>
+    <td>The classpath to pass into the script. <em>Since Ant 1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a path
+    defined elsewhere.
     <em>Since Ant 1.7</em></td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>classpath</h4>
-  <p><em>Since Ant 1.7</em></p>
-<p>
-  <code>Script</code>'s <code>classpath</code> attribute is a 
-  <a href="../using.html#path">path-like structure</a> and can also be set via a nested
-  <code>&lt;classpath&gt;</code> element.
-  <p>
-    If a classpath is set, it will be used as the current thread
-    context classloader, and
-    as the classloader given to the BSF manager. 
-    This means that it can be used to specify
-    the classpath containing the language implementation for BSF
-    or for JSR 223 managers.
-    This can be useful if one wants
-    to keep ${user.home}/.ant/lib free of lots of scripting language
-    specific jar files.
-  </p>
-  <p>
-    <b>NB: (Since Ant 1.7.1)</b>
-    This classpath <em>can</em> be used to
-    specify the location of
-    the BSF jar file and/or languages
-    that have engines in the BSF jar file. This includes the
-    javascript, jython, netrexx and jacl languages.
-  </p>
+<p><em>Since Ant 1.7</em></p>
+<p><code>Script</code>'s <var>classpath</var> attribute is a <a href="../using.html#path">path-like
+structure</a> and can also be set via a nested <code>&lt;classpath&gt;</code> element.
 </p>
+<p>If a classpath is set, it will be used as the current thread context classloader, and as the
+classloader given to the BSF manager.  This means that it can be used to specify the classpath
+containing the language implementation for BSF or for JSR 223 managers.  This can be useful if one
+wants to keep <samp>${user.home}/.ant/lib</samp> free of lots of scripting language specific jar
+files.</p>
+<p><strong>Note</strong>: (<em>since Ant 1.7.1</em>) This classpath <em>can</em> be used to specify
+the location of the BSF jar file and/or languages that have engines in the BSF jar file. This
+includes the <q>javascript</q>, <q>jython</q>, <q>netrexx</q> and <q>jacl</q> languages.</p>
 <h3>Examples</h3>
-The following snippet shows use of five different languages:
-  <blockquote><pre>
+<p>The following snippet shows use of five different languages:</p>
+<pre>
     &lt;property name="message" value="Hello world"/&gt;
 
     &lt;script language="groovy"&gt;
@@ -178,74 +156,48 @@
 
     &lt;script language="jython"&gt;
 print "message is %s" % message
-    &lt;/script&gt;
-</pre>
-  </blockquote>
-  <p>
-  Note that for the <i>jython</i> example, the script contents <b>must</b>
-  start on the first column.
-  </p>
-  <p>
-    Note also that for the <i>ruby</i> example, the names of the set variables are prefixed
-    by a '$'.
-  <p>
-    The following script shows a little more complicated jruby example:
-  </p>
-  <blockquote><pre>
+    &lt;/script&gt;</pre>
+<p>Note that for the <q>jython</q> example, the script contents <strong>must</strong> start on the
+first column.</p>
+<p>Note also that for the <q>ruby</q> example, the names of the set variables are prefixed by
+a <q>$</q>.</p>
+<p>The following script shows a little more complicated JRuby example:</p>
+<pre>
 &lt;script language="ruby"&gt;
   xmlfiles = Dir.new(".").entries.delete_if { |i| ! (i =~ /\.xml$/) }
   xmlfiles.sort.each { |i| $self.log(i) }
-&lt;/script&gt;
-</pre>
-  </blockquote>
-  <p>
-    The same example in groovy is:
-  </p>
-  <blockquote><pre>
+&lt;/script&gt;</pre>
+<p>The same example in Groovy is:</p>
+<pre>
 &lt;script language="groovy"&gt;
   xmlfiles = new java.io.File(".").listFiles().findAll{ it =~ "\.xml$"}
-  xmlfiles.sort().each { self.log(it.toString())}
-&lt;/script&gt;
-</pre>
-  </blockquote>
-  <p>
-    The following example shows the use of classpath to specify the location
-    of the beanshell jar file.
-  </p>
-  <blockquote><pre>
+  xmlfiles.sort().each { self.log(it.toString()) }
+&lt;/script&gt;</pre>
+<p>The following example shows the use of classpath to specify the location of the beanshell jar
+file.</p>
+<pre>
 &lt;script language="beanshell" setbeans="true"&gt;
   &lt;classpath&gt;
-    &lt;fileset dir="${user.home}/lang/beanshell" includes="*.jar" /&gt;
+    &lt;fileset dir="${user.home}/lang/beanshell" includes="*.jar"/&gt;
   &lt;/classpath&gt;
   System.out.println("Hello world");
-&lt;/script&gt;
-</pre>
-  </blockquote>
-  <p>
-    The following script uses javascript to create a number of
-    echo tasks and execute them.
-  </p>
-<blockquote><pre>
+&lt;/script&gt;</pre>
+<p>The following script uses JavaScript to create a number of <code>echo</code> tasks and execute
+them.</p>
+<pre>
 &lt;project name=&quot;squares&quot; default=&quot;main&quot; basedir=&quot;.&quot;&gt;
-
   &lt;target name=&quot;main&quot;&gt;
-
     &lt;script language=&quot;javascript&quot;&gt; &lt;![CDATA[
-
-      for (i=1; i&lt;=10; i++) {
+      for (i = 1; i &lt;= 10; i++) {
         echo = squares.createTask(&quot;echo&quot;);
         echo.setMessage(i*i);
         echo.perform();
       }
-
     ]]&gt; &lt;/script&gt;
-
   &lt;/target&gt;
-
-&lt;/project&gt;
-</pre></blockquote>
+&lt;/project&gt;</pre>
 <p>generates</p>
-<blockquote><pre>
+<pre>
 main:
 1
 4
@@ -258,15 +210,13 @@
 81
 100
 
-BUILD SUCCESSFUL
-</pre></blockquote>
+BUILD SUCCESSFUL</pre>
 
-<p>Now a more complex example using the Java API and the Ant API. The goal is to list the
-filesizes of all files a <code>&lt;fileset/&gt;</code> caught.</p>
-<blockquote><pre>
-
-&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
-&lt;project name="<font color=blue>MyProject</font>" basedir="." default="main"&gt;
+<p>Now a more complex example using the Java API and the Ant API. The goal is to list the file sizes
+of all files a <code>&lt;fileset/&gt;</code> caught.</p>
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;project name="<span style="color:blue">MyProject</span>" basedir="." default="main"&gt;
 
   &lt;property name="fs.dir" value="src"/&gt;
   &lt;property name="fs.includes" value="**/*.txt"/&gt;
@@ -274,20 +224,24 @@
 
   &lt;target name="main"&gt;
     &lt;script language="javascript"&gt; &lt;![CDATA[
-
       // import statements
-      <font color=blue>// importPackage(java.io)</font>;
-      <font color=blue>importClass(java.io.File)</font>;
+      <span style="color:blue">// importPackage(java.io)</span>;
+      <span style="color:blue">importClass(java.io.File)</span>;
+      // Nashorn syntax
+      // <span style="color:blue">load("nashorn:mozilla_compat.js");</span>
+      // or
+      // <span style="color:blue">var File = Java.type('java.io.File');</span>
+
 
       // Access to Ant-Properties by their names
-      dir      = <font color=blue>project</font>.getProperty("fs.dir");
-      includes = <font color=blue>MyProject</font>.getProperty("fs.includes");
-      excludes = <font color=blue>self.getProject()</font>  .<font color=blue>getProperty("fs.excludes")</font>;
+      dir      = <span style="color:blue">project</span>.getProperty("fs.dir");
+      includes = <span style="color:blue">MyProject</span>.getProperty("fs.includes");
+      excludes = <span style="color:blue">self.getProject()</span>.<span style="color:blue">getProperty("fs.excludes")</span>;
 
       // Create a &lt;fileset dir="" includes=""/&gt;
-      fs = project.<font color=blue>createDataType("fileset")</font>;
-      fs.setDir( new File(dir) );
-      <font color=blue>fs.setIncludes(includes)</font>;
+      fs = project.<span style="color:blue">createDataType("fileset")</span>;
+      fs.setDir(new File(dir));
+      <span style="color:blue">fs.setIncludes(includes)</span>;
       fs.setExcludes(excludes);
 
       // Get the files (array) of that fileset
@@ -295,50 +249,70 @@
       srcFiles = ds.getIncludedFiles();
 
       // iterate over that array
-      for (i=0; i&lt;srcFiles.length; i++) {
+      for (i = 0; i &lt; srcFiles.length; i++) {
 
         // get the values via Java API
         var basedir  = fs.getDir(project);
         var filename = srcFiles[i];
-        var file = <font color=blue>new File(basedir, filename)</font>;
+        var file = <span style="color:blue">new File(basedir, filename)</span>;
         var size = file.length();
 
         // create and use a Task via Ant API
-        echo = MyProject.<font color=blue>createTask("echo")</font>;
+        echo = MyProject.<span style="color:blue">createTask("echo")</span>;
         echo.setMessage(filename + ": " + size + " byte");
-        echo.<font color=blue>perform()</font>;
+        echo.<span style="color:blue">perform()</span>;
       }
     ]]&gt;&lt;/script&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre></blockquote>
-<p>We want to use the Java API. Because we don't want always typing the package signature
-we do an import. Rhino knows two different methods for import statements: one for packages
-and one for a single class. By default only the <i>java</i> packages are available, so
-<i>java.lang.System</i> can be directly imported with <code>importClass/importPackage</code>.
-For other packages you have to prefix the full classified name with <i>Packages</i>.
-For example Ant's <i>FileUtils</i> class can be imported with
-<code>importClass(<b>Packages</b>.org.apache.tools.ant.util.FileUtils)</code>
-<br>
-The <code>&lt;script&gt;</code> task populates the Project instance under
-the name <i>project</i>, so we can use that reference. Another way is to use its given name
-or getting its reference from the task itself.<br>
-The Project provides methods for accessing and setting properties, creating DataTypes and
-Tasks and much more.<br>
-After creating a FileSet object we initialize that by calling its set-methods. Then we can
-use that object like a normal Ant task (<code>&lt;copy&gt;</code> for example).<br>
-For getting the size of a file we instantiate a <code>java.io.File</code>. So we are using
-normal Java API here.<br>
-Finally we use the <code>&lt;echo&gt;</code> task for producing the output. The task is not executed by
-its execute() method, because the perform() method (implemented in Task itself) does the
-appropriate logging before and after invoking execute().
-</p>
-<p>
-  Here is an example of using beanshell to create an ant
-  task. This task will add filesets and paths to a referenced
-  path. If the path does not exist, it will be created.
-</p>
-<blockquote><pre>
+&lt;/project&gt;</pre>
+<p>We want to use the Java API. Because we don't want always typing the package signature we do an
+import. Rhino knows two different methods for import statements: one for packages and one for a
+single class. By default only the <code>java</code> packages are available,
+so <code class="code">java.lang.System</code> can be directly imported
+with <code>importClass</code>/<code>importPackage</code>. For other packages you have to prefix the
+full classified name with <strong>Packages</strong>. For example
+Ant's <code class="code">FileUtils</code> class can be imported
+with <code class="code">importClass(<strong>Packages</strong>.org.apache.tools.ant.util.FileUtils)</code></p>
+<p>In Java 8 up until Java 14, you may use the built-in Nashorn JavaScript engine rather than Rhino (which is
+available in Java 7 runtime). Then, use <code>Java.type</code> as import statement for any Java
+class
+or <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html#A1147207">the
+compatibility script</a>: <code>load("nashorn:mozilla_compat.js");</code>.</p>
+
+<p>Starting with Java 15 Nashorn has been removed again and you need
+  to provide an external JavaScript engine. Your best option probably
+  is <a href="https://github.com/graalvm/graaljs">GraalVM
+  JavaScript</a> which requires you to add a lot of extra jars. For
+  GraalVM JavaScript 20.1 you'll
+  need <code>org.graalvm.js:js</code>, <code>org.graalvm.js:js-engine</code>
+  which in turn
+  require <code>org.graalvm.regex:regex</code>, <code>org.graalvm.truffle:truffle-api</code>, <code>org.graalvm.sdk:graal-sdk</code>,
+  and <code>com.ibm.icu:icu4j</code>. GraalVM JavaScript is not a
+  drop-in replacement for Nashorn, see
+  Graal's <a href="https://github.com/graalvm/graaljs/blob/master/docs/user/NashornMigrationGuide.md">Nashorn
+  Migration Guide</a> for more details.</p>
+
+<p>When using GraalVM JavaScript Ant will enable the
+  feature <code>polyglot.js.allowAllAccess</code> in order to allow
+  scripts to use Ant objects. By default it will also enable Nashorn
+  compatibility mode, but you can disable this by setting the magic
+  Ant property <code>ant.disable.graal.nashorn.compat</code>
+  to <code>true</code>.</p>
+
+<p>The <code>&lt;script&gt;</code> task populates the Project instance under the
+name <code class="code">project</code>, so we can use that reference. Another way is to use its
+given name or getting its reference from the task itself. The Project provides methods for accessing
+and setting properties, creating DataTypes and Tasks and much more.<br/>After creating a FileSet
+object we initialize that by calling its set-methods. Then we can use that object like a normal Ant
+task (<code>&lt;copy&gt;</code> for example).<br/>For getting the size of a file we instantiate
+a <code class="code">java.io.File</code>. So we are using normal Java API here.<br/>Finally we use
+the <code>&lt;echo&gt;</code> task for producing the output. The task is not executed by
+its <code class="code">execute()</code> method, because the <code class="code">perform()</code>
+method (implemented in Task itself) does the appropriate logging before and after
+invoking <code class="code">execute()</code>.</p>
+<p>Here is an example of using beanshell to create an Ant task. This task will add filesets and
+paths to a referenced path. If the path does not exist, it will be created.</p>
+<pre>
 &lt;!--
        Define addtopath task
  --&gt;
@@ -366,15 +340,11 @@
         }
     }
     project.addTaskDefinition("addtopath", AddToPath.class);
-&lt;/script&gt;
-</pre></blockquote>
-  <p>
-    An example of using this task to create a path
-    from a list of directories (using antcontrib's
-    <a href="http://ant-contrib.sourceforge.net/tasks/tasks/for.html">
-      &lt;for&gt;</a> task) follows:
-  </p>
-<blockquote><pre>
+&lt;/script&gt;</pre>
+<p>An example of using this task to create a path from a list of directories (using
+Ant-Contrib's <a href="http://ant-contrib.sourceforge.net/tasks/tasks/for.html"
+target="_top">&lt;for&gt;</a> task) follows:</p>
+<pre>
 &lt;path id="main.path"&gt;
   &lt;fileset dir="build/classes"/&gt;
 &lt;/path&gt;
@@ -386,8 +356,7 @@
                includes="**/*.jar"/&gt;
     &lt;/addtopath&gt;
   &lt;/sequential&gt;
-&lt;/ac:for&gt;
-</pre></blockquote>
+&lt;/ac:for&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/scriptdef.html b/manual/Tasks/scriptdef.html
index 38c3fff..5427020 100644
--- a/manual/Tasks/scriptdef.html
+++ b/manual/Tasks/scriptdef.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,319 +15,290 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Scriptdef Task</title>
 </head>
 
 <body>
 
-<h2><a name="script">Scriptdef</a></h2>
+<h2 id="script">Scriptdef</h2>
 <h3>Description</h3>
-<p>Scriptdef can be used to define an Apache Ant task using a scripting language. Ant
-scripting languages supported by
-<a href="http://jakarta.apache.org/bsf" target="_top">Apache BSF</a> 
-or
-  <a href="https://scripting.dev.java.net">JSR 223</a>
-may be
-used to define the script. Scriptdef provides a mechanism to encapsulate
-control logic from a build within an Ant task minimizing the need for
-providing control style tasks in Ant itself. Complex logic can be made
-available while retaining the simple structure of an Ant build file. Scriptdef
-is also useful for prototyping new custom tasks. Certainly as the complexity
-of the script increases it would be better to migrate the task definition
-into a Java based custom task.
-</p>
+<p><code>Scriptdef</code> can be used to define an Apache Ant task using a scripting language. Ant
+scripting languages supported by <a href="https://jakarta.apache.org/bsf" target="_top">Apache
+BSF</a> or <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr223/223ChangeLog.html"
+target="_top">JSR 223</a> may be used to define the script. <code>Scriptdef</code> provides a
+mechanism to encapsulate control logic from a build within an Ant task minimizing the need for
+providing control style tasks in Ant itself. Complex logic can be made available while retaining the
+simple structure of an Ant build file. <code>Scriptdef</code> is also useful for prototyping new
+custom tasks. Certainly as the complexity of the script increases it would be better to migrate the
+task definition into a Java based custom task.</p>
 
-<p><b>Note:</b> This task depends on external libraries not included in the
-Ant distribution. See
-<a href="../install.html#librarydependencies">Library Dependencies</a>
-for more information.</p>
-
-
+<p><strong>Note</strong>: This task depends on external libraries not included in the Ant
+distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
 
 <p>The attributes and nested elements supported by the task may be defined
 using <code>&lt;attribute&gt;</code> and <code>&lt;element&gt;</code> nested elements. These are
-available to the script that implements the task as two collection style
-script variables <code>attributes</code> and <code>elements</code>. The
-elements in the <code>attributes</code> collection may be accessed by the
-attribute name. The <code>elements</code> collection is accessed by the nested
-element name. This will return a list of all instances of the nested element.
-The instances in this list may be accessed by an integer index.
-</p>
+available to the script that implements the task as two collection style script
+variables <code class="code">attributes</code> and <code class="code">elements</code>. The elements
+in the <code class="code">attributes</code> collection may be accessed by the attribute
+name. The <code class="code">elements</code> collection is accessed by the nested element name. This
+will return a list of all instances of the nested element.  The instances in this list may be
+accessed by an integer index.</p>
 
-<p><b>Note:</b> Ant will turn all attribute and element names into all
-lowercase names, so even if you use name="SomeAttribute", you'll have
-to use "someattribute" to retrieve the attribute's value from the
-<code>attributes</code> collection.</p>
+<p><strong>Note</strong>: Ant will turn all attribute and element names into all lowercase names, so
+even if you use <var>name</var>=<q>SomeAttribute</q>, you'll have to use <q>someattribute</q> to
+retrieve the attribute's value from the <code class="code">attributes</code> collection.</p>
 
-<p>The name "self" (<i>since Ant 1.6.3</i>) is a pre-defined reference to the
-    script def task instance.
-    It can be used for logging, or for integration with the rest of
-    ant. the <code>self.text attribute</code> contains
-    any nested text passed to the script</p>
+<p>The name <code class="code">self</code> (<em>since Ant 1.6.3</em>) is a pre-defined reference to
+the <code>scriptdef</code> task instance.  It can be used for logging, or for integration with the
+rest of Ant. The <code class="code">self.text</code> attribute contains any nested text passed to
+the script</p>
 
-<p>If an attribute or element is not passed in, 
-then <code>attributes.get()</code> or <code>elements.get()</code> will 
-return null. It is up to the script to perform any checks and validation. 
-<code>self.fail(String message)</code>can be used to raise a 
-<code>BuildException</code>.
-</p>
+<p>If an attribute or element is not passed in, then <code class="code">attributes.get()</code>
+or <code class="code">elements.get()</code> will return null. It is up to the script to perform any
+checks and validation. <code class="code">self.fail(String message)</code>can be used to raise
+a <code>BuildException</code>.</p>
 
-
-<p>The name "project" is a pre-defined reference to the Ant Project. For
-more information on writing scripts, please refer to the
-<a href="script.html"><code>&lt;script&gt;</code></a> task
-</p>
-
+<p>The name <code class="code">project</code> is a pre-defined reference to the Ant Project. For
+more information on writing scripts, please refer to
+the <a href="script.html"><code>&lt;script&gt;</code></a> task.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the task to be created using the script</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>the name of the task to be created using the script</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">language</td>
-    <td valign="top">The programming language the script is written in.
-      Must be a supported Apache BSF or JSR 223 language</td>
-    <td valign="top" align="center">Yes</td>
+    <td>language</td>
+    <td>The programming language the script is written in.  Must be a supported Apache BSF or JSR
+      223 language</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">manager</td>
-    <td valign="top">
-      The script engine manager to use.
-      See the <a href="../Tasks/script.html">script</a> task
-      for using this attribute.
+    <td>manager</td>
+    <td>The script engine manager to use.  See the <a href="../Tasks/script.html">script</a> task
+      for using this attribute.</td>
+    <td>No; default is <q>auto</q></td>
+  </tr>
+  <tr>
+    <td>src</td>
+    <td>The location of the script as a file, if not inline</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>encoding</td>
+    <td>The encoding of the script as a file. <em>since Ant 1.10.2</em>.</td>
+    <td>No; defaults to default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>compiled</td>
+    <td>If true, the script is compiled before the first evaluation for faster multiple executions,
+      on the condition that the <var>manager</var> is <q>javax</q> and the target engine
+      implements <code>javax.script.Compilable</code>.  Note that the <q>bsf</q> manager may
+      automatically compile the script. <em>since Ant 1.10.2</em>.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>uri</td>
+    <td>The XML namespace uri that this definition should live in.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>The classpath to pass into the script.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a path
+      defined elsewhere.
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>loaderRef</td>
+    <td>the name of the loader that is used to load the script, constructed from the specified
+      classpath. This allows multiple script definitions to reuse the same class loader.
     </td>
-    <td valign="top" align="center">No - default is "auto"</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">The location of the script as a file, if not inline</td>
-    <td valign="top" align="center">No</td>
-  </tr>
-  <tr>
-    <td valign="top">uri</td>
-    <td valign="top">
-      The XML namespace uri that this definition should live in.
+    <td>setbeans</td>
+    <td>This attribute controls whether to set variables for all properties, references and targets
+      in the running script. If this attribute is <q>false</q>, only the <code>project</code> and
+      <code>self</code> variables are set. If this attribute is <q>true</q> all the variables are
+      set. <em>Since Ant 1.10.13</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; default <q>false</q> for backward compatibility</td>
   </tr>
-  <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">
-      The classpath to pass into the script.
-    </td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use, given as a
-      <a href="../using.html#references">reference</a> to a path defined elsewhere.
-      <td align="center" valign="top">No</td>
-    </tr>
-    <tr>
-      <td valign="top">loaderRef</td>
-      <td valign="top">the name of the loader that is
-        used to load the script, constructed from the specified 
-        classpath. This allows multiple script definitions
-        to reuse the same class loader.
-      </td>
-      <td align="center" valign="top">No</td>
-    </tr>
-  </table>
+</table>
 
-<h3>Nested elements</h3>
+<h3>Parameters specified as nested elements</h3>
 <h4>attribute</h4>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the attribute</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>the name of the attribute</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>default</td>
+    <td>the default value of the attribute <em>Since Ant 1.10.13</em></td>
+    <td>No</td>
   </tr>
 </table>
 
 <h4>element</h4>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the nested element to be supported by the
-                     task defined by the script</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>the name of the nested element to be supported by the task defined by the script</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">the classname of the class to be used for the nested element.
-         This specifies the class directly and is an alternative to specifying
-         the Ant type name.</td>
-    <td valign="top" align="center">No</td>
+    <td>classname</td>
+    <td>the classname of the class to be used for the nested element.  This specifies the class
+      directly and is an alternative to specifying the Ant type name.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">This is the name of an Ant task or type which is to
-        be used when this element is to be created. This is an alternative
-        to specifying the class name directly. If the type is in a namespace,
-        the URI and a : must be prefixed to the type. For example
-        <code>type="antlib:example.org:newtype"</code></td>
-    <td valign="top" align="center">No</td>
+    <td>type</td>
+    <td>This is the name of an Ant task or type which is to be used when this element is to be
+      created. This is an alternative to specifying the class name directly. If the type is in a
+      namespace, the URI and a <q>:</q> must be prefixed to the type. For
+      example <var>type</var>=<q>antlib:example.org:newtype</q></td>
+    <td>No</td>
   </tr>
-  <tr>
-    <td valign="top">any resource or resource collection</td>
-    <td valign="top">Since Ant1.7.1, this task can load scripts
-    from any resource supplied as a nested element. when </td>
-    <td valign="top" align="center">No</td>
-  </tr>
-
 </table>
 
-  <h4>classpath</h4>
-  <p>
-    See the <a href="../Tasks/script.html">script</a> task
-    for using this nested element.
-  </p>
+<h4>classpath</h4>
+<p>See the <a href="../Tasks/script.html">script</a> task for using this nested element.</p>
 
+<h4>any resource collection</h4>
+<p><em>Since Ant 1.7.1</em></p>
+<p>This task can load scripts from any resource supplied as a nested element.</p>
 
 <h3>Examples</h3>
 
-<p>
-The following definition creates a task which supports an attribute called
-attr and two nested elements, one being a fileset and the other a path. When
-executed, the resulting task logs the value of the attribute and the basedir
-of the first fileset.
-</p>
+<p>The following definition creates a task which supports an attribute called <var>attr</var> and
+two nested elements, one being a fileset and the other a path. When executed, the resulting task
+logs the value of the attribute and the <var>basedir</var> of the first fileset.</p>
 
 <pre>
-  &lt;scriptdef name=&quot;scripttest&quot; language=&quot;javascript&quot;&gt;
-    &lt;attribute name=&quot;attr1&quot;/&gt;
-    &lt;element name=&quot;fileset&quot; type=&quot;fileset&quot;/&gt;
-    &lt;element name=&quot;path&quot; type=&quot;path&quot;/&gt;
-    &lt;![CDATA[
+&lt;scriptdef name=&quot;scripttest&quot; language=&quot;javascript&quot;&gt;
+  &lt;attribute name=&quot;attr1&quot;/&gt;
+  &lt;element name=&quot;fileset&quot; type=&quot;fileset&quot;/&gt;
+  &lt;element name=&quot;path&quot; type=&quot;path&quot;/&gt;
+  &lt;![CDATA[
 
-      self.log(&quot;Hello from script&quot;);
-      self.log(&quot;Attribute attr1 = &quot; + attributes.get(&quot;attr1&quot;));
-      self.log(&quot;First fileset basedir = &quot;
-        + elements.get(&quot;fileset&quot;).get(0).getDir(project));
+    self.log(&quot;Hello from script&quot;);
+    self.log(&quot;Attribute attr1 = &quot; + attributes.get(&quot;attr1&quot;));
+    self.log(&quot;First fileset basedir = &quot;
+      + elements.get(&quot;fileset&quot;).get(0).getDir(project));
 
-    ]]&gt;
-  &lt;/scriptdef&gt;
+  ]]&gt;
+&lt;/scriptdef&gt;
 
-  &lt;scripttest attr1=&quot;test&quot;&gt;
-    &lt;path&gt;
-      &lt;pathelement location=&quot;src&quot;/&gt;
-    &lt;/path&gt;
-    &lt;fileset dir=&quot;src&quot;/&gt;
-    &lt;fileset dir=&quot;main&quot;/&gt;
-  &lt;/scripttest&gt;
-</pre>
+&lt;scripttest attr1=&quot;test&quot;&gt;
+  &lt;path&gt;
+    &lt;pathelement location=&quot;src&quot;/&gt;
+  &lt;/path&gt;
+  &lt;fileset dir=&quot;src&quot;/&gt;
+  &lt;fileset dir=&quot;main&quot;/&gt;
+&lt;/scripttest&gt;</pre>
 
-<p>
-The following variation on the above script lists the number of fileset elements
-and iterates through them
-</p>
+<p>The following variation on the above script lists the number of fileset elements and iterates
+through them</p>
 <pre>
-  &lt;scriptdef name=&quot;scripttest2&quot; language=&quot;javascript&quot;&gt;
-    &lt;element name=&quot;fileset&quot; type=&quot;fileset&quot;/&gt;
-    &lt;![CDATA[
-      filesets = elements.get(&quot;fileset&quot;);
-      self.log(&quot;Number of filesets = &quot; + filesets.size());
-      for (i = 0; i &lt; filesets.size(); ++i) {
-        self.log(&quot;fileset &quot; + i + &quot; basedir = &quot;
-          + filesets.get(i).getDir(project));
-      }
-    ]]&gt;
-  &lt;/scriptdef&gt
+&lt;scriptdef name=&quot;scripttest2&quot; language=&quot;javascript&quot;&gt;
+  &lt;element name=&quot;fileset&quot; type=&quot;fileset&quot;/&gt;
+  &lt;![CDATA[
+    filesets = elements.get(&quot;fileset&quot;);
+    self.log(&quot;Number of filesets = &quot; + filesets.size());
+    for (i = 0; i &lt; filesets.size(); ++i) {
+      self.log(&quot;fileset &quot; + i + &quot; basedir = &quot;
+        + filesets.get(i).getDir(project));
+    }
+  ]]&gt;
+&lt;/scriptdef&gt;
 
-  &lt;scripttest2&gt;
-    &lt;fileset dir=&quot;src&quot;/&gt;
-    &lt;fileset dir=&quot;main&quot;/&gt;
-  &lt;/scripttest2&gt;
-</pre>
+&lt;scripttest2&gt;
+  &lt;fileset dir=&quot;src&quot;/&gt;
+  &lt;fileset dir=&quot;main&quot;/&gt;
+&lt;/scripttest2&gt;</pre>
 
-<p>
-When a script has a syntax error, the scriptdef name will be listed in the
-error. For example in the above script, removing the closing curly bracket
-would result in this error
-</p>
+<p>When a script has a syntax error, the <code>scriptdef</code> name will be listed in the
+error. For example in the above script, removing the closing curly bracket would result in this
+error</p>
 
-<p><code>build.xml:15: SyntaxError: missing } in compound
-statement (scriptdef <code>&lt;scripttest2&gt;</code>; line 10)</code></p>
+<pre class="output">build.xml:15: SyntaxError: missing } in compound
+statement (scriptdef &lt;scripttest2&gt;; line 10)</pre>
 
-<p>
-Script errors are only detected when a script task is actually executed.
-</p>
-<p>
-    The next example does uses nested text in Jython. It also declares 
-    the script in a new xml namespace, which must be used to refer to 
-    the task. Declaring scripts in a new namespace guarantees that Ant will 
-    not create a task of the same (namespace,localname) name pair. 
-</p>
+<p>Script errors are only detected when a <code>script</code> task is actually executed.</p>
+<p>The next example does uses nested text in Jython. It also declares the script in a new xml
+namespace, which must be used to refer to the task. Declaring scripts in a new namespace guarantees
+that Ant will not create a task of the same (namespace,localname) name pair.</p>
 
 <pre>
 &lt;target name="echo-task-jython"&gt;
   &lt;scriptdef language="jython"
-      name="echo"
-      uri="http://example.org/script"&gt;
+             name="echo"
+             uri="https://example.org/script"&gt;
       &lt;![CDATA[
 self.log("text: " +self.text)
-    ]]&gt;
+      ]]&gt;
     &lt;/scriptdef&gt;
 &lt;/target&gt;
 
 &lt;target name="testEcho" depends="echo-task-jython"
-    xmlns:s="http://example.org/script"&gt;
+        xmlns:s="https://example.org/script"&gt;
   &lt;s:echo&gt;nested text&lt;/s:echo&gt;
-&lt;/target&gt;
-</pre>
+&lt;/target&gt;</pre>
 
-The next example shows the use of &lt;classpath&gt; and
-"loaderref" to get access to the beanshell jar.
+<p>The next example shows the use of <code>&lt;classpath&gt;</code> and <var>loaderref</var> to get
+access to the beanshell jar.</p>
 <pre>
-    &lt;scriptdef name="b1" language="beanshell"
-               loaderref="beanshell-ref"&gt;
-      &lt;attribute name="a"/&gt;
-      &lt;classpath
-        path="${user.home}/scripting/beanshell/bsh-1.3b1.jar"/&gt;
-      self.log("attribute a is " + attributes.get("a"));
-    &lt;/scriptdef&gt;
+&lt;scriptdef name="b1" language="beanshell"
+           loaderref="beanshell-ref"&gt;
+  &lt;attribute name="a"/&gt;
+  &lt;classpath path="${user.home}/scripting/beanshell/bsh-1.3b1.jar"/&gt;
+  self.log("attribute a is " + attributes.get("a"));
+&lt;/scriptdef&gt;
 
-    &lt;scriptdef name="b2" language="beanshell"
-               loaderref="beanshell-ref"&gt;
-      &lt;attribute name="a2"/&gt;
-      self.log("attribute a2 is " + attributes.get("a2"));
-    &lt;/scriptdef&gt;
+&lt;scriptdef name="b2" language="beanshell"
+           loaderref="beanshell-ref"&gt;
+  &lt;attribute name="a2"/&gt;
+  self.log("attribute a2 is " + attributes.get("a2"));
+&lt;/scriptdef&gt;
 
-    &lt;b1 a="this is an 'a'"/&gt;
-    &lt;b2 a2="this is an 'a2' for b2"/&gt;
-</pre>
-<h3>Testing Scripts</h3>
+&lt;b1 a="this is an 'a'"/&gt;
+&lt;b2 a2="this is an 'a2' for b2"/&gt;</pre>
 
-<p>
-The easiest way to test scripts is to use the 
-<a href="http://ant.apache.org/antlibs/antunit/">AntUnit</a> ant library.
-This will run all targets in a script that begin with "test" (and their dependencies). </p>
+<h3>Testing scripts</h3>
 
-
-
+<p>The easiest way to test scripts is to use the <a href="https://ant.apache.org/antlibs/antunit/"
+target="_top">AntUnit</a> Ant library.  This will run all targets in a script that begin
+with <q>test</q> (and their dependencies).</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/sequential.html b/manual/Tasks/sequential.html
index d3deda6..034a8ff 100644
--- a/manual/Tasks/sequential.html
+++ b/manual/Tasks/sequential.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Sequential Task</title>
 </head>
@@ -26,16 +26,17 @@
 
 <h2>Sequential</h2>
 <h3>Description</h3>
-<p>Sequential is a container task - it can contain other Apache Ant tasks. The nested 
-tasks are simply executed in sequence. Sequential's primary use is to support 
-the sequential execution of a subset of tasks within the 
-<a href="parallel.html">parallel</a> task</p>
+<p><code>Sequential</code> is a container task&mdash;it can contain other Apache Ant tasks. The
+nested tasks are simply executed in sequence. Sequential's primary use is to support the sequential
+execution of a subset of tasks within the <a href="parallel.html">parallel</a> task</p>
 
-<p>The sequential task has no attributes and does not support any nested 
-elements apart from Ant tasks. Any valid Ant task may be embedded within the 
-sequential task.</p>
+<p>The <code>sequential</code> task has no attributes and does not support any nested elements apart
+from Ant tasks. Any valid Ant task may be embedded within the sequential task.</p>
 
 <h3>Example</h3>
+
+<p>This example shows how the <code>sequential</code> task is used to execute three tasks in
+sequence, while another task is being executed in a separate thread.</p>
 <pre>
 &lt;parallel&gt;
   &lt;wlrun ... &gt;
@@ -44,12 +45,7 @@
     &lt;junit ... &gt;
     &lt;wlstop/&gt;
   &lt;/sequential&gt;
-&lt;/parallel&gt;
-</pre>
-<p>This example shows how the sequential task is used to execute three tasks in
-sequence, while another task is being executed in a separate thread. </p>
-
+&lt;/parallel&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/serverdeploy.html b/manual/Tasks/serverdeploy.html
index 87d0777..780c661 100644
--- a/manual/Tasks/serverdeploy.html
+++ b/manual/Tasks/serverdeploy.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ServerDeploy Task</title>
 
@@ -25,311 +25,281 @@
 
 <body>
 
-<h1><a name="serverdeploy">Apache Ant ServerDeploy User Manual</a></h1>
+<h1 id="serverdeploy">Apache Ant ServerDeploy User Manual</h1>
 <p>by</p>
 <!-- Names are in alphabetical order, on last name -->
 <ul>
-<li>Christopher A. Longo (<a href="mailto:cal@cloud9.net">cal@cloud9.net</a>)</li>
-<li>Cyrille Morvan (<a href="mailto:cmorvan@ingenosya.com">cmorvan@ingenosya.com</a>)</li>
+  <li>Christopher A. Longo (<a href="mailto:cal@cloud9.net">cal@cloud9.net</a>)</li>
+  <li>Cyrille Morvan (<a href="mailto:cmorvan@ingenosya.com">cmorvan@ingenosya.com</a>)</li>
 </ul>
 
-</p>
-<hr>
-<p> At present the tasks support:<br>
+<hr/>
+<p>At present the tasks support:</p>
 
 <ul>
-<li><a href="http://www.bea.com" target="_top">Weblogic</a> servers</li>
-<li><a href="http://www.objectweb.org/jonas/" target="_top">JOnAS</a>
-2.4 Open Source EJB server</li>
+  <li><a href="https://www.oracle.com/corporate/acquisitions/bea/" target="_top">WebLogic</a> servers</li>
+  <li><a href="https://jonas.ow2.org/" target="_top">JOnAS</a> 2.4 Open Source EJB server</li>
 </ul>
-Over time we expect further optional tasks  to support additional J2EE Servers.
-</p>
+<p>Over time we expect further optional tasks to support additional J2EE Servers.</p>
 
-<hr>
+<hr/>
 
-<table border="1" cellpadding="5">
-<tr><td>Task</td><td colspan="2">Application Servers</td></tr>
-<tr><td rowspan="4"><a href="#serverdeploy_element">serverdeploy</a></td><td colspan="2" align="center"><b>Nested Elements</b></td></tr>
-<tr><td><a href="#serverdeploy_generic">generic</a></td><td>Generic task</td></tr>
-<tr><td><a href="#serverdeploy_jonas">jonas</a></td><td>JOnAS 2.4</td></tr>
-<tr><td><a href="#serverdeploy_weblogic">weblogic</a></td><td>Weblogic</td></tr>
-
+<table>
+  <tr><th scope="col">Task</th><th scope="col" colspan="2">Application Servers</th></tr>
+  <tr><td rowspan="4"><a href="#serverdeploy_element">serverdeploy</a></td><th scope="col" colspan="2">Nested Elements</th></tr>
+  <tr><td><a href="#serverdeploy_generic">generic</a></td><td>Generic task</td></tr>
+  <tr><td><a href="#serverdeploy_jonas">jonas</a></td><td>JOnAS 2.4</td></tr>
+  <tr><td><a href="#serverdeploy_weblogic">weblogic</a></td><td>WebLogic</td></tr>
 </table>
 
-<a name="serverdeploy_element">
-<h2>ServerDeploy element</h2>
+<h2 id="serverdeploy_element">ServerDeploy element</h2>
 
-<h3><b>Description:</b></h3>
+<h3>Description</h3>
 
-<p>The <code>serverdeploy</code> task is used to run a "hot" deployment tool for
-vendor-specific J2EE server. The task requires nested elements which define
-the attributes of the vendor-specific deployment tool being executed.
-Vendor-specific deployment tools elements may enforce rules for which
-attributes are required, depending on the tool.
-</p>
+<p>The <code>serverdeploy</code> task is used to run a "hot" deployment tool for vendor-specific
+J2EE server. The task requires nested elements which define the attributes of the vendor-specific
+deployment tool being executed.  Vendor-specific deployment tools elements may enforce rules for
+which attributes are required, depending on the tool.</p>
 
-<h3>Parameters:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">action</td>
-    <td valign="top">This is the action to be performed.  For most cases this
-    will be "deploy".  Some tools support additional actions, such as "delete", "list",
-    "undeploy", "update"...</td>
+    <td>action</td>
+    <td>This is the action to be performed.  For most cases this will be <q>deploy</q>.  Some tools
+      support additional actions, such
+      as <q>delete</q>, <q>list</q>, <q>undeploy</q>, <q>update</q>, ...</td>
     <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">source</td>
-    <td valign="top">A fully qualified path/filename of the component to be deployed.
-    This may be an .ear, .jar, .war, or any other type that is supported by the server.
-    </td>
+    <td>source</td>
+    <td>A fully qualified path/filename of the component to be deployed.  This may be
+      an <samp>.ear</samp>, <samp>.jar</samp>, <samp>.war</samp>, or any other type that is
+      supported by the server.</td>
     <td>Tool dependent</td>
   </tr>
 </table>
 
-<h3>Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
-<p>The serverdeploy task supports a nested <code>classpath</code> element to set the classpath.</p>
+<p>The <code>serverdeploy</code> task supports a nested <code>classpath</code> element to set the
+classpath.</p>
 
 <h3>Vendor-specific nested elements</h3>
 
-<h3>Parameters used for all tools:</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Also supported are nested vendor-specific elements.</p>
+
+<h3>Parameters used for all tools</h3>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">The classpath to be passed to the JVM running the tool.
-    The classpath may also be supplied as a nested element.</td>
+    <td>classpath</td>
+    <td>The classpath to be passed to the JVM running the tool.  The classpath may also be supplied
+      as a nested element.</td>
     <td>Tool dependent</td>
   </tr>
   <tr>
-    <td valign="top">server</td>
-    <td valign="top">The address or URL for the server where the component will be deployed.</td>
+    <td>server</td>
+    <td>The address or URL for the server where the component will be deployed.</td>
     <td>Tool dependent</td>
   </tr>
   <tr>
-    <td valign="top">username</td>
-    <td valign="top">The user with privileges to deploy applications to the server.</td>
+    <td>username</td>
+    <td>The user with privileges to deploy applications to the server.</td>
     <td>Tool dependent</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">The password of the user with privileges to deploy applications to the server.</td>
+    <td>password</td>
+    <td>The password of the user with privileges to deploy applications to the server.</td>
     <td>Tool dependent</td>
   </tr>
 </table>
 
-<p>Also supported are nested vendor-specific elements.</p>
-
-<a name="serverdeploy_generic">
-<h3>Generic element</h3>
-This element is provided for generic Java-based deployment tools.
-The generic task accepts (but does not require) nested <code>arg</code>
-and <code>jvmarg</code> elements.
-A JVM will be spawned with the provided attributes.  It is recommended
-that a vendor-specific element be used over the generic one if at all
-possible.
+<h3 id="serverdeploy_generic">Generic element</h3>
+<p>This element is provided for generic Java-based deployment tools.  The generic task accepts (but
+does not require) nested <code>arg</code> and <code>jvmarg</code> elements.  A JVM will be spawned
+with the provided attributes.  It is recommended that a vendor-specific element be used over the
+generic one if at all possible.</p>
 <p>The following attributes are supported by the generic element.</p>
-<p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">This is the fully qualified classname of the Java based
-    deployment tool to execute.</td>
+    <td>classname</td>
+    <td>This is the fully qualified classname of the Java based deployment tool to execute.</td>
     <td>Yes</td>
   </tr>
 </table>
-</p>
 
-<h3>Nested Elements</h3>
-<p>The generic element supports nested <code>&lt;arg&gt;</code> and <code>&lt;jvmarg&gt;</code> elements.</p>
+<h4>Nested elements</h4>
+<p>The generic element supports nested <code>&lt;arg&gt;</code> and <code>&lt;jvmarg&gt;</code>
+elements.</p>
 
 <h3>Example</h3>
 
-<p>This example shows the use of generic deploy element to deploy a component
-using a Java based deploy tool:</p>
+<p>This example shows the use of generic deploy element to deploy a component using a Java based
+deploy tool:</p>
 
 <pre>
-    &lt;serverdeploy action=&quot;deploy&quot; source=&quot;${lib.dir}/ejb_myApp.ear&quot;&gt;
-        &lt;generic classname="com.yamato.j2ee.tools.deploy.DeployTool"
-            classpath=&quot;${classpath}&quot;
-            username=&quot;${user.name}&quot;
-            password=&quot;${user.password}&quot;&gt;
-            &lt;arg value="-component=WildStar"/&gt;
-            &lt;arg value="-force"/&gt;
-            &lt;jvmarg value="-ms64m"/&gt;
-            &lt;jvmarg value="-mx128m"/&gt;
-        &lt;/generic&gt;
-    &lt;/serverdeploy&gt;
-</pre>
+&lt;serverdeploy action=&quot;deploy&quot; source=&quot;${lib.dir}/ejb_myApp.ear&quot;&gt;
+    &lt;generic classname="com.yamato.j2ee.tools.deploy.DeployTool"
+             classpath=&quot;${classpath}&quot;
+             username=&quot;${user.name}&quot;
+             password=&quot;${user.password}&quot;&gt;
+        &lt;arg value="-component=WildStar"/&gt;
+        &lt;arg value="-force"/&gt;
+        &lt;jvmarg value="-ms64m"/&gt;
+        &lt;jvmarg value="-mx128m"/&gt;
+    &lt;/generic&gt;
+&lt;/serverdeploy&gt;</pre>
 
-<a name="serverdeploy_weblogic">
-<h3>WebLogic element</h3>
-<p>
-The WebLogic element contains additional attributes to run the
-<code>weblogic.deploy</code> deployment tool.
-<p>Valid actions for the tool are <code>deploy</code>, <code>undeploy</code>,
-<code>list</code>, <code>update</code>, and <code>delete</code>.
-<p>If the action is <code>deploy</code> or <code>update</code>,
-the <code>application</code> and <code>source</code> attributes must be set.
-If the action is <code>undeploy</code> or <code>delete</code>,
-the <code>application</code> attribute must be set.  If the <code>username</code>
-attribute is omitted, it defaults to "system".  The <code>password</code> attribute is
-required for all actions.
-<p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3 id="serverdeploy_weblogic">WebLogic element</h3>
+<p>The WebLogic element contains additional attributes to run the <code>weblogic.deploy</code>
+deployment tool.</p>
+<p>Valid actions for the tool are <q>deploy</q>, <q>undeploy</q>, <q>list</q>, <q>update</q>,
+and <q>delete</q>.</p>
+<p>If the action is <q>deploy</q> or <q>update</q>, the <var>application</var> and <var>source</var>
+attributes must be set.  If the action is <q>undeploy</q> or <q>delete</q>,
+the <var>application</var> attribute must be set.  If the <var>username</var> attribute is omitted,
+it defaults to <q>system</q>.  The <var>password</var> attribute is required for all actions.</p>
+
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">application</td>
-    <td valign="top">This is the name of the application being deployed</td>
+    <td>application</td>
+    <td>This is the name of the application being deployed</td>
     <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">component</td>
-    <td valign="top">This is the component string for deployment targets.
-    It is in the form <code>&lt;component&gt;:&lt;target1&gt;,&lt;target2&gt;...</code>
-    Where component is the archive name (minus the .jar, .ear, .war
-    extension).  Targets are the servers where the components will be deployed</td>
-    <td>no</td>
+    <td>component</td>
+    <td>This is the component string for deployment targets.  It is in the
+      form <code>&lt;component&gt;:&lt;target1&gt;,&lt;target2&gt;...</code>  Where component is the
+      archive name (minus the <samp>.jar</samp>, <samp>.ear</samp>, <samp>.war</samp> extension).
+      Targets are the servers where the components will be deployed</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">debug</td>
-    <td valign="top">If set to true, additional information will be
-    printed during the deployment process.</td>
+    <td>debug</td>
+    <td>If set to <q>true</q>, additional information will be printed during the deployment
+      process.</td>
     <td>No</td>
   </tr>
 </table>
 
-
 <h3>Examples</h3>
 
-<p>This example shows the use of serverdeploy to deploy a component to a WebLogic server:</p>
+<p>This example shows the use of <code>serverdeploy</code> to deploy a component to a WebLogic
+server:</p>
 
 <pre>
-    &lt;serverdeploy action=&quot;deploy&quot; source=&quot;${lib.dir}/ejb_myApp.ear&quot;&gt;
-        &lt;weblogic application=&quot;myapp&quot;
-            server=&quot;t3://myserver:7001&quot;
-            classpath=&quot;${weblogic.home}/lib/weblogic.jar&quot;
-            username=&quot;${user.name}&quot;
-            password=&quot;${user.password}&quot;
-            component=&quot;ejb_foobar:myserver,productionserver&quot;
-            debug=&quot;true&quot;/&gt;
-    &lt;/serverdeploy&gt;
-</pre>
+&lt;serverdeploy action=&quot;deploy&quot; source=&quot;${lib.dir}/ejb_myApp.ear&quot;&gt;
+    &lt;weblogic application=&quot;myapp&quot;
+              server=&quot;t3://myserver:7001&quot;
+              classpath=&quot;${weblogic.home}/lib/weblogic.jar&quot;
+              username=&quot;${user.name}&quot;
+              password=&quot;${user.password}&quot;
+              component=&quot;ejb_foobar:myserver,productionserver&quot;
+              debug=&quot;true&quot;/&gt;
+&lt;/serverdeploy&gt;</pre>
 
-<p>This example shows serverdeploy being used to delete a component from a
-WebLogic server:</p>
+<p>This example shows <code>serverdeploy</code> being used to delete a component from a WebLogic
+server:</p>
 
 <pre>
-    &lt;serverdeploy action=&quot;delete&quot; source=&quot;${lib.dir}/ejb_myApp.jar&quot;/&gt
-        &lt;weblogic application=&quot;myapp&quot;
-            server=&quot;t3://myserver:7001&quot;
-            classpath=&quot;${weblogic.home}/lib/weblogic.jar&quot;
-            username=&quot;${user.name}&quot;
-            password=&quot;${user.password}&quot;/&gt;
-    &lt;/serverdeploy&gt;
-</pre>
+&lt;serverdeploy action=&quot;delete&quot; source=&quot;${lib.dir}/ejb_myApp.jar&quot;/&gt;
+    &lt;weblogic application=&quot;myapp&quot;
+              server=&quot;t3://myserver:7001&quot;
+              classpath=&quot;${weblogic.home}/lib/weblogic.jar&quot;
+              username=&quot;${user.name}&quot;
+              password=&quot;${user.password}&quot;/&gt;
+&lt;/serverdeploy&gt;</pre>
 
-<a name="serverdeploy_jonas">
-<h3>JOnAS (Java Open Application Server) element</h3>
-<p>
-The JOnAS element contains additional attributes to run the
-<code>JonasAdmin</code> deployment tool.
-<p>Valid actions for the tool are <code>deploy</code>, <code>undeploy</code>,
-<code>list</code> and <code>update</code>.
-<p>You can't use <code>user</code> and <code>password</code> property with this 
-task.
-<p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3 id="serverdeploy_jonas">JOnAS (Java Open Application Server) element</h3>
+<p>The JOnAS element contains additional attributes to run the <code>JonasAdmin</code> deployment
+tool.</p>
+<p>Valid actions for the tool are <q>deploy</q>, <q>undeploy</q>, <q>list</q> and <q>update</q>.</p>
+<p>You can't use <var>user</var> and <var>password</var> property with this task.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">jonasroot</td>
-    <td valign="top">The root directory for JOnAS.</td>
+    <td>jonasroot</td>
+    <td>The root directory for JOnAS.</td>
     <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">orb</td>
-    <td valign="top">Choose your ORB : RMI, JEREMIE, DAVID, ... If omitted, it defaults
-     to the one present in classpath. The corresponding JOnAS JAR is
-     automatically added to the classpath. If your orb is DAVID (RMI/IIOP) you must 
-     specify davidhost and davidport properties.</td>
+    <td>orb</td>
+    <td>Choose your ORB: <q>RMI</q>, <q>JEREMIE</q>, <q>DAVID</q>, ... The corresponding JOnAS JAR
+      is automatically added to the classpath. If your <var>orb</var> is <q>DAVID</q> (RMI/IIOP) you
+      must specify <var>davidhost</var> and <var>davidport</var> properties.</td>
+    <td>No; defaults to the ORB present in classpath</td>
+  </tr>
+  <tr>
+    <td>davidhost</td>
+    <td>The value for the system property: <code>david.CosNaming.default_host</code>.</td>
     <td>No</td>
   </tr>
   <tr>
-    <td valign="top">davidhost</td>
-    <td valign="top">The value for the system property : <code>david.CosNaming.default_host</code> .</td>
+    <td>davidport</td>
+    <td>The value for the system property: <code>david.CosNaming.default_port</code>.</td>
     <td>No</td>
   </tr>
   <tr>
-    <td valign="top">davidport</td>
-    <td valign="top">The value for the system property : <code>david.CosNaming.default_port</code> .</td>
-    <td>No</td>
+    <td>classname</td>
+    <td>This is the fully qualified classname of the Java based deployment tool to execute.</td>
+    <td>No; default is <code>org.objectweb.jonas.adm.JonasAdmin</code></td>
   </tr>
-  <tr>
-    <td valign="top">classname</td>
-    <td valign="top">This is the fully qualified classname of the Java based
-    deployment tool to execute. Default to <code>org.objectweb.jonas.adm.JonasAdmin</code></td>
-    <td>No</td>
-  </tr>
-
 </table>
 
-<h3>Nested Elements</h3>
-<p>The jonas element supports nested <code>&lt;arg&gt;</code> and <code>&lt;jvmarg&gt;</code> elements.</p>
-
+<h4>Nested elements</h4>
+<p>The <code>jonas</code> element supports nested <code>&lt;arg&gt;</code>
+and <code>&lt;jvmarg&gt;</code> elements.</p>
 
 <h3>Examples</h3>
 
-<p>This example shows the use of serverdeploy to deploy a component to a JOnAS server:</p>
+<p>This example shows the use of <code>serverdeploy</code> to deploy a component to a JOnAS
+server:</p>
 
 <pre>
-    &lt;serverdeploy action=&quot;deploy&quot; source=&quot;${lib.dir}/ejb_myApp.jar&quot;&gt;
-        &lt;jonas server=&quot;MyJOnAS&quot; jonasroot="${jonas.root}"&gt;
+&lt;serverdeploy action=&quot;deploy&quot; source=&quot;${lib.dir}/ejb_myApp.jar&quot;&gt;
+    &lt;jonas server=&quot;MyJOnAS&quot; jonasroot="${jonas.root}"&gt;
+       &lt;classpath&gt;
+           &lt;pathelement path=&quot;${jonas.root}/lib/RMI_jonas.jar&quot;/&gt;
+           &lt;pathelement path=&quot;${jonas.root}/config/&quot;/&gt;
+       &lt;/classpath&gt;
+    &lt;/jonas&gt;
+&lt;/serverdeploy&gt;</pre>
 
-           &lt;classpath&gt;
-               &lt;pathelement path=&quot;${jonas.root}/lib/RMI_jonas.jar&quot;/&gt;
-               &lt;pathelement path=&quot;${jonas.root}/config/&quot;/&gt;
-           &lt;/classpath&gt;
-        &lt;/jonas&gt;
-    &lt;/serverdeploy&gt;
-</pre>
-
-<p>This example shows serverdeploy being used to list the components from a
-JOnAS server and a WebLogic server:</p>
+<p>This example shows <code>serverdeploy</code> being used to list the components from a JOnAS
+server and a WebLogic server:</p>
 
 <pre>
-    &lt;serverdeploy action=&quot;list&quot;/&gt
-        &lt;jonas jonasroot=&quot;${jonas.root}&quot; orb=&quot;JEREMIE&quot;/&gt;
-        &lt;weblogic application=&quot;myapp&quot
-            server=&quot;t3://myserver:7001&quot;
-            classpath=&quot;${weblogic.home}/lib/weblogic.jar&quot;
-            username=&quot;${user.name}&quot;
-            password=&quot;${user.password}&quot;/&gt;
-    &lt;/serverdeploy&gt;
-</pre>
-
-
+&lt;serverdeploy action=&quot;list&quot;/&gt;
+    &lt;jonas jonasroot=&quot;${jonas.root}&quot; orb=&quot;JEREMIE&quot;/&gt;
+    &lt;weblogic application=&quot;myapp&quot;
+              server=&quot;t3://myserver:7001&quot;
+              classpath=&quot;${weblogic.home}/lib/weblogic.jar&quot;
+              username=&quot;${user.name}&quot;
+              password=&quot;${user.password}&quot;/&gt;
+&lt;/serverdeploy&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/setpermissions.html b/manual/Tasks/setpermissions.html
new file mode 100644
index 0000000..f6ac15e
--- /dev/null
+++ b/manual/Tasks/setpermissions.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+   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
+
+       https://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">
+
+<head>
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<title>SetPermissions Task</title>
+</head>
+
+<body>
+
+<h2 id="setpermissions">SetPermissions</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 arbitrary 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&mdash;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 class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>permissions</td>
+    <td>The permissions to set as comma separated list of names
+      of <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/file/attribute/PosixFilePermission.html"
+      target="_top">PosixFilePermission</a> values.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>mode</td>
+    <td>The permissions to set as traditional Unix three-digit octal number.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>nonPosixMode</td>
+    <td>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 <q>fail</q> (fail the
+      build), <q>pass</q> (just log an error), <q>tryDosOrFail</q> (at least try to set the
+      read-only flag on DOS file systems, fail if that isn't possible either)
+      and <q>tryDosOrPass</q> (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>No; defaults to <q>fail</q></td>
+  </tr>
+  <tr>
+    <td>failonerror</td>
+    <td>Whether to stop the build if setting permissions fails.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+</table>
+<h3>Parameters specified as nested elements</h3>
+
+<h4>any resource collection</h4>
+<p><a href="../Types/resources.html#collection">resource collections</a> are used to select groups
+of resources.</p>
+
+<h3>Examples</h3>
+
+<p>Make the <samp>start.sh</samp> file readable and executable for anyone and in addition writable
+by the owner.</p>
+<pre>
+&lt;setpermissions mode=&quot;755&quot;&gt;
+  &lt;file file=&quot;${dist}/start.sh&quot;/&gt;
+&lt;/setpermissions&gt;</pre>
+
+<p>Make the <samp>start.sh</samp> file readable and executable for anyone and in addition writable
+by the owner.</p>
+<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>
+</body>
+</html>
diff --git a/manual/Tasks/setproxy.html b/manual/Tasks/setproxy.html
index 245924c..cd5a2eb 100644
--- a/manual/Tasks/setproxy.html
+++ b/manual/Tasks/setproxy.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,207 +15,98 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-    
-<html>
+
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
+  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Setproxy Task</title>
 </head>
 
-<body bgcolor="#ffffff" text="#000000" link="#525D76"
-      alink="#525D76" vlink="#525D76">
+<body>
+<h2>Setproxy Task</h2>
 
-<table border="0" width="100%" cellspacing="4">
+<h3 id="description">Description</h3>
+<p>Sets Java's web proxy properties, so that tasks and code run in the same JVM can have
+through-the-firewall access to remote web sites, and remote FTP sites. You can nominate an HTTP and
+FTP proxy, or a SOCKS server, reset the server settings, or do nothing at all.</p>
 
-  <!-- PAGE HEADER -->
+<h3 id="attributes">Parameters</h3>
+<table class="attr">
   <tr>
-    <td>
-      <table border="0" width="100%"><tr>
-          <td valign="bottom">
-            <font size="+3" face="arial,helvetica,sanserif"><strong>Setproxy Task</strong></font>
-            <br><font face="arial,helvetica,sanserif">Sets Java's web proxy properties, so that tasks and code run in the same JVM can have through-the-firewall access to remote web sites, and remote ftp sites.</font>
-          </td>
-          <td>
-            <!-- PROJECT LOGO -->
-            <a href="http://ant.apache.org/">
-              <img src="../images/ant_logo_large.gif" align="right" alt="Apache Ant" border="0">
-            </a>
-          </td>
-      </tr></table>
-    </td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Type</th>
+    <th scope="col">Required</th>
   </tr>
-
-  <!-- START RIGHT SIDE MAIN BODY -->
   <tr>
-    <td  valign="top" align="left">
-
-          <!-- Applying task/long-description -->
-    <!-- Start Description -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="description">
-          <strong>Description</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-        Sets Java's web proxy properties, so that tasks and code run in the same JVM can have through-the-firewall access to remote web sites, and remote ftp sites. You can nominate an http and ftp proxy, or a socks server, reset the server settings, or do nothing at all. <p> Examples <pre>&lt;setproxy/&gt;</pre> do nothing <pre>&lt;setproxy proxyhost="firewall"/&gt;</pre> set the proxy to firewall:80 <pre>&lt;setproxy proxyhost="firewall" proxyport="81"/&gt;</pre> set the proxy to firewall:81 <pre>&lt;setproxy proxyhost=""/&gt;</pre> stop using the http proxy; don't change the socks settings <pre>&lt;setproxy socksproxyhost="socksy"/&gt;</pre> use socks via socksy:1080 <pre>&lt;setproxy socksproxyhost=""/&gt;</pre> stop using the socks server. <p> You can set a username and password for http with the <tt>proxyHost</tt> and <tt>proxyPassword</tt> attributes. On Java1.4 and above these can also be used against SOCKS5 servers. </p>
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Description -->
-
- <!-- Ignore -->
-
-
-
-    <!-- Start Attributes -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="attributes">
-          <strong>Parameters</strong></a></font>
-      </td></tr>
-      <tr><td><blockquote>
-        <table>
-          <tr>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Attribute</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Description</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Type</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Requirement</b></font>
-        </td>
-          </tr>
-    <!-- Attribute Group -->    
-    
-    <!-- Attribute Group -->    
-        <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">nonproxyhosts</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">A list of hosts to bypass the proxy on. These should be separated with the vertical bar character '|'. Only in Java 1.4 does ftp use this list. e.g. fozbot.corp.sun.com|*.eng.sun.com</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left" rowspan="7">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Optional</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">proxyhost</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">the HTTP/ftp proxy host. Set this to "" for the http proxy option to be disabled</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">proxypassword</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Set the password for the proxy. Used only if the proxyUser is set.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">proxyport</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">the HTTP/ftp proxy port number; default is 80</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">int</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">proxyuser</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">set the proxy user. Probably requires a password to accompany this setting. Default=""</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">socksproxyhost</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">The name of a Socks server. Set to "" to turn socks proxying off.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">socksproxyport</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Set the ProxyPort for socks connections. The default value is 1080</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">int</font>
-        </td>
-    </tr>
-
-
-        </table>
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Attributes -->
-
-    <!-- Start Elements -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="elements">
-          <strong>Parameters as nested elements</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Elements -->
-
-
-    </td>
+    <td>nonproxyhosts</td>
+    <td>A list of hosts to bypass the proxy on. These should be separated with the vertical bar
+      character <q>|</q>. Only in Java 1.4 does FTP use this
+      list. e.g. <samp>fozbot.corp.sun.com|*.eng.sun.com</samp></td>
+    <td>String</td>
+    <td>No</td>
   </tr>
-  <!-- END RIGHT SIDE MAIN BODY -->
-
+  <tr>
+    <td>proxyhost</td>
+    <td>the HTTP/FTP proxy host. Set this to <q></q> for the HTTP proxy option to be disabled.</td>
+    <td>String</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>proxypassword</td>
+    <td>Set the password for the proxy. Used only if the <var>proxyUser</var> is set.</td>
+    <td>String</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>proxyport</td>
+    <td>the HTTP/FTP proxy port number</td>
+    <td>int</td>
+    <td>No; default is <q>80</q></td>
+  </tr>
+  <tr>
+    <td>proxyuser</td>
+    <td>set the proxy user. Probably requires a password to accompany this setting.</td>
+    <td>String</td>
+    <td>No; default is <q></q></td>
+  </tr>
+  <tr>
+    <td>socksproxyhost</td>
+    <td>The name of a SOCKS server. Set to <q></q> to turn SOCKS proxying off.</td>
+    <td>String</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>socksproxyport</td>
+    <td>Set the ProxyPort for SOCKS connections.</td>
+    <td>int</td>
+    <td>No; default is <q>1080</q></td>
+  </tr>
 </table>
 
+<h3>Examples</h3>
+
+<p>Do nothing</p>
+<pre>&lt;setproxy/&gt;</pre>
+
+<p>Set the proxy to <samp>firewall:80</samp></p>
+<pre>&lt;setproxy proxyhost="firewall"/&gt;</pre>
+
+<p>Set the proxy to <samp>firewall:81</samp></p>
+<pre>&lt;setproxy proxyhost="firewall" proxyport="81"/&gt;</pre>
+
+<p>Stop using HTTP proxy; don't change SOCKS settings</p>
+<pre>&lt;setproxy proxyhost=""/&gt;</pre>
+
+<p>Use SOCKS via <samp>socksy:1080</samp></p>
+<pre>&lt;setproxy socksproxyhost="socksy"/&gt;</pre>
+
+<p>Stop using the SOCKS server</p>
+<pre>&lt;setproxy socksproxyhost=""/&gt;</pre>
+
+<p>You can set a username and password for HTTP with the <var>proxyHost</var>
+and <var>proxyPassword</var> attributes. On Java 1.4 and above, these can also be used against SOCKS
+5 servers.</p>
+
 </body>
 </html>
diff --git a/manual/Tasks/signjar.html b/manual/Tasks/signjar.html
index 88bdb43..26794d5 100644
--- a/manual/Tasks/signjar.html
+++ b/manual/Tasks/signjar.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,319 +15,298 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>SignJar Task</title>
 </head>
 
 <body>
 
-<h2><a name="signjar">SignJar</a></h2>
+<h2 id="signjar">SignJar</h2>
 <h3>Description</h3>
 <p>Signing a jar allows users to authenticate the publisher.</p>
-<p>Signs JAR files with the <a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html"><tt>jarsigner</tt> command line tool</a>.
-It will take a named file in the <tt>jar</tt> attribute, and an optional
-<tt>destDir</tt> or <tt>signedJar</tt> attribute. Nested paths are also
-supported; here only an (optional) <tt>destDir</tt> is allowed. If a destination
-directory or explicit JAR file name is not provided, JARs are signed in place.
-</p>
-<p>
-Dependency rules
-</p>
+<p>Signs JAR files with
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html"
+target="_top"><kbd>jarsigner</kbd></a> command line tool.  It will take a named file in
+the <var>jar</var> attribute, and an optional <var>destDir</var> or <var>signedJar</var>
+attribute. Nested paths are also supported; here only an (optional) <var>destDir</var> is
+allowed. If a destination directory or explicit JAR file name is not provided, JARs are signed in
+place.</p>
+<p>Dependency rules</p>
 <ul>
-<li>Nonexistent destination JARs are created/signed</li>
-<li>Out of date destination JARs are created/signed</li>
-<li>If a destination file and a source file are the same,
-and <tt>lazy</tt> is true, the JAR is only signed if it does not
-contain a signature by this alias.</li>
-<li>If a destination file and a source file are the same,
-and <tt>lazy</tt> is false, the JAR is signed.</li>
+  <li>Nonexistent destination JARs are created/signed</li>
+  <li>Out of date destination JARs are created/signed</li>
+  <li>If a destination file and a source file are the same, and <var>lazy</var> is <q>true</q>, the
+    JAR is only signed if it does not contain a signature by this alias.</li>
+  <li>If a destination file and a source file are the same, and <var>lazy</var> is <q>false</q>, the
+    JAR is signed.</li>
 </ul>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">jar</td>
-    <td valign="top">the jar file to sign</td>
-    <td valign="top" align="center">Yes, unless nested paths have
-      been used.</td>
+    <td>jar</td>
+    <td>the jar file to sign</td>
+    <td>Yes, unless nested paths have been used</td>
   </tr>
   <tr>
-    <td valign="top">alias</td>
-    <td valign="top">the alias to sign under</td>
-    <td valign="top" align="center">Yes.</td>
+    <td>alias</td>
+    <td>the alias to sign under</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">storepass</td>
-    <td valign="top">password for keystore integrity. Ant will not use
+    <td>storepass</td>
+    <td>password for keystore integrity. Ant will not use
     the <code>-storepass</code> command line argument but send the
     password to jarsigner when it prompts for it.</td>
-    <td valign="top" align="center">Yes.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">keystore</td>
-    <td valign="top">keystore location</td>
-    <td valign="top" align="center">No</td>
+    <td>keystore</td>
+    <td>keystore location</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">storetype</td>
-    <td valign="top">keystore type</td>
-    <td valign="top" align="center">No</td>
+    <td>storetype</td>
+    <td>keystore type</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keypass</td>
-    <td valign="top">password for private key (if different)</td>
-    <td valign="top" align="center">No</td>
+    <td>keypass</td>
+    <td>password for private key (if different)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sigfile</td>
-    <td valign="top">name of .SF/.DSA file</td>
-    <td valign="top" align="center">No</td>
+    <td>sigfile</td>
+    <td>name of <samp>.SF</samp>/<samp>.DSA</samp> file</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">signedjar</td>
-    <td valign="top">name of signed JAR file. This can only be set when
-    the <tt>jar</tt> attribute is set.</td>
-    <td valign="top" align="center">No.</td>
+    <td>signedjar</td>
+    <td>name of signed JAR file. This can only be set when the <var>jar</var> attribute is set.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">(true | false) verbose output when signing</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>verbose</td>
+    <td>(<q>true|false</q>) verbose output when signing</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">strict</td>
-    <td valign="top">(true | false) strict checking when signing.<br/><em>since Ant 1.9.1</em>.</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>strict</td>
+    <td>(<q>true|false</q>) strict checking when signing.<br/><em>since Ant 1.9.1</em>.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">internalsf</td>
-    <td valign="top">(true | false) include the .SF file inside the signature
-block</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>internalsf</td>
+    <td>(<q>true|false</q>) include the <samp>.SF</samp> file inside the signature block</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">sectionsonly</td>
-    <td valign="top">(true | false) don't compute hash of entire manifest</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>sectionsonly</td>
+    <td>(<q>true|false</q>) don't compute hash of entire manifest</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">lazy</td>
-    <td valign="top">flag to control whether the presence of a signature
-  file means a JAR is signed. This is only used when the target JAR matches
-  the source JAR</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>lazy</td>
+    <td>flag to control whether the presence of a signature file means a JAR is signed. This is only
+      used when the target JAR matches the source JAR</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Specifies the maximum memory the jarsigner VM will use. Specified in the
-                     style of standard java memory specs (e.g. 128m = 128 MBytes)</td>
-    <td valign="top" align="center">No</td>
+    <td>maxmemory</td>
+    <td>Specifies the maximum memory the <kbd>jarsigner</kbd> JVM will use. Specified in the style
+      of standard Java memory specs (e.g. <q>128m</q> = 128 MBytes)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">preservelastmodified</td>
-    <td valign="top">Give the signed files the same last modified
-      time as the original jar files.</td>
-    <td valign="top" align="center">No; default false.</td>
+    <td>preservelastmodified</td>
+    <td>Give the signed files the same last modified time as the original jar files.</td>
+    <td>No; default <q>false</q>.</td>
   </tr>
   <tr>
-    <td valign="top">tsaurl</td>
-    <td valign="top">URL for a timestamp authority for timestamped
-    JAR files in Java1.5+</td>
-    <td valign="top" align="center">No</td>
+    <td>tsaurl</td>
+    <td>URL for a timestamp authority for timestamped JAR files in Java 5+</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">tsacert</td>
-    <td valign="top">alias in the keystore for a timestamp authority for
-    timestamped JAR files in Java1.5+</td>
-    <td valign="top" align="center">No</td>
+    <td>tsacert</td>
+    <td>alias in the keystore for a timestamp authority for timestamped JAR files in Java 5+</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">tsaproxyhost</td>
-    <td valign="top">proxy host to be used when connecting to TSA server</td>
-    <td valign="top" align="center">No</td>
+    <td>tsaproxyhost</td>
+    <td>proxy host to be used when connecting to TSA server</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">tsaproxyport</td>
-    <td valign="top">proxy port to be used when connecting to TSA server</td>
-    <td valign="top" align="center">No</td>
+    <td>tsaproxyport</td>
+    <td>proxy port to be used when connecting to TSA server</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">Specify a particular <code>jarsigner</code> executable
-      to use in place of the default binary (found in the same JDK as
-      Apache Ant is running in).<br/>
-      Must support the same command line options as the Sun JDK
-      jarsigner command.
-      <em>since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No</td>
+    <td>executable</td>
+    <td>Specify a particular <kbd>jarsigner</kbd> executable to use in place of the default binary
+      (found in the same JDK as Apache Ant is running in).<br/>Must support the same command line
+      options as the Sun JDK <kbd>jarsigner</kbd> command.  <em>since Ant 1.8.0</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">Whether to force signing of the jar file even if
-      it doesn't seem to be out of date or already signed.
-      <em>since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No; default false</td>
+    <td>force</td>
+    <td>Whether to force signing of the jar file even if it doesn't seem to be out of date or
+      already signed.  <em>since Ant 1.8.0</em>.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">sigalg</td>
-    <td valign="top">name of signature algorithm</td>
-    <td valign="top" align="center">No</td>
+    <td>sigalg</td>
+    <td>name of signature algorithm</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">digestalg</td>
-    <td valign="top">name of digest algorithm</td>
-    <td valign="top" align="center">No</td>
+    <td>digestalg</td>
+    <td>name of digest algorithm</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">providername</td>
-    <td valign="top">name of a cryptographic service provider's name
+    <td>tsadigestalg</td>
+    <td>name of TSA digest algorithm. <em>since Ant 1.10.2</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>providername</td>
+    <td>name of a cryptographic service provider's name
       when listed in the security properties file.
-      <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+      <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">providerclass</td>
-    <td valign="top">name of a cryptographic service provider's master
+    <td>providerclass</td>
+    <td>name of a cryptographic service provider's master
       class file when the service provider is not listed in the security
       properties file.
-      <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+      <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">providerarg</td>
-    <td valign="top">Represents an optional string input argument for
+    <td>providerarg</td>
+    <td>Represents an optional string input argument for
       the constructor of provider_class_name. Ignored
       if <code>providerclass</code> is not set.
-      <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+      <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Parameters as nested elements</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">path</td>
-    <td valign="top">path of JAR files to sign. <em>since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
+    <td>path</td>
+    <td>path of JAR files to sign. <em>since Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">fileset</td>
-    <td valign="top">fileset of JAR files to sign. </td>
-    <td valign="top" align="center">No</td>
+    <td>fileset</td>
+    <td>fileset of JAR files to sign.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">mapper</td>
-    <td valign="top">A mapper to rename jar files during signing</td>
-    <td valign="top" align="center">No, and only one can be supplied</td>
+    <td>mapper</td>
+    <td>A mapper to rename jar files during signing</td>
+    <td>No, and only one can be supplied</td>
   </tr>
   <tr>
-    <td valign="top">sysproperty</td>
-    <td valign="top">JVM system properties, with the syntax of Ant
-    <a href="exec.html#env">environment variables</a> </td>
-    <td valign="top" align="center">No, and only one can be supplied</td>
+    <td>sysproperty</td>
+    <td>JVM system properties, with the syntax of Ant <a href="exec.html#env">environment
+      variables</a></td>
+    <td>No, and only one can be supplied</td>
   </tr>
   <tr>
-    <td valign="top">arg</td>
-    <td valign="top">Use this to specify a <code>keytool</code>
+    <td>arg</td>
+    <td>Use this to specify a <kbd>keytool</kbd>
     <a href="../using.html#arg">command line argument</a> not
     explicitly supported via an attribute.
-    <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+    <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
 </table>
 
-
 <h3>Examples</h3>
-<p>For instructions on generating a code signing certificate, see the <a target="_blank" href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/keytool.html">keytool documentation</a> and/or instructions from your certificate authority.</p>
-  <blockquote><pre>
-&lt;signjar jar=&quot;${dist}/lib/ant.jar&quot;
-alias=&quot;apache-group&quot; storepass=&quot;secret&quot;/&gt;
-</pre></blockquote>
-<p>
-  signs the ant.jar with alias &quot;apache-group&quot; accessing the
-  keystore and private key via &quot;secret&quot; password.
-</p>
-  <blockquote><pre>
-&lt;signjar destDir="signed"
-    alias="testonly" keystore="testkeystore"
-    storepass="apacheant"
-    preservelastmodified="true"&gt;
-  &lt;path&gt;
-    &lt;fileset dir="dist" includes="**/*.jar" /&gt;
-  &lt;/path&gt;
-  &lt;flattenmapper /&gt;
-&lt;/signjar&gt;
-</pre></blockquote>
-<p>
-Sign all JAR files matching the dist/**/*.jar pattern, copying them to the
-directory "signed" afterwards. The flatten mapper means that they will
-all be copied to this directory, not to subdirectories.
+<p>For instructions on generating a code signing certificate, see
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html"
+target="_top">keytool documentation</a> and/or instructions from your certificate authority.</p>
 
-</p>
-  <blockquote><pre>
-&lt;signjar
-    alias="testonly" keystore="testkeystore"
-    storepass="apacheant"
-    lazy="true"
-    &gt;
+<p>Sign the <samp>ant.jar</samp> with alias <q>apache-group</q> accessing the keystore and private
+key via <q>secret</q> password.</p>
+<pre>
+&lt;signjar jar=&quot;${dist}/lib/ant.jar&quot;
+         alias=&quot;apache-group&quot; storepass=&quot;secret&quot;/&gt;</pre>
+
+<p>Sign all JAR files matching the <samp>dist/**/*.jar</samp> pattern, copying them to the
+directory <samp>signed</samp> afterwards. The flatten mapper means that they will all be copied to
+this directory, not to subdirectories.</p>
+<pre>
+&lt;signjar destDir="signed"
+         alias="testonly" keystore="testkeystore"
+         storepass="apacheant"
+         preservelastmodified="true"&gt;
   &lt;path&gt;
-    &lt;fileset dir="dist" includes="**/*.jar" /&gt;
+    &lt;fileset dir="dist" includes="**/*.jar"/&gt;
   &lt;/path&gt;
-&lt;/signjar&gt;
-</pre></blockquote>
-<p>
-Sign all the JAR files in dist/**/*.jar <i>in-situ</i>. Lazy signing is used,
-so the files will only be signed if they are not already signed.
-</p>
-  <blockquote><pre>
-&lt;signjar
-    alias="testonly" keystore="testkeystore"
-    storepass="apacheant"
-    sigalg="MD5withRSA"
-    digestalg="SHA1"&gt;
+  &lt;flattenmapper/&gt;
+&lt;/signjar&gt;</pre>
+
+<p>Sign all the JAR files in <samp>dist/**/*.jar</samp> <em>in-situ</em>. Lazy signing is used, so
+the files will only be signed if they are not already signed.</p>
+<pre>
+&lt;signjar alias="testonly" keystore="testkeystore"
+         storepass="apacheant"
+         lazy="true"&gt;
   &lt;path&gt;
-    &lt;fileset dir="dist" includes="**/*.jar" /&gt;
+    &lt;fileset dir="dist" includes="**/*.jar"/&gt;
   &lt;/path&gt;
-&lt;/signjar&gt;
-</pre></blockquote>
-<p>
-Sign all the JAR files in dist/**/*.jar using the digest algorithm SHA1 and the
-signature algorithm MD5withRSA. This is especially useful when you want to use
-the JDK 7 jarsigner (which uses SHA256 and SHA256withRSA as default) to create
-signed jars that will be deployed on platforms not supporting SHA256 and
-SHA256withRSA.
-</p>
+&lt;/signjar&gt;</pre>
+
+<p>Sign all the JAR files in <samp>dist/**/*.jar</samp> using the digest algorithm SHA1 and the
+signature algorithm MD5withRSA. This is especially useful when you want to use the JDK
+7 <kbd>jarsigner</kbd> (which uses SHA256 and SHA256withRSA as default) to create signed jars that
+will be deployed on platforms not supporting SHA256 and SHA256withRSA.</p>
+<pre>
+&lt;signjar alias="testonly" keystore="testkeystore"
+         storepass="apacheant"
+         sigalg="MD5withRSA"
+         digestalg="SHA1"&gt;
+  &lt;path&gt;
+    &lt;fileset dir="dist" includes="**/*.jar"/&gt;
+  &lt;/path&gt;
+&lt;/signjar&gt;</pre>
+
 <h3>About timestamp signing</h3>
 
-<p>Timestamps record the date and time that a signature took place, allowing the signature to be verified as of that point in time.
-With trusted timestamping, users can verify that signing occurred before a certificate's expiration or revocation. Without this timestamp, users can only verify the signature as of their current date.</p>
+<p>Timestamps record the date and time that a signature took place, allowing the signature to be
+verified as of that point in time.  With trusted timestamping, users can verify that signing
+occurred before a certificate's expiration or revocation. Without this timestamp, users can only
+verify the signature as of their current date.</p>
 
-<p>
-Timestamped JAR files were introduced in Java1.5 and supported in Ant since
-Ant 1.7. Since Ant 1.9.5, Ant can use unauthenticated proxies for this signing process.
-</p>
+<p>Timestamped JAR files were introduced in Java 5; they are supported <em>since Ant
+1.7</em>. Unauthenticated proxies can be used to access TSAs <em>since Ant 1.9.5</em>.</p>
 
-<p>Common public timestamp authorities include
-  <ul>
-    <li>http://timestamp.verisign.com</li>
-	<li>http://tsa.starfieldtech.com</li>
-	<li>https://timestamp.geotrust.com/tsa</li>
-	<li>Others (see your certificate authority)</li>
-  </ul></p>
+<p>Common public timestamp authorities include</p>
+<ul>
+  <li>http://timestamp.verisign.com</li>
+  <li>http://tsa.starfieldtech.com</li>
+  <li>https://timestamp.geotrust.com/tsa</li>
+  <li>Others (see your certificate authority)</li>
+</ul>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/sleep.html b/manual/Tasks/sleep.html
index 80827b5..9b8b995 100644
--- a/manual/Tasks/sleep.html
+++ b/manual/Tasks/sleep.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
@@ -23,63 +24,61 @@
 
 <body>
 
-<h2><a name="sleep">Sleep</a></h2>
+<h2 id="sleep">Sleep</h2>
 <h3>Description</h3>
-<p> A task for sleeping a short period of time, useful when a build or deployment 
-  process requires an interval between tasks.</p>
+<p>A task for sleeping a short period of time, useful when a build or deployment process requires an
+interval between tasks.</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>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
-  <tr> 
-    <td valign="top">hours</td>
-    <td valign="top">hours to to add to the sleep time</td>
-    <td valign="top" align="center">No</td>
+  <tr>
+    <td>hours</td>
+    <td>hours to to add to the sleep time</td>
+    <td>No</td>
   </tr>
-  <tr> 
-    <td valign="top">minutes</td>
-    <td valign="top"> minutes to add to the sleep time</td>
-    <td valign="top" align="center">No</td>
+  <tr>
+    <td>minutes</td>
+    <td>minutes to add to the sleep time</td>
+    <td>No</td>
   </tr>
-  <tr> 
-    <td valign="top">seconds</td>
-    <td valign="top">seconds to add to the sleep time</td>
-    <td align="center" valign="top">No</td>
+  <tr>
+    <td>seconds</td>
+    <td>seconds to add to the sleep time</td>
+    <td>No</td>
   </tr>
-  <tr> 
-    <td valign="top">milliseconds</td>
-    <td valign="top">milliseconds to add to the sleep time</td>
-    <td align="center" valign="top">No</td>
+  <tr>
+    <td>milliseconds</td>
+    <td>milliseconds to add to the sleep time</td>
+    <td>No</td>
   </tr>
-  <tr> 
-    <td valign="top">failonerror</td>
-    <td valign="top">flag controlling whether to break the build on an error. 
-    </td>
-    <td align="center" valign="top">No</td>
+  <tr>
+    <td>failonerror</td>
+    <td>flag controlling whether to break the build on an error</td>
+    <td>No</td>
   </tr>
 </table>
-<p>The sleep time is the sum of specified values, hours, minutes seconds and milliseconds. 
-  A negative value can be supplied to any of them provided the total sleep time 
-  is positive</p>
-<p>Note that sleep times are always hints to be interpred by the OS how it feels 
-  - small times may either be ignored or rounded up to a minimum timeslice. Note 
-  also that the system clocks often have a fairly low granularity too, which complicates 
-  measuring how long a sleep actually took.</p>
+<p>The sleep time is the sum of specified values, hours, minutes seconds and milliseconds.  A
+negative value can be supplied to any of them provided the total sleep time is positive</p>
+<p>Note that sleep times are always hints to be interpreted by the OS how it feels&mdash;small times
+may either be ignored or rounded up to a minimum timeslice. Note also that the system clocks often
+have a fairly low granularity too, which complicates measuring how long a sleep actually took.</p>
 <h3>Examples</h3>
-<pre>   &lt;sleep milliseconds=&quot;10&quot;/&gt;</pre>
-Sleep for about 10 mS. 
-<pre>   &lt;sleep seconds=&quot;2&quot;/&gt;</pre>
-Sleep for about 2 seconds. 
-<pre>   &lt;sleep hours=&quot;1&quot; minutes=&quot;-59&quot; seconds=&quot;-58&quot;/&gt;</pre>
-<p>Sleep for one hour less 59:58, or two seconds again </p>
-<pre>   &lt;sleep/&gt;</pre>
-Sleep for no time at all. This may yield the CPU time to another thread or process. 
+<p>Sleep for about 10 ms.</p>
+<pre>&lt;sleep milliseconds=&quot;10&quot;/&gt;</pre>
 
+<p>Sleep for about 2 seconds.</p>
+<pre>&lt;sleep seconds=&quot;2&quot;/&gt;</pre>
+
+<p>Sleep for one hour less 59:58, or two seconds again.</p>
+<pre>&lt;sleep hours=&quot;1&quot; minutes=&quot;-59&quot; seconds=&quot;-58&quot;/&gt;</pre>
+
+<p>Sleep for no time at all. This may yield the CPU time to another thread or process.</p>
+<pre>&lt;sleep/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/sos.html b/manual/Tasks/sos.html
index c068263..45305e4 100644
--- a/manual/Tasks/sos.html
+++ b/manual/Tasks/sos.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,182 +15,171 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-
-  <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
   <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>SOS Tasks</title>
-
+  <title>SOS Tasks</title>
 </head>
 <body>
 
-<div align="center">
 <h1>SourceOffSite Tasks User Manual</h1>
-
-<div align="left">by
+<p>by</p>
 <ul>
-<li><a href="mailto:jesse@cryptocard.com">Jesse Stockall</a></li>
+  <li><a href="mailto:jesse@cryptocard.com">Jesse Stockall</a></li>
 </ul>
-Version 1.1 2002/01/23
-<br>
-<br>
+<p>Version 1.1 2002/01/23</p>
 
-<hr width="100%" size="2">
+<hr/>
 <h2>Contents</h2>
 
 <ul>
-    <li><a href="#intro">Introduction</a></li>
-    <li><a href="#tasks">The Tasks</a></li>
-
+  <li><a href="#intro">Introduction</a></li>
+  <li><a href="#tasks">The Tasks</a></li>
 </ul>
-<br>
 
-<h2><a name="intro">Introduction</a> </h2>
+<h2 id="intro">Introduction</h2>
 
-<p>These tasks provide an interface to the <a href="http://msdn.microsoft.com/ssafe/default.asp" target="_top">
-Microsoft Visual SourceSafe</a> SCM via <a href="http://www.sourcegear.com">
-SourceGear's</a> <a href="http://sourcegear.com/sos/index.htm">SourceOffSite</a>
-product. SourceOffSite is an add-on to Microsoft's VSS, that allows remote
-development teams and tele-commuters that need fast and secure read/write
-access to a centralized SourceSafe database via any TCP/IP connection. SOS
-provides Linux ,Solaris &amp; Windows clients. The
-<code> org.apache.tools.ant.taskdefs.optional.sos</code>
-package consists  of a simple framework to support SOS functionality as well
-as some Apache Ant tasks  encapsulating frequently used SOS commands.  Although it
-is possible to use  these commands on the desktop,  they were primarily intended
-to be used by  automated build systems. These tasks have been tested with
-SourceOffSite  version 3.5.1 connecting to VisualSourceSafe 6.0. The tasks
-have been tested with Linux, Solaris &amp; Windows2000.</p>
+<p>These tasks provide an interface to
+the <a href="https://msdn.microsoft.com/en-us/library/3h0544kx(v=vs.80).aspx"
+target="_top">Microsoft Visual SourceSafe</a> SCM via <a href="https://sourcegear.com"
+target="_top">SourceGear's</a> <a href="https://sourcegear.com/sos/" target="_top">SourceOffSite</a>
+product. SourceOffSite is an add-on to Microsoft's VSS, that allows remote development teams and
+tele-commuters that need fast and secure read/write access to a centralized SourceSafe database via
+any TCP/IP connection. SOS provides Linux, Solaris &amp; Windows
+clients. The <code class="code">org.apache.tools.ant.taskdefs.optional.sos</code> package consists
+of a simple framework to support SOS functionality as well as some Apache Ant tasks encapsulating
+frequently used SOS commands.  Although it is possible to use these commands on the desktop, they
+were primarily intended to be used by automated build systems. These tasks have been tested with
+SourceOffSite version 3.5.1 connecting to VisualSourceSafe 6.0. The tasks have been tested with
+Linux, Solaris &amp; Windows 2000.</p>
 
-<h2><a name="tasks">The Tasks</a> </h2>
+<h2 id="tasks">The Tasks</h2>
 
-<table border="0" cellspacing="0" cellpadding="3">
-       <tbody>
-         <tr>
-           <td><a href="#SOSGet">sosget</a></td>
-           <td>Retrieves a read-only copy of the specified project or file.</td>
-         </tr>
-         <tr>
-           <td><a href="#SOSLabel">soslabel</a></td>
-           <td>Assigns a label to the specified project.</td>
-         </tr>
-         <tr>
-           <td><a href="#SOSCheckIn">soscheckin</a></td>
-           <td>Updates VSS with changes made to a checked out file or project,
-           and unlocks the VSS master copy.</td>
-         </tr>
-         <tr>
-           <td><a href="#SOSCheckOut">soscheckout</a></td>
-           <td>Retrieves a read-write copy of the specified project
-           or file, locking the&nbsp;VSS master copy</td>
-         </tr>
-
+<table>
+  <tbody>
+    <tr>
+      <td><a href="#SOSGet">sosget</a></td>
+      <td>Retrieves a read-only copy of the specified project or file.</td>
+    </tr>
+    <tr>
+      <td><a href="#SOSLabel">soslabel</a></td>
+      <td>Assigns a label to the specified project.</td>
+    </tr>
+    <tr>
+      <td><a href="#SOSCheckIn">soscheckin</a></td>
+      <td>Updates VSS with changes made to a checked out file or project,
+        and unlocks the VSS master copy.</td>
+    </tr>
+    <tr>
+      <td><a href="#SOSCheckOut">soscheckout</a></td>
+      <td>Retrieves a read-write copy of the specified project or file, locking the VSS master
+        copy</td>
+    </tr>
   </tbody>
 </table>
-     <br>
-
-<hr width="100%" size="2">
+<hr/>
 <h2>Task Descriptions</h2>
 
-<h2><a name="SOSGet"></a>SOSGet<br>
-     </h2>
+<h2 id="SOSGet">SOSGet</h2>
 <h3>Description</h3>
-             Task to perform GET commands with SOS<br>
+<p>Task to perform <var>Get</var> commands with SOS</p>
 <h3>Parameters</h3>
-     </div>
-     </div>
 
-<table border="1">
-     <tbody>
-       <tr>
-          <th>Attribute</th>
-          <th>Values</th>
-          <th>Required</th>
-        </tr>
-        <tr>
-          <td>soscmd</td>
-          <td>Directory which contains soscmd(.exe) <br>
-          soscmd(.exe) must be in the path if this is not specified</td>
-          <td>No</td>
-        </tr>
-        <tr>
-           <td>vssserverpath</td>
-           <td>path to the srcsafe.ini  - eg. \\server\vss\srcsafe.ini</td>
-           <td>Yes</td>
-        </tr>
-        <tr>
-           <td>sosserverpath</td>
-           <td>address &amp; port of the SOS server  - eg. 192.168.0.1:8888</td>
-           <td>Yes</td>
-        </tr>
-        <tr>
-           <td>projectpath</td>
-           <td>SourceSafe project path - eg. $/SourceRoot/Project1</td>
-           <td>Yes</td>
-        </tr>
-        <tr>
-           <td>file</td>
-           <td>Filename to act upon<br>
-           If no file is specified then act upon the project</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>username</td>
-           <td>SourceSafe username</td>
-           <td>Yes</td>
-        </tr>
-        <tr>
-           <td>password</td>
-           <td>SourceSafe password</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>localpath</td>
-           <td>Override the working directory and get to the specified path</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>soshome</td>
-           <td>The path to the SourceOffSite home directory</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>nocompress</td>
-           <td>true or false - disable compression</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>recursive</td>
-           <td>true or false - Only works with the GetProject command</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>version</td>
-           <td>a version number to get - Only works with the GetFile command</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>label</td>
-           <td>a label version to get - Only works with the GetProject command</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>nocache</td>
-           <td>true or false - Only needed if SOSHOME is set as an environment variable</td>
-           <td>No</td>
-        </tr>
-        <tr>
-           <td>verbose</td>
-           <td>true or false - Status messages are displayed</td>
-           <td>No</td>
-        </tr>
+<table class="attr">
+  <thead>
+    <tr>
+      <th scope="col">Attribute</th>
+      <th scope="col">Values</th>
+      <th scope="col">Required</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>soscmd</td>
+      <td>Directory which contains <kbd>soscmd(.exe)</kbd></td>
+      <td>No; by default, the executable must be in the path</td>
+    </tr>
+    <tr>
+      <td>vssserverpath</td>
+      <td>path to the <samp>srcsafe.ini</samp>&mdash;eg. <samp>\\server\vss\srcsafe.ini</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>sosserverpath</td>
+      <td>address &amp; port of the SOS server&mdash;eg. <samp>192.168.0.1:8888</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>projectpath</td>
+      <td>SourceSafe project path&mdash;eg. <samp>$/SourceRoot/Project1</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>file</td>
+      <td>Filename to act upon</td>
+      <td>No; by default, act upon the project</td>
+    </tr>
+    <tr>
+      <td>username</td>
+      <td>SourceSafe username</td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>password</td>
+      <td>SourceSafe password</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>localpath</td>
+      <td>Override the working directory and get to the specified path</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>soshome</td>
+      <td>The path to the SourceOffSite home directory</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>nocompress</td>
+      <td><q>true|false</q>&mdash;disable compression</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>recursive</td>
+      <td><q>true|false</q>&mdash;Only works with the <var>GetProject</var> command</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>version</td>
+      <td>a version number to get&mdash;Only works with the <var>GetFile</var> command</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>label</td>
+      <td>a label version to get&mdash;Only works with the <var>GetProject</var> command</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>nocache</td>
+      <td><q>true|false</q>&mdash;Only needed if <code>SOSHOME</code> is set as an environment
+        variable</td>
+      <td>No</td>
+    </tr>
+    <tr>
+      <td>verbose</td>
+      <td><q>true|false</q>&mdash;Status messages are displayed</td>
+      <td>No</td>
+    </tr>
   </tbody>
 </table>
 
 <h3>Example</h3>
 
+<p>Connect to a SourceOffsite server on <samp>192.168.10.6:8888</samp>
+with <q>build</q>, <q>build</q> as the username &amp; password. The SourceSafe database resides on
+the same box as the SOS server &amp; the VSS database is at <samp>d:\vss\srcsafe.ini</samp>. Do a
+recursive <var>GetProject</var> on <samp>$/SourceRoot/project1</samp>, using <samp>tmp</samp> as the
+working directory.</p>
 <pre>
 &lt;sosget verbose=&quot;true&quot;
         recursive=&quot;true&quot;
@@ -198,183 +188,182 @@
         localpath=&quot;tmp&quot;
         projectpath=&quot;$/SourceRoot/project1&quot;
         sosserverpath=&quot;192.168.10.6:8888&quot;
-        vssserverpath=&quot;d:\vss\srcsafe.ini&quot;/&gt;
-</pre>
-<small>Connects to a SourceOffsite server on 192.168.10.6:8888 with
-build,build as the username &amp; password. The SourceSafe  database resides
-on the same box as the SOS server  &amp; the VSS database  is at
-&quot;d:\vss\srcsafe.ini&quot; Does a recursive GetProject on
-$/SourceRoot/project1, using tmp as the working
-directory. </small><br>
-<br>
+        vssserverpath=&quot;d:\vss\srcsafe.ini&quot;/&gt;</pre>
 
-<hr width="100%" size="2">
-<h2><a name="SOSLabel"></a>SOSLabel</h2>
+<hr/>
+<h2 id="SOSLabel">SOSLabel</h2>
 
 <h3>Description</h3>
-             Task to perform Label commands with SOS<br>
+<p>Task to perform <var>Label</var> commands with SOS</p>
 <h3>Parameters</h3>
 
-<table border="1">
-    <tbody><tr>
-      <th>Attribute</th>
-      <th>Values</th>
-      <th>Required</th>
+<table class="attr">
+  <thead>
+    <tr>
+      <th scope="col">Attribute</th>
+      <th scope="col">Values</th>
+      <th scope="col">Required</th>
     </tr>
+  </thead>
+  <tbody>
     <tr>
       <td>soscmd</td>
-      <td>Directory which contains soscmd(.exe) <br>
-      soscmd(.exe) must be in the path if this is not specified</td>
+      <td>Directory which contains <kbd>soscmd(.exe)</kbd></td>
+      <td>No; by default, the executable must be in the path</td>
+    </tr>
+    <tr>
+      <td>vssserverpath</td>
+      <td>path to the <samp>srcsafe.ini</samp>&mdash;eg. <samp>\\server\vss\srcsafe.ini</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>sosserverpath</td>
+      <td>address and port of the SOS server&mdash;eg. <samp>192.168.0.1:8888</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>projectpath</td>
+      <td>SourceSafe project path&mdash;eg. <samp>$/SourceRoot/Project1</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>username</td>
+      <td>SourceSafe username</td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>password</td>
+      <td>SourceSafe password</td>
       <td>No</td>
     </tr>
     <tr>
-       <td>vssserverpath</td>
-       <td>path to the srcsafe.ini  - eg. \\server\vss\srcsafe.ini</td>
-       <td>Yes</td>
+      <td>label</td>
+      <td>The label to apply to a project</td>
+      <td>Yes</td>
     </tr>
     <tr>
-       <td>sosserverpath</td>
-       <td>address and port of the SOS server  - eg. 192.168.0.1:8888</td>
-       <td>Yes</td>
-    </tr>
-    <tr>
-       <td>projectpath</td>
-       <td>SourceSafe project path - eg. $/SourceRoot/Project1</td>
-       <td>Yes</td>
-    </tr>
-    <tr>
-       <td>username</td>
-       <td>SourceSafe username</td>
-       <td>Yes</td>
-    </tr>
-    <tr>
-       <td>password</td>
-       <td>SourceSafe password</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>label</td>
-       <td>The label to apply to a project</td>
-       <td>Yes</td>
-    </tr>
-    <tr>
-       <td>comment</td>
-       <td>A comment to be applied to all files being labeled</td>
-       <td>No</td>
+      <td>comment</td>
+      <td>A comment to be applied to all files being labeled</td>
+      <td>No</td>
     </tr>
     <tr>
        <td>verbose</td>
-       <td>true or false - Status messages are displayed</td>
+       <td><q>true|false</q>&mdash;Status messages are displayed</td>
        <td>No</td>
     </tr>
   </tbody>
 </table>
 
 <h3>Example</h3>
+
+<p>Connect to a SourceOffsite server on <samp>192.168.10.6:8888</samp>
+with <q>build</q>, <q>build</q> as the username &amp; password. The SourceSafe database resides on
+the same box as the SOS server &amp; the VSS database is at <samp>d:\vss\srcsafe.ini</samp>. Label
+the <samp>$/SourceRoot/project1</samp> project with <q>test label</q>.</p>
 <pre>
 &lt;soslabel username=&quot;build&quot;
           password=&quot;build&quot;
           label=&quot;test label&quot;
           projectpath=&quot;$/SourceRoot/project1&quot;
           sosserverpath=&quot;192.168.10.6:8888&quot;
-          vssserverpath=&quot;d:\vss\srcsafe.ini&quot;/&gt;
-</pre>
+          vssserverpath=&quot;d:\vss\srcsafe.ini&quot;/&gt;</pre>
 
-<small>Connects to a SourceOffsite server on 192.168.10.6:8888 with
-build,build as the username &amp; password. The SourceSafe database resides
-on the same box as  the  SOS server  &amp; the VSS database is at
-&quot;d:\vss\srcsafe.ini&quot;. Labels the $/SourceRoot/project1
-project with &quot;test label&quot;.</small><br>
-<br>
-
-<hr width="100%" size="2"><br>
-
-<h2><a name="SOSCheckIn"></a>SOSCheckIn</h2>
+<hr/>
+<h2 id="SOSCheckIn">SOSCheckIn</h2>
 
 <h3>Description</h3>
-        Task to perform CheckIn commands with SOS<br>
+<p>Task to perform <var>CheckIn</var> commands with SOS</p>
 <h3>Parameters</h3>
-<table border="1">
-       <tbody>
+<table class="attr">
+  <thead>
     <tr>
-      <th>Attribute</th>
-      <th>Values</th>
-      <th>Required</th>
+      <th scope="col">Attribute</th>
+      <th scope="col">Values</th>
+      <th scope="col">Required</th>
     </tr>
+  </thead>
+  <tbody>
     <tr>
       <td>soscmd</td>
-      <td>Directory which contains soscmd(.exe) <br>
-      soscmd(.exe) must be in the path if this is not specified</td>
+      <td>Directory which contains <kbd>soscmd(.exe)</kbd></td>
+      <td>No; by default, the executable must be in the path</td>
+    </tr>
+    <tr>
+      <td>vssserverpath</td>
+      <td>path to the <samp>srcsafe.ini</samp>&mdash;eg. <samp>\\server\vss\srcsafe.ini</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>sosserverpath</td>
+      <td>address and port of the SOS server&mdash;eg. <samp>192.168.0.1:8888</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>projectpath</td>
+      <td>SourceSafe project path&mdash;eg. <samp>$/SourceRoot/Project1</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>file</td>
+      <td>Filename to act upon</td>
+      <td>No; by default, act upon the project</td>
+    </tr>
+    <tr>
+      <td>username</td>
+      <td>SourceSafe username</td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>password</td>
+      <td>SourceSafe password</td>
       <td>No</td>
     </tr>
     <tr>
-       <td>vssserverpath</td>
-       <td>path to the srcsafe.ini  - eg. \\server\vss\srcsafe.ini</td>
-       <td>Yes</td>
+      <td>localpath</td>
+      <td>Override the working directory and get to the specified path</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>sosserverpath</td>
-       <td>address and port of the SOS server  - eg. 192.168.0.1:8888</td>
-       <td>Yes</td>
+      <td>soshome</td>
+      <td>The path to the SourceOffSite home directory</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>projectpath</td>
-       <td>SourceSafe project path - eg. $/SourceRoot/Project1</td>
-       <td>Yes</td>
+      <td>nocompress</td>
+      <td><q>true|false</q>&mdash;disable compression</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>file</td>
-       <td>Filename to act upon<br> If no file is specified then act upon the project</td>
-       <td>No</td>
+      <td>recursive</td>
+      <td><q>true|false</q>&mdash;Only works with the <var>CheckOutProject</var> command</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>username</td>
-       <td>SourceSafe username</td>
-       <td>Yes</td>
+      <td>nocache</td>
+      <td><q>true|false</q>&mdash;Only needed if <code>SOSHOME</code> is set as an environment
+        variable</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>password</td>
-       <td>SourceSafe password</td>
-       <td>No</td>
+      <td>verbose</td>
+      <td><q>true|false</q>&mdash;Status messages are displayed</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>localpath</td>
-       <td>Override the working directory and get to the specified path</td>
-       <td>No</td>
+      <td>comment</td>
+      <td>A comment to be applied to all files being checked in</td>
+      <td>No</td>
     </tr>
-    <tr>
-       <td>soshome</td>
-       <td>The path to the SourceOffSite home directory</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>nocompress</td>
-       <td>true or false - disable compression</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>recursive</td>
-       <td>true or false - Only works with the CheckOutProject command</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>nocache</td>
-       <td>true or false - Only needed if SOSHOME is set as an environment variable</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>verbose</td>
-       <td>true or false - Status messages are displayed</td>
-       <td>No</td>
-    </tr>
-    <tr><td>comment</td>
-       <td>A comment to be applied to all files being checked in</td>
-       <td>No</td>
-    </tr>
- </tbody>
+  </tbody>
 </table>
 
 <h3>Example</h3>
+
+<p>Connect to a SourceOffsite server on <samp>server1:8888</samp> with <q>build</q>, <q>build</q> as
+the username &amp; password. The SourceSafe database resides on a different box
+(<samp>server2</samp>) &amp; the VSS database is on a share called <samp>vss</samp>. Check-in only
+the <samp>foobar.txt</samp> file adding a comment of <q>comment abc</q>. Extra status messages will
+be displayed on screen.</p>
 <pre>
 &lt;soscheckin username=&quot;build&quot;
             password=&quot;build&quot;
@@ -383,103 +372,101 @@
             comment=&quot;comment abc&quot;
             projectpath=&quot;$/SourceRoot/project1&quot;
             sosserverpath=&quot;server1:8888&quot;
-            vssserverpath=&quot;\\server2\vss\srcsafe.ini&quot;/&gt;
-</pre>
+            vssserverpath=&quot;\\server2\vss\srcsafe.ini&quot;/&gt;</pre>
 
-<small>Connects to a SourceOffsite server on server1:8888 with build,build as
-the username &amp; password. The SourceSafe database resides on a different
-box (server2) &amp; the VSS database is on a share called
-&quot;vss&quot;. Checks-in only the &quot;foobar.txt&quot; file adding
-a comment of &quot;comment abc&quot;. Extra status messages will be
-displayed on screen.</small><br>
-<br>
-
-<hr width="100%" size="2">
-<h2><a name="SOSCheckOut"></a>SOSCheckOut</h2>
+<hr/>
+<h2 id="SOSCheckOut">SOSCheckOut</h2>
 
 <h3>Description</h3>
-       Task to perform CheckOut commands with SOS<br>
+<p>Task to perform <var>CheckOut</var> commands with SOS</p>
 
 <h3>Parameters</h3>
 
-<table border="1">
-       <tbody>
+<table class="attr">
+  <thead>
     <tr>
-      <th>Attribute</th>
-      <th>Values</th>
-      <th>Required</th>
+      <th scope="col">Attribute</th>
+      <th scope="col">Values</th>
+      <th scope="col">Required</th>
     </tr>
+  </thead>
+  <tbody>
     <tr>
       <td>soscmd</td>
-      <td>Directory which contains soscmd(.exe) <br>
-      soscmd(.exe) must be in the path if this is not specified</td>
+      <td>Directory which contains <kbd>soscmd(.exe)</kbd></td>
+      <td>No; by default, the executable must be in the path</td>
+    </tr>
+    <tr>
+      <td>vssserverpath</td>
+      <td>path to the <samp>srcsafe.ini</samp>&mdash;eg. <samp>\\server\vss\srcsafe.ini</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>sosserverpath</td>
+      <td>address and port of the SOS server&mdash;eg. <samp>192.168.0.1:8888</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>projectpath</td>
+      <td>SourceSafe project path&mdash;eg. <samp>$/SourceRoot/Project1</samp></td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>file</td>
+      <td>Filename to act upon</td>
+      <td>No; by default, act upon the project</td>
+    </tr>
+    <tr>
+      <td>username</td>
+      <td>SourceSafe username</td>
+      <td>Yes</td>
+    </tr>
+    <tr>
+      <td>password</td>
+      <td>SourceSafe password</td>
       <td>No</td>
     </tr>
     <tr>
-       <td>vssserverpath</td>
-       <td>path to the srcsafe.ini  - eg. \\server\vss\srcsafe.ini</td>
-       <td>Yes</td>
+      <td>localpath</td>
+      <td>Override the working directory and get to the specified path</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>sosserverpath</td>
-       <td>address and port of the SOS server  - eg. 192.168.0.1:8888</td>
-       <td>Yes</td>
+      <td>soshome</td>
+      <td>The path to the SourceOffSite home directory</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>projectpath</td>
-       <td>SourceSafe project path - eg. $/SourceRoot/Project1</td>
-       <td>Yes</td>
+      <td>nocompress</td>
+      <td><q>true|false</q>&mdash;disable compression</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>file</td>
-       <td>Filename to act upon<br> If no file is specified then act upon the project</td>
-       <td>No</td>
+      <td>recursive</td>
+      <td><q>true|false</q>&mdash;Only works with the <var>CheckOutProject</var> command</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>username</td>
-       <td>SourceSafe username</td>
-       <td>Yes</td>
+      <td>nocache</td>
+      <td><q>true|false</q>&mdash;Only needed if <code>SOSHOME</code> is set as an environment variable</td>
+      <td>No</td>
     </tr>
     <tr>
-       <td>password</td>
-       <td>SourceSafe password</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>localpath</td>
-       <td>Override the working directory and get to the specified path</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>soshome</td>
-       <td>The path to the SourceOffSite home directory</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>nocompress</td>
-       <td>true or false - disable compression</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>recursive</td>
-       <td>true or false - Only works with the CheckOutProject command</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>nocache</td>
-       <td>true or false - Only needed if SOSHOME is set as an environment variable</td>
-       <td>No</td>
-    </tr>
-    <tr>
-       <td>verbose</td>
-       <td>true or false - Status messages are displayed</td>
-       <td>No</td>
+      <td>verbose</td>
+      <td><q>true|false</q>&mdash;Status messages are displayed</td>
+      <td>No</td>
     </tr>
   </tbody>
 </table>
-     <br>
 
 <h3>Example</h3>
+
+<p>Connect to a SourceOffsite server on <samp>server1:8888</samp> with <q>build</q>, <q>build</q> as
+the username &amp; password. The SourceSafe database resides on a different box
+(<samp>server2</samp>) &amp; the VSS database is on a share
+called <samp>vss</samp>. Check-out <q>project1</q>, only the <samp>project1</samp> directory will be
+locked as the recursive option was not set. Extra status messages will be displayed on
+screen. The <code>soscmd(.exe)</code> file to be used resides in <samp>/usr/local/bin</samp>.</p>
 <pre>
 &lt;soscheckout soscmd=&quot;/usr/local/bin&quot;
              verbose=&quot;true&quot;
@@ -487,17 +474,7 @@
              password=&quot;build&quot;
              projectpath=&quot;$/SourceRoot/project1&quot;
              sosserverpath=&quot;192.168.10.6:8888&quot;
-             vssserverpath=&quot;\\server2\vss\srcsafe.ini&quot;/&gt;
-</pre>
-
-<small>Connects to a SourceOffsite server on server1:8888 with build,build as
-the username &amp; password. The SourceSafe database resides on a different
-box (server2) &amp; the VSS database is on a share called
-&quot;vss&quot;. Checks-out &quot;project1&quot;, Only the
-&quot;project1&quot; directory will be locked as the recursive option
-was not set. Extra status messages will be displayed on screen. The
-soscmd(.exe) file to be used resides in /usr/local/bin.</small><br>
-<br>
+             vssserverpath=&quot;\\server2\vss\srcsafe.ini&quot;/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/sound.html b/manual/Tasks/sound.html
index 1095f80..102a300 100644
--- a/manual/Tasks/sound.html
+++ b/manual/Tasks/sound.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,77 +15,69 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Sound Task</title>
 </head>
 
 <body>
 
-<h2><a name="sound">Sound</a></h2>
+<h2 id="sound">Sound</h2>
 <h3>Description</h3>
-<p>Plays a sound-file at the end of the build, according to whether
-the build failed or succeeded. You can specify either a specific
-sound-file to play, or, if a directory is specified, the
-<code>&lt;sound&gt;</code> task will randomly select a file to play.
-Note: At this point, the random selection is based on all the files
-in the directory, not just those ending in appropriate suffixes
-for sound-files, so be sure you only have sound-files in the 
-directory you specify.</p>
-<p>More precisely <code>&lt;sound&gt;</code> registers a hook that is
-triggered when the build finishes. Therefore you have to place this
-task as top level or inside a target which is always executed.</p>
-<p>
-Unless you are running on Java 1.3 or later, you need the Java Media Framework
-on the classpath (javax.sound). 
-</p>
+<p>Plays a sound file at the end of the build, according to whether the build failed or
+succeeded. You can specify either a specific sound file to play, or, if a directory is specified,
+the <code>&lt;sound&gt;</code> task will randomly select a file to play. <strong>Note</strong>: At
+this point, the random selection is based on all the files in the directory, not just those ending
+in appropriate suffixes for sound files, so be sure you only have sound files in the directory you
+specify.</p>
+<p>More precisely <code>&lt;sound&gt;</code> registers a hook that is triggered when the build
+finishes. Therefore you have to place this task as top level or inside a target which is always
+executed.</p>
+<p>Unless you are running on Java 1.3 or later, you need the Java Media Framework on the classpath
+(<code class="code">javax.sound</code>).</p>
 
-
-<h3>Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 <h4>success</h4>
 <p>Specifies the sound to be played if the build succeeded.</p>
+
 <h4>fail</h4>
 <p>Specifies the sound to be played if the build failed.</p>
 
-<h3>Nested Element Parameters</h3>
-<p>
-The following attributes may be used on the <code>&lt;success&gt;</code> 
+<h4>Nested element parameters</h4>
+<p>The following attributes may be used on the <code>&lt;success&gt;</code>
 and <code>&lt;fail&gt;</code> elements:</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">source</td>
-    <td valign="top">the path to a sound-file directory, or the name of a
-specific sound-file, to be played. If this file does not exist, an error message
-will be logged.
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>source</td>
+    <td>the path to a sound file directory, or the name of a specific sound file, to be played. If
+      this file does not exist, an error message will be logged.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">loops</td>
-    <td valign="top">the number of extra times to play the sound-file;
-      default is <code>0</code>.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>loops</td>
+    <td>the number of extra times to play the sound file.</td>
+    <td>No; default is <q>0</q></td>
   </tr>
   <tr>
-    <td valign="top">duration</td>
-    <td valign="top">the amount of time (in milliseconds) to play
-      the sound-file.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>duration</td>
+    <td>the amount of time (in milliseconds) to play the sound file.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote>
+
+<p>Play the <samp>bell.wav</samp> sound file if the build succeeded, or the <samp>ohno.wav</samp>
+sound file if the build failed, three times, if the <code>fun</code> property is set to <q>true</q>.
+If the target is a dependency of an "initialization" target that other targets depend on,
+the <code>fun.done</code> property prevents the target from being executed more than once.</p>
 <pre>
 &lt;target name=&quot;fun&quot; if=&quot;fun&quot; unless=&quot;fun.done&quot;&gt;
   &lt;sound&gt;
@@ -92,18 +85,9 @@
     &lt;fail source=&quot;${user.home}/sounds/ohno.wav&quot; loops=&quot;2&quot;/&gt;
   &lt;/sound&gt;
   &lt;property name=&quot;fun.done&quot; value=&quot;true&quot;/&gt;
-&lt;/target&gt;
-</pre>
-</blockquote>
-plays the <code>bell.wav</code> sound-file if the build succeeded, or
-the <code>ohno.wav</code> sound-file if the build failed, three times,
-if the <code>fun</code> property is set to <code>true</code>.
-If the target
-is a dependency of an &quot;initialization&quot; target that other
-targets depend on, the
-<code>fun.done</code> property prevents the target from being executed
-more than once.
-<blockquote>
+&lt;/target&gt;</pre>
+
+<p>Randomly select a sound file to play when the build succeeds or fails.</p>
 <pre>
 &lt;target name=&quot;fun&quot; if=&quot;fun&quot; unless=&quot;fun.done&quot;&gt;
   &lt;sound&gt;
@@ -113,11 +97,6 @@
   &lt;property name=&quot;fun.done&quot; value=&quot;true&quot;/&gt;
 &lt;/target&gt;
 </pre>
-</blockquote>
-randomly selects a sound-file to play when the build succeeds or fails.
-
-
 
 </body>
 </html>
-
diff --git a/manual/Tasks/splash.html b/manual/Tasks/splash.html
index e158bd2..5494585 100644
--- a/manual/Tasks/splash.html
+++ b/manual/Tasks/splash.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,141 +15,119 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Apache Ant User Manual</title>
 </head>
 
 <body>
 
-<h2><a name="Splash">Splash</a></h2>
+<h2 id="splash">Splash</h2>
 <p>by Les Hughes (leslie.hughes@rubus.com)
 <h3>Description</h3>
-<p>This task creates a splash screen. The splash screen is displayed
-for the duration of the build and includes a handy progress bar as
-well. Use in conjunction with the sound task to provide interest
-whilst waiting for your builds to complete...</p>
+<p>This task creates a splash screen. The splash screen is displayed for the duration of the build
+and includes a handy progress bar as well. Use in conjunction with the <code>sound</code> task to
+provide interest whilst waiting for your builds to complete...</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
-    <td align="center" valign="top"><b>Default</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">imageurl</td>
-    <td valign="top">A URL pointing to an image to display.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">antlogo.gif from the classpath</td>
-  </tr>
- 
-  <tr>
-    <td valign="top">showduration</td>
-    <td valign="top">Initial period to pause the build to show the
-    splash in milliseconds.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">5000 ms</td>
+    <td>imageurl</td>
+    <td>A URL pointing to an image to display.</td>
+    <td>No; defaults to <samp>antlogo.gif</samp> from the classpath</td>
   </tr>
   <tr>
-    <td valign="top">progressregexp</td>
-    <td valign="top">Progress regular expression which is used to
-      parse the output and dig out current progress. Exactly one group
-      pattern must exists, and it represents the progress number (0-100)
-      (i.e "Progress: (.*)%")<br/>
-      <em>since Apache Ant 1.8.0</em></td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">progress is increased every action
-      and log output line</td>
+    <td>showduration</td>
+    <td>Initial period to pause the build to show the splash in milliseconds.</td>
+    <td>No; defaults to <q>5000</q></td>
   </tr>
   <tr>
-    <td valign="top">displaytext</td>
-    <td valign="top">display text presented in the splash window<br/>
-      <em>since Ant 1.8.0</em></td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">Building ...</td>
+    <td>progressregexp</td>
+    <td>Progress regular expression which is used to parse the output and dig out current
+      progress. Exactly one group pattern must exists, and it represents the progress number (0-100)
+      (i.e <q>Progress: (.*)%</q>)<br/><em>since Apache Ant 1.8.0</em></td>
+    <td>No; defaults to progress increase with every action and logged output line</td>
+  </tr>
+  <tr>
+    <td>displaytext</td>
+    <td>display text presented in the splash window<br/><em>since Ant 1.8.0</em></td>
+    <td>No; defaults to <q class="no-break">Building ...</q></td>
   </tr>
 </table>
 <h3>Deprecated properties</h3>
 
-The following properties can be used to configure the proxy settings to retrieve
-an image from behind a firewall. However, the settings apply not just to this
-task, but to all following tasks. Therefore they are now deprecated in 
-preference to the <code>&lt;setproxy&gt;</code> task, that makes it clear to readers of
-the build exactly what is going on.
+<p>The following properties can be used to configure the proxy settings to retrieve an image from
+behind a firewall. However, the settings apply not just to this task, but to all following
+tasks. Therefore they are now deprecated in preference to the <code>&lt;setproxy&gt;</code> task,
+that makes it clear to readers of the build exactly what is going on.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top">useproxy</td>
-    <td valign="top">Use a proxy to access imgurl. Note: Only tested
-    on JDK 1.2.2 and above</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">None</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">proxy</td>
-    <td valign="top">IP or hostname of the proxy server</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">None</td>
+    <td>useproxy</td>
+    <td>Use a proxy to access <var>imgurl</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">Proxy portnumber</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">None</td>
+    <td>proxy</td>
+    <td>IP or hostname of the proxy server</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">user</td>
-    <td valign="top">User to authenticate to the proxy as.</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">None</td>
-
+    <td>port</td>
+    <td>Proxy port number</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">Proxy password</td>
-    <td valign="top" align="center">No</td>
-    <td valign="top" align="center">None</td>
+    <td>user</td>
+    <td>User to authenticate to the proxy as</td>
+    <td>No</td>
   </tr>
-
+  <tr>
+    <td>password</td>
+    <td>Proxy password</td>
+    <td>No</td>
+  </tr>
 </table>
-<h3>Examples</h3>
-<blockquote><pre>
-&lt;splash/&gt;
-</pre></blockquote>
-<p>Splash <code>images/ant_logo_large.gif</code> from the classpath.</p>
-<blockquote><pre>
-&lt;splash imageurl=&quot;http://jakarta.apache.org/images/jakarta-logo.gif&quot;
-           useproxy=&quot;true&quot;
-           showduration=&quot;5000&quot;/&gt;
 
-</pre></blockquote>
-<p>Splashes the jakarta logo, for an initial period of 5 seconds.</p>
+<h3>Examples</h3>
+
+<p>Splash <samp>images/ant_logo_large.gif</samp> from the classpath.</p>
+<pre>&lt;splash/&gt;</pre>
+
+<p>Splash the Jakarta logo, for an initial period of 5 seconds.</p>
+<pre>
+&lt;splash imageurl=&quot;https://jakarta.apache.org/images/jakarta-logo.gif&quot;
+        useproxy=&quot;true&quot;
+        showduration=&quot;5000&quot;/&gt;</pre>
 
 <p>Splash with controlled progress and nondefault text</p>
-<blockquote><pre>
-        &lt;target name="test_new_features"&gt;
-                &lt;echo&gt;New features&lt;/echo&gt;
-                &lt;splash progressRegExp="Progress: (.*)%" showduration="0" displayText="Test text"/&gt;
-                &lt;sleep seconds="1"/&gt;
-                &lt;echo&gt;Progress: 10%&lt;/echo&gt;
-                &lt;sleep seconds="1"/&gt;
-                &lt;echo&gt;Progress: 20%&lt;/echo&gt;
-                &lt;sleep seconds="1"/&gt;
-                &lt;echo&gt;Progress: 50%&lt;/echo&gt;
-                &lt;sleep seconds="1"/&gt;
-                &lt;echo&gt;Progress: 70%&lt;/echo&gt;
-                &lt;sleep seconds="1"/&gt;
-                &lt;echo&gt;Progress: 100%&lt;/echo&gt;
-                &lt;sleep seconds="3"/&gt;
-        &lt;/target&gt;
-</pre></blockquote>
-
-
+<pre>
+&lt;target name="test_new_features"&gt;
+    &lt;echo&gt;New features&lt;/echo&gt;
+    &lt;splash progressRegExp="Progress: (.*)%" showduration="0" displayText="Test text"/&gt;
+    &lt;sleep seconds="1"/&gt;
+    &lt;echo&gt;Progress: 10%&lt;/echo&gt;
+    &lt;sleep seconds="1"/&gt;
+    &lt;echo&gt;Progress: 20%&lt;/echo&gt;
+    &lt;sleep seconds="1"/&gt;
+    &lt;echo&gt;Progress: 50%&lt;/echo&gt;
+    &lt;sleep seconds="1"/&gt;
+    &lt;echo&gt;Progress: 70%&lt;/echo&gt;
+    &lt;sleep seconds="1"/&gt;
+    &lt;echo&gt;Progress: 100%&lt;/echo&gt;
+    &lt;sleep seconds="3"/&gt;
+&lt;/target&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/sql.html b/manual/Tasks/sql.html
index bade590..ba2c04b 100644
--- a/manual/Tasks/sql.html
+++ b/manual/Tasks/sql.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,454 +15,397 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>SQL Task</title>
 </head>
 <body>
 
-<h2><a name="sql">Sql</a></h2>
+<h2 id="sql">Sql</h2>
 <h3>Description</h3>
-<p>Executes a series of SQL statements via JDBC to a database. Statements can 
-either be read in from a text file using the <i>src</i> attribute or from 
-between the enclosing SQL tags.</p>
+<p>Executes a series of SQL statements via JDBC to a database. Statements can either be read in from
+a text file using the <var>src</var> attribute or from between the enclosing SQL tags.</p>
 
-<p>Multiple statements can be provided, separated by semicolons (or the 
-defined <i>delimiter</i>). Individual lines within the statements can be 
-commented using either --, // or REM at the start of the line.</p>
+<p>Multiple statements can be provided, separated by semicolons (or the
+defined <var>delimiter</var>). Individual lines within the statements can be commented using
+either <q>--</q>, <q>//</q> or <q>REM</q> at the start of the line.</p>
 
-<p>The <i>autocommit</i> attribute specifies whether auto-commit should be 
-turned on or off whilst executing the statements. If auto-commit is turned 
-on each statement will be executed and committed. If it is turned off the 
-statements will all be executed as one transaction.</p>
+<p>The <var>autocommit</var> attribute specifies whether auto-commit should be turned on or off
+whilst executing the statements. If auto-commit is turned <q>on</q> each statement will be executed
+and committed. If it is turned <q>off</q> the statements will all be executed as one
+transaction.</p>
 
-<p>The <i>onerror</i> attribute specifies how to proceed when an error occurs 
-during the execution of one of the statements. 
-The possible values are: <b>continue</b> execution, only show the error;
-<b>stop</b> execution, log the error but don't fail the task
-and <b>abort</b> execution and transaction and fail task.</p>
+<p>The <var>onerror</var> attribute specifies how to proceed when an error occurs during the
+execution of one of the statements.  The possible values are: <q>continue</q> execution, only show
+the error; <q>stop</q> execution, log the error but don't fail the task and <q>abort</q> execution
+and transaction and fail task.</p>
 
-<p>
-<b>Proxies</b>. Some JDBC drivers (including the Oracle thin driver), 
-    use the JVM's proxy settings to route their JDBC operations to the database.
-    Since Apache Ant1.7, Ant running on Java1.5 or later defaults to 
-    <a href="../proxy.html">using
-    the proxy settings of the operating system</a>. 
-    Accordingly, the OS proxy settings need to be valid, or Ant's proxy
-    support disabled with <code>-noproxy</code> option.
-</p>
+<p><strong>Proxies</strong>. Some JDBC drivers (including the Oracle thin driver), use the JVM's
+proxy settings to route their JDBC operations to the database.  <em>Since Apache Ant 1.7</em>, Ant
+running on Java 5 or later defaults to <a href="../proxy.html">using the proxy settings of the
+operating system</a>.  Accordingly, the OS proxy settings need to be valid, or Ant's proxy support
+disabled with <kbd>-noproxy</kbd> option.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
-<tr>
-  <td width="12%" valign="top">driver</td>
-  <td width="78%" valign="top">Class name of the jdbc driver</td>
-  <td width="10%" valign="top">Yes</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">url</td>
-  <td width="78%" valign="top">Database connection url</td>
-  <td width="10%" valign="top">Yes</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">userid</td>
-  <td width="78%" valign="top">Database user name</td>
-  <td width="10%" valign="top">Yes</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">password</td>
-  <td width="78%" valign="top">Database password</td>
-  <td width="10%" valign="top">Yes</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">src</td>
-  <td width="78%" valign="top">File containing SQL statements</td>
-  <td width="10%" valign="top">Yes, unless statements enclosed within tags</td>
-</tr>
-<tr>
-  <td valign="top">encoding</td>
-  <td valign="top">The encoding of the files containing SQL statements</td>
-  <td align="center">No - defaults to default JVM encoding</td>
-</tr>
-<tr>
-  <td valign="top">outputencoding</td>
-  <td valign="top">The encoding of the files holding
-    results.  <em>since 1.9.4</em</td>
-  <td align="center">No - defaults to default JVM encoding</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">delimiter</td>
-  <td width="78%" valign="top">String that separates SQL statements</td>
-  <td width="10%" valign="top">No, default &quot;;&quot;</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">autocommit</td>
-  <td width="78%" valign="top">Auto commit flag for database connection (default false)</td>
-  <td width="10%" valign="top">No, default &quot;false&quot;</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">print</td>
-  <td width="78%" valign="top">Print result sets from the statements (default false)</td>
-  <td width="10%" valign="top">No, default &quot;false&quot;</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">showheaders</td>
-  <td width="78%" valign="top">Print headers for result sets from the statements (default true)</td>
-  <td width="10%" valign="top">No, default &quot;true&quot;</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">showtrailers</td>
-  <td width="78%" valign="top">Print trailer for number of rows affected (default true)</td>
-  <td width="10%" valign="top">No, default &quot;true&quot;</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">output</td>
-  <td width="78%" valign="top">Output file for result sets (defaults to System.out)
-    <b>Since Ant 1.8</b> can specify any Resource that supports output (see
-    <a href="../develop.html#set-magic">note</a>).
-  </td>
-  <td width="10%" valign="top">No (print to System.out by default)</td>
-</tr>
+<table class="attr">
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">whether output should be appended to or overwrite
-    an existing file.  Defaults to false.</td>
-    <td align="center" valign="top">No, ignored if <i>output</i> does not
-      specify a filesystem destination.</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
-<tr>
-  <td width="12%" valign="top">classpath</td>
-  <td width="78%" valign="top">Classpath used to load driver</td>
-  <td width="10%" valign="top">No (use system classpath)</td>
-</tr>
   <tr>
-    <td width="12%" valign="top">classpathref</td>
-    <td width="78%" valign="top">The classpath to use, given as a <a href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-  <td width="10%" valign="top">No (use system classpath)</td>
+    <td>driver</td>
+    <td>Class name of the jdbc driver</td>
+    <td>Yes</td>
   </tr>
-<tr>
-  <td width="12%" valign="top">onerror</td>
-  <td width="78%" valign="top">Action to perform when statement fails: continue, stop, abort</td>
-  <td width="10%" valign="top">No, default &quot;abort&quot;</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">rdbms</td>
-  <td width="78%" valign="top">Execute task only if this rdbms</td>
-  <td width="10%" valign="top">No (no restriction)</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">version</td>
-  <td width="78%" valign="top">Execute task only if rdbms version match</td>
-  <td width="10%" valign="top">No (no restriction)</td>
-</tr>
-<tr>
-  <td width="12%" valign="top">caching</td>
-  <td width="78%" valign="top">Should the task cache loaders and the driver?</td>
-  <td width="10%" valign="top">No (default=true)</td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">delimitertype</td>
-  <td width="78%" valign="top">Control whether the delimiter will only be recognized on a line by itself.<br>
-    Can be "normal" -anywhere on the line, or "row", meaning it must be on a line by itself</td>
-  <td width="10%" valign="top">No (default:normal)</td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">keepformat</td>
-  <td width="78%" valign="top">Control whether the format of the sql will be preserved.<br>
-    Useful when loading packages and procedures.
-  <td width="10%" valign="top">No (default=false)</td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">escapeprocessing</td>
-  <td width="78%" valign="top">Control whether the Java statement
-    object will perform escape substitution.<br>
-    See <a
-    href="http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#setEscapeProcessing%28boolean%29">Statement's
-    API docs</a> for details.  <em>Since Ant 1.6</em>.
-  <td width="10%" valign="top">No (default=true)</td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">expandproperties</td>
-  <td width="78%" valign="top">Set to true to turn on property expansion in
-  nested SQL, inline in the task or nested transactions. <em>Since Ant 1.7</em>.
-  <td width="10%" valign="top">No (default=true)</td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">rawblobs</td>
-  <td width="78%" valign="top">If true, will write raw streams rather than hex encoding when
-    printing BLOB results. <em>Since Ant 1.7.1</em>.</td>
-  <td width="10%" valign="top">No, default <em>false</em></td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">failOnConnectionError</td>
-  <td width="78%" valign="top">If false, will only print a warning
-    message and not execute any statement if the task fails to connect
-    to the database.  <em>Since Ant 1.8.0</em>.</td>
-  <td width="10%" valign="top">No, default <em>true</em></td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">strictDelimiterMatching</td>
-  <td width="78%" valign="top">If false, delimiters will be searched
-    for in a case-insensitive manner (i.e. delimiter="go" matches "GO")
-    and surrounding whitespace will be ignored (delimiter="go" matches
-    "GO ").  <em>Since Ant 1.8.0</em>.</td>
-  <td width="10%" valign="top">No, default <em>true</em></td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">showWarnings</td>
-  <td width="78%" valign="top">If true, SQLWarnings will be logged at
-    the WARN level.  <em>Since Ant 1.8.0</em>.<br/>
-    <b>Note:</b> even if the attribute is set to false, warnings that
-    apply to the connection will be logged at the verbose level.</td>
-  <td width="10%" valign="top">No, default <em>false</em></td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">treatWarningsAsErrors</td>
-  <td width="78%" valign="top">If true, SQLWarnings will be treated
-    like errors - and the logic selected via the onError attribute
-    applies.
-    <em>Since Ant 1.8.0</em>.</td>
-  <td width="10%" valign="top">No, default <em>false</em></td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">csvColumnSeparator</td>
-  <td width="78%" valign="top">The column separator used when printing
-    the results.
-    <em>Since Ant 1.8.0</em>.</td>
-  <td width="10%" valign="top">No, default <em>','</em></td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">csvQuoteCharacter</td>
-  <td width="78%" valign="top">The character used to quote column
-    values.<br/>
-    If set, columns that contain either the column separator or the
-    quote character itself will be surrounded by the quote character.
-    The quote character itself will be doubled if it appears inside of
-    the column's value.<br/>
-    <b>Note:</b> BLOB values will never be quoted.
-    <em>Since Ant 1.8.0</em>.</td>
-  <td width="10%" valign="top">No, default is not set (i.e. no quoting
-    ever occurs)</td>
-</tr>
-
-<tr>
-  <td width="12%" valign="top">forceCsvQuoteChar</td>
-  <td width="78%" valign="top">If true, quoting always occurs</td>
-  <td width="10%" valign="top">No, default is not set (i.e. quoting
-    occurs only where needed)</td>
-</tr>
-
-<tr>
-  <td valign="top">errorproperty</td>
-  <td valign="top">The name of a property to set in the event of an
-    error.  <em>Since Ant 1.8.0</em></td>
-  <td align="center" valign="top">No</td>
-</tr>
-<tr>
-  <td valign="top">warningproperty</td>
-  <td valign="top">The name of a property to set in the event of an
-    warning.  <em>Since Ant 1.8.0</em></td>
-  <td align="center" valign="top">No</td>
-</tr>
-<tr>
-  <td valign="top">rowcountproperty</td>
-  <td valign="top">The name of a property to set to the number of rows
-    updated by the first statement/transaction that actually returned
-    a row count.  <em>Since Ant 1.8.0</em></td>
-  <td align="center" valign="top">No</td>
-</tr>
+  <tr>
+    <td>url</td>
+    <td>Database connection URL</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>userid</td>
+    <td>Database user name</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>password</td>
+    <td>Database password</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>src</td>
+    <td>File containing SQL statements</td>
+    <td>Yes, unless statements enclosed within tags</td>
+  </tr>
+  <tr>
+    <td>encoding</td>
+    <td>The encoding of the files containing SQL statements</td>
+    <td>No; defaults to default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>outputencoding</td>
+    <td>The encoding of the files holding results.  <em>since Ant 1.9.4</em></td>
+    <td>No; defaults to default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>delimiter</td>
+    <td>String that separates SQL statements</td>
+    <td>No; defaults to <q>;;</q></td>
+  </tr>
+  <tr>
+    <td>autocommit</td>
+    <td>Auto commit flag for database connection</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>print</td>
+    <td>Print result sets from the statements</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>showheaders</td>
+    <td>Print headers for result sets from the statements</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>showtrailers</td>
+    <td>Print trailer for number of rows affected</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>output</td>
+    <td>Output file for result sets.  <em>Since Ant 1.8</em> can specify any Resource that supports
+      output (see <a href="../develop.html#set-magic">note</a>).</td>
+    <td>No; print to <code>System.out</code> by default</td>
+  </tr>
+  <tr>
+    <td>append</td>
+    <td>whether output should be appended to or overwrite an existing file.</td>
+    <td>No; defaults to <q>false</q>, ignored if <var>output</var> does not specify a filesystem
+      destination</td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>Classpath used to load driver</td>
+    <td>No; defaults to system classpath</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a path
+      defined elsewhere.</td>
+    <td>No; defaults to system classpath</td>
+  </tr>
+  <tr>
+    <td>onerror</td>
+    <td>Action to perform when statement fails: <q>continue</q>, <q>stop</q>, <q>abort</q></td>
+    <td>No; defaults to <q>abort</q></td>
+  </tr>
+  <tr>
+    <td>rdbms</td>
+    <td>Execute task only if this rdbms</td>
+    <td>No; unrestricted by default</td>
+  </tr>
+  <tr>
+    <td>version</td>
+    <td>Execute task only if rdbms version match</td>
+    <td>No; unrestricted by default</td>
+  </tr>
+  <tr>
+    <td>caching</td>
+    <td>Should the task cache loaders and the driver?</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>delimitertype</td>
+    <td>Control whether the delimiter will only be recognized on a line by itself.<br/>Can
+      be <q>normal</q>&mdash;anywhere on the line, or <q>row</q>, meaning it must be on a line by
+      itself</td>
+    <td>No; defaults to <q>normal</q></td>
+  </tr>
+  <tr>
+    <td>keepformat</td>
+    <td>Control whether the format of SQL will be preserved.<br/>Useful when loading packages and
+      procedures.
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>escapeprocessing</td>
+    <td>Control whether the Java statement object will perform escape substitution.<br/>
+      See <a href="https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#setEscapeProcessing-boolean-"
+      target="_top">Statement's API docs</a> for details.  <em>Since Ant 1.6</em>.
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>expandproperties</td>
+    <td>Set to true to turn on property expansion in nested SQL, inline in the task or nested
+      transactions. <em>Since Ant 1.7</em>.
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>rawblobs</td>
+    <td>If <q>true</q>, will write raw streams rather than hex encoding when printing BLOB
+      results. <em>Since Ant 1.7.1</em>.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>failOnConnectionError</td>
+    <td>If <q>false</q>, will only print a warning message and not execute any statement if the task
+      fails to connect to the database.  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>strictDelimiterMatching</td>
+    <td>If <q>false</q>, delimiters will be searched for in a case-insensitive manner
+      (i.e. <var>delimiter</var>=<q>go</q> matches <q>GO</q>) and surrounding whitespace will be
+      ignored (<var>delimiter</var>=<q>go</q> matches <q>GO </q>).  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>showWarnings</td>
+    <td>If <q>true</q>, SQLWarnings will be logged at the <q>warning</q> level.  <em>Since Ant
+      1.8.0</em>.<br/><strong>Note</strong>: even if the attribute is set to <q>false</q>, warnings
+      that apply to the connection will be logged at the <q>verbose</q> level.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>treatWarningsAsErrors</td>
+    <td>If <q>true</q>, SQLWarnings will be treated like errors&mdash;and the logic selected via
+      the <var>onError</var> attribute applies.  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>csvColumnSeparator</td>
+    <td>The column separator used when printing the results.  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; defaults to <q>,</q></td>
+  </tr>
+  <tr>
+    <td>csvQuoteCharacter</td>
+    <td>The character used to quote column values.<br/>If set, columns that contain either the
+      column separator or the quote character itself will be surrounded by the quote character.  The
+      quote character itself will be doubled if it appears inside of the column's
+      value.<br/><strong>Note</strong>: BLOB values will never be quoted.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; default is not set (i.e. no quoting ever occurs)</td>
+  </tr>
+  <tr>
+    <td>forceCsvQuoteChar</td>
+    <td>If <q>true</q>, quoting always occurs</td>
+    <td>No; default is not set (i.e. quoting occurs only where needed)</td>
+  </tr>
+  <tr>
+    <td>errorproperty</td>
+    <td>The name of a property to set in the event of an error.  <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>warningproperty</td>
+    <td>The name of a property to set in the event of an warning.  <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>rowcountproperty</td>
+    <td>The name of a property to set to the number of rows updated by the first
+      statement/transaction that actually returned a row count.  <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
+  </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 <h4>transaction</h4>
-<p>Use nested <code>&lt;transaction&gt;</code> 
-elements to specify multiple blocks of commands to the executed
-executed in the same connection but different transactions. This
-is particularly useful when there are multiple files to execute
-on the same schema.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Use nested <code>&lt;transaction&gt;</code> elements to specify multiple blocks of commands to
+the executed executed in the same connection but different transactions. This is particularly useful
+when there are multiple files to execute on the same schema.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">File containing SQL statements</td>
-    <td valign="top" align="center">Yes, unless statements enclosed within tags</td>
+    <td>src</td>
+    <td>File containing SQL statements</td>
+    <td>Yes, unless statements enclosed within tags</td>
   </tr>
 </table>
-<p>The <code>&lt;transaction&gt;</code> element supports any <a
-href="../Types/resources.html">resource</a> or single element
-resource collection as nested element to specify the resource
-containing the SQL statements.</p>
+<p>The <code>&lt;transaction&gt;</code> element supports
+any <a href="../Types/resources.html">resource</a> or single element resource collection as nested
+element to specify the resource containing the SQL statements.</p>
 
-<h4>any <a href="../Types/resources.html">resource</a> or resource
-collection</h4>
+<h4>any <a href="../Types/resources.html">resource</a> or resource collection</h4>
 
-<p>You can specify multiple sources via nested resource collection
-elements.  Each resource of the collection will be run in a
-transaction of its own.  Prior to Ant 1.7 only filesets were
-supported.  Use a sort resource collection to get a predictable order
-of transactions. </p>
+<p>You can specify multiple sources via nested resource collection elements.  Each resource of the
+collection will be run in a transaction of its own.  Prior to Ant 1.7 only filesets were supported.
+Use a sort resource collection to get a predictable order of transactions.</p>
 
 <h4>classpath</h4>
-<p><code>Sql</code>'s <em>classpath</em> attribute is a <a
-href="../using.html#path">PATH like structure</a> and can also be set via a nested
-<em>classpath</em> element. It is used to load the JDBC classes.</p>
+<p><code>Sql</code>'s <em>classpath</em> attribute is a <a href="../using.html#path">path-like
+structure</a> and can also be set via a nested <em>classpath</em> element. It is used to load the
+JDBC classes.</p>
 
 <h4>connectionProperty</h4>
 <p><em>Since Ant 1.8.0</em></p>
-<p>Use nested <code>&lt;connectionProperty&gt;</code> elements to
-  specify additional JDBC properties that need to be set when
-  connecting to the database.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Use nested <code>&lt;connectionProperty&gt;</code> elements to specify additional JDBC properties
+that need to be set when connecting to the database.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Name of the property</td>
-    <td valign="top" align="center">Yes</td>
+    <td>name</td>
+    <td>Name of the property</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">Value of the property</td>
-    <td valign="top" align="center">Yes</td>
+    <td>value</td>
+    <td>Value of the property</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;
-    src=&quot;data.sql&quot;
-/&gt;
-</pre></blockquote>
 
-<p>Connects to the database given in <i>url</i> as the sa user using the 
-org.database.jdbcDriver and executes the SQL statements contained within 
-the file data.sql</p>
+<p>Connect to the database given in <var>url</var> as the <q>sa</q> user using
+the <code>org.database.jdbcDriver</code> and execute the SQL statements contained within the
+file <samp>data.sql</samp></p>
 
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;
-    src=&quot;data.sql&quot;&gt;
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;
+     src=&quot;data.sql&quot;/&gt;</pre>
+
+<p>Connect to the database given in <var>url</var> as the <q>sa</q> user using
+the <code>org.database.jdbcDriver</code> and execute the SQL statements contained within the
+file <samp>data.sql</samp>. Also set the property <code>internal_logon</code> to the
+value <q>SYSDBA</q>.</p>
+
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;
+     src=&quot;data.sql&quot;&gt;
   &lt;connectionProperty name=&quot;internal_logon&quot; value=&quot;SYSDBA&quot;&gt;
-&lt;/sql&gt;
-</pre></blockquote>
+&lt;/sql&gt;</pre>
 
-<p>Connects to the database given in <i>url</i> as the sa user using
-the org.database.jdbcDriver and executes the SQL statements contained
-within the file data.sql.  Also sets the
-property <i>internal_logon</i> to the value <i>SYSDBA</i>.</p>
+<p>Connect to the database given in <var>url</var> as the <q>sa</q> user using
+the <code>org.database.jdbcDriver</code> and execute the two SQL statements inserting data
+into <samp>some_table</samp> and truncating <samp>some_other_table</samp>. Ant properties in the
+nested text will not be expanded.</p>
 
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;
-    &gt;
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;&gt;
 insert
 into table some_table
 values(1,2,3,4);
 
 truncate table some_other_table;
-&lt;/sql&gt;
-</pre></blockquote>
+&lt;/sql&gt;</pre>
 
-<p>Connects to the database given in <i>url</i> as the sa
- user using the org.database.jdbcDriver and executes the two SQL statements 
- inserting data into some_table and truncating some_other_table. Ant Properties
- in the nested text will not be expanded.</p>
+<p>Note that you may want to enclose your statements in <code>&lt;![CDATA[</code>
+... <code>]]&gt;</code> sections so you don't need to
+escape <code>&lt;</code>, <code>&gt;</code>, <code>&amp;</code> or other special characters. For
+example:</p>
 
-<p>Note that you may want to enclose your statements in
-<code>&lt;![CDATA[</code> ... <code>]]&gt;</code> sections so you don't
-need to escape <code>&lt;</code>, <code>&gt;</code> <code>&amp;</code>
-or other special characters. For example:</p>
-
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;
-    &gt;&lt;![CDATA[
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;&gt;&lt;![CDATA[
 
 update some_table set column1 = column1 + 1 where column2 &lt; 42;
 
-]]&gt;&lt;/sql&gt;
-</pre></blockquote>
+]]&gt;&lt;/sql&gt;</pre>
 
-The following command turns property expansion in nested text on (it is off purely for backwards
-compatibility), then creates a new user in the HSQLDB database using Ant properties. 
+<p>The following command turns property expansion in nested text on (it is off purely for backwards
+compatibility), then creates a new user in the HSQLDB database using Ant properties.</p>
 
-<blockquote><pre>&lt;sql
-    driver="org.hsqldb.jdbcDriver";
-    url="jdbc:hsqldb:file:${database.dir}"
-    userid="sa"
-    password=""
-    expandProperties="true"
-    &gt;
+<pre>
+&lt;sql driver="org.hsqldb.jdbcDriver";
+     url="jdbc:hsqldb:file:${database.dir}"
+     userid="sa"
+     password=""
+     expandProperties="true"&gt;
   &lt;transaction&gt;
     CREATE USER ${newuser} PASSWORD ${newpassword}
   &lt;/transaction&gt;
-&lt;/sql&gt;
-</pre></blockquote>
+&lt;/sql&gt;</pre>
 
+<p>The following connects to the database given in <var>url</var> as the <q>sa</q> user using
+the <code>org.database.jdbcDriver</code> and executes the SQL statements contained within the
+files <samp>data1.sql</samp>, <samp>data2.sql</samp> and <samp>data3.sql</samp> and then executes
+the truncate operation on <samp>some_other_table</samp>.</p>
 
-<p>The following connects to the database given in url as the sa user using 
-the org.database.jdbcDriver and executes the SQL statements contained within 
-the files data1.sql, data2.sql and data3.sql and then executes the truncate 
-operation on <i>some_other_table</i>.</p>
-
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot; &gt;
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;&gt;
   &lt;transaction  src=&quot;data1.sql&quot;/&gt;
   &lt;transaction  src=&quot;data2.sql&quot;/&gt;
   &lt;transaction  src=&quot;data3.sql&quot;/&gt;
   &lt;transaction&gt;
     truncate table some_other_table;
   &lt;/transaction&gt;
-&lt;/sql&gt;
-</pre></blockquote>
+&lt;/sql&gt;</pre>
 
-<p>The following example does the same as (and may execute additional
-SQL files if there are more files matching the pattern
-<code>data*.sql</code>) but doesn't guarantee that data1.sql will be
-run before <code>data2.sql</code>.</p>
+<p>The following example does the same as (and may execute additional SQL files if there are more
+files matching the pattern <samp>data*.sql</samp>) but doesn't guarantee that <samp>data1.sql</samp>
+will be run before <samp>data2.sql</samp>.</p>
 
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;&gt;
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;&gt;
   &lt;path&gt;
     &lt;fileset dir=&quot;.&quot;&gt;
       &lt;include name=&quot;data*.sql&quot;/&gt;
@@ -470,49 +414,43 @@
   &lt;transaction&gt;
     truncate table some_other_table;
   &lt;/transaction&gt;
-&lt;/sql&gt;
-</pre></blockquote>
+&lt;/sql&gt;</pre>
 
-<p>The following connects to the database given in url as the sa user using the 
-org.database.jdbcDriver and executes the SQL statements contained within the 
-file data.sql, with output piped to outputfile.txt, searching /some/jdbc.jar 
-as well as the system classpath for the driver class.</p>
+<p>The following connects to the database given in <var>url</var> as the <q>sa</q> user using
+the <code>org.database.jdbcDriver</code> and executes the SQL statements contained within the
+file <samp>data.sql</samp>, with output piped to <samp>outputfile.txt</samp>,
+searching <samp>/some/jdbc.jar</samp> as well as the system classpath for the driver class.</p>
 
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;
-    src=&quot;data.sql&quot;
-    print=&quot;yes&quot;
-    output=&quot;outputfile.txt&quot;
-    &gt;
-&lt;classpath&gt;
-	&lt;pathelement location=&quot;/some/jdbc.jar&quot;/&gt;
-&lt;/classpath&gt;
-&lt;/sql&gt;
-</pre></blockquote>
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;
+     src=&quot;data.sql&quot;
+     print=&quot;yes&quot;
+     output=&quot;outputfile.txt&quot;&gt;
+  &lt;classpath&gt;
+    &lt;pathelement location=&quot;/some/jdbc.jar&quot;/&gt;
+  &lt;/classpath&gt;
+&lt;/sql&gt;</pre>
 
-<p>The following will only execute if the RDBMS is &quot;oracle&quot; and the version 
-starts with &quot;8.1.&quot;</p>
+<p>The following will only execute if the RDBMS is <q>oracle</q> and the version starts
+with <q>8.1.</q></p>
 
-<blockquote><pre>&lt;sql
-    driver=&quot;org.database.jdbcDriver&quot;
-    url=&quot;jdbc:database-url&quot;
-    userid=&quot;sa&quot;
-    password=&quot;pass&quot;
-    src=&quot;data.sql&quot;
-    rdbms=&quot;oracle&quot;
-    version=&quot;8.1.&quot;
-    &gt;
+<pre>
+&lt;sql driver=&quot;org.database.jdbcDriver&quot;
+     url=&quot;jdbc:database-url&quot;
+     userid=&quot;sa&quot;
+     password=&quot;pass&quot;
+     src=&quot;data.sql&quot;
+     rdbms=&quot;oracle&quot;
+     version=&quot;8.1.&quot;&gt;
 insert
 into table some_table
 values(1,2,3,4);
 
 truncate table some_other_table;
-&lt;/sql&gt;
-</pre></blockquote>
-
+&lt;/sql&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/sshexec.html b/manual/Tasks/sshexec.html
index d085abd..f0a0e9c 100644
--- a/manual/Tasks/sshexec.html
+++ b/manual/Tasks/sshexec.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,295 +15,298 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>SSHEXEC Task</title>
 </head>
 
 <body>
 
-<h2><a name="sshexec">SSHEXEC</a></h2>
+<h2 id="sshexec">SSHEXEC</h2>
+<p><em>Since Apache Ant 1.6</em></p>
 <h3>Description</h3>
 
-<p><em>since Apache Ant 1.6</em></p>
+<p>Runs a command on a remote machine running SSH daemon.</p>
 
-<p>Runs a command on a remote machine running SSH daemon.
-</p>
-
-<p><b>Note:</b> This task depends on external libraries not included
-in the Ant distribution.  See <a
-href="../install.html#librarydependencies">Library Dependencies</a>
-for more information.  This task has been tested with jsch-0.1.29 and above
-and won't work with versions of jsch earlier than
-0.1.28.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Ant
+distribution.  See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.  This task has been tested with JSCh 0.1.29 and above and won't work with versions of
+JSCh earlier than 0.1.28.</p>
 
 <p>See also the <a href="scp.html">scp task</a></p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">host</td>
-    <td valign="top">The hostname or IP address of the remote host to which you wish to connect.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>host</td>
+    <td>The hostname or IP address of the remote host to which you wish to connect.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">username</td>
-    <td valign="top">The username on the remote host to which you are connecting.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>username</td>
+    <td>The username on the remote host to which you are connecting.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">command</td>
-    <td valign="top">The command to run on the remote host.</td>
-    <td valian="top" align="center">Either this or commandResource must be set</td>
+    <td>command</td>
+    <td>The command to run on the remote host.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">commandResource</td>
-    <td valign="top">The resource (file) that contains the commands to run on the remote host.
-    Since Ant 1.7.1</td>
-    <td valian="top" align="center">Either this or command must be set</td>
+    <td>commandResource</td>
+    <td class="left">The resource (file) that contains the commands to run on the remote
+    host.  <em>Since Ant 1.7.1</em></td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">The port to connect to on the remote host.</td>
-    <td valian="top" align="center">No, defaults to 22.</td>
+    <td>port</td>
+    <td>The port to connect to on the remote host.</td>
+    <td>No; defaults to <q>22</q></td>
   </tr>
   <tr>
-    <td valign="top">trust</td>
-
-    <td valign="top">This trusts all unknown hosts if set to yes/true.<br>
-      <strong>Note</strong> If you set this to false (the default), the
-      host you connect to must be listed in your knownhosts file, this
-      also implies that the file exists.</td>
-    <td valian="top" align="center">No, defaults to No.</td>
+    <td>trust</td>
+    <td>This trusts all unknown hosts if set to <q>yes</q>
+      or <q>true</q>.<br/><strong>Note</strong>: If you set this to <q>false</q> (the default), the
+      host you connect to must be listed in your <var>knownhosts</var> file, this also implies that
+      the file exists.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">knownhosts</td>
-    <td valign="top">This sets the known hosts file to use to validate
-    the identity of the remote host.  This must be a SSH2 format file.
-    SSH1 format is not supported.</td>
-    <td valian="top" align="center">No, defaults to
-    ${user.home}/.ssh/known_hosts.</td>
+    <td>knownhosts</td>
+    <td>This sets the known hosts file to use to validate the identity of the remote host.  This
+      must be a SSH2 format file.  SSH1 format is not supported.</td>
+    <td>No; defaults to <q>${user.home}/.ssh/known_hosts</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-     <td valign="top">Whether to halt the build if the command does not complete successfully.
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>failonerror</td>
+    <td>Whether to halt the build if the command does not complete successfully.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-     <td valign="top">The password.</td>
-     <td valign="top" align="center">Not if you are using key based
-     authentication or the password has been given in the file or
-     todir attribute.</td>
+    <td>password</td>
+    <td>The password.</td>
+    <td>Yes, unless you are using key based authentication or the password has been given in the
+      file or <var>todir</var> attribute.</td>
   </tr>
   <tr>
-    <td valign="top">keyfile</td>
-     <td valign="top">Location of the file holding the private key.</td>
-     <td valign="top" align="center">Yes, if you are using key based
-     authentication.</td>
+    <td>keyfile</td>
+    <td>Location of the file holding the private key.</td>
+    <td>Yes, if you are using key based authentication</td>
   </tr>
   <tr>
-    <td valign="top">passphrase</td>
-     <td valign="top">Passphrase for your private key.</td>
-     <td valign="top" align="center">No, defaults to an empty string.</td>
+    <td>passphrase</td>
+    <td>Passphrase for your private key.</td>
+    <td>No; defaults to an empty string</td>
   </tr>
   <tr>
-    <td valign="top">suppresssystemout</td>
-    <td valign="top">Whether to suppress system out.
-      <em>since Ant 1.9.0</em></td>
-    <td align="center" valign="top">No, defaults to false</td>
+    <td>sshConfig</td>
+    <td>Location of the file holding the OpenSSH style configuration (e.g. <code>${user.home}/.ssh/config</code>).
+        The username and the key file are read from the configuration file,
+        unless they are already specified in the task parameters.
+        <em>since Ant 1.10.8</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suppresssystemerr</td>
-    <td valign="top">Whether to suppress system err.
-      <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No, defaults to false</td>
+    <td>suppresssystemout</td>
+    <td>Whether to suppress system out. <em>since Ant 1.9.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">Name of a file to which to write the output.</td>
-    <td align="center" valign="top">No</td>
+    <td>suppresssystemerr</td>
+    <td>Whether to suppress <code>System.err</code>. <em>since Ant 1.9.4</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">errorOutput</td>
-    <td valign="top">The file to which the standard error of the
-    command should be redirected.  <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No</td>
+    <td>output</td>
+    <td>Name of a file to which to write the output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Whether output file should be appended to or overwritten. Defaults to false, meaning overwrite any existing file.</td>
-    <td align="center" valign="top">No</td>
+    <td>errorOutput</td>
+    <td>The file to which the standard error of the command should be redirected.  <em>since Ant
+      1.9.4</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errAppend</td>
-    <td valign="top">Whether errorOutput file should be appended to or
-    overwritten. Defaults to false, meaning overwrite any existing
-    file.  <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No</td>
+    <td>append</td>
+    <td>Whether <var>output</var> file should be appended to or overwritten.</td>
+    <td>No; defaults to <q>false</q>, meaning overwrite any existing file</td>
   </tr>
   <tr>
-    <td valign="top">outputproperty</td>
-    <td valign="top">The name of a property in which the output of the 
-      command should be stored.  If you use the commandResource
-      attribute, each command's output will be prefixed by the
+    <td>errAppend</td>
+    <td>Whether <var>errorOutput</var> file should be appended to or overwritten. <em>since Ant
+      1.9.4</em></td>
+    <td>No; defaults to <q>false</q>, meaning overwrite any existing file</td>
+  </tr>
+  <tr>
+    <td>outputproperty</td>
+    <td>The name of a property in which the output of the command should be stored.  If you use
+      the <var>commandResource</var> attribute, each command's output will be prefixed by the
       command itself.</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property in which the standard error of the
-      command should be stored.  <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property in which the standard error of the command should be
+      stored.  <em>since Ant 1.9.4</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">resultproperty</td>
-    <td valign="top">the name of a property in which the return code
-      of the command should be stored. Only of interest if
-      failonerror=false.  <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No</td>
+    <td>resultproperty</td>
+    <td>the name of a property in which the return code of the command should be stored. Only of
+      interest if <var>failonerror</var>=<q>false</q>.  <em>since Ant 1.9.4</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Stop the command if it doesn't finish within the
-      specified time (given in milliseconds <b>unlike telnet, which
-        expects a timeout in seconds</b>).
-      Defaults to 0 which means &quot;wait forever&quot;.</td>
-    <td align="center" valign="top">No</td>
+    <td>timeout</td>
+    <td>Stop the command if it doesn't finish within the specified time (given in
+      milliseconds <strong>unlike <code>telnet</code>, which expects a timeout in
+      seconds</strong>).</td>
+    <td>No; defaults to <q>0</q> which means <q>never</q></td>
   </tr>
   <tr>
-    <td valign="top">input</td>
-    <td valign="top">A file from which the executed command's standard
-      input is taken. This attribute is mutually exclusive with the
-      inputstring and inputproperty attributes.<br/>
-      When executing more than one command via commandResource, input
-      will be read for each command.
-      <em>since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>input</td>
+    <td>A file from which the executed command's standard input is taken. This attribute is mutually
+      exclusive with the <var>inputstring</var> and <var>inputproperty</var> attributes.<br/>  When
+      executing more than one command via <var>commandResource</var>, input will be read for each
+      command.  <em>since Ant 1.8.0</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Determines whether sshexec outputs verbosely to the user.<br/> 
-    Similar output is generated as the ssh commandline tool wit the -v option. 
-    <em>since Ant 1.8.0</em></td>
-    <td align="center">No, defaults to false</td>
+    <td>verbose</td>
+    <td>Determines whether <code>sshexec</code> outputs verbosely to the user.<br/>  Similar output
+      is generated as the <kbd>ssh</kbd> command line tool with the <kbd>-v</kbd>
+      option.  <em>since Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">inputproperty</td>
-    <td valign="top">Name of a property who's content serves as the
-      input stream for the executed command. This attribute is
-      mutually exclusive with the input and inputstring
-      attributes.<br/>
-      When executing more than one command via commandResource, input
-      will be read for each command.
-      <em>since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>inputproperty</td>
+    <td>Name of a property content of which serves as the input stream for the executed
+      command. This attribute is mutually exclusive with the <var>input</var>
+      and <var>inputstring</var> attributes.<br/>  When executing more than one command
+      via <var>commandResource</var>, input will be read for each command.  <em>since Ant
+      1.8.0</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputstring</td>
-    <td valign="top">A string which serves as the input stream for the
-      executed command. This attribute is mutually exclusive with the
-      input and inputproperty attributes.<br/>
-      When executing more than one command via commandResource, input
-      will be read for each command.
-      <em>since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No</td>
+    <td>inputstring</td>
+    <td>A string which serves as the input stream for the executed command. This attribute is
+      mutually exclusive with the <var>input</var> and <var>inputproperty</var> attributes.<br/>
+      When executing more than one command via <var>commandResource</var>, input will be read for
+      each command.  <em>since Ant 1.8.3</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">usepty</td>
-    <td valign="top">Whether to allocate a pseudo-tty (like ssh -t).
-      <em>since Ant 1.8.3</em></td>
-    <td align="center" valign="top">No, defaults to false</td>
+    <td>usepty</td>
+    <td>Whether to allocate a pseudo-tty (like <kbd>ssh -t</kbd>).  <em>since Ant 1.8.3</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">useSystemIn</td>
-    <td valign="top">Whether to pass the current standard input to the
-      remote process.
-      <em>since Ant 1.9.4</em></td>
-    <td align="center" valign="top">No, defaults to false</td>
+    <td>useSystemIn</td>
+    <td>Whether to pass the current standard input to the remote process.  <em>since Ant
+      1.9.4</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">serverAliveIntervalSeconds</td>
-    <td valign="top">Sets a timeout interval in seconds after which if no data has
-      been received from the server, the task will send a message through
-      the encrypted channel to request a response from the server.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No, the default is 0, indicating
-      that these messages will not be sent to the server</td>
+    <td>serverAliveIntervalSeconds</td>
+    <td>Sets a timeout interval in seconds after which if no data has been received from the server,
+      the task will send a message through the encrypted channel to request a response from the
+      server.  <em>since Ant 1.9.7</em></td>
+    <td>No, the default is <q>0</q>, indicating that these messages will not be sent to the
+      server</td>
   </tr>
   <tr>
-    <td valign="top">serverAliveCountMax</td>
-    <td valign="top">The number of server alive messages which may be
-      sent without receiving any messages back from the server. Only
-      used if serverAliveIntervalSeconds is not 0.
-      <em>since Ant 1.9.7</em></td>
-    <td align="center" valign="top">No, defaults to 3</td>
+    <td>serverAliveCountMax</td>
+    <td>The number of server alive messages which may be sent without receiving any messages back
+      from the server. Only used if <var>serverAliveIntervalSeconds</var> is
+      not <q>0</q>.  <em>since Ant 1.9.7</em></td>
+    <td>No; defaults to <q>3</q></td>
+  </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+
+<h4 id="additionalConfig">additionalConfig</h4>
+
+<p><em>since Ant 1.10.10</em></p>
+
+<p>Adds configuration settings for the JSch Session created that are
+  not directly supported by specific Ant attributes.</p>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>key</td>
+    <td>The key of the configuration setting.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>The value of the configuration setting.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<p><b>Run a command on a remote machine using password authentication</b></p>
-<pre>
-  &lt;sshexec host=&quot;somehost&quot;
-	username=&quot;dude&quot;
-	password=&quot;yo&quot;
-	command=&quot;touch somefile&quot;/&gt;
-</pre>
 
-<p><b>Run a command on a remote machine using key authentication</b></p>
-<pre>
-  &lt;sshexec host=&quot;somehost&quot;
-	username=&quot;dude&quot;
-	keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
-	passphrase=&quot;yo its a secret&quot;
-	command=&quot;touch somefile&quot;/&gt;
-</pre>
+<p>Run a command on a remote machine using password authentication</p>
 
-<p><b>Run a command on a remote machine using key authentication with no passphrase</b></p>
 <pre>
-  &lt;sshexec host=&quot;somehost&quot;
-	username=&quot;dude&quot;
-	keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
-	command=&quot;touch somefile&quot;/&gt;
-</pre>
+&lt;sshexec host=&quot;somehost&quot;
+         username=&quot;dude&quot;
+         password=&quot;yo&quot;
+         command=&quot;touch somefile&quot;/&gt;</pre>
 
-<p><b>Run a set of commands from a command resource (file) on a remote machine using key authentication with no passphrase</b></p>
+<p>Run a command on a remote machine using key authentication</p>
+
 <pre>
-  &lt;sshexec host=&quot;somehost&quot;
-	username=&quot;dude&quot;
-	keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
-	commandResource=&quot;to_run&quot;/&gt;
-</pre>
+&lt;sshexec host=&quot;somehost&quot;
+         username=&quot;dude&quot;
+         keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
+         passphrase=&quot;yo its a secret&quot;
+         command=&quot;touch somefile&quot;/&gt;</pre>
 
+<p>Run a command on a remote machine using key authentication with no passphrase</p>
 
-<p><strong>Security Note:</strong>  Hard coding passwords and/or usernames
-in sshexec task can be a serious security hole.  Consider using variable
-substitution and include the password on the command line.  For example:<br>
 <pre>
-  &lt;sshexec host=&quot;somehost&quot;
-	username=&quot;${username}&quot;
-	password=&quot;${password}&quot;
-	command=&quot;touch somefile&quot;/&gt;
-</pre>
-Invoking ant with the following command line:
-<pre>
-    ant -Dusername=me -Dpassword=mypassword target1 target2
-</pre>
+&lt;sshexec host=&quot;somehost&quot;
+         username=&quot;dude&quot;
+         keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
+         command=&quot;touch somefile&quot;/&gt;</pre>
 
-Is slightly better, but the username/password is exposed to all users
-on an Unix system (via the ps command). The best approach is to use
-the
-<code>&lt;input&gt;</code> task and/or retrieve the password from a (secured)
-.properties file.
-</p>
+<p>Run a set of commands from a command resource (file) on a remote machine using key authentication
+with no passphrase</p>
+
+<pre>
+&lt;sshexec host=&quot;somehost&quot;
+         username=&quot;dude&quot;
+         keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
+         commandResource=&quot;to_run&quot;/&gt;</pre>
+
+<p><strong>Security Note</strong>: Hardcoding passwords and/or usernames in <var>sshexec</var> task
+can be a serious security hole. Consider using variable substitution and include the password on the
+command line. For example:</p>
+
+<pre>
+&lt;sshexec host=&quot;somehost&quot;
+         username=&quot;${username}&quot;
+         password=&quot;${password}&quot;
+         command=&quot;touch somefile&quot;/&gt;</pre>
+
+<p>Invoking Ant with the following command line:</p>
+<pre class="input">ant -Dusername=me -Dpassword=mypassword target1 target2</pre>
+<p>is slightly better, but the username/password is exposed to all users on an Unix system (via
+the <kbd>ps</kbd> command). The best approach is to use the <code>&lt;input&gt;</code> task and/or
+retrieve the password from a (secured) <samp>.properties</samp> file.</p>
 </body>
 </html>
diff --git a/manual/Tasks/sshsession.html b/manual/Tasks/sshsession.html
index e9696d1..c8cf291 100644
--- a/manual/Tasks/sshsession.html
+++ b/manual/Tasks/sshsession.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,275 +15,272 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>SSHSESSION Task</title>
 </head>
 
 <body>
 
-<h2><a name="sshsession">SSHSESSION</a></h2>
+<h2 id="sshsession">SSHSESSION</h2>
+<p><em>Since Apache Ant 1.8.0</em></p>
 <h3>Description</h3>
 
-<p><em>since Apache Ant 1.8.0</em></p>
+<p>A Task which establishes an SSH connection with a remote machine running SSH daemon, optionally
+establishes any number of local or remote tunnels over that connection, then executes any nested
+tasks before taking down the connection.</p>
 
-<p>A Task which establishes an SSH connection with a remote machine
-running SSH daemon, optionally establishes any number of local or
-remote tunnels over that connection, then executes any nested tasks
-before taking down the connection.
-</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Ant
+distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.  This task has been tested with JSCh 0.1.33 and above and won't work with versions of
+JSCh earlier than 0.1.28.</p>
 
-<p><b>Note:</b> This task depends on external libraries not included
-in the Ant
-distribution. See <a href="../install.html#librarydependencies">Library
-Dependencies</a> for more information.  This task has been tested with
-jsch-0.1.33 and above and won't work with versions of jsch earlier
-than 0.1.28.</p>
-
-<p>See also the <a href="sshexec.html">sshexec</a>
-and <a href="scp.html">scp</a> tasks</p>
+<p>See also the <a href="sshexec.html">sshexec</a> and <a href="scp.html">scp</a> tasks</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">host</td>
-    <td valign="top">The hostname or IP address of the remote host to which you wish to connect.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>host</td>
+    <td>The hostname or IP address of the remote host to which you wish to connect.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">username</td>
-    <td valign="top">The username on the remote host to which you are connecting.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>username</td>
+    <td>The username on the remote host to which you are connecting.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">port</td>
-    <td valign="top">The port to connect to on the remote host.</td>
-    <td valian="top" align="center">No, defaults to 22.</td>
+    <td>port</td>
+    <td>The port to connect to on the remote host.</td>
+    <td>No; defaults to <q>22</q></td>
   </tr>
   <tr>
-  <tr>
-    <td valign="top">localtunnels</td>
-    <td valign="top">A comma-delimited list of
-      colon-delimited <code>lport:rhost:rport</code> triplets defining
-      local port forwarding.<br>  If
-      nested <a href="#LocalTunnel">localtunnel</a> elements are also
+    <td>localtunnels</td>
+    <td>A comma-delimited list of colon-delimited <samp>lport:rhost:rport</samp> triplets defining
+      local port forwarding.<br/>If nested <a href="#LocalTunnel">localtunnel</a> elements are also
       provided, both sets of tunnels will be established.</td>
-    <td valian="top" align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">remotetunnels</td>
-    <td valign="top">A comma-delimited list of
-      colon-delimited <code>rport:lhost:lport</code> triplets defining
-      remote port forwarding.<br>  If
-      nested <a href="#RemoteTunnel">remotetunnel</a> elements are
+    <td>remotetunnels</td>
+    <td>A comma-delimited list of colon-delimited <samp>rport:lhost:lport</samp> triplets defining
+      remote port forwarding.<br/>  If nested <a href="#RemoteTunnel">remotetunnel</a> elements are
       also provided, both sets of tunnels will be established.</td>
-    <td valian="top" align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">trust</td>
-    
-    <td valign="top">This trusts all unknown hosts if set to yes/true.<br>
-      <strong>Note</strong> If you set this to false (the default), the
-      host you connect to must be listed in your knownhosts file, this
-      also implies that the file exists.</td>
-    <td valian="top" align="center">No, defaults to No.</td>
+    <td>trust</td>
+    <td>This trusts all unknown hosts if set to <q>yes</q>
+      or <q>true</q>.<br/><strong>Note</strong>: If you set this to <q>false</q> (the default), the
+      host you connect to must be listed in your <var>knownhosts</var> file, this also implies that
+      the file exists.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">knownhosts</td>
-    <td valign="top">This sets the known hosts file to use to validate
-      the identity of the remote host.	This must be a SSH2 format file.
-      SSH1 format is not supported.</td>
-    <td valian="top" align="center">No, defaults to
-      ${user.home}/.ssh/known_hosts.</td>
+    <td>knownhosts</td>
+    <td>This sets the known hosts file to use to validate the identity of the remote host. This must
+      be a SSH2 format file.  SSH1 format is not supported.</td>
+    <td>No; defaults to <q>${user.home}/.ssh/known_hosts</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">Whether to halt the build if the command does not complete successfully.
-    </td>
-    <td valign="top" align="center">No; defaults to true.</td>
+    <td>failonerror</td>
+    <td>Whether to halt the build if the command does not complete successfully.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">password</td>
-    <td valign="top">The password.</td>
-    <td valign="top" align="center">Not if you are using key based
-      authentication or the password has been given in the file or
-      todir attribute.</td>
+    <td>password</td>
+    <td>The password.</td>
+    <td>Yes, unless you are using key based authentication or the password has been given in the
+      file or <var>todir</var> attribute</td>
   </tr>
   <tr>
-    <td valign="top">keyfile</td>
-    <td valign="top">Location of the file holding the private key.</td>
-    <td valign="top" align="center">Yes, if you are using key based
-      authentication.</td>
+    <td>keyfile</td>
+    <td>Location of the file holding the private key.</td>
+    <td>Yes, if you are using key based authentication</td>
   </tr>
   <tr>
-    <td valign="top">passphrase</td>
-    <td valign="top">Passphrase for your private key.</td>
-    <td valign="top" align="center">No, defaults to an empty string.</td>
+    <td>passphrase</td>
+    <td>Passphrase for your private key.</td>
+    <td>No; defaults to an empty string</td>
   </tr>
   <tr>
-    <td valign="top">timeout</td>
-    <td valign="top">Give up if the connection cannot be established
-      within the specified time (given in milliseconds). Defaults to 0
-      which means &quot;wait forever&quot;.</td>
-    <td align="center" valign="top">No</td>
+    <td>sshConfig</td>
+    <td>Location of the file holding the OpenSSH style configuration (e.g. <code>${user.home}/.ssh/config</code>).
+        The username and the key file are read from the configuration file,
+        unless they are already specified in the task parameters.
+        <em>since Ant 1.10.8</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>timeout</td>
+    <td>Give up if the connection cannot be established within the specified time (given in
+      milliseconds).</td>
+    <td>No; defaults to <q>0</q> which means <q>never</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<a name="LocalTunnel"><h4>localtunnel</h4></a>
-<p>Optionally, any number of localtunnel elements can be used to
-define local port forwarding over the SSH connection.  If the
-localtunnels parameter was also specified, both sets of tunnels will
-be established.</p>
+<h4 id="LocalTunnel">localtunnel</h4>
+<p>Optionally, any number of <code>localtunnel</code> elements can be used to define local port
+forwarding over the SSH connection.  If the <var>localtunnels</var> parameter was also specified,
+both sets of tunnels will be established.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">lport</td>
-    <td valign="top">The number of the local port to be forwarded.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>lport</td>
+    <td>The number of the local port to be forwarded.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">rhost</td>
-    <td valign="top">The hostname or IP address of the remote host to
-      which the local port should be forwarded.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>rhost</td>
+    <td>The hostname or IP address of the remote host to which the local port should be
+      forwarded.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">rport</td>
-    <td valign="top">The number of the port on the remote host to
-      which the local port should be forwarded.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>rport</td>
+    <td>The number of the port on the remote host to which the local port should be forwarded.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<a name="RemoteTunnel"><h4>remotetunnel</h4></a>
-<p>Optionally, any number of remotetunnel elements can be used to
-define remote port forwarding over the SSH connection.  If the
-remotetunnels parameter was also specified, both sets of tunnels will
-be established.</p>
+<h4 id="RemoteTunnel">remotetunnel</h4>
+<p>Optionally, any number of <code>remotetunnel</code> elements can be used to define remote port
+forwarding over the SSH connection.  If the <var>remotetunnels</var> parameter was also specified,
+both sets of tunnels will be established.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">rport</td>
-    <td valign="top">The number of the remote port to be forwarded.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>rport</td>
+    <td>The number of the remote port to be forwarded.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">lhost</td>
-    <td valign="top">The hostname or IP address of the local host to
-      which the remote port should be forwarded.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>lhost</td>
+    <td>The hostname or IP address of the local host to which the remote port should be
+      forwarded.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">lport</td>
-    <td valign="top">The number of the port on the local host to which
-      the remote port should be forwarded.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>lport</td>
+    <td>The number of the port on the local host to which the remote port should be forwarded.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<a name="Sequential"><h4>sequential</h4></a>
-<p>The sequential element is a required parameter.  It is a container
-for nested Tasks which are to be executed once the SSH connection is
-established and all local and/or remote tunnels established.</p>
+<h4 id="additionalConfig">additionalConfig</h4>
+
+<p><em>since Ant 1.10.10</em></p>
+
+<p>Adds configuration settings for the JSch Session created that are
+  not directly supported by specific Ant attributes.</p>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>key</td>
+    <td>The key of the configuration setting.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>The value of the configuration setting.</td>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h4 id="Sequential">sequential</h4>
+<p>The <code>sequential</code> element is a required parameter.  It is a container for nested Tasks
+which are to be executed once the SSH connection is established and all local and/or remote tunnels
+established.</p>
 
 <h3>Examples</h3>
-<p><b>Connect to a remote machine using password authentication,
-forward the local cvs port to the remote host, and execute a cvs
-command locally, which can use the tunnel.</b></p>
+
+<p>Connect to a remote machine using password authentication, forward the local CVS port to the
+remote host, and execute a CVS command locally, which can use the tunnel.</p>
+
 <pre>
-  &lt;sshsession host=&quot;somehost&quot;
-    username=&quot;dude&quot;
-    password=&quot;yo&quot;
-    localtunnels=&quot;2401:localhost:2401&quot;
-  &gt;
-    &lt;sequential&gt;
-      &lt;cvs  command=&quot;update ${cvs.parms} ${module}&quot;
-        cvsRoot=&quot;${cvs.root}&quot;
-        dest=&quot;${local.root}&quot;
-        failonerror=&quot;true&quot;
-      /&gt;
-    &lt;/sequential&gt;
-  &lt;/sshsession&gt;
-</pre>
+&lt;sshsession host=&quot;somehost&quot;
+            username=&quot;dude&quot;
+            password=&quot;yo&quot;
+            localtunnels=&quot;2401:localhost:2401&quot;&gt;
+  &lt;sequential&gt;
+    &lt;cvs command=&quot;update ${cvs.parms} ${module}&quot;
+         cvsRoot=&quot;${cvs.root}&quot;
+         dest=&quot;${local.root}&quot;
+         failonerror=&quot;true&quot;/&gt;
+  &lt;/sequential&gt;
+&lt;/sshsession&gt;</pre>
 
-<p><b>Do the same thing using nested localtunnel element.</b></p>
+<p>Do the same thing using nested <code>localtunnel</code> element.</p>
+
 <pre>
-  &lt;sshsession host=&quot;somehost&quot;
-    username=&quot;dude&quot;
-    password=&quot;yo&quot;
-  &gt;
-    &lt;localtunnel lport=&quot;2401&quot; rhost=&quot;localhost&quot; rport=&quot;2401&quot;/&gt;
-    &lt;sequential&gt;
-      &lt;cvs  command=&quot;update ${cvs.parms} ${module}&quot;
-        cvsRoot=&quot;${cvs.root}&quot;
-        dest=&quot;${local.root}&quot;
-        failonerror=&quot;true&quot;
-    /&gt;
-    &lt;/sequential&gt;
-  &lt;/sshsession&gt;
-</pre>
+&lt;sshsession host=&quot;somehost&quot;
+            username=&quot;dude&quot;
+            password=&quot;yo&quot;&gt;
+  &lt;localtunnel lport=&quot;2401&quot; rhost=&quot;localhost&quot; rport=&quot;2401&quot;/&gt;
+  &lt;sequential&gt;
+    &lt;cvs command=&quot;update ${cvs.parms} ${module}&quot;
+         cvsRoot=&quot;${cvs.root}&quot;
+         dest=&quot;${local.root}&quot;
+         failonerror=&quot;true&quot;/&gt;
+  &lt;/sequential&gt;
+&lt;/sshsession&gt;</pre>
 
-<p><b>Connect to a remote machine using key authentication, forward
-port 1080 to port 80 of an intranet server which is not directly
-accessible, then run a get task using that tunnel.</b></p>
+<p>Connect to a remote machine using key authentication, forward port 1080 to port 80 of an intranet
+server which is not directly accessible, then run a <code>get</code> task using that tunnel.</p>
+
 <pre>
-  &lt;sshsession host=&quot;somehost&quot;
-  username=&quot;dude&quot;
-  keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
-  passphrase=&quot;yo its a secret&quot;/&gt;
-    &lt;LocalTunnel lport=&quot;1080&quot; rhost=&quot;intranet.mycomp.com&quot; rport=&quot;80&quot;/&gt;
-    &lt;sequential&gt;
-      &lt;get src=&quot;http://localhost:1080/somefile&quot; dest=&quot;temp/somefile&quot;/&gt;
-    &lt;/sequential&gt;
-  &lt;/sshsession&gt;
-</pre>
+&lt;sshsession host=&quot;somehost&quot;
+            username=&quot;dude&quot;
+            keyfile=&quot;${user.home}/.ssh/id_dsa&quot;
+            passphrase=&quot;yo its a secret&quot;/&gt;
+  &lt;LocalTunnel lport=&quot;1080&quot; rhost=&quot;intranet.mycomp.com&quot; rport=&quot;80&quot;/&gt;
+  &lt;sequential&gt;
+    &lt;get src=&quot;http://localhost:1080/somefile&quot; dest=&quot;temp/somefile&quot;/&gt;
+  &lt;/sequential&gt;
+&lt;/sshsession&gt;</pre>
 
+<p><strong>Security Note</strong>: Hardcoding passwords or passphrases and/or usernames
+in <code>sshsession</code> task can be a serious security hole. Consider using variable substitution
+and include the password on the command line. For example:</p>
 
-<p><strong>Security Note:</strong> Hard coding passwords or
-passphrases and/or usernames in sshsession task can be a serious
-security hole. Consider using variable substitution and include the
-password on the command line. For example:<br>
 <pre>
-  &lt;sshsession host=&quot;somehost&quot;
-  username=&quot;${username}&quot;
-  password=&quot;${password}&quot;
-  localtunnels=&quot;2401:localhost:2401&quot;&gt;
-    &lt;sequential&gt;
-      &lt;sometask/&gt;
-    &lt;/sequential&gt;
-  &lt;/sshsession&gt;
-</pre>
+&lt;sshsession host=&quot;somehost&quot;
+            username=&quot;${username}&quot;
+            password=&quot;${password}&quot;
+            localtunnels=&quot;2401:localhost:2401&quot;&gt;
+  &lt;sequential&gt;
+    &lt;sometask/&gt;
+  &lt;/sequential&gt;
+&lt;/sshsession&gt;</pre>
 
-Invoking ant with the following command line:
-<pre>
-    ant -Dusername=me -Dpassword=mypassword target1 target2
-</pre>
-
-Is slightly better, but the username/password is exposed to all users
-on an Unix system (via the ps command). The best approach is to use
-the
-<code>&lt;input&gt;</code> task and/or retrieve the password from a (secured)
-.properties file.
-</p>
+<p>Invoking Ant with the following command line:</p>
+<pre class="input">ant -Dusername=me -Dpassword=mypassword target1 target2</pre>
+<p>is slightly better, but the username/password is exposed to all users on an Unix system (via
+the <kbd>ps</kbd> command). The best approach is to use the <code>&lt;input&gt;</code> task and/or
+retrieve the password from a (secured) <samp>.properties</samp> file.</p>
 </body>
 </html>
diff --git a/manual/Tasks/style.html b/manual/Tasks/style.html
index 81e7e6b..9f0a16c 100644
--- a/manual/Tasks/style.html
+++ b/manual/Tasks/style.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,576 +15,507 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>XSLT Task</title>
 </head>
 
 <body>
 
-<h2><a name="style">XSLT</a></h2>
-<p><em>The name <code>style</code> is a deprecated name for the same task.</em></p>
+<h2 id="style">XSLT</h2>
+<p><em>The name <code>style</code> is a <u>deprecated</u> name for the same task.</em></p>
 <h3>Description</h3>
 <p>Process a set of documents via XSLT.</p>
-<p>This is useful for building views of XML based documentation,
-or for generating code.</p>
-<p><b>Note:</b> If you are using JDK 1.4 or higher, this task does not require external libraries
-not supplied in the Apache Ant distribution. However, often the built in XSL engine is not as up
-to date as a fresh download, so an update is still highly recommended
-  in particular since the built-in XSLT processors of Java 5 (and to a
-  certain extent Java 6) are known to have serious issues.
-See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information.</p>
-<p>It is possible to refine the set of files that are being processed. This can be
-done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and <i>defaultexcludes</i>
-attributes. With the <i>includes</i> or <i>includesfile</i> attribute you specify the files you want to
-have included by using patterns. The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
-the files you want to have excluded. This is also done with patterns. And
-finally with the <i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+<p>This is useful for building views of XML based documentation, or for generating code.</p>
+<p>It is possible to refine the set of files that are being processed. This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+and <var>defaultexcludes</var> attributes. With the <var>includes</var> or <var>includesfile</var>
+attribute you specify the files you want to have included by using patterns. The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded. This is
+also done with patterns. And finally with the <var>defaultexcludes</var> attribute, you can specify
+whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
 inclusion/exclusion of files works, and how to write patterns.</p>
 <p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports all
-  attributes of <code>&lt;fileset&gt;</code> (<code>dir</code> becomes <code>basedir</code>)
-  as well as the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
-  and <code>&lt;patternset&gt;</code> elements.</p>
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>basedir</var>) as well
+as the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
 
-<p><b>Note</b>: Unlike other similar tasks, this task treats
-directories that have been matched by the include/exclude patterns of
-the implicit fileset in a special way.  It will apply the stylesheets
-to all files contain in them as well.  Since the default include
-pattern is <code>**</code> this means it will apply the stylesheet to
-all files.  If you specify an excludes pattern, it may still work on
-the files matched by those patterns because the parent directory has
-been matched.  If this behavior is not what you want, set the
-scanincludedirectories attribute to false.</p>
+<p><strong>Note</strong>: Unlike other similar tasks, this task treats directories that have been
+matched by the include/exclude patterns of the implicit fileset in a special way.  It will apply the
+stylesheets to all files contain in them as well.  Since the default <var>includes</var> pattern
+is <code>**</code> this means it will apply the stylesheet to all files.  If you specify
+an <var>excludes</var> pattern, it may still work on the files matched by those patterns because the
+parent directory has been matched.  If this behavior is not what you want, set
+the <var>scanincludedirectories</var> attribute to <q>false</q>.</p>
 
-<p>Starting with Ant 1.7 this task supports nested <a
-href="../Types/resources.html#collection">resource collection</a>s
-in addition to (or instead of, depending on the useImplicitFileset
-attribute) the implicit fileset formed by this task.</p>
+<p><em>Since Ant 1.7</em>, this task supports
+nested <a href="../Types/resources.html#collection">resource collections</a> in addition to (or
+instead of, depending on the <var>useImplicitFileset</var> attribute) the implicit fileset formed by
+this task.</p>
 
-<p>This task supports the use of a nested <code>&lt;param&gt;</code> element which is used to pass values
-  to an <code>&lt;xsl:param&gt;</code> declaration.</p>
-<p>This task supports the use of a nested <a href="../Types/xmlcatalog.html">xmlcatalog</a>
-element which is used to perform Entity and URI resolution.</p>
+<p>This task supports the use of a nested <code>&lt;param&gt;</code> element which is used to pass
+values to an <code>&lt;xsl:param&gt;</code> declaration.</p>
+<p>This task supports the use of a nested <a href="../Types/xmlcatalog.html">xmlcatalog</a> element
+which is used to perform Entity and URI resolution.</p>
 
-<p><b>Note on XSLT extension functions</b>: when using the default
-  TraX implementation of the Java class library and
-  a <code>SecurityManager</code> is active - e.g. when running from
-  within an IDE - XSLT extension functions cannot be used as "secure
-  processing" is active in Java 7 and above. Ant contains a special
-  "hack" that allows XSLT extensions to be used in Java 7 and 8, but
-  this hack fails for Java 9. If you want to use extensions like the
-  redirect extension that are provided by the Java class library
-  itself, you can allow them by enabling the
-  feature <code>http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions</code>
-  in Java 9 and above. If you need to use an extension function not
-  provided by Java itself you can set the
-  attribute <code>jdk.xml.transform.extensionClassLoader</code> to a
-  classloader (reference to an Ant PATH-like structure).</p>
+<p><strong>Note on XSLT extension functions</strong>: when using the default TrAX implementation of
+the Java class library and a <code>SecurityManager</code> is active&mdash;e.g. when running from
+within an IDE&mdash;XSLT extension functions cannot be used as "secure processing" is active in Java
+7 and above. Ant contains a special "hack" that allows XSLT extensions to be used in Java 7 and 8,
+but this hack fails for Java 9. If you want to use extensions like the redirect extension that are
+provided by the Java class library itself, you can allow them by enabling the
+feature <var>http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions</var> in Java 9 and
+above. If you need to use an extension function not provided by Java itself you can set the
+attribute <var>jdk.xml.transform.extensionClassLoader</var> to a classloader (reference to an Ant
+path-like structure).</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">where to find the source XML file, default is the
-      project's basedir.</td>
-    <td align="center" valign="top">No</td>
+    <td>basedir</td>
+    <td>where to find the source XML file.</td>
+    <td>No; defaults to the project's <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">destdir</td>
-    <td valign="top">directory in which to store the results.</td>
-    <td align="center" valign="top">Yes, unless in and out have been
-      specified.</td>
+    <td>destdir</td>
+    <td>directory in which to store the results.</td>
+    <td>Yes, unless <var>in</var> and <var>out</var> have been specified.</td>
   </tr>
   <tr>
-    <td valign="top">extension</td>
-    <td valign="top">desired file extension to be used for the targets. If not
-      specified, the default is &quot;.html&quot;.  Will be ignored if
-      a nested <code>&lt;mapper&gt;</code> or both <code>in</code> and
-      <code>out</code> have been specified.</td>
-    <td align="center" valign="top">No</td>
+    <td>extension</td>
+    <td>desired file extension to be used for the targets.</td>
+    <td>No; default is <q>.html</q>, ignored if a nested <code>&lt;mapper&gt;</code> or
+      both <var>in</var> and <var>out</var> have been specified</td>
   </tr>
   <tr>
-    <td valign="top">style</td>
-    <td valign="top">name of the stylesheet to use - given either relative
-      to the project's basedir or as an absolute path.<br/>
-      <br/>
-      Alternatively, a nested element which ant can interpret as a resource
-      can be used to indicate where to find the stylesheet<br/>
-      <em>deprecated variation :</em> <br/>
-      If the stylesheet cannot be found, and if you have specified the
-      attribute basedir for the task, ant will assume that the style
-      attribute is relative to the basedir of the task.
+    <td>style</td>
+    <td>name of the stylesheet to use&mdash;given either relative to the
+      project's <var>basedir</var> or as an absolute path.<br/>  Alternatively, a nested element
+      which Ant can interpret as a resource can be used to indicate where to find the
+      stylesheet.<br/><em><u>Deprecated</u> variation</em>:<br/> If the stylesheet cannot be found,
+      and if you have specified the attribute <var>basedir</var> for the task, Ant will assume that
+      the <var>style</var> attribute is relative to the <var>basedir</var> of the task.</td>
+    <td>No, if the location of the stylesheet is specified using a nested <code>&lt;style&gt;</code>
+      element</td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>the classpath to use when looking up the XSLT processor.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>the classpath to use, given as <a href="../using.html#references">reference</a> to a path
+      defined elsewhere.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>force</td>
+    <td>Recreate target files, even if they are newer than their corresponding source files or the
+      stylesheet.</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>processor</td>
+    <td>name of the XSLT processor to use.  Permissible value is:
+      <ul>
+        <li><q>trax</q> for a TraX compliant processor (ie JAXP interface implementation such as
+          Xalan 2 or Saxon)</li>
+      </ul>
+      Support for Xalan 1 has been removed <em>since Ant 1.7</em>.
     </td>
-    <td align="center" valign="top">No, if the location of
-        the stylesheet is specified using a nested &lt;style&gt; element</td>
+    <td>No; defaults to <q>trax</q></td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use when looking up the XSLT
-      processor.</td>
-    <td align="center" valign="top">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">the classpath to use, given as <a
-      href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">force</td>
-    <td valign="top">Recreate target files, even if they are newer
-      than their corresponding source files or the stylesheet.</td>
-    <td valign="top" align="center">No; default is false</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">processor</td>
-
-    <td valign="top">name of the XSLT processor to use.
-      Permissible value is :<ul>
-      <li>&quot;trax&quot; for a TraX compliant processor (ie JAXP interface
-      implementation such as Xalan 2 or Saxon)</li></ul>
-      Defaults to trax.
-      <br/>
-      Support for xalan1 has been removed in ant 1.7.
-      </td>
-    <td align="center" valign="top">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be included.
-      All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is taken to be
-      an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>in</td>
+    <td>specifies a single XML document to be styled. Should be used
+      with the <var>out</var> attribute.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be excluded.
-      No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>out</td>
+    <td>specifies the output name for the styled result from the <var>in</var> attribute.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is taken to be
-      an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>scanincludeddirectories</td>
+    <td>If any directories are matched by the <var>includes</var>/<var>excludes</var> patterns, try
+      to transform all files in these directories.
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>reloadstylesheet</td>
+    <td>Control whether the stylesheet transformer is created anew for every transform operation. If
+      you set this to <q>true</q>, performance may suffer, but you may work around a bug in certain
+      Xalan versions.  <em>Since Ant 1.5.2</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">in</td>
-    <td valign="top">specifies a single XML document to be styled. Should be used
-      with the out attribute.</td>
-    <td valign="top" align="center">No</td>
+    <td>useImplicitFileset</td>
+    <td>Whether the implicit fileset formed by this task shall be used.  If you set this
+      to <q>false</q> you must use nested resource collections&mdash;or the <var>in</var> attribute,
+      in which case this attribute has no impact anyway. <em>Since Ant 1.7</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">out</td>
-    <td valign="top">specifies the output name for the styled result from the
-      in attribute.</td>
-    <td valign="top" align="center">No</td>
+    <td>filenameparameter</td>
+    <td>Specifies an XSL parameter for accessing the name of the current processed file. If not set,
+      the file name is not passed to the transformation.  <em>Since Ant 1.7</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">scanincludeddirectories</td>
-    <td valign="top">If any directories are matched by the
-      includes/excludes patterns, try to transform all files in these
-      directories.  Default is <code>true</code></td>
-    <td valign="top" align="center">No</td>
+    <td>filedirparameter</td>
+    <td>Specifies a XSL parameter for accessing the directory of the current processed file. For
+      files in the current directory, a value of <q>.</q> will be passed to the transformation.  If
+      not set, the directory is not passed to the transformation.  <em>Since Ant 1.7</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">reloadstylesheet</td>
-    <td valign="top">Control whether the stylesheet transformer is created
-    anew for every transform operation. If you set this to true, performance may
-    suffer, but you may work around a bug in certain Xalan-J versions.
-    Default is <code>false</code>.  <em>Since Ant 1.5.2</em>.</td>
-    <td valign="top" align="center">No</td>
+    <td>suppressWarnings</td>
+    <td>Whether processor warnings shall be suppressed.  This option requires support by the
+      processor, it is supported by the TrAX processor bundled with Ant.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">useImplicitFileset</td>
-    <td valign="top">Whether the implicit fileset formed by this task
-    shall be used.  If you set this to false you must use nested
-    resource collections - or the in attribute, in which case this
-    attribute has no impact anyway.  Default is <code>true</code>.
-    <em>Since Ant 1.7</em>.</td>
-    <td valign="top" align="center">No</td>
+    <td>failOnError</td>
+    <td>Whether the build should fail if any error occurs.  Note that transformation errors can
+      still be suppressed by setting <var>failOnTransformationError</var> to <q>false</q> even if
+      this attribute is <q>true</q>.  <em>Since Ant 1.8.0</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">filenameparameter</td>
-    <td valign="top">Specifies a xsl parameter for accessing the name
-    of the current processed file. If not set, the file name is not
-    passed to the transformation.
-    <em>Since Ant 1.7</em>.</td>
-    <td valign="top" align="center">No</td>
+    <td>failOnTransformationError</td>
+    <td>Whether the build should fail if an error occurs while transforming the document.  Note that
+      this attribute has no effect if <var>failOnError</var> is <q>false</q>.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">filedirparameter</td>
-    <td valign="top">Specifies a xsl parameter for accessing the directory
-    of the current processed file. For files in the current directory a
-    value of '.' will be passed to the transformation.
-    If not set, the directory is not passed to the transformation. 
-    <em>Since Ant 1.7</em>.</td>
-    <td valign="top" align="center">No</td>
-  </tr>
-  <tr>
-    <td valign="top">suppressWarnings</td>
-    <td valign="top">Whether processor warnings shall be suppressed.
-    This option requires support by the processor, it is supported by
-    the trax processor bundled with Ant. 
-    <em>Since Ant 1.8.0</em>.</td>
-    <td valign="top" align="center">No, default is false.</td>
-  </tr>
-  <tr>
-    <td valign="top">failOnError</td>
-    <td valign="top">Whether the build should fail if any error
-    occurs.  Note that transformation errors can still be suppressed by
-    setting failOnTransformationError to false even if this attribute
-    is true.
-    <em>Since Ant 1.8.0</em>.</td>
-    <td valign="top" align="center">No, default is true.</td>
-  </tr>
-  <tr>
-    <td valign="top">failOnTransformationError</td>
-    <td valign="top">Whether the build should fail if an error occurs
-    while transforming the document.  Note that this attribute has no
-    effect of <code>failOnError</code> is false.
-    <em>Since Ant 1.8.0</em>.</td>
-    <td valign="top" align="center">No, default is true.</td>
-  </tr>
-  <tr>
-    <td valign="top">failOnNoResources</td>
-    <td valign="top">Whether the build should fail if the nested
-    resource collection is empty.  Note that this attribute has no
-    effect of <code>failOnError</code> is false.
-    <em>Since Ant 1.8.0</em>.</td>
-    <td valign="top" align="center">No, default is true.</td>
+    <td>failOnNoResources</td>
+    <td>Whether the build should fail if the nested resource collection is empty.  Note that this
+      attribute has no effect of <var>failOnError</var> is <q>false</q>.  <em>Since Ant
+      1.8.0</em>.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
-<h4>any <a href="../Types/resources.html#collection">resource
-collection</a></h4>
+<h4>any <a href="../Types/resources.html#collection">resource collection</a></h4>
 
-<p><em>since Ant 1.7</em></p>
+<p><em>Since Ant 1.7</em></p>
 
-<p>Use resource collections to specify resources that the stylesheet
-should be applied to.  Use a nested mapper and the task's destdir
-attribute to specify the output files.</p>
+<p>Use resource collections to specify resources that the stylesheet should be applied to.  Use a
+nested mapper and the task's <q>destdir</q> attribute to specify the output files.</p>
 
-<h4><a name="classpath">classpath</a></h4>
+<h4 id="classpath">classpath</h4>
 <p>The classpath to load the processor from can be specified via a
-nested <code>&lt;classpath&gt;</code>, as well - that is, a
-<a href="../using.html#path">path</a>-like structure.</p>
+nested <code>&lt;classpath&gt;</code>, as well&mdash;that is,
+a <a href="../using.html#path">path-like structure</a>.</p>
 
 <h4>xmlcatalog</h4>
-<p>The <a href="../Types/xmlcatalog.html">xmlcatalog</a>
-element is used to perform Entity and URI resolution.</p>
+<p>The <a href="../Types/xmlcatalog.html">xmlcatalog</a> element is used to perform Entity and URI
+resolution.</p>
 
 <h4>param</h4>
-<p>Param is used to pass a parameter to the XSL stylesheet.</p>
-<blockquote>
-<h4>Parameters</h4>
-<table width="60%" 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">name</td>
-    <td valign="top">Name of the XSL parameter</td>
-    <td align="center" valign="top">Yes</td>
-  </tr>
-  <tr>
-    <td valign="top">expression</td>
-    <td valign="top">
-        The value to be placed into the param or an XPath expression
-        (depending on <code>type</code>).
-    </td>
-    <td align="center" valign="top">Yes</td>
-  </tr>
-  <tr>
-    <td valign="top">type</td>
-    <td valign="top">
-        Data type of the parameter. Possible values are:
-        <ul>
-            <li><code>STRING</code></li>
-            <li><code>BOOLEAN</code></li>
-            <li><code>INT</code></li>
-            <li><code>LONG</code></li>
-            <li><code>DOUBLE</code></li>
-            <li><code>XPATH_STRING</code></li>
-            <li><code>XPATH_BOOLEAN</code></li>
-            <li><code>XPATH_NUMBER</code></li>
-            <li><code>XPATH_NODE</code></li>
-            <li><code>XPATH_NODESET</code></li>
-        </ul>
-        <em>since Ant 1.9.3</em>
-    </td>
-    <td align="center" valign="top">No; default is <code>STRING</code></td>
-  </tr>
-  <tr>
-    <td valign="top">if</td>
-    <td valign="top">The param will only be passed <a href="../properties.html#if+unless">if this property is set</a>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">unless</td>
-    <td valign="top">The param will not be passed <a href="../properties.html#if+unless">if this property is set</a>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
+<p><code>Param</code> is used to pass a parameter to the XSL stylesheet.</p>
 
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>Name of the XSL parameter</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>expression</td>
+    <td>The value to be placed into the param or an XPath expression (depending
+    on <var>type</var>).</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>type</td>
+    <td>Data type of the parameter. Possible values are:
+      <ul>
+        <li><q>STRING</q></li>
+        <li><q>BOOLEAN</q></li>
+        <li><q>INT</q></li>
+        <li><q>LONG</q></li>
+        <li><q>DOUBLE</q></li>
+        <li><q>XPATH_STRING</q></li>
+        <li><q>XPATH_BOOLEAN</q></li>
+        <li><q>XPATH_NUMBER</q></li>
+        <li><q>XPATH_NODE</q></li>
+        <li><q>XPATH_NODESET</q></li>
+      </ul><em>since Ant 1.9.3</em>
+    </td>
+    <td>No; default is <q>STRING</q></td>
+  </tr>
+  <tr>
+    <td>if</td>
+    <td>The param will only be passed <a href="../properties.html#if+unless">if this property is
+      set</a>.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>unless</td>
+    <td>The param will not be passed <a href="../properties.html#if+unless">if this property is
+      set</a>.</td>
+    <td>No</td>
+  </tr>
 </table>
-</blockquote>
+<p>The <q>XPATH_*</q> types says that the <var>expression</var> is not just a primitive-type value
+but an XPath expression.  This expression will be evaluated on an empty XML document and the result
+will be passed to the XSLT transformer as a parameter of given type.  In these expressions the
+declared Ant properties can be used as XPath variables e.g. <code>$someProperty</code>.  So you can
+compute something using standard XPath functions and operators.</p>
+<p>If you write <code>${someProperty}</code> instead of <code>$someProperty</code>, the value will
+be simply substituted by Ant before evaluating the XPath expression (this substitution works also
+for primitive types).</p>
 
-  <p>      
-      The <code>XPATH_*</code> types says that the <code>expression</code> is not just a primitive-type value but an XPath expression.
-      This expression will be evaluated on an empty XML document and the result will be passed to the XSLT transformer as a parameter of given type.
-      In these expressions the declared Ant properties can be used as XPath variables e.g. <code>$someProperty</code>.
-      So you can compute something using standard XPath functions and operators.
-  </p>
-  <p>
-      If you write <code>${someProperty}</code> instead of <code>$someProperty</code>,
-      the value will be simply substituted by Ant before evaluating the XPath expression
-      (this substitution works also for primitive types).
-  </p>
+<h4>outputproperty (<var>trax</var> processors only)</h4>
+<p>Used to specify how you wish the result tree to be output as specified in
+the <a href="https://www.w3.org/TR/xslt#output" target="_top">XSLT specifications</a>.
 
-<h4>outputproperty ('trax' processors only)</h4>
-<p>Used to specify how you wish the result tree to be output
-as specified in the <a href="http://www.w3.org/TR/xslt#output">
-XSLT specifications</a>.
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>Name of the property</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>Value of the property</td>
+    <td>Yes</td>
+  </tr>
+</table>
+
+<h4 id="factory">factory (<var>trax</var> processors only)</h4>
+<p><em>Since Ant 1.9.8</em></p>
+<p>Used to specify factory settings.</p>
+
+<h5>Parameters</h5>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>fully qualified classname of the transformer factory to use. For
+       example <code>org.apache.xalan.processor.TransformerFactoryImpl</code>
+       or <code>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</code>
+       or <code>net.sf.saxon.TransformerFactoryImpl</code>...</td>
+    <td>No; defaults to the JAXP lookup mechanism</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<h6>attribute</h6>
+<p>Used to specify settings of the processor factory.  The attribute names and values are entirely
+processor specific so you must be aware of the implementation to figure them out.  Read the
+documentation of your processor.  For example, in Xalan 2.x:</p>
+<ul>
+  <li><var>http://xml.apache.org/xalan/features/optimize</var> (boolean)</li>
+  <li><var>http://xml.apache.org/xalan/features/incremental</var> (boolean)</li>
+  <li>...</li>
+</ul>
+<p>And in Saxon 7.x:</p>
+<ul>
+  <li><var>http://saxon.sf.net/feature/allow-external-functions</var> (boolean)</li>
+  <li><var>http://saxon.sf.net/feature/timing</var> (boolean)</li>
+  <li><var>http://saxon.sf.net/feature/traceListener</var> (string)</li>
+  <li><var>http://saxon.sf.net/feature/treeModel</var> (integer)</li>
+  <li><var>http://saxon.sf.net/feature/linenumbering</var> (integer)</li>
+  <li>...</li>
+</ul>
 <blockquote>
-<h4>Parameters</h4>
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<h6>Parameters</h6>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Name of the property</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>Name of the attribute</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">value of the property.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>value</td>
+    <td>Value of the attribute.</td>
+    <td rowspan="3">Exactly one of these</td>
+  </tr>
+  <tr>
+    <td>valueref</td>
+    <td class="left">Value of the attribute is the value of the project reference with the given
+      id. <em>since Ant 1.9.8</em></td>
+  </tr>
+  <tr>
+    <td>classloaderforpath</td>
+    <td class="left">Value of the attribute is a classloader that uses the classpath specified by a
+      path that is the project reference with the given <var>id</var>. <em>since Ant 1.9.8</em></td>
   </tr>
 </table>
 </blockquote>
 
-<h4><a name="factory">factory ('trax' processors only)</a></h4>
-Used to specify factory settings.
-<blockquote>
-<h4>Parameters</h4>
-<table width="60%" 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">name</td>
-    <td valign="top">fully qualified classname of the
-    transformer factory to use. For example
-      <tt>org.apache.xalan.processor.TransformerFactoryImpl</tt>
-       or <tt>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</tt>
-       or <tt>net.sf.saxon.TransformerFactoryImpl</tt>...
-    </td>
-    <td align="center" valign="top">No. Defaults to the JAXP lookup mechanism.</td>
-  </tr>
-</table>
-<h3>Parameters specified as nested elements</h3>
-<h4>attribute</h4>
-<p>Used to specify settings of the processor factory.
-The attribute names and values are entirely processor specific
-so you must be aware of the implementation to figure them out.
-Read the documentation of your processor.
-For example, in Xalan 2.x:
-<ul>
-<li>http://xml.apache.org/xalan/features/optimize (boolean)</li>
-<li>http://xml.apache.org/xalan/features/incremental (boolean)</li>
-<li>...</li>
-</ul>
-And in Saxon 7.x:
-<ul>
-<li>http://saxon.sf.net/feature/allow-external-functions (boolean)</li>
-<li>http://saxon.sf.net/feature/timing (boolean)</li>
-<li>http://saxon.sf.net/feature/traceListener (string)</li>
-<li>http://saxon.sf.net/feature/treeModel (integer)</li>
-<li>http://saxon.sf.net/feature/linenumbering (integer)</li>
-<li>...</li>
-</ul>
-<blockquote>
-<h4>Parameters</h4>
-<table width="60%" 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">name</td>
-    <td valign="top">Name of the attribute</td>
-    <td align="center" valign="top">Yes</td>
-  </tr>
-  <tr>
-    <td valign="top">value</td>
-    <td valign="top">value of the attribute.</td>
-    <td align="center" valign="middle" rowspan="3">Exactly one of these</td>
-  </tr>
-  <tr>
-    <td valign="top">valueref</td>
-    <td valign="top">value of the attribute is the value of the
-      project reference with the given id. <em>since Ant 1.9.8</em></td>
-  </tr>
-  <tr>
-    <td valign="top">classloaderforpath</td>
-    <td valign="top">value of the attribute is a classloader that uses
-      the classpath specified by a path that is the project reference
-      with the given id. <em>since Ant 1.9.8</em></td>
-  </tr>
-</table>
-
-<h4>Examples</h4>
+<h5>Examples</h5>
 
 <pre>
-  &lt;path id="extension-path"&gt;
-    ...
-  &lt;/path&gt;
+&lt;path id="extension-path"&gt;
+  ...
+&lt;/path&gt;
 
+&lt;xslt ...&gt;
+  &lt;factory&gt;
+    &lt;attribute name="jdk.xml.transform.extensionClassLoader"
+               classloaderforpath="extension-path"/&gt;
+  &lt;/factory&gt;
+&lt;/xslt ...&gt;</pre>
 
-  &lt;xslt ...&gt;
-    &lt;factory&gt;
-      &lt;attribute name="jdk.xml.transform.extensionClassLoader"
-                 classloaderforpath="extension-path"/&gt;
-    &lt;/factory&gt;
-  &lt;/xslt ...&gt;
-</pre>
-<p>Sets the classloader to use when loading extension functions to a
-  classloader using the <code>path</code> with the
-  id <code>extension-path</code>.
-</blockquote>
-<h4>feature</h4>
-<p><em>since Ant 1.9.8</em></p>
-<p>Used to specify settings of the processor factory.  The feature
-names are mostly processor specific so you must be aware of the
-implementation to figure them out.  Read the documentation of your
-processor. The only feature all implementations are required to
-support
-is <code>http://javax.xml.XMLConstants/feature/secure-processing</code>.
+<p>Sets the classloader to use when loading extension functions to a classloader using
+the <code>path</code> with the id <code>extension-path</code>.</p>
+
+<h6>feature</h6>
+<p>Used to specify settings of the processor factory.  The feature names are mostly processor
+specific so you must be aware of the implementation to figure them out.  Read the documentation of
+your processor. The only feature all implementations are required to support
+is <var>http://javax.xml.XMLConstants/feature/secure-processing</var>.
 <blockquote>
-<h4>Parameters</h4>
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<h6>Parameters</h6>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Name of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>Name of the feature</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">value of the feature. A boolean value
-    (i.e. permitted values are true,false,yes,no,on,off).</td>
-    <td align="center" valign="top">No, defaults to false</td>
+    <td>value</td>
+    <td>Value of the feature. A boolean value (i.e. permitted values
+      are <q>true</q>, <q>false</q>, <q>yes</q>, <q>no</q>, <q>on</q>, <q>off</q>).</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 </blockquote>
-</blockquote>
+
 <h4>mapper</h4>
 
-<p><em>since Ant 1.6.2</em></p>
+<p><em>Since Ant 1.6.2</em></p>
 
-<p>You can define filename transformations by using a nested <a
-href="../Types/mapper.html">mapper</a> element. The default mapper
-used by <code>&lt;xslt&gt;</code> removes the file extension from the
-source file and adds the extension specified via the extension
-attribute.</p>
+<p>You can define filename transformations by using a
+nested <a href="../Types/mapper.html">mapper</a> element. The default mapper used
+by <code>&lt;xslt&gt;</code> removes the file extension from the source file and adds the extension
+specified via the extension attribute.</p>
 
 <h4>style</h4>
 
 <p><em>Since Ant 1.7</em></p>
 
-<p>The nested style element can be used to specify your stylesheet in terms
-of Ant's <a href="../Types/resources.html">resource</a> types.  With
-this element, the stylesheet should be specified as a nested resource or
-single-element collection.  Alternatively, use the <code>refid</code> to
-specify the resource or collection as a reference.</p>
+<p>The nested <code>style</code> element can be used to specify your stylesheet in terms of
+Ant's <a href="../Types/resources.html">resource</a> types.  With this element, the stylesheet
+should be specified as a nested resource or single-element collection.  Alternatively, use
+the <var>refid</var> to specify the resource or collection as a reference.</p>
 
 <h4>sysproperty</h4>
-<p>Use nested <code>&lt;sysproperty&gt;</code> elements to specify
-system properties required by the factory or transformation.  These
-properties will be made available to the VM during the execution of
-the class. The attributes for this element are the same as
-for <a href="exec.html#env">environment variables</a>.</p>
 
-<p><em>since Ant 1.8.0</em>.</p>
+<p><em>Since Ant 1.8.0</em>.</p>
+<p>Use nested <code>&lt;sysproperty&gt;</code> elements to specify system properties required by the
+factory or transformation.  These properties will be made available to JVM during the execution of
+the class. The attributes for this element are the same as for <a href="exec.html#env">environment
+variables</a>.</p>
 
 <h4>syspropertyset</h4>
 
+<p><em>Since Ant 1.8.0</em>.</p>
+
 <p>You can specify a set of properties to be used as system properties
 with <a href="../Types/propertyset.html">syspropertyset</a>s.</p>
 
-<p><em>since Ant 1.8.0</em>.</p>
-
 <h3>Examples</h3>
-<blockquote>
-  <pre>
+<pre>
 &lt;xslt basedir=&quot;doc&quot; destdir=&quot;build/doc&quot;
        extension=&quot;.html&quot; style=&quot;style/apache.xsl&quot;/&gt;</pre>
-  <h4>Using an xmlcatalog</h4>
-  <pre>
+<h4>Using an xmlcatalog</h4>
+<pre>
 &lt;xslt basedir=&quot;doc&quot; destdir=&quot;build/doc&quot;
       extension=&quot;.html&quot; style=&quot;style/apache.xsl&quot;&gt;
   &lt;xmlcatalog refid=&quot;mycatalog&quot;/&gt;
 &lt;/xslt&gt;
 
 &lt;xslt basedir=&quot;doc&quot; destdir=&quot;build/doc&quot;
-   extension=&quot;.html&quot; style=&quot;style/apache.xsl&quot;&gt;
+      extension=&quot;.html&quot; style=&quot;style/apache.xsl&quot;&gt;
    &lt;xmlcatalog&gt;
        &lt;dtd
          publicId=&quot;-//ArielPartners//DTD XML Article V1.0//EN&quot;
          location=&quot;com/arielpartners/knowledgebase/dtd/article.dtd&quot;/&gt;
    &lt;/xmlcatalog&gt;
-&lt;/xslt&gt;
-</pre>
-  <h4>Using XSL parameters</h4>
-  <p>Simple String parameter:</p>
+&lt;/xslt&gt;</pre>
+<h4>Using XSL parameters</h4>
+<p>Simple String parameter:</p>
 <pre>
 &lt;xslt basedir=&quot;doc&quot; destdir=&quot;build/doc&quot;
       extension=&quot;.html&quot; style=&quot;style/apache.xsl&quot;&gt;
   &lt;param name=&quot;date&quot; expression=&quot;07-01-2000&quot;/&gt;
 &lt;/xslt&gt;</pre>
 
-  <p>Then if you declare a global parameter &quot;date&quot; with the top-level
-  element &lt;xsl:param name=&quot;date&quot;/&gt;, the variable
-  <code>$date</code> will subsequently have the value 07-01-2000.
-  </p>
-  
-  <p>Various data types and XPath expressions:</p>
-  
-  <pre>&lt;property name="antProperty1" value="ANT_PROPERTY_1"/&gt;
+<p>Then if you declare a global parameter <q>date</q> with the top-level element <code>&lt;xsl:param
+name=&quot;date&quot;/&gt;</code>, the variable <code>$date</code> will subsequently have the value
+07-01-2000.</p>
+
+<p>Various data types and XPath expressions:</p>
+
+<pre>
+&lt;property name="antProperty1" value="ANT_PROPERTY_1"/&gt;
 &lt;property name="antProperty2" value="ANT_PROPERTY_2"/&gt;
 &lt;property name="antProperty3" value="3"/&gt;
 &lt;property name="antProperty4" value="substring-before"/&gt;
@@ -594,43 +526,43 @@
 --&gt;
 
 &lt;xslt in="in.xml" out="out.xml" style="template.xsl"&gt;
-  
+
   &lt;!-- Simple String parameter: --&gt;
   &lt;param name="p0" expression="some nice string" type="STRING"/&gt;
-  
+
   &lt;!-- A value substituted by Ant --&gt;
   &lt;param name="p1" expression="some string with ${antProperty1} constructed by Ant" type="STRING"/&gt;
-  
+
   &lt;!-- XPath resulting in: and this is done in XPath: ANT_PROPERTY_2 --&gt;
   &lt;param name="p2" expression="concat('and this is done in XPath: ', $antProperty2)" type="XPATH_STRING"/&gt;
-  
+
   &lt;!-- Some XPath math, result: 42 --&gt;
   &lt;param name="p3" expression="64 * 64 div 128 + 10" type="XPATH_NUMBER"/&gt;
-  
+
   &lt;!-- Some numeric parameter: --&gt;
   &lt;param name="p4" expression="123.45" type="DOUBLE"/&gt;
-  
+
   &lt;!-- XPath expression, result: true boolean --&gt;
   &lt;param name="p5" expression="$antProperty1 = 'ANT_PROPERTY_1'" type="XPATH_BOOLEAN"/&gt;
-  
+
   &lt;!-- First one is an XPath variable, second one is a text substituted by Ant, result: true boolean --&gt;
   &lt;param name="p6" expression="$antProperty2 = '${antProperty2}'" type="XPATH_BOOLEAN"/&gt;
-  
+
   &lt;!-- Some XPath math with a variable, result: 64 --&gt;
   &lt;param name="p7" expression="$antProperty3 * 4 * 5 + 4" type="XPATH_NUMBER"/&gt;
-  
-  &lt;!-- 
+
+  &lt;!--
     XPath expression with substituted function name and a variable:
     substring-before($antProperty2, '_')
     result: ANT
   --&gt;
   &lt;param name="p8" expression="${antProperty4}($antProperty2, '_')" type="XPATH_STRING"/&gt;
-  
+
   &lt;!-- Without type attribute: --&gt;
   &lt;param name="p9" expression="default type is String"/&gt;
 &lt;/xslt&gt;</pre>
 
-  <h4>Using output properties</h4>
+<h4>Using output properties</h4>
 <pre>
 &lt;xslt in=&quot;doc.xml&quot; out=&quot;build/doc/output.xml&quot;
       style=&quot;style/apache.xsl&quot;&gt;
@@ -638,10 +570,9 @@
   &lt;outputproperty name=&quot;standalone&quot; value=&quot;yes&quot;/&gt;
   &lt;outputproperty name=&quot;encoding&quot; value=&quot;iso8859_1&quot;/&gt;
   &lt;outputproperty name=&quot;indent&quot; value=&quot;yes&quot;/&gt;
-&lt;/xslt&gt;
-</pre>
+&lt;/xslt&gt;</pre>
 
-  <h4>Using factory settings</h4>
+<h4>Using factory settings</h4>
 <pre>
 &lt;xslt in=&quot;doc.xml&quot; out=&quot;build/doc/output.xml&quot;
       style=&quot;style/apache.xsl&quot;&gt;
@@ -650,15 +581,15 @@
   &lt;/factory&gt;
 &lt;/xslt&gt;</pre>
 
-  <h4>Using a mapper</h4>
+<h4>Using a mapper</h4>
 <pre>
 &lt;xslt basedir=&quot;in&quot; destdir=&quot;out&quot;
       style=&quot;style/apache.xsl&quot;&gt;
   &lt;mapper type=&quot;glob&quot; from=&quot;*.xml.en&quot; to=&quot;*.html.en&quot;/&gt;
 &lt;/xslt&gt;</pre>
 
-  <h4>Using a nested resource to define the stylesheet</h4>
-    <pre>
+<h4>Using a nested resource to define the stylesheet</h4>
+<pre>
 &lt;xslt in="data.xml" out="${out.dir}/out.xml"&gt;
     &lt;style&gt;
         &lt;url url="${printParams.xsl.url}"/&gt;
@@ -666,25 +597,24 @@
     &lt;param name="set" expression="value"/&gt;
 &lt;/xslt&gt;</pre>
 
-  <h4>Print the current processed file name</h4>
+<h4>Print the current processed file name</h4>
 <pre>
 &lt;project&gt;
   &lt;xslt style=&quot;printFilename.xsl&quot; destdir=&quot;out&quot; basedir=&quot;in&quot; extension=&quot;.txt&quot;
         filenameparameter=&quot;filename&quot;
-        filedirparameter=&quot;filedir&quot;
-  /&gt;
+        filedirparameter=&quot;filedir&quot;/&gt;
 &lt;/project&gt;
 
 &lt;xsl:stylesheet
-  version=&quot;1.0&quot;
-  xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
+     version=&quot;1.0&quot;
+     xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
 
-    &lt;xsl:param name=&quot;filename&quot;&gt;&lt;/xsl:param&gt;
-    &lt;xsl:param name=&quot;filedir&quot;&gt;.&lt;/xsl:param&gt;
+  &lt;xsl:param name=&quot;filename&quot;&gt;&lt;/xsl:param&gt;
+  &lt;xsl:param name=&quot;filedir&quot;&gt;.&lt;/xsl:param&gt;
 
-&lt;xsl:template match=&quot;/&quot;&gt;
-  Current file is &lt;xsl:value-of select=&quot;$filename&quot;/&gt; in directory &lt;xsl:value-of select=&quot;$filedir&quot;/&gt;.
-&lt;/xsl:template&gt;
+  &lt;xsl:template match=&quot;/&quot;&gt;
+    Current file is &lt;xsl:value-of select=&quot;$filename&quot;/&gt; in directory &lt;xsl:value-of select=&quot;$filedir&quot;/&gt;.
+  &lt;/xsl:template&gt;
 
 &lt;/xsl:stylesheet&gt;
 </pre>
@@ -694,12 +624,9 @@
 <pre>
 &lt;xslt ...&gt;
     &lt;sysproperty key="org.apache.xerces.xni.parser.XMLParserConfiguration"
-                 value="org.apache.xerces.parsers.XIncludeParserConfiguration"
-     /&gt;
+                 value="org.apache.xerces.parsers.XIncludeParserConfiguration"/&gt;
 &lt;xslt&gt;
 </pre>
-</blockquote>
-
 
 </body>
 </html>
diff --git a/manual/Tasks/subant.html b/manual/Tasks/subant.html
index 424bb67..9122bd7 100644
--- a/manual/Tasks/subant.html
+++ b/manual/Tasks/subant.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -15,594 +16,258 @@
    limitations under the License.
 -->
 
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
+  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Subant Task</title>
 </head>
 
-<body bgcolor="#ffffff" text="#000000" link="#525D76"
-      alink="#525D76" vlink="#525D76">
+<body>
+<h2>Subant Task</h2>
+<p><em>Since Apache Ant 1.6</em></p>
+<h3 id="description">Description</h3>
+<p>Calls a given target for all defined sub-builds.  This is an extension of Ant for bulk project
+execution.  <strong>This task must not be used outside of a <code>target</code> if it invokes the
+same build file it is part of.</strong></p>
 
-<table border="0" width="100%" cellspacing="4">
+<p><code>subant</code> uses <code>ant</code> internally so many things said
+in <a href="ant.html"><code>ant</code>'s manual page</a> apply here as well.</p>
 
-  <!-- PAGE HEADER -->
-  <tr>
-    <td>
-      <table border="0" width="100%"><tr>
-          <td valign="bottom">
-            <font size="+3" face="arial,helvetica,sanserif"><strong>Subant Task</strong></font>
-            <br><font face="arial,helvetica,sanserif">Calls a given target for all defined sub-builds.</font>
-          </td>
-          <td>
-            <!-- PROJECT LOGO -->
-            <a href="http://ant.apache.org/">
-              <img src="../images/ant_logo_large.gif" align="right" alt="Apache Ant" border="0">
-            </a>
-          </td>
-      </tr></table>
-    </td>
-  </tr>
-
-  <!-- START RIGHT SIDE MAIN BODY -->
-  <tr>
-    <td  valign="top" align="left">
-
-          <!-- Applying task/description -->
-    <!-- Start Description -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="description">
-          <strong>Description</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-<p>
-            Calls a given target for all defined sub-builds.
-            This is an extension
-            of ant for bulk project execution.
-
-            <strong>This task must not be used outside of a
-                <code>target</code> if it invokes the same build file it is
-                part of.</strong>
-        </p>
-        <p><em>Since Apache Ant 1.6</em></p>
-
-<p><code>subant</code> uses <code>ant</code> internally so many things
-  said in <a href="ant.html"><code>ant</code>'s manual page</a> apply
-  here as well.</p>
-
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <!-- Subsection heading -->
-      <tr><td bgcolor="#828DA6">
-          <font color="#ffffff" face="arial,helvetica.sanserif">
-                              <a name="Use with directories">
-          <strong>Use with directories</strong></a></font>
-      </td></tr>
-      <!-- Subsection body -->
-      <tr><td>
-        <p>
-                subant can be used with directory sets to execute a build from different directories.
-                2 different options are offered :
-            </p>
+<h3 id="Use-with-directories">Use with directories</h3>
+<p><code>subant</code> can be used with directory sets to execute a build from different
+directories.  2 different options are offered:</p>
 <ul>
-                <li>
-                    to run the same build file <code>/somepath/otherpath/mybuild.xml</code>
-                    with different base directories, use the genericantfile attribute
-                </li>
-                <li>if you want to run <code>directory1/mybuild.xml</code>, <code>directory2/mybuild.xml</code>, <code>....</code>,
-                    use the antfile attribute. The subant task does not set the base directory for you in this case, because you can specify it in each build file.
-                </li>
-            </ul>
+  <li>to run the same build file <samp>/somepath/otherpath/mybuild.xml</samp> with different base
+    directories, use the <var>genericantfile</var> attribute</li>
+  <li>if you want to
+    run <samp>directory1/mybuild.xml</samp>, <samp>directory2/mybuild.xml</samp>, <samp>...</samp>,
+    use the <var>antfile</var> attribute. The <code>subant</code> task does not set the base
+    directory for you in this case, because you can specify it in each build file.</li>
+</ul>
 
-      </td></tr>
-    </table>
-
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Description -->
-
- <!-- Ignore -->
-
-
-
-    <!-- Start Attributes -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="attributes">
-          <strong>Parameters</strong></a></font>
-      </td></tr>
-      <tr><td><blockquote>
-        <table>
-          <tr>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Attribute</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Description</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Type</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Requirement</b></font>
-        </td>
-          </tr>
-    <!-- Attribute Group -->
-
-    <!-- Attribute Group -->
-        <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">antfile</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Build file name, to use in conjunction with directories.<br> Defaults to "build.xml".<br> If <code>genericantfile</code> is set, this attribute is ignored.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left" rowspan="10">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Optional</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">buildpath</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Set the buildpath to be used to find sub-projects.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Path</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">buildpathref</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Buildpath to use, by reference.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Reference</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">failonerror</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Sets whether to fail with a build exception on error, or go on.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">genericantfile</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Build file path, to use in conjunction with directories.<br> Use <code>genericantfile</code>, in order to run the same build file with different basedirs.<br> If this attribute is set, <code>antfile</code> is ignored.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">File</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">inheritall</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1"
-                        face="arial,helvetica,sanserif">Corresponds to
-                        <code>&lt;ant&gt;</code>'s
-                        <code>inheritall</code> attribute but defaults
-                        to false in this task..</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">inheritrefs</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Corresponds to <code>&lt;ant&gt;</code>'s <code>inheritrefs</code> attribute.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">output</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Corresponds to <code>&lt;ant&gt;</code>'s <code>output</code> attribute.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">target</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"></font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">verbose</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">
-            Enable/ disable log messages showing when each sub-build path is entered/ exited.
-            The default value is false.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-    </tr>
-
-
-        </table>
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Attributes -->
-
-    <!-- Start Elements -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="elements">
-          <strong>Parameters as nested elements</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>any filesystem based <a href="../Types/resources.html#collection">resource collection</a></strong></font>
-      </td></tr>
-      <tr><td><blockquote>
-        This includes <code>&lt;fileset&gt;</code>,
-        <code>&lt;dirset&gt;</code> and <code>&lt;filelist&gt;</code>
-        which are the nested resource collections supported prior
-        to Ant 1.7.
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>dirset</strong> (org.apache.tools.ant.types.DirSet)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Adds a directory set to the implicit build path. <p> <em>Note that the directories will be added to the build path in no particular order, so if order is significant, one should use a file list instead!</em>
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>filelist</strong> (org.apache.tools.ant.types.FileList)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Adds an ordered file list to the implicit build path. <p> <em>Note that contrary to file and directory sets, file lists can reference non-existent files or directories!</em>
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>fileset</strong> (org.apache.tools.ant.types.FileSet)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Adds a file set to the implicit build path. <p> <em>Note that the directories will be added to the build path in no particular order, so if order is significant, one should use a file list instead!</em>
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>property</strong> (org.apache.tools.ant.taskdefs.Property)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;property&gt;</code> element.
-
-<p>When more than one nested <code>&lt;property&gt;</code> element
-  would set a property of the same name, the one declared last will
-  win.  This is for backwards compatibility reasons even so it is
-  different from the way <code>&lt;property&gt;</code> tasks in build
-  files behave.</p>
-
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>propertyset</strong> (org.apache.tools.ant.types.PropertySet)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;propertyset&gt;</code> element.
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>buildpath</strong> (org.apache.tools.ant.types.Path)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Creates a nested build path, and add it to the implicit build path.
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>buildpathelement</strong> (org.apache.tools.ant.types.Path.PathElement)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        Creates a nested <code>&lt;buildpathelement&gt;</code>, and add it to the implicit build path.
- <!-- Ignore -->
- <!-- Ignore -->
-
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-
-
-
-
-<!-- manually written -->
-    <!-- Start Element -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#828DA6">
-        <font color="#ffffff" face="arial,helvetica.sanserif" size="-1">
-          <strong>target</strong> (org.apache.tools.ant.taskdefs.Ant.TargetElement)</font>
-      </td></tr>
-      <tr><td><blockquote>
-        You can specify multiple targets using nested <code>&lt;target&gt;</code> elements
-        instead of using the target attribute.  These will be executed as if
-        Ant had been invoked with a single target whose dependencies are the
-        targets so specified, in the order specified.
- <!-- Ignore -->
- <!-- Ignore -->
-      <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">name</td>
-          <td valign="top">The name of the called target.</td>
-          <td valign="top" align="center">Yes</td>
-        </tr>
-      </table>
-      <p><em>since Ant 1.7</em>.</p>
-      </blockquote></td></tr>
-    </table>
-    <!-- End Element -->
-<!-- manually written end -->
-
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Elements -->
-
-
-
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-          <font color="#ffffff" face="arial,helvetica.sanserif">
-                              <a name="examples">
-          <strong>Examples</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote style="">
-        <pre>
-        &lt;project name="subant" default="subant1"&gt;
-            &lt;property name="build.dir" value="subant.build"/&gt;
-            &lt;target name="subant1"&gt;
-                &lt;subant target=""&gt;
-                    &lt;property name="build.dir" value="subant1.build"/&gt;
-                    &lt;property name="not.overloaded" value="not.overloaded"/&gt;
-                    &lt;fileset dir="." includes="*/build.xml"/&gt;
-                &lt;/subant&gt;
-            &lt;/target&gt;
-        &lt;/project&gt;
-        </pre>
-<p>
-            this snippet build file will run ant in each subdirectory of the project directory,
-            where a file called build.xml can be found.
-            The property build.dir will have the value subant1.build in the ant projects called by subant.
-        </p>
-<pre>
-          &lt;subant target=""&gt;
-              &lt;propertyset&gt;
-                  &lt;propertyref prefix="toplevel"/&gt;
-                  &lt;mapper type="glob" from="foo*" to="bar*"/&gt;
-              &lt;/propertyset&gt;
-              &lt;fileset dir="." includes="*/build.xml"/&gt;
-          &lt;/subant&gt;
-        </pre>
-<p>
-            this snippet build file will run ant in each subdirectory of the project directory,
-            where a file called build.xml can be found.
-            All properties whose name starts with "foo" are passed, their names are changed to start with "bar" instead
-        </p>
-<pre>
-          &lt;subant target="compile" genericantfile="/opt/project/build1.xml"&gt;
-              &lt;dirset dir="." includes="projects*"/&gt;
-          &lt;/subant&gt;
-        </pre>
-<p>
-            assuming the subdirs of the project dir are called projects1, projects2, projects3
-            this snippet will execute the compile target of /opt/project/build1.xml,
-            setting the basedir to projects1, projects2, projects3
-        </p>
-
-        <!-- manually written -->
-        <p>Now a little more complex - but useful - scenario. Assume that we have
-        a directory structure like this:</p>
-        <pre>
-        root
-          |  common.xml
-          |  build.xml
-          |
-          +-- modules
-                +-- modA
-                |     +-- src
-                +-- modB
-                      +-- src
-
-        <u><b>common.xml:</b></u><br>
-        &lt;project&gt;
-            &lt;property name="src.dir"      value="src"/&gt;
-            &lt;property name="build.dir"    value="build"/&gt;
-            &lt;property name="classes.dir"  value="${build.dir}/classes"/&gt;
-
-            &lt;target name="compile"&gt;
-                &lt;mkdir dir="${classes.dir}"/&gt;
-                &lt;javac srcdir="${src.dir}" destdir="${classes.dir}"/&gt;
-            &lt;/target&gt;
-
-            &lt;!-- more targets --&gt;
-        &lt;/project&gt;
-
-        <u><b>build.xml:</b></u><br>
-        &lt;project&gt;
-
-            &lt;macrodef name="iterate"&gt;
-                &lt;attribute name="target"/&gt;
-                &lt;sequential&gt;
-                    &lt;subant target="@{target}"&gt;
-                        &lt;fileset dir="modules" includes="*/build.xml"/&gt;
-                    &lt;/subant&gt;
-                &lt;/sequential&gt;
-            &lt;/macrodef&gt;
-
-
-            &lt;target name="compile"&gt;
-                &lt;iterate target="compile"/&gt;
-            &lt;/target&gt;
-
-            &lt;!-- more targets --&gt;
-        &lt;/project&gt;
-
-        <u><b>modules/modA/build.xml:</b></u><br>
-        &lt;project name="modA"&gt;
-            &lt;import file="../../common.xml"/&gt;
-        &lt;/project&gt;
-        </pre>
-
-        <p>This results in very small buildfiles in the modules, maintainable
-        buildfile (common.xml) and a clear project structure. Additionally
-        the root buildfile is capable to run the whole build over all
-        modules.
-        </p>
-
-        <pre>
-        &lt;subant failonerror="false"&gt;
-            &lt;fileset dir="." includes="**/build.xml" excludes="build.xml"/&gt;
-            &lt;target name="clean"/&gt;
-            &lt;target name="build"/&gt;
-        &lt;/subant&gt;
-        </pre>
-
-        <p>Does a &quot;clean build&quot; for each subproject.</p>
-        <p><b>Hint:</b> because buildfiles are plain xml, you could generate the
-        masterbuildfile from the common buildfile by using a XSLT transformation:
-        </p>
-
-        <pre>
-        &lt;xslt in=&quot;common.xml&quot;
-              out=&quot;master.xml&quot;
-              style=&quot;${ant.home}/etc/common2master.xsl&quot;
-        /&gt;
-        </pre>
-
-        <!-- manually written -->
-
-      </blockquote></td></tr>
-
-    </table>
-
-    </td>
+<h3 id="attributes">Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Type</th>
+    <th scope="col">Required</th>
   </tr>
-  <!-- END RIGHT SIDE MAIN BODY -->
-
+  <tr>
+    <td>antfile</td>
+    <td>Build file name, to use in conjunction with directories.</td>
+    <td>String</td>
+    <td>No; defaults to <q>build.xml</q>, ignored if <var>genericantfile</var> is set</td>
+  </tr>
+  <tr>
+    <td>buildpath</td>
+    <td>Set the buildpath to be used to find sub-projects.</td>
+    <td>Path</td>
+    <td rowspan="8">No</td>
+  </tr>
+  <tr>
+    <td>buildpathref</td>
+    <td>Buildpath to use, by reference.</td>
+    <td class="left">Reference</td>
+  </tr>
+  <tr>
+    <td>failonerror</td>
+    <td>Sets whether to fail with a build exception on error, or go on.</td>
+    <td class="left">boolean</td>
+  </tr>
+  <tr>
+    <td>genericantfile</td>
+    <td>Build file path, to use in conjunction with directories.<br/>  Use <var>genericantfile</var>,
+      in order to run the same build file with different <var>basedir</var>s.<br/>  If this attribute
+      is set, <var>antfile</var> is ignored.</td>
+    <td class="left">File</td>
+  </tr>
+  <tr>
+    <td>inheritall</td>
+    <td>Corresponds to <code>&lt;ant&gt;</code>'s <var>inheritall</var> attribute but defaults
+      to <q>false</q> in this task.</td>
+    <td class="left">boolean</td>
+  </tr>
+  <tr>
+    <td>inheritrefs</td>
+    <td>Corresponds to <code>&lt;ant&gt;</code>'s <var>inheritrefs</var> attribute.</td>
+    <td class="left">boolean</td>
+  </tr>
+  <tr>
+    <td>output</td>
+    <td>Corresponds to <code>&lt;ant&gt;</code>'s <var>output</var> attribute.</td>
+    <td class="left">String</td>
+  </tr>
+  <tr>
+    <td>target</td>
+    <td>&nbsp;</td>
+    <td class="left">String</td>
+  </tr>
+  <tr>
+    <td>verbose</td>
+    <td>Enable/disable log messages showing when each sub-build path is entered/exited.</td>
+    <td>boolean</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+</table>
+<h3 id="elements">Parameters as nested elements</h3>
+<h4>any filesystem based <a href="../Types/resources.html#collection">resource collection</a></h4>
+<p>This includes <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code>
+and <code>&lt;filelist&gt;</code> which are the nested resource collections supported prior to Ant
+1.7.</p>
+<h4><strong>dirset</strong> (org.apache.tools.ant.types.DirSet)</h4>
+Adds a directory set to the implicit build path.
+<p><em>Note that the directories will be added to the build path in no particular order, so if order
+is significant, one should use a file list instead!</em></p>
+<h4><strong>filelist</strong> (org.apache.tools.ant.types.FileList)</h4>
+<p>Adds an ordered file list to the implicit build path.</p>
+<p><em>Note that contrary to file and directory sets, file lists can reference non-existent files or
+directories!</em></p>
+<h4><strong>fileset</strong> (org.apache.tools.ant.types.FileSet)</h4>
+<p>Adds a file set to the implicit build path.</p>
+<p><em>Note that the directories will be added to the build path in no particular order, so if order
+is significant, one should use a file list instead!</em></p>
+<h4><strong>property</strong> (org.apache.tools.ant.taskdefs.Property)</h4>
+<p>Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;property&gt;</code> element.</p>
+<p>When more than one nested <code>&lt;property&gt;</code> element would set a property of the same
+name, the one declared last will win.  This is for backwards compatibility reasons even so it is
+different from the way <code>&lt;property&gt;</code> tasks in build files behave.</p>
+<h4><strong>propertyset</strong> (org.apache.tools.ant.types.PropertySet)</h4>
+<p>Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;propertyset&gt;</code> element.</p>
+<h4><strong>buildpath</strong> (org.apache.tools.ant.types.Path)</h4>
+<p>Creates a nested build path, and add it to the implicit build path.</p>
+<h4><strong>buildpathelement</strong> (org.apache.tools.ant.types.Path.PathElement)</h4>
+<p>Creates a nested <code>&lt;buildpathelement&gt;</code>, and add it to the implicit build
+path.</p>
+<h4><strong>target</strong> (org.apache.tools.ant.taskdefs.Ant.TargetElement)</h4>
+<p><em>Since Ant 1.7</em>.</p>
+<p>You can specify multiple targets using nested <code>&lt;target&gt;</code> elements instead of
+using the target attribute.  These will be executed as if Ant had been invoked with a single target
+whose dependencies are the targets so specified, in the order specified.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>The name of the called target.</td>
+    <td>Yes</td>
+  </tr>
 </table>
 
+<h3 id="examples">Examples</h3>
+
+<p>This snippet build file will run <kbd>ant</kbd> in each subdirectory of the project directory,
+where a file called <samp>build.xml</samp> can be found. The property <code>build.dir</code> will
+have the value <q>subant1.build</q> in the Ant projects called by <code>subant</code>.</p>
+
+<pre>
+&lt;project name="subant" default="subant1"&gt;
+    &lt;property name="build.dir" value="subant.build"/&gt;
+    &lt;target name="subant1"&gt;
+        &lt;subant target=""&gt;
+            &lt;property name="build.dir" value="subant1.build"/&gt;
+            &lt;property name="not.overloaded" value="not.overloaded"/&gt;
+            &lt;fileset dir="." includes="*/build.xml"/&gt;
+        &lt;/subant&gt;
+    &lt;/target&gt;
+&lt;/project&gt;</pre>
+
+<p>This snippet build file will run <kbd>ant</kbd> in each subdirectory of the project directory,
+where a file called <samp>build.xml</samp> can be found. All properties whose name starts
+with <q>foo</q> are passed, their names are changed to start with <q>bar</q> instead</p>
+
+<pre>
+&lt;subant target=""&gt;
+    &lt;propertyset&gt;
+        &lt;propertyref prefix="toplevel"/&gt;
+        &lt;mapper type="glob" from="foo*" to="bar*"/&gt;
+    &lt;/propertyset&gt;
+    &lt;fileset dir="." includes="*/build.xml"/&gt;
+&lt;/subant&gt;</pre>
+
+<p>Assuming the subdirs of the project dir are
+called <samp>projects1</samp>, <samp>projects2</samp>, <samp>projects3</samp>, this snippet will
+execute the <q>compile</q> target of <samp>/opt/project/build1.xml</samp>, setting
+the <var>basedir</var> to <q>projects1</q>, <q>projects2</q>, <q>projects3</q></p>
+
+<pre>
+&lt;subant target="compile" genericantfile="/opt/project/build1.xml"&gt;
+    &lt;dirset dir="." includes="projects*"/&gt;
+&lt;/subant&gt;</pre>
+
+<p>Now a little more complex&mdash;but useful&mdash;scenario. Assume that we have a directory
+structure like this:</p>
+
+<pre>
+root
+  |  common.xml
+  |  build.xml
+  |
+  +-- modules
+        +-- modA
+        |     +-- src
+        +-- modB
+              +-- src
+
+<b>common.xml:</b><br/>
+&lt;project&gt;
+    &lt;property name="src.dir"      value="src"/&gt;
+    &lt;property name="build.dir"    value="build"/&gt;
+    &lt;property name="classes.dir"  value="${build.dir}/classes"/&gt;
+
+    &lt;target name="compile"&gt;
+        &lt;mkdir dir="${classes.dir}"/&gt;
+        &lt;javac srcdir="${src.dir}" destdir="${classes.dir}"/&gt;
+    &lt;/target&gt;
+
+    &lt;!-- more targets --&gt;
+&lt;/project&gt;
+
+<b>build.xml:</b><br/>
+&lt;project&gt;
+    &lt;macrodef name="iterate"&gt;
+        &lt;attribute name="target"/&gt;
+        &lt;sequential&gt;
+            &lt;subant target="@{target}"&gt;
+                &lt;fileset dir="modules" includes="*/build.xml"/&gt;
+            &lt;/subant&gt;
+        &lt;/sequential&gt;
+    &lt;/macrodef&gt;
+
+    &lt;target name="compile"&gt;
+        &lt;iterate target="compile"/&gt;
+    &lt;/target&gt;
+
+    &lt;!-- more targets --&gt;
+&lt;/project&gt;
+
+<b>modules/modA/build.xml:</b><br/>
+&lt;project name="modA"&gt;
+    &lt;import file="../../common.xml"/&gt;
+&lt;/project&gt;</pre>
+
+<p>This results in very small build files in the modules, maintainable build file
+(<samp>common.xml</samp>) and a clear project structure. Additionally the root build file is capable
+to run the whole build over all modules.</p>
+
+<p>This task performs a <q>clean build</q> for each subproject.</p>
+
+<pre>
+&lt;subant failonerror="false"&gt;
+    &lt;fileset dir="." includes="**/build.xml" excludes="build.xml"/&gt;
+    &lt;target name="clean"/&gt;
+    &lt;target name="build"/&gt;
+&lt;/subant&gt;</pre>
+
+<p><strong>Hint</strong>: because build files are plain XML, you could generate the master build
+file from the common build file by using a XSLT transformation:</p>
+
+<pre>
+&lt;xslt in=&quot;common.xml&quot;
+      out=&quot;master.xml&quot;
+      style=&quot;${ant.home}/etc/common2master.xsl&quot;/&gt;</pre>
 </body>
 </html>
diff --git a/manual/Tasks/symlink.html b/manual/Tasks/symlink.html
index df42abd..6c93d05 100644
--- a/manual/Tasks/symlink.html
+++ b/manual/Tasks/symlink.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,133 +15,110 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Symlink Task</title>
 </head>
 
 <body>
 
-<h2><a name="symlink">Symlink</a></h2>
+<h2 id="symlink">Symlink</h2>
 <h3>Description</h3>
-<p> Manages symbolic links on Unix based platforms. Can be used to
-make an individual link, delete a link, create multiple links from properties files, 
-or create properties files describing links in the specified directories.
-Existing links are not overwritten by default.
-
-<p><a href="../Types/fileset.html">FileSet</a>s are used to select a
-set of links to record, or a set of property files to create links from. </p>
+<p>Manages symbolic links on platforms where Java supports symbolic links.  Can be used to make an
+individual link, delete a link, create multiple links from properties files, or create properties
+files describing links in the specified directories. Existing files are not overwritten by
+default.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s are used to select a set of links to record, or a
+set of property files to create links from.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">action</td>
-    <td valign="top">The type of action to perform, may be "single", 
-    "record", "recreate" or "delete".</td>
-    <td valign="top" align="center">No, defaults to single.</td>
+    <td>action</td>
+    <td>The type of action to perform, may be <q>single</q>, "<q>record</q>, <q>recreate</q>
+      or <q>delete</q>.</td>
+    <td>No; defaults to <q>single</q></td>
   </tr>
   <tr>
-    <td valign="top">link</td>
-    <td valign="top">The name of the link to be created or deleted.<br/>
-      <b>Note</b> this attribute is resolved against the current
-      working directory rather than the project's basedir for
-      historical reasons.  It is recommended you always use an
-      absolute path or a path like <code>${basedir}/some-path</code>
-      as its value.
+    <td>link</td>
+    <td>The name of the link to be created or deleted.<br/><strong>Note</strong>: this attribute is
+      resolved against the current working directory rather than the project's <var>basedir</var>
+      for historical reasons.  It is recommended you always use an absolute path or a path
+      like <samp>${basedir}/some-path</samp> as its value.
     </td>
-    <td valign="center" align="center" >required for 
-    action="single" or "delete". Ignored in other actions.</td>
+    <td>Yes, for <var>action</var>=<q>single</q> or <q>delete</q>; ignored in other actions</td>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top">The resource the link should point to.</td>
-    <td valign="top" align="center">required for action="single". Ignored in other actions.</td>
+    <td>resource</td>
+    <td>The resource the link should point to.</td>
+    <td>Yes, for <var>action</var>=<q>single</q>; ignored in other actions</td>
   </tr>
   <tr>
-    <td valign="top">linkfilename</td>
-    <td valign="top">The name of the properties file to create in 
-    each included directory.</td>
-    <td valign="top" align="center">required for action="record". 
-    Ignored in other actions.</td>
+    <td>linkfilename</td>
+    <td>The name of the properties file to create in each included directory.</td>
+    <td>Yes, for <var>action</var>=<q>record</q>; ignored in other actions</td>
   </tr>
   <tr>
-    <td valign="top">overwrite</td>
-    <td valign="top">Overwrite existing links or not.</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>overwrite</td>
+    <td>Overwrite existing files or not. If overwrite is set to <q>true</q>, then any existing file,
+      specified by the link attribute, will be overwritten irrespective of whether or not the
+      existing file is a symbolic link.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-     <td valign="top">Stop build if true, log a warning message, but do not stop the build,
-       when the an error occurs if false.
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>failonerror</td>
+    <td>Stop build if true, log a warning message, but do not stop the build, when the an error
+      occurs if <q>false</q>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
- 
+
 <h4>fileset</h4>
- <p><a href="../Types/fileset.html">FileSet</a>s
- are used when action = "record" to select directories and linknames to be recorded. 
- They are also used when action = "recreate" to specify both the name of the property 
- files to be processed, and the directories in which they can be found. At least one 
- fileset is required for each case.</p>
- 
+<p><a href="../Types/fileset.html">FileSet</a>s are used when <var>action</var>=<q>record</q> to
+select directories and link names to be recorded.  They are also used
+when <var>action</var>=<q>recreate</q> to specify both the name of the property files to be
+processed, and the directories in which they can be found. At least one fileset is required for each
+case.</p>
+
 <h3>Examples</h3>
 
-  <p> Make a link named "foo" to a resource named "bar.foo" in subdir:</p>
-  <pre>
-  &lt;symlink link="${dir.top}/foo" resource="${dir.top}/subdir/bar.foo"/&gt;
-  </pre>
- 
-  <p> Record all links in subdir and it's descendants in files named
-  "dir.links"</p>
-  <pre>
-  &lt;symlink action="record" linkfilename="dir.links"&gt;
-     &lt;fileset dir="${dir.top}" includes="subdir&#47;**"/&gt;
-  &lt;/symlink&gt;
-  </pre>
- 
-  <p> Recreate the links recorded in the previous example:</p>
-  <pre>
-  &lt;symlink action="recreate"&gt;
-     &lt;fileset dir="${dir.top}" includes="subdir&#47;**&#47;dir.links"/&gt;  
-  &lt;/symlink&gt;
-  </pre>
- 
- <p> Delete a link named "foo":
- <pre>
- &lt;symlink action="delete" link="${dir.top}/foo"/&gt;
- </pre>
+<p>Make a link named <samp>foo</samp> to a resource named <samp>bar.foo</samp>
+in <samp>subdir</samp>:</p>
+<pre>&lt;symlink link="${dir.top}/foo" resource="${dir.top}/subdir/bar.foo"/&gt;</pre>
 
-  <p><strong>Java 1.2 and earlier:</strong> Due to limitations on executing system
-  level commands in Java versions earlier than 1.3 this task may have difficulty
-  operating with a relative path in ANT_HOME. The typical symptom is an 
-  IOException where Apache Ant can't find /some/working/directory${ANT_HOME}/bin/antRun
-  or something similar. The workaround is to change your ANT_HOME environment
-  variable to an absolute path, which will remove the /some/working/directory portion
-  of the above path and allow ant to find the correct commandline execution script.
- 
-  <p><strong>LIMITATIONS:</strong> Because Java has no direct support for
-  handling symlinks this task divines them by comparing canonical and
-  absolute paths. On non-unix systems this may cause false positives.
-  Furthermore, any operating system on which the command
-  <code>ln -s &lt;linkname&gt; &lt;resourcename&gt;</code> is not a valid 
-  command on the command line will not be able to use action="single" or 
-  action="recreate". Action="record" and action=delete should still work. Finally, 
-  the lack of support for symlinks in Java means that all links are recorded as 
-  links to the <strong>canonical</strong> resource name. Therefore the link:
-  <code>link --> subdir/dir/../foo.bar</code> will be recorded as
-  <code>link=subdir/foo.bar</code> and restored as
-  <code>link --> subdir/foo.bar</code></p>
+<p>Record all links in <samp>subdir</samp> and it's descendants in files
+named <samp>dir.links</samp></p>
+<pre>
+&lt;symlink action="record" linkfilename="dir.links"&gt;
+    &lt;fileset dir="${dir.top}" includes="subdir/**"/&gt;
+&lt;/symlink&gt;</pre>
 
+<p>Recreate the links recorded in the previous example:</p>
+<pre>
+&lt;symlink action="recreate"&gt;
+    &lt;fileset dir="${dir.top}" includes="subdir/**/dir.links"/&gt;
+&lt;/symlink&gt;</pre>
 
+<p>Delete a link named <samp>foo</samp>:</p>
+<pre>&lt;symlink action="delete" link="${dir.top}/foo"/&gt;</pre>
+
+<p><strong>Java 1.2 and earlier</strong>: Due to limitations on executing system level commands in
+Java versions earlier than 1.3 this task may have difficulty operating with a relative path
+in <code>ANT_HOME</code>. The typical symptom is an <code>IOException</code> where Apache Ant can't
+find <samp>/some/working/directory${ANT_HOME}/bin/antRun</samp> or something similar. The workaround
+is to change your <code>ANT_HOME</code> environment variable to an absolute path, which will remove
+the <samp>/some/working/directory</samp> portion of the above path and allow Ant to find the correct
+command line execution script.</p>
+
+<p><strong>Note</strong>: <em>Since Ant 1.10.2</em>, this task relies on the symbolic link support
+introduced in Java 7 through the <code class="code">java.nio.file.Files</code> APIs</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/sync.html b/manual/Tasks/sync.html
index 1d34aee..2fefeed 100644
--- a/manual/Tasks/sync.html
+++ b/manual/Tasks/sync.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,153 +15,131 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Sync Task</title>
 </head>
 
 <body>
 
-<h2><a name="get">Sync</a></h2>
+<h2 id="get">Sync</h2>
 <p><em>Since Apache Ant 1.6</em></p>
 <h3>Description</h3>
 
 <p>Synchronize a target directory from the files defined in one or
-more <a href="../Types/resources.html#collection">Resource Collection</a>s.</p>
+more <a href="../Types/resources.html#collection">resource collections</a>.</p>
 
-<p>Any file in the target directory that has not been matched by at
-least one of the nested resource collections gets removed.  I.e. if you exclude a
-file in your sources and a file of that name is present in the target
-dir, it will get removed from the target.</p>
+<p>Any file in the target directory that has not been matched by at least one of the nested resource
+collections gets removed.  I.e. if you exclude a file in your sources and a file of that name is
+present in the target dir, it will get removed from the target.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">the target directory to sync with the resource collections</td>
-    <td align="center" valign="top">Yes</td>
-  </tr>  
-  <tr>
-    <td valign="top">overwrite</td>
-    <td valign="top">Overwrite existing files even if the destination
-      files are newer.</td>
-    <td valign="top" align="center">No; defaults to false.</td>
+    <td>todir</td>
+    <td>the target directory to sync with the resource collections</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">includeEmptyDirs</td>
-     <td valign="top">Copy any empty directories included in the
-       resource collection(s).<br/>
-       <b>Note</b> this attribute also controls the behavior for any
-       nested &lt;preserveintarget&gt; element.  If this attribute is
-       false (the default) empty directories that only exist in the
-       target directory will be removed even if they are matched by
-       the patterns of &lt;preserveintarget&gt;.  This can be
-       overridden by &lt;preserveintarget&gt;'s
-       preserveEmptyDirs attribute.
-     </td>
-     <td valign="top" align="center">No; defaults to false.</td>
+    <td>overwrite</td>
+    <td>Overwrite existing files even if the destination files are newer.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-     <td valign="top">If is set to false, log a warning message, but do not stop the build,
-       when one of the nested filesets points to a directory that
-       doesn't exist.
-     </td>
-     <td valign="top" align="center">No; defaults to true.</td>
+    <td>includeEmptyDirs</td>
+    <td>Copy any empty directories included in the resource
+      collection(s).<br/><strong>Note</strong>: this attribute also controls the behavior for any
+      nested <code>&lt;preserveintarget&gt;</code> element.  If this attribute is <q>false</q> (the
+      default) empty directories that only exist in the target directory will be removed even if
+      they are matched by the patterns of <code>&lt;preserveintarget&gt;</code>.  This can be
+      overridden by <code>&lt;preserveintarget&gt;</code>'s <var>preserveEmptyDirs</var>
+      attribute.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-     <td valign="top">Log the files that are being copied.</td>
-     <td valign="top" align="center">No; defaults to false.</td>
+    <td>failonerror</td>
+    <td>If set to <q>false</q>, log a warning message, but do not stop the build, when one of the
+      nested filesets points to a directory that doesn't exist.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">granularity</td>
-    <td valign="top">The number of milliseconds leeway to give before
-    deciding a file is out of date. This is needed because not every
-    file system supports tracking the last modified time to the
-    millisecond level. Default is 0 milliseconds, or 2 seconds on DOS
-    systems.  This can also be useful if source and target files live
-    on separate machines with clocks being out of sync.  <em>since Ant
-    1.6.2</em>.</td>
-     <td valign="top" align="center">No.</td>
+    <td>verbose</td>
+    <td>Log the files that are being copied.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>granularity</td>
+    <td>The number of milliseconds leeway to give before deciding a file is out of date. This is
+      needed because not every file system supports tracking the last modified time to the
+      millisecond level.  This can also be useful if source and target files live on separate
+      machines with clocks being out of sync.  <em>since Ant 1.6.2</em>.</td>
+    <td>No; default is 0 milliseconds, or 2 seconds on DOS systems.</td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>fileset or any other resource collection</h4>
-<p><a href="../Types/resources.html#collection">Resource
-Collection</a>s are used to select groups of files to copy.</p>
-<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> has been
-supported as a nested element.</p>
+<h4>any resource collection</h4>
+<p><a href="../Types/resources.html#collection">resource collections</a> are used to select groups
+of files to copy.</p>
+<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> has been supported as a nested element.</p>
 
 <h4>preserveInTarget</h4>
 
 <p><em>Since Ant 1.7.0</em></p>
 
-<p>Specifies files or directories that should be kept in the target
-directory even if they are not present in one of the source
-directories.</p>
+<p>Specifies files or directories that should be kept in the target directory even if they are not
+present in one of the source directories.</p>
 
-<p>This nested element is like a <a
-href="../Types/fileset.html">FileSet</a> except that it doesn't
-support the dir attribute and the usedefaultexcludes attribute
-defaults to false.</p>
+<p>This nested element is like a <a href="../Types/fileset.html">FileSet</a> except that it doesn't
+support the <var>dir</var> attribute and the <var>usedefaultexcludes</var> attribute defaults
+to <q>false</q>.</p>
 
-<h5>Additional Parameters</h5>
-<table border="1" cellpadding="2" cellspacing="0">
+<h5>Additional parameters</h5>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">preserveEmptyDirs</td>
-    <td valign="top">Overrules the includeEmptydirs setting for
-      directories matched by this element.  If you want to preserve
-      empty directories that are not in your source directory you can
-      either set the task's includeemptydirs attribute or this one.
-      If the two attribute values conflict, this attribute
-      "wins".</td>
-    <td align="center" valign="top">No, defaults to the value of the
-      task's includeemptydirs attribute</td>
-  </tr>  
+    <td>preserveEmptyDirs</td>
+    <td>Overrules the <var>includeEmptydirs</var> setting for directories matched by this element.
+      If you want to preserve empty directories that are not in your source directory you can either
+      set the task's <var>includeemptydirs</var> attribute or this one.  If the two attribute values
+      conflict, this attribute "wins".</td>
+    <td>No; defaults to the value of the task's <var>includeemptydirs</var> attribute</td>
+  </tr>
 </table>
 
 <h3>Examples</h3>
 
-<blockquote><pre>
+<p>Overwrite all files in <samp>site</samp> with newer files from <samp>generated-site</samp>,
+delete files from <samp>site</samp> that are not present in <samp>generated-site</samp>.</p>
+
+<pre>
 &lt;sync todir=&quot;site&quot;&gt;
   &lt;fileset dir=&quot;generated-site&quot;/&gt;
-&lt;/sync&gt;
-</pre></blockquote>
-<p>overwrites all files in <em>site</em> with newer files from
-<em>generated-site</em>, deletes files from <em>site</em> that are not
-present in <em>generated-site</em>.</p>
+&lt;/sync&gt;</pre>
 
-<blockquote><pre>
+<p>Overwrite all files in <samp>site</samp> with newer files from <samp>generated-site</samp>,
+delete files from <samp>site</samp> that are not present in <samp>generated-site</samp> but keep all
+files in any <samp>CVS</samp> sub-directory.</p>
+
+<pre>
 &lt;sync todir=&quot;site&quot;&gt;
   &lt;fileset dir=&quot;generated-site&quot;/&gt;
   &lt;preserveintarget&gt;
     &lt;include name=&quot;**/CVS/**&quot;/&gt;
   &lt;/preserveintarget&gt;
-&lt;/sync&gt;
-</pre></blockquote>
-<p>overwrites all files in <em>site</em> with newer files from
-<em>generated-site</em>, deletes files from <em>site</em> that are not
-present in <em>generated-site</em> but keeps all files in any
-<em>CVS</em> sub-directory.</p>
-
-
+&lt;/sync&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/tar.html b/manual/Tasks/tar.html
index 4794d63..88d3c3a 100644
--- a/manual/Tasks/tar.html
+++ b/manual/Tasks/tar.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,193 +15,177 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Tar Task</title>
 </head>
 
 <body>
 
-<h2><a name="tar">Tar</a></h2>
+<h2 id="tar">Tar</h2>
 <h3>Description</h3>
 <p>Creates a tar archive.</p>
-<p>The <i>basedir</i> attribute is the reference directory from where to tar.</p>
-<p>This task is a <a href="../dirtasks.html#directorybasedtasks">directory based task</a>
-and, as such, forms an implicit <a href="../Types/fileset.html">Fileset</a>. This
-defines which files, relative to the <i>basedir</i>, will be included in the
-archive. The tar task supports all the attributes of Fileset to refine the
-set of files to be included in the implicit fileset.</p>
+<p>The <var>basedir</var> attribute is the reference directory from where to tar.</p>
+<p>This task is a <a href="../dirtasks.html#directorybasedtasks">directory based task</a> and, as
+such, forms an implicit <a href="../Types/fileset.html">Fileset</a>. This defines which files,
+relative to the <var>basedir</var>, will be included in the archive. The <code>tar</code> task
+supports all the attributes of Fileset to refine the set of files to be included in the implicit
+fileset.</p>
 
-<p>In addition to the implicit fileset, the tar task supports nested
-      resource collections and a special form of filesets. These
-filesets are extended to allow control over the access mode, username and groupname
-to be applied to the tar entries. This is useful, for example, when preparing archives for
-  Unix systems where some files need to have execute permission.  By
-  default this task will use Unix permissions of 644 for files and 755
-  for directories.</p>
+<p>In addition to the implicit fileset, the <code>tar</code> task supports nested resource
+collections and a special form of filesets. These filesets are extended to allow control over the
+access mode, username and groupname to be applied to the tar entries. This is useful, for example,
+when preparing archives for Unix systems where some files need to have execute permission.  By
+default this task will use Unix permissions of 644 for files and 755 for directories.</p>
 
-<p>Early versions of tar did not support path lengths greater than 100
-  characters. Over time several incompatible extensions have been
-  developed until a new POSIX standard was created that added so
-  called PAX extension headers (as the pax utility first introduced
-  them) that among another things addressed file names longer than 100
-  characters.  All modern implementations of tar support PAX extension
-  headers.</p>
+<p>Early versions of <kbd>tar</kbd> utility did not support paths longer than 100 characters. Over
+time several incompatible extensions have been developed until a new POSIX standard was created that
+added so called PAX extension headers (as the <kbd>pax</kbd> utility first introduced them) that
+among another things addressed file names longer than 100 characters.  All modern implementations
+of <kbd>tar</kbd> support PAX extension headers.</p>
 
-<p>Ant's tar support predates the standard with PAX extension headers,
-  it supports different dialects that can be enabled using the
-  <i>longfile</i> attribute.
-If the longfile attribute is set to <code>fail</code>, any long paths will
-cause the tar task to fail.  If the longfile attribute is set to
-<code>truncate</code>, any long paths will be truncated to the 100 character
-maximum length prior to adding to the archive. If the value of the longfile
-attribute is set to <code>omit</code> then files containing long paths will be
-omitted from the archive.  Either option ensures that the archive can be
-untarred by any compliant version of tar.</p>
+<p>Ant's <kbd>tar</kbd> support predates the standard with PAX extension headers, it supports
+different dialects that can be enabled using the <var>longfile</var> attribute.  If
+the <var>longfile</var> attribute is set to <q>fail</q>, any long paths will cause
+the <code>tar</code> task to fail.  If the <var>longfile</var> attribute is set to <q>truncate</q>,
+any long paths will be truncated to the 100 character maximum length prior to adding to the
+archive. If the value of the <var>longfile</var> attribute is set to <q>omit</q> then files
+containing long paths will be omitted from the archive.  Either option ensures that the archive can
+be untarred by any compliant version of <kbd>tar</kbd>.</p>
 
-<p>If the loss of path or file
-information is not acceptable, and it rarely is, longfile may be set to the
-value <code>gnu</code> or <code>posix</code>.  With <code>posix</code>
-  Ant will add PAX extension headers, with <code>gnu</code> it adds
-  GNU tar specific extensions that newer versions of GNU tar call
-  "oldgnu".  GNU tar still creates these extensions by default but
-  supports PAX extension headers as well.  Either choice will produce
-  a tar file which
-can have arbitrary length paths. Note however, that the resulting archive will
-only be able to be untarred with tar tools that support the chosen format.
+<p>If the loss of path or file information is not acceptable, and it rarely is, <var>longfile</var>
+may be set to the value <q>gnu</q> or <q>posix</q>.  With <q>posix</q> Ant will add PAX extension
+headers, with <q>gnu</q> it adds GNU <kbd>tar</kbd> specific extensions that newer versions of
+GNU <kbd>tar</kbd> call <q>oldgnu</q>.  GNU <kbd>tar</kbd> still creates these extensions by default
+but supports PAX extension headers as well.  Either choice will produce a tar file which can have
+arbitrary length paths. Note however, that the resulting archive will only be able to be untarred
+with <kbd>tar</kbd> tools that support the chosen format.</p>
 
-<p>The default for the longfile
-attribute is <code>warn</code> which behaves just like the gnu option except
-that it produces a warning for each file path encountered that does not match
-the limit.  It uses gnu rather than posix for backwards compatibility
-  reasons.</p>
+<p>The default for the <var>longfile</var> attribute is <q>warn</q> which behaves just like
+the <q>gnu</q> option except that it produces a warning for each filepath encountered that does not
+match the limit.  It uses <q>gnu</q> rather than <q>posix</q> for backwards compatibility
+reasons.</p>
 
-<p>To achivieve best interoperability you should use
-  either <code>fail</code> or <code>posix</code> for the longfile attribute.</p>
+<p>To achieve best interoperability you should use either <q>fail</q> or <q>posix</q> for
+the <var>longfile</var> attribute.</p>
 
-<p>This task can perform compression by setting the compression attribute to "gzip"
-or "bzip2".</p>
+<p>This task can perform compression by setting the <var>compression</var> attribute
+to <q>gzip</q>, <q>bzip2</q>, or <q>xz</q>.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top" align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">the tar-file to create.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>destfile</td>
+    <td>the tar file to create.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the directory from which to tar the files.</td>
-    <td align="center" valign="top">No</td>
+    <td>basedir</td>
+    <td>the directory from which to tar the files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">longfile</td>
-    <td valign="top">Determines how long files (&gt;100 chars) are to be
-       handled.  Allowable values are &quot;truncate&quot;, &quot;fail&quot;,
-       &quot;warn&quot;, &quot;omit&quot;, &quot;gnu&quot; and &quot;posix&quot;.  Default is
-       &quot;warn&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>longfile</td>
+    <td>Determines how long filenames (&gt; 100 chars) are to be handled.  Allowed values
+      are <q>truncate</q>, <q>fail</q>, <q>warn</q>, <q>omit</q>, <q>gnu</q> and <q>posix</q>.</td>
+    <td>No; default is <q>warn</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">compression</td>
-    <td valign="top">compression method.  Allowable values are 
-       &quot;none&quot;, &quot;gzip&quot; and &quot;bzip2&quot;.  Default is
-       &quot;none&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>compression</td>
+    <td>compression method.  Allowable values are <q>none</q>, <q>gzip</q>, <q>xz</q>
+      and <q>bzip2</q>.</td>
+    <td>No; default is <q>none</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The character encoding to use for filenames
-    inside the tar file.  For a list of possible values see the <a
-                href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">Supported Encodings</a>.<br/>
-    Defaults to the platform's default character encoding.
-      <em>Since Ant 1.9.5</em>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The character encoding to use for filenames inside the tar file.  For a list of possible
+      values see
+      the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+      target="_top">Supported Encodings</a>.<br/><em>Since Ant 1.9.5</em>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
 </table>
 
-<h3>Nested Elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
-The tar task supports nested <a
-href="../Types/tarfileset.html">tarfileset</a> elements. These are
-extended <a href="../Types/fileset.html">FileSets</a> which,
-in addition to the standard elements, support one additional
-attributes
+<p>The task supports nested <a href="../Types/tarfileset.html">tarfileset</a> elements. These
+are extended <a href="../Types/fileset.html">FileSets</a> which, in addition to the standard
+elements, support one additional attributes</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top" align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">preserveLeadingSlashes</td>
-    <td valign="top">Indicates whether leading `/'s should
-    be preserved in the file names. Default is <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>preserveLeadingSlashes</td>
+    <td>Indicates whether leading <q>/</q> should be preserved in the file names.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
 <h4>any other resource collection</h4>
-<p><a href="../Types/resources.html#collection">Resource
-Collection</a>s are used to select groups of files to archive.</p>
-<p>Prior to Apache Ant 1.7 only <code>&lt;fileset&gt;</code> has been
-supported as a nested element.</p>
+<p><a href="../Types/resources.html#collection">resource collections</a> are used to select groups
+of files to archive.</p>
+<p>Prior to Apache Ant 1.7 only <code>&lt;fileset&gt;</code> has been supported as a nested
+element.</p>
 
 <h3>Examples</h3>
+
+<p>Tar all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.tar</samp> in the <samp>${dist}</samp> directory, then apply
+the <code>gzip</code> task to compress it.</p>
+
 <pre>
 &lt;tar destfile=&quot;${dist}/manual.tar&quot; basedir=&quot;htdocs/manual&quot;/&gt;
 &lt;gzip destfile=&quot;${dist}/manual.tar.gz&quot; src=&quot;${dist}/manual.tar&quot;/&gt;</pre>
-<p>tars all files in the <code>htdocs/manual</code> directory into a file called <code>manual.tar</code>
-in the <code>${dist}</code>  directory, then applies the gzip task to compress
-it.</p>
+
+<p>Tar all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.tar</samp> in the <samp>${dist}</samp> directory. Files in the
+directory <samp>mydocs</samp>, or files with the name <samp>todo.html</samp> are excluded.</p>
 
 <pre>
 &lt;tar destfile=&quot;${dist}/manual.tar&quot;
      basedir=&quot;htdocs/manual&quot;
-     excludes=&quot;mydocs/**, **/todo.html&quot;
-/&gt;</pre>
-<p>tars all files in the <code>htdocs/manual</code> directory into a file called <code>manual.tar</code>
-in the <code>${dist}</code> directory. Files in the directory <code>mydocs</code>,
-or files with the name <code>todo.html</code> are excluded.</p>
+     excludes=&quot;mydocs/**, **/todo.html&quot;/&gt;</pre>
+
+<p>Write the file <samp>docs/readme.txt</samp> as <samp>/usr/doc/ant/README</samp> into the
+archive. All <samp>*.html</samp> files in the <samp>docs</samp> directory are prefixed
+by <samp>/usr/doc/ant</samp>, so for example <samp>docs/index.html</samp> is written
+as <samp>/usr/doc/ant/index.html</samp> to the archive.</p>
 
 <pre>
 &lt;tar destfile=&quot;${basedir}/docs.tar&quot;&gt;
@@ -215,14 +200,11 @@
     &lt;include name=&quot;*.html&quot;/&gt;
   &lt;/tarfileset&gt;
 &lt;/tar&gt;</pre>
-<p>
-  Writes the file <code>docs/readme.txt</code> as
-  <code>/usr/doc/ant/README</code> into the archive. All
-  <code>*.html</code> files in the <code>docs</code> directory are
-  prefixed by <code>/usr/doc/ant</code>, so for example
-  <code>docs/index.html</code> is written as
-  <code>/usr/doc/ant/index.html</code> to the archive.
-</p>
+
+<p>Build a tar which uses the GNU extensions for long paths where some files need to be marked as
+executable (mode 755) and the rest use the default mode (read-write by owner). The first fileset
+selects just the executable files. The second fileset must exclude the executable files and include
+all others.</p>
 
 <pre>
 &lt;tar longfile=&quot;gnu&quot;
@@ -236,46 +218,30 @@
     &lt;exclude name=&quot;${dist.name}/bootstrap.sh&quot;/&gt;
     &lt;exclude name=&quot;${dist.name}/build.sh&quot;/&gt;
   &lt;/tarfileset&gt;
-&lt;/tar&gt;
-</pre>
-<p>This example shows building a tar which uses the GNU extensions for long paths and
-where some files need to be marked as executable (mode 755)
-and the rest are use the default mode (read-write by owner). The first
-fileset selects just the executable files. The second fileset must exclude
-the executable files and include all others. </p>
+&lt;/tar&gt;</pre>
 
+<p><strong>Note</strong>: The <code>tar</code> task does not ensure that a file is only selected by
+one resource collection. If the same file is selected by more than one collection, it will be
+included in the tar file twice, with the same path.</p>
 
+<p><strong>Note</strong>: The patterns in the <code>include</code> and <code>exclude</code> elements
+are considered to be relative to the corresponding <var>dir</var> attribute as with all other
+filesets.  In the example above, <samp>${dist.name}</samp> is not an absolute path, but a simple
+name of a directory, so <samp>${dist.name}</samp> is a valid path relative
+to <samp>${dist.name}/..</samp>.</p>
 
-<p><strong>Note: </strong> The tar task does not ensure that a file is only selected
-by one resource collection. If the same file is selected by more than one collection, it will be included in the
-tar file twice, with the same path.</p>
-
-<p><strong>Note:</strong> The patterns in the include and exclude
-elements are considered to be relative to the corresponding dir
-attribute as with all other filesets.  In the example above,
-<code>${dist.name}</code> is not an absolute path, but a simple name
-of a directory, so <code>${dist.name}</code> is a valid path relative
-to <code>${dist.name}/..</code>.</p>
-
+<p>Re-package a ZIP archive as a GZip compressed tar archive.  If Unix file permissions have been
+stored as part of the ZIP file, they will be retained in the resulting tar archive.</p>
 
 <pre>
 &lt;tar destfile="release.tar.gz" compression="gzip"&gt;
   &lt;zipfileset src="release.zip"/&gt;
-&lt;/tar&gt;
-</pre>
-<p>Re-packages a ZIP archive as a GZip compressed tar archive.  If
-Unix file permissions have been stored as part of the ZIP file, they
-will be retained in the resulting tar archive.</p>
+&lt;/tar&gt;</pre>
 
-
-<p><strong>Note:</strong>
-  Please note the tar task creates a tar file, it does not append 
-  to an existing tar file. The existing tar file is replaced instead.
-  As with most tasks in Ant, the task only takes action if the output
-  file (the tar file in this case) is older than the input files, or
-  if the output file does not exist.
-</p>
+<p><strong>Note</strong>: Please note the <code>tar</code> task creates a tar file, it does not
+append to an existing tar file. The existing tar file is replaced instead.  As with most tasks in
+Ant, the task only takes action if the output file (the tar file in this case) is older than the
+input files, or if the output file does not exist.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/taskdef.html b/manual/Tasks/taskdef.html
index 4f6f5d2..fd2fa0b 100644
--- a/manual/Tasks/taskdef.html
+++ b/manual/Tasks/taskdef.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,31 +15,31 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>TaskDef Task</title>
 </head>
 
 <body>
 
-<h2><a name="taskdef">Taskdef</a></h2>
-<h3>Description</h3>
-  <p>Adds a task definition to the current project, such that this new task can be
-    used in the current project.</p>
-  <p>This task is a form of <a href="typedef.html">Typedef</a> with the
-    attributes "adapter" and "adaptto" set to the values 
-    "org.apache.tools.ant.TaskAdapter" and "org.apache.tools.ant.Task"
-    respectively.  Anything said in the <a href="typedef.html">manual
-      page of typedef</a> applies to taskdef as well.</p>
-<h3>Examples</h3>
-<pre>  &lt;taskdef name=&quot;myjavadoc&quot; classname=&quot;com.mydomain.JavadocTask&quot;/&gt;</pre>
-<p>makes a task called <code>myjavadoc</code> available to Apache Ant. The class <code>com.mydomain.JavadocTask</code>
-implements the task.</p>
+<h2 id="taskdef">Taskdef</h2>
 
+<h3>Description</h3>
+<p>Adds a task definition to the current project, such that this new task can be used in the current
+project.</p>
+<p>This task is a form of <a href="typedef.html">Typedef</a> with the attributes <var>adapter</var>
+and <var>adaptto</var> set to the values <q>org.apache.tools.ant.TaskAdapter</q>
+and <q>org.apache.tools.ant.Task</q> respectively. Anything said in
+the <a href="typedef.html">manual page of typedef</a> applies to <code>taskdef</code> as well.</p>
+
+<h3>Examples</h3>
+
+<p>Make a task called <code>myjavadoc</code> available to Apache Ant. The
+class <code>com.mydomain.JavadocTask</code> implements the task.</p>
+
+<pre>&lt;taskdef name=&quot;myjavadoc&quot; classname=&quot;com.mydomain.JavadocTask&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/telnet.html b/manual/Tasks/telnet.html
index 0ac65b3..cc4eb88 100644
--- a/manual/Tasks/telnet.html
+++ b/manual/Tasks/telnet.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,103 +15,95 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Telnet Task</title>
 </head>
 
 <body>
 
-<h2><a name="telnet">Telnet</a></h2>
+<h2 id="telnet">Telnet</h2>
 <h3>Description</h3>
-Task to automate a remote telnet session. The task uses 
-nested <tt>&lt;read&gt;</tt> to indicate strings to wait for, and
-<tt>&lt;write&gt;</tt> tags to specify text to send.  
+<p>Task to automate a remote telnet session. The task uses nested <code>&lt;read&gt;</code> to
+indicate strings to wait for, and <code>&lt;write&gt;</code> tags to specify text to send.</p>
 
-<p>If you do specify a userid and password, the system will 
-assume a common unix prompt to wait on. This behavior can be easily over-ridden.</p>
-<p><b>Note:</b> This task depends on external libraries not included in the Apache Ant distribution.
-See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information.</p>
+<p>If you do specify a userid and password, the system will assume a common Unix prompt to wait
+on. This behavior can be easily overridden.</p>
+<p><strong>Note</strong>: This task depends on external libraries not included in the Apache Ant
+distribution.  See <a href="../install.html#librarydependencies">Library Dependencies</a> for more
+information.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-     <td>userid</td>
-     <td>the login id to use on the telnet server.</td>
-     <td>Only if password is specified</td>
+    <td>userid</td>
+    <td>the login id to use on the telnet server.</td>
+    <td>Only if <var>password</var> is specified</td>
   </tr>
   <tr>
-     <td>password</td>
-     <td>the login password to use on the telnet server.</td>
-     <td>Only if userid is specified</td>
+    <td>password</td>
+    <td>the login password to use on the telnet server.</td>
+    <td>Only if <var>userid</var> is specified</td>
   </tr>
   <tr>
-     <td>server</td>
-     <td>the address of the remote telnet server.</td>
-     <td>Yes</td>
+    <td>server</td>
+    <td>the address of the remote telnet server.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-     <td>port</td>
-     <td>the port number of the remote telnet server. Defaults to port 23.</td>
-     <td>No</td>
+    <td>port</td>
+    <td>the port number of the remote telnet server.</td>
+    <td>No; defaults to <q>23</q></td>
   </tr>
   <tr>
-     <td>initialCR</td>
-     <td>send a cr after connecting (&quot;yes&quot;). Defaults to &quot;no&quot;.</td>
-     <td>No</td>
+    <td>initialCR</td>
+    <td>send a cr after connecting if <q>yes</q>.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
   <tr>
-     <td>timeout</td>
-     <td>set a default timeout to wait for a response. Specified in seconds. Default is no timeout.</td>
-     <td>No</td>
+    <td>timeout</td>
+    <td>set a default timeout to wait for a response. Specified in seconds.</td>
+    <td>No; default is no timeout</td>
   </tr>
 </table>
-<h3><a name="nested">Nested Elements</a></h3>
-The commands to send to the server, and responses to wait for, are
-described as nested elements.  
+<h3 id="nested">Parameters specified as nested elements</h3>
+<p>The commands to send to the server, and responses to wait for, are described as nested
+elements.</p>
 
 <h4>read</h4>
 
-<p>declare (as a text child of this element) a string to wait for.
-The element supports the timeout attribute, which overrides any
-timeout specified for the task as a whole. It also has a <tt>string</tt>
-attribute, which is an alternative to specifying the string as 
-a text element.
-</p>
-<i>Always declare an opening and closing
-<code>&lt;read&gt;</code> element to ensure that statements are not sent before
-the connection is ready, and that the connection is not broken before
-the final command has completed.
-</i>
+<p>declare (as a text child of this element) a string to wait for.  The element supports
+the <var>timeout</var> attribute, which overrides any timeout specified for the task as a whole. It
+also has a <var>string</var> attribute, which is an alternative to specifying the string as a text
+element.</p>
+<p><em>Always declare an opening and closing <code>&lt;read&gt;</code> element to ensure that
+statements are not sent before the connection is ready, and that the connection is not broken before
+the final command has completed.</em></p>
+
 <h4>write</h4>
+<p>describes the text to send to the server. The <var>echo</var> boolean attribute controls whether
+the string is echoed to the local log; this is <q>true</q> by default.</p>
 
-<p>describes the text to send to the server. The <tt>echo</tt> boolean
-attribute controls whether the string is echoed to the local log; 
-this is "true" by default
-</p>
 <h3>Examples</h3>
-A simple example of connecting to a server and running a command.  This assumes
- a prompt of &quot;ogin:&quot; for the userid, and a prompt of &quot;assword:&quot;
- for the password.
+<p>A simple example of connecting to a server and running a command.  This assumes a prompt
+of <q>ogin:</q> for the userid, and a prompt of <q>assword:</q> for the password.</p>
 
-<blockquote><pre>
+<pre>
 &lt;telnet userid=&quot;bob&quot; password=&quot;badpass&quot; server=&quot;localhost&quot;&gt;
    &lt;read&gt;/home/bob&lt;/read&gt;
    &lt;write&gt;ls&lt;/write&gt;
    &lt;read string=&quot;/home/bob&quot;/&gt;
-&lt;/telnet&gt;
-</pre></blockquote>
+&lt;/telnet&gt;</pre>
 
-This task can be rewritten as:
-<blockquote><pre>
+<p>This task can be rewritten as:</p>
+<pre>
 &lt;telnet server=&quot;localhost&quot;&gt;
    &lt;read&gt;ogin:&lt;/read&gt;
    &lt;write&gt;bob&lt;/write&gt;
@@ -119,37 +112,32 @@
    &lt;read&gt;/home/bob&lt;/read&gt;
    &lt;write&gt;ls&lt;/write&gt;
    &lt;read&gt;/home/bob&lt;/read&gt;
-&lt;/telnet&gt;
-</pre></blockquote>
+&lt;/telnet&gt;</pre>
 
-A timeout can be specified at the <code>&lt;telnet&gt;</code> level or at the <code>&lt;read&gt;</code> level. 
-This will connect, issue a sleep command that is suppressed from displaying and wait 
-10 seconds before quitting.
-<blockquote><pre>
+<p>A timeout can be specified at the <code>&lt;telnet&gt;</code> level or at
+the <code>&lt;read&gt;</code> level.  This will connect, issue a <kbd>sleep</kbd> command that is
+suppressed from displaying and wait 10 seconds before quitting.</p>
+
+<pre>
 &lt;telnet userid=&quot;bob&quot; password=&quot;badpass&quot; server=&quot;localhost&quot; timeout=&quot;20&quot;&gt;
    &lt;read&gt;/home/bob&lt;/read&gt;
    &lt;write echo=&quot;false&quot;&gt;sleep 15&lt;/write&gt;
    &lt;read timeout=&quot;10&quot;&gt;/home/bob&lt;/read&gt;
-&lt;/telnet&gt;
-</pre></blockquote>
+&lt;/telnet&gt;</pre>
 
-The task can be used with other ports as well:
-<blockquote><pre>
+<p>The task can be used with other ports as well:</p>
+<pre>
 &lt;telnet port=&quot;80&quot; server=&quot;localhost&quot; timeout=&quot;20&quot;&gt;
    &lt;read/&gt;
    &lt;write&gt;GET / http/0.9&lt;/write&gt;
    &lt;write/&gt;
    &lt;read timeout=&quot;10&quot;&gt;&amp;lt;/HTML&amp;gt;&lt;/read&gt;
-&lt;/telnet&gt;
-</pre></blockquote>
-<p>
-To use this task against the WinNT telnet service, you need to configure the service to use 
-classic authentication rather than NTLM negotiated authentication. 
-This can be done in the Telnet Server Admin app: 
-select "display/change registry settings", then "NTLM", then set the value of NTLM to 1.
-</p>
+&lt;/telnet&gt;</pre>
 
+<p>To use this task against the Windows NT telnet service, you need to configure the service to use
+classic authentication rather than NTLM negotiated authentication.  This can be done in the Telnet
+Server Admin app: select <q>display/change registry settings</q>, then <q>NTLM</q>, then set the
+value of NTLM to 1.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/tempfile.html b/manual/Tasks/tempfile.html
index 1be00d0..772d54f 100644
--- a/manual/Tasks/tempfile.html
+++ b/manual/Tasks/tempfile.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,216 +15,74 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-    
-<html>
+
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
+  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
   <title>Tempfile Task</title>
 </head>
 
-<body bgcolor="#ffffff" text="#000000" link="#525D76"
-      alink="#525D76" vlink="#525D76">
-
-<table border="0" width="100%" cellspacing="4">
-
-  <!-- PAGE HEADER -->
+<body>
+<h2>Tempfile Task</h2>
+<h3 id="description">Description</h3>
+<p>This task sets a property to the name of a temporary file.
+Unlike <code class="code">java.io.File.createTempFile</code>, this task does not actually create the
+temporary file, but it does guarantee that the file did not exist when the task was executed.</p>
+<h3 id="attributes">Parameters</h3>
+<table class="attr">
   <tr>
-    <td>
-      <table border="0" width="100%"><tr>
-          <td valign="bottom">
-            <font size="+3" face="arial,helvetica,sanserif"><strong>Tempfile  Task</strong></font>
-            <br><font face="arial,helvetica,sanserif">This task sets a property to the name of a temporary file.</font>
-          </td>
-          <td>
-            <!-- PROJECT LOGO -->
-            <a href="http://ant.apache.org/">
-              <img src="../images/ant_logo_large.gif" align="right" alt="Apache Ant" border="0">
-            </a>
-          </td>
-      </tr></table>
-    </td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Type</th>
+    <th scope="col">Required</th>
   </tr>
-
-  <!-- START RIGHT SIDE MAIN BODY -->
   <tr>
-    <td  valign="top" align="left">
-
-          <!-- Applying task/long-description -->
-    <!-- Start Description -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="description">
-          <strong>Description</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-
-          This task sets a property to the name of a temporary file.
-          Unlike <code>java.io.File.createTempFile</code>,
-          this task does not actually create the temporary file, but it does guarantee that the
-          file did not exist when the task was executed.
-
-          <p>Examples:
-
-          <pre>&lt;tempfile property="temp.file"/&gt;</pre>
-
-          create a temporary file
-
-          <pre>&lt;tempfile property="temp.file" suffix=".xml"/&gt;</pre>
-
-          create a temporary file with the <code>.xml</code> suffix
-
-          <pre>&lt;tempfile property="temp.file" destDir="build"/&gt;</pre>
-
-          create a temporary file in the <code>build</code> subdirectory
-
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Description -->
-
- <!-- Ignore -->
-
-
-
-    <!-- Start Attributes -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="attributes">
-          <strong>Parameters</strong></a></font>
-      </td></tr>
-      <tr><td><blockquote>
-        <table>
-          <tr>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Attribute</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Description</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Type</b></font>
-        </td>
-        <td bgcolor="#cccccc" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif"><b>Requirement</b></font>
-        </td>
-          </tr>
-    <!-- Attribute Group -->    
-        <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">property</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Sets the property you wish to assign the temporary file to.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left" rowspan="1">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Required</font>
-        </td>
-    </tr>
-
-    <!-- Attribute Group -->    
-        <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">destdir</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Sets the destination directory. If not set, the basedir directory is used instead.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">File</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left" rowspan="5">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Optional</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">prefix</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Sets the optional prefix string for the temp file.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">suffix</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Sets the optional suffix string for the temp file.</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">String</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">deleteonexit</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Whether the temp file will be marked for deletion on normal exit of the Java Virtual Machine (even though the file may never be created); default <em>false</em>. <strong>Since Apache Ant 1.7</strong></font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-    </tr>
-    <!-- Attribute -->
-    <tr>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">createfile</font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">Whether the temp file should be created by this task; default <em>false</em>.<strong>Since Ant 1.8</strong></font>
-        </td>
-        <td bgcolor="#eeeeee" valign="top" align="left">
-          <font color="#000000" size="-1" face="arial,helvetica,sanserif">boolean</font>
-        </td>
-    </tr>
-
-        </table>
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Attributes -->
-
-    <!-- Start Elements -->
-    <table border="0" cellspacing="0" cellpadding="2" width="100%">
-      <tr><td>&nbsp;</td></tr>
-
-      <tr><td bgcolor="#525D76">
-        <font color="#ffffff" face="arial,helvetica.sanserif">
-          <a name="elements">
-          <strong>Parameters as nested elements</strong></a></font>
-      </td></tr>
-
-      <tr><td><blockquote>
-
-      </blockquote></td></tr>
-
-    </table>
-    <!-- End Elements -->
-
-
-    </td>
+    <td>property</td>
+    <td>Sets the property you wish to assign the temporary file to.</td>
+    <td>String</td>
+    <td>Yes</td>
   </tr>
-  <!-- END RIGHT SIDE MAIN BODY -->
-
+  <tr>
+    <td>destdir</td>
+    <td>Sets the destination directory.</td>
+    <td>File</td>
+    <td>No; defaults to <var>basedir</var></td>
+  </tr>
+  <tr>
+    <td>prefix</td>
+    <td>Sets the optional prefix string for the temp file.</td>
+    <td>String</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>suffix</td>
+    <td>Sets the optional suffix string for the temp file.</td>
+    <td>String</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>deleteonexit</td>
+    <td>Whether the temp file will be marked for deletion on normal exit of JVM (even though the
+      file may never be created). <em>Since Apache Ant 1.7</em></td>
+    <td>boolean</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>createfile</td>
+    <td>Whether the temp file should be created by this task. <em>Since Ant 1.8</em></td>
+    <td>boolean</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
 </table>
 
+<h3>Examples</h3>
+<p>Create a temporary file</p>
+<pre>&lt;tempfile property="temp.file"/&gt;</pre>
+
+<p>Create a temporary file with the <code>.xml</code> suffix</p>
+<pre>&lt;tempfile property="temp.file" suffix=".xml"/&gt;</pre>
+
+<p>Create a temporary file in the <code>build</code> subdirectory</p>
+<pre>&lt;tempfile property="temp.file" destDir="build"/&gt;</pre>
 </body>
 </html>
diff --git a/manual/Tasks/touch.html b/manual/Tasks/touch.html
index 8adee38..f798761 100644
--- a/manual/Tasks/touch.html
+++ b/manual/Tasks/touch.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,146 +15,133 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Touch Task</title>
 </head>
 
 <body>
 
-<h2><a name="touch">Touch</a></h2>
+<h2 id="touch">Touch</h2>
 <h3>Description</h3>
 
-<p>Changes the modification time of a resource and possibly creates it
-at the same time. In addition to working with a single file, this Task
-can also work on <a href="../Types/resources.html">resources</a> and
-resource collections (which also includes directories).  Prior to Apache Ant
-1.7 only FileSet or <a href="../Types/filelist.html">Filelist</a>
-(since Ant 1.6) have been supported.</p>
+<p>Changes the modification time of a resource and possibly creates it at the same time. In addition
+to working with a single file, this Task can also work
+on <a href="../Types/resources.html">resources</a> and resource collections (which also includes
+directories).  Prior to Apache Ant 1.7 only FileSet or <a href="../Types/filelist.html">Filelist</a>
+(<em>since Ant 1.6</em>) were supported.</p>
 
-<p>Ant uses the API of <code>java.io.File</code> to set the last
-  modification time which has some limitations.  For example the
-  timestamp granularity depends on the operating system and sometimes
-  the operating system may allow a granularity smaller than
-  milliseconds.  If you need more control you have to fall back to
-  the <code>&lt;exec&gt;</code> task and native commands.</p>
+<p>Ant uses the API of <code class="code">java.io.File</code> to set the last modification time
+which has some limitations.  For example, the timestamp granularity depends on the operating system
+and sometimes the operating system may allow a granularity smaller than milliseconds.  If you need
+more control you have to fall back to the <code>&lt;exec&gt;</code> task and native commands.</p>
 
-<p>Starting with Ant 1.8.2 Ant will log a warning message if it fails
-  to change the file modification time.  This will happen if you try
-  to change the modification time of a file you do not own on many
-  Unix systems, for example.</p>
+<p><em>Since Ant 1.8.2</em>, a warning message is logged upon failure to change the file
+modification time.  This will happen if you try to change the modification time of a file you do not
+own on many Unix systems, for example.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The name of the file.</td>
-    <td valign="top" align="center">Unless a nested resource collection element
-       has been specified.</td>
+    <td>file</td>
+    <td>The name of the file.</td>
+    <td>Unless a nested resource collection element has been specified</td>
   </tr>
   <tr>
-    <td valign="top">millis</td>
-    <td valign="top">Specifies the new modification time of the file
-       in milliseconds since midnight Jan 1 1970.</td>
-    <td valign="center" align="center" rowspan="2">No--datetime takes
-       precedence, however if both are omitted the current time is assumed.</td>
+    <td>millis</td>
+    <td>Specifies the new modification time of the file in milliseconds since midnight Jan 1
+      1970.</td>
+    <td rowspan="2">No; <var>datetime</var> takes precedence, however if both are omitted then
+      current time is assumed</td>
   </tr>
   <tr>
-    <td valign="top">datetime</td>
-    <td valign="top">Specifies the new modification time of the file. The 
-       special value &quot;now&quot; indicates the current time 
-       (now supported since Ant 1.8).</td>
+    <td>datetime</td>
+    <td class="left">Specifies the new modification time of the file.  <em>Since Ant 1.8</em>, the
+      special value <q>now</q> indicates the current time.</td>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">SimpleDateFormat-compatible pattern string using
-       the current locale.
-       Defaults to "MM/dd/YYYY hh:mm a" or "MM/dd/yyyy hh:mm:ss a"
-       using the US locale.
-       <b>Since Ant 1.6.3</b></td>
-    <td valign="top" align="center">No</td>
+    <td>pattern</td>
+    <td>SimpleDateFormat-compatible pattern string using the current locale. <em>Since Ant
+      1.6.3</em></td>
+    <td>No; defaults to <q>MM/dd/YYYY hh:mm a</q> or <q>MM/dd/yyyy hh:mm:ss a</q> using the US
+      locale.</td>
   </tr>
   <tr>
-    <td valign="top">mkdirs</td>
-    <td valign="top">Whether to create nonexistent parent
-       directories when touching new files. <b>Since Ant 1.6.3</b></td>
-    <td valign="top" align="center">No, default <i>false</i>.</td>
+    <td>mkdirs</td>
+    <td>Whether to create nonexistent parent directories when touching new files. <em>Since Ant
+      1.6.3</em></td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">Whether to log the creation of new files.
-       <b>Since Ant 1.6.3</b></td>
-    <td valign="top" align="center">No, default <i>true</i>.</td>
+    <td>verbose</td>
+    <td>Whether to log the creation of new files.  <em>Since Ant 1.6.3</em></td>
+    <td>No; default <q>true</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>any resource collection</h4>
 
-<p>You can use any number of nested resource collection elements to
-define the resources for this task and refer to resources defined
-elsewhere.  <b>Note:</b> resources passed to this task must implement
-the <code>org.apache.tools.ant.types.resources.Touchable</code>
-interface, this is true for all filesystem-based resources like those
-returned by path, fileset ot filelist.</p>
+<p>You can use any number of nested resource collection elements to define the resources for this
+task and refer to resources defined elsewhere. <strong>Note</strong>: resources passed to this task
+must implement the <code class="code">org.apache.tools.ant.types.resources.Touchable</code>
+interface, this is true for all filesystem-based resources like those returned by path, fileset ot
+filelist.</p>
 
-<p>For backwards compatibility directories matched by nested filesets
-will be "touched" as well, use a &lt;type&gt; selector to suppress
-this.  This only applies to filesets nested into the task directly,
-not to filesets nested into a path or any other resource
-collection.</p>
+<p>For backwards compatibility directories matched by nested filesets will be "touched" as well, use
+a <var>type</var> selector to suppress this.  This only applies to filesets nested into the task
+directly, not to filesets nested into a path or any other resource collection.</p>
 
 <h4>mapper</h4>
-<p><em>Since Ant 1.6.3,</em> a nested <a href="../Types/mapper.html">
-    mapper</a> can be specified.  Files specified via nested
-    <code>fileset</code>s, <code>filelist</code>s, or the <code>file</code>
-    attribute are mapped using the specified mapper.  For each file mapped,
-    the resulting files are touched. If no time has been specified and
-    the original file exists its timestamp will be used.
-    If no time has been specified and the original file does not exist the 
-    current time is used. Since Ant 1.8 the task settings (<code>millis</code>,
-    and <code>datetime</code>) have priority over the timestamp of the original
-    file.</p>
+<p><em>Since Ant 1.6.3</em>, a nested <a href="../Types/mapper.html">mapper</a> can be specified.
+Files specified via nested <code>fileset</code>s, <code>filelist</code>s, or the <code>file</code>
+attribute are mapped using the specified mapper.  For each file mapped, the resulting files are
+touched. If no time has been specified and the original file exists its timestamp will be used.  If
+no time has been specified and the original file does not exist the current time is used. <em>Since
+Ant 1.8</em>, the task settings (<var>millis</var> and <var>datetime</var>) have priority over the
+timestamp of the original file.</p>
 <h3>Examples</h3>
-<pre>  &lt;touch file=&quot;myfile&quot;/&gt;</pre>
-<p>creates <code>myfile</code> if it doesn't exist and changes the
-modification time to the current time.</p>
-<pre>  &lt;touch file=&quot;myfile&quot; datetime=&quot;06/28/2000 2:02 pm&quot;/&gt;</pre>
-<p>creates <code>myfile</code> if it doesn't exist and changes the
-modification time to Jun, 28 2000 2:02 pm (14:02 for those used to 24
-hour times).</p>
-<pre>  &lt;touch datetime=&quot;09/10/1974 4:30 pm&quot;&gt;
+
+<p>Create <samp>myfile</samp> if it doesn't exist and change the modification time to the current
+time.</p>
+<pre>&lt;touch file=&quot;myfile&quot;/&gt;</pre>
+
+<p>Create <samp>myfile</samp> if it doesn't exist and change the modification time to Jun, 28 2000
+2:02 pm (14:02 for those used to 24 hour time).</p>
+<pre>&lt;touch file=&quot;myfile&quot; datetime=&quot;06/28/2000 2:02 pm&quot;/&gt;</pre>
+
+<p>Change the modification time to Oct, 09 1974 4:30 pm of all files and directories found
+in <samp>src_dir</samp>.</p>
+<pre>
+&lt;touch datetime=&quot;09/10/1974 4:30 pm&quot;&gt;
     &lt;fileset dir=&quot;src_dir&quot;/&gt;
-  &lt;/touch&gt;</pre>
-<p>changes the modification time to Oct, 09 1974 4:30 pm of all files and directories 
-  found in <code>src_dir</code>. </p>
-<pre>  &lt;touch file=&quot;myfile&quot; datetime=&quot;06/28/2000 2:02:17 pm&quot;/&gt;</pre>
-<p>creates <code>myfile</code> if it doesn't exist and changes the
-modification time to Jun, 28 2000 2:02:17 pm (14:02:17 for those used to 24
-hour times), if the filesystem allows a precision of one second - a
-time close to it otherwise.</p>
-<pre>  &lt;touch file=&quot;foo&quot;&gt;
-    &lt;mapper type=&quot;glob&quot; from=&quot;foo&quot; to=&quot;bar&quot; /&gt;
-  &lt;/touch&gt;
-</pre>
-<p>creates <code>bar</code> if it doesn't exist and changes the
-modification time to that of <code>foo</code>.</p>
+&lt;/touch&gt;</pre>
 
-<pre>  &lt;touch file=&quot;foo&quot; datetime=&quot;now&quot;&gt;
-    &lt;mapper type=&quot;regexp&quot; from=&quot;^src(.*)\.java&quot; to=&quot;shadow\1.empty&quot; /&gt;
-  &lt;/touch&gt;
-</pre>
-<p>creates files in the <code>shadow</code> directory for every java file in the
-   <code>src</code> directory if it doesn't exist and changes the modification
-   time of those files to the current time.</p>
+<p>Create <samp>myfile</samp> if it doesn't exist and change the modification time to Jun, 28 2000
+2:02:17 pm (14:02:17 for those used to 24 hour time), if the filesystem allows a precision of one
+second&mdash;a time close to it otherwise.</p>
+<pre>&lt;touch file=&quot;myfile&quot; datetime=&quot;06/28/2000 2:02:17 pm&quot;/&gt;</pre>
 
+<p>Create <samp>bar</samp> if it doesn't exist and change the modification time to that
+of <samp>foo</samp>.</p>
+<pre>
+&lt;touch file=&quot;foo&quot;&gt;
+    &lt;mapper type=&quot;glob&quot; from=&quot;foo&quot; to=&quot;bar&quot;/&gt;
+&lt;/touch&gt;</pre>
+
+<p>Create files in the <samp>shadow</samp> directory for every <samp>.java</samp> file in
+the <samp>src</samp> directory if it doesn't exist and change the modification time of those files
+to the current time.</p>
+<pre>
+&lt;touch file=&quot;foo&quot; datetime=&quot;now&quot;&gt;
+    &lt;mapper type=&quot;regexp&quot; from=&quot;^src(.*)\.java&quot; to=&quot;shadow\1.empty&quot;/&gt;
+&lt;/touch&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/translate.html b/manual/Tasks/translate.html
index 10e812a..0be22ba 100644
--- a/manual/Tasks/translate.html
+++ b/manual/Tasks/translate.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,37 +15,28 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Translate Task</title>
 </head>
 
 <body>
 
-<h2><a name="translate">Translate</a></h2>
+<h2 id="translate">Translate</h2>
 <h3>Description</h3>
-<p>Identifies keys in files delimited by special tokens
-and translates them with values read from resource bundles.
-</p>
-<p>
-A resource bundle contains locale-specific key-value pairs.
-A resource bundle is a hierarchical set of property files.
-A bundle name makes up its base family name.  Each file that
-makes up this bundle has this name plus its locale.  For example,
-if the resource bundle name is MyResources, the file that contains
-German text will take the name MyResources_de.  In addition to
-language, country and variant are also used to form the files in
-the bundle.
-</p>
-<p>
-The resource bundle lookup searches for resource files with various
-suffixes on the basis of (1) the desired locale and (2) the default
-locale (basebundlename), in the following order from lower-level
-(more specific) to parent-level (less specific):
-</p>
+<p>Identifies keys in files delimited by special tokens and translates them with values read from
+resource bundles.</p>
+<p>A resource bundle contains locale-specific key-value pairs.  A resource bundle is a hierarchical
+set of property files.  A bundle name makes up its base family name.  Each file that makes up this
+bundle has this name plus its locale.  For example, if the resource bundle name
+is <samp>MyResources</samp>, the file that contains German text will take the
+name <samp>MyResources_de</samp>.  In addition to language, country and variant are also used to
+form the files in the bundle.</p>
+<p>The resource bundle lookup searches for resource files with various suffixes on the basis of (1)
+the desired locale and (2) the default locale (basebundlename), in the following order from
+lower-level (more specific) to parent-level (less specific):</p>
 <pre>
 basebundlename + &quot;_&quot; + language1 + &quot;_&quot; + country1 + &quot;_&quot; + variant1
 basebundlename + &quot;_&quot; + language1 + &quot;_&quot; + country1
@@ -54,129 +46,103 @@
 basebundlename + &quot;_&quot; + language2 + &quot;_&quot; + country2
 basebundlename + &quot;_&quot; + language2
 </pre>
-<p>
-The file names generated thus are appended with the string &quot;.properties&quot;
-to make up the file names that are to be used.
-</p>
-<p>
-File encoding is supported.  The encoding scheme of the source files,
-destination files and the bundle files can be specified.
-
-Destination files can be explicitly overwritten using the
-<var>forceoverwrite</var> attribute.  If <var>forceoverwrite</var>
-is false, the destination file is overwritten only if either the
-source file or any of the files that make up the bundle have been
-modified after the destination file was last modified.
-</p>
-<p>
-<em>New in Apache Ant 1.6:</em><br>
-Line endings of source files are preserved in the translated files.
-</p>
-<p><a href="../Types/fileset.html">FileSet</a>s are used to select files to
-translate.
-</p>
+<p>The file names generated thus are appended with the string <samp>.properties</samp> to make up
+the file names that are to be used.</p>
+<p>File encoding is supported.  The encoding scheme of the source files, destination files and the
+bundle files can be specified.</p>
+<p>Destination files can be explicitly overwritten using the <var>forceoverwrite</var> attribute.
+If <var>forceoverwrite</var> is <q>false</q>, the destination file is overwritten only if either the
+source file or any of the files that make up the bundle have been modified after the destination
+file was last modified.</p>
+<p><em>Since Apache Ant 1.6</em> line endings of source files are preserved in the translated
+files.</p>
+<p><a href="../Types/fileset.html">FileSet</a>s are used to select files to translate.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">todir</td>
-    <td valign="top">Destination directory where destination files are
-      to be created.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>todir</td>
+    <td>Destination directory where destination files are to be created.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">starttoken</td>
-    <td valign="top">The starting token to identify keys.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>starttoken</td>
+    <td>The starting token to identify keys.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">endtoken</td>
-    <td valign="top">The ending token to identify keys.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>endtoken</td>
+    <td>The ending token to identify keys.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">bundle</td>
-    <td valign="top">Family name of resource bundle.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>bundle</td>
+    <td>Family name of resource bundle.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">bundlelanguage</td>
-    <td valign="top">
-        Locale specific language of resource bundle.  Defaults to
-        default locale's language.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>bundlelanguage</td>
+    <td>Locale specific language of resource bundle.</td>
+    <td>No; defaults to default locale's language</td>
   </tr>
   <tr>
-    <td valign="top">bundlecountry</td>
-    <td valign="top">
-        Locale specific country of resource bundle.  Defaults to
-        default locale's country.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>bundlecountry</td>
+    <td>Locale specific country of resource bundle.</td>
+    <td>No; defaults to default locale's country</td>
   </tr>
   <tr>
-    <td valign="top">bundlevariant</td>
-    <td valign="top">
-        Locale specific variant of resource bundle.  Defaults to
-        the default variant of the country and language being used.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>bundlevariant</td>
+    <td>Locale specific variant of resource bundle.</td>
+    <td>No; defaults to <var>bundlelanguage</var>_<var>bundlecountry</var></td>
   </tr>
   <tr>
-    <td valign="top">srcencoding</td>
-    <td valign="top">Source file encoding scheme.  Defaults to
-    system default file encoding.</td>
-    <td valign="top" align="center">No</td>
+    <td>srcencoding</td>
+    <td>Source file encoding scheme.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">destencoding</td>
-    <td valign="top">Destination file encoding scheme.  Defaults to
-    source file encoding.</td>
-    <td valign="top" align="center">No</td>
+    <td>destencoding</td>
+    <td>Destination file encoding scheme.</td>
+    <td>No; defaults to <var>srcencoding</var></td>
   </tr>
   <tr>
-    <td valign="top">bundleencoding</td>
-    <td valign="top">Resource Bundle file encoding scheme.  Defaults to
-    source file encoding.</td>
-    <td valign="top" align="center">No</td>
+    <td>bundleencoding</td>
+    <td>Resource Bundle file encoding scheme.</td>
+    <td>No; defaults to <var>srcencoding</var></td>
   </tr>
   <tr>
-    <td valign="top">forceoverwrite</td>
-    <td valign="top">Overwrite existing files even if the destination
-      files are newer. Defaults to &quot;no&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>forceoverwrite</td>
+    <td>Overwrite existing files even if the destination files are newer.</td>
+    <td>No; defaults to <q>no</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
 <h4>fileset</h4>
- <p><a href="../Types/fileset.html">FileSets</a> are used to select files that
- contain keys for which value translated files are to be generated.
-</p>
+<p><a href="../Types/fileset.html">FileSets</a> are used to select files that contain keys for which
+value translated files are to be generated.</p>
+
 <h3>Examples</h3>
-<p><b>Translate source file encoded in english into its japanese
-equivalent using a resource bundle encoded in japanese.
-</b></p>
+<p>Translate source file encoded in English into its Japanese equivalent using a resource bundle
+encoded in Japanese.</p>
 <pre>
-  &lt;translate toDir=&quot;$(dest.dir}/ja&quot;
-        starttoken=&quot;#&quot;
-        endtoken=&quot;#&quot;
-        bundle=&quot;resource/BaseResource&quot;
-        bundlelanguage=&quot;ja&quot;
-        forceoverwrite=&quot;yes&quot;
-        srcencoding=&quot;ISO8859_1&quot;
-        destencoding=&quot;SJIS&quot;
-        bundleencoding=&quot;SJIS&quot;&gt;
-        &lt;fileset dir=&quot;${src.dir}&quot;&gt;
-            &lt;include name=&quot;**/*.jsp&quot;/&gt;
-        &lt;/fileset&gt;
-  &lt;/translate&gt;
-</pre>
+&lt;translate toDir=&quot;$(dest.dir}/ja&quot;
+           starttoken=&quot;#&quot;
+           endtoken=&quot;#&quot;
+           bundle=&quot;resource/BaseResource&quot;
+           bundlelanguage=&quot;ja&quot;
+           forceoverwrite=&quot;yes&quot;
+           srcencoding=&quot;ISO8859_1&quot;
+           destencoding=&quot;SJIS&quot;
+           bundleencoding=&quot;SJIS&quot;&gt;
+    &lt;fileset dir=&quot;${src.dir}&quot;&gt;
+        &lt;include name=&quot;**/*.jsp&quot;/&gt;
+    &lt;/fileset&gt;
+&lt;/translate&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/truncate.html b/manual/Tasks/truncate.html
index b7df3f7..205b548 100644
--- a/manual/Tasks/truncate.html
+++ b/manual/Tasks/truncate.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,96 +15,87 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Truncate Task</title>
 </head>
 
 <body>
 
-<h2><a name="touch">Truncate</a></h2>
+<h2 id="touch">Truncate</h2>
+<p><em>Since Apache Ant 1.7.1</em></p>
 <h3>Description</h3>
 
-<p>Set the length of one or more files, as the intermittently available
-<code>truncate</code> Unix utility/function. In addition to working with
-a single file, this Task can also work on
-<a href="../Types/resources.html">resources</a> and resource collections.
-<strong>Since Apache Ant 1.7.1</strong>.
-</p>
+<p>Set the length of one or more files, as the <code>truncate</code> Unix function or GNU
+utility. In addition to working with a single file, this Task can also work
+on <a href="../Types/resources.html">resources</a> and resource collections.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The name of the file.</td>
-    <td valign="top" align="center">Unless a nested resource collection element
-       has been specified.</td>
+    <td>file</td>
+    <td>The name of the file.</td>
+    <td>Unless a nested resource collection element has been specified</td>
   </tr>
   <tr>
-    <td valign="top">length</td>
-    <td valign="top">Specifies the new file length (in bytes) to set.
-                     The following suffixes are supported:
+    <td>length</td>
+    <td>Specifies the new file length (in bytes) to set.  The following suffixes are supported:
       <ul>
-        <li>K : Kilobytes (1024 bytes)</li>
-        <li>M : Megabytes (1024 K)</li>
-        <li>G : Gigabytes (1024 M)</li>
-        <li>T : Terabytes (1024 G)</li>
-        <li>P : Petabytes (1024 T)</li>
+        <li><q>K</q> : Kilobytes (1024 bytes)</li>
+        <li><q>M</q> : Megabytes (1024 K)</li>
+        <li><q>G</q> : Gigabytes (1024 M)</li>
+        <li><q>T</q> : Terabytes (1024 G)</li>
+        <li><q>P</q> : Petabytes (1024 T)</li>
       </ul>
     </td>
-    <td valign="center" align="center" rowspan="2">At most one of these.
-      Omitting both implies <code>length="0"</code>.
+    <td rowspan="2">At most one of these; omitting both implies <var>length</var>=<q>0</q>
     </td>
   </tr>
   <tr>
-    <td valign="top">adjust</td>
-    <td valign="top">Specifies the number of bytes
-      (and positive/negative direction)
-      by which to adjust file lengths.  The same suffixes are supported
-      for this attribute as for the <code>length</code> attribute.
+    <td>adjust</td>
+    <td class="left">Specifies the number of bytes (and positive/negative direction) by which to
+      adjust file lengths.  The same suffixes are supported for this attribute as for
+      the <var>length</var> attribute.
     </td>
   </tr>
   <tr>
-    <td valign="top">create</td>
-    <td valign="top">Whether to create nonexistent files.</td>
-    <td valign="top" align="center">No, default <i>true</i>.</td>
+    <td>create</td>
+    <td>Whether to create nonexistent files.</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">mkdirs</td>
-    <td valign="top">Whether to create nonexistent parent
-       directories when creating new files.</td>
-    <td valign="top" align="center">No, default <i>false</i>.</td>
+    <td>mkdirs</td>
+    <td>Whether to create nonexistent parent directories when creating new files.</td>
+    <td>No; default <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>any resource collection</h4>
 
-<p>You can use any number of nested resource collection elements to
-define the resources for this task and refer to resources defined
-elsewhere.  <b>Note:</b> resources passed to this task are expected
-to be filesystem-based.</p>
+<p>You can use any number of nested resource collection elements to define the resources for this
+task and refer to resources defined elsewhere.  <strong>Note</strong>: resources passed to this task
+are expected to be filesystem-based.</p>
 
 <h3>Examples</h3>
 
-<pre>  &lt;truncate file="foo" /&gt;</pre>
-<p>Sets the length of file <code>foo</code> to zero.</p>
+<p>Set the length of file <samp>foo</samp> to zero.</p>
+<pre>&lt;truncate file="foo"/&gt;</pre>
 
-<pre>  &lt;truncate file="foo" length="1K" /&gt;</pre>
-<p>Sets the length of file <code>foo</code> to 1 kilobyte (1024 bytes).</p>
+<p>Set the length of file <samp>foo</samp> to 1 kilobyte (1024 bytes).</p>
+<pre>&lt;truncate file="foo" length="1K"/&gt;</pre>
 
-<pre>  &lt;truncate file="foo" adjust="1K" /&gt;</pre>
-<p>Adjusts the length of file <code>foo</code> upward by 1 kilobyte.</p>
+<p>Adjust the length of file <samp>foo</samp> upward by 1 kilobyte.</p>
+<pre>&lt;truncate file="foo" adjust="1K"/&gt;</pre>
 
-<pre>  &lt;truncate file="foo" adjust="-1M" /&gt;</pre>
-<p>Adjusts the length of file <code>foo</code> downward by 1 megabyte.</p>
+<p>Adjust the length of file <samp>foo</samp> downward by 1 megabyte.</p>
+<pre>&lt;truncate file="foo" adjust="-1M"/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/tstamp.html b/manual/Tasks/tstamp.html
index 6baa0c8..1661392 100644
--- a/manual/Tasks/tstamp.html
+++ b/manual/Tasks/tstamp.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,154 +15,144 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>TStamp Task</title>
 </head>
 
 <body>
 
-<h2><a name="tstamp">Tstamp</a></h2>
+<h2 id="tstamp">Tstamp</h2>
 
 <h3>Description</h3>
-<p>Sets the <code>DSTAMP</code>, <code>TSTAMP</code>, and <code>TODAY</code>
-properties in the current project. By default,
-the <code>DSTAMP</code> property is in the
-format &quot;yyyyMMdd&quot;, <code>TSTAMP</code> is in the
-format &quot;hhmm&quot;, and <code>TODAY</code> is in the
-format &quot;MMMM dd yyyy&quot;. Use the nested <code>&lt;format&gt;</code> element
-to specify a different format.</p>
+<p>Sets the <code>DSTAMP</code>, <code>TSTAMP</code>, and <code>TODAY</code> properties in the
+current project. By default, the <code>DSTAMP</code> property is in the
+format <q>yyyyMMdd</q>, <code>TSTAMP</code> is in the format <q>hhmm</q>, and <code>TODAY</code> is
+in the format <q>MMMM dd yyyy</q>. Use the nested <code>&lt;format&gt;</code> element to specify a
+different format.</p>
 
-<p>These properties can be used in the build-file, for instance, to create
-time-stamped filenames, or used to replace placeholder tags inside documents
-to indicate, for example, the release date. The best place for this task is
-probably in an initialization target.</p>
+<p>These properties can be used in the build file, for instance, to create timestamped filenames, or
+used to replace placeholder tags inside documents to indicate, for example, the release date. The
+best place for this task is probably in an initialization target.</p>
 
-<p><em>Since Ant 1.9.10</em> the magic
-  property <code>ant.tstamp.now</code> can be used to specify a fixed
-  date value in order to create reproducible builds. Its value must be
-  a number and is interpreted as seconds since the epoch (midnight
-  1970-01-01).</p>
+<p><em>Since Ant 1.10.2</em> the magic property <code>ant.tstamp.now</code> can be used to specify a
+fixed date value in order to create reproducible builds. Its value must be a number and is
+interpreted as seconds since the epoch (midnight 1970-01-01). With <code>ant.tstamp.now.iso</code>
+you could also specify that value in ISO-8601 format (<code>1972-04-17T08:07:00Z</code>). If you
+specify a value in an invalid format an INFO message will be logged and the value will be
+ignored.</p>
+
+<p>
+  <em>Since Ant 1.10.8</em> the <code>SOURCE_DATE_EPOCH</code> environment variable value (if set)
+  will be honoured for <a href="https://reproducible-builds.org/specs/source-date-epoch/#idm55">reproducible builds</a>.
+  Ant will log a DEBUG message if an invalid value (value that cannot be parsed to an integer), is specified
+  for that environment variable and will instead use the "current" date.
+</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">Prefix used for all properties set. The default is no prefix.</td>
-    <td align="center" valign="top">No</td>
+    <td>prefix</td>
+    <td>Prefix used for all properties set.</td>
+    <td>No; default is no prefix</td>
   </tr>
 </table>
 
-<h3>Nested Elements</h3>
-The Tstamp task supports a <code>&lt;format&gt;</code> nested element that
-allows a property to be set to the current date and time in a given format.
-The date/time patterns are as defined in the Java
-<a href="http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html">SimpleDateFormat</a> class.
-The format element also allows offsets to be applied to the time to generate different time values.
-<br><br>
-<table width="60%" border="1" cellpadding="2" cellspacing="0">
+<h3>Parameters specified as nested elements</h3>
+<p>The task supports a <code>&lt;format&gt;</code> nested element that allows a property to be set
+to the current date and time in a given format.  The date/time patterns are as defined in the
+Java <a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html"
+target="_top">SimpleDateFormat</a> class.  The format element also allows offsets to be applied to
+the time to generate different time values.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">
-        The property to receive the date/time string in the given pattern.
-    </td>
-    <td align="center" valign="top">Yes</td>
+    <td>property</td>
+    <td>The property to receive the date/time string in the given pattern.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">The date/time pattern to be used. The values are as defined by the Java SimpleDateFormat class.</td>
-    <td align="center" valign="top">Yes</td>
-  </tr>
-  <tr>
-    <td valign="top">timezone</td>
-    <td valign="top">The timezone to use for displaying time. The values are as defined by the Java <a href="http://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html">TimeZone</a> class.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">offset</td>
-    <td valign="top">The numeric offset to the current time</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">unit</td>
-    <td valign="top">The unit of the offset to be applied to the current time.
-                     Valid Values are
-                     <ul>
-                        <li>millisecond</li>
-                        <li>second</li>
-                        <li>minute</li>
-                        <li>hour</li>
-                        <li>day</li>
-                        <li>week</li>
-                        <li>month</li>
-                        <li>year</li>
-                     </ul>
-    </td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">locale</td>
-    <td valign="top">The locale used to create date/time string. The general
-      form is &quot;language, country, variant&quot; but either variant or variant and
-      country may be omitted. For more information please refer to documentation
-      for the
-      <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Locale.html">Locale</a>
+    <td>pattern</td>
+    <td>The date/time pattern to be used. The values are as defined by the Java SimpleDateFormat
       class.</td>
-    <td align="center" valign="top">No</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>timezone</td>
+    <td>The timezone to use for displaying time. The values are as defined by the
+      Java <a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html"
+      target="_top">TimeZone</a> class.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>offset</td>
+    <td>The numeric offset to the current time</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>unit</td>
+    <td>The unit of the offset to be applied to the current time.  Valid values are
+      <ul>
+        <li><q>millisecond</q></li>
+        <li><q>second</q></li>
+        <li><q>minute</q></li>
+        <li><q>hour</q></li>
+        <li><q>day</q></li>
+        <li><q>week</q></li>
+        <li><q>month</q></li>
+        <li><q>year</q></li>
+      </ul>
+    </td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>locale</td>
+    <td>The locale used to create date/time string. The general form is <q>language[, country[,
+      variant]]</q> (either <q>variant</q> or both <q>variant</q> and <q>country</q> may be
+      omitted). For more information please refer to documentation for
+      the <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html"
+      target="_top">Locale</a> class.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
 
-<pre>
-  &lt;tstamp/&gt;
-</pre>
+<p>Set the standard <code>DSTAMP</code>, <code>TSTAMP</code>, and <code>TODAY</code> properties
+according to the default formats.</p>
+<pre>&lt;tstamp/&gt;</pre>
 
-<p>
-sets the standard <code>DSTAMP</code>, <code>TSTAMP</code>,
-and <code>TODAY</code> properties according to the default formats.</p>
+<p>Set the standard properties as well as the property <code>TODAY_UK</code> with the date/time
+pattern <q>d-MMMM-yyyy</q> using English locale (eg. 21-May-2001).</p>
 <pre>
-  &lt;tstamp&gt;
+&lt;tstamp&gt;
     &lt;format property=&quot;TODAY_GB&quot; pattern=&quot;d-MMMM-yyyy&quot; locale=&quot;en,GB&quot;/&gt;
-  &lt;/tstamp&gt;
-</pre>
-<p>
-sets the standard properties as well as the property
-<code>TODAY_UK</code> with the date/time pattern &quot;d-MMMM-yyyy&quot;
-using English locale (eg. 21-May-2001).</p>
+&lt;/tstamp&gt;</pre>
 
+<p>Create a timestamp, in the property <code>touch.time</code>, 5 hours before the current time. The
+format in this example is suitable for use with the <code>&lt;touch&gt;</code> task. The standard
+properties are set also.</p>
 <pre>
-  &lt;tstamp&gt;
-      &lt;format property=&quot;touch.time&quot; pattern=&quot;MM/dd/yyyy hh:mm aa&quot;
-              offset=&quot;-5&quot; unit=&quot;hour&quot;/&gt;
-  &lt;/tstamp&gt;
-</pre>
-<p>
-Creates a timestamp, in the property touch.time, 5 hours before the current time. The format in this example
-is suitable for use with the <code>&lt;touch&gt;</code> task. The standard properties are set also.</p>
+&lt;tstamp&gt;
+    &lt;format property=&quot;touch.time&quot; pattern=&quot;MM/dd/yyyy hh:mm aa&quot;
+            offset=&quot;-5&quot; unit=&quot;hour&quot;/&gt;
+&lt;/tstamp&gt;</pre>
 
-<pre>
-  &lt;tstamp prefix="start"/&gt;
-</pre>
-<p>
-Sets three properties with the standard formats, prefixed with "start.":
-<code>start.DSTAMP</code>, <code>start.TSTAMP</code>, and <code>start.TODAY</code>.</p>
-
-
-
+<p>Set three properties with the standard formats, prefixed
+with <q>start.</q>: <code>start.DSTAMP</code>, <code>start.TSTAMP</code>,
+and <code>start.TODAY</code>.</p>
+<pre>&lt;tstamp prefix="start"/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/typedef.html b/manual/Tasks/typedef.html
index bdd58a7..243ce06 100644
--- a/manual/Tasks/typedef.html
+++ b/manual/Tasks/typedef.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,256 +15,188 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Typedef Task</title>
 </head>
 
 <body>
 
-<h2><a name="typedef">Typedef</a></h2>
+<h2 id="typedef">Typedef</h2>
 <h3>Description</h3>
-  <p>
-    Adds a task or a data type definition to the current project
-    such that this new type or task can be used in the current project.
-  </p>
-  <p>
-    A Task is any class that extends org.apache.tools.ant.Task or
-    can be adapted as a Task using an adapter class.
-  </p>
-  <p>
-    Data types are things like <a href="../using.html#path">paths</a> or
-    <a href="../Types/fileset.html">filesets</a> that can be defined at
-    the project level and referenced via their ID attribute.
-    Custom data types usually need custom tasks to put them to good use.
-  </p>
-  <p>
-    Two attributes are needed to make a definition: the name that
-    identifies this data type uniquely, and the full name of the class
-    (including its package name) that implements this type.
-  </p>
-  <p>
-    You can also define a group of definitions at once using the file or
-    resource attributes.  These attributes point to files in the format of
-    Java property files or an xml format.
-  </p>
-  <p>
-    For property files each line defines a single data type in the
-    format:</p>
-  <pre>
-    typename=fully.qualified.java.classname
-  </pre>
-    
-  <p>
-    The xml format is described in the
-    <a href="../Types/antlib.html">Antlib</a> section.
-  </p>
+<p>Adds a task or a data type definition to the current project such that this new type or task can
+be used in the current project.</p>
+<p>A Task is any class that extends <code class="code">org.apache.tools.ant.Task</code> or can be adapted
+as a Task using an adapter class.</p>
+<p>Data types are things like <a href="../using.html#path">paths</a>
+or <a href="../Types/fileset.html">filesets</a> that can be defined at the project level and
+referenced via their <var>id</var> attribute.  Custom data types usually need custom tasks to put
+them to good use.</p>
+<p>Two attributes are needed to make a definition: the name that identifies this data type uniquely,
+and the full name of the class (including its package name) that implements this type.</p>
+<p>You can also define a group of definitions at once using the file or resource attributes.  These
+attributes point to files in the format of Java property files or an xml format.</p>
+<p>For property files each line defines a single data type in the format:</p>
+<pre>typename=fully.qualified.java.classname</pre>
+<p>The xml format is described in the <a href="../Types/antlib.html">Antlib</a> section.</p>
 
-  <p>If you are defining tasks or types that share the same classpath
-    with multiple taskdef or typedef tasks, the corresponding classes
-    will be loaded by different
-    Java <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html">ClassLoaders</a>.
-    Two classes with the same name loaded via different ClassLoaders
-    are not the same class from the point of view of the Java VM, they
-    don't share static variables and instances of these classes can't
-    access private methods or attributes of instances defined by "the
-    other class" of the same name.  They don't even belong to the same
-    Java package and can't access package private code, either.</p>
+<p>If you are defining tasks or types that share the same classpath with
+multiple <code>taskdef</code> or <code>typedef</code> tasks, the corresponding classes will be
+loaded by different
+Java <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html"
+target="_top">ClassLoaders</a>.  Two classes with the same name loaded via different ClassLoaders
+are not the same class from the point of view of JVM, they don't share static variables and
+instances of these classes can't access private methods or attributes of instances defined by "the
+other class" of the same name.  They don't even belong to the same Java package and can't access
+package private code, either.</p>
 
-  <p>The best way to load several tasks/types that are supposed to
-    cooperate with each other via shared Java code is to use the
-    resource attribute and an antlib descriptor.  If this is not
-    possible, the second best option is to use the loaderref attribute
-    and specify the same name for each and every typedef/taskdef -
-    this way the classes will share the same ClassLoader.  Note that
-    the typedef/taskdef tasks must use identical classpath definitions
-    (this includes the order of path components) for the loaderref
-    attribute to work.</p>
+<p>The best way to load several tasks/types that are supposed to cooperate with each other via
+shared Java code is to use the <var>resource</var> attribute and an <code>antlib</code> descriptor.
+If this is not possible, the second best option is to use the <var>loaderref</var> attribute and
+specify the same name for each and every <code>typedef</code>/<code>taskdef</code>&mdash;this way
+the classes will share the same <code>ClassLoader</code>.  Note that
+the <code>typedef</code>/<code>taskdef</code> tasks must use identical classpath definitions (this
+includes the order of path components) for the <var>loaderref</var> attribute to work.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the data type</td>
-    <td valign="top" align="center">Yes, unless the file or resource type
-      attributes have been specified.</td>
+    <td>name</td>
+    <td>the name of the data type</td>
+    <td rowspan="2">Yes, unless <var>file</var> or <var>resource</var> attributes have been
+      specified.</td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">the full class name implementing the data type</td>
-    <td valign="top" align="center">Yes, unless file or resource
-      have been specified.</td>
+    <td>classname</td>
+    <td class="left">the full class name implementing the data type</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">Name of the file to load definitions from.</td>
-    <td valign="top" align="center">No</td>
+    <td>file</td>
+    <td>Name of the file to load definitions from.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">resource</td>
-    <td valign="top">
-      Name of the resource to load definitions from.
-      If multiple resources by this name are found along the classpath,
-      and the format is "properties", the first resource will be loaded;
-      otherwise all such resources will be loaded.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>resource</td>
+    <td>Name of the resource to load definitions from.  If multiple resources by this name are found
+      along the classpath, and <var>format</var> is <q>properties</q>, the first resource will be
+      loaded; otherwise all such resources will be loaded.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">format</td>
-    <td valign="top">The format of the file or resource. The values
-      are "properties" or "xml". If the value is "properties" the file/resource
-      is a property file contains name to classname pairs. If the value
-      is "xml", the file/resource is an xml file/resource structured according
-      to <a href="../Types/antlib.html">Antlib</a>.
-      The default is "properties" unless the file/resource name ends with
-      ".xml", in which case the format attribute will have the value "xml".
-      <b>since Apache Ant 1.6</b>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>format</td>
+    <td>The format of the file or resource. The values are <q>properties</q>" or <q>xml</q>. If the
+      value is <q>properties</q> the file/resource is a property file contains name-classname
+      pairs. If the value is <q>xml</q>, the file/resource is an XML file/resource structured
+      according to <a href="../Types/antlib.html">Antlib</a>.  The default is <q>properties</q>
+      unless the file/resource name ends with <samp>.xml</samp>, in which case the <var>format</var>
+      attribute will have the value <q>xml</q>.  <em>Since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td> <td valign="top">the classpath to
-      use when looking up <code>classname</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>the classpath to use when looking up <var>classname</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">
-      a reference to a classpath to use when looking up <code>classname</code>.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>a reference to a classpath to use when looking up <var>classname</var>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">loaderRef</td>
-    <td valign="top">the name of the loader that is
-      used to load the class, constructed from the specified classpath. Use
-      this to allow multiple tasks/types to be loaded with the same loader,
-      so they can call each other. <b>since Ant 1.5</b> </td>
-    <td align="center" valign="top">No</td>
+    <td>loaderRef</td>
+    <td>the name of the loader that is used to load the class, constructed from the specified
+      classpath. Use this to allow multiple tasks/types to be loaded with the same loader, so they
+      can call each other. <em>Since Ant 1.5</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">onerror</td>
-    <td valign="top">The action to take if there was a failure in defining the
-      type. The values are <i>fail</i>: cause a build exception; <i>report</i>:
-      output a warning, but continue; <i>ignore</i>: do nothing.
-      <b>since Ant 1.6</b>
-      An additional value is <i>failall</i>: cause all behavior of fail,
-      as well as a build exception for the resource or file attribute
-      if the resource or file is not found. <b>since Ant 1.7</b>
-      The default is <i>fail</i>.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>onerror</td>
+    <td>The action to take if there was a failure in defining the type. The values are <q>fail</q>:
+      cause a build exception; <q>report</q>: output a warning, but continue; <q>ignore</q>: do
+      nothing.  <em>Since Ant 1.6</em>, an additional value is <q>failall</q>: cause all behavior of
+      fail, as well as a build exception for the resource or file attribute if the resource or file
+      is not found.</td>
+    <td>No; default is <q>fail</q> (<em>since Ant 1.7</em>)</td>
   </tr>
   <tr>
-    <td valign="top">adapter</td>
-    <td valign="top">A class that is used to adapt the defined class to
-      another interface/class. The adapter class must implement the interface
-      "org.apache.tools.ant.TypeAdapter". The adapter class will be used
-      to wrap the defined class unless the defined class implements/extends
-      the class defined by the attribute "adaptto".
-      If "adaptto" is not set, the defined class will always be wrapped.
-      <b>since Ant 1.6</b>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>adapter</td>
+    <td>A class that is used to adapt the defined class to another interface/class. The adapter
+      class must implement the interface <code>org.apache.tools.ant.TypeAdapter</code>. The adapter
+      class will be used to wrap the defined class unless the defined class implements/extends the
+      class defined by the attribute <q>adaptto</q>.  If <q>adaptto</q> is not set, the defined
+      class will always be wrapped.  <em>Since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">adaptto</td>
-    <td valign="top">This attribute is used in conjunction with the
-      adapter attribute.
-      If the defined class does not implement/extend the interface/class
-      specified by this attribute, the adaptor class will be used
-      to wrap the class. <b>since Ant 1.6</b>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>adaptto</td>
+    <td>This attribute is used in conjunction with the adapter attribute.  If the defined class does
+      not implement/extend the interface/class specified by this attribute, the adaptor class will
+      be used to wrap the class. <em>Since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">uri</td>
-    <td valign="top">
-      The uri that this definition should live in.
-      <b>since Ant 1.6</b>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>uri</td>
+    <td>The uri that this definition should live in.  <em>Since Ant 1.6</em></td>
+    <td>No</td>
   </tr>
 </table>
-  <h3>Parameters specified as nested elements</h3>
-  <h4>classpath</h4>
-  <p><code>Typedef</code>'s <i>classpath</i> attribute is a 
-    <a href="../using.html#path">path-like structure</a> and can also be set
-    via a nested <i>classpath</i> element.</p>
+<h3>Parameters specified as nested elements</h3>
+<h4>classpath</h4>
+<p><code>Typedef</code>'s <var>classpath</var> attribute is a <a href="../using.html#path">path-like
+structure</a> and can also be set via a nested <code>classpath</code> element.</p>
 
 <h3>Examples</h3>
-  The following fragment defines define a type called <i>urlset</i>.
-  <pre>
-    &lt;typedef name="urlset" classname="com.mydomain.URLSet"/&gt; </pre>
-  The data type is now available to Ant. The
-  class <code>com.mydomain.URLSet</code> implements this type.</p>
+<p>The following fragment defines define a type called <code>urlset</code>.</p>
+<pre>&lt;typedef name="urlset" classname="com.mydomain.URLSet"/&gt;</pre>
+<p>The data type is now available to Ant. The class <code>com.mydomain.URLSet</code> implements this
+type.</p>
 
+<p>Assuming a class <code>org.acme.ant.RunnableAdapter</code> that
+extends <code class="code">Task</code> and
+implements <code class="code">org.apache.tools.ant.TypeAdapter</code>, and in
+the <code class="code">execute()</code> method invokes <code class="code">run()</code> on the
+proxied object, one may use a <code class="code">Runnable</code> class as an Ant task. The following
+fragment defines a task called <code>runclock</code>.</p>
+<pre>
+&lt;typedef name="runclock"
+         classname="com.acme.ant.RunClock"
+         adapter="org.acme.ant.RunnableAdapter"/&gt;</pre>
 
-  <p>
-    Assuming a class <i>org.acme.ant.RunnableAdapter</i> that
-    extends Task and implements <i>org.apache.tools.ant.TypeAdapter</i>,
-    and in the execute method invokes <i>run</i> on the proxied object,
-    one may use a Runnable class as an Ant task. The following fragment
-    defines a task called <i>runclock</i>.
-  </p>
-  <pre>
-    &lt;typedef name="runclock"
-             classname="com.acme.ant.RunClock"
-             adapter="org.acme.ant.RunnableAdapter"/&gt;
-  </pre>
+<p>The following fragment shows the use of the <var>classpathref</var> and <var>loaderref</var> to
+load up two definitions.</p>
+<pre>
+&lt;path id="lib.path"&gt;
+    &lt;fileset dir="lib" includes="lib/*.jar"/&gt;
+&lt;/path&gt;
 
+&lt;typedef name="filter1"
+         classname="org.acme.filters.Filter1"
+         classpathref="lib.path"
+         loaderref="lib.path.loader"/&gt;
+&lt;typedef name="filter2"
+         classname="org.acme.filters.Filter2"
+         loaderref="lib.path.loader"/&gt;</pre>
 
-  <p>
-    The following fragment shows the use of the classpathref and
-    loaderref to load up two definitions.
-  </p>
-  <pre>
-    &lt;path id="lib.path"&gt;
-      &lt;fileset dir="lib" includes="lib/*.jar"/&gt;
-    &lt;/path&gt;
-
-    &lt;typedef name="filter1"
-             classname="org.acme.filters.Filter1"
-             classpathref="lib.path"
-             loaderref="lib.path.loader"
-             /&gt;
-    &lt;typedef name="filter2"
-             classname="org.acme.filters.Filter2"
-             loaderref="lib.path.loader"
-             /&gt;
-  </pre>
-  
-  
-  <p>
-    If you want to load an antlib into a special xml-namespace, the <tt>uri</tt> attribute
-    is important:
-  </p>
-  <pre>
-  &lt;project xmlns:antcontrib="antlib:net.sf.antcontrib"&gt;
+<p>If you want to load an antlib into a special XML namespace, the <var>uri</var> attribute is
+important:</p>
+<pre>
+&lt;project xmlns:antcontrib="antlib:net.sf.antcontrib"&gt;
      &lt;taskdef uri="antlib:net.sf.antcontrib"
               resource="net/sf/antcontrib/antlib.xml"
-              classpath="path/to/ant-contrib.jar"/&gt;
-  </pre>
-            
-<p>Here the namespace
-  declaration <code>xmlns:antcontrib="antlib:net.sf.antcontrib"</code>
-  allows tasks and types of the AntContrib Antlib to be used with the
-  <code>antcontrib</code> prefix
-  like <code>&lt;antcontrib:if&gt;</code>.
-  The normal rules of XML namespaces apply and you can declare the
-  prefix at any element to make it usable for the element it is
-  declared on as well as all its child elements.</p>
+              classpath="path/to/ant-contrib.jar"/&gt;</pre>
 
+<p>Here the namespace declaration <code>xmlns:antcontrib="antlib:net.sf.antcontrib"</code> allows
+tasks and types of the Ant-Contrib Antlib to be used with the <samp>antcontrib</samp> prefix
+like <code>&lt;antcontrib:if&gt;</code>.  The normal rules of XML namespaces apply and you can
+declare the prefix at any element to make it usable for the element it is declared on as well as all
+its child elements.</p>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/unpack.html b/manual/Tasks/unpack.html
index dcc88a9..89fff55 100644
--- a/manual/Tasks/unpack.html
+++ b/manual/Tasks/unpack.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,104 +15,95 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>GUnzip/BUnzip2 Task</title>
 </head>
 
 <body>
 
-<h2><a name="unpack">GUnzip/BUnzip2</a></h2>
+<h2 id="unpack">GUnzip/BUnzip2/UnXZ</h2>
 <h3>Description</h3>
-<p>Expands a resource packed using GZip or BZip2.</p>
+<p>Expands a resource packed using GZip, BZip2 or XZ.</p>
 
-<p>If <i>dest</i> is a directory the name of the destination file is
-the same as <i>src</i> (with the &quot;.gz&quot; or &quot;.bz2&quot;
-extension removed if present). If <i>dest</i> is omitted, the parent
-dir of <i>src</i> is taken. The file is only expanded if the source
-resource is newer than the destination file, or when the destination file
-does not exist.</p>
+<p>If <var>dest</var> is a directory the name of the destination file is the same as <var>src</var>
+(with the <q>.gz</q>, <q>.bz2</q> or <q>.xz</q> extension removed if present). If <var>dest</var> is
+omitted, the parent dir of <var>src</var> is taken. The file is only expanded if the source resource
+is newer than the destination file, or when the destination file does not exist.</p>
+
+<p>XZ compression support has been added <em>since Apache Ant 1.10.1</em> and depends on external
+libraries not included in the Ant distribution.
+See <a href="../install.html#librarydependencies">Library Dependencies</a> for more information.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">the file to expand.</td>
-    <td align="center" valign="top">Yes, or a nested resource collection.</td>
+    <td>src</td>
+    <td>the file to expand.</td>
+    <td>Yes, or a nested resource collection</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">the destination file or directory.</td>
-    <td align="center" valign="top">No</td>
+    <td>dest</td>
+    <td>the destination file or directory.</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
-<h4>any <a href="../Types/resources.html">resource</a> or single element
-resource collection</h4>
+<h4>any <a href="../Types/resources.html">resource</a> or single element resource collection</h4>
 
-<p>The specified resource will be used as src.</p>
+<p>The specified resource will be used as <var>src</var>.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;gunzip src=&quot;test.tar.gz&quot;/&gt;
-</pre></blockquote>
-<p>expands <i>test.tar.gz</i> to <i>test.tar</i></p>
-<blockquote><pre>
-&lt;bunzip2 src=&quot;test.tar.bz2&quot;/&gt;
-</pre></blockquote>
-<p>expands <i>test.tar.bz2</i> to <i>test.tar</i></p>
-<blockquote><pre>
-&lt;gunzip src=&quot;test.tar.gz&quot; dest=&quot;test2.tar&quot;/&gt;
-</pre></blockquote>
-<p>expands <i>test.tar.gz</i> to <i>test2.tar</i></p>
-<blockquote><pre>
-&lt;gunzip src=&quot;test.tar.gz&quot; dest=&quot;subdir&quot;/&gt;
-</pre></blockquote>
-<p>expands <i>test.tar.gz</i> to <i>subdir/test.tar</i> (assuming
-subdir is a directory).</p>
-<blockquote><pre>
+<p>Expand <samp>test.tar.gz</samp> to <samp>test.tar</samp></p>
+<pre>&lt;gunzip src=&quot;test.tar.gz&quot;/&gt;</pre>
+
+<p>Expand <samp>test.tar.bz2</samp> to <samp>test.tar</samp></p>
+<pre>&lt;bunzip2 src=&quot;test.tar.bz2&quot;/&gt;</pre>
+
+<p>Expand <samp>test.tar.xz</samp> to <samp>test.tar</samp></p>
+<pre>&lt;unxz src=&quot;test.tar.xz&quot;/&gt;</pre>
+
+<p>Expand <samp>test.tar.gz</samp> to <samp>test2.tar</samp></p>
+<pre>&lt;gunzip src=&quot;test.tar.gz&quot; dest=&quot;test2.tar&quot;/&gt;</pre>
+
+<p>Expand <samp>test.tar.gz</samp> to <samp>subdir/test.tar</samp> (assuming <samp>subdir</samp> is
+a directory).</p>
+<pre>&lt;gunzip src=&quot;test.tar.gz&quot; dest=&quot;subdir&quot;/&gt;</pre>
+
+<p>Download <samp>https://example.org/archive.tar.gz</samp> and expand it to <samp>archive.tar</samp>
+in the project's <var>basedir</var> on the fly.</p>
+<pre>
 &lt;gunzip dest=&quot;.&quot;&gt;
-  &lt;url url="http://example.org/archive.tar.gz"/&gt;
+  &lt;url url="https://example.org/archive.tar.gz"/&gt;
 &lt;/gunzip&gt;
-</pre></blockquote>
-<p>downloads <i>http://example.org/archive.tar.gz</i> and expands it
-to <i>archive.tar</i> in the project's basedir on the fly.</p>
+</pre>
 
 <h3>Related tasks</h3>
 
-<pre>
-&lt;gunzip src="some-archive.gz" dest="some-dest-dir"/&gt;
-</pre>
-
-is identical to
-
+<p>The following</p>
+<pre>&lt;gunzip src="some-archive.gz" dest="some-dest-dir"/&gt;</pre>
+<p>is identical to</p>
 <pre>
 &lt;copy todir="some-dest-dir"&gt;
   &lt;gzipresource&gt;
     &lt;file file="some-archive.gz"/&gt;
   &lt;/gzipresource&gt;
   &lt;mapper type="glob" from="*.gz" to="*"/&gt;
-&lt;/copy&gt;
-</pre>
+&lt;/copy&gt;</pre>
 
-<p>The same is also true for <code>&lt;bunzip2&gt;</code> and
-<code>&lt;bzip2resource&gt;</code>.  <code>&lt;copy&gt;</code> offers
-additional features like <a
-href="../Types/filterchain.html">filtering files</a> on the fly,
-allowing a file to be mapped to multiple destinations, preserving the
-last modified time or a configurable file system timestamp
-granularity.</p>
-
-
+<p>The same is also true for <code>&lt;bunzip2&gt;</code> and <code>&lt;bzip2resource&gt;</code>
+or <code>&lt;unxz&gt;</code> and <code>&lt;xzresource&gt;</code>.  <code>&lt;copy&gt;</code> offers
+additional features like <a href="../Types/filterchain.html">filtering files</a> on the fly,
+allowing a file to be mapped to multiple destinations, preserving the last modified time or a
+configurable file system timestamp granularity.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/untar.html b/manual/Tasks/untar.html
index bfaf28f..489cbfd 100644
--- a/manual/Tasks/untar.html
+++ b/manual/Tasks/untar.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,22 +15,20 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Untar Task</title>
 </head>
 
 <body>
 
-<h2><a name="untar">Untar</a></h2>
+<h2 id="untar">Untar</h2>
 <h3>Description</h3>
 <p>Untars a tarfile.</p>
 
-This document has moved <A HREF="unzip.html">here</A>
+This document has moved <a href="unzip.html">here</a>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/unzip.html b/manual/Tasks/unzip.html
index dbf4a16..f4a6ce5 100644
--- a/manual/Tasks/unzip.html
+++ b/manual/Tasks/unzip.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,150 +15,123 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Unzip Task</title>
 </head>
 
 <body>
 
-<h2><a name="unzip">Unjar/Untar/Unwar/Unzip</a></h2>
+<h2 id="unzip">Unjar/Untar/Unwar/Unzip</h2>
 <h3>Description</h3>
 <p>Unzips a zip-, war-, or jar file.</p>
-<p><a href="../Types/patternset.html">PatternSet</a>s are used to select files to extract
-<I>from</I> the archive.  If no patternset is used, all files are extracted.
-</p>
+<p><a href="../Types/patternset.html">PatternSet</a>s are used to select files to
+extract <em>from</em> the archive.  If no patternset is used, all files are extracted.</p>
 
-<p><a href="../Types/resources.html#collection">Resource
-Collection</a>s may be used to select archived files to perform
-unarchival upon.  Only file system based resource collections are
-supported by Unjar/Unwar/Unzip, this includes <a
-href="../Types/fileset.html">fileset</a>, <a
-href="../Types/filelist.html">filelist</a>, <a
-href="../using.html#path">path</a>, and <a
-href="../Types/resources.html#files">files</a>.
-Untar supports arbitrary resource collections.
-Prior to Apache Ant 1.7 only fileset has been supported as a nested element.</p>
+<p><a href="../Types/resources.html#collection">resource collections</a> may be used to select
+archived files to perform unarchival upon.  Only file system based resource collections are
+supported by <code>Unjar</code>/<code>Unwar</code>/<code>Unzip</code>, this
+includes <a href="../Types/fileset.html">fileset</a>, <a href="../Types/filelist.html">filelist</a>, <a href="../using.html#path">path</a>,
+and <a href="../Types/resources.html#files">files</a>. <code>Untar</code> supports arbitrary
+resource collections.  Prior to Apache Ant 1.7 only <code>fileset</code> has been supported as a
+nested element.</p>
 
-<p>You can define filename transformations by using a nested <a href="../Types/mapper.html">mapper</a> element.  The default mapper is the
-<a href="../Types/mapper.html#identity-mapper">identity mapper</a>.
-</p>
+<p>You can define filename transformations by using a
+nested <a href="../Types/mapper.html">mapper</a> element.  The default mapper is the
+<a href="../Types/mapper.html#identity-mapper">identity mapper</a>.</p>
 <p>File permissions will not be restored on extracted files.</p>
-<p>The untar task recognizes the long pathname entries used by GNU tar.<p>
+<p>The <code>untar</code> task recognizes the long pathname entries used by GNU tar.<p>
 
-<p><b>Please note</b> that different ZIP tools handle timestamps
-differently when it comes to applying timezone offset calculations of
-files.  Some ZIP libraries will store the timestamps as they've been
-read from the filesystem while others will modify the timestamps both
-when reading and writing the files to make all timestamps use the same
-timezone.  A ZIP archive created by one library may extract files with
-"wrong timestamps" when extracted by another library.</p>
+<p><strong>Please note</strong> that different ZIP tools handle timestamps differently when it comes
+to applying timezone offset calculations of files.  Some ZIP libraries will store the timestamps as
+they've been read from the filesystem while others will modify the timestamps both when reading and
+writing the files to make all timestamps use the same timezone.  A ZIP archive created by one
+library may extract files with "wrong timestamps" when extracted by another library.</p>
 
-<p>Ant's ZIP classes use the same algorithm as the InfoZIP tools and
-zlib (timestamps get adjusted), Windows' "compressed folders" function
-and WinZIP don't change the timestamps.  This means that using the
-unzip task on files created by Windows' compressed folders function
-may create files with timestamps that are "wrong", the same is true if
-you use Windows' functions to extract an Ant generated ZIP
-archive.</p>
-
+<p>Ant's ZIP classes use the same algorithm as the InfoZIP tools and zlib (timestamps get adjusted),
+Windows' "compressed folders" function and WinZIP don't change the timestamps.  This means that
+using the <code>unzip</code> task on files created by Windows' compressed folders function may
+create files with timestamps that are "wrong", the same is true if you use Windows' functions to
+extract an Ant generated ZIP archive.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">src</td>
-    <td valign="top">archive file to expand.</td>
-    <td align="center" valign="top">Yes, if filesets are not used.</td>
+    <td>src</td>
+    <td>archive file to expand.</td>
+    <td>Yes, unless filesets are used</td>
   </tr>
   <tr>
-    <td valign="top">dest</td>
-    <td valign="top">directory where to store the expanded files.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>dest</td>
+    <td>directory where to store the expanded files.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">overwrite</td>
-    <td valign="top">Overwrite files, even if they are newer than the
-      corresponding entries in the archive (true or false, default is
-      true).</td>
-    <td align="center" valign="top">No</td>
+    <td>overwrite</td>
+    <td>Overwrite files, even if they are newer than the corresponding entries in the archive
+      (<q>true|false</q>).</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">compression</td>
-    <td valign="top"><b>Note:</b> This attribute is only available for
-    the <code>untar</code> task.<br>
-    compression method.  Allowable values are &quot;none&quot;,
-    &quot;gzip&quot; and &quot;bzip2&quot;.  Default is
-    &quot;none&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>compression</td>
+    <td><strong>Note</strong>: This attribute is only available for the <code>untar</code> task.<br/>
+      compression method.  Allowable values are <q>none</q>, <q>gzip</q>, <q>xz</q>
+      and <q>bzip2</q>.</td>
+    <td>No; default is <q>none</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">
-    The character encoding that has been used for filenames
-    inside the zip file.  For a list of possible values see the <a
-    href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">Supported Encodings</a>.<br/>
-    Defaults to &quot;UTF8&quot; for the <code>unzip</code> and the
-    platform's default encoding for the <code>untar</code> task.  Use
-    the magic value
-    <code>native-encoding</code> for the platform's default character
-    encoding.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The character encoding that has been used for filenames inside the zip file.  For a list of
+      possible values see
+      the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+      target="_top">Supported Encodings</a>.<br/>  Use the magic value <q>native-encoding</q> for
+      default JVM character encoding.<br/>  See also the <a href="zip.html#encoding">discussion in
+      the zip task page</a></td>
+    <td>No; defaults to <q>UTF8</q> for <code>unzip</code> and default JVM character encoding
+      for <code>untar</code> task</td>
   </tr>
   <tr>
-    <td valign="top">failOnEmptyArchive</td>
-    <td valign="top">whether trying to extract an empty archive is an
-      error. <em>since Ant 1.8.0</em></td>
-    <td valign="top" align="center">No, defaults to false</td>
+    <td>failOnEmptyArchive</td>
+    <td>whether trying to extract an empty archive is an error. <em>since Ant 1.8.0</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">stripAbsolutePathSpec</td>
-    <td valign="top">whether Ant should remove leading '/' or '\'
-      characters from the extracted file name before extracting it.
-      Note that this changes the entry's name before applying
-      include/exclude patterns and before using the nested mappers (if
-      any).  <em>since Ant 1.8.0</em></td>
-    <td valign="top" align="center">No, defaults to true since 1.9.12
-      (used to defaukt to false prior to that)</td>
+    <td>stripAbsolutePathSpec</td>
+    <td>whether Ant should remove leading <q>/</q> or <q>\</q> characters from the extracted file
+      name before extracting it.  Note that this changes the entry name before
+      applying <code>include</code>/<code>exclude</code> patterns and before using the nested
+      mappers (if any).  <em>since Ant 1.8.0</em></td>
+    <td>No; defaults to <q>true</q> <em>since Ant 1.10.4</em>
+      (used to default to <q>false</q> prior to that)</td>
   </tr>
   <tr>
-    <td valign="top">scanForUnicodeExtraFields</td>
-    <td valign="top"><b>Note:</b> This attribute is not available for
-    the <code>untar</code> task.<br>
-      If the archive contains uncode extra fields then use them to set
-      the file names, ignoring the specified encoding.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, defaults to true</td>
+    <td>scanForUnicodeExtraFields</td>
+    <td><strong>Note</strong>: This attribute is not available for the <code>untar</code> task.<br/>
+      If the archive contains Unicode extra fields then use them to set the file names, ignoring the
+      specified encoding.<br/>See also the <a href="zip.html#encoding">discussion in the zip task
+      page</a></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">allowFilesToEscapeDest</td>
-    <td valign="top">Whether to allow the extracted file or directory
-      to be outside of the dest directory.
-      <em>since Ant 1.9.12</em></td>
-    <td valign="top" align="center">No, defaults to false unless
-    stripAbsolutePathSpec is false and the entry's name starts with a leading
-    path spec.</td>
+    <td>allowFilesToEscapeDest</td>
+    <td>Whether to allow the extracted file or directory to be outside of the dest
+      directory.  <em>since Ant 1.10.4</em></td>
+    <td>No, defaults to <q>false</q> unless <var>stripAbsolutePathSpec</var> is <q>false</q> and the
+      entry's name starts with a leading path spec.</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<pre>
-&lt;unzip src=&quot;${tomcat_src}/tools-src.zip&quot; dest=&quot;${tools.home}&quot;/&gt;
-</pre>
-<p>
+<pre>&lt;unzip src=&quot;${tomcat_src}/tools-src.zip&quot; dest=&quot;${tools.home}&quot;/&gt;</pre>
 <pre>
 &lt;gunzip src=&quot;tools.tar.gz&quot;/&gt;
-&lt;untar src=&quot;tools.tar&quot; dest=&quot;${tools.home}&quot;/&gt;
-</pre>
+&lt;untar src=&quot;tools.tar&quot; dest=&quot;${tools.home}&quot;/&gt;</pre>
 <pre>
 &lt;unzip src=&quot;${tomcat_src}/tools-src.zip&quot;
        dest=&quot;${tools.home}&quot;&gt;
@@ -165,9 +139,7 @@
         &lt;include name=&quot;**/*.java&quot;/&gt;
         &lt;exclude name=&quot;**/Test*.java&quot;/&gt;
     &lt;/patternset&gt;
-&lt;/unzip&gt;
-</pre>
-<p>
+&lt;/unzip&gt;</pre>
 <pre>
 &lt;unzip dest=&quot;${tools.home}&quot;&gt;
     &lt;patternset&gt;
@@ -178,30 +150,49 @@
         &lt;include name=&quot;**/*.zip&quot;/&gt;
         &lt;exclude name=&quot;**/tmp*.zip&quot;/&gt;
     &lt;/fileset&gt;
-&lt;/unzip&gt;
-</pre>
-<p>
+&lt;/unzip&gt;</pre>
 <pre>
 &lt;unzip src=&quot;apache-ant-bin.zip&quot; dest=&quot;${tools.home}&quot;&gt;
     &lt;patternset&gt;
         &lt;include name=&quot;apache-ant/lib/ant.jar&quot;/&gt;
     &lt;/patternset&gt;
     &lt;mapper type=&quot;flatten&quot;/&gt;
-&lt;/unzip&gt;
-</pre>
+&lt;/unzip&gt;</pre>
+
+<p>Extract all images from <samp>ant.jar</samp> which are stored in the <samp>images</samp>
+  directory of the jar file (or somewhere under it). While extracting the directory structure
+  (<samp>images</samp>) will be preserved.</p>
+<pre>
+&lt;unzip src=&quot;${ant.home}/lib/ant.jar&quot; dest=&quot;...&quot;&gt;
+  &lt;patternset&gt;
+    &lt;include name=&quot;images/&quot;/&gt;
+  &lt;/patternset&gt;
+&lt;/unzip&gt;</pre>
+
+<p>Extract two files, <samp>ant_logo_large.gif</samp> and <samp>LICENSE.txt</samp>,
+  from <samp>ant.jar</samp>. More exactly: extract all files with these names from anywhere in the
+  source file. While extracting the directory structure will be preserved.</p>
+<pre>
+&lt;unzip src=&quot;${ant.home}/lib/ant.jar&quot; dest=&quot;...&quot;&gt;
+  &lt;patternset&gt;
+    &lt;include name=&quot;**/ant_logo_large.gif&quot;/&gt;
+    &lt;include name=&quot;**/LICENSE.txt&quot;/&gt;
+  &lt;/patternset&gt;
+&lt;/unzip&gt;</pre>
 
 <h3>Related tasks</h3>
 
+<p>The task</p>
+
 <pre>
 &lt;unzip src="some-archive" dest="some-dir"&gt;
   &lt;patternset&gt;
     &lt;include name="some-pattern"/&gt;
   &lt;/patternset&gt;
   &lt;mapper type=&quot;some-mapper&quot;/&gt;
-&lt;/unzip&gt;
-</pre>
+&lt;/unzip&gt;</pre>
 
-is identical to
+<p>is identical to</p>
 
 <pre>
 &lt;copy todir="some-dir" preservelastmodified="true"&gt;
@@ -211,44 +202,20 @@
     &lt;/patternset&gt;
   &lt;/zipfileset&gt;
   &lt;mapper type=&quot;some-mapper&quot;/&gt;
-&lt;/copy&gt;
-</pre>
+&lt;/copy&gt;</pre>
 
-<p>The same is also true for <code>&lt;untar&gt;</code> and
-<code>&lt;tarfileset&gt;</code>.  <code>&lt;copy&gt;</code> offers
-additional features like <a href="../Types/filterchain.html">filtering files</a> on the fly,
-allowing a file to be mapped to multiple destinations or a
-configurable file system timestamp granularity.</p>
+<p>The same is also true for <code>&lt;untar&gt;</code>
+and <code>&lt;tarfileset&gt;</code>.  <code>&lt;copy&gt;</code> offers additional features
+like <a href="../Types/filterchain.html">filtering files</a> on the fly, allowing a file to be
+mapped to multiple destinations or a configurable file system timestamp granularity.</p>
+
+<p>&quot;Delete&quot; files from a zipfile.</p>
 
 <pre>&lt;zip destfile=&quot;new.jar&quot;&gt;
   &lt;zipfileset src=&quot;old.jar&quot;&gt;
     &lt;exclude name=&quot;do/not/include/this/class&quot;/&gt;
   &lt;/zipfileset&gt;
-&lt;/zip&gt;
-</pre>
-<p>&quot;Deletes&quot; files from a zipfile.</p>
-
-<pre>
-&lt;unzip src=&quot;${ant.home}/lib/ant.jar&quot; dest=&quot;...&quot;&gt;
-  &lt;patternset&gt;
-    &lt;include name=&quot;images/&quot;/&gt;
-  &lt;/patternset&gt;
-&lt;/unzip&gt;
-</pre>
-<p>This extracts all images from <tt>ant.jar</tt> which are stored in the <tt>images</tt> directory
-of the Jar (or somewhere under it). While extracting the directory structure (<tt>images</tt>)
-will be taken.</p>
-
-<pre>
-&lt;unzip src=&quot;${ant.home}/lib/ant.jar&quot; dest=&quot;...&quot;&gt;
-  &lt;patternset&gt;
-    &lt;include name=&quot;**/ant_logo_large.gif&quot;/&gt;
-    &lt;include name=&quot;**/LICENSE.txt&quot;/&gt;
-  &lt;/patternset&gt;
-&lt;/unzip&gt;
-</pre>
-<p>This extracts the two files <tt>ant_logo_large.gif</tt> and <tt>LICENSE.txt</tt> from the
-<tt>ant.jar</tt>. More exactly: it extracts all files with these names from anywhere in the source file. While extracting the directory structure will be taken.</p>
+&lt;/zip&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/uptodate.html b/manual/Tasks/uptodate.html
index c724f20..1a3014e 100644
--- a/manual/Tasks/uptodate.html
+++ b/manual/Tasks/uptodate.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,164 +15,138 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Uptodate Task</title>
 </head>
 
 <body>
 
-<h2><a name="uptodate">Uptodate</a></h2>
+<h2 id="uptodate">Uptodate</h2>
 <h3>Description</h3>
-<p>Sets a property if a target file or set of target files is more up-to-date
-than a source file or set of source files. A single source file is specified
-using the <code>srcfile</code> attribute. A set of source files is specified
-using the nested <code>&lt;srcfiles&gt;</code>
-elements. These are <a href="../Types/fileset.html">FileSet</a>s,
-whereas multiple target files are specified using a nested
-<a href="../Types/mapper.html"><code>&lt;mapper&gt;</code></a> element.</p>
-<p>By default, the value of the property is set to <code>true</code> if
-the timestamp of the source file(s) is not more recent than the timestamp of
-the corresponding target file(s). You can set the value to something other
-than the default by specifying the <code>value</code> attribute.</p>
+<p>Sets a property if a target file or set of target files is more up-to-date than a source file or
+set of source files. A single source file is specified using the <var>srcfile</var> attribute. A set
+of source files is specified using the nested <code>&lt;srcfiles&gt;</code> elements. These
+are <a href="../Types/fileset.html">FileSet</a>s, whereas multiple target files are specified using
+a nested <a href="../Types/mapper.html"><code>&lt;mapper&gt;</code></a> element.</p>
+<p>By default, the value of the property is set to <q>true</q> if the timestamp of the source
+file(s) is not more recent than the timestamp of the corresponding target file(s). You can set the
+value to something other than the default by specifying the <var>value</var> attribute.</p>
 <p>If a <code>&lt;srcfiles&gt;</code> element is used, without also specifying
-a <code>&lt;mapper&gt;</code> element, the default behavior is to use a
-<a href="../Types/mapper.html#merge-mapper">merge mapper</a>, with the
-<code>to</code> attribute set to the value of the
-<code>targetfile</code> attribute.</p>
-<p>Normally, this task is used to set properties that are useful to avoid
-target execution depending on the relative age of the specified files.</p>
+a <code>&lt;mapper&gt;</code> element, the default behavior is to use
+a <a href="../Types/mapper.html#merge-mapper">merge mapper</a>, with the <var>to</var> attribute set
+to the value of the <var>targetfile</var> attribute.</p>
+<p>Normally, this task is used to set properties that are useful to avoid target execution depending
+on the relative age of the specified files.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">property</td>
-    <td valign="top">The name of the property to set.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>property</td>
+    <td>The name of the property to set.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The value to set the property to.</td>
-    <td valign="top" align="center">No; defaults to <code>true</code>.</td>
+    <td>value</td>
+    <td>The value to set the property to.</td>
+    <td>No; defaults to <q>true</q>.</td>
   </tr>
   <tr>
-    <td valign="top">srcfile</td>
-    <td valign="top">The file to check against the target file(s).</td>
-    <td valign="top" align="center">Yes, unless a nested
+    <td>srcfile</td>
+    <td>The file to check against the target file(s).</td>
+    <td>Yes, unless a nested
     <code>&lt;srcfiles&gt;</code> or <code>&lt;srcresources&gt;</code>
     element is present.</td>
   </tr>
   <tr>
-    <td valign="top">targetfile</td>
-    <td valign="top">The file for which we want to determine the status.</td>
-    <td valign="top" align="center">Yes, unless a nested
-      <code>&lt;mapper&gt;</code> element is present.</td>
+    <td>targetfile</td>
+    <td>The file for which we want to determine the status.</td>
+    <td>Yes, unless a nested <code>&lt;mapper&gt;</code> element is present.</td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
-<h4><a name="srcfiles">srcfiles</a></h4>
-<p>The nested <code>&lt;srcfiles&gt;</code> element is a
-<a href="../Types/fileset.html">fileset</a> and allows you to
-specify a set of files to check against the target file(s).</p>
+<h4 id="srcfiles">srcfiles</h4>
+<p>The nested <code>&lt;srcfiles&gt;</code> element is a <a href="../Types/fileset.html">fileset</a>
+and allows you to specify a set of files to check against the target file(s).</p>
 
-<p><strong>Note:</strong> You can specify either the <code>srcfile</code>
-attribute or nested <code>&lt;srcfiles&gt;</code> elements, but not both.
+<p><strong>Note</strong>: You can specify either the <var>srcfile</var> attribute or
+nested <code>&lt;srcfiles&gt;</code> elements, but not both.
 
-<p>Note that the task will completely ignore any directories that seem
-  to be matched by the srcfiles fileset, it will only consider normal
-  files.  If you need logic that applies to directories as well, use a
-  nested srcresource and a dirset (for example).</p>
+<p>Note that the task will completely ignore any directories that seem to be matched by
+the <var>srcfiles</var> fileset, it will only consider normal files.  If you need logic that applies
+to directories as well, use a nested <code>srcresources</code> element and a <code>dirset</code>
+(for example).</p>
 
-<h4><a name="srcresources">srcresources</a></h4>
-<p>The nested <code>&lt;srcresources&gt;</code> element is a <a
-href="../Types/resources.html#union">union</a> and allows you to
-specify a collection of resources to check against the target file(s).
-<em>Since Apache Ant 1.7</em></p>
+<h4 id="srcresources">srcresources</h4>
+<p><em>Since Apache Ant 1.7</em></p>
+<p>The nested <code>&lt;srcresources&gt;</code> element is
+a <a href="../Types/resources.html#union">union</a> and allows you to specify a collection of
+resources to check against the target file(s).</p>
 
-<h4><a name="mapper">mapper</a></h4>
-<p>The nested <code>&lt;mapper&gt;</code> element allows you to specify
-a set of target files to check for being up-to-date with respect to a
-set of source files.</p>
-   <p>
-      The mapper "to" attribute is relative to the target file, or to
-      the "dir" attribute of the nested srcfiles element.
-   </p>
-  <p>
-    <em>Since Ant 1.6.3</em>,
-    one can use a filenamemapper type in place of the mapper element.
-  </p>
+<h4 id="mapper">mapper</h4>
+<p>The nested <code>&lt;mapper&gt;</code> element allows you to specify a set of target files to
+check for being up-to-date with respect to a set of source files.</p>
+<p>The mapper <var>to</var> attribute is relative to the target file, or to the <var>dir</var>
+attribute of the nested <code>srcfiles</code> element.</p>
+<p><em>Since Ant 1.6.3</em>, one can use a <code>filenamemapper</code> type in place of the mapper
+element.</p>
 <h3>Examples</h3>
-<pre>  &lt;uptodate property=&quot;xmlBuild.notRequired&quot; targetfile=&quot;${deploy}\xmlClasses.jar&quot; &gt;
-    &lt;srcfiles dir= &quot;${src}/xml&quot; includes=&quot;**/*.dtd&quot;/&gt;
-  &lt;/uptodate&gt;</pre>
-<p>sets the property <code>xmlBuild.notRequired</code> to <code>true</code>
-if the <code>${deploy}/xmlClasses.jar</code> file is more up-to-date than
-any of the DTD files in the <code>${src}/xml</code> directory.</p>
+<p>Set the property <code>xmlBuild.notRequired</code> to <q>true</q> if
+the <samp>${deploy}/xmlClasses.jar</samp> file is more up-to-date than any of the DTD files in
+the <samp>${src}/xml</samp> directory.</p>
+<pre>
+&lt;uptodate property=&quot;xmlBuild.notRequired&quot; targetfile=&quot;${deploy}\xmlClasses.jar&quot;&gt;
+  &lt;srcfiles dir=&quot;${src}/xml&quot; includes=&quot;**/*.dtd&quot;/&gt;
+&lt;/uptodate&gt;</pre>
 <p>This can be written as:</p>
-<pre>  &lt;uptodate property=&quot;xmlBuild.notRequired&quot;&gt;
-    &lt;srcfiles dir= &quot;${src}/xml&quot; includes=&quot;**/*.dtd&quot;/&gt;
-    &lt;mapper type=&quot;merge&quot; to=&quot;${deploy}\xmlClasses.jar&quot;/&gt;
-  &lt;/uptodate&gt;</pre>
-as well.
+<pre>
+&lt;uptodate property=&quot;xmlBuild.notRequired&quot;&gt;
+  &lt;srcfiles dir= &quot;${src}/xml&quot; includes=&quot;**/*.dtd&quot;/&gt;
+  &lt;mapper type=&quot;merge&quot; to=&quot;${deploy}\xmlClasses.jar&quot;/&gt;
+&lt;/uptodate&gt;</pre>
+<p>as well.</p>
 
-The <code>xmlBuild.notRequired</code> property can then be used in a
-<code>&lt;target&gt;</code> tag's <code>unless</code> attribute to
-conditionally run that target. For example, running the following target:</p>
+<p>The <code>xmlBuild.notRequired</code> property can then be used in a <code>&lt;target&gt;</code>
+tag's <var>unless</var> attribute to conditionally run that target. For example, running the
+following target:</p>
 <pre>
 &lt;target name=&quot;xmlBuild&quot; depends=&quot;chkXmlBuild&quot; unless=&quot;xmlBuild.notRequired&quot;&gt;
   ...
-&lt;/target&gt;
+&lt;/target&gt;</pre>
+<p>will first run the <q>chkXmlBuild</q> target, which contains the <code>&lt;uptodate&gt;</code>
+task that determines whether <code>xmlBuild.notRequired</code> gets set. The property named in
+the <var>unless</var> attribute is then checked for being set/not set.  If it did get set (ie., the
+jar file is up-to-date), then the <q>xmlBuild</q> target won't be run.</p>
+
+<p>The following example shows a single source file being checked against a single target file:</p>
+<pre>
+&lt;uptodate property=&quot;isUpToDate&quot;
+          srcfile=&quot;/usr/local/bin/testit&quot;
+          targetfile=&quot;${build}/.flagfile&quot;/&gt;
 </pre>
-will first run the <code>chkXmlBuild</code> target, which contains
-the <code>&lt;uptodate&gt;</code> task that determines whether
-<code>xmlBuild.notRequired</code> gets set. The property named in
-the <code>unless</code> attribute is then checked for being set/not set.
-If it did get set (ie., the jar file is up-to-date),
-then the <code>xmlBuild</code> target won't be run.
-</p>
-
-<p> The following example shows a single source file being checked
-against a single target file:</p>
-<pre>  &lt;uptodate property=&quot;isUpToDate&quot;
-            srcfile=&quot;/usr/local/bin/testit&quot;
-            targetfile=&quot;${build}/.flagfile&quot;/&gt;
-</pre>
-<p>sets the property <code>isUpToDate</code> to <code>true</code>
-if <code>/usr/local/bin/testit</code> is not newer than
-<code>${build}/.flagfile</code>.</p>
-</p>
-  <p>
-    The following shows usage of a relative mapper.
-  </p>
-  <pre>
-    &lt;uptodate property="checkUptodate.uptodate"&gt;
-      &lt;srcfiles dir="src" includes="*"/&gt;
-      &lt;mapper type="merge" to="../dest/output.done"/&gt;
-    &lt;/uptodate&gt;
-    &lt;echo message="checkUptodate result: ${checkUptodate.uptodate}"/&gt;
-  </pre>
-  <p>
-    The previous example can be a bit confusing, so it may be better to
-    use absolute paths:
-  </p>
-  <pre>
-    &lt;property name="dest.dir" location="dest"/&gt;
-    &lt;uptodate property="checkUptodate.uptodate"&gt;
-      &lt;srcfiles dir="src" includes="*"/&gt;
-      &lt;mapper type="merge" to="${dest.dir}/output.done"/&gt;
-    &lt;/uptodate&gt;
-  </pre>
-
-
+<p>sets the property <code>isUpToDate</code> to <q>true</q> if <samp>/usr/local/bin/testit</samp> is
+not newer than <samp>${build}/.flagfile</samp>.</p>
+<p>The following shows usage of a relative mapper.</p>
+<pre>
+&lt;uptodate property="checkUptodate.uptodate"&gt;
+  &lt;srcfiles dir="src" includes="*"/&gt;
+  &lt;mapper type="merge" to="../dest/output.done"/&gt;
+&lt;/uptodate&gt;
+&lt;echo message="checkUptodate result: ${checkUptodate.uptodate}"/&gt;</pre>
+<p>The previous example can be a bit confusing, so it may be better to use absolute paths:</p>
+<pre>
+&lt;property name="dest.dir" location="dest"/&gt;
+&lt;uptodate property="checkUptodate.uptodate"&gt;
+  &lt;srcfiles dir="src" includes="*"/&gt;
+  &lt;mapper type="merge" to="${dest.dir}/output.done"/&gt;
+&lt;/uptodate&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/verifyjar.html b/manual/Tasks/verifyjar.html
index b2df426..3d35ebb 100644
--- a/manual/Tasks/verifyjar.html
+++ b/manual/Tasks/verifyjar.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,167 +15,155 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>VerifyJar Task</title>
 </head>
 
 <body>
 
-<h2><a name="verifyjar">VerifyJar</a></h2>
+<h2 id="verifyjar">VerifyJar</h2>
 <h3>Description</h3>
-<p>Verifies JAR files with the <tt>jarsigner</tt> command line tool.
-It will take a named file in the <tt>jar</tt> attribute. Nested paths are also
-supported
-</p>
-
+<p>Verifies JAR files with
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html"
+target="_top"><kbd>jarsigner</kbd></a> command line tool.  It will take a named file in
+the <var>jar</var> attribute. Nested paths are also supported.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">jar</td>
-    <td valign="top">the jar file to verify</td>
-    <td valign="top" align="center">Yes, unless nested paths have
-      been used.</td>
+    <td>jar</td>
+    <td>the jar file to verify</td>
+    <td>Yes, unless nested paths have been used</td>
   </tr>
   <tr>
-    <td valign="top">alias</td>
-    <td valign="top">the alias to verify under</td>
-    <td valign="top" align="center">Yes.</td>
+    <td>alias</td>
+    <td>the alias to verify under</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">storepass</td>
-    <td valign="top">password for keystore integrity.
+    <td>storepass</td>
+    <td>password for keystore integrity.
     Note that
     jarsigner does not read the password from stdin during
     verification, so the password must be send via a command line
     interface and may be visible to other users of the system.</td>
-    <td valign="top" align="center">No.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keystore</td>
-    <td valign="top">keystore location</td>
-    <td valign="top" align="center">No</td>
+    <td>keystore</td>
+    <td>keystore location</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">storetype</td>
-    <td valign="top">keystore type</td>
-    <td valign="top" align="center">No</td>
+    <td>storetype</td>
+    <td>keystore type</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keypass</td>
-    <td valign="top">password for private key (if different)</td>
-    <td valign="top" align="center">No</td>
+    <td>keypass</td>
+    <td>password for private key (if different)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">certificates</td>
-    <td valign="top">(true | false) display information about certificates</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>certificates</td>
+    <td>(<q>true|false</q>) display information about certificates</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">verbose</td>
-    <td valign="top">(true | false) verbose output when verifying</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>verbose</td>
+    <td>(<q>true|false</q>) verbose output when verifying</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">strict</td>
-    <td valign="top">(true | false) strict checking when verifying.<br/><em>since Ant 1.9.1</em>.</td>
-    <td valign="top" align="center">No; default false</td>
+    <td>strict</td>
+    <td>(<q>true|false</q>) strict checking when verifying.<br/><em>since Ant 1.9.1</em>.</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">maxmemory</td>
-    <td valign="top">Specifies the maximum memory the jarsigner VM will use. Specified in the
-                     style of standard java memory specs (e.g. 128m = 128 MBytes)</td>
-    <td valign="top" align="center">No</td>
+    <td>maxmemory</td>
+    <td>Specifies the maximum memory the <kbd>jarsigner</kbd> JVM will use. Specified in the style
+      of standard Java memory specs (e.g. <q>128m</q> = 128 MBytes)</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">executable</td>
-    <td valign="top">Specify a particular <code>jarsigner</code> executable
-      to use in place of the default binary (found in the same JDK as
-      Apache Ant is running in).<br/>
-      Must support the same command line options as the Sun JDK
-      jarsigner command.
-      <em>since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No</td>
-  </tr>  
+    <td>executable</td>
+    <td>Specify a particular <kbd>jarsigner</kbd> executable to use in place of the default binary
+      (found in the same JDK as Apache Ant is running in).<br/>  Must support the same command line
+      options as the Sun JDK <kbd>jarsigner</kbd> command.  <em>since Ant 1.8.0</em>.</td>
+    <td>No</td>
+  </tr>
   <tr>
-    <td valign="top">providername</td>
-    <td valign="top">name of a cryptographic service provider's name
+    <td>providername</td>
+    <td>name of a cryptographic service provider's name
       when listed in the security properties file.
-      <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+      <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">providerclass</td>
-    <td valign="top">name of a cryptographic service provider's master
+    <td>providerclass</td>
+    <td>name of a cryptographic service provider's master
       class file when the service provider is not listed in the security
       properties file.
-      <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+      <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">providerarg</td>
-    <td valign="top">Represents an optional string input argument for
+    <td>providerarg</td>
+    <td>Represents an optional string input argument for
       the constructor of provider_class_name. Ignored
       if <code>providerclass</code> is not set.
-      <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+      <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Parameters as nested elements</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">path</td>
-    <td valign="top">path of JAR files to verify. <em>since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
+    <td>path</td>
+    <td>path of JAR files to verify. <em>since Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">fileset</td>
-    <td valign="top">fileset of JAR files to verify. </td>
-    <td valign="top" align="center">No</td>
+    <td>fileset</td>
+    <td>fileset of JAR files to verify.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">sysproperty</td>
-    <td valign="top">JVM system properties, with the syntax of Ant
-    <a href="exec.html#env">environment variables</a> </td>
-    <td valign="top" align="center">No, and only one can be supplied</td>
+    <td>sysproperty</td>
+    <td>JVM system properties, with the syntax of Ant <a href="exec.html#env">environment
+      variables</a></td>
+    <td>No, and only one can be supplied</td>
   </tr>
   <tr>
-    <td valign="top">arg</td>
-    <td valign="top">Use this to specify a <code>keytool</code>
+    <td>arg</td>
+    <td>Use this to specify a <kbd>keytool</kbd>
     <a href="../using.html#arg">command line argument</a> not
     explicitly supported via an attribute.
-    <em>since Ant 1.9.14</em>.</td>
-    <td valign="top" align="center">No</td>
+    <em>since Ant 1.10.6</em>.</td>
+    <td>No</td>
   </tr>
 </table>
 
-
 <h3>Examples</h3>
-  <blockquote><pre>
+
+<p>Verify the <samp>ant.jar</samp> with alias <q>apache-group</q> accessing the keystore and private
+key via <q>secret</q> password.</p>
+<pre>
 &lt;verifyjar jar=&quot;${dist}/lib/ant.jar&quot;
-alias=&quot;apache-group&quot; storepass=&quot;secret&quot;/&gt;
-</pre></blockquote>
-<p>
-  verifies the ant.jar with alias &quot;apache-group&quot; accessing the
-  keystore and private key via &quot;secret&quot; password.
-</p>
-
-
+           alias=&quot;apache-group&quot; storepass=&quot;secret&quot;/&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/vss.html b/manual/Tasks/vss.html
index 2c0ed68..2c6dfa1 100644
--- a/manual/Tasks/vss.html
+++ b/manual/Tasks/vss.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,333 +15,313 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>Microsoft Visual SourceSafe(VSS) Tasks</title>
+<title>Microsoft Visual SourceSafe (VSS) Tasks</title>
 </head>
 <body>
 <h1>Microsoft Visual SourceSafe Tasks User Manual</h1>
 <p>by</p>
 <ul>
-    <li>Craig Cottingham</li>
-    <li>Andrew Everitt</li>
-    <li>Balazs Fejes 2</li>
-    <li><a href="mailto:Glenn_Twiggs@bmc.com">Glenn_Twiggs@bmc.com</a></li>
-    <li>Martin Poeschl (<a href="mailto:mpoeschl@marmot.at">mpoeschl@marmot.at</a>)</li>
-    <li>Phillip Wells</li>
-    <li>Jon Skeet (<a href="mailto:jon.skeet@peramon.com">jon.skeet@peramon.com</a>)</li>
-    <li>Nigel Magnay (<a href="mailto:nigel.magnay@parsec.co.uk">nigel.magnay@parsec.co.uk</a>)</li>
-    <li>Gary S. Weaver</li>
-    <li>Jesse Stockall</li>
- </ul>
-<hr>
+  <li>Craig Cottingham</li>
+  <li>Andrew Everitt</li>
+  <li>Balazs Fejes 2</li>
+  <li><a href="mailto:Glenn_Twiggs@bmc.com">Glenn_Twiggs@bmc.com</a></li>
+  <li>Martin Poeschl (<a href="mailto:mpoeschl@marmot.at">mpoeschl@marmot.at</a>)</li>
+  <li>Phillip Wells</li>
+  <li>Jon Skeet (<a href="mailto:jon.skeet@peramon.com">jon.skeet@peramon.com</a>)</li>
+  <li>Nigel Magnay (<a href="mailto:nigel.magnay@parsec.co.uk">nigel.magnay@parsec.co.uk</a>)</li>
+  <li>Gary S. Weaver</li>
+  <li>Jesse Stockall</li>
+</ul>
+<hr/>
 <h2>Contents</h2>
 <ul>
-    <li><a href="#intro">Introduction</a></li>
-    <li><a href="#tasks">The Tasks</a></li>
+  <li><a href="#intro">Introduction</a></li>
+  <li><a href="#tasks">The Tasks</a></li>
 </ul>
-<br>
-<h2><a name="intro">Introduction</a></h2>
-<p>These tasks provide an interface to the
-<a href="http://msdn.microsoft.com/ssafe/default.asp" target="_top">Microsoft Visual SourceSafe</a> SCM.
-The <code>org.apache.tools.ant.taskdefs.optional.vss</code> package consists of a simple framework to support
-vss functionality as well as some Apache Ant tasks encapsulating frequently used vss commands.
-Although it is possible to use these commands on the desktop,
-they were primarily intended to be used by automated build systems.</p>
-<p>
-If you get a CreateProcess IOError=2 when running these, it means
-that ss.exe was not found. Check to see if you can run it from the
-command line -you may need to alter your path, or set the <tt>ssdir</tt>
-property.
-<h2><a name="tasks">The Tasks</a></h2>
 
-<table border="0" cellspacing="0" cellpadding="3">
-    <tr>
-        <td><a href="#vssget">vssget</a></td>
-        <td>Retrieves a copy of the specified VSS file(s).</td>
-    </tr>
-    <tr>
-        <td><a href="#vsslabel">vsslabel</a></td>
-        <td>Assigns a label to the specified version or current version of a file or project.</td>
-    </tr>
-    <tr>
-        <td><a href="#vsshistory">vsshistory</a></td>
-        <td>Shows the history of a file or project in VSS.</td>
-    </tr>
-    <tr>
-        <td><a href="#vsscheckin">vsscheckin</a></td>
-        <td>Updates VSS with changes made to a checked out file, and unlocks the VSS master copy.</td>
-    </tr>
-    <tr>
-        <td><a href="#vsscheckout">vsscheckout</a></td>
-        <td>Copies a file from the current project to the current folder, for the purpose of editing.</td>
-    </tr>
-    <tr>
-        <td><a href="#vssadd">vssadd</a></td>
-        <td>Adds a new file into the VSS Archive</td>
-    </tr>
-    <tr>
-        <td><a href="#vsscp">vsscp</a></td>
-        <td>Change the current project being used in VSS</td>
-    </tr>
-    <tr>
-        <td><a href="#vsscreate">vsscreate</a></td>
-        <td>Creates a project in VSS.</td>
-    </tr>
+<br/>
+<h2 id="intro">Introduction</h2>
+<p>These tasks provide an interface to
+the <a href="https://msdn.microsoft.com/en-us/library/3h0544kx(v=vs.80).aspx"
+target="_top">Microsoft Visual SourceSafe</a> SCM.
+The <code class="code">org.apache.tools.ant.taskdefs.optional.vss</code> package consists of a
+simple framework to support VSS functionality as well as some Apache Ant tasks encapsulating
+frequently used VSS commands.  Although it is possible to use these commands on the desktop, they
+were primarily intended to be used by automated build systems.</p>
+<p>If you get a <code class="output">CreateProcess error=2</code> when running these, it means
+that <kbd>ss.exe</kbd> was not found. Check to see if you can run it from the command line&mdash;you
+may need to alter your path, or set the <var>ssdir</var> property.</p>
+<h2 id="tasks">The Tasks</h2>
+
+<table>
+  <tr><th scope="col">Task</th><th scope="col">Description</th></tr>
+  <tr>
+    <td><a href="#vssget">vssget</a></td>
+    <td>Retrieves a copy of the specified VSS file(s).</td>
+  </tr>
+  <tr>
+    <td><a href="#vsslabel">vsslabel</a></td>
+    <td>Assigns a label to the specified version or current version of a file or project.</td>
+  </tr>
+  <tr>
+    <td><a href="#vsshistory">vsshistory</a></td>
+    <td>Shows the history of a file or project in VSS.</td>
+  </tr>
+  <tr>
+    <td><a href="#vsscheckin">vsscheckin</a></td>
+    <td>Updates VSS with changes made to a checked out file, and unlocks the VSS master copy.</td>
+  </tr>
+  <tr>
+    <td><a href="#vsscheckout">vsscheckout</a></td>
+    <td>Copies a file from the current project to the current folder, for the purpose of editing.</td>
+  </tr>
+  <tr>
+    <td><a href="#vssadd">vssadd</a></td>
+    <td>Adds a new file into the VSS Archive</td>
+  </tr>
+  <tr>
+    <td><a href="#vsscp">vsscp</a></td>
+    <td>Change the current project being used in VSS</td>
+  </tr>
+  <tr>
+    <td><a href="#vsscreate">vsscreate</a></td>
+    <td>Creates a project in VSS.</td>
+  </tr>
 </table>
 
-<hr>
+<hr/>
 <h2>Task Descriptions</h2>
 
 <!-- VSSGET -->
 
-<h2><a name="vssget">VssGet</a></h2>
+<h2 id="vssget">VssGet</h2>
 <h3>Description</h3>
-Task to perform GET commands to Microsoft Visual SourceSafe.
-<p>If you specify two or more attributes from version, date and
-label only one will be used in the order version, date, label.</p>
+<p>Task to perform GET commands to Microsoft Visual SourceSafe.</p>
+<p>If you specify two or more attributes from version, date and label only one will be used in the
+order version, date, label.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-     <td>vsspath</td>
-     <td>SourceSafe path which specifies the project/file(s) you wish to
-         perform the action on.</td>
-     <td>Yes</td>
+    <td>vsspath</td>
+    <td>SourceSafe path which specifies the project/file(s) you wish to perform the action on.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-     <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
-     <td>No</td>
+    <td>login</td>
+    <td><q>username[,password]</q>&mdash;The username and password needed to get access to VSS. Note
+      that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang if you
+      leave the password out and VSS does not accept login without a password.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>localpath</td>
-     <td>Override the working directory and get to the specified path</td>
-     <td>No</td>
+    <td>localpath</td>
+    <td>Override the working directory and get to the specified path</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
+    <td>ssdir</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
   </tr>
   <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>writable</td>
-     <td>true or false; default false</td>
-     <td>No</td>
+    <td>writable</td>
+    <td><q>true|false</q></td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-     <td>recursive</td>
-     <td>true or false; default false. Note however that in the SourceSafe UI
-     , there is a setting accessed via Tools/Options/GeneralTab called
-     &quot;Act on projects recursively&quot;.  If this setting is checked,
-     then the recursive attribute is effectively ignored, and the get
-     will always be done recursively
-     </td>
-     <td>No</td>
+    <td>recursive</td>
+    <td><q>true|false</q>. Note however that in the SourceSafe UI there is a setting accessed
+      via <q>Tools/Options/GeneralTab</q> called <q>Act on projects recursively</q>.  If this
+      setting is checked, then the <var>recursive</var> attribute is effectively ignored, and get
+      will always be done recursively</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-     <td>version</td>
-     <td>a version number to get</td>
-     <td rowspan="3">No, only one of these allowed</td>
+    <td>version</td>
+    <td>a version number to get</td>
+    <td rowspan="3">No; only one of these may be used</td>
   </tr>
   <tr>
-     <td>date</td>
-     <td>a date stamp to get at</td>
+    <td>date</td>
+    <td class="left">a date stamp to get at</td>
   </tr>
   <tr>
-     <td>label</td>
-     <td>a label to get for</td>
+    <td>label</td>
+    <td class="left">a label to get for</td>
   </tr>
   <tr>
-     <td>quiet</td>
-     <td>suppress output (off by default)</td>
-     <td>No</td>
+    <td>quiet</td>
+    <td>suppress output</td>
+    <td>No; defaults to <q>off</q></td>
   </tr>
   <tr>
-     <td>autoresponse</td>
-     <td>What to respond with (sets the -I option). By default, -I- is
-     used; values of Y or N will be appended to this.</td>
-     <td>No</td>
+    <td>autoresponse</td>
+    <td>What to respond with (sets the <kbd>-I</kbd> option). By default, <kbd>-I-</kbd> is
+      used; values of <q>Y</q> or <q>N</q> will be appended to this.</td>
+    <td>No</td>
   </tr>
   <tr>
     <td>writablefiles</td>
-    <td>Behavior when local files are writable. Valid options are: <code>replace</code>, 
-        <code>skip</code> and <code>fail</code>; Defaults to <code>fail</code>
-        <br><code>skip</code> implies <code>failonerror=false</code></td>
-    <td>No</td>
+    <td>Behavior when local files are writable. Valid options are: <q>replace</q>, <q>skip</q>
+      and <q>fail</q>; <q>skip</q> implies <var>failonerror</var>=<q>false</q></td>
+    <td>No; defaults to <q>fail</q></td>
   </tr>
   <tr>
     <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
     <td>filetimestamp</td>
-    <td>Set the behavior for timestamps of local files. Valid options are <code>current</code>, 
-        <code>modified</code>, or <code>updated</code>. Defaults to <code>current</code>.</td> 
-    <td>No</td>
+    <td>Set the behavior for timestamps of local files. Valid options
+      are <q>current</q>, <q>modified</q>, or <q>updated</q>.</td>
+    <td>No; defaults to <q>current</q></td>
   </tr>
 </table>
 <p>Note that only one of version, date or label should be specified</p>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Perform a get on the VSS Project <samp>$/source/myproject</samp> using the username <q>me</q> and
+the password <q>mypassword</q>. That will recursively get the files which are
+labeled <q>Release1</q> and write them to the local directory <samp>C:\mysrc\myproject</samp>. The
+local files will be writable.</p>
+
 <pre>
 &lt;vssget localPath=&quot;C:\mysrc\myproject&quot;
         recursive=&quot;true&quot;
         label=&quot;Release1&quot;
         login=&quot;me,mypassword&quot;
         vsspath=&quot;$/source/aProject&quot;
-        writable=&quot;true&quot;/&gt;
-</pre>
-</blockquote>
-<p>Does a get on the VSS-Project <i>$/source/myproject</i> using the username
-<i>me</i> and the password <i>mypassword</i>. It will recursively get the files
-which are labeled <i>Release1</i> and write them to the local directory
-<i>C:\mysrc\myproject</i>. The local files will be writable.</p>
-<hr>
+        writable=&quot;true&quot;/&gt;</pre>
 
+<hr/>
 <!-- VSSLABEL -->
-
-<h2><a name="vsslabel">VssLabel</a></h2>
+<h2 id="vsslabel">VssLabel</h2>
 <h3>Description</h3>
-Task to perform LABEL commands to Microsoft Visual SourceSafe.
-<p>Assigns a label to the specified version or current version of a file or
-project.</p>
+<p>Task to perform LABEL commands to Microsoft Visual SourceSafe.</p>
+<p>Assigns a label to the specified version or current version of a file or project.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-   <tr>
-     <th>Attribute</th>
-     <th>Values</th>
-     <th>Required</th>
-   </tr>
+<table class="attr">
   <tr>
-     <td>vsspath</td>
-     <td>SourceSafe path which specifies the project/file(s) you wish to
-         perform the action on.</td>
-     <td>Yes</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-     <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
-     <td>No</td>
+    <td>vsspath</td>
+    <td>SourceSafe path which specifies the project/file(s) you wish to perform the action on.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-     <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
+    <td>login</td>
+    <td><q>username[,password]</q>&mdash;The username and password needed to get access to VSS. Note
+      that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang if you
+      leave the password out and VSS does not accept login without a password.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
+    <td>ssdir</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
   </tr>
-   <tr>
-      <td>label</td>
-      <td>A label to apply to the hierarchy</td>
-      <td>Yes</td>
-   </tr>
-   <tr>
-      <td>version</td>
-      <td>An existing file or project version to label. By default the current
-      version is labeled.</td>
-      <td>No</td>
-   </tr>
-   <tr>
-      <td>comment</td>
-      <td>The comment to use for this label. Empty or '-' for no comment.</td>
-      <td>No</td>
-   </tr>
   <tr>
-     <td>autoresponse</td>
-     <td>What to respond with (sets the -I option). By default, -I- is
-     used; values of Y or N will be appended to this.</td>
-     <td>No</td>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>label</td>
+    <td>A label to apply to the hierarchy</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>version</td>
+    <td>An existing file or project version to label. By default the current version is
+      labeled.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>The comment to use for this label. Empty or <q>-</q> for no comment.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>autoresponse</td>
+    <td>What to respond with (sets the <kbd>-I</kbd> option). By default, <kbd>-I-</kbd> is
+      used; values of <q>Y</q> or <q>N</q> will be appended to this.</td>
+    <td>No</td>
   </tr>
   <tr>
     <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
+
+<p>Label the current version of the VSS project <samp>$/source/aProject</samp> with the
+label <q>Release1</q> using the username <q>me</q> and the password <q>mypassword</q>.</p>
+
 <pre>
 &lt;vsslabel vsspath=&quot;$/source/aProject&quot;
           login=&quot;me,mypassword&quot;
-          label=&quot;Release1&quot;/&gt;
-</pre>
-</blockquote>
-<p>Labels the current version of the VSS project <i>$/source/aProject</i> with
-the label <i>Release1</i> using the username <i>me</i> and the password
-<i>mypassword</i>.
-</p>
-<blockquote>
+          label=&quot;Release1&quot;/&gt;</pre>
+
+<p>Label version 4 of the VSS file <samp>$/source/aProject/myfile.txt</samp> with the
+label <q>1.03.004</q>. If this version already has a label, the operation (and the build) will
+fail.</p>
+
 <pre>
 &lt;vsslabel vsspath=&quot;$/source/aProject/myfile.txt&quot;
           version=&quot;4&quot;
-          label=&quot;1.03.004&quot;/&gt;
-</pre>
-</blockquote>
-<p>Labels version 4 of the VSS file <i>$/source/aProject/myfile.txt</i> with the
-label <i>1.03.004</i>. If this version already has a label, the operation (and
-the build) will fail.
-</p>
-<hr>
+          label=&quot;1.03.004&quot;/&gt;</pre>
 
+<hr/>
 <!-- VSSHISTORY -->
-
-<h2><a name="vsshistory">VssHistory</a></h2>
+<h2 id="vsshistory">VssHistory</h2>
 <h3>Description</h3>
 Task to perform HISTORY commands to Microsoft Visual SourceSafe.
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-     <td>vsspath</td>
-     <td>SourceSafe path which specifies the project/file(s) you wish to
-         perform the action on.</td>
-     <td>Yes</td>
+    <td>vsspath</td>
+    <td>SourceSafe path which specifies the project/file(s) you wish to perform the action on.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-     <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
-     <td>No</td>
+    <td>login</td>
+    <td><q>username[,password]</q>&mdash;The username and password needed to get access to VSS. Note
+      that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang if you
+      leave the password out and VSS does not accept login without a password.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
+    <td>ssdir</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
   </tr>
   <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
   </tr>
   <tr>
     <td>fromDate</td>
@@ -354,10 +335,10 @@
   </tr>
   <tr>
     <td>dateFormat</td>
-    <td>Format of dates in fromDate and toDate. Used when calculating dates with
-      the numdays attribute. This string uses the formatting rules of SimpleDateFormat.
-      Defaults to DateFormat.SHORT.</td>
-    <td>No</td>
+    <td>Format of dates in <var>fromDate</var> and <var>toDate</var>. Used when calculating dates
+      with the <var>numdays</var> attribute. This string uses the formatting rules of
+      SimpleDateFormat.</td>
+    <td>No; defaults to <code>DateFormat.SHORT</code></td>
   </tr>
   <tr>
     <td>fromLabel</td>
@@ -381,13 +362,13 @@
   </tr>
   <tr>
     <td>recursive</td>
-    <td>true or false</td>
+    <td><q>true|false</q></td>
     <td>No</td>
   </tr>
   <tr>
     <td>style</td>
-    <td>brief, codediff, default or nofile. The default is default.</td>
-    <td>No</td>
+    <td><q>brief</q>, <q>codediff</q>, <q>default</q> or <q>nofile</q>.</td>
+    <td>No; defaults to <q>default</q></td>
   </tr>
   <tr>
     <td>user</td>
@@ -396,43 +377,41 @@
   </tr>
   <tr>
     <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 
 <h4>Specifying the time-frame</h4>
 <p>There are different ways to specify what time-frame you wish to evaluate:</p>
 <ul>
-  <li>Changes between two dates: Specify both <code>fromDate</code> and <code>toDate</code> </li>
-  <li>Changes before a date: Specify <code>toDate</code></li>
-  <li>Changes after a date: Specify <code>fromDate</code></li>
-  <li>Changes X Days before a date: Specify <code>toDate</code> and (negative!) <code>numDays</code></li>
-  <li>Changes X Days after a date: Specify <code>fromDate</code> and <code>numDays</code></li>
+  <li>Changes between two dates: Specify both <var>fromDate</var> and <var>toDate</var></li>
+  <li>Changes before a date: Specify <var>toDate</var></li>
+  <li>Changes after a date: Specify <var>fromDate</var></li>
+  <li>Changes X Days before a date: Specify <var>toDate</var> and (negative!) <var>numDays</var></li>
+  <li>Changes X Days after a date: Specify <var>fromDate</var> and <var>numDays</var></li>
 </ul>
 
-
 <h3>Examples</h3>
-<blockquote>
-  <pre>
+
+<p>Show all changes between <q>Release1</q> and <q>Release2</q>.</p>
+
+<pre>
 &lt;vsshistory vsspath=&quot;$/myProject&quot; recursive=&quot;true&quot;
             fromLabel=&quot;Release1&quot;
-            toLabel=&quot;Release2&quot;/&gt;
-</pre>
-</blockquote>
-<p>Shows all changes between &quot;Release1&quot; and &quot;Release2&quot;.</p>
+            toLabel=&quot;Release2&quot;/&gt;</pre>
 
-<blockquote>
-  <pre>
+<p>Show all changes between January 1st 2001 and March 31st 2001 (in Germany, date must be specified
+according to your locale).</p>
+
+<pre>
 &lt;vsshistory vsspath=&quot;$/myProject&quot; recursive=&quot;true&quot;
             fromDate=&quot;01.01.2001&quot;
-            toDate=&quot;31.03.2001&quot;/&gt;
-</pre>
-</blockquote>
-<p>Shows all changes between January 1st 2001 and March 31st 2001 (in Germany, date must be specified according to your locale).</p>
+            toDate=&quot;31.03.2001&quot;/&gt;</pre>
 
-<blockquote>
-  <pre>
+<p>Shows all changes in the last fortnight.</p>
+
+<pre>
 &lt;tstamp&gt;
   &lt;format property=&quot;to.tstamp&quot; pattern=&quot;M-d-yy;h:mma&quot;/&gt;
 &lt;/tstamp&gt;
@@ -440,36 +419,30 @@
 &lt;vsshistory vsspath=&quot;$/myProject&quot; recursive=&quot;true&quot;
             numDays=&quot;-14&quot;
             dateFormat=&quot;M-d-yy;h:mma&quot;
-            toDate=&quot;${to.tstamp}&quot;/&gt;
-</pre>
-</blockquote>
-<p>Shows all changes in the 14 days before today.</p>
-<hr>
+            toDate=&quot;${to.tstamp}&quot;/&gt;</pre>
 
+<hr/>
 <!-- VSSCHECKIN -->
-
-<h2><a name="vsscheckin">VssCheckin</a></h2>
+<h2 id="vsscheckin">VssCheckin</h2>
 <h3>Description</h3>
-Task to perform CHECKIN commands to Microsoft Visual SourceSafe.
+<p>Task to perform CHECKIN commands to Microsoft Visual SourceSafe.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
      <td>vsspath</td>
-     <td>SourceSafe path which specifies the project/file(s) you wish to
-         perform the action on.</td>
+     <td>SourceSafe path which specifies the project/file(s) you wish to perform the action on.</td>
      <td>Yes</td>
   </tr>
   <tr>
      <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
+     <td><q>username[,password]</q>&mdash;The username and password needed to get access to
+       VSS. Note that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang
+       if you leave the password out and VSS does not accept login without a password.</td>
      <td>No</td>
   </tr>
   <tr>
@@ -479,303 +452,285 @@
   </tr>
   <tr>
      <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
+     <td>directory where <kbd>ss.exe</kbd> resides.</td>
+     <td>No; by default expected to be in <code>PATH</code></td>
   </tr>
   <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>writable</td>
-     <td>true or false</td>
-     <td>No</td>
+    <td>writable</td>
+    <td><q>true|false</q></td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>recursive</td>
-     <td>true or false</td>
-     <td>No</td>
+    <td>recursive</td>
+    <td><q>true|false</q></td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>comment</td>
-     <td>Comment to use for the files that where checked in.</td>
-     <td>No</td>
+    <td>comment</td>
+    <td>Comment to use for the files that where checked in.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>autoresponse</td>
-     <td>'Y', 'N' or empty. Specify how to reply to questions from VSS.</td>
-     <td>No</td>
+    <td>autoresponse</td>
+    <td><q>Y</q>, <q>N</q> or empty. Specify how to reply to questions from VSS.</td>
+    <td>No</td>
   </tr>
   <tr>
     <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote>
+
+<p>Check in the file(s) named <samp>test*</samp> in the project <samp>$/test</samp> using the local
+directory <samp>D:\build</samp>.</p>
+
 <pre>
 &lt;vsscheckin vsspath=&quot;$/test/test*&quot;
             localpath=&quot;D:\build\&quot;
             comment=&quot;Modified by automatic build&quot;/&gt;
 </pre>
-</blockquote>
-<p>Checks in the file(s) named <i>test*</i> in the project <i>$/test</i> using
-the local directory <i>D:\build</i>.</p>
-<hr>
 
+<hr/>
 <!-- VSSCHECKOUT -->
-
-<h2><a name="vsscheckout">VssCheckout</a></h2>
+<h2 id="vsscheckout">VssCheckout</h2>
 <h3>Description</h3>
-Task to perform CHECKOUT commands to Microsoft Visual SourceSafe.
-<p>If you specify two or more attributes from version, date and
-label only one will be used in the order version, date, label.</p>
+<p>Task to perform CHECKOUT commands to Microsoft Visual SourceSafe.</p>
+<p>If you specify two or more attributes from <var>version</var>, <var>date</var>
+and <var>label</var> only one will be used in the
+order <var>version</var>, <var>date</var>, <var>label</var>.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-     <td>vsspath</td>
-     <td>SourceSafe path which specifies the project/file(s) you wish to
-         perform the action on.</td>
-     <td>Yes</td>
+    <td>vsspath</td>
+    <td>SourceSafe path which specifies the project/file(s) you wish to perform the action on.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-     <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
-     <td>No</td>
+    <td>login</td>
+    <td><q>username[,password]</q>&mdash;The username and password needed to get access to VSS. Note
+      that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang if you
+      leave the password out and VSS does not accept login without a password.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>localpath</td>
-     <td>Override the working directory and get to the specified path</td>
-     <td>No</td>
+    <td>localpath</td>
+    <td>Override the working directory and get to the specified path</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
+    <td>ssdir</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
   </tr>
   <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>writable</td>
-     <td>true or false</td>
-     <td>No</td>
+    <td>writable</td>
+    <td><q>true|false</q></td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>recursive</td>
-     <td>true or false</td>
-     <td>No</td>
+    <td>recursive</td>
+    <td><q>true|false</q></td>
+    <td>No</td>
   </tr>
   <tr>
-     <td>version</td>
-     <td>a version number to get</td>
-     <td rowspan="3">No, only one of these allowed</td>
+    <td>version</td>
+    <td>a version number to get</td>
+    <td rowspan="3">No; only one of these may be used</td>
   </tr>
   <tr>
-     <td>date</td>
-     <td>a date stamp to get at</td>
+    <td>date</td>
+    <td class="left">a date stamp to get at</td>
   </tr>
   <tr>
-     <td>label</td>
-     <td>a label to get for</td>
+    <td>label</td>
+    <td class="left">a label to get for</td>
   </tr>
   <tr>
     <td>writablefiles</td>
-    <td>Behavior when local files are writable. Valid options are: <code>replace</code>, 
-        <code>skip</code> and <code>fail</code>; Defaults to <code>fail</code>
-        <br><code>skip</code> implies <code>failonerror=false</code></td>
-    <td>No</td>
+    <td>Behavior when local files are writable. Valid options are: <q>replace</q>, <q>skip</q>
+      and <q>fail</q>; <q>skip</q> implies <var>failonerror</var>=<q>false</q></td>
+    <td>No; defaults to <q>fail</q></td>
   </tr>
   <tr>
     <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
     <td>filetimestamp</td>
-    <td>Set the behavior for timestamps of local files. Valid options are <code>current</code>, 
-        <code>modified</code>, or <code>updated</code>. Defaults to <code>current</code>.</td> 
-    <td>No</td>
+    <td>Set the behavior for timestamps of local files. Valid options
+      are <q>current</q>, <q>modified</q>, or <q>updated</q>.</td>
+    <td>No; defaults to <q>current</q></td>
   </tr>
   <tr>
     <td>getlocalcopy</td>
-    <td>Set the behavior to retrieve local copies of the files. Defaults to true.</td> 
-    <td>No</td>
+    <td>Set the behavior to retrieve local copies of the files.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote>
+
+<p>Check out the project <samp>$/test</samp> recursively to the directory <samp>D:\build</samp>.</p>
+
 <pre>
 &lt;vsscheckout vsspath=&quot;$/test&quot;
              localpath=&quot;D:\build&quot;
              recursive=&quot;true&quot;
-             login=&quot;me,mypass&quot;/&gt;
-</pre>
-</blockquote>
-<p>Does a recursive checkout of the project <i>$/test</i> to the directory D:\build.
-</p>
-<hr>
+             login=&quot;me,mypass&quot;/&gt;</pre>
 
+<hr/>
 <!-- VSSADD -->
-
-<h2><a name="vssadd">VssAdd</a></h2>
+<h2 id="vssadd">VssAdd</h2>
 <h3>Description</h3>
 Task to perform ADD commands to Microsoft Visual SourceSafe.
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-     <td>localpath</td>
-     <td>Specify the local file(s) to add to VSS</td>
-     <td>Yes</td>
-  </tr>
-  <tr>
-     <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>writable</td>
-     <td>true or false</td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>recursive</td>
-     <td>true or false</td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>comment</td>
-     <td>Comment to use for the files that where checked in.</td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>autoresponse</td>
-     <td>'Y', 'N' or empty. Specify how to reply to questions from VSS.</td>
-     <td>No</td>
-  </tr>
-  <tr>
-    <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
-  </tr>
-</table>
-
-<h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;vssadd localpath=&quot;D:\build\build.00012.zip&quot;
-            comment=&quot;Added by automatic build&quot;/&gt;
-</pre>
-</blockquote>
-<p>Add the file named build.00012.zip into the project current working
-directory (see vsscp).</p>
-<hr>
-
-<!-- VSSCP -->
-
-<h2><a name="vsscp">VssCp</a></h2>
-<h3>Description</h3>
-<p>Task to perform CP (Change Project) commands to Microsoft Visual SourceSafe.</p>
-<p>This task is typically used before a VssAdd in order to set the target project</p>
-<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-  <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
-  </tr>
-  <tr>
-     <td>vsspath</td>
-     <td>SourceSafe path which specifies the project you wish to
-         make the current project.</td>
-     <td>Yes</td>
-  </tr>
-  <tr>
-     <td>login</td>
-     <td>username[,password] - The username and password needed to get access
-         to VSS. Note that you may need to specify both (if you have a password) -
-         Ant/VSS will hang if you leave the password out and VSS does not accept
-         login without a password. </td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>ssdir</td>
-     <td>directory where <code>ss.exe</code> resides. By default the
-         task expects it to be in the PATH.</td>
-     <td>No</td>
-  </tr>
-  <tr>
-     <td>serverPath</td>
-     <td>directory where <code>srcsafe.ini</code> resides.</td>
-     <td>No</td>
-  </tr>
-  <tr>
-    <td>failonerror</td>
-    <td>Stop the buildprocess if ss.exe exits with a returncode of 100. Defaults to true</td>
-    <td>No</td>
-  </tr>
-</table>
-
-<h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;vsscp vsspath=&quot;$/Projects/ant&quot;/&gt;
-</pre>
-</blockquote>
-<p>Sets the current VSS project to <i>$/Projects/ant</i>.</p>
-<hr>
-
-<!-- VSSCREATE -->
-
- <h2><a name="vsscreate">VssCreate</a></h2>
- <h3>Description</h3>
- Task to perform CREATE commands to Microsoft Visual Source Safe.
- <p>Creates a new project in VSS.</p>
-<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-  <tr>
-    <th>Attribute</th>
-    <th>Values</th>
-    <th>Required</th>
+    <td>localpath</td>
+    <td>Specify the local file(s) to add to VSS</td>
+    <td>Yes</td>
   </tr>
   <tr>
     <td>login</td>
-    <td>username,password</td>
+    <td><q>username[,password]</q>&mdash;The username and password needed to get access to VSS. Note
+      that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang if you
+      leave the password out and VSS does not accept login without a password.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>ssdir</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
+  </tr>
+  <tr>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>writable</td>
+    <td><q>true|false</q></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>recursive</td>
+    <td><q>true|false</q></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>comment</td>
+    <td>Comment to use for the files that where checked in.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>autoresponse</td>
+    <td><q>Y</q>, <q>N</q> or empty. Specify how to reply to questions from VSS.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerror</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q>.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+</table>
+
+<h3>Examples</h3>
+
+<p>Add the file named <samp>build.00012.zip</samp> into the project current working directory
+(see <code>vsscp</code>).</p>
+
+<pre>
+&lt;vssadd localpath=&quot;D:\build\build.00012.zip&quot;
+        comment=&quot;Added by automatic build&quot;/&gt;</pre>
+
+<hr/>
+<!-- VSSCP -->
+<h2 id="vsscp">VssCp</h2>
+<h3>Description</h3>
+<p>Task to perform CP (Change Project) commands to Microsoft Visual SourceSafe.</p>
+<p>This task is typically used before a <code>VssAdd</code> in order to set the target project</p>
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>vsspath</td>
+    <td>SourceSafe path which specifies the project you wish to make the current project.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>login</td>
+    <td><q>username[,password]</q>&mdash;The username and password needed to get access to VSS. Note
+      that you may need to specify both (if you have a password)&mdash;Ant/VSS will hang if you
+      leave the password out and VSS does not accept login without a password.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>ssdir</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
+  </tr>
+  <tr>
+    <td>serverPath</td>
+    <td>directory where <samp>srcsafe.ini</samp> resides.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>failonerror</td>
+    <td>Stop the build process if <kbd>ss.exe</kbd> exits with a return code <q>100</q>.</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+</table>
+
+<h3>Examples</h3>
+
+<p>Set the current VSS project to <samp>$/Projects/ant</samp>.</p>
+
+<pre>&lt;vsscp vsspath=&quot;$/Projects/ant&quot;/&gt;</pre>
+
+<hr/>
+<!-- VSSCREATE -->
+<h2 id="vsscreate">VssCreate</h2>
+<h3>Description</h3>
+<p>Task to perform CREATE commands to Microsoft Visual Source Safe.</p>
+<p>Creates a new project in VSS.</p>
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Values</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>login</td>
+    <td><q>username,password</q></td>
     <td>No</td>
   </tr>
   <tr>
@@ -785,39 +740,36 @@
   </tr>
   <tr>
     <td>ssdir</td>
-    <td>directory where <code>ss.exe</code> resides. By default the task expects it to be in the PATH.</td>
-    <td>No</td>
+    <td>directory where <kbd>ss.exe</kbd> resides.</td>
+    <td>No; by default expected to be in <code>PATH</code></td>
   </tr>
   <tr>
     <td>quiet</td>
-    <td>suppress output (off by default)</td>
-    <td>No</td>
-   </tr>
+    <td>suppress output</td>
+    <td>No; defaults to <q>off</q></td>
+  </tr>
   <tr>
     <td>failOnError</td>
-    <td>fail if there is an error creating the project (true by default)</td>
-    <td>No</td>
+    <td>fail if there is an error creating the project.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
     <td>autoresponse</td>
-    <td>What to respond with (sets the -I option). By default, -I- is used; values of Y or N will be appended to this.</td>
+    <td>What to respond with (sets the <kbd>-I</kbd> option). By default, <kbd>-I-</kbd> is
+      used; values of <q>Y</q> or <q>N</q> will be appended to this.</td>
     <td>No</td>
   </tr>
   <tr>
     <td>comment</td>
-    <td>The comment to use for this label. Empty or '-' for no comment.</td>
+    <td>The comment to use for this label. Empty or <q>-</q> for no comment.</td>
     <td>No</td>
   </tr>
 </table>
 <h3>Examples</h3>
-<blockquote>
-<pre>
-&lt;vsscreate vsspath=&quot;$/existingProject/newProject&quot;/&gt;
-</pre>
-</blockquote>
-<p>Creates the VSS-Project <i>$/existingProject/newProject</i>.</p>
-<hr>
 
-<!-- Footer -->
+<p>Create the VSS Project <samp>$/existingProject/newProject</samp>.</p>
+
+<pre>&lt;vsscreate vsspath=&quot;$/existingProject/newProject&quot;/&gt;</pre>
+
 </body>
 </html>
diff --git a/manual/Tasks/waitfor.html b/manual/Tasks/waitfor.html
index 54ff8ed..2f6056f 100644
--- a/manual/Tasks/waitfor.html
+++ b/manual/Tasks/waitfor.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>WaitFor Task</title>
 </head>
@@ -26,108 +26,98 @@
 
 <h2>Waitfor</h2>
 <h3>Description</h3>
-<p>Blocks execution until a set of specified conditions become true. This is intended
-  to be used with the <a href="parallel.html">parallel</a> task to
-  synchronize a set of processes.</p>
-<p>The conditions to wait for are defined in <a href="waitfor.html#nested">nested elements</a>,
-if multiple conditions are specified, then the task will wait until all conditions are true..</p>
-<p></p>
-<p>If both maxwait and maxwaitunit are not specified, the maxwait is 3 minutes (180000 milliseconds).</p>
-<p>If the <code>timeoutproperty</code> attribute has been set, a
-property of that name will be created if the condition didn't come
-true within the specified time.</p>
+<p>Blocks execution until a set of specified conditions become true. This is intended to be used
+with the <a href="parallel.html">parallel</a> task to synchronize a set of processes.</p>
+<p>The conditions to wait for are defined in <a href="waitfor.html#nested">nested elements</a>, if
+multiple conditions are specified, then the task will wait until all conditions are true.</p>
+<p>If both <var>maxwait</var> and <var>maxwaitunit</var> are not specified,
+default <var>maxwait</var> is 3 minutes (180000 milliseconds).</p>
+<p>If the <var>timeoutproperty</var> attribute has been set, a property of that name will be created
+if the condition didn't come true within the specified time.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">maxwait</td>
-    <td valign="top">The maximum amount of time to wait for all the required conditions
-      to become true before failing the task. Defaults to 180000 maxwaitunits.</td>
-    <td valign="top" align="center">No</td>
+    <td>maxwait</td>
+    <td>The maximum amount of time to wait for all the required conditions to become true before
+      failing the task.</td>
+    <td>No; defaults to 180000 <var>maxwaitunit</var>s</td>
   </tr>
   <tr>
-    <td valign="top">maxwaitunit</td>
-    <td valign="top">The unit of time that must be used to interpret the value of the
-    maxwait attribute.  Defaults to millisecond.
-                     Valid Values are
-                     <ul>
-                        <li>millisecond</li>
-                        <li>second</li>
-                        <li>minute</li>
-                        <li>hour</li>
-                        <li>day</li>
-                        <li>week</li>
-                     </ul>
-      </td>
-    <td valign="top" align="center">No</td>
-  </tr>
-  <tr>
-    <td valign="top">checkevery</td>
-    <td valign="top">The amount of time to wait between each test of the conditions.
-      Defaults to 500 checkeveryunits.</td>
-    <td valign="top" align="center">No</td>
-  </tr>
-  <tr>
-    <td valign="top">checkeveryunit</td>
-    <td valign="top">The unit of time that must be used to interpret the value of the
-    checkevery attribute.  Defaults to millisecond.
-                     Valid Values are
-                     <ul>
-                        <li>millisecond</li>
-                        <li>second</li>
-                        <li>minute</li>
-                        <li>hour</li>
-                        <li>day</li>
-                        <li>week</li>
-                     </ul>
+    <td>maxwaitunit</td>
+    <td>The unit of time that must be used to interpret the value of the <var>maxwait</var>
+      attribute.  Valid values are
+      <ul>
+        <li><q>millisecond</q></li>
+        <li><q>second</q></li>
+        <li><q>minute</q></li>
+        <li><q>hour</q></li>
+        <li><q>day</q></li>
+        <li><q>week</q></li>
+      </ul>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to <q>millisecond</q></td>
   </tr>
   <tr>
-    <td valign="top">timeoutproperty</td>
-    <td valign="top">the name of the property to set if maxwait has
-      been exceeded.</td>
-    <td valign="top" align="center">No</td>
+    <td>checkevery</td>
+    <td>The amount of time to wait between each test of the conditions.</td>
+    <td>No; defaults to 500 <var>checkeveryunit</var>s</td>
+  </tr>
+  <tr>
+    <td>checkeveryunit</td>
+    <td>The unit of time that must be used to interpret the value of the <var>checkevery</var>
+      attribute.  Valid values are
+      <ul>
+        <li><q>millisecond</q></li>
+        <li><q>second</q></li>
+        <li><q>minute</q></li>
+        <li><q>hour</q></li>
+        <li><q>day</q></li>
+        <li><q>week</q></li>
+      </ul>
+    </td>
+    <td>No; defaults to <q>millisecond</q></td>
+  </tr>
+  <tr>
+    <td>timeoutproperty</td>
+    <td>the name of the property to set if <var>maxwait</var> has been exceeded.</td>
+    <td>No</td>
   </tr>
 </table>
-<h3><a name="nested">Nested Elements</a></h3>
 
-<p>The available conditions that satisfy the
-<code>&lt;waitfor&gt;</code> task are the same as those for the
-<a href="condition.html"><code>&lt;condition&gt;</code></a> task. See
-<a href="conditions.html">here</a> for the full list.</p>
+<h3 id="nested">Parameters specified as nested elements</h3>
+<p>The available conditions that satisfy the <code>&lt;waitfor&gt;</code> task are the same as those
+for the <a href="condition.html"><code>&lt;condition&gt;</code></a>
+task. See <a href="conditions.html">here</a> for the full list.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
-&lt;waitfor maxwait="30" maxwaitunit="second"&gt;
-        &lt;available file="errors.log"/&gt;
-&lt;/waitfor&gt;
-</pre></blockquote>
-<p>waits up to 30 seconds for a file called errors.log to appear.</p>
-<blockquote><pre>
-&lt;waitfor maxwait="3" maxwaitunit="minute" checkevery="500"&gt;
-        &lt;http url="http://localhost/myapp/index.html"/&gt;
-&lt;/waitfor&gt;
-</pre></blockquote>
-<p>waits up to 3 minutes (and checks every 500 milliseconds) for a web server on localhost
-  to serve up the specified URL.</p>
-<blockquote><pre>
-&lt;waitfor maxwait="10" maxwaitunit="second"&gt;
-        &lt;and&gt;
-            &lt;socket server="dbserver" port="1521"/&gt;
-            &lt;http url="http://webserver/mypage.html"/&gt;
-        &lt;/and&gt;
-&lt;/waitfor&gt;
-</pre></blockquote>
-<p>waits up to 10 seconds for a server on the dbserver machine to begin listening
-  on port 1521 and for the http://webserver/mypage.html web page
-  to become available.</p>
 
+<p>Wait up to 30 seconds for a file called <samp>errors.log</samp> to appear.</p>
+<pre>
+&lt;waitfor maxwait="30" maxwaitunit="second"&gt;
+    &lt;available file="errors.log"/&gt;
+&lt;/waitfor&gt;</pre>
+
+<p>Wait up to 3 minutes (and checks every 500 milliseconds) for a web server
+on <samp>localhost</samp> to serve up the specified URL.</p>
+<pre>
+&lt;waitfor maxwait="3" maxwaitunit="minute" checkevery="500"&gt;
+    &lt;http url="https://localhost/myapp/index.html"/&gt;
+&lt;/waitfor&gt;</pre>
+
+<p>Wait up to 10 seconds for a server on the <samp>dbserver</samp> machine to begin listening on
+port 1521 and for the <samp>https://webserver/mypage.html</samp> web page to become available.</p>
+<pre>
+&lt;waitfor maxwait="10" maxwaitunit="second"&gt;
+    &lt;and&gt;
+        &lt;socket server="dbserver" port="1521"/&gt;
+        &lt;http url="https://webserver/mypage.html"/&gt;
+    &lt;/and&gt;
+&lt;/waitfor&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Tasks/war.html b/manual/Tasks/war.html
index b3c9096..6357501 100644
--- a/manual/Tasks/war.html
+++ b/manual/Tasks/war.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,267 +15,231 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>WAR Task</title>
 </head>
 
 <body>
 
-<h2><a name="war">War</a></h2>
+<h2 id="war">War</h2>
 <h3>Description</h3>
-<p>An extension of the <a href="jar.html">Jar</a> task with special
-treatment for files that should end up in the
-<code>WEB-INF/lib</code>, <code>WEB-INF/classes</code> or
-<code>WEB-INF</code> directories of the Web Application Archive.</p>
-<p>(The War task is a shortcut for specifying the particular layout of a WAR file.
-The same thing can be accomplished by using the <i>prefix</i> and <i>fullpath</i>
-attributes of zipfilesets in a Zip or Jar task.)</p>
-<p>The extended zipfileset element from the zip task
-    (with attributes <i>prefix</i>, <i>fullpath</i>, and <i>src</i>)
-    is available in the War task. The task is also resource-enabled
-    and will add nested resources and resource collections to the archive.</p>
+<p>An extension of the <a href="jar.html">Jar</a> task with special treatment for files that should
+end up in the <samp>WEB-INF/lib</samp>, <samp>WEB-INF/classes</samp> or <samp>WEB-INF</samp>
+directories of the Web Application Archive.</p>
 
-<p>
-    Before Servlet API 2.5/Java EE 5, a WEB-INF/web.xml file was mandatory in a
-    WAR file, so this task failed if the <code>webxml</code> attribute was missing.
-    As the web.xml file is now optional, the <code>webxml</code> attribute may now
-    be made optional. However, as most real web applications do need a web.xml file,
-    it is not optional by default. The task will fail if the file is not
-    included, unless the <code>needxmlfile</code> attribute
-    is set to <code>false</code>. The task
-    will warn if more than one web.xml file is added to the JAR  
-    through the filesets.
-</p>
+<p>(The <code>War</code> task is a shortcut for specifying the particular layout of a WAR file.  The
+same thing can be accomplished by using the <var>prefix</var> and <var>fullpath</var> attributes
+of <code>zipfileset</code>s in a <code>Zip</code> or <code>Jar</code> task.)</p>
+<p>The extended <code>zipfileset</code> element from the <code>zip</code> task (with
+attributes <var>prefix</var>, <var>fullpath</var>, and <var>src</var>) is available in
+the <code>War</code> task. The task is also resource-enabled and will add nested resources and
+resource collections to the archive.</p>
 
+<p>Before Servlet API 2.5/Java EE 5, a <samp>WEB-INF/web.xml</samp> file was mandatory in a WAR
+file, so this task failed if the <var>webxml</var> attribute was missing.  As
+the <samp>web.xml</samp> file is now optional, the <var>webxml</var> attribute may now be made
+optional. However, as most real web applications do need a <samp>web.xml</samp> file, it is not
+optional by default. The task will fail if the file is not included, unless
+the <var>needxmlfile</var> attribute is set to <q>false</q>. The task will warn if more than
+one <samp>web.xml</samp> file is added to the JAR through the filesets.</p>
 
-<p><b>Please note that the Zip format allows multiple files of the same
-fully-qualified name to exist within a single archive.  This has been
-documented as causing various problems for unsuspecting users.  If you wish
-to avoid this behavior you must set the <code>duplicate</code> attribute
-to a value other than its default, <code>&quot;add&quot;</code>.</b></p>
+<p><strong>Please note that the Zip format allows multiple files of the same fully-qualified name to
+exist within a single archive.  This has been documented as causing various problems for
+unsuspecting users.  If you wish to avoid this behavior you must set the <var>duplicate</var>
+attribute to a value other than its default, <q>add</q>.</strong></p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">the WAR file to create.</td>
-    <td align="center" valign="top" rowspan="2">Exactly one of the two.</td>
+    <td>destfile</td>
+    <td>the WAR file to create.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">warfile</td>
-    <td valign="top"><i>Deprecated</i> name of the file to create
-    -use <tt>destfile</tt> instead.</td>
+    <td>warfile</td>
+    <td class="left"><em><u>Deprecated</u></em> name of the file to
+      create&mdash;use <var>destfile</var> instead.</td>
   </tr>
   <tr>
-    <td valign="top">webxml</td>
-    <td valign="top">The servlet configuration descriptor to use (WEB-INF/web.xml).</td>
-    <td valign="top" align="center">Yes, unless <tt>needxmlfile</tt> is true,
-    the file is pulled in via a nested fileset, or an existing WAR file is
-    being updated.</td>
+    <td>webxml</td>
+    <td>The servlet configuration descriptor to use (<samp>WEB-INF/web.xml</samp>).</td>
+    <td>Yes, unless <var>needxmlfile</var> is <q>true</q>, the file is pulled in via a nested
+      fileset, or an existing WAR file is being updated.</td>
   </tr>
   <tr>
-    <td valign="top">needxmlfile</td>
-    <td valign="top">Flag to indicate whether or not the web.xml file is needed.
-        It should be set to false when generating
-        servlet 2.5+ WAR files without a web.xml file.
-        <em>Since Apache Ant 1.7</em></td>
-    <td valign="top" align="center">No -default "true"</td>
+    <td>needxmlfile</td>
+    <td>Flag to indicate whether or not the <samp>web.xml</samp> file is needed.  It should be set
+      to <q>false</q> when generating servlet 2.5+ WAR files without a <samp>web.xml</samp>
+      file.  <em>Since Apache Ant 1.7</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the directory from which to jar the files.</td>
-    <td valign="top" align="center">No</td>
+    <td>basedir</td>
+    <td>the directory from which to jar the files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compress</td>
-    <td valign="top">Not only store data but also compress them,
-    defaults to true.  Unless you set the <em>keepcompression</em>
-    attribute to false, this will apply to the entire archive, not
-    only the files you've added while updating.</td>
-    <td align="center" valign="top">No</td>
+    <td>compress</td>
+    <td>Not only store data but also compress them.  Unless you set the <var>keepcompression</var>
+      attribute to <q>false</q>, this will apply to the entire archive, not only the files you've
+      added while updating.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">keepcompression</td>
-    <td valign="top">For entries coming from existing archives (like
-    nested <em>zipfileset</em>s or while updating the archive), keep
-    the compression as it has been originally instead of using the
-    <em>compress</em> attribute.  Defaults false.  <em>Since Ant
-    1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>keepcompression</td>
+    <td>For entries coming from existing archives (like nested <var>zipfileset</var>s or while
+      updating the archive), keep the compression as it has been originally instead of using
+      the <var>compress</var> attribute. <em>Since Ant 1.6</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The character encoding to use for filenames
-      inside the archive.  Defaults to UTF8. <strong>It is not
-      recommended to change this value as the created archive will most
-      likely be unreadable for Java otherwise.</strong>
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The character encoding to use for filenames inside the archive. <strong>It is not
+      recommended to change this value as the created archive will most likely be unreadable for
+      Java otherwise.</strong>  <br/>See also the <a href="zip.html#encoding">discussion in the zip
+      task page</a></td>
+    <td>No; defaults to <q>UTF8</q></td>
   </tr>
   <tr>
-    <td valign="top">filesonly</td>
-    <td valign="top">Store only file entries, defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>filesonly</td>
+    <td>Store only file entries</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>Comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an include pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>Comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>Name of a file. Each line of this file is taken to be an exclude pattern</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>Indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">manifest</td>
-    <td valign="top">the manifest file to use.</td>
-    <td valign="top" align="center">No</td>
+    <td>manifest</td>
+    <td>the manifest file to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">filesetmanifest</td>
-    <td valign="top">behavior when a Manifest is found in a zipfileset or zipgroupfileset file is found.  Valid values are &quot;skip&quot;, &quot;merge&quot;, and &quot;mergewithoutmain&quot;.  &quot;merge&quot; will merge all of the manifests together, and merge this into any other specified manifests.  &quot;mergewithoutmain&quot; merges everything but the Main section of the manifests.  Default value is &quot;skip&quot;.
+    <td>filesetmanifest</td>
+    <td>behavior when a manifest is found in a <code>zipfileset</code>
+      or <code>zipgroupfileset</code> file.  Valid values are <q>skip</q>, <q>merge</q>,
+      and <q>mergewithoutmain</q>.  <q>merge</q> will merge all of the manifests together, and merge
+      this into any other specified manifests.  <q>mergewithoutmain</q> merges everything but the
+      Main section of the manifests.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to <q>skip</q></td>
   </tr>
   <tr>
-    <td valign="top">whenmanifestonly</td>
-    <td valign="top">behavior when no files match.  Valid values are &quot;fail&quot;, &quot;skip&quot;, and &quot;create&quot;.  Default is &quot;create&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>whenmanifestonly</td>
+    <td>behavior when no files match.  Valid values are <q>fail</q>, <q>skip</q>,
+      and <q>create</q>.</td>
+    <td>No; defaults to <q>create</q></td>
   </tr>
   <tr>
-    <td valign="top">update</td>
-    <td valign="top">indicates whether to update or overwrite
-      the destination file if it already exists.  Default is &quot;false&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>update</td>
+    <td>indicates whether to update or overwrite the destination file if it already exists.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">duplicate</td>
-    <td valign="top">behavior when a duplicate file is found.  Valid values are &quot;add&quot;, &quot;preserve&quot;, and &quot;fail&quot;.  The default value is &quot;add&quot;.  </td>
-    <td valign="top" align="center">No</td>
+    <td>duplicate</td>
+    <td>behavior when a duplicate file is found.  Valid values are <q>add</q>, <q>preserve</q>,
+      and <q>fail</q>.</td>
+    <td>No; defaults to <q>add</q></td>
   </tr>
   <tr>
-    <td valign="top">roundup</td>
-    <td valign="top">Whether the file modification times will be
-    rounded up to the next even number of seconds.<br>
-    Zip archives store file modification times with a granularity of
-    two seconds, so the times will either be rounded up or down.  If
-    you round down, the archive will always seem out-of-date when you
-    rerun the task, so the default is to round up.  Rounding up may
-    lead to a different type of problems like JSPs inside a web
-    archive that seem to be slightly more recent than precompiled
-    pages, rendering precompilation useless.<br>
-    Defaults to true.  <em>Since Ant 1.6.2</em></td>
-    <td align="center" valign="top">No</td>
+    <td>roundup</td>
+    <td>Whether the file modification times will be rounded up to the next even number of
+      seconds.<br/>Zip archives store file modification times with a granularity of 2 seconds, so
+      the times will either be rounded up or down.  If you round down, the archive will always seem
+      out-of-date when you rerun the task, so the default is to round up.  Rounding up may lead to a
+      different type of problems like JSPs inside a web archive that seem to be slightly more recent
+      than precompiled pages, rendering precompilation useless. <em>Since Ant 1.6.2</em></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">level</td>
-    <td valign="top">Non-default level at which file compression should be
-    performed. Valid values range from 0 (no compression/fastest) to 9
-    (maximum compression/slowest). <em>Since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
+    <td>level</td>
+    <td>Non-default level at which file compression should be performed. Valid values range
+      from <q>0</q> (no compression/fastest) to <q>9</q> (maximum compression/slowest). <em>Since
+      Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">preserve0permissions</td>
-    <td valign="top">when updating an archive or adding entries from a
-    different archive Ant will assume that a Unix permissions value of
-    0 (nobody is allowed to do anything to the file/directory) means
-    that the permissions haven't been stored at all rather than real
-    permissions and will instead apply its own default values.<br/>
-    Set this attribute to true if you really want to preserve the
-      original permission field.<em>since Ant 1.8.0</em>
-    </td>
-    <td valign="top" align="center">No, default is false</td>
+    <td>preserve0permissions</td>
+    <td>when updating an archive or adding entries from a different archive Ant will assume that a
+      Unix permissions value of 0 (nobody is allowed to do anything to the file/directory) means
+      that the permissions haven't been stored at all rather than real permissions and will instead
+      apply its own default values.<br/>  Set this attribute to <q>true</q> if you really want to
+      preserve the original permission field. <em>since Ant 1.8.0</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">useLanguageEncodingFlag</td>
-    <td valign="top">Whether to set the language encoding flag if the
-      encoding is UTF-8.  This setting doesn't have any effect if the
-      encoding is not UTF-8.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td valign="top" align="center">No, default is true</td>
+    <td>useLanguageEncodingFlag</td>
+    <td>Whether to set the language encoding flag if the encoding is UTF-8.  This setting doesn't
+      have any effect if the encoding is not UTF-8. <em>Since Ant 1.8.0</em>.  <br/>See also
+      the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">createUnicodeExtraFields</td>
-    <td valign="top">Whether to create unicode extra fields to store
-      the file names a second time inside the entry's metadata.
-      <br>Possible values are "never", "always" and "not-encodeable"
-      which will only add Unicode extra fields if the file name cannot
-      be encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
+    <td>createUnicodeExtraFields</td>
+    <td>Whether to create Unicode extra fields to store the file names a second time inside the
+      entry's metadata.<br/>Possible values are <q>never</q>, <q>always</q>
+      and <q>not-encodeable</q> which will only add Unicode extra fields if the file name cannot be
+      encoded using the specified encoding. <em>Since Ant 1.8.0</em>.<br/>See also
+      the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; default is <q>never</q></td>
   </tr>
   <tr>
-    <td valign="top">fallbacktoUTF8</td>
-    <td valign="top">Whether to use UTF-8 and the language encoding
-      flag instead of the specified encoding if a file name cannot be
-      encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="zip.html#encoding">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>fallbacktoUTF8</td>
+    <td>Whether to use UTF-8 and the language encoding flag instead of the specified encoding if a
+      file name cannot be encoded using the specified encoding. <em>Since Ant 1.8.0</em>.<br/>See
+      also the <a href="zip.html#encoding">discussion in the zip task page</a></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">mergeClassPathAttributes</td>
-    <td valign="top">Whether to merge the Class-Path attributes found
-      in different manifests (if merging manifests).  If false, only
-      the attribute of the last merged manifest will be preserved.
-      <em>Since Ant 1.8.0</em>.
-      <br/>unless you also set flattenAttributes to true this may
-      result in manifests containing multiple Class-Path attributes
-      which violates the manifest specification.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>mergeClassPathAttributes</td>
+    <td>Whether to merge the <code>Class-Path</code> attributes found in different manifests (if
+      merging manifests).  If <q>false</q>, only the attribute of the last merged manifest will be
+      preserved.  <em>Since Ant 1.8.0</em>.<br/>Unless you also set <var>flattenAttributes</var>
+      to <q>true</q> this may result in manifests containing multiple <code>Class-Path</code>
+      attributes which violates the manifest specification.</td>
+    <td>No; default is false</td>
   </tr>
   <tr>
-    <td valign="top">flattenAttributes</td>
-    <td valign="top">Whether to merge attributes occurring more than
-      once in a section (this can only happen for the Class-Path
-      attribute) into a single attribute.
-      <em>Since Ant 1.8.0</em>.</td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>flattenAttributes</td>
+    <td>Whether to merge attributes occurring more than once in a section (this can only happen for
+      the <code>Class-Path</code> attribute) into a single attribute. <em>Since Ant 1.8.0</em>.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">zip64Mode</td>
-    <td valign="top">When to use Zip64 extensions for entries.  The
-      possible values are "never", "always" and "as-needed".
-      <em>Since Ant 1.9.1</em>.
-      <br/>See also the <a href="zip.html#zip64">discussion in the
-      zip task page</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
+    <td>zip64Mode</td>
+    <td>When to use Zip64 extensions for entries.  The possible values
+      are <q>never</q>, <q>always</q> and <q>as-needed</q>.  <em>Since Ant 1.9.1</em>.<br/>See also
+      the <a href="zip.html#zip64">discussion in the zip task page</a></td>
+    <td>No; default is <q>never</q></td>
   </tr>
   <tr>
     <td valign="top">modificationtime</td>
@@ -282,37 +247,35 @@
     given time. This can either be a number interpreted as
     milliseconds since 1970-01-01T00:00:00Z or a string that can be
     parsed as a ISO 8601 timestamp with optional timezone.
-      <em>Since Ant 1.9.10</em>.
+      <em>Since Ant 1.10.2</em>.
     </td>
     <td align="center" valign="top">No</td>
   </tr>
 </table>
 
-<h3>Nested elements</h3>
+<h3>Parameters specified as nested elements</h3>
 
 <h4>lib</h4>
-<p>The nested <code>lib</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in this fileset will
-end up in the <code>WEB-INF/lib</code> directory of the war file.</p>
+<p>The nested <code>lib</code> element specifies a <a href="../Types/fileset.html">FileSet</a>. All
+files included in this fileset will end up in the <samp>WEB-INF/lib</samp> directory of the war
+file.</p>
 
 <h4>classes</h4>
-<p>The nested <code>classes</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in this fileset will
-end up in the <code>WEB-INF/classes</code> directory of the war file.</p>
+<p>The nested <code>classes</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>. All files included in this fileset will end up in
+the <samp>WEB-INF/classes</samp> directory of the war file.</p>
 
 <h4>webinf</h4>
-<p>The nested <code>webinf</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in this fileset will
-end up in the <code>WEB-INF</code> directory of the war file. If this
-fileset includes a file named <code>web.xml</code>, the file is
-ignored and you will get a warning.</p>
+<p>The nested <code>webinf</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>. All files included in this fileset will end up in
+the <samp>WEB-INF</samp> directory of the war file. If this fileset includes a file
+named <samp>web.xml</samp>, the file is ignored and you will get a warning.</p>
 
 <h4>metainf</h4>
-<p>The nested <code>metainf</code> element specifies a <a
-href="../Types/fileset.html">FileSet</a>. All files included in this fileset will
-end up in the <code>META-INF</code> directory of the war file. If this
-fileset includes a file named <code>MANIFEST.MF</code>, the file is
-ignored and you will get a warning.</p>
+<p>The nested <code>metainf</code> element specifies
+a <a href="../Types/fileset.html">FileSet</a>. All files included in this fileset will end up in
+the <samp>META-INF</samp> directory of the war file. If this fileset includes a file
+named <samp>MANIFEST.MF</samp>, the file is ignored and you will get a warning.</p>
 
 <h4>manifest, indexjars, service</h4>
 These are inherited from <a href="jar.html">&lt;jar&gt;</a>
@@ -328,9 +291,8 @@
 src/html/myapp/index.html
 src/jsp/myapp/front.jsp
 src/graphics/images/gifs/small/logo.gif
-src/graphics/images/gifs/large/logo.gif
-</pre>
-then the war file <code>myapp.war</code> created with
+src/graphics/images/gifs/large/logo.gif</pre>
+<p>then the war file <samp>myapp.war</samp> created with</p>
 <pre>
 &lt;war destfile=&quot;myapp.war&quot; webxml=&quot;src/metadata/myapp.xml&quot;&gt;
   &lt;fileset dir=&quot;src/html/myapp&quot;/&gt;
@@ -341,9 +303,8 @@
   &lt;classes dir=&quot;build/main&quot;/&gt;
   &lt;zipfileset dir=&quot;src/graphics/images/gifs&quot;
               prefix=&quot;images&quot;/&gt;
-&lt;/war&gt;
-</pre>
-will consist of
+&lt;/war&gt;</pre>
+<p>will consist of</p>
 <pre>
 WEB-INF/web.xml
 WEB-INF/lib/jdbc2.jar
@@ -352,23 +313,19 @@
 index.html
 front.jsp
 images/small/logo.gif
-images/large/logo.gif
-</pre>
+images/large/logo.gif</pre>
 using Ant's default manifest file. The content of
-<code>WEB-INF/web.xml</code> is identical to
-<code>src/metadata/myapp.xml</code>.
+<samp>WEB-INF/web.xml</samp> is identical to
+<samp>src/metadata/myapp.xml</samp>.
 
-<p>We regularly receive bug reports that this task is creating the WEB-INF
-directory as web-inf (all lower case), and thus it is our fault your webapp doesn't work. The cause
-of these complaints lies in WinZip, which turns an all upper-case
-directory into an all lower case one in a fit of helpfulness. Please check that
-<code>jar xvf yourwebapp.war</code> shows the same behaviour before filing another
-report.<br/>
-Winzip has an option allowing all uppercase names (which is off by default!).  It can be enabled by:
-Menu "Options" -> "Configuration",  "View" property/tab page, then "General" group box has an option called "Allow all uppercase file names".
-</p>
-
-
+<p>We regularly receive bug reports that this task is creating the <samp>WEB-INF</samp> directory
+as <samp>web-inf</samp> (all lower case), and thus it is our fault your webapp doesn't work. The
+cause of these complaints lies in WinZip, which turns an all upper-case directory into an all
+lower-case one in a fit of helpfulness. Please check that <code>jar xvf yourwebapp.war</code> shows
+the same behaviour before filing another report.<br/>WinZip has an option allowing all uppercase
+names (which is off by default!).  It can be enabled by: Menu <q>Options</q>
+&rarr; <q>Configuration</q>, <q>View</q> property/tab page, then <q>General</q> group box has an
+option called <q>Allow all uppercase file names</q>.</p>
 
 </body>
 </html>
diff --git a/manual/Tasks/whichresource.html b/manual/Tasks/whichresource.html
index 5b2b54e..8ed6afe 100644
--- a/manual/Tasks/whichresource.html
+++ b/manual/Tasks/whichresource.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,107 +15,75 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-    
-<html>
+
+<html lang="en">
   <head>
-    <meta http-equiv="Content-Language" content="en-us">
-      <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-        <title>Whichresource Task</title>
-      </link>
-    </meta>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+    <title>Whichresource Task</title>
   </head>
 
-
   <body>
-    <h2><a name="whichresource">Whichresource</a></h2>
+    <h2 id="whichresource">Whichresource</h2>
     <h3>Description</h3>
-    <p>
-      Find a class or resource on the supplied classpath, or the
-      system classpath if none is supplied.
-      The named property is set if the item can be found.
-      For example:
-    </p>
-<blockquote><pre>
-  &lt;whichresource resource="/log4j.properties" property="log4j.url" &gt;
-</pre></blockquote>
+    <p>Find a class or resource on the supplied classpath, or the system classpath if none is
+      supplied.  The named property is set if the item can be found.  For example:</p>
+    <pre>&lt;whichresource resource="/log4j.properties" property="log4j.url"/&gt;</pre>
     <h3>Parameters</h3>
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">property</td>
-        <td valign="top">
-          The property to fill with the URL of the resource of class.
-        </td>
-        <td valign="top" align="center">Yes</td>
+        <td>property</td>
+        <td>The property to fill with the URL of the resource of class.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">class</td>
-        <td valign="top">
-          The name of the class to look for.
-        </td>
-        <td valign="top" align="center" rowspan="2">Exactly one of these.</td>
+        <td>class</td>
+        <td>The name of the class to look for.</td>
+        <td rowspan="2">Exactly one of these</td>
       </tr>
       <tr>
-        <td valign="top">resource</td>
-        <td valign="top">
-          The name of the resource to look for.
-        </td>
+        <td>resource</td>
+        <td class="left">The name of the resource to look for.</td>
       </tr>
       <tr>
-        <td valign="top">classpath</td>
-        <td valign="top">
-          The classpath to use when looking up <code>class</code>
-          or <code>resource</code>.
-        </td>
-        <td align="center" valign="top">No</td>
+        <td>classpath</td>
+        <td>The classpath to use when looking up <var>class</var> or <var>resource</var>.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">classpathref</td>
-        <td valign="top">
-          The classpath to use, given as a
-          <a href="../using.html#references">reference</a>
-          to a path defined elsewhere.
-          <em>Since Apache Ant 1.7.1.</em>
-        </td>
-        <td align="center" valign="top">No</td>
+        <td>classpathref</td>
+        <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a
+          path defined elsewhere.  <em>Since Apache Ant 1.7.1</em>.</td>
+        <td>No</td>
       </tr>
     </table>
     <h3>Parameters specified as nested elements</h3>
     <h4>classpath</h4>
-    <p>
-      <code>Whichresource</code>'s <code>classpath</code> attribute is a
-      <a href="../using.html#path">path-like structure</a> and can also be
-      set via a nested <code>&lt;classpath&gt;</code> element.
-    </p>
+    <p><code>Whichresource</code>'s <var>classpath</var> attribute is
+      a <a href="../using.html#path">path-like structure</a> and can also be set via a
+      nested <code>&lt;classpath&gt;</code> element.</p>
     <h3>Examples</h3>
-    <p>
-      The following shows using a classpath reference.
-    </p>
-<blockquote><pre>
-  &lt;path id="bsf.classpath"&gt;
-    &lt;fileset dir="${user.home}/lang/bsf" includes="*.jar"/&gt;
-  &lt;/path&gt;
-  &lt;whichresource property="bsf.class.location"
-                 class="org.apache.bsf.BSFManager"
-                 classpathref="bsf.classpath"/&gt;
-  &lt;echo&gt;${bsf.class.location}&lt;/echo&gt;
-</pre></blockquote>
-    <p>
-      The following shows using a nested classpath.
-    </p>
-<blockquote><pre>
-  &lt;whichresource
-    property="ant-contrib.antlib.location"
-    resource="net/sf/antcontrib/antlib.xml"&gt;
-    &lt;classpath&gt;
-      &lt;path path="f:/testing/ant-contrib/target/ant-contrib.jar"/&gt;
-    &lt;/classpath&gt;
-  &lt;/whichresource&gt;
-  &lt;echo&gt;${ant-contrib.antlib.location}&lt;/echo&gt;
-</pre></blockquote>
+    <p>The following shows using a classpath reference.</p>
+    <pre>
+&lt;path id="bsf.classpath"&gt;
+  &lt;fileset dir="${user.home}/lang/bsf" includes="*.jar"/&gt;
+&lt;/path&gt;
+&lt;whichresource property="bsf.class.location"
+               class="org.apache.bsf.BSFManager"
+               classpathref="bsf.classpath"/&gt;
+&lt;echo&gt;${bsf.class.location}&lt;/echo&gt;</pre>
+    <p>The following shows using a nested classpath.</p>
+    <pre>
+&lt;whichresource property="ant-contrib.antlib.location"
+               resource="net/sf/antcontrib/antlib.xml"&gt;
+  &lt;classpath&gt;
+    &lt;path path="f:/testing/ant-contrib/target/ant-contrib.jar"/&gt;
+  &lt;/classpath&gt;
+&lt;/whichresource&gt;
+&lt;echo&gt;${ant-contrib.antlib.location}&lt;/echo&gt;</pre>
   </body>
 </html>
diff --git a/manual/Tasks/wljspc.html b/manual/Tasks/wljspc.html
index 5663494..d3e907d 100644
--- a/manual/Tasks/wljspc.html
+++ b/manual/Tasks/wljspc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,85 +15,75 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
-<head><link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>WLJSPC Task</title></head>
+<html lang="en">
+  <head>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+    <title>WLJSPC Task</title>
+  </head>
 <body>
 <h1>wljspc</h1>
 <h3>Description</h3>
-<p>Class to precompile JSP's using weblogic's jsp compiler (weblogic.jspc)</p>
-Tested only on Weblogic 4.5.1 - NT4.0 and Solaris 5.7,5.8<br>
+<p>Class to precompile JSP's using WebLogic JSP compiler (<code>weblogic.jspc</code>)</p>
+<p>Tested only on WebLogic 4.5.1&mdash;NT 4.0 and Solaris 7 &amp; 8</p>
 <h3>Parameters</h3>
-<table border="1" cellPadding="2" cellSpacing="0">
+<table class="attr">
+  <thead>
+    <tr>
+      <th scope="col">Attribute</th>
+      <th scope="col">Values</th>
+      <th scope="col">Required</th>
+    </tr>
+  </thead>
   <tbody>
     <tr>
-      <th>Attribute</th>
-      <th>Values</th>
-      <th>Required</th>
-    </tr>
-    <tr>
       <td>src</td>
-      <td>root of source tree for JSP, ie, the document root for your weblogic server</td>
+      <td>root of source tree for JSP, ie, the document root for your WebLogic server</td>
       <td>Yes</td>
     </tr>
     <tr>
-      <td>
-dest</td>
-      <td> root of destination directory, what you have set as WorkingDir in the weblogic properties</td>
+      <td>dest</td>
+      <td>root of destination directory, what you have set as <code>WorkingDir</code> in the
+        WebLogic properties</td>
       <td>Yes</td>
     </tr>
     <tr>
-      <td>
-package</td>
-      <td> start package name under which your JSP's would be compiled</td>
+      <td>package</td>
+      <td>start package name under which your JSPs would be compiled</td>
       <td>Yes</td>
     </tr>
     <tr>
-      <td>
-classpath</td>
-      <td>Class path to use when compiling jsp's</td>
+      <td>classpath</td>
+      <td>Class path to use when compiling JSPs</td>
       <td>Yes</td>
     </tr>
   </tbody>
 </table>
-<p>
-<br>
-
-A classpath should be set which contains the weblogic classes as well as all application classes<br>
-referenced by the JSP. The system classpath is also appended when the jspc is called, so you may<br>
-choose to put everything in the classpath while calling Apache Ant. However, since presumably the JSP's will reference<br>
-classes being build by Ant, it would be better to explicitly add the classpath in the task<br>
-<br>
-The task checks timestamps on the JSP's and the generated classes, and compiles<br>
-only those files that have changed.<br>
-<br>
-It follows the weblogic naming convention of putting classes in<br>
-<b> _dirName/_fileName.class for dirname/fileName.jsp   </b><br>
-<br>
-</p>
-<h3><br>
-Example<br>
-</h3>
-<p>
+<p>A classpath should be set which contains the WebLogic classes as well as all application classes
+referenced by JSP. The system classpath is also appended when the <code>jspc</code> is called, so
+you may choose to put everything in the classpath while calling Apache Ant. However, since
+presumably JSPs will reference classes being build by Ant, it would be better to explicitly add the
+classpath in the task.</p>
+<p>The task checks timestamps on the JSP's and the generated classes, and compiles only those files
+that have changed.</p>
+<p>It follows the WebLogic naming convention of putting classes in <samp>_dirName/_fileName.class
+for dirname/fileName.jsp</samp></p>
+<h3>Example</h3>
 <pre>
 &lt;target name="jspcompile" depends="compile"&gt;
-  &lt;wljspc src="c:\\weblogic\\myserver\\public_html" dest="c:\\weblogic\\myserver\\serverclasses" package="myapp.jsp"&gt
+  &lt;wljspc src="c:\\weblogic\\myserver\\public_html" dest="c:\\weblogic\\myserver\\serverclasses" package="myapp.jsp"&gt;
     &lt;classpath&gt;
       &lt;pathelement location="${weblogic.classpath}"/&gt;
       &lt;pathelement path="${compile.dest}"/&gt;
     &lt;/classpath&gt;
   &lt;/wljspc&gt;
-&lt;/target&gt;
-</pre>
-
-</p>
+&lt;/target&gt;</pre>
 
 <h3>Limitations</h3>
 <ul>
-<li>This works only on weblogic 4.5.1</li>
-<li>It compiles the files thru the Classic compiler only.</li>
-<li>Since it is my experience that weblogic jspc throws out of memory error on being given too
-many files at one go, it is called multiple times with one jsp file each.</li>
+  <li>This works only on WebLogic 4.5.1</li>
+  <li>It compiles the files through the Classic compiler only.</li>
+  <li>Since it is my experience that <code>weblogic.jspc</code> throws out of memory error on being
+    given too many files at one go, it is called multiple times with one JSP file each.</li>
 </ul>
 
 </body>
diff --git a/manual/Tasks/xmlproperty.html b/manual/Tasks/xmlproperty.html
index 293cf24..e568392 100644
--- a/manual/Tasks/xmlproperty.html
+++ b/manual/Tasks/xmlproperty.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>XmlProperty Task</title>
@@ -22,268 +23,236 @@
 
 <body>
 
-<h2><a name="xmlproperty">XmlProperty</a></h2>
+<h2 id="xmlproperty">XmlProperty</h2>
 <h3>Description</h3>
-<p>
-Loads property values from a well-formed xml file. There are no other restrictions
-than "well-formed". You can choose the layout you want. For example this XML property file:
+<p>Loads property values from a well-formed xml file. There are no other restrictions than
+"well-formed". You can choose the layout you want. For example this XML property file:</p>
 <pre>
   &lt;root&gt;
     &lt;properties&gt;
       &lt;foo&gt;bar&lt;/foo&gt;
     &lt;/properties&gt;
-  &lt;/root&gt;
-</pre>
-is roughly equivalent to this Java property file:
-<pre>
-  root.properties.foo = bar
-</pre>
+  &lt;/root&gt;</pre>
+<p>is roughly equivalent to this Java property file:</p>
+<pre>root.properties.foo = bar</pre>
 
-<p>
-By default, this load
-does <em>no</em> processing of the input.  In particular, unlike the
-<a href="property.html">Property task</a>, property references
-(i.e., <samp>${foo}</samp>) are not resolved.
-<p>
-<a name="semanticAttributes">
-<h3>Semantic Attributes</h3>
-</a>
-Input processing can be enabled by using the <b>semanticAttributes</b>
-attribute.  If this attribute is set to <i>true</i> (its default is
-<i>false</i>), the following processing occurs as the input XML file
-is loaded:
+<p>By default, this load does <em>no</em> processing of the input.  In particular, unlike
+the <a href="property.html">Property task</a>, property references (i.e., <samp>${foo}</samp>) are
+not resolved.</p>
+<h3 id="semanticAttributes">Semantic attributes</h3>
+<p>Input processing can be enabled by using the <var>semanticAttributes</var> attribute.  If this
+attribute is set to <q>true</q> (its default is <q>false</q>), the following processing occurs as
+the input XML file is loaded:/p>
 <ul>
   <li>Property references are resolved.</li>
   <li>The following attributes are treated differently:
     <ul>
-      <li><b>id</b>: The property is associated with the given id value.</li>
-      <li><b>location</b>: The property is treated as a file location</li>
-      <li><b>refid</b>: The property is set to the value of the
-          referenced property.</li>
-      <li><b>value</b>: The property is set to the value indicated.</li>
+      <li><var>id</var>: The property is associated with the given id value.</li>
+      <li><var>location</var>: The property is treated as a file location</li>
+      <li><var>refid</var>: The property is set to the value of the referenced property.</li>
+      <li><var>value</var>: The property is set to the value indicated.</li>
     </ul>
   </li>
-  <li><a href="../using.html#path">Path-like Structures</a> can be defined
-      by use of the following attributes:
+  <li><a href="../using.html#path">path-like structures</a> can be defined by use of the following
+    attributes:
     <ul>
-      <li><b>pathid</b>: The given id is used to identify a path.  The
-          nested XML tag name is ignored.  Child elements can be used
-          (XML tag names are ignored) to identify elements of the path.</li>
+      <li><var>pathid</var>: The given <var>id</var> is used to identify a path.  The nested XML tag
+        name is ignored.  Child elements can be used (XML tag names are ignored) to identify
+        elements of the path.</li>
     </ul>
   </li>
 </ul>
-<p>
-For example, with semantic attribute processing enabled, this XML property
-file:
+<p>For example, with semantic attribute processing enabled, this XML property file:</p>
 <pre>
-  &lt;root&gt;
-    &lt;properties&gt;
-      &lt;foo location="bar"/&gt;
-      &lt;quux&gt;${root.properties.foo}&lt;/quux&gt;
-    &lt;/properties&gt;
-  &lt;/root&gt;
-</pre>
-is roughly equivalent to the following fragments in a build.xml file:
+&lt;root&gt;
+  &lt;properties&gt;
+    &lt;foo location="bar"/&gt;
+    &lt;quux&gt;${root.properties.foo}&lt;/quux&gt;
+  &lt;/properties&gt;
+&lt;/root&gt;</pre>
+<p>is roughly equivalent to the following fragments in a <samp>build.xml</samp> file:</p>
 <pre>
-  &lt;property name="root.properties.foo" location="bar"/&gt;
-  &lt;property name="root.properties.quux" value="${root.properties.foo}"/&gt;
-</pre>
-
-</p>
+&lt;property name="root.properties.foo" location="bar"/&gt;
+&lt;property name="root.properties.quux" value="${root.properties.foo}"/&gt;</pre>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The XML file to parse.</td>
-    <td valign="top" align="center">Yes, or a nested resource collection.</td>
+    <td>file</td>
+    <td>The XML file to parse.</td>
+    <td>Yes, or a nested resource collection</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">The prefix to prepend to each property</td>
-    <td valign="top" align="center">No</td>
+    <td>prefix</td>
+    <td>The prefix to prepend to each property.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">keepRoot</td>
-    <td valign="top">Keep the xml root tag as the
-                     first value in the property name.</td>
-    <td valign="top" align="center">No, default is <i>true</i>.</td>
+    <td>keepRoot</td>
+    <td>Keep the XML root tag as the first value in the property name.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">validate</td>
-    <td valign="top">Validate the input file (e.g. by a DTD). Otherwise the XML must only be well-formed.</td>
-    <td valign="top" align="center">No, default is <i>false</i>.</td>
+    <td>validate</td>
+    <td>Validate the input file (e.g. by a DTD). Otherwise the XML must only be well-formed.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">collapseAttributes</td>
-    <td valign="top">Treat attributes as nested elements.</td>
-    <td valign="top" align="center">No, default is <i>false</i>.</td>
+    <td>collapseAttributes</td>
+    <td>Treat attributes as nested elements.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">semanticAttributes</td>
-    <td valign="top">Enable special handling of certain attribute names.
-                     See the <a href="#semanticAttributes">Semantic Attributes</a>
-                     section for more information.</td>
-    <td valign="top" align="center">No, default is <i>false</i>.</td>
+    <td>semanticAttributes</td>
+    <td>Enable special handling of certain attribute names.  See
+      the <a href="#semanticAttributes">Semantic Attributes</a> section for more information.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includeSemanticAttribute</td>
-    <td valign="top">Include the semantic attribute name
-                     as part of the property name.  Ignored if
-                     <i>semanticAttributes</i> is not set to <i>true</i>.
-                     See the <a href="#semanticAttributes">Semantic Attributes</a>
-                     section for more information.</td>
-    <td valign="top" align="center">No, default is <i>false</i>.</td>
+    <td>includeSemanticAttribute</td>
+    <td>Include the semantic attribute name as part of the property name.  Ignored
+      if <var>semanticAttributes</var> is not set to <q>true</q>.  See
+      the <a href="#semanticAttributes">Semantic Attributes</a> section for more information.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">rootDirectory</td>
-    <td valign="top">The directory to use for resolving file references. Ignored
-                     if <i>semanticAttributes</i> is not set to <i>true</i>.</td>
-    <td valign="top" align="center">No, default is <i>${basedir}</i>.</td>
+    <td>rootDirectory</td>
+    <td>The directory to use for resolving file references. Ignored if <var>semanticAttributes</var>
+      is not set to <q>true</q>.</td>
+    <td>No; default is <var>basedir</var></td>
   </tr>
   <tr>
-    <td valign="top">delimiter</td>
-    <td valign="top">Delimiter for splitting multiple values.<br><i>since Apache Ant 1.7.1</i></td>
-    <td valign="top" align="center">No, defaults to comma</td>
+    <td>delimiter</td>
+    <td>Delimiter for splitting multiple values.<br/><em>since Apache Ant 1.7.1</em></td>
+    <td>No; defaults to <q>,</q> (comma)</td>
   </tr>
 </table>
 
-<h3><a name="nested">Nested Elements</a></h3>
+<h3 id="nested">Parameters specified as nested elements</h3>
 <h4>xmlcatalog</h4>
-<p>The <a href="../Types/xmlcatalog.html"><tt>&lt;xmlcatalog&gt;</tt></a>
-element is used to perform entity resolution.</p>
+<p>The <a href="../Types/xmlcatalog.html"><code>&lt;xmlcatalog&gt;</code></a> element is used to
+perform entity resolution.</p>
 
-<h4>any <a href="../Types/resources.html">resource</a> or single element
-resource collection</h4>
+<h4>any <a href="../Types/resources.html">resource</a> or single element resource collection</h4>
 
 <p>The specified resource will be used as input.</p>
 
-<a name="examples">
-<h3>Examples</h3>
-</a>
+<h3 id="examples">Examples</h3>
 
-<h4>Non-semantic Attributes</h4>
+<h4>Non-semantic attributes</h4>
 
-<p>Here is an example xml file that does not have any semantic attributes.</p>
+<p>Here is an example XML file that does not have any semantic attributes.</p>
 
 <pre>
-   &lt;root-tag myattr="true"&gt;
-    &lt;inner-tag someattr="val"&gt;Text&lt;/inner-tag&gt;
-    &lt;a2&gt;&lt;a3&gt;&lt;a4&gt;false&lt;/a4&gt;&lt;/a3&gt;&lt;/a2&gt;
-   &lt;/root-tag&gt;
-</pre>
+&lt;root-tag myattr="true"&gt;
+  &lt;inner-tag someattr="val"&gt;Text&lt;/inner-tag&gt;
+  &lt;a2&gt;&lt;a3&gt;&lt;a4&gt;false&lt;/a4&gt;&lt;/a3&gt;&lt;/a2&gt;
+&lt;/root-tag&gt;</pre>
 
 <h5>default loading</h5>
-<p>This entry in a build file:
-<pre>   &lt;xmlproperty file="somefile.xml"/&gt;</pre>
-is equivalent to the following properties:
+<p>This entry in a build file:</p>
+<pre>&lt;xmlproperty file="somefile.xml"/&gt;</pre>
+<p>is equivalent to the following properties:</p>
 <pre>
-   root-tag(myattr)=true
-   root-tag.inner-tag=Text
-   root-tag.inner-tag(someattr)=val
-   root-tag.a2.a3.a4=false
-</pre>
+root-tag(myattr)=true
+root-tag.inner-tag=Text
+root-tag.inner-tag(someattr)=val
+root-tag.a2.a3.a4=false</pre>
 
-<h5>collapseAttributes=false</h5>
-<p>This entry in a build file:
-<pre>   &lt;xmlproperty file="somefile.xml" collapseAttributes="true"/&gt;</pre>
-is equivalent to the following properties:
+<h5><var>collapseAttributes</var>=<q>false</q></h5>
+<p>This entry in a build file:</p>
+<pre>&lt;xmlproperty file="somefile.xml" collapseAttributes="true"/&gt;</pre>
+<p>is equivalent to the following properties:</p>
 <pre>
-   root-tag.myattr=true
-   root-tag.inner-tag=Text
-   root-tag.inner-tag.someatt=val
-   root-tag.a2.a3.a4=false
-</pre>
+root-tag.myattr=true
+root-tag.inner-tag=Text
+root-tag.inner-tag.someatt=val
+root-tag.a2.a3.a4=false</pre>
 
-<h5>keepRoot=false</h5>
-<p>This entry in a build file:
-<pre>   &lt;xmlproperty file="somefile.xml" keepRoot="false"/&gt;</pre>
-is equivalent to the following properties:
+<h5><var>keepRoot</var>=<q>false</q></h5>
+<p>This entry in a build file:</p>
+<pre>&lt;xmlproperty file="somefile.xml" keepRoot="false"/&gt;</pre>
+<p>is equivalent to the following properties:</p>
 <pre>
-   inner-tag=Text
-   inner-tag(someattr)=val
-   a2.a3.a4=false
-</pre>
+inner-tag=Text
+inner-tag(someattr)=val
+a2.a3.a4=false</pre>
 
-<h4>Semantic Attributes</h4>
+<h4>Semantic attributes</h4>
 
-<p>Here is an example xml file that has semantic attributes.</p>
+<p>Here is an example XML file that has semantic attributes.</p>
 <pre>
-  &lt;root-tag&gt;
-    &lt;version value="0.0.1"/&gt;
-    &lt;build folder="build"&gt;
-      &lt;classes id="build.classes" location="${build.folder}/classes"/&gt;
-      &lt;reference refid="build.classes"/&gt;
-    &lt;/build&gt;
-    &lt;compile&gt;
-      &lt;classpath pathid="compile.classpath"&gt;
-        &lt;pathelement location="${build.classes}"/&gt;
-      &lt;/classpath&gt;
-    &lt;/compile&gt;
-    &lt;run-time&gt;
-      &lt;jars&gt;*.jar&lt;/jars&gt;
-      &lt;classpath pathid="run-time.classpath"&gt;
-        &lt;path refid="compile.classpath"/&gt;
-        &lt;pathelement path="${run-time.jars}"/&gt;
-      &lt;/classpath&gt;
-    &lt;/run-time&gt;
-  &lt;/root-tag&gt;
-</pre>
+&lt;root-tag&gt;
+  &lt;version value="0.0.1"/&gt;
+  &lt;build folder="build"&gt;
+    &lt;classes id="build.classes" location="${build.folder}/classes"/&gt;
+    &lt;reference refid="build.classes"/&gt;
+  &lt;/build&gt;
+  &lt;compile&gt;
+    &lt;classpath pathid="compile.classpath"&gt;
+      &lt;pathelement location="${build.classes}"/&gt;
+    &lt;/classpath&gt;
+  &lt;/compile&gt;
+  &lt;run-time&gt;
+    &lt;jars&gt;*.jar&lt;/jars&gt;
+    &lt;classpath pathid="run-time.classpath"&gt;
+      &lt;path refid="compile.classpath"/&gt;
+      &lt;pathelement path="${run-time.jars}"/&gt;
+    &lt;/classpath&gt;
+  &lt;/run-time&gt;
+&lt;/root-tag&gt;</pre>
 
-<h5>default loading (semanticAttributes=true)</h5>
-<p>This entry in a build file:
-<pre>   &lt;xmlproperty file="somefile.xml" keepRoot="false"
-                semanticAttributes="true"/&gt;</pre>
-is equivalent to the following entries in a build file:
+<h5>default loading (<var>semanticAttributes</var>=<q>true</q>)</h5>
+<p>This entry in a build file:</p>
 <pre>
-  &lt;property name="version" value="0.0.1"/&gt;
-  &lt;property name="build.folder" value="build"/&gt;
-  &lt;property name="build.classes" location="${build.folder}/classes" id="build.classes"/&gt;
-  &lt;property name="build.reference" refid="build.classes"/&gt;
-
-  &lt;property name="run-time.jars" value="*.jar"/&gt;
-
-  &lt;path id="compile.classpath"&gt;
-    &lt;pathelement location="${build.classes}"/&gt;
-  &lt;/path&gt;
-
-  &lt;path id="run-time.classpath"&gt;
-    &lt;path refid="compile.classpath"/&gt;
-    &lt;pathelement path="${run-time.jars}"/&gt;
-  &lt;/path&gt;
-</pre>
-
-<h5>includeSemanticAttribute="true"</h5>
-<p>This entry in a build file:
-<pre>   &lt;xmlproperty file="somefile.xml"
-                semanticAttributes="true" keepRoot="false"
-                includeSemanticAttribute="true"/&gt;
-</pre>
-is equivalent to the following entries in a build file:
+&lt;xmlproperty file="somefile.xml" keepRoot="false"
+             semanticAttributes="true"/&gt;</pre>
+<p>is equivalent to the following entries in a build file:</p>
 <pre>
-  &lt;property name="version.value" value="0.0.1"/&gt;
-  &lt;property name="build.folder" value="build"/&gt;
-  &lt;property name="build.classes.location" location="${build.folder}/classes"/&gt;
-  &lt;property name="build.reference.refid" refid="build.classes"/&gt;
+&lt;property name="version" value="0.0.1"/&gt;
+&lt;property name="build.folder" value="build"/&gt;
+&lt;property name="build.classes" location="${build.folder}/classes" id="build.classes"/&gt;
+&lt;property name="build.reference" refid="build.classes"/&gt;
 
-  &lt;property name="run-time.jars" value="*.jar"/&gt;
+&lt;property name="run-time.jars" value="*.jar"/&gt;
 
-  &lt;path id="compile.classpath"&gt;
-    &lt;pathelement location="${build.classes}"/&gt;
-  &lt;/path&gt;
+&lt;path id="compile.classpath"&gt;
+  &lt;pathelement location="${build.classes}"/&gt;
+&lt;/path&gt;
 
-  &lt;path id="run-time.classpath"&gt;
-    &lt;path refid="compile.classpath"/&gt;
-    &lt;pathelement path="${run-time.jars}"/&gt;
-  &lt;/path&gt;
-</pre>
+&lt;path id="run-time.classpath"&gt;
+  &lt;path refid="compile.classpath"/&gt;
+  &lt;pathelement path="${run-time.jars}"/&gt;
+&lt;/path&gt;</pre>
 
+<h5><var>includeSemanticAttribute</var>=<q>true</q></h5>
+<p>This entry in a build file:</p>
+<pre>
+&lt;xmlproperty file="somefile.xml"
+             semanticAttributes="true" keepRoot="false"
+             includeSemanticAttribute="true"/&gt;</pre>
+<p>is equivalent to the following entries in a build file:</p>
+<pre>
+&lt;property name="version.value" value="0.0.1"/&gt;
+&lt;property name="build.folder" value="build"/&gt;
+&lt;property name="build.classes.location" location="${build.folder}/classes"/&gt;
+&lt;property name="build.reference.refid" refid="build.classes"/&gt;
 
+&lt;property name="run-time.jars" value="*.jar"/&gt;
+
+&lt;path id="compile.classpath"&gt;
+  &lt;pathelement location="${build.classes}"/&gt;
+&lt;/path&gt;
+
+&lt;path id="run-time.classpath"&gt;
+  &lt;path refid="compile.classpath"/&gt;
+  &lt;pathelement path="${run-time.jars}"/&gt;
+&lt;/path&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Tasks/xmlvalidate.html b/manual/Tasks/xmlvalidate.html
index c362bbe..9f92a0c 100644
--- a/manual/Tasks/xmlvalidate.html
+++ b/manual/Tasks/xmlvalidate.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
@@ -23,241 +24,211 @@
 
 <body>
 
-<h2><a name="xmlvalidate">XMLValidate</a></h2>
+<h2 id="xmlvalidate">XMLValidate</h2>
 <h3>Description</h3>
 
-<p>This task checks that XML files are valid (or only well formed). The
-task uses the SAX2 parser implementation provided by JAXP by default
-(probably the one that is used by Apache Ant itself), but one can specify any
-SAX1/2 parser if needed.</p>
+<p>This task checks that XML files are valid (or only well formed). The task uses the SAX2 parser
+implementation provided by JAXP by default (probably the one that is used by Apache Ant itself), but
+one can specify any SAX1/2 parser if needed.</p>
 
-<p>This task supports the use of nested
-  <li><a href="../Types/xmlcatalog.html"><tt>&lt;xmlcatalog&gt;</tt></a> elements</li>
-  <li><tt>&lt;dtd&gt;</tt> elements which are used to resolve DTDs and entities</li>
-  <li><tt>&lt;attribute&gt;</tt> elements which are used to set features on the parser.
-      These can be any number of
-      <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"><tt>http://xml.org/sax/features/</tt></a>
-      or other features that your parser may support.</li>
-  <li><tt>&lt;property&gt;</tt> elements, containing string properties
-</p>
+<p>This task supports the use of nested</p>
+<ul>
+  <li><a href="../Types/xmlcatalog.html"><code>&lt;xmlcatalog&gt;</code></a> elements</li>
+  <li><code>&lt;dtd&gt;</code> elements which are used to resolve DTDs and entities</li>
+  <li><code>&lt;attribute&gt;</code> elements which are used to set features on the parser.  These
+    can be any number
+    of <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
+    target="_top"><code>http://xml.org/sax/features/</code></a> or other features that your parser
+    may support.</li>
+  <li><code>&lt;property&gt;</code> elements, containing string properties</li>
+</ul>
 
-<p><b>Warning</b> : JAXP creates by default a non namespace aware parser.
-The <tt>"http://xml.org/sax/features/namespaces"</tt> feature is set
-by default to <tt>false</tt> by the JAXP implementation used by ant. To validate
-a document containing namespaces,
-set the namespaces feature to <tt>true</tt> explicitly by nesting the following element:
-<pre>
-  &lt;attribute name="http://xml.org/sax/features/namespaces" value="true"/&gt;
-</pre>
-If you are using for instance a <tt>xsi:noNamespaceSchemaLocation</tt> attribute in your XML files,
-you will need this namespace support feature.
-</p>
-<p>If you are using a parser not generated by JAXP, by using the <tt>classname</tt> attribute of xmlvalidate, this warning
-may not apply.</p>
-
+<p><strong>Warning</strong>: By default, JAXP creates a non namespace aware parser.
+The <var>http://xml.org/sax/features/namespaces</var> feature is set by default to <q>false</q> by
+the JAXP implementation used by Ant. To validate a document containing namespaces, set the
+namespaces feature to <q>true</q> explicitly by nesting the following element:</p>
+<pre>&lt;attribute name="http://xml.org/sax/features/namespaces" value="true"/&gt;</pre>
+<p>If you are using for instance a <code>xsi:noNamespaceSchemaLocation</code> attribute in your XML
+files, you will need this namespace support feature.</p>
+<p>If you are using a parser not generated by JAXP, by using the <var>classname</var> attribute
+of <code>xmlvalidate</code>, this warning may not apply.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">the file(s) you want to check. (optionally can use an embedded fileset)</td>
-    <td valign="top" align="center">No</td>
+    <td>file</td>
+    <td>the file(s) you want to check.</td>
+    <td>Yes, unless an embedded <code>&lt;fileset&gt;</code> is specified</td>
   </tr>
   <tr>
-    <td valign="top">lenient</td>
-    <td valign="top">
-      if true, only check the XML document is well formed
-        (ignored if the specified parser is a SAX1 parser)
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>lenient</td>
+    <td>if <q>true</q>, only check the XML document is well formed (ignored if the specified parser
+      is a SAX1 parser).</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">the parser to use.</td>
-    <td align="center" valign="top">No</td>
+    <td>classname</td>
+    <td>the parser to use.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">where to find the parser class. Optionally can use an embedded <tt>&lt;classpath&gt;</tt> element.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>where to find the parser class.</td>
+    <td>No, can use an embedded <code>&lt;classpath&gt;</code> element</td>
   </tr>
   <tr>
-    <td valign="top">failonerror</td>
-    <td valign="top">fails on a error if set to true (defaults to true).</td>
-    <td align="center" valign="top">No</td>
+    <td>failonerror</td>
+    <td>fails on a error if set to <q>true</q>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">warn</td>
-    <td valign="top">log parser warn events.</td>
-    <td align="center" valign="top">No</td>
+    <td>warn</td>
+    <td>log parser warn events.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3><a name="nested">Nested Elements</a></h3>
+<h3 id="nested">Parameters specified as nested elements</h3>
 <h4>dtd</h4>
-<p>
-<tt>&lt;dtd&gt;</tt> is used to specify different locations for DTD resolution.
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
+<p><code>&lt;dtd&gt;</code> is used to specify different locations for DTD resolution.</p>
+<table class="attr">
   <tr>
-    <td valign="top">publicId</td>
-    <td valign="top">Public ID of the DTD to resolve</td>
-    <td align="center" valign="top">Yes</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">location</td>
-    <td valign="top">Location of the DTD to use, which can be a file,
-    a resource, or a URL</td>
-    <td align="center" valign="top">Yes</td>
+    <td>publicId</td>
+    <td>Public ID of the DTD to resolve</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>location</td>
+    <td>Location of the DTD to use, which can be a file, a resource, or a URL</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h4>xmlcatalog</h4>
-<p>The <a href="../Types/xmlcatalog.html"><tt>&lt;xmlcatalog&gt;</tt></a>
-element is used to perform entity resolution.</p>
+<p>The <a href="../Types/xmlcatalog.html"><code>&lt;xmlcatalog&gt;</code></a> element is used to
+perform entity resolution.</p>
 <h4>attribute</h4>
-<p>The <tt>&lt;attribute&gt;</tt> element is used to set parser features.<br>
-Features usable with the xerces parser are defined here :
- <a href="http://xml.apache.org/xerces-j/features.html">Setting features</a><br>
-
-SAX features are defined here:
- <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"><tt>http://xml.org/sax/features/</tt></a><br>
- </p>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
+<p>The <code>&lt;attribute&gt;</code> element is used to set parser features.</p>
+<p>Features usable with the Xerces parser are defined
+here: <a href="https://xml.apache.org/xerces-j/features.html" target="_top">Setting Features</a></p>
+<p>SAX features are defined
+here: <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
+target="_top">SAX2 Standard Feature Flags</a></p>
+<table class="attr">
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The boolean value of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the feature</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>The boolean value of the feature</td>
+    <td>Yes</td>
   </tr>
 </table>
-</p>
 
 <h4>property</h4>
-<p>The <tt>&lt;property&gt;</tt> element is used to set properties.
-These properties are defined here for the xerces XML parser implementation :
- <a href="http://xml.apache.org/xerces-j/properties.html">XML Parser properties</a>
-Properties can be used to set the schema used to validate the XML file.
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
-<tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
-</tr>
+<p>The <code>&lt;property&gt;</code> element is used to set properties.  These properties are
+defined here for the Xerces XML parser
+implementation: <a href="https://xml.apache.org/xerces-j/properties.html" target="_top">XML Parser
+properties</a>. Properties can be used to set the schema used to validate the XML file.</p>
+<table class="attr">
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the feature</td>
-    <td align="center" valign="top">Yes</td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The string value of the property</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the feature</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>value</td>
+    <td>The string value of the property</td>
+    <td>Yes</td>
   </tr>
 </table>
-</p>
-
 
 <h3>Examples</h3>
-<pre>
-&lt;xmlvalidate file="toto.xml"/&gt;
-</pre>
-Validate toto.xml
+<p>Validate <samp>toto.xml</samp></p>
+<pre>&lt;xmlvalidate file="toto.xml"/&gt;</pre>
+
+<p>Validate all <samp>.xsl</samp> files in <samp>src/style</samp>, but only warn if there is an
+error, rather than halt the build.</p>
 <pre>
 &lt;xmlvalidate failonerror="no" lenient="yes" warn="yes"
              classname="org.apache.xerces.parsers.SAXParser"&gt;
              classpath="lib/xerces.jar"&gt;
   &lt;fileset dir="src" includes="style/*.xsl"/&gt;
-&lt;/xmlvalidate&gt;
-</pre>
-Validate all .xsl files in src/style, but only warn if there is an error, rather than
-halt the build.
-<pre>
+&lt;/xmlvalidate&gt;</pre>
 
+<p>Validate a struts configuration, using a local copy of the DTD.</p>
+<pre>
 &lt;xmlvalidate file="struts-config.xml" warn="false"&gt;
   &lt;dtd publicId="-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
        location="struts-config_1_0.dtd"/&gt;
-&lt;/xmlvalidate&gt;
-</pre>
+&lt;/xmlvalidate&gt;</pre>
 
-Validate a struts configuration, using a local copy of the DTD. 
-<pre> 
+<p>Scan all XML files in the project, using a predefined catalog to map URIs to local files.</p>
+<pre>
 &lt;xmlvalidate failonerror="no"&gt;
   &lt;fileset dir="${project.dir}" includes="**/*.xml"/&gt;
   &lt;xmlcatalog refid="mycatalog"/&gt;
-&lt;/xmlvalidate&gt;
-</pre>
+&lt;/xmlvalidate&gt;</pre>
 
-Scan all XML files in the project, using a predefined catalog to map URIs to local files.
+<p>Scan all XML files in the project, using the catalog defined inline.</p>
 <pre>
 &lt;xmlvalidate failonerror="no"&gt;
   &lt;fileset dir="${project.dir}" includes="**/*.xml"/&gt;
   &lt;xmlcatalog&gt;
-       &lt;dtd
-         publicId=&quot;-//ArielPartners//DTD XML Article V1.0//EN&quot;
+    &lt;dtd publicId=&quot;-//ArielPartners//DTD XML Article V1.0//EN&quot;
          location=&quot;com/arielpartners/knowledgebase/dtd/article.dtd&quot;/&gt;
   &lt;/xmlcatalog&gt;
-&lt;/xmlvalidate&gt;
-</pre>
-Scan all XML files in the project, using the catalog defined inline.
+&lt;/xmlvalidate&gt;</pre>
 
+<p>Validate all <samp>.xml</samp> files in <samp>xml</samp> directory with the parser configured to
+perform XSD validation. Note: The parser must support the
+feature <var>http://apache.org/xml/features/validation/schema</var>. The <a href="schemavalidate.html">schemavalidate</a>
+task is better for validating W3C XML Schemas, as it extends this task with the right options
+automatically enabled, and makes it easy to add a list of schema files/URLs to act as sources.</p>
 <pre>
 &lt;xmlvalidate failonerror="yes" lenient="no" warn="yes"&gt;
   &lt;fileset dir="xml" includes="**/*.xml"/&gt;
   &lt;attribute name="http://xml.org/sax/features/validation" value="true"/&gt;
   &lt;attribute name="http://apache.org/xml/features/validation/schema"  value="true"/&gt;
   &lt;attribute name="http://xml.org/sax/features/namespaces" value="true"/&gt;
-&lt;/xmlvalidate&gt;
-</pre>
-Validate all .xml files in xml directory with the parser configured to perform XSD validation.
-Note: The parser must support the feature
-<code>http://apache.org/xml/features/validation/schema</code>.
-The <a href="schemavalidate.html">schemavalidate</a> task is better for validating
-W3C XML Schemas, as it extends this task with the right options automatically enabled,
-and makes it easy to add a list of schema files/URLs to act as sources.
+&lt;/xmlvalidate&gt;</pre>
 
+<p>Validate the file <samp>xml/endpiece-noSchema.xml</samp> against the
+schema <samp>xml/doc.xsd</samp>.</p>
 <pre>
-<!-- Converts path to URL format -->
+&lt;!-- Convert path to URL format --&gt;
 &lt;pathconvert dirsep="/" property="xsd.file"&gt;
 &lt;path&gt;
    &lt;pathelement location="xml/doc.xsd"/&gt;
 &lt;/path&gt;
 &lt;/pathconvert&gt;
 
-&lt;xmlvalidate file="xml/endpiece-noSchema.xml" lenient="false"
-  failonerror="true" warn="true"&gt;
-  &lt;attribute name="http://apache.org/xml/features/validation/schema"
-  value="true"/&gt;
+&lt;xmlvalidate file="xml/endpiece-noSchema.xml" lenient="false" failonerror="true" warn="true"&gt;
+  &lt;attribute name="http://apache.org/xml/features/validation/schema" value="true"/&gt;
   &lt;attribute name="http://xml.org/sax/features/namespaces" value="true"/&gt;
-  &lt;property
-  name="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"
-  value="${xsd.file}"/&gt;
-&lt;/xmlvalidate&gt;
-</pre>
-<br>
-Validate the file xml/endpiece-noSchema.xml against the schema xml/doc.xsd.
-<br>
-
-
+  &lt;property name="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"
+            value="${xsd.file}"/&gt;
+&lt;/xmlvalidate&gt;</pre>
 </body>
 </html>
-
diff --git a/manual/Tasks/zip.html b/manual/Tasks/zip.html
index 3c7d0e0..e24de54 100644
--- a/manual/Tasks/zip.html
+++ b/manual/Tasks/zip.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,271 +15,246 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Zip Task</title>
 </head>
 
 <body>
 
-<h2><a name="zip">Zip</a></h2>
+<h2 id="zip">Zip</h2>
 <h3>Description</h3>
 <p>Creates a zipfile.</p>
-<p>The <i>basedir</i> attribute is the reference directory from where to zip.</p>
+<p>The <var>basedir</var> attribute is the reference directory from where to zip.</p>
 <p>Note that file permissions will not be stored in the resulting zipfile.</p>
-<p>It is possible to refine the set of files that are being zipped. This can be
-done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and <i>defaultexcludes</i>
-attributes. With the <i>includes</i> or <i>includesfile</i> attribute you specify the files you want to
-have included by using patterns. The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
-the files you want to have excluded. This is also done with patterns. And
-finally with the <i>defaultexcludes</i> attribute, you can specify whether you
-want to use default exclusions or not. See the section on <a
-href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
-inclusion/exclusion of files works, and how to write patterns. </p>
-<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and
-supports most attributes of <code>&lt;fileset&gt;</code>
-(<code>dir</code> becomes <code>basedir</code>) as well as the nested
-<code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
-<code>&lt;patternset&gt;</code> elements.</p>
-<p>Or, you may place within it nested file sets, or references to file sets.
-In this case <code>basedir</code> is optional; the implicit file set is <i>only used</i>
-if <code>basedir</code> is set. You may use any mixture of the implicit file set
-(with <code>basedir</code> set, and optional attributes like <code>includes</code>
-and optional subelements like <code>&lt;include&gt;</code>); explicit nested
-<code>&lt;fileset&gt;</code> elements so long as at least one fileset total is specified. The ZIP file will
-only reflect the relative paths of files <i>within</i> each fileset. The Zip task and its derivatives know a special form of a fileset named zipfileset that has additional attributes (described below). </p>
-<p>The Zip task also supports the merging of multiple zip files into the zip file. 
-This is possible through either the <i>src</i> attribute of any nested filesets 
-or by using the special nested fileset <i>zipgroupfileset</i>.</p>
 
-<p>The <code>update</code> parameter controls what happens if the ZIP
-file already exists. When set to <code>yes</code>, the ZIP file is
-updated with the files specified. (New files are added; old files are
-replaced with the new versions.) When set to <code>no</code> (the
-default) the ZIP file is overwritten if any of the files that would be
-added to the archive are newer than the entries inside the archive.
-Please note that ZIP files store file modification times with a
-granularity of two seconds.  If a file is less than two seconds newer
-than the entry in the archive, Apache Ant will not consider it newer.</p>
+<p>It is possible to refine the set of files that are being zipped. This can be done with
+the <var>includes</var>, <var>includesfile</var>, <var>excludes</var>, <var>excludesfile</var>
+and <var>defaultexcludes</var> attributes. With the <var>includes</var> or <var>includesfile</var>
+attribute you specify the files you want to have included by using patterns. The <var>exclude</var>
+or <var>excludesfile</var> attribute is used to specify the files you want to have excluded. This is
+also done with patterns. And finally with the <var>defaultexcludes</var> attribute, you can specify
+whether you want to use default exclusions or not. See the section
+on <a href="../dirtasks.html#directorybasedtasks">directory based tasks</a>, on how the
+inclusion/exclusion of files works, and how to write patterns.</p>
 
-<p>The <code>whenempty</code> parameter controls what happens when no files match.
-If <code>skip</code> (the default), the ZIP is not created and a warning is issued.
-If <code>fail</code>, the ZIP is not created and the build is halted with an error.
-If <code>create</code>, an empty ZIP file (explicitly zero entries) is created,
-which should be recognized as such by compliant ZIP manipulation tools.</p>
-<p>This task will now use the platform's default character encoding
-for filenames - this is consistent with the command line ZIP tools,
-but causes problems if you try to open them from within Java and your
-filenames contain non US-ASCII characters. Use the encoding attribute
-and set it to UTF8 to create zip files that can safely be read by
-Java.  For a more complete discussion,
+<p>This task forms an implicit <a href="../Types/fileset.html">FileSet</a> and supports most
+attributes of <code>&lt;fileset&gt;</code> (<var>dir</var> becomes <var>basedir</var>) as well as
+the nested <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;patternset&gt;</code> elements.</p>
+
+<p>Or, you may place within it nested file sets, or references to file sets.  In this
+case <var>basedir</var> is optional; the implicit file set is <em>only used</em>
+if <var>basedir</var> is set. You may use any mixture of the implicit file set
+(with <var>basedir</var> set, and optional attributes like <var>includes</var> and optional
+subelements like <code>&lt;include&gt;</code>); explicit nested <code>&lt;fileset&gt;</code>
+elements so long as at least one fileset total is specified. The ZIP file will only reflect the
+relative paths of files <em>within</em> each fileset. The Zip task and its derivatives know a
+special form of a fileset named <code>zipfileset</code> that has additional attributes (described
+below).</p>
+
+<p>The Zip task also supports the merging of multiple zip files into the zip file.  This is possible
+through either the <var>src</var> attribute of any nested filesets or by using the special nested
+fileset <code>zipgroupfileset</code>.</p>
+
+<p>The <var>update</var> parameter controls what happens if the ZIP file already exists. When set
+to <q>yes</q>, the ZIP file is updated with the files specified. (New files are added; old files are
+replaced with the new versions.) When set to <q>no</q> (the default) the ZIP file is overwritten if
+any of the files that would be added to the archive are newer than the entries inside the archive.
+Please note that ZIP files store file modification times with a granularity of 2 seconds.  If a file
+is less than 2 seconds newer than the entry in the archive, Apache Ant will not consider it
+newer.</p>
+
+<p>The <var>whenempty</var> parameter controls what happens when no files match.  If <q>skip</q>
+(the default), the ZIP is not created and a warning is issued.  If <q>fail</q>, the ZIP is not
+created and the build is halted with an error.  If <q>create</q>, an empty ZIP file (explicitly zero
+entries) is created, which should be recognized as such by compliant ZIP manipulation tools.</p>
+
+<p>This task will now use default JVM character encoding for filenames&mdash;this is consistent with
+the command line ZIP tools, but causes problems if you try to open them from within Java and your
+filenames contain non US-ASCII characters. Use the <var>encoding</var> attribute and set it
+to <q>UTF8</q> to create zip files that can safely be read by Java.  For a more complete discussion,
 see <a href="#encoding">below</a></p>
 
-<p>Starting with Ant 1.5.2, <code>&lt;zip&gt;</code> can store Unix permissions
-inside the archive (see description of the filemode and dirmode
-attributes for <a href="../Types/zipfileset.html">&lt;zipfileset&gt;</a>).
-Unfortunately there is no portable way to store these permissions.
-Ant uses the algorithm used by <a href="http://www.info-zip.org">Info-Zip's</a>
-implementation of the zip and unzip commands - these are the default
-versions of zip and unzip for many Unix and Unix-like systems.</p>
+<p><em>Since Ant 1.5.2</em>, <code>&lt;zip&gt;</code> can store Unix permissions inside the archive
+(see description of the <var>filemode</var> and <var>dirmode</var> attributes
+for <a href="../Types/zipfileset.html">&lt;zipfileset&gt;</a>).  Unfortunately there is no portable
+way to store these permissions.  Ant uses the algorithm used by <a href="http://www.info-zip.org"
+target="_top">Info-Zip's</a> implementation of the <kbd>zip</kbd> and <kbd>unzip</kbd>
+commands&mdash;these are the default versions of <kbd>zip</kbd> and <kbd>unzip</kbd> for many
+Unix(-like) systems.</p>
 
-<p><b>Please note that the zip format allows multiple files of the same
-fully-qualified name to exist within a single archive.  This has been
-documented as causing various problems for unsuspecting users.  If you wish
-to avoid this behavior you must set the <code>duplicate</code> attribute
-to a value other than its default, <code>&quot;add&quot;</code>.</b></p>
+<p><strong>Please note that the zip format allows multiple files of the same fully-qualified name to
+exist within a single archive.  This has been documented as causing various problems for
+unsuspecting users.  If you wish to avoid this behavior you must set the <var>duplicate</var>
+attribute to a value other than its default, <q>add</q>.</strong></p>
 
-<p><b>Please also note</b> that different ZIP tools handle timestamps
-differently when it comes to applying timezone offset calculations of
-files.  Some ZIP libraries will store the timestamps as they've been
-read from the filesystem while others will modify the timestamps both
-when reading and writing the files to make all timestamps use the same
-timezone.  A ZIP archive created by one library may extract files with
-"wrong timestamps" when extracted by another library.</p>
+<p><strong>Please also note</strong> that different ZIP tools handle timestamps differently when it
+comes to applying timezone offset calculations of files.  Some ZIP libraries will store the
+timestamps as they've been read from the filesystem while others will modify the timestamps both
+when reading and writing the files to make all timestamps use the same timezone.  A ZIP archive
+created by one library may extract files with "wrong timestamps" when extracted by another
+library.</p>
 
-<p>Ant's ZIP classes use the same algorithm as the InfoZIP tools and
-zlib (timestamps get adjusted), Windows' "compressed folders" function
-and WinZIP don't change the timestamps.  This means that using the
-unzip task on files created by Windows' compressed folders function
-may create files with timestamps that are "wrong", the same is true if
-you use Windows' functions to extract an Ant generated ZIP
-archive.</p>
+<p>Ant's ZIP classes use the same algorithm as the InfoZIP tools and zlib (timestamps get adjusted),
+Windows' "compressed folders" function and WinZIP don't change the timestamps.  This means that
+using the <code>unzip</code> task on files created by Windows' compressed folders function may
+create files with timestamps that are "wrong", the same is true if you use Windows' functions to
+extract an Ant generated ZIP archive.</p>
 
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td valign="top" align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">destfile</td>
-    <td valign="top">the zip-file to create.</td>
-    <td align="center" valign="top" rowspan="2">Exactly one of the two.</td>
+    <td>destfile</td>
+    <td>the zip file to create.</td>
+    <td rowspan="2">Exactly one of the two</td>
   </tr>
   <tr>
-    <td valign="top">zipfile</td>
-    <td valign="top">the <i>deprecated</i> old name of destfile.</td>
+    <td>zipfile</td>
+    <td class="left"><em><u>deprecated</u></em> old name of <var>destfile</var>.</td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the directory from which to zip the files.</td>
-    <td align="center" valign="top">No</td>
+    <td>basedir</td>
+    <td>the directory from which to zip the files.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">compress</td>
-    <td valign="top">Not only store data but also compress them,
-    defaults to true.  Unless you set the <em>keepcompression</em>
-    attribute to false, this will apply to the entire archive, not
-    only the files you've added while updating.</td>
-    <td align="center" valign="top">No</td>
+    <td>compress</td>
+    <td>Not only store data but also compress them.  Unless you set the <var>keepcompression</var>
+      attribute to <q>false</q>, this will apply to the entire archive, not only the files you've
+      added while updating.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">keepcompression</td>
-    <td valign="top">For entries coming from existing archives (like
-    nested <em>zipfileset</em>s or while updating the archive), keep
-    the compression as it has been originally instead of using the
-    <em>compress</em> attribute.  Defaults false.  <em>Since Ant
-    1.6</em></td>
-    <td align="center" valign="top">No</td>
+    <td>keepcompression</td>
+    <td>For entries coming from existing archives (like nested <code>zipfileset</code>s or while
+      updating the archive), keep the compression as it has been originally instead of using
+      the <var>compress</var> attribute. <em>Since Ant 1.6</em></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The character encoding to use for filenames
-    inside the zip file.  For a list of possible values see the <a
-                href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">Supported Encodings</a>.<br/>
-    Defaults to the platform's default character encoding.
-      <br/>See also the <a href="#encoding">discussion below</a></td>
-    <td align="center" valign="top">No</td>
+    <td>encoding</td>
+    <td>The character encoding to use for filenames inside the zip file.  For a list of possible
+      values see
+      the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+      target="_top">Supported Encodings</a>.</td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">filesonly</td>
-    <td valign="top">Store only file entries, defaults to false</td>
-    <td align="center" valign="top">No</td>
+    <td>filesonly</td>
+    <td>Store only file entries.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all (<q>**</q>)</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an include pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>name of a file. Each line of this file is taken to be an include pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded. No files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file. Each line of this file is
-      taken to be an exclude pattern</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file. Each line of this file is taken to be an exclude pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether default excludes should be used or not
-      (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether default excludes should be used or not (<q>yes|no</q>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">update</td>
-    <td valign="top">indicates whether to update or overwrite
-      the destination file if it already exists.  Default is &quot;false&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>update</td>
+    <td>indicates whether to update or overwrite the destination file if it already exists.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">whenempty</td>
-    <td valign="top">behavior when no files match.  Valid values are &quot;fail&quot;, &quot;skip&quot;, and &quot;create&quot;.  Default is &quot;skip&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>whenempty</td>
+    <td>behavior when no files match.  Valid values are <q>fail</q>, <q>skip</q>,
+      and <q>create</q>.</td>
+    <td>No; default is <q>skip</q></td>
   </tr>
   <tr>
-    <td valign="top">duplicate</td>
-    <td valign="top">behavior when a duplicate file is found.  Valid values are &quot;add&quot;, &quot;preserve&quot;, and &quot;fail&quot;. The default value is &quot;add&quot;.  </td>
-    <td valign="top" align="center">No</td>
+    <td>duplicate</td>
+    <td>behavior when a duplicate file is found.  Valid values are <q>add</q>, <q>preserve</q>,
+      and <q>fail</q>.</td>
+    <td>No; default is <q>add</q></td>
   </tr>
   <tr>
-    <td valign="top">roundup</td>
-    <td valign="top">Whether the file modification times will be
-    rounded up to the next even number of seconds.<br>
-    Zip archives store file modification times with a granularity of
-    two seconds, so the times will either be rounded up or down.  If
-    you round down, the archive will always seem out-of-date when you
-    rerun the task, so the default is to round up.  Rounding up may
-    lead to a different type of problems like JSPs inside a web
-    archive that seem to be slightly more recent than precompiled
-    pages, rendering precompilation useless.<br>
-    Defaults to true.  <em>Since Ant 1.6.2</em></td>
-    <td align="center" valign="top">No</td>
+    <td>roundup</td>
+    <td>Whether the file modification times will be rounded up to the next even number of
+      seconds.<br/>Zip archives store file modification times with a granularity of 2 seconds, so
+      the times will either be rounded up or down. If you round down, the archive will always seem
+      out-of-date when you rerun the task, so the default is to round up.  Rounding up may lead to a
+      different type of problems like JSPs inside a web archive that seem to be slightly more recent
+      than precompiled pages, rendering precompilation useless. <em>Since Ant 1.6.2</em></td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">comment</td>
-    <td valign="top">Comment to store in the archive. <em>Since Ant 1.6.3</em></td>
-    <td valign="top" align="center">No</td>
+    <td>comment</td>
+    <td>Comment to store in the archive. <em>Since Ant 1.6.3</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">level</td>
-    <td valign="top">Non-default level at which file compression should be
-    performed. Valid values range from 0 (no compression/fastest) to 9
-    (maximum compression/slowest). <em>Since Ant 1.7</em></td>
-    <td valign="top" align="center">No</td>
+    <td>level</td>
+    <td>Non-default level at which file compression should be performed. Valid values range
+      from <q>0</q> (no compression/fastest) to <q>9</q> (maximum compression/slowest). <em>Since
+      Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">preserve0permissions</td>
-    <td valign="top">when updating an archive or adding entries from a
-    different archive Ant will assume that a Unix permissions value of
-    0 (nobody is allowed to do anything to the file/directory) means
-    that the permissions haven't been stored at all rather than real
-    permissions and will instead apply its own default values.<br/>
-    Set this attribute to true if you really want to preserve the
-      original permission field.<em>since Ant 1.8.0</em>
+    <td>preserve0permissions</td>
+    <td>when updating an archive or adding entries from a different archive Ant will assume that a
+      Unix permissions value of 0 (nobody is allowed to do anything to the file/directory) means
+      that the permissions haven't been stored at all rather than real permissions and will instead
+      apply its own default values.<br/>  Set this attribute to <q>true</q> if you really want to
+      preserve the original permission field. <em>Since Ant 1.8.0</em>
     </td>
-    <td valign="top" align="center">No, default is false</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">useLanguageEncodingFlag</td>
-    <td valign="top">Whether to set the language encoding flag if the
-      encoding is UTF-8.  This setting doesn't have any effect if the
-      encoding is not UTF-8.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="#encoding">discussion below</a></td>
-    <td align="center" valign="top">No, default is true</td>
+    <td>useLanguageEncodingFlag</td>
+    <td>Whether to set the language encoding flag if the encoding is UTF-8. This setting doesn't
+      have any effect if the encoding is not UTF-8.  <em>Since Ant 1.8.0</em>.<br/>See also
+      the <a href="#encoding">discussion below</a></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">createUnicodeExtraFields</td>
-    <td valign="top">Whether to create unicode extra fields to store
-      the file names a second time inside the entry's metadata.
-      <br>Possible values are "never", "always" and "not-encodeable"
-      which will only add Unicode extra fields if the file name cannot
-      be encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="#encoding">discussion below</a></td>
-    <td align="center" valign="top">No, default is "never"</td>
+    <td>createUnicodeExtraFields</td>
+    <td>Whether to create Unicode extra fields to store the file names a second time inside the
+      entry's metadata.<br/>Possible values are <q>never</q>, <q>always</q>
+      and <q>not-encodeable</q> which will only add Unicode extra fields if the file name cannot be
+      encoded using the specified encoding.  <em>Since Ant 1.8.0</em>.<br/>See also
+      the <a href="#encoding">discussion below</a></td>
+    <td>No; default is <q>never</q></td>
   </tr>
   <tr>
-    <td valign="top">fallbacktoUTF8</td>
-    <td valign="top">Whether to use UTF-8 and the language encoding
-      flag instead of the specified encoding if a file name cannot be
-      encoded using the specified encoding.
-      <em>Since Ant 1.8.0</em>.
-      <br/>See also the <a href="#encoding">discussion below</a></td>
-    <td align="center" valign="top">No, default is false</td>
+    <td>fallbacktoUTF8</td>
+    <td>Whether to use UTF-8 and the language encoding flag instead of the specified encoding if a
+      file name cannot be encoded using the specified encoding.  <em>Since Ant 1.8.0</em>.<br/>See
+      also the <a href="#encoding">discussion below</a></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">zip64Mode</td>
-    <td valign="top">When to use Zip64 extensions for entries.  The
-      possible values are "never", "always" and "as-needed".
-      <em>Since Ant 1.9.1</em>.
-      <br/>See also the <a href="#zip64">discussion below</a></td>
-    <td align="center" valign="top">No, default is "as-needed"</td>
+    <td>zip64Mode</td>
+    <td>When to use Zip64 extensions for entries.  The possible values
+      are <q>never</q>, <q>always</q> and <q>as-needed</q>.  <em>Since Ant 1.9.1</em>.<br/>See also
+      the <a href="#zip64">discussion below</a></td>
+    <td>No; default is <q>as-needed</q></td>
   </tr>
   <tr>
     <td valign="top">modificationtime</td>
@@ -286,276 +262,236 @@
     given time. This can either be a number interpreted as
     milliseconds since 1970-01-01T00:00:00Z or a string that can be
     parsed as a ISO 8601 timestamp with optional timezone.
-      <em>Since Ant 1.9.10</em>.
+      <em>Since Ant 1.10.2</em>.
     </td>
     <td align="center" valign="top">No</td>
   </tr>
 </table>
 
-<h3><a name="encoding">Encoding of File Names</a></h3>
+<h3 id="encoding">Encoding of file names</h3>
 
-<p>Traditionally the ZIP archive format uses CodePage 437 as encoding
-  for file name, which is not sufficient for many international
-  character sets.</p>
+<p>Traditionally the ZIP archive format uses CodePage 437 as encoding for file name, which is not
+sufficient for many international character sets.</p>
 
-<p>Over time different archivers have chosen different ways to work
-  around the limitation - the <code>java.util.zip</code> packages
-  simply uses UTF-8 as its encoding for example.</p>
+<p>Over time different archivers have chosen different ways to work around the
+limitation&mdash;the <code class="code">java.util.zip</code> packages simply uses UTF-8 as its
+encoding for example.</p>
 
-<p>Ant has been offering the encoding attribute of the zip and unzip
-  task as a way to explicitly specify the encoding to use (or expect)
-  since Ant 1.4.  It defaults to the platform's default encoding for
-  zip and UTF-8 for jar and other jar-like tasks (war, ear, ...) as
-  well as the unzip family of tasks.</p>
+<p>Ant has been offering the <q>encoding</q> attribute of the <code>zip</code>
+and <code>unzip</code> task as a way to explicitly specify the encoding to use (or expect) <em>since
+Ant 1.4</em>.  It defaults to default JVM character encoding for <code>zip</code> and UTF-8
+for <code>jar</code> and other jar-like tasks (<code>war</code>, <code>ear</code>, ...) as well as
+the <code>unzip</code> family of tasks.</p>
 
-<p>More recent versions of the ZIP specification introduce something
-  called the &quot;language encoding flag&quot; which can be used to
-  signal that a file name has been encoded using UTF-8.  Starting with
-  Ant 1.8.0 all zip-/jar- and similar archives written by Ant will set
-  this flag, if the encoding has been set to UTF-8.  Our
-  interoperabilty tests with existing archivers didn't show any ill
-  effects (in fact, most archivers ignore the flag to date), but you
-  can turn off the "language encoding flag" by setting the attribute
-  <code>useLanguageEncodingFlag</code> to <code>false</code> on the
-  zip-task if you should encounter problems.</p>
+<p>More recent versions of the ZIP specification introduce something called the <q>language encoding
+flag</q> which can be used to signal that a file name has been encoded using UTF-8. <em>Since Ant
+1.8.0</em>, all zip, jar and similar archives written by Ant will set this flag, if the encoding has
+been set to UTF-8.  Our interoperability tests with existing archivers didn't show any ill effects
+(in fact, most archivers ignore the flag to date), but you can turn off the <q>language encoding
+flag</q> by setting the attribute <var>useLanguageEncodingFlag</var> to <q>false</q> on
+the <code>zip</code> task if you should encounter problems.</p>
 
-<p>The unzip (and similar tasks) -task will recognize the language
-  encoding flag and ignore the encoding set on the task if it has been
-  found.</p>
+<p>The <code>unzip</code> task (and similar tasks) will recognize the language encoding flag and
+ignore the encoding set on the task if it has been found.</p>
 
-<p>The InfoZIP developers have introduced new ZIP extra fields that
-  can be used to add an additional UTF-8 encoded file name to the
-  entry's metadata.  Most archivers ignore these extra fields.  The
-  zip family of tasks support an
-  option <code>createUnicodeExtraFields</code> since Ant 1.8.0 which
-  makes Ant write these extra fields either for all entries ("always")
-  or only those whose name cannot be encoded using the specified
-  encoding (not-encodeable), it defaults to "never" since the extra
-  fields create bigger archives.</p>
+<p>The InfoZIP developers have introduced new ZIP extra fields that can be used to add an additional
+UTF-8 encoded file name to the entry's metadata.  Most archivers ignore these extra
+fields.  <em>Since Ant 1.8.0</em>, the <code>zip</code> family of tasks support an
+option <var>createUnicodeExtraFields</var>, which makes Ant write these extra fields either for all
+entries (<q>always</q>) or only those whose name cannot be encoded using the specified encoding
+(<q>not-encodeable</q>), it defaults to <q>never</q> since the extra fields create bigger
+archives.</p>
 
-<p>The fallbackToUTF8 attribute of zip can be used to create archives
-  that use the specified encoding in the majority of cases but UTF-8 and
-  the language encoding flag for filenames that cannot be encoded
-  using the specified encoding.</p>
+<p>The <var>fallbackToUTF8</var> attribute of <code>zip</code> can be used to create archives that
+use the specified encoding in the majority of cases but UTF-8 and the language encoding flag for
+filenames that cannot be encoded using the specified encoding.</p>
 
-<p>The unzip-task will recognize the unicode extra fields by default
-  and read the file name information from them, unless you set the
-  optional attribute <code>scanForUnicodeExtraFields</code> to
-  false.</p>
+<p>The <code>unzip</code> task will recognize the Unicode extra fields by default and read the file
+name information from them, unless you set the optional
+attribute <var>scanForUnicodeExtraFields</var> to <q>false</q>.</p>
 
-<h4>Recommendations for Interoperability</h4>
+<h4>Recommendations for interoperability</h4>
 
-<p>The optimal setting of flags depends on the archivers you expect as
-  consumers/producers of the ZIP archives.  Below are some test
-  results which may be superseeded with later versions of each
-  tool.</p>
+<p>The optimal setting of flags depends on the archivers you expect as consumers/producers of the
+ZIP archives.  Below are some test results which may be superseded with later versions of each
+tool.</p>
 
 <ul>
-  <li>The java.util.zip package used by the jar executable or to read
-    jars from your CLASSPATH reads and writes UTF-8 names, it doesn't
-    set or recognize any flags or unicode extra fields.</li>
-
-  <li>Starting with Java7 <code>java.util.zip</code> writes UTF-8 by
-    default and uses the language encoding flag.  It is possible to
-    specify a different encoding when reading/writing ZIPs via new
-    constructors.  The package now recognizes the language encoding
-    flag when reading and ignores the Unicode extra fields.</li>
-
-  <li>7Zip writes CodePage 437 by default but uses UTF-8 and the
-    language encoding flag when writing entries that cannot be encoded
-    as CodePage 437 (similar to the zip task with fallbacktoUTF8 set
-    to true).  It recognizes the language encoding flag when reading
-    and ignores the unicode extra fields.</li>
-
-  <li>WinZIP writes CodePage 437 and uses unicode extra fields by
-    default.  It recognizes the unicode extra field and the language
-    encoding flag when reading.</li>
-
-  <li>Windows' "compressed folder" feature doesn't recognize any flag
-    or extra field and creates archives using the platforms default
-    encoding - and expects archives to be in that encoding when reading
-    them.</li>
-
-  <li>InfoZIP based tools can recognize and write both, it is a
-    compile time option and depends on the platform so your mileage
-    may vary.</li>
-
-  <li>PKWARE zip tools recognize both and prefer the language encoding
-    flag.  They create archives using CodePage 437 if possible and UTF-8
-    plus the language encoding flag for file names that cannot be
-    encoded as CodePage 437.</li>
+  <li>The <code class="code">java.util.zip</code> package used by the <kbd>jar</kbd> executable or
+    to read jars from your <code>CLASSPATH</code> reads and writes UTF-8 names, it doesn't set or
+    recognize any flags or unicode extra fields.</li>
+  <li>Since Java 7, <code class="code">java.util.zip</code> writes UTF-8 by default and uses the
+    language encoding flag.  It is possible to specify a different encoding when reading/writing
+    ZIPs via new constructors.  The package now recognizes the language encoding flag when reading
+    and ignores the Unicode extra fields.</li>
+  <li>7Zip writes CodePage 437 by default but uses UTF-8 and the language encoding flag when writing
+    entries that cannot be encoded as CodePage 437 (similar to the <code>zip</code> task
+    with <var>fallbacktoUTF8</var> set to <q>true</q>).  It recognizes the language encoding flag
+    when reading and ignores the Unicode extra fields.</li>
+  <li>WinZIP writes CodePage 437 and uses Unicode extra fields by default.  It recognizes the
+    Unicode extra field and the language encoding flag when reading.</li>
+  <li>Windows' "compressed folder" feature doesn't recognize any flag or extra field and creates
+    archives using the default platform encoding&mdash;and expects archives to be in that encoding
+    when reading them.</li>
+  <li>InfoZIP based tools can recognize and write both, it is a compile time option and depends on
+    the platform so your mileage may vary.</li>
+  <li>PKWARE zip tools recognize both and prefer the language encoding flag.  They create archives
+    using CodePage 437 if possible and UTF-8 plus the language encoding flag for file names that
+    cannot be encoded as CodePage 437.</li>
 </ul>
 
 <p>So, what to do?</p>
 
-<p>If you are creating jars, then java.util.zip is your main
-  consumer.  We recommend you set the encoding to UTF-8 and keep the
-  language encoding flag enabled.  The flag won't help or hurt
-  java.util.zip prior to Java7 but archivers that support it will show
-  the correct file names.</p>
+<p>If you are creating jars, then <code class="code">java.util.zip</code> is your main consumer.  We
+recommend you set the encoding to UTF-8 and keep the language encoding flag enabled.  The flag won't
+help or hurt <code class="code">java.util.zip</code> prior to Java 7 but archivers that support it
+will show the correct file names.</p>
 
-<p>For maximum interop it is probably best to set the encoding to
-  UTF-8, enable the language encoding flag and create unicode extra
-  fields when writing ZIPs.  Such archives should be extracted
-  correctly by java.util.zip, 7Zip, WinZIP, PKWARE tools and most
-  likely InfoZIP tools.  They will be unusable with Windows'
-  "compressed folders" feature and bigger than archives without the
-  unicode extra fields, though.</p>
+<p>For maximum interoparability it is probably best to set the encoding to UTF-8, enable the
+language encoding flag and create Unicode extra fields when writing ZIPs.  Such archives should be
+extracted correctly by <code class="code">java.util.zip</code>, 7Zip, WinZIP, PKWARE tools and most
+likely InfoZIP tools.  They will be unusable with Windows' "compressed folders" feature and bigger
+than archives without the Unicode extra fields, though.</p>
 
-<p>If Windows' "compressed folders" is your primary consumer, then
-  your best option is to explicitly set the encoding to the target
-  platform.  You may want to enable creation of unicode extra fields
-  so the tools that support them will extract the file names
-  correctly.</p>
+<p>If Windows' "compressed folders" is your primary consumer, then your best option is to explicitly
+set the encoding to the target platform.  You may want to enable creation of Unicode extra fields so
+the tools that support them will extract the file names correctly.</p>
 
-<h3><a name="zip64">Zip64 extensions</a></h3>
+<h3 id="zip64">Zip64 extensions</h3>
 
-<p>Zip64 extensions provide a way to create archives bigger than 4GB
-  or holding more than 65535 entries - or add individual entries
-  bigger than 4GB using the ZIP extension field mechanism.  These
-  extensions are supported by most modern ZIP implementations.</p>
+<p>Zip64 extensions provide a way to create archives bigger than 4 GB or holding more than 65535
+entries&mdash;or add individual entries bigger than 4 GB using the ZIP extension field mechanism.
+These extensions are supported by most modern ZIP implementations.</p>
 
-<p>When Ant writes compressed entries into the archive it creates it
-  doesn't know the compressed size of an entry before it has been
-  written.  Unfortunately the decision whether a Zip64 extra field
-  will be written has to be made before writing the entry's
-  content.</p>
+<p>When Ant writes compressed entries into the archive it creates it doesn't know the compressed
+size of an entry before it has been written.  Unfortunately the decision whether a Zip64 extra field
+will be written has to be made before writing the entry's content.</p>
 
-<p>Starting with Ant 1.9.0 Ant supports Zip64 extensions but didn't
-  provide any control over their usage, starting with Ant 1.9.1 a
-  new <em>zip64mode</em> attribute was added to the <code>zip</code>
-  family of tasks.  It supports three values:
+<p>Ant 1.9.0 introduced support for Zip64 extensions but didn't provide any control over their
+usage. <em>Since Ant 1.9.1</em>, a new <var>zip64mode</var> attribute was added to
+the <code>zip</code> family of tasks.  It supports three values:
 
 <ul>
-  <li><em>never</em> means no Zip64 extra fields will ever be
-    written, this is the behavior of Ant 1.8.x and earlier and the
-    default behavior of <code>jar</code>, <code>ear</code>
-    and <code>war</code> starting with Ant 1.9.1.</li>
-  <li><em>always</em> means Zip64 extra fields are written for all
-    entries.</li>
-  <li><em>as-needed</em> means Zip64 extra fields are written for all
-    compressed entries to the "local file header" (by default these
-    are all files but not the directories) but only written to the
-    central directory if the entry really required Zip64 features.
-    This is the default behavior of Ant 1.9.0 and remains the default
-    behavior of the <code>zip</code> task.</li>
+  <li><q>never</q> means no Zip64 extra fields will ever be written. This is the behavior of Ant
+    prior to 1.9.0 and the default behavior of <code>jar</code>, <code>ear</code>
+    and <code>war</code> <em>since Ant 1.9.1</em>.</li>
+  <li><q>always</q> means Zip64 extra fields are written for all entries.</li>
+  <li><q>as-needed</q> means Zip64 extra fields are written for all compressed entries to the "local
+    file header" (by default these are all files but not the directories) but only written to the
+    central directory if the entry really required Zip64 features.  This is the default behavior of
+    Ant 1.9.0 and remains the default behavior of the <code>zip</code> task.</li>
 </ul>
 
-<p><em>as-needed</em> provides a good compromise if you don't know
-  whether you archive will exceed the limits of traditional zip files
-  but don't want to waste too much space (the Zip64 extensions take up
-  extra space).  Unfortunately some ZIP implementations don't
-  understand Zip64 extra fields or fail to parse archives with extra
-  fields in local file headers that are not present in the central
-  directory, one such implementation is the java.util.zip package of
-  Java5, that's why the <code>jar</code> tasks default
-  to <em>never</em>.  Archives created with <em>as-needed</em> can be
-  read without problems with Java6 and later.</p>
+<p><q>as-needed</q> provides a good compromise if you don't know whether you archive will exceed the
+limits of traditional zip files but don't want to waste too much space (the Zip64 extensions take up
+extra space).  Unfortunately some ZIP implementations don't understand Zip64 extra fields or fail to
+parse archives with extra fields in local file headers that are not present in the central
+directory, one such implementation is the <code class="code">java.util.zip</code> package of Java 5,
+that's why the <code>jar</code> tasks default to <q>never</q>.  Archives created
+with <q>as-needed</q> can be read without problems with Java 6 and later.</p>
 
 <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 files to archive.</p>
-<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> and
-<code>&lt;zipfileset&gt;</code> have been supported as nested elements.</p>
+<p><a href="../Types/resources.html#collection">resource collections</a> are used to select groups
+of files to archive.</p>
+<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> and <code>&lt;zipfileset&gt;</code> have been
+supported as nested elements.</p>
 
-<a name="zipgroupfileset" />
-<h4>zipgroupfileset</h4>
-<p>A <code>&lt;zipgroupfileset&gt;</code> allows for multiple zip files to be 
-merged into the archive. Each file found in this fileset is added to the archive 
-the same way that <i>zipfileset src</i> files are added.</p>
+<h4 id="zipgroupfileset">zipgroupfileset</h4>
+<p>A <code>&lt;zipgroupfileset&gt;</code> allows for multiple zip files to be merged into the
+archive. Each file found in this fileset is added to the archive the same way
+that <code>zipfileset</code> <var>src</var> files are added.</p>
 
-<p><code>&lt;zipgroupfileset&gt;</code> is
-  a <a href="../Types/fileset.html">fileset</a> and supports all
-  of its attributes and nested elements.</a>
+<p><code>&lt;zipgroupfileset&gt;</code> is a <a href="../Types/fileset.html">fileset</a> and
+supports all of its attributes and nested elements.</p>
 
 <h3>Examples</h3>
-<pre>  &lt;zip destfile=&quot;${dist}/manual.zip&quot;
-       basedir=&quot;htdocs/manual&quot;
-  /&gt;</pre>
-<p>zips all files in the <code>htdocs/manual</code> directory into a file called <code>manual.zip</code>
-in the <code>${dist}</code> directory.</p>
-<pre>  &lt;zip destfile=&quot;${dist}/manual.zip&quot;
-       basedir=&quot;htdocs/manual&quot;
-       update=&quot;true&quot;
-  /&gt;</pre>
-<p>zips all files in the <code>htdocs/manual</code> directory into a file called <code>manual.zip</code>
-in the <code>${dist}</code> directory. If <code>manual.zip</code>
-doesn't exist, it is created; otherwise it is updated with the
-new/changed files.</p>
-<pre>  &lt;zip destfile=&quot;${dist}/manual.zip&quot;
-       basedir=&quot;htdocs/manual&quot;
-       excludes=&quot;mydocs/**, **/todo.html&quot;
-  /&gt;</pre>
-<p>zips all files in the <code>htdocs/manual</code> directory. Files in the directory <code>mydocs</code>,
-or files with the name <code>todo.html</code> are excluded.</p>
-<pre>  &lt;zip destfile=&quot;${dist}/manual.zip&quot;
-       basedir=&quot;htdocs/manual&quot;
-       includes=&quot;api/**/*.html&quot;
-       excludes=&quot;**/todo.html&quot;
-  /&gt;</pre>
-<p>zips all files in the <code>htdocs/manual</code> directory. Only html files under the directory <code>api</code>
-are zipped, and files with the name <code>todo.html</code> are excluded.</p>
-<pre>  &lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
-    &lt;fileset dir=&quot;htdocs/manual&quot;/&gt;
-    &lt;fileset dir=&quot;.&quot; includes=&quot;ChangeLog.txt&quot;/&gt;
-  &lt;/zip&gt;</pre>
-<p>zips all files in the <code>htdocs/manual</code> directory, and also adds the file <code>ChangeLog.txt</code> in the
-current directory. <code>ChangeLog.txt</code> will be added to the top of the ZIP file, just as if
-it had been located at <code>htdocs/manual/ChangeLog.txt</code>.</p>
-<pre>  &lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
-    &lt;zipfileset dir=&quot;htdocs/manual&quot; prefix=&quot;docs/user-guide&quot;/&gt;
-    &lt;zipfileset dir=&quot;.&quot; includes=&quot;ChangeLog27.txt&quot; fullpath=&quot;docs/ChangeLog.txt&quot;/&gt;
-    &lt;zipfileset src=&quot;examples.zip&quot; includes=&quot;**/*.html&quot; prefix=&quot;docs/examples&quot;/&gt;
-  &lt;/zip&gt;</pre>
-<p>zips all files in the <code>htdocs/manual</code> directory into the <code>docs/user-guide</code> directory
-in the archive, adds the file <code>ChangeLog27.txt</code> in the
-current directory as <code>docs/ChangeLog.txt</code>, and includes all the html files in <code>examples.zip</code> 
-under <code>docs/examples</code>.  The archive might end up containing the files:</p>
-<pre>    docs/user-guide/html/index.html
+<p>Zip all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.zip</samp> in the <samp>${dist}</samp> directory.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;
+     basedir=&quot;htdocs/manual&quot;/&gt;</pre>
+
+<p>Zip all files in the <samp>htdocs/manual</samp> directory into a file
+called <samp>manual.zip</samp> in the <samp>${dist}</samp> directory. If <samp>manual.zip</samp>
+doesn't exist, it is created; otherwise it is updated with the new/changed files.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;
+     basedir=&quot;htdocs/manual&quot;
+     update=&quot;true&quot;/&gt;</pre>
+
+<p>Zip all files in the <samp>htdocs/manual</samp> directory. Files in the
+directory <samp>mydocs</samp>, or files with the name <samp>todo.html</samp> are excluded.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;
+     basedir=&quot;htdocs/manual&quot;
+     excludes=&quot;mydocs/**, **/todo.html&quot;/&gt;</pre>
+
+<p>Zip all files in the <samp>htdocs/manual</samp> directory. Only <samp>html</samp> files under the
+directory <samp>api</samp> are zipped, and files with the name <samp>todo.html</samp> are
+excluded.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;
+     basedir=&quot;htdocs/manual&quot;
+     includes=&quot;api/**/*.html&quot;
+     excludes=&quot;**/todo.html&quot;/&gt;</pre>
+
+<p>Zip all files in the <samp>htdocs/manual</samp> directory, and also add the
+file <samp>ChangeLog.txt</samp> in the current directory. <samp>ChangeLog.txt</samp> will be added
+to the top of the ZIP file, just as if it had been located
+at <samp>htdocs/manual/ChangeLog.txt</samp>.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
+  &lt;fileset dir=&quot;htdocs/manual&quot;/&gt;
+  &lt;fileset dir=&quot;.&quot; includes=&quot;ChangeLog.txt&quot;/&gt;
+&lt;/zip&gt;</pre>
+
+<p>Zip all files in the <samp>htdocs/manual</samp> directory into the <samp>docs/user-guide</samp>
+directory in the archive, adds the file <samp>ChangeLog27.txt</samp> in the current directory
+as <samp>docs/ChangeLog.txt</samp>, and includes all the <samp>html</samp> files
+in <samp>examples.zip</samp> under <samp>docs/examples</samp>.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
+  &lt;zipfileset dir=&quot;htdocs/manual&quot; prefix=&quot;docs/user-guide&quot;/&gt;
+  &lt;zipfileset dir=&quot;.&quot; includes=&quot;ChangeLog27.txt&quot; fullpath=&quot;docs/ChangeLog.txt&quot;/&gt;
+  &lt;zipfileset src=&quot;examples.zip&quot; includes=&quot;**/*.html&quot; prefix=&quot;docs/examples&quot;/&gt;
+&lt;/zip&gt;</pre>
+<p>The archive might end up containing the files:</p>
+<pre>
+    docs/user-guide/html/index.html
     docs/ChangeLog.txt
-    docs/examples/index.html
-</pre>
-<p>
-The code
-<pre>
-  &lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
-    &lt;zipfileset dir=&quot;htdocs/manual&quot; prefix=&quot;docs/user-guide&quot;/&gt;
-    &lt;zipgroupfileset dir=&quot;.&quot; includes=&quot;examples*.zip&quot;/&gt;
-  &lt;/zip&gt;
-</pre>
-<p>
-<p>zips all files in the <code>htdocs/manual</code> directory into the <code>docs/user-guide</code> directory in the archive and includes all the files in any file that matches <code>examples*.zip</code>, such as all files within <code>examples1.zip</code> or <code>examples_for_brian.zip</code>.
-The same can be achieved with
-<pre>
-  &lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
-    &lt;mappedresources&gt;
-      &lt;fileset dir=&quot;htdocs/manual&quot;/&gt;
-      &lt;globmapper from="*" to="docs/user-guide/*"/&gt;
-    &lt;/mappedresources&gt;
-    &lt;archives&gt;
-      &lt;zips&gt;
-        &lt;fileset dir=&quot;.&quot; includes=&quot;examples*.zip&quot;/&gt;
-      &lt;/zips&gt;
-    &lt;/archives&gt;
-  &lt;/zip&gt;
-</pre>
+    docs/examples/index.html</pre>
 
-The next example
+<p>Zip all files in the <samp>htdocs/manual</samp> directory into the <samp>docs/user-guide</samp>
+directory in the archive and include all the files in any file that
+matches <samp>examples*.zip</samp>, such as all files within <samp>examples1.zip</samp>
+or <samp>examples_for_brian.zip</samp>.</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
+  &lt;zipfileset dir=&quot;htdocs/manual&quot; prefix=&quot;docs/user-guide&quot;/&gt;
+  &lt;zipgroupfileset dir=&quot;.&quot; includes=&quot;examples*.zip&quot;/&gt;
+&lt;/zip&gt;</pre>
+<p>The same can be achieved with</p>
+<pre>
+&lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
+  &lt;mappedresources&gt;
+    &lt;fileset dir=&quot;htdocs/manual&quot;/&gt;
+    &lt;globmapper from="*" to="docs/user-guide/*"/&gt;
+  &lt;/mappedresources&gt;
+  &lt;archives&gt;
+    &lt;zips&gt;
+      &lt;fileset dir=&quot;.&quot; includes=&quot;examples*.zip&quot;/&gt;
+    &lt;/zips&gt;
+  &lt;/archives&gt;
+&lt;/zip&gt;</pre>
 
+<p>Re-package a TAR archive as a ZIP archive. If Unix file permissions have been stored as part of
+the TAR file, they will be retained in the resulting ZIP archive.</p>
 <pre>
 &lt;zip destfile="release.zip"&gt;
   &lt;tarfileset src="release.tar"/&gt;
-&lt;/zip&gt;
-</pre>
-
-<p>re-packages a TAR archive as a ZIP archive.  If Unix file
-permissions have been stored as part of the TAR file, they will be
-retained in the resulting ZIP archive.</p>
-
-
+&lt;/zip&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Types/antlib.html b/manual/Types/antlib.html
index 925320a..9662ce6 100644
--- a/manual/Types/antlib.html
+++ b/manual/Types/antlib.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,253 +15,203 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
   <head>
-    <meta http-equiv="Content-Language" content="en-us"></meta>
     <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
     <title>AntLib</title>
   </head>
 
   <body>
-    <h2><a name="antlib">Antlib</a></h2>
-
+    <h2 id="antlib">Antlib</h2>
 
     <h3>Description</h3>
     <p>
-      An antlib file is an xml file with a root element of "antlib".
-      Antlib's elements are Apache Ant definition tasks - like
-      <a href="../Tasks/taskdef.html">Taskdef</a>
-      or any Ant task that extends
-      <code>org.apache.tools.ant.taskdefs.AntlibDefinition</code>.
+      An antlib file is an xml file with a root element of <code>antlib</code>.  Antlib's elements
+      are Apache Ant definition tasks&mdash;like <a href="../Tasks/taskdef.html">Taskdef</a> or any
+      Ant task that
+      extends <code class="code">org.apache.tools.ant.taskdefs.AntlibDefinition</code>.
     </p>
     <p>
-        The current set of declarations bundled with Ant that do this are:
+      The current set of declarations bundled with Ant that do this are:
     </p>
-        <ol>
-            <li><a href="../Tasks/typedef.html">Typedef</a>
-            </li>
-            <li><a href="../Tasks/taskdef.html">Taskdef</a>
-            </li>
-            <li><a href="../Tasks/macrodef.html">Macrodef</a>
-            </li>
-            <li><a href="../Tasks/presetdef.html">Presetdef</a>
-            </li>
-            <li><a href="../Tasks/scriptdef.html">Scriptdef</a>
-            </li>
-        </ol>
+    <ol>
+      <li><a href="../Tasks/typedef.html">Typedef</a></li>
+      <li><a href="../Tasks/taskdef.html">Taskdef</a></li>
+      <li><a href="../Tasks/macrodef.html">Macrodef</a></li>
+      <li><a href="../Tasks/presetdef.html">Presetdef</a></li>
+      <li><a href="../Tasks/scriptdef.html">Scriptdef</a></li>
+    </ol>
     <p>
-      A group of tasks and types may be defined together in an antlib
-      file. For example the file <i>sample.xml</i> contains the following:
+      A group of tasks and types may be defined together in an antlib file. For example the
+      file <samp>sample.xml</samp> contains the following:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;?xml version="1.0"?&gt;
 &lt;antlib&gt;
-   &lt;typedef name="if" classname="org.acme.ant.If"/&gt;
-   &lt;typedef name="scriptpathmapper"
-            classname="org.acme.ant.ScriptPathMapper"
-            onerror="ignore"/&gt;
-   &lt;macrodef name="print"&gt;
-      &lt;attribute name="file"/&gt;
-      &lt;sequential&gt;
-         &lt;concat taskname="print"&gt;
-            &lt;fileset dir="." includes="@{file}"/&gt;
-         &lt;/concat&gt;
-      &lt;/sequential&gt;
-   &lt;/macrodef&gt;
-&lt;/antlib&gt;
-      </pre>
-    </blockquote>
+    &lt;typedef name="if" classname="org.acme.ant.If"/&gt;
+    &lt;typedef name="scriptpathmapper"
+             classname="org.acme.ant.ScriptPathMapper"
+             onerror="ignore"/&gt;
+    &lt;macrodef name="print"&gt;
+        &lt;attribute name="file"/&gt;
+        &lt;sequential&gt;
+            &lt;concat taskname="print"&gt;
+                &lt;fileset dir="." includes="@{file}"/&gt;
+            &lt;/concat&gt;
+        &lt;/sequential&gt;
+    &lt;/macrodef&gt;
+&lt;/antlib&gt;</pre>
     <p>
-      It defines two types or tasks, <i>if</i> and <i>scriptpathmapper</i>.
-      This antlib file may be used in a build script as follows:
+      It defines two types or tasks, <code>if</code> and <code>scriptpathmapper</code>.  This
+      antlib file may be used in a build script as follows:
     </p>
-    <blockquote>
-      <pre>
-&lt;typedef file="sample.xml"/&gt;
-      </pre>
-    </blockquote>
+    <pre>&lt;typedef file="sample.xml"/&gt;</pre>
     <p>
-      The other attributes of <code>&lt;typedef&gt;</code> may be used as well.
-      For example, assuming that the <i>sample.xml</i> is in a jar
-      file <i>sample.jar</i> also containing the classes, the
-      following build fragment will define the <i>if</i> and <i>scriptpathmapper</i>
-      tasks/types and place them in the namespace uri <i>samples:/acme.org</i>.
+      The other attributes of <code>&lt;typedef&gt;</code> may be used as well.  For example,
+      assuming that the <samp>sample.xml</samp> is in a jar file <samp>sample.jar</samp> also
+      containing the classes, the following build fragment will define the <code>if</code>
+      and <code>scriptpathmapper</code> tasks/types and place them in the namespace
+      uri <code>samples:/acme.org</code>.
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;typedef resource="org/acme/ant/sample.xml"
-         uri="samples:/acme.org"/&gt;
-      </pre>
-    </blockquote>
+         uri="samples:/acme.org"/&gt;</pre>
     <p>
       The definitions may then be used as follows:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;sample:if valuetrue="${props}" xmlns:sample="samples:/acme.org"&gt;
-   &lt;sample:scriptpathmapper language="beanshell"&gt;
-      some bean shell
-   &lt;/sample:scriptpathmapper&gt;
-&lt;/sample:if&gt;
-      </pre>
-    </blockquote>
+    &lt;sample:scriptpathmapper language="beanshell"&gt;
+        some bean shell
+    &lt;/sample:scriptpathmapper&gt;
+&lt;/sample:if&gt;</pre>
 
-
-    <h3><a name="antlibnamespace">Antlib namespace</a></h3>
+    <h3 id="antlibnamespace">Antlib namespace</h3>
     <p>
-      The name space URIs with the pattern <b>antlib:<i>java package</i></b>
-      are given special treatment.
+      The name space URIs with the pattern <code>antlib:<i>java.package</i></code> are given
+      special treatment.
     </p>
     <p>
-      When Ant encounters a element with a namespace URI with this pattern, it
-      will check to see if there is a resource of the name <i>antlib.xml</i> in
-      the package directory in the default classpath.
+      When Ant encounters a element with a namespace URI with this pattern, it will check to see
+      if there is a resource of the name <samp>antlib.xml</samp> in the package directory in the
+      default classpath.
     </p>
     <p>
-      For example, assuming that the file <i>antcontrib.jar</i> has been placed
-      in the directory <i>${ant.home}/lib</i> and it contains the resource
-      <i>net/sf/antcontrib/antlib.xml</i> which has all antcontrib's definitions
-      defined, the following build file will automatically load the antcontrib
-      definitions at location <i>HERE</i>:
+      For example, assuming that the file <samp>antcontrib.jar</samp> has been placed in the
+      directory <samp>${ant.home}/lib</samp> and it contains the
+      resource <samp>net/sf/antcontrib/antlib.xml</samp> which has all antcontrib's definitions
+      defined, the following build file will automatically load the antcontrib definitions at
+      location <code>HERE</code>:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;project default="deletetest" xmlns:antcontrib="antlib:net.sf.antcontrib"&gt;
-   &lt;macrodef name="showdir"&gt;
-      &lt;attribute name="dir"/&gt;
-      &lt;sequential&gt;
-         &lt;antcontrib:shellscript shell="bash"&gt;  &lt;!-- HERE --&gt;
-            ls -Rl @{dir}
-         &lt;/antcontrib:shellscript&gt;
-      &lt;/sequential&gt;
-   &lt;/macrodef&gt;
+    &lt;macrodef name="showdir"&gt;
+        &lt;attribute name="dir"/&gt;
+        &lt;sequential&gt;
+            &lt;antcontrib:shellscript shell="bash"&gt;  &lt;!-- HERE --&gt;
+                ls -Rl @{dir}
+            &lt;/antcontrib:shellscript&gt;
+        &lt;/sequential&gt;
+    &lt;/macrodef&gt;
 
-   &lt;target name="deletetest"&gt;
-      &lt;delete dir="a" quiet="yes"/&gt;
-      &lt;mkdir dir="a/b"/&gt;
-      &lt;touch file="a/a.txt"/&gt;
-      &lt;touch file="a/b/b.txt"/&gt;
-      &lt;delete&gt;
-         &lt;fileset dir="a"/&gt;
-      &lt;/delete&gt;
-      &lt;showdir dir="a"/&gt;
-   &lt;/target&gt;
-&lt;/project&gt;
-      </pre>
-    </blockquote>
+    &lt;target name="deletetest"&gt;
+        &lt;delete dir="a" quiet="yes"/&gt;
+        &lt;mkdir dir="a/b"/&gt;
+        &lt;touch file="a/a.txt"/&gt;
+        &lt;touch file="a/b/b.txt"/&gt;
+        &lt;delete&gt;
+            &lt;fileset dir="a"/&gt;
+        &lt;/delete&gt;
+        &lt;showdir dir="a"/&gt;
+    &lt;/target&gt;
+&lt;/project&gt;</pre>
     <p>
-      The requirement that the resource is in the default classpath
-      may be removed in future versions of Ant.</p>
+      The requirement that the resource is in the default classpath may be removed in future
+      versions of Ant.
     </p>
-
-
-	<h3><a name="loadFromInside">Load antlib from inside of the buildfile</a></h3>
-	<p>
-	  If you want to separate the antlib from your local Ant installation, e.g. because you 
-	  want to hold that jar in your projects SCM system, you have to specify a classpath, so 
-	  that Ant could find that jar. The best solution is loading the antlib with <tt>&lt;taskdef&gt;</tt>.
-	</p>
-    <blockquote>
-      <pre>
-&lt;project xmlns:<font color="green">antcontrib</font>="<font color="red">antlib:net.sf.antcontrib</font>"&gt;
-   &lt;taskdef uri="<font color="red">antlib:net.sf.antcontrib</font>"
-            resource="net/sf/antcontrib/antlib.xml"
-            classpath="path/to/ant-contrib.jar"/&gt;
-   
-   &lt;target name="iterate"&gt;
-      &lt;<font color="green">antcontrib</font>:for param="file"&gt;
-         &lt;fileset dir="."/&gt;
-         &lt;sequential&gt;
-            &lt;echo message="- @{file}"/&gt;
-         &lt;/sequential&gt;
-      &lt;/antcontrib:for&gt;
-   &lt;/target&gt;
-&lt;/project&gt;
-      </pre>
-    </blockquote>
-
-	
-	
-
-    <h3><a name="currentnamespace">Current namespace</a></h3>
+    <h3 id="loadFromInside">Load antlib from inside of the buildfile</h3>
     <p>
-      Definitions defined in antlibs may be used in antlibs. However
-      the namespace that definitions are placed in are dependent on
-      the <code>&lt;typedef&gt;</code> that uses the antlib. To deal with this
-      problem, the definitions are placed in the namespace URI <i>ant:current</i>
-      for the duration of the antlib execution.
-      For example the following antlib defines the task <code>&lt;if&gt;</code>, the
-      type <code>&lt;isallowed&gt;</code> and a macro
-      <code>&lt;ifallowed&gt;</code> that makes use of the task and type:
+      If you want to separate the antlib from your local Ant installation, e.g. because you want
+      to hold that jar in your project's SCM system, you have to specify a classpath, so that
+      Ant could find that jar. The best solution is loading the antlib
+      with <code>&lt;taskdef&gt;</code>.
     </p>
-    <blockquote>
-      <pre>
+    <pre>
+&lt;project xmlns:<span style="color:green">antcontrib</span>="<span style="color:red">antlib:net.sf.antcontrib</span>"&gt;
+    &lt;taskdef uri="<span style="color:red">antlib:net.sf.antcontrib</span>"
+             resource="net/sf/antcontrib/antlib.xml"
+             classpath="path/to/ant-contrib.jar"/&gt;
+
+    &lt;target name="iterate"&gt;
+        &lt;<span style="color:green">antcontrib</span>:for param="file"&gt;
+            &lt;fileset dir="."/&gt;
+            &lt;sequential&gt;
+                &lt;echo message="- @{file}"/&gt;
+            &lt;/sequential&gt;
+        &lt;/antcontrib:for&gt;
+    &lt;/target&gt;
+&lt;/project&gt;</pre>
+    <h3 id="currentnamespace">Current namespace</h3>
+    <p>
+      Definitions defined in antlibs may be used in antlibs. However, the namespace that
+      definitions are placed in are dependent on the <code>&lt;typedef&gt;</code> that uses the
+      antlib. To deal with this problem, the definitions are placed in the namespace
+      URI <code>ant:current</code> for the duration of the antlib execution.  For example, the
+      following antlib defines the task <code>&lt;if&gt;</code>, the
+      type <code>&lt;isallowed&gt;</code> and a macro <code>&lt;ifallowed&gt;</code> that makes
+      use of the task and type:
+    </p>
+    <pre>
 &lt;antlib xmlns:current="ant:current"&gt;
-   &lt;taskdef name="if" classname="org.acme.ant.If"/&gt;
-   &lt;typedef name="isallowed" classname="org.acme.ant.Isallowed"/&gt;
-   &lt;macrodef name="ifallowed"&gt;
-      &lt;attribute name="action"/&gt;
-      &lt;element name="do"/&gt;
-      &lt;sequential&gt;
-         &lt;current:if&gt;
-            &lt;current:isallowed test="@{action}"/&gt;
-            &lt;current:then&gt;
-               &lt;do/&gt;
-            &lt;/current:then&gt;
-         &lt;/current:if&gt;
-      &lt;/sequential&gt;
-   &lt;/macrodef&gt;
-&lt;/antlib&gt;
-      </pre>
-    </blockquote>
-
-
+    &lt;taskdef name="if" classname="org.acme.ant.If"/&gt;
+    &lt;typedef name="isallowed" classname="org.acme.ant.Isallowed"/&gt;
+    &lt;macrodef name="ifallowed"&gt;
+        &lt;attribute name="action"/&gt;
+        &lt;element name="do"/&gt;
+        &lt;sequential&gt;
+            &lt;current:if&gt;
+                &lt;current:isallowed test="@{action}"/&gt;
+                &lt;current:then&gt;
+                    &lt;do/&gt;
+                &lt;/current:then&gt;
+            &lt;/current:if&gt;
+        &lt;/sequential&gt;
+    &lt;/macrodef&gt;
+&lt;/antlib&gt;</pre>
     <h3>Other examples and comments</h3>
     <p>
       Antlibs may make use of other antlibs.
     </p>
     <p>
-      As the names defined in the antlib are in the namespace uri as
-      specified by the calling <code>&lt;typedef&gt;</code> or by automatic element
-      resolution, one may reuse names from core ant types and tasks,
-      provided the caller uses a namespace uri. For example, the
-      following antlib may be used to define defaults for various
-      tasks:
+      As the names defined in the antlib are in the namespace URI as specified by the
+      calling <code>&lt;typedef&gt;</code> or by automatic element resolution, one may reuse
+      names from core Ant types and tasks, provided the caller uses a namespace URI. For
+      example, the following antlib may be used to define defaults for various tasks:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;antlib xmlns:antcontrib="antlib:net.sf.antcontrib"&gt;
-   &lt;presetdef name="javac"&gt;
-      &lt;javac deprecation="${deprecation}"
-             debug="${debug}"/&gt;
-   &lt;/presetdef&gt;
-   &lt;presetdef name="delete"&gt;
-      &lt;delete quiet="yes"/&gt;
-   &lt;/presetdef&gt;
-   &lt;presetdef name="shellscript"&gt;
-      &lt;antcontrib:shellscript shell="bash"/&gt;
-   &lt;/presetdef&gt;
-&lt;/antlib&gt;
-      </pre>
-    </blockquote>
+    &lt;presetdef name="javac"&gt;
+        &lt;javac deprecation="${deprecation}"
+               debug="${debug}"/&gt;
+    &lt;/presetdef&gt;
+    &lt;presetdef name="delete"&gt;
+        &lt;delete quiet="yes"/&gt;
+    &lt;/presetdef&gt;
+    &lt;presetdef name="shellscript"&gt;
+        &lt;antcontrib:shellscript shell="bash"/&gt;
+    &lt;/presetdef&gt;
+&lt;/antlib&gt;</pre>
     <p>
       This may be used as follows:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;project xmlns:local="localpresets"&gt;
-   &lt;typedef file="localpresets.xml" uri="localpresets"/&gt;
-   &lt;local:shellscript&gt;
-      echo "hello world"
-   &lt;/local:shellscript&gt;
-&lt;/project&gt;
-      </pre>
-    </blockquote>
-    
-
+    &lt;typedef file="localpresets.xml" uri="localpresets"/&gt;
+    &lt;local:shellscript&gt;
+        echo "hello world"
+    &lt;/local:shellscript&gt;
+&lt;/project&gt;</pre>
 
 </body>
 </html>
-
diff --git a/manual/Types/assertions.html b/manual/Types/assertions.html
index e168969..33e811f 100644
--- a/manual/Types/assertions.html
+++ b/manual/Types/assertions.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,195 +15,174 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Assertions type</title>
 </head>
 
 <body>
 
-<h2><a name="assertions">Assertions</a></h2>
+<h2 id="assertions">Assertions</h2>
 <p>
-The <tt>assertions</tt> type enables or disables the Java 1.4 assertions feature,
-on a whole Java program, or components of a program. It can be used
-in <a href="../Tasks/java.html"><code>&lt;java&gt;</code></a> and
-<a href="../Tasks/junit.html"><code>&lt;junit&gt;</code></a> to add extra validation to code.  
+The <code>assertions</code> type enables or disables the Java 1.4 assertions feature, on a whole
+Java program, or components of a program. It can be used
+in <a href="../Tasks/java.html"><code>&lt;java&gt;</code></a>
+and <a href="../Tasks/junit.html"><code>&lt;junit&gt;</code></a> to add extra validation to code.
 
 <p>
-Assertions are covered in the 
-<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html">Java SE documentation</a>,
-and the
-<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.10">Java Language Specification</a>.
+Assertions are covered in
+the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html"
+target="_top">Java SE documentation</a>, and
+the <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.10"
+target="_top">Java Language Specification</a>.
 
 <p>
-The key points to note are that a <tt>java.lang.AssertionError</tt>
-is thrown when an assertion fails, and that the facility is only available 
-on Java 1.4 and later. To enable assertions one must set <tt>source="1.4"</tt>
-(or later) in <tt>&lt;javac&gt;</tt> when the source is being compiled, and
-that the code must contain <tt>assert</tt> statements to be tested. The
-result of such an action is code that neither compiles or runs on earlier
-versions of Java. For this reason Apache Ant itself currently contains no assertions.
+The key points to note are that a <code>java.lang.AssertionError</code> is thrown when an assertion
+fails, and that the facility is only available on Java 1.4 and later. To enable assertions one must
+set <var>source</var>=<q>1.4</q> (or later) in <code>&lt;javac&gt;</code> when the source is being
+compiled, and that the code must contain <code>assert</code> statements to be tested. The result of
+such an action is code that neither compiles or runs on earlier versions of Java. For this reason
+Apache Ant itself currently contains no assertions.
 <p>
 
-When assertions are enabled (or disabled) in a task through nested 
-assertions elements, the class loader or command line is modified with the 
-appropriate options. This means that the JVM executed must be a Java 1.4
-or later JVM, even if there are no assertions in the code. Attempting to
-enable assertions on earlier VMs will result in an "Unrecognized option" 
-error and the JVM will not start.  
-
 <p>
-<h4>Attributes</h4>
-<p>
-
-
+When assertions are enabled (or disabled) in a task through nested assertions elements, the class
+loader or command line is modified with the appropriate options. This means that the JVM executed
+must be of version 1.4 or later, even if there are no assertions in the code. Attempting to enable
+assertions on earlier JVMs will result in an "Unrecognized option" error and the JVM will not start.
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+
+<h4>Attributes</h4>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">enableSystemAssertions</td>
-    <td valign="top">Flag to turn system assertions on or off.</td>
-    <td valign="top" align="center">No; default is "unspecified"</td>
+    <td>enableSystemAssertions</td>
+    <td>Flag to turn system assertions on or off.</td>
+    <td>No; default is <q>unspecified</q></td>
   </tr>
 </table>
 <p>
-When system assertions have been neither enabled nor disabled, then
-the JVM is not given any assertion information - the default action of the
- current JVMs is to disable system assertions. 
+When system assertions have been neither enabled nor disabled, then the JVM is not given any
+assertion information&mdash;the default action of the current JVMs is to disable system assertions.
+</p>
 <p>
-Note also that there is no apparent documentation for what parts of the
-JRE come with useful assertions.
+Note also that there is no apparent documentation for what parts of the JRE come with useful
+assertions.
+</p>
 
 <h3>Nested elements</h3>
 
 <h4>enable</h4>
 <p>
-Enable assertions in portions of code.
-If neither a package nor class is specified, assertions are turned on in <i>all</i> (user) code.
+Enable assertions in portions of code.  If neither a package nor class is specified, assertions are
+turned on in <em>all</em> (user) code.
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">class</td>
-    <td valign="top">The name of a class on which to enable assertions.</td>
-    <td valign="top" align="center">No</td>
+    <td>class</td>
+    <td>The name of a class on which to enable assertions.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">
-    The name of a package in which to enable assertions on all classes. (Includes subpackages.)
-    Use "<tt>...</tt>" for the anonymous package.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>package</td>
+    <td>The name of a package in which to enable assertions on all classes. (Includes subpackages.)
+      Use <q>...</q> for the anonymous package.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h4>disable</h4>
 <p>
 Disable assertions in portions of code.
-
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">class</td>
-    <td valign="top">The name of a class on which to disable assertions.</td>
-    <td valign="top" align="center">No</td>
+    <td>class</td>
+    <td>The name of a class on which to disable assertions.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">package</td>
-    <td valign="top">
-    The name of a package in which to disable assertions on all classes. (Includes subpackages.)
-    Use "<tt>...</tt>" for the anonymous package.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>package</td>
+    <td>The name of a package in which to disable assertions on all classes. (Includes subpackages.)
+      Use <q>...</q> for the anonymous package.</td>
+    <td>No</td>
   </tr>
 </table>
 <p>
-
-Because assertions are disabled by default, it only makes sense to disable
-assertions where they have been enabled in a parent package.
-
-
+Because assertions are disabled by default, it only makes sense to disable assertions where they
+have been enabled in a parent package.
+</p>
 <h4>Examples</h4>
 
 <h5>Example: enable assertions in all user classes</h5>
 
-All classes not in the JRE (i.e. all non-system classes) will have assertions turned on.
+<p>All classes not in the JRE (i.e. all non-system classes) will have assertions turned on.</p>
 <pre>
 &lt;assertions&gt;
   &lt;enable/&gt;
-&lt;/assertions&gt;
-</pre>
+&lt;/assertions&gt;</pre>
 
 <h5>Example: enable a single class</h5>
 
-Enable assertions in a class called Test
+<p>Enable assertions in a class called Test</p>
 <pre>
 &lt;assertions&gt;
   &lt;enable class="Test"/&gt;
-&lt;/assertions&gt;
-</pre>
+&lt;/assertions&gt;</pre>
 
 <h5>Example: enable a package</h5>
 
-Enable assertions in the <tt>org.apache</tt> package
-and all packages starting with the <tt>org.apache.</tt> prefix
+<p>Enable assertions in the <code>org.apache</code> package and all packages starting with
+the <code>org.apache.</code> prefix</p>
 <pre>
 &lt;assertions&gt;
   &lt;enable package="org.apache"/&gt;
-&lt;/assertions&gt;
-</pre>
+&lt;/assertions&gt;</pre>
 
 <h5>Example: System assertions</h5>
 
-Example: enable system assertions and assertions in all <tt>org.apache</tt> packages except
-for Ant (but including <tt>org.apache.tools.ant.Main</tt>)
+<p>Enable system assertions and assertions in all <code>org.apache</code> packages except for Ant
+(but including <code>org.apache.tools.ant.Main</code>)</p>
 <pre>
 &lt;assertions enableSystemAssertions="true"&gt;
   &lt;enable package="org.apache"/&gt;
   &lt;disable package="org.apache.tools.ant"/&gt;
   &lt;enable class="org.apache.tools.ant.Main"/&gt;
-&lt;/assertions&gt;
-</pre>
+&lt;/assertions&gt;</pre>
 
 <h5>Example: disabled and anonymous package assertions</h5>
 
-Disable system assertions; enable those in the anonymous package
+<p>Disable system assertions; enable those in the anonymous package</p>
 <pre>
 &lt;assertions enableSystemAssertions="false"&gt;
   &lt;enable package="..."/&gt;
-&lt;/assertions&gt;
-</pre>
-
+&lt;/assertions&gt;</pre>
 
 <h5>Example: referenced assertions</h5>
 
-This type is a datatype, so you can declare assertions and use them later
-
+<p>This type is a datatype, so you can declare assertions and use them later</p>
 <pre>
 &lt;assertions id="project.assertions"&gt;
   &lt;enable package="org.apache.test"/&gt;
 &lt;/assertions&gt;
 
-&lt;assertions refid="project.assertions"/&gt;
-</pre>
-
+&lt;assertions refid="project.assertions"/&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Types/classfileset.html b/manual/Types/classfileset.html
index a83d266..236f20e 100644
--- a/manual/Types/classfileset.html
+++ b/manual/Types/classfileset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,106 +15,99 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ClassFileSet Type</title>
 </head>
 
 <body>
-<h2><a name="fileset">ClassFileSet</a></h2>
-<p>A classfileset is a specialized type of fileset which, given a set of 
-&quot;root&quot; classes, will include all of the class files upon which the 
-root classes depend. This is typically used to create a jar with all of the
-required classes for a particular application.
+<h2 id="fileset">ClassFileSet</h2>
+<p>A classfileset is a specialized type of fileset which, given a set of &quot;root&quot;
+classes, will include all of the class files upon which the root classes depend. This is
+typically used to create a jar with all of the required classes for a particular application.
 </p>
 <p>
-classfilesets are typically used by reference. They are declared with an
-&quot;id&quot; value and this is then used as a reference where a normal fileset
-is expected.
+classfilesets are typically used by reference. They are declared with an <var>id</var> value and
+this is then used as a reference where a normal fileset is expected.
 </p>
 <p>
-This type requires the <code>BCEL</code> <a href="../install.html#librarydependencies">library</a>.
+This type requires
+the <code>BCEL</code> <a href="../install.html#librarydependencies">library</a>.
 </p>
 
-
 <h3>Attributes</h3>
-<p>The class fileset support the following attributes in addition
-to those supported by the 
-<a href="../Types/fileset.html">standard fileset</a>:
+<p>
+The class fileset support the following attributes in addition to those supported by
+the <a href="fileset.html">standard fileset</a>:
 </p>
- 
-<table border="1" cellpadding="2" cellspacing="0">
+
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">rootclass</td>
-    <td valign="top">A single root class name</td>
-    <td valign="top" align="center">No</td>
+    <td>rootclass</td>
+    <td>A single root class name</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h3>Nested Elements</h3>
+<h3>Nested elements</h3>
 
 <h4>Root</h4>
 <p>
 When more than one root class is required, multiple nested <code>&lt;root&gt;</code> elements
 may be used
 </p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">The fully qualified name of the root class</td>
-    <td align="center" valign="top">Yes</td>
+    <td>classname</td>
+    <td>The fully qualified name of the root class</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>RootFileSet</h4>
 <p>
-A root fileset is used to add a set of root classes from a fileset. In this case the entries in 
-the fileset are expected to be Java class files. The name of the Java class is determined by the 
-relative location of the classfile in the fileset. So, the file 
-<code>org/apache/tools/ant/Project.class</code> corresponds to the Java class
-<code>org.apache.tools.ant.Project</code>.</p>
+A root fileset is used to add a set of root classes from a fileset. In this case the entries in the
+fileset are expected to be Java class files. The name of the Java class is determined by the
+relative location of the classfile in the fileset. So, the
+file <code>org/apache/tools/ant/Project.class</code> corresponds to the Java
+class <code class="code">org.apache.tools.ant.Project</code>.</p>
 
 <h4>Examples</h4>
-<blockquote><pre>
+<pre>
 &lt;classfileset id=&quot;reqdClasses" dir=&quot;${classes.dir}&quot;&gt;
   &lt;root classname=&quot;org.apache.tools.ant.Project&quot;/&gt;
-&lt;/classfileset&gt;
-</pre></blockquote>
-
-<p>This example creates a fileset containing all the class files upon which the 
-<code>org.apache.tools.ant.Project</code> class depends. This fileset could 
-then be used to create a jar. 
+&lt;/classfileset&gt;</pre>
+<p>
+This example creates a fileset containing all the class files upon which
+the <code class="code">org.apache.tools.ant.Project</code> class depends. This fileset could then be
+used to create a jar.
 </p>
 
-<blockquote><pre>
+<pre>
 &lt;jar destfile=&quot;minimal.jar&quot;&gt;
   &lt;fileset refid=&quot;reqdClasses&quot;/&gt;
-&lt;/jar&gt;
-</pre></blockquote>
+&lt;/jar&gt;</pre>
 
-<blockquote><pre>
+<pre>
 &lt;classfileset id=&quot;reqdClasses&quot; dir=&quot;${classes.dir}&quot;&gt;
   &lt;rootfileset dir=&quot;${classes.dir}&quot; includes=&quot;org/apache/tools/ant/Project*.class&quot;/&gt;
-&lt;/classfileset&gt;
-</pre></blockquote>
-
-<p>This example constructs the classfileset using all the class with names starting with Project 
-in the org.apache.tools.ant package</p> 
-
-
+&lt;/classfileset&gt;</pre>
+<p>
+This example constructs the classfileset using all the class with names starting
+with <code class="code">Project</code> in the <code class="code">org.apache.tools.ant</code>
+package.
+</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/custom-programming.html b/manual/Types/custom-programming.html
index 96bade3..6015d41 100644
--- a/manual/Types/custom-programming.html
+++ b/manual/Types/custom-programming.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,58 +15,52 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
   <head>
-    <meta http-equiv="Content-Language" content="en-us"></meta>
-<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>Custom Components</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+    <title>Custom Components</title>
   </head>
   <body>
     <h2>Custom Components</h2>
     <h3>Overview</h3>
     <p>
-      Custom components are conditions, selectors, filters and other
-      objects that are defined outside Apache Ant core.
+      Custom components are conditions, selectors, filters and other objects that are defined
+      outside Apache Ant core.
     </p>
     <p>
-      In Ant 1.6 custom conditions, selectors and filters has
-      been overhauled.
+      In Ant 1.6 custom conditions, selectors and filters has been overhauled.
     </p>
     <p>
-      It is now possible to define custom conditions, selectors and filters
-      that behave like Ant Core components.
-      This is achieved by allowing datatypes defined in build scripts
-      to be used as custom components if the class of the datatype
-      is compatible, or has been adapted by an adapter class.
+      It is now possible to define custom conditions, selectors and filters that behave like Ant
+      Core components.  This is achieved by allowing datatypes defined in build scripts to be used
+      as custom components if the class of the datatype is compatible, or has been adapted by an
+      adapter class.
     </p>
     <p>
       The old methods of defining custom components are still supported.
     </p>
-    <h3>Definition and use</h3>
+    <h3>Definition and Use</h3>
     <p>
-      A custom component is a normal Java class that implements a particular
-      interface or extends a  particular class, or has been adapted to the
-      interface or class.
+      A custom component is a normal Java class that implements a particular interface or extends a
+      particular class, or has been adapted to the interface or class.
     </p>
     <p>
-      It is exactly like writing a
-      <a href="../develop.html#writingowntask">custom task</a>.
-      One defines attributes and nested elements by writing <i>setter</i>
-      methods and <i>add</i> methods.
+      It is exactly like writing a <a href="../develop.html#writingowntask">custom task</a>.  One
+      defines attributes and nested elements by writing <em>setter</em> methods and <em>add</em>
+      methods.
     </p>
     <p>
-      After the class has been written, it is added to the ant system
-      by using <code>&lt;typedef&gt;</code>.
+      After the class has been written, it is added to the ant system by
+      using <code>&lt;typedef&gt;</code>.
     </p>
-    <h3><a name="customconditions">Custom Conditions</a></h3>
+    <h3 id="customconditions">Custom Conditions</h3>
     <p>
-      Custom conditions are datatypes that implement
-      <code>org.apache.tools.ant.taskdefs.condition.Condition</code>.
-      For example a custom condition that returns true if a
-      string is all upper case could be written as:
+      Custom conditions are datatypes that
+      implement <code class="code">org.apache.tools.ant.taskdefs.condition.Condition</code>.  For
+      example a custom condition that returns true if a string is all upper case could be written
+      as:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 package com.mydomain;
 
 import org.apache.tools.ant.BuildException;
@@ -85,120 +80,90 @@
             throw new BuildException("value attribute is not set");
         }
         return value.toUpperCase().equals(value);
-   }
-}
-      </pre>
-    </blockquote>
-
+    }
+}</pre>
     <p>
-        Adding the condition to the system is achieved as follows:
+      Adding the condition to the system is achieved as follows:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;typedef
     name="alluppercase"
     classname="com.mydomain.AllUpperCaseCondition"
-    classpath="${mydomain.classes}"/&gt;
-      </pre>
-    </blockquote>
+    classpath="${mydomain.classes}"/&gt;</pre>
     <p>
-      This condition can now be used wherever a Core Ant condition
-      is used.
+      This condition can now be used wherever a Core Ant condition is used.
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;condition property="allupper"&gt;
-   &lt;alluppercase value="THIS IS ALL UPPER CASE"/&gt;
-&lt;/condition&gt;
-      </pre>
-    </blockquote>
-    <h3><a name="customselectors">Custom Selectors</a></h3>
+    &lt;alluppercase value="THIS IS ALL UPPER CASE"/&gt;
+&lt;/condition&gt;</pre>
+    <h3 id="customselectors">Custom Selectors</h3>
     <p>
-      Custom selectors are datatypes that implement
-      <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
+      Custom selectors are datatypes that
+      implement <code class="code">org.apache.tools.ant.types.selectors.FileSelector</code>.
     </p>
-    <p>There is only one method required.
-      <code>public boolean isSelected(File basedir, String filename,
-        File file)</code>.
-      It returns true
-      or false depending on whether the given file should be
-      selected or not.
+    <p>
+      There is only one method required, <code class="code">public boolean isSelected(File basedir,
+      String filename, File file)</code>.  It returns true or false depending on whether the given
+      file should be selected or not.
     </p>
     <p>
       An example of a custom selection that selects filenames ending
-      in ".java" would be:
+      in <samp>.java</samp> would be:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 package com.mydomain;
 import java.io.File;
 import org.apache.tools.ant.types.selectors.FileSelector;
 public class JavaSelector implements FileSelector {
     public boolean isSelected(File b, String filename, File f) {
-       return filename.toLowerCase().endsWith(".java");
+        return filename.toLowerCase().endsWith(".java");
     }
-}
-      </pre>
-    </blockquote>
+}</pre>
     <p>
       Adding the selector to the system is achieved as follows:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;typedef
     name="javaselector"
     classname="com.mydomain.JavaSelector"
-    classpath="${mydomain.classes}"/&gt;
-      </pre>
-    </blockquote>
-        <p>
-      This selector can now be used wherever a Core Ant selector
-      is used, for example:
+    classpath="${mydomain.classes}"/&gt;</pre>
+    <p>
+      This selector can now be used wherever a Core Ant selector is used, for example:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;copy todir="to"&gt;
-   &lt;fileset dir="src"&gt;
-      &lt;javaselector/&gt;
-   &lt;/fileset&gt;
-&lt;/copy&gt;
-      </pre>
-    </blockquote>
-
-      <p>
-        One may use
-        <code>org.apache.tools.ant.types.selectors.BaseSelector</code>,
-        a convenience class that provides reasonable default
-        behaviour.
-        It has some predefined behaviours you can take advantage
-        of. Any time you encounter a problem when setting attributes or
-        adding tags, you can call setError(String errmsg) and the class
-        will know that there is a problem. Then, at the top of your
-        <code>isSelected()</code> method call <code>validate()</code> and
-        a BuildException will be thrown with the contents of your error
-        message. The <code>validate()</code> method also gives you a
-        last chance to check your settings for consistency because it
-        calls <code>verifySettings()</code>. Override this method and
-        call <code>setError()</code> within it if you detect any
-        problems in how your selector is set up.
+    &lt;fileset dir="src"&gt;
+        &lt;javaselector/&gt;
+    &lt;/fileset&gt;
+&lt;/copy&gt;</pre>
+    <p>
+      One may use <code class="code">org.apache.tools.ant.types.selectors.BaseSelector</code>, a
+      convenience class that provides reasonable default behaviour.  It has some predefined
+      behaviours you can take advantage of. Any time you encounter a problem when setting attributes
+      or adding tags, you can call <code class="code">setError(String errmsg)</code> and the class
+      will know that there is a problem. Then, at the top of
+      your <code class="code">isSelected()</code> method call <code class="code">validate()</code>
+      and a <code>BuildException</code> will be thrown with the contents of your error
+      message. The <code class="code">validate()</code> method also gives you a last chance to check
+      your settings for consistency because it
+      calls <code class="code">verifySettings()</code>. Override this method and
+      call <code class="code">setError()</code> within it if you detect any problems in how your
+      selector is set up.
     </p>
     <p>
-      To write custom selector containers one should extend
-      <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
-      Implement the
-      <code>public boolean isSelected(File baseDir, String filename, File file)</code>
-      method to do the right thing. Chances are you'll want to iterate
-      over the selectors under you, so use
-      <code>selectorElements()</code> to get an iterator that will do
-      that.
+      To write custom selector containers one should
+      extend <code class="code">org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
+      Implement the <code class="code">public boolean isSelected(File baseDir, String filename, File
+      file)</code> method to do the right thing. Chances are you'll want to iterate over the
+      selectors under you, so use <code class="code">selectorElements()</code> to get an iterator
+      that will do that.
     </p>
     <p>
-      For example to create a selector container that will select files
-      if a certain number of contained selectors select, one could write
-      a selector as follows:
+      For example to create a selector container that will select files if a certain number of
+      contained selectors select, one could write a selector as follows:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 public class MatchNumberSelectors extends BaseSelectorContainer {
     private int number = -1;
     public void setNumber(int number) {
@@ -220,196 +185,167 @@
         }
         return numberSelected == number;
     }
-}
-      </pre>
-    </blockquote>
+}</pre>
     <p>
       To define and use this selector one could do:
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 &lt;typedef name="numberselected"
          classname="com.mydomain.MatchNumberSelectors"/&gt;
 ...
 &lt;fileset dir="${src.path}"&gt;
-   &lt;numberselected number="2"&gt;
-      &lt;contains text="script" casesensitive="no"/&gt;
-      &lt;size value="4" units="Ki" when="more"/&gt;
-      &lt;javaselector/&gt;
-   &lt;/numberselected&gt;
-&lt;/fileset&gt;
-      </pre>
-    </blockquote>
+    &lt;numberselected number="2"&gt;
+        &lt;contains text="script" casesensitive="no"/&gt;
+        &lt;size value="4" units="Ki" when="more"/&gt;
+        &lt;javaselector/&gt;
+    &lt;/numberselected&gt;
+&lt;/fileset&gt;</pre>
     <p>
-      <i>The custom selector</i>
+      <em>The custom selector</em>
     </p>
     <p>
-      The custom selector was the pre ant 1.6 way of defining custom selectors.
-      This method is still supported for backward compatibility.
+      The custom selector was the pre Ant 1.6 way of defining custom selectors.  This method is
+      still supported for backward compatibility.
     </p>
-    <p>You can write your own selectors and use them within the selector
-      containers by specifying them within the <code>&lt;custom&gt;</code> tag.</p>
-
-        <p>To create a new Custom Selector, you have to create a class that
-        implements
-        <code>org.apache.tools.ant.types.selectors.ExtendFileSelector</code>.
-        The easiest way to do that is through the convenience base class
-        <code>org.apache.tools.ant.types.selectors.BaseExtendSelector</code>,
-        which provides all of the methods for supporting
-        <code>&lt;param&gt;</code> tags. First, override the
-        <code>isSelected()</code> method, and optionally the
-        <code>verifySettings()</code> method. If your custom
-        selector requires parameters to be set, you can also override
-        the <code>setParameters()</code> method and interpret the
-        parameters that are passed in any way you like. Several of the
-        core selectors demonstrate how to do that because they can
-        also be used as custom selectors.</p>
-
-
-    <p>Once that is written, you include it in your build file by using
+    <p>
+      You can write your own selectors and use them within the selector containers by specifying
+      them within the <code>&lt;custom&gt;</code> tag.
+    </p>
+    <p>
+      To create a new Custom Selector, you have to create a class that
+      implements <code class="code">org.apache.tools.ant.types.selectors.ExtendFileSelector</code>.
+      The easiest way to do that is through the convenience base
+      class <code class="code">org.apache.tools.ant.types.selectors.BaseExtendSelector</code>, which
+      provides all of the methods for supporting <code>&lt;param&gt;</code> tags. First, override
+      the <code class="code">isSelected()</code> method, and optionally
+      the <code class="code">verifySettings()</code> method. If your custom selector requires
+      parameters to be set, you can also override the <code class="code">setParameters()</code>
+      method and interpret the parameters that are passed in any way you like. Several of the core
+      selectors demonstrate how to do that because they can also be used as custom selectors.
+    </p>
+    <p>
+      Once that is written, you include it in your build file by using
       the <code>&lt;custom&gt;</code> tag.
     </p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">classname</td>
-        <td valign="top">The name of your class that implements
-          <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
+        <td>classname</td>
+        <td>
+          The name of your class that
+          implements <code class="code">org.apache.tools.ant.types.selectors.FileSelector</code>.
         </td>
-        <td valign="top" align="center">Yes</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">classpath</td>
-        <td valign="top">The classpath to use in order to load the
-          custom selector class. If neither this classpath nor the
-          classpathref are specified, the class will be
+        <td>classpath</td>
+        <td>
+          The classpath to use in order to load the custom selector class. If
+          neither <var>classpath</var> nor <var>classpathref</var> are specified, the class will be
           loaded from the classpath that Ant uses.
         </td>
-        <td valign="top" align="center">No</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">classpathref</td>
-        <td valign="top">A reference to a classpath previously
-          defined. If neither this reference nor the
-          classpath above are specified, the class will be
-          loaded from the classpath that Ant uses.
+        <td>classpathref</td>
+        <td>
+          A reference to a classpath previously defined. If neither <var>classpathref</var>
+          nor <var>classpath</var> above are specified, the class will be loaded from the classpath
+          that Ant uses.
         </td>
-        <td valign="top" align="center">No</td>
+        <td>No</td>
       </tr>
     </table>
 
-    <p>Here is how you use <code>&lt;custom&gt;</code> to
-      use your class as a selector:
+    <p>
+      Here is how you use <code>&lt;custom&gt;</code> to use your class as a selector:
     </p>
-
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir="${mydir}" includes="**/*"&gt;
     &lt;custom classname="com.mydomain.MySelector"&gt;
         &lt;param name="myattribute" value="myvalue"/&gt;
     &lt;/custom&gt;
-&lt;/fileset&gt;
-      </pre></blockquote>
-
-
-    <p>The core selectors that can also be used as custom selectors
-      are</p>
+&lt;/fileset&gt;</pre>
+    <p>The core selectors that can also be used as custom selectors are</p>
 
     <ul>
       <li><a href="selectors.html#containsselect">Contains Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.ContainsSelector</code>
-      </li>
+        classname <code class="code">org.apache.tools.ant.types.selectors.ContainsSelector</code></li>
       <li><a href="selectors.html#dateselect">Date Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.DateSelector</code>
-      </li>
+        classname <code class="code">org.apache.tools.ant.types.selectors.DateSelector</code></li>
       <li><a href="selectors.html#depthselect">Depth Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.DepthSelector</code>
-      </li>
+        classname <code class="code">org.apache.tools.ant.types.selectors.DepthSelector</code></li>
       <li><a href="selectors.html#filenameselect">Filename Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.FilenameSelector</code>
-      </li>
+        classname <code class="code">org.apache.tools.ant.types.selectors.FilenameSelector</code></li>
       <li><a href="selectors.html#sizeselect">Size Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.SizeSelector</code>
-      </li>
+        classname <code class="code">org.apache.tools.ant.types.selectors.SizeSelector</code></li>
     </ul>
 
-    <p>Here is the example from the Depth Selector section rewritten
-    to use the selector through <code>&lt;custom&gt;</code>.</p>
-
-    <blockquote><pre>
+    <p>
+      Here is the example from the Depth Selector section rewritten to use the selector
+      through <code>&lt;custom&gt;</code>.
+    </p>
+    <pre>
 &lt;fileset dir="${doc.path}" includes="**/*"&gt;
     &lt;custom classname="org.apache.tools.ant.types.selectors.DepthSelector"&gt;
         &lt;param name="max" value="1"/&gt;
     &lt;/custom&gt;
-&lt;/fileset&gt;
-      </pre></blockquote>
+&lt;/fileset&gt;</pre>
+    <p>Selects all files in the base directory and one directory below that.</p>
 
-    <p>Selects all files in the base directory and one directory below
-      that.</p>
-
-    <h3><a name="filterreaders">Custom Filter Readers</a></h3>
+    <h3 id="filterreaders">Custom Filter Readers</h3>
     <p>
-      Custom filter readers selectors are datatypes that implement
-      <code>org.apache.tools.ant.types.filters.ChainableReader</code>.
-    </p>
-    <p>There is only one method required.
-      <code>Reader chain(Reader reader)</code>.
-      This returns a reader that filters input from the specified
-      reader.
+      Custom filter readers selectors are datatypes that
+      implement <code class="code">org.apache.tools.ant.types.filters.ChainableReader</code>.
     </p>
     <p>
-      For example a filterreader that removes every second character
-      could be:
+      There is only one method required, <code class="code">Reader chain(Reader reader)</code>.
+      This returns a reader that filters input from the specified reader.
     </p>
-    <blockquote>
-      <pre>
+    <p>
+      For example a filterreader that removes every second character could be:
+    </p>
+    <pre>
 public class RemoveOddCharacters implements ChainableReader {
-   public Reader chain(Reader reader) {
-      return new BaseFilterReader(reader) {
-          int count = 0;
-          public int read() throws IOException {
-              while (true) {
-                int c = in.read();
-                if (c == -1) {
-                    return c;
+    public Reader chain(Reader reader) {
+        return new BaseFilterReader(reader) {
+            int count = 0;
+            public int read() throws IOException {
+                while (true) {
+                    int c = in.read();
+                    if (c == -1) {
+                        return c;
+                    }
+                    count++;
+                    if ((count % 2) == 1) {
+                        return c;
+                    }
                 }
-                count++;
-                if ((count % 2) == 1) {
-                    return c;
-                }
-              }
-          }
-      }
-   }
-}
-      </pre>
-    </blockquote>
+            }
+        }
+    }
+}</pre>
     <p>
-      For line oriented filters it may be easier to extend
-      <code>ChainableFilterReader</code> an inner class of
-      <code>org.apache.tools.ant.filters.TokenFilter</code>.
+      For line oriented filters it may be easier to
+      extend <code class="code">ChainableFilterReader</code> an inner class
+      of <code class="code">org.apache.tools.ant.filters.TokenFilter</code>.
     </p>
     <p>
       For example a filter that appends the line number could be
     </p>
-    <blockquote>
-      <pre>
+    <pre>
 public class AddLineNumber extends ChainableReaderFilter {
-   private void lineNumber = 0;
-   public String filter(String string) {
-      lineNumber++;
-      return "" + lineNumber + "\t" + string;
-   }
-}
-      </pre>
-    </blockquote>
+    private void lineNumber = 0;
+    public String filter(String string) {
+        lineNumber++;
+        return "" + lineNumber + "\t" + string;
+    }
+}</pre>
 
-
-    <hr></hr>
   </body>
 </html>
-
diff --git a/manual/Types/description.html b/manual/Types/description.html
index 85942be..159c777 100644
--- a/manual/Types/description.html
+++ b/manual/Types/description.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,33 +15,29 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Apache Ant User Manual</title>
 </head>
 
 <body>
 
-<h2><a name="description">Description</a></h2>
+<h2 id="description">Description</h2>
 <h3>Description</h3>
-<p>Allows for a description of the project to be specified that
-will be included in the output of the <code>ant &#x2011;projecthelp</code>
-command.</p>
+<p>Allows for a description of the project to be specified that will be
+included in the output of the <kbd>ant -projecthelp</kbd> command.</p>
 
 <h3>Parameters</h3>
 <p>(none)</p>
 <h3>Examples</h3>
-<pre>  
+<pre>
 &lt;description&gt;
-This buildfile is used to build the Foo subproject within 
+This buildfile is used to build the Foo subproject within
 the large, complex Bar project.
 &lt;/description&gt;
 </pre>
 
-
 </body>
 </html>
-
diff --git a/manual/Types/dirset.html b/manual/Types/dirset.html
index 0434e9c..d391a1f 100644
--- a/manual/Types/dirset.html
+++ b/manual/Types/dirset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,141 +15,128 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>DirSet Type</title>
 </head>
 
 <body>
 
-<h2><a name="dirset">DirSet</a></h2>
-<p>A DirSet is a group of directories. These directories can be found in a
-directory tree starting in a base directory and are matched by
-patterns taken from a number of <a href="patternset.html">PatternSets</a>
-and <a href="selectors.html">Selectors</a>.
-</p>
-<p>PatternSets can be specified as nested
-<code>&lt;patternset&gt;</code> elements. In addition, DirSet holds
-an implicit PatternSet and supports the nested
-<code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>,
-<code>&lt;exclude&gt;</code> and <code>&lt;excludesfile&gt;</code>
-elements of <code>&lt;patternset&gt;</code> directly, as well as
-<code>&lt;patternset&gt;</code>'s attributes.</p>
-<p>Selectors are available as nested elements within the DirSet.
-If any of the selectors within the DirSet do not select the directory, it
-is not considered part of the DirSet. This makes a DirSet
-equivalent to an <code>&lt;and&gt;</code> selector container.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h2 id="dirset">DirSet</h2>
+<p>A DirSet is a group of directories. These directories can be found in a directory tree
+starting in a base directory and are matched by patterns taken from a number
+of <a href="patternset.html">PatternSets</a> and <a href="selectors.html">Selectors</a>.</p>
+<p>PatternSets can be specified as nested <code>&lt;patternset&gt;</code> elements. In
+addition, DirSet holds an implicit PatternSet and supports the
+nested <code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;excludesfile&gt;</code> elements of <code>&lt;patternset&gt;</code> directly,
+as well as <code>&lt;patternset&gt;</code>'s attributes.</p>
+<p>Selectors are available as nested elements within the DirSet.  If any of the selectors
+within the DirSet do not select the directory, it is not considered part of the DirSet. This
+makes a DirSet equivalent to an <code>&lt;and&gt;</code> selector container.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The root of the directory tree of this DirSet.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dir</td>
+    <td>The root of the directory tree of this DirSet.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">A comma- or space-separated list of patterns of directories that
-     must be included; all directories are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>Comma- or space-separated list of patterns of directories that must be included.</td>
+    <td>No; defaults to all directories</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">The name of a file; each line of this file is
-      taken to be an include pattern.
-      <b>Note:</b> if the file is empty and there are no other
-      patterns defined for the fileset, all directories will be included.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>Name of a file; each line of this file is taken to be an include
+      pattern. <strong>Note:</strong> if the file is empty and there are no other patterns defined
+      for the fileset, all directories will be included.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">A comma- or space-separated list of patterns of directories that
-     must be excluded; no directories are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>Comma- or space-separated list of patterns of directories that must be excluded.</td>
+    <td>No; defaults to none</td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">The name of a file; each line of this file is
-      taken to be an exclude pattern.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>Name of a file; each line of this file is taken to be an exclude pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Specifies whether case-sensitivity should be applied
-     (<code>true</code>|<code>yes</code>|<code>on</code> or
-     <code>false</code>|<code>no</code>|<code>off</code>).</td>
-    <td valign="top" align="center">No; defaults to true.</td>
+    <td>casesensitive</td>
+    <td>Specifies whether case-sensitivity should be applied (<q>true</q>, <q>yes</q>, <q>on</q>
+      or <q>false</q>, <q>no</q>, <q>off</q>).</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">followsymlinks</td>
-    <td valign="top">Shall symbolic links be followed? Defaults to
-      true. See <a href="fileset.html#symlink">fileset's documentation</a>.</td>
-    <td valign="top" align="center">No</td>
+    <td>followsymlinks</td>
+    <td>Shall symbolic links be followed?  See <a href="fileset.html#symlink">fileset's
+      documentation</a>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">erroronmissingdir</td>
-    <td valign="top">
-      Specify what happens if the base directory does not exist.
-      If true a build error will happen, if false, the dirset
-      will be ignored/empty.
-      Defaults to true.
-      <em>Since Apache Ant 1.7.1 (default is true for backward compatibility
-        reasons.)</em>
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>erroronmissingdir</td>
+    <td>Specify what happens if the base directory does not exist.  If <q>true</q> a build error
+      will happen, if <q>false</q>, the dirset will be ignored/empty.  <em>Since Apache Ant
+      1.7.1</em></td>
+    <td>No; defaults to true (for backward compatibility reasons)</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>dirset</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>dirset</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h4>Examples</h4>
 
-<blockquote><pre>
+<pre>
 &lt;dirset dir=&quot;${build.dir}&quot;&gt;
   &lt;include name=&quot;apps/**/classes&quot;/&gt;
   &lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
 &lt;/dirset&gt;
-</pre></blockquote>
-<p>Groups all directories named <code>classes</code> found under the
-<code>apps</code> subdirectory of <code>${build.dir}</code>, except those
-that have the text <code>Test</code> in their name.</p>
+</pre>
+<p>Groups all directories named <samp>classes</samp> found under the <samp>apps</samp> subdirectory
+of <samp>${build.dir}</samp>, except those that have the text <samp>Test</samp> in their name.</p>
 
-<blockquote><pre>
+<pre>
 &lt;dirset dir=&quot;${build.dir}&quot;&gt;
   &lt;patternset id=&quot;non.test.classes&quot;&gt;
     &lt;include name=&quot;apps/**/classes&quot;/&gt;
     &lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
   &lt;/patternset&gt;
 &lt;/dirset&gt;
-</pre></blockquote>
-<p>Groups the same directories as the above example, but also establishes
-a PatternSet that can be referenced in other
-<code>&lt;dirset&gt;</code> elements, rooted at a different directory.</p>
+</pre>
+<p>Groups the same directories as the above example, but also establishes a PatternSet that can be
+referenced in other <code>&lt;dirset&gt;</code> elements, rooted at a different directory.</p>
 
-<blockquote><pre>
+<pre>
 &lt;dirset dir=&quot;${debug_build.dir}&quot;&gt;
   &lt;patternset refid=&quot;non.test.classes&quot;/&gt;
 &lt;/dirset&gt;
-</pre></blockquote>
-<p>Groups all directories in directory <code>${debug_build.dir}</code>,
-using the same patterns as the above example.</p>
+</pre>
+<p>Groups all directories in directory <samp>${debug_build.dir}</samp>, using the same patterns as
+the above example.</p>
 
-<blockquote><pre>
+<pre>
 &lt;dirset id=&quot;dirset&quot; dir=&quot;${workingdir}&quot;&gt;
    &lt;present targetdir=&quot;${workingdir}&quot;&gt;
-        &lt;mapper type=&quot;glob&quot; from=&quot;*&quot; to=&quot;*/${markerfile}&quot; /&gt;
+        &lt;mapper type=&quot;glob&quot; from=&quot;*&quot; to=&quot;*/${markerfile}&quot;/&gt;
    &lt;/present&gt;
 &lt;/dirset&gt;
-</pre></blockquote>
-<p>Selects all directories somewhere under <code>${workingdir}</code>
-which contain a <code>${markerfile}</code>.</p>
-
+</pre>
+<p>Selects all directories somewhere under <samp>${workingdir}</samp> which contain
+a <samp>${markerfile}</samp>.</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/extension.html b/manual/Types/extension.html
index b05c0a6..3b7932b 100644
--- a/manual/Types/extension.html
+++ b/manual/Types/extension.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,78 +15,82 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Extension Type</title>
 </head>
 
 <body>
-<h2><a name="fileset">Extension</a></h2>
-<p>Utility type that represents either an available "Optional Package"
- (formerly known as "Standard Extension") as described in the manifest
- of a JAR file, or the requirement for such an optional package.</p>
-<p>Note that this type
-works with extensions as defined by the "Optional Package" specification.
- For more information about optional packages, see the document
-<em>Optional Package Versioning</em> in the documentation bundle for your
-Java2 Standard Edition package, in file
-<code>guide/extensions/versioning.html</code> or the online
-<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/versioning/spec/versioning2.html#wp90779">
-Package Versioning documentation.</p>
+<h2 id="fileset">Extension</h2>
+<p>Utility type that represents either an available "Optional Package" (formerly known as "Standard
+Extension") as described in the manifest of a JAR file, or the requirement for such an optional
+package.</p>
+<p>Note that this type works with extensions as defined by the "Optional Package" specification.
+For more information about optional packages, see the document <em>Optional Package Versioning</em>
+in the documentation bundle for your Java Standard Edition package, in
+file <samp>guide/extensions/versioning.html</samp> or the
+online <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"
+target="_top">Package Versioning documentation.</a></p>
 
 <h3>Attributes</h3>
-<p>The extension type supports the following attributes</a>:
-</p>
+<p>The extension type supports the following attributes:</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">extensionName</td>
-    <td valign="top">The name of extension</td>
-    <td valign="top" align="center">yes</td>
+    <td>extensionName</td>
+    <td>The name of extension</td>
+    <td>yes</td>
   </tr>
   <tr>
-    <td valign="top">specificationVersion</td>
-    <td valign="top">The version of extension specification (Must be in
-    dewey decimal aka dotted decimal notation. 3.2.4)</td>
-    <td valign="top" align="center">no</td>
+    <td>specificationVersion</td>
+    <td>The version of extension specification (must be in dewey decimal aka dotted decimal
+      notation, eg <q>3.2.4</q>)</td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top">specificationVendor</td>
-    <td valign="top">The specification vendor</td>
-    <td valign="top" align="center">no</td>
+    <td>specificationVendor</td>
+    <td>The specification vendor</td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top">implementationVersion</td>
-    <td valign="top">The version of extension implementation (Must be in
-    dewey decimal aka dotted decimal notation. 3.2.4)</td>
-    <td valign="top" align="center">no</td>
+    <td>implementationVersion</td>
+    <td>The version of extension implementation (must be in dewey decimal aka dotted decimal
+      notation, eg <q>3.2.4</q>)</td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top">implementationVendor</td>
-    <td valign="top">The implementation vendor</td>
-    <td valign="top" align="center">no</td>
+    <td>implementationVendor</td>
+    <td>The implementation vendor</td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top">implementationVendorId</td>
-    <td valign="top">The implementation vendor ID</td>
-    <td valign="top" align="center">no</td>
+    <td>implementationVendorId</td>
+    <td>The implementation vendor ID</td>
+    <td>no</td>
   </tr>
   <tr>
-    <td valign="top">implementationURL</td>
-    <td valign="top">The url from which to retrieve extension.</td>
-    <td valign="top" align="center">no</td>
+    <td>implementationURL</td>
+    <td>The url from which to retrieve extension.</td>
+    <td>no</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>extension</code>
+      a <a href="../using.html#references">reference</a> to
+      an <code>extension</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h4>Examples</h4>
-<blockquote><pre>
+<pre>
 &lt;extension id=&quot;e1&quot;
     extensionName=&quot;MyExtensions&quot;
     specificationVersion=&quot;1.0&quot;
@@ -93,22 +98,19 @@
     implementationVendorID=&quot;vv&quot;
     implementationVendor=&quot;Apache&quot;
     implementationVersion=&quot;2.0&quot;
-    implementationURL=&quot;http://somewhere.com/myExt.jar&quot;/&gt;
-</pre></blockquote>
+    implementationURL=&quot;https://somewhere.com/myExt.jar&quot;/&gt;
+</pre>
 
-<p>Fully specific extension object.</p>
+<p>Fully specified extension object.</p>
 
-<blockquote><pre>
+<pre>
 &lt;extension id=&quot;e1&quot;
     extensionName=&quot;MyExtensions&quot;
     specificationVersion=&quot;1.0&quot;
     specificationVendor=&quot;Peter Donald&quot;/&gt;
-</pre></blockquote>
+</pre>
 
-<p>Extension object that just species the specification details.</p>
-
-
+<p>Extension object that just specifies the specification details.</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/extensionset.html b/manual/Types/extensionset.html
index f38c1ed..aeb0854 100644
--- a/manual/Types/extensionset.html
+++ b/manual/Types/extensionset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,9 +15,8 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ExtensionSet Type</title>
 </head>
@@ -24,32 +24,34 @@
 <body>
 <h2><a>ExtensionSet</a></h2>
 <p>Utility type that represents a set of Extensions.</p>
-<p>Note that this type
-works with extensions as defined by the "Optional Package" specification.
- For more information about optional packages, see the document
-<em>Optional Package Versioning</em> in the documentation bundle for your
-Java2 Standard Edition package, in file
-<code>guide/extensions/versioning.html</code> or online at
-<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/versioning/spec/versioning2.html#wp90779">
-Package Versioning documentation.</p>
+<p>Note that this type works with extensions as defined by the "Optional Package" specification.
+For more information about optional packages, see the document <em>Optional Package Versioning</em>
+in the documentation bundle for your Java Standard Edition package, in
+file <samp>guide/extensions/versioning.html</samp> or online
+at <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90779"
+target="_top">Package Versioning documentation.</a></p>
 
-<h3>Nested Elements</h3>
+<p>The only supported attribute is <code>refid</code> which makes this
+  <code>extensionset</code>
+  a <a href="../using.html#references">reference</a> to
+  an <code>extensionset</code> defined elsewhere. If specified no
+  other attributes or nested elements are allowed.</p>
+
+<h3>Nested elements</h3>
 
 <h4>extension</h4>
 <p><a href="extension.html">Extension</a> object to add to set.</p>
 
 <h4>fileset</h4>
- <p><a href="../Types/fileset.html">FileSet</a>s all files contained
- contained within set that are jars and implement an extension are added
- to extension set.</p>
+<p><a href="fileset.html">FileSet</a>s all files contained contained within set that are jars and
+implement an extension are added to extension set.</p>
 
-<h4>LibFileSet</h4>
- <p>All files contained contained within set that are jars and implement 
- an extension are added to extension set. However the extension information 
- may be modified by attributes of libfileset</p>
+<h4>libfileset</h4>
+<p>All files contained contained within set that are jars and implement an extension are added to
+extension set. However, the extension information may be modified by attributes of libfileset.</p>
 
 <h4>Examples</h4>
-<blockquote><pre>
+<pre>
 &lt;extension id=&quot;e1&quot;
     extensionName=&quot;MyExtensions&quot;
     specificationVersion=&quot;1.0&quot;
@@ -57,7 +59,7 @@
     implementationVendorID=&quot;vv&quot;
     implementationVendor=&quot;Apache&quot;
     implementationVersion=&quot;2.0&quot;
-    implementationURL=&quot;http://somewhere.com/myExt.jar&quot;/&gt;
+    implementationURL=&quot;https://somewhere.com/myExt.jar&quot;/&gt;
 
 &lt;libfileset id="lfs"
                includeUrl="true"
@@ -73,11 +75,7 @@
   &lt;libfileset refid="lfs"/&gt;
   &lt;extension refid="e1"/&gt;
 &lt;/extensionSet&gt;
-
-</pre></blockquote>
-
-
+</pre>
 
 </body>
 </html>
-
diff --git a/manual/Types/filelist.html b/manual/Types/filelist.html
index 57c981d..b92ac28 100644
--- a/manual/Types/filelist.html
+++ b/manual/Types/filelist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,107 +15,97 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>FileList Type</title>
 </head>
 
 <body>
 
-<h2><a name="filelist">FileList</a></h2> 
+<h2 id="filelist">FileList</h2>
 
-<p>FileLists are explicitly named lists of files.  Whereas FileSets
-act as filters, returning only those files that exist in the file
-system and match specified patterns, FileLists are useful for
-specifying files that may or may not exist.  Multiple files are
-specified as a list of files, relative to the specified directory,
-with no support for wildcard expansion (filenames with wildcards will be
-included in the list unchanged).
-FileLists can appear inside tasks that support this feature or as stand-alone
-types.
-</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>FileLists are explicitly named lists of files.  Whereas FileSets act as filters, returning
+only those files that exist in the file system and match specified patterns, FileLists are
+useful for specifying files that may or may not exist.  Multiple files are specified as a list
+of files, relative to the specified directory, with no support for wildcard expansion (filenames
+with wildcards will be included in the list unchanged).  FileLists can appear inside tasks that
+support this feature or as stand-alone types.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">The base directory of this FileList.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>dir</td>
+    <td>The base directory of this FileList.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">files</td>
-    <td valign="top">The list of file names. This is a list of
-    file name separated by whitespace, or by commas.</td>
-    <td valign="top" align="center">
-      Yes, unless there is a nested file element</td>
+    <td>files</td>
+    <td>The list of file names. This is a list of file name separated by whitespace, or by
+    commas.</td>
+    <td>Yes, unless there is a nested file element</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>filelist</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>filelist</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
-  <h4>Nested Element: file</h4>
-  <p>
-    This represents a file name. The nested element allows filenames containing
-    white space and commas.
-  </p>
-  <p><em>Since Apache Ant 1.6.2</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">name</td>
-      <td valign="top">The name of the file.</td>
-      <td valign="top" align="center">Yes</td>
-    </tr>
-</table>  
+<h4>Nested element: file</h4>
+<p><em>Since Apache Ant 1.6.2</em></p>
+<p>This represents a file name. The nested element allows filenames containing white space and
+commas.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>The name of the file.</td>
+    <td>Yes</td>
+  </tr>
+</table>
 <h4>Examples</h4>
-<blockquote><pre>
-&lt;filelist 
-    id=&quot;docfiles&quot; 
+<pre>
+&lt;filelist
+    id=&quot;docfiles&quot;
     dir=&quot;${doc.src}&quot;
-    files=&quot;foo.xml,bar.xml&quot;/&gt; 
-</pre></blockquote>
+    files=&quot;foo.xml,bar.xml&quot;/&gt;</pre>
 
-<p>The files <code>${doc.src}/foo.xml</code> and
-<code>${doc.src}/bar.xml</code>.  Note that these files may not (yet)
-actually exist.
-</p>
+<p>The files <samp>${doc.src}/foo.xml</samp> and <samp>${doc.src}/bar.xml</samp>.  Note that
+these files may not (yet) actually exist.</p>
 
-<blockquote><pre>
-&lt;filelist 
-    id=&quot;docfiles&quot; 
+<pre>
+&lt;filelist
+    id=&quot;docfiles&quot;
     dir=&quot;${doc.src}&quot;
     files=&quot;foo.xml
-           bar.xml&quot;/&gt; 
-</pre></blockquote>
+           bar.xml&quot;/&gt;</pre>
 
 <p>Same files as the example above.</p>
 
-<blockquote><pre>
-&lt;filelist refid=&quot;docfiles&quot;/&gt; 
-</pre></blockquote>
+<pre>&lt;filelist refid=&quot;docfiles&quot;/&gt;</pre>
 
 <p>Same files as the example above.</p>
 
-<blockquote><pre>
-&lt;filelist 
-    id=&quot;docfiles&quot; 
+<pre>
+&lt;filelist
+    id=&quot;docfiles&quot;
     dir=&quot;${doc.src}&quot;&gt;
     &lt;file name="foo.xml"/&gt;
     &lt;file name="bar.xml"/&gt;
-&lt;/filelist&gt;
-</pre></blockquote>
+&lt;/filelist&gt;</pre>
 
 <p>Same files as the example above.</p>
 
-
-
 </body>
 </html>
-
diff --git a/manual/Types/fileset.html b/manual/Types/fileset.html
index 3d90172..62c2d13 100644
--- a/manual/Types/fileset.html
+++ b/manual/Types/fileset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,173 +15,168 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>FileSet Type</title>
 </head>
 
 <body>
 
-<h2><a name="fileset">FileSet</a></h2>
-<p>A FileSet is a group of files. These files can be found in a
-directory tree starting in a base directory and are matched by
-patterns taken from a number of <a
-href="patternset.html">PatternSets</a> and
-<a href="selectors.html">Selectors</a>.
-<p>PatternSets can be specified as nested
-<code>&lt;patternset&gt;</code> elements. In addition, FileSet holds
-an implicit PatternSet and supports the nested
-<code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>,
-<code>&lt;exclude&gt;</code> and <code>&lt;excludesfile&gt;</code>
-elements of PatternSet directly, as well as PatternSet's
+<h2 id="fileset">FileSet</h2>
+<p>A FileSet is a group of files. These files can be found in a directory tree starting in a
+base directory and are matched by patterns taken from a number
+of <a href="patternset.html">PatternSets</a> and <a href="selectors.html">Selectors</a>.</p>
+<p>PatternSets can be specified as nested <code>&lt;patternset&gt;</code> elements. In
+addition, FileSet holds an implicit PatternSet and supports the
+nested <code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;excludesfile&gt;</code> elements of PatternSet directly, as well as PatternSet's
 attributes.</p>
-<p>Selectors are available as nested elements within the FileSet.
-If any of the selectors within the FileSet do not select the file, the
-file is not considered part of the FileSet. This makes a FileSet
-equivalent to an <code>&lt;and&gt;</code> selector container.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Selectors are available as nested elements within the FileSet. If any of the selectors
+within the FileSet do not select the file, the file is not considered part of the FileSet. This
+makes a FileSet equivalent to an <code>&lt;and&gt;</code> selector container.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">dir</td>
-    <td valign="top">the root of the directory tree of this FileSet.</td>
-    <td valign="middle" align="center" rowspan="2">Exactly one of dir or file must be specified</td>
+    <td>dir</td>
+    <td>the root of the directory tree of this FileSet.</td>
+    <td rowspan="2">Exactly one of dir or file must be specified</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">shortcut for specifying a single-file fileset</td>
+    <td>file</td>
+    <td class="left">shortcut for specifying a single-file fileset</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">indicates whether <a href="../dirtasks.html#defaultexcludes">default excludes</a> should be used or not
-      (<code>yes | no</code>); default excludes are used when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>defaultexcludes</td>
+    <td>indicates whether <a href="../dirtasks.html#defaultexcludes">default excludes</a> should
+      be used or not (<code>yes|no</code>).</td>
+    <td>No; defaults to <q>yes</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included; all files are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>No; defaults to all files</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file; each line of this file is
-      taken to be an include pattern.<br/>
-      <b>Note:</b> if the file is empty and there are no other
-      patterns defined for the fileset, all files will be included.
+    <td>includesfile</td>
+    <td>name of a file; each line of this file is taken to be an include pattern.<br/>
+      <strong>Note</strong>: if the file is empty and there are no other patterns defined for
+      the fileset, all files will be included.
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded; no files (except default excludes) are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No; defaults to default excludes or none if <var>defaultexcludes</var> is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file; each line of this file is
-      taken to be an exclude pattern.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>name of a file; each line of this file is taken to be an exclude pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Must the include and exclude patterns be treated in a case sensitive way?
-        Defaults to true.</td>
-    <td valign="top" align="center">No</td>
+    <td>casesensitive</td>
+    <td>Must the include and exclude patterns be treated in a case sensitive way?</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">followsymlinks</td>
-    <td valign="top">Shall symbolic links be followed? Defaults to
-      true. See the note <a href="#symlink">below</a>.</td>
-    <td valign="top" align="center">No</td>
+    <td>followsymlinks</td>
+    <td>Shall symbolic links be followed? See the note <a href="#symlink">below</a>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">erroronmissingdir</td>
-    <td valign="top">
-      Specify what happens if the base directory does not exist.
-      If true a build error will happen, if false, the fileset
-      will be ignored/empty.
-      Defaults to true.
-      <em>Since Apache Ant 1.7.1 (default is true for backward compatibility
-        reasons.)</em>
+    <td>erroronmissingdir</td>
+    <td>
+      Specify what happens if the base directory does not exist. If <q>true</q> a build error
+      will happen, if <q>false</q>, the fileset will be ignored/empty.
+      <em>Since Apache Ant 1.7.1</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; defaults to <q>true</q> (for backward compatibility reasons)</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>fileset</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>fileset</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p><a name="symlink"><b>Note</b></a>: All files/directories for which
-the canonical path is different from its path are considered symbolic
-links.  On Unix systems this usually means the file really is a
-symbolic link but it may lead to false results on other
-platforms.</p>
+<p id="symlink"><strong>Note</strong>: All files/directories for which the canonical path is
+different from its path are considered symbolic links. On Unix systems this usually means the
+file really is a symbolic link but it may lead to false results on other platforms.</p>
+
+<p>Ant is restricted to features that JRE considers portable, and symbolic links is one such feature
+that was long considered non-portable. That has changed with Java 7 and NIO.2, yet full support for
+symbolic links is still lacking (notably, in Zip files). Full support of symbolic links in Ant would
+require a different implementation of FileSet and revision of all tasks and/or types that derive
+from it. Currently, the semantics of <var>followsymlinks</var> in FileSet is such that <q>false</q>
+excludes symbolic links completely, and <q>true</q> allows symbolic links to be considered by
+selectors, which may have their own <var>followsymlinks</var> attributes with proper semantics;
+i.e., <q>false</q> allows selector to inspect properties of a symbolic link itself, and <q>true</q>
+those of its target.
+</p>
 
 <h4>Examples</h4>
-<blockquote><pre>
+<pre>
 &lt;fileset dir=&quot;${server.src}&quot; casesensitive=&quot;yes&quot;&gt;
   &lt;include name=&quot;**/*.java&quot;/&gt;
   &lt;exclude name=&quot;**/*Test*&quot;/&gt;
 &lt;/fileset&gt;
-</pre></blockquote>
-<p>Groups all files in directory <code>${server.src}</code> that are Java
-source files and don't have the text <code>Test</code> in their
-name.</p>
+</pre>
+<p>Groups all files in directory <samp>${server.src}</samp> that are Java source files and don't
+have the text <samp>Test</samp> in their name.</p>
 
-<blockquote><pre>
+<pre>
 &lt;fileset dir=&quot;${server.src}&quot; casesensitive=&quot;yes&quot;&gt;
   &lt;patternset id=&quot;non.test.sources&quot;&gt;
     &lt;include name=&quot;**/*.java&quot;/&gt;
     &lt;exclude name=&quot;**/*Test*&quot;/&gt;
   &lt;/patternset&gt;
 &lt;/fileset&gt;
-</pre></blockquote>
-<p>Groups the same files as the above example, but also establishes
-a PatternSet that can be referenced in other
-<code>&lt;fileset&gt;</code> elements, rooted at a different directory.</p>
+</pre>
+<p>Groups the same files as the above example, but also establishes a PatternSet that can be
+referenced in other <code>&lt;fileset&gt;</code> elements, rooted at a different directory.</p>
 
-<blockquote><pre>
+<pre>
 &lt;fileset dir=&quot;${client.src}&quot; &gt;
   &lt;patternset refid=&quot;non.test.sources&quot;/&gt;
 &lt;/fileset&gt;
-</pre></blockquote>
-<p>Groups all files in directory <code>${client.src}</code>, using the
-same patterns as the above example.</p>
+</pre>
+<p>Groups all files in directory <samp>${client.src}</samp>, using the same patterns as the
+above example.</p>
 
-<blockquote><pre>
+<pre>
 &lt;fileset dir=&quot;${server.src}&quot; casesensitive=&quot;yes&quot;&gt;
   &lt;filename name=&quot;**/*.java&quot;/&gt;
   &lt;filename name=&quot;**/*Test*&quot; negate=&quot;true&quot;/&gt;
 &lt;/fileset&gt;
-</pre></blockquote>
-<p>Groups the same files as the top example, but using the
-<code>&lt;filename&gt;</code> selector.</p>
+</pre>
+<p>Groups the same files as the top example, but using the <code>&lt;filename&gt;</code>
+selector.</p>
 
-<blockquote><pre>
+<pre>
 &lt;fileset dir=&quot;${server.src}&quot; casesensitive=&quot;yes&quot;&gt;
   &lt;filename name=&quot;**/*.java&quot;/&gt;
   &lt;not&gt;
     &lt;filename name=&quot;**/*Test*&quot;/&gt;
   &lt;/not&gt;
 &lt;/fileset&gt;
-</pre></blockquote>
-<p>Groups the same files as the previous example using a combination of the
-<code>&lt;filename&gt;</code> selector and the <code>&lt;not&gt;</code>
-selector container.</p>
+</pre>
+<p>Groups the same files as the previous example using a combination of
+the <code>&lt;filename&gt;</code> selector and the <code>&lt;not&gt;</code> selector
+container.</p>
 
-<blockquote><pre>
-&lt;fileset dir="src" includes="main/" /&gt;
-</pre></blockquote>
-<p>Selects all files in <i>src/main</i> (e.g. <i>src/main/Foo.java</i> or 
-<i>src/main/application/Bar.java</i>).</p>
-
-
+<pre>&lt;fileset dir="src" includes="main/"/&gt;</pre>
+<p>Selects all files in <samp>src/main</samp> (e.g. <samp>src/main/Foo.java</samp>
+or <samp>src/main/application/Bar.java</samp>).</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/filterchain.html b/manual/Types/filterchain.html
index c83b106..86f2a28 100644
--- a/manual/Types/filterchain.html
+++ b/manual/Types/filterchain.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,51 +15,39 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html>
+<html lang="en">
 <head>
-  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>FilterChains and FilterReaders</title>
 </head>
 
 <body>
 
 <h2>FilterChains and FilterReaders</h2>
-Consider the flexibility of Unix pipes.  If you wanted,
-for example, to copy just those lines that contained the
-string blee from the first 10 lines of a text file 'foo'
-(<em>you wouldn't want to filter a binary file</em>)
-to a file 'bar', you would do something like:<p>
-<code>
-cat foo|head -n10|grep blee &gt; bar
-</code><p>
-Apache Ant was not flexible enough.  There was no way for the
-<code>&lt;copy&gt;</code> task to do something similar.  If you wanted
-the <code>&lt;copy&gt;</code> task to get the first 10 lines, you would have
-had to create special attributes:<p>
-<code>
-&lt;copy file=&quot;foo&quot; tofile=&quot;bar&quot; head=&quot;10&quot; contains=&quot;blee&quot;/&gt;
-</code><p>
-The obvious problem thus surfaced: Ant tasks would not be able
-to accommodate such data transformation attributes as they would
-be endless.  The task would also not know in which order these
-attributes were to be interpreted.  That is, must the task execute the
-contains attribute first and then the head attribute or vice-versa?
-What Ant tasks needed was a mechanism to allow pluggable filter (data
-transformer) chains.  Ant would provide a few filters for which there
-have been repeated requests.  Users with special filtering needs
-would be able to easily write their own and plug them in.<p>
+<p>Consider the flexibility of Unix pipes.  If you wanted, for example, to copy just those lines
+that contained the string <q>blee</q> from the first 10 lines of a text file <samp>foo</samp>
+(<em>you wouldn't want to filter a binary file</em>) to a file <samp>bar</samp>, you would do
+something like:</p>
+<pre class="input">cat foo|head -n10|grep blee &gt; bar</pre>
+<p>Apache Ant was not flexible enough.  There was no way for the <code>&lt;copy&gt;</code> task to
+do something similar.  If you wanted the <code>&lt;copy&gt;</code> task to get the first 10 lines,
+you would have had to create special attributes:</p>
+<pre>&lt;copy file=&quot;foo&quot; tofile=&quot;bar&quot; head=&quot;10&quot; contains=&quot;blee&quot;/&gt;</pre>
+<p>The obvious problem thus surfaced: Ant tasks would not be able to accommodate such data
+transformation attributes as they would be endless.  The task would also not know in which order
+these attributes were to be interpreted.  That is, must the task execute the contains attribute
+first and then the head attribute or vice-versa?  What Ant tasks needed was a mechanism to allow
+pluggable filter (data transformer) chains.  Ant would provide a few filters for which there have
+been repeated requests.  Users with special filtering needs would be able to easily write their own
+and plug them in.</p>
 
-The solution was to refactor data transformation oriented
-tasks to support FilterChains.  A FilterChain is a group of
-ordered FilterReaders.  Users can define their own FilterReaders
-by just extending the java.io.FilterReader class.  Such custom
-FilterReaders can be easily plugged in as nested elements of
-<code>&lt;filterchain&gt;</code> by using <code>&lt;filterreader&gt;</code> elements.
-<p>
-Example:
-<blockquote><pre>
+<p>The solution was to refactor data transformation oriented tasks to support FilterChains.  A
+FilterChain is a group of ordered FilterReaders.  Users can define their own FilterReaders by just
+extending the <code class="code">java.io.FilterReader</code> class.  Such custom FilterReaders can
+be easily plugged in as nested elements of <code>&lt;filterchain&gt;</code> by
+using <code>&lt;filterreader&gt;</code> elements.</p>
+<p>Example:</p>
+<pre>
 &lt;copy file=&quot;${src.file}&quot; tofile=&quot;${dest.file}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;your.extension.of.java.io.FilterReader&quot;&gt;
@@ -72,535 +61,479 @@
       &lt;param type=&quot;abra&quot; value=&quot;cadabra&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/copy&gt;
-</pre></blockquote>
+&lt;/copy&gt;</pre>
 
-Ant provides some built-in filter readers.  These filter readers
-can also be declared using a syntax similar to the above syntax.
-However, they can be declared using some simpler syntax also.<p>
-Example:
-<blockquote><pre>
+<p>Ant provides some built-in filter readers.  These filter readers can also be declared using a
+syntax similar to the above syntax.  However, they can be declared using some simpler syntax
+also.</p>
+<p>Example:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;src.file.head&quot;&gt;
   &lt;filterchain&gt;
     &lt;headfilter lines=&quot;15&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
-is equivalent to:
-<blockquote><pre>
+&lt;/loadfile&gt;</pre>
+<p>is equivalent to:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;src.file.head&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.HeadFilter&quot;&gt;
       &lt;param name=&quot;lines&quot; value=&quot;15&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-The following built-in tasks support nested <code>&lt;filterchain&gt;</code> elements.<br>
-<a href="../Tasks/concat.html">Concat</a>,<br>
-<a href="../Tasks/copy.html">Copy</a>,<br>
-<a href="../Tasks/loadfile.html">LoadFile</a>,<br>
-<a href="../Tasks/loadproperties.html">LoadProperties</a>,<br>
-<a href="../Tasks/loadresource.html">LoadResource</a>,<br>
-<a href="../Tasks/move.html">Move</a><br><br>
+<p>The only supported attribute is <code>refid</code> which makes this
+  <code>filterchain</code>
+  a <a href="../using.html#references">reference</a> to
+  a <code>filterchain</code> defined elsewhere. If specified no other
+  attributes or nested elements are allowed.</p>
 
-A FilterChain is formed by defining zero or more of the following
-nested elements.<br>
-<a href="#filterreader">FilterReader</a><br>
-<a href="#classconstants">ClassConstants</a><br>
-<a href="#escapeunicode">EscapeUnicode</a><br>
-<a href="#expandproperties">ExpandProperties</a><br>
-<a href="#headfilter">HeadFilter</a><br>
-<a href="#linecontains">LineContains</a><br>
-<a href="#linecontainsregexp">LineContainsRegExp</a><br>
-<a href="#prefixlines">PrefixLines</a><br>
-<a href="#replacetokens">ReplaceTokens</a><br>
-<a href="#stripjavacomments">StripJavaComments</a><br>
-<a href="#striplinebreaks">StripLineBreaks</a><br>
-<a href="#striplinecomments">StripLineComments</a><br>
-<a href="#suffixlines">SuffixLines</a><br>
-<a href="#tabstospaces">TabsToSpaces</a><br>
-<a href="#tailfilter">TailFilter</a><br>
-<a href="#deletecharacters">DeleteCharacters</a><br>
-<a href="#concatfilter">ConcatFilter</a><br>
-<a href="#tokenfilter">TokenFilter</a><br>
-<a href="../Tasks/fixcrlf.html">FixCRLF</a><br>
-<a href="#sortfilter">SortFilter</a><br>
+<p>The following built-in tasks support nested <code>&lt;filterchain&gt;</code> elements.<br/>
+<a href="../Tasks/concat.html">Concat</a>,<br/>
+<a href="../Tasks/copy.html">Copy</a>,<br/>
+<a href="../Tasks/loadfile.html">LoadFile</a>,<br/>
+<a href="../Tasks/loadproperties.html">LoadProperties</a>,<br/>
+<a href="../Tasks/loadresource.html">LoadResource</a>,<br/>
+<a href="../Tasks/move.html">Move</a></p>
 
-<h3><a name="filterreader">FilterReader</a></h3>
+<p>A FilterChain is formed by defining zero or more of the following nested elements.<br/>
+<a href="#filterreader">FilterReader</a><br/>
+<a href="#classconstants">ClassConstants</a><br/>
+<a href="#escapeunicode">EscapeUnicode</a><br/>
+<a href="#expandproperties">ExpandProperties</a><br/>
+<a href="#headfilter">HeadFilter</a><br/>
+<a href="#linecontains">LineContains</a><br/>
+<a href="#linecontainsregexp">LineContainsRegExp</a><br/>
+<a href="#prefixlines">PrefixLines</a><br/>
+<a href="#replacetokens">ReplaceTokens</a><br/>
+<a href="#stripjavacomments">StripJavaComments</a><br/>
+<a href="#striplinebreaks">StripLineBreaks</a><br/>
+<a href="#striplinecomments">StripLineComments</a><br/>
+<a href="#suffixlines">SuffixLines</a><br/>
+<a href="#tabstospaces">TabsToSpaces</a><br/>
+<a href="#tailfilter">TailFilter</a><br/>
+<a href="#deletecharacters">DeleteCharacters</a><br/>
+<a href="#concatfilter">ConcatFilter</a><br/>
+<a href="#sortfilter">SortFilter</a><br/>
+<a href="#tokenfilter">TokenFilter</a><br/>
+<a href="../Tasks/fixcrlf.html">FixCRLF</a></p>
 
-The filterreader element is the generic way to
-define a filter.  User defined filter elements are
-defined in the build file using this.  Please note that
-built in filter readers can also be defined using this
-syntax.
+<h3 id="filterreader">FilterReader</h3>
 
-A FilterReader element must be supplied with a class name as
-an attribute value.  The class resolved by this name must
-extend java.io.FilterReader.  If the custom filter reader
-needs to be parameterized, it must implement
-org.apache.tools.type.Parameterizable.
+<p>The <code>filterreader</code> element is the generic way to define a filter.  User defined filter
+elements are defined in the build file using this.  Please note that built in filter readers can
+also be defined using this syntax.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<p>A FilterReader element must be supplied with a class name as an attribute value.  The class
+resolved by this name must extend <code class="code">java.io.FilterReader</code>.  If the custom
+filter reader needs to be parameterized, it must
+implement <code class="code">org.apache.tools.type.Parameterizable</code>.</p>
+
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>classname</td>
-    <td vAlign=top>The class name of the filter reader.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>classname</td>
+    <td>The class name of the filter reader.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<p>
-<h4>Nested Elements:</h4>
-<code>&lt;filterreader&gt;</code> supports <code>&lt;classpath&gt;</code> and <code>&lt;param&gt;</code>
-as nested elements.  Each <code>&lt;param&gt;</code> element may take in the following
-attributes - name, type and value.
-<p>
-The following FilterReaders are supplied with the default
-distribution.
+<h4>Nested elements</h4>
+<p><code>&lt;filterreader&gt;</code> supports <code>&lt;classpath&gt;</code>
+and <code>&lt;param&gt;</code> as nested elements.  Each <code>&lt;param&gt;</code> element may take
+in the following attributes&mdash;<var>name</var>, <var>type</var> and <var>value</var>.</p>
+<p>The following FilterReaders are supplied with the default distribution.</p>
 
-<h3><a name="classconstants">ClassConstants</a></h3>
-<p>
-  This filters basic constants defined in a Java Class,
-  and outputs them in lines composed of the format <i>name</i>=<i>value</i>.
-  This filter uses the <em>bcel</em> library to understand the Java Class file.
-  See <a href="../install.html#librarydependencies">Library Dependencies</a>.
-<p>
-  <p>
-    <em><b>Important:</b></em>
-    This filter is different from most of the other filters.
-    Most of the filters operate on a sequence of characters.
-    This filter operates on the sequence of bytes that makes up
-    a class. However the bytes arrive to the filter as a sequence
-    of characters. This means that one must be careful on the
-    choice of character encoding to use. Most encoding lose information
-    on conversion from an arbitrary sequence of bytes to characters
-    and back again to bytes. In particular the usual default
-    character encodings (CP152 and UTF-8) do.
-    For this reason, <em>since Ant 1.7</em>, the character
-    encoding <b>ISO-8859-1</b> is used to convert from characters back to
-    bytes, so one <b>has</b> to use this encoding for reading the java
-    class file.
-<h4>Example:</h4>
+<h3 id="classconstants">ClassConstants</h3>
+<p>This filters basic constants defined in a Java Class, and outputs them in lines composed of the
+format <em>name</em>=<em>value</em>.  This filter uses the BCEL library to understand the Java Class
+file.  See <a href="../install.html#librarydependencies">Library Dependencies</a>.</p>
+<p><strong>Important</strong>: This filter is different from most of the other filters.  Most of the
+filters operate on a sequence of characters.  This filter operates on the sequence of bytes that
+makes up a class. However the bytes arrive to the filter as a sequence of characters. This means
+that one must be careful on the choice of character encoding to use. Most encodings lose information
+on conversion from an arbitrary sequence of bytes to characters and back again to bytes. In
+particular, the usual default character encodings (CP1252 and UTF-8) do.  For this reason, <em>since
+Ant 1.7</em>, the character encoding <strong>ISO-8859-1</strong> is used to convert from characters
+back to bytes, so one <strong>has</strong> to use this encoding for reading the Java class file.</p>
+<h4>Example</h4>
 
-This loads the basic constants defined in a Java class as Ant properties.
+<p>This loads the basic constants defined in a Java class as Ant properties.</p>
 
-<blockquote><pre>
+<pre>
 &lt;loadproperties srcfile="foo.class" encoding="ISO-8859-1"&gt;
   &lt;filterchain&gt;
     &lt;classconstants/&gt;
   &lt;/filterchain&gt;
-&lt;/loadproperties&gt;
-</pre></blockquote>
+&lt;/loadproperties&gt;</pre>
 
-This loads the constants from a Java class file as Ant properties,
-prepending the names with a prefix.
+<p>This loads the constants from a Java class file as Ant properties, prepending the names with
+a prefix.</p>
 
-    <blockquote><pre>
+<pre>
 &lt;loadproperties srcfile="build/classes/org/acme/bar.class"
                 encoding="ISO-8859-1"&gt;
   &lt;filterchain&gt;
     &lt;classconstants/&gt;
     &lt;prefixlines prefix="ini."/&gt;
   &lt;/filterchain&gt;
-&lt;/loadproperties&gt;
-</pre></blockquote>
-<h3><a name="escapeunicode">EscapeUnicode</a></h3>
-<p>
-This filter converts its input by changing all non US-ASCII characters
-into their equivalent unicode escape backslash u plus 4 digits.</p>
+&lt;/loadproperties&gt;</pre>
+<h3 id="escapeunicode">EscapeUnicode</h3>
 
-<p><em>since Ant 1.6</em></p>
+<p>This filter converts its input by changing all non US-ASCII characters into their equivalent
+Unicode escape backslash u plus 4 digits.</p>
 
-<h4>Example:</h4>
+<p><em>Since Ant 1.6</em></p>
 
-This loads the basic constants defined in a Java class as Ant properties.
-<blockquote><pre>
+<h4>Example</h4>
+
+<p>This loads the basic constants defined in a Java class as Ant properties.</p>
+<pre>
 &lt;loadproperties srcfile=&quot;non_ascii_property.properties&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.EscapeUnicode&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadproperties&gt;
-</pre></blockquote>
+&lt;/loadproperties&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadproperties srcfile=&quot;non_ascii_property.properties&quot;&gt;
   &lt;filterchain&gt;
     &lt;escapeunicode/&gt;
   &lt;/filterchain&gt;
-&lt;/loadproperties&gt;
-</pre></blockquote>
+&lt;/loadproperties&gt;</pre>
 
-<h3><a name="expandproperties">ExpandProperties</a></h3>
-<p>
-If the data contains data that represents Ant
-properties (of the form ${...}), that is substituted
-with the property's actual value.
-<p>
-<h4>Example:</h4>
+<h3 id="expandproperties">ExpandProperties</h3>
+<p>If the data contains data that represents Ant properties (of the form <code>${...}</code>), that
+is substituted with the property's actual value.</p>
 
-This results in the property modifiedmessage holding the value
-&quot;All these moments will be lost in time, like teardrops in the rain&quot;
-<blockquote><pre>
-&lt;echo
-  message=&quot;All these moments will be lost in time, like teardrops in the ${weather}&quot;
-  file=&quot;loadfile1.tmp&quot;
-  /&gt;
+<h4>Example</h4>
+
+<p>This results in the property <code>modifiedmessage</code> holding the value <q>All these moments
+will be lost in time, like teardrops in the rain</q></p>
+<pre>
+&lt;echo message=&quot;All these moments will be lost in time, like teardrops in the ${weather}&quot;
+      file=&quot;loadfile1.tmp&quot;/&gt;
 &lt;property name=&quot;weather&quot; value=&quot;rain&quot;/&gt;
 &lt;loadfile property=&quot;modifiedmessage&quot; srcFile=&quot;loadfile1.tmp&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.ExpandProperties&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
-&lt;echo
-  message=&quot;All these moments will be lost in time, like teardrops in the ${weather}&quot;
-  file=&quot;loadfile1.tmp&quot;
-  /&gt;
+<p>Convenience method:</p>
+<pre>
+&lt;echo message=&quot;All these moments will be lost in time, like teardrops in the ${weather}&quot;
+      file=&quot;loadfile1.tmp&quot;/&gt;
 &lt;property name=&quot;weather&quot; value=&quot;rain&quot;/&gt;
 &lt;loadfile property=&quot;modifiedmessage&quot; srcFile=&quot;loadfile1.tmp&quot;&gt;
   &lt;filterchain&gt;
     &lt;expandproperties/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<p>As of Ant <strong>1.8.3</strong>, a nested
- <a href="propertyset.html">PropertySet</a> can be specified:
+<p><em>Since Ant 1.8.3</em>, a nested <a href="propertyset.html">PropertySet</a> can be specified:</p>
 
-<blockquote><pre>
+<pre>
 &lt;property name=&quot;weather&quot; value=&quot;rain&quot;/&gt;
 &lt;loadfile property=&quot;modifiedmessage&quot; srcFile=&quot;loadfile1.tmp&quot;&gt;
   &lt;filterchain&gt;
     &lt;expandproperties&gt;
       &lt;propertyset&gt;
-        &lt;propertyref name="weather" /&gt;
+        &lt;propertyref name="weather"/&gt;
       &lt;/propertyset&gt;
     &lt;/expandproperties&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<h3><a name="headfilter">HeadFilter</a></h3>
+<h3 id="headfilter">HeadFilter</h3>
 
-This filter reads the first few lines from the data supplied to it.
+<p>This filter reads the first few lines from the data supplied to it.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>lines</td>
-    <td vAlign=top align="center">Number of lines to be read.
-    Defaults to &quot;10&quot; <br> A negative value means that all lines are
-    passed (useful with <i>skip</i>)</td>
-    <td vAlign=top align="center">No</td>
+    <td>lines</td>
+    <td>Number of lines to be read.<br/>
+      A negative value means that all lines are passed (useful with <var>skip</var>).</td>
+    <td>No; defaults to <q>10</q></td>
   </tr>
   <tr>
-    <td vAlign=top>skip</td>
-    <td vAlign=top align="center">Number of lines to be skipped (from the beginning).
-    Defaults to &quot;0&quot;</td>
-    <td vAlign=top align="center">No</td>
+    <td>skip</td>
+    <td>Number of lines to be skipped (from the beginning).</td>
+    <td>No; defaults to <q>0</q></td>
   </tr>
 </table>
-<p>
-<h4>Example:</h4>
 
-This stores the first 15 lines of the supplied data in the property src.file.head
-<blockquote><pre>
+<h4>Example</h4>
+<p>This stores the first 15 lines of the supplied data in the property <code>src.file.head</code></p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;src.file.head&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.HeadFilter&quot;&gt;
       &lt;param name=&quot;lines&quot; value=&quot;15&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;src.file.head&quot;&gt;
   &lt;filterchain&gt;
     &lt;headfilter lines=&quot;15&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-This stores the first 15 lines, skipping the first 2 lines, of the supplied data
-in the property src.file.head. (Means: lines 3-17)
-<blockquote><pre>
+<p>This stores the first 15 lines, skipping the first 2 lines, of the supplied data in the
+property <code>src.file.head</code> (means: lines 3-17).</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;src.file.head&quot;&gt;
   &lt;filterchain&gt;
     &lt;headfilter lines=&quot;15&quot; skip=&quot;2&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-See the testcases for more examples (<i>src\etc\testcases\filters\head-tail.xml</i> in the
-source distribution).
+<p>See the testcases for more examples (<samp>src\etc\testcases\filters\head-tail.xml</samp> in
+the source distribution).</p>
 
-<h3><a name="linecontains">LineContains</a></h3>
+<h3 id="linecontains">LineContains</h3>
 
-This filter includes only those lines that contain all the user-specified
-strings.
+<p>This filter includes only those lines that contain all the user-specified strings.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Type</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Type</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>contains</td>
-    <td vAlign=top align="center">Substring to be searched for.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>contains</td>
+    <td>Substring to be searched for.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td vAlign=top>negate</td>
-    <td vAlign=top align="center">Whether to select
-      <i>non-</i>matching lines only. <b>Since Ant 1.7</b></td>
-    <td vAlign=top align="center">No</td>
+    <td>negate</td>
+    <td>Whether to select <em>non-</em>matching lines only. <em>Since Ant 1.7</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>matchAny</td>
+    <td>If <q>false</q>, then all the strings are expected to be present in the line. If
+      <q>true</q>, then the presence of any of the strings in the line is considered
+      a successful match.<br/><em>Since Ant 1.10.4</em>
+    </td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <p>
-<h4>Example:</h4>
+<h4>Example</h4>
 
-This will include only those lines that contain <code>foo</code> and
-<code>bar</code>.
-<blockquote><pre>
+<p>This will include only those lines that contain <q>foo</q> and <q>bar</q>.</p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.LineContains&quot;&gt;
   &lt;param type=&quot;contains&quot; value=&quot;foo&quot;/&gt;
   &lt;param type=&quot;contains&quot; value=&quot;bar&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
+&lt;/filterreader&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;linecontains&gt;
   &lt;contains value=&quot;foo&quot;/&gt;
   &lt;contains value=&quot;bar&quot;/&gt;
-&lt;/linecontains&gt;
-</pre></blockquote>
+&lt;/linecontains&gt;</pre>
 
-Negation:
-<blockquote><pre>
+<p>Negation:</p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.LineContains&quot;&gt;
   &lt;param type=&quot;negate&quot; value=&quot;true&quot;/&gt;
   &lt;param type=&quot;contains&quot; value=&quot;foo&quot;/&gt;
   &lt;param type=&quot;contains&quot; value=&quot;bar&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
-<i>or</i>
-<blockquote><pre>
+&lt;/filterreader&gt;</pre>
+<p><em>or</em></p>
+<pre>
 &lt;linecontains negate=&quot;true&quot;&gt;
   &lt;contains value=&quot;foo&quot;/&gt;
   &lt;contains value=&quot;bar&quot;/&gt;
-&lt;/linecontains&gt;
-</pre></blockquote>
+&lt;/linecontains&gt;</pre>
 
-<h3><a name="linecontainsregexp">LineContainsRegExp</a></h3>
+<h3 id="linecontainsregexp">LineContainsRegExp</h3>
 
-Filter which includes only those lines that contain the user-specified
-regular expression matching strings.
+<p>Filter which includes only those lines that contain the user-specified regular expression
+matching strings.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Type</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Type</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>regexp</td>
-    <td vAlign=top align="center">Regular expression to be searched for.<br>
-      <em>Starting with 1.9.10 this also works as an attribute
-        on <code>linecontainsregexp</code>, in earlier versions of Ant
-        you must use a nested element when using the convenience
-        method.</em>
+    <td>regexp</td>
+    <td>Regular expression to be searched for.<br/><em>Since Ant 1.10.2</em>, this also works as an
+      attribute on <code>linecontainsregexp</code>. In earlier versions of Ant you must use a nested
+      element when using the convenience method.
     </td>
-    <td vAlign=top align="center">Yes</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td vAlign=top>negate</td>
-    <td vAlign=top align="center">Whether to select
-      <i>non-</i>matching lines only. <b>Since Ant 1.7</b></td>
-    <td vAlign=top align="center">No</td>
+    <td>negate</td>
+    <td>Whether to select <em>non-</em>matching lines only. <em>Since Ant 1.7</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>casesensitive</td>
-    <td vAlign=top align="center">Perform a case sensitive
-      match. Default is true. <b>Since Ant 1.8.2</b></td>
-    <td vAlign=top align="center">No</td>
+    <td>casesensitive</td>
+    <td>Perform a case sensitive match. <em>Since Ant 1.8.2</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
 </table>
 
-See <a href="regexp.html">Regexp Type</a> for the description of the nested element regexp and of
-the choice of regular expression implementation.
-<h4>Example:</h4>
+<p>See <a href="regexp.html">Regexp Type</a> for the description of the nested element regexp
+and of the choice of regular expression implementation.</p>
 
-This will fetch all those lines that contain the pattern <code>foo</code>
-<blockquote><pre>
+<h4>Example</h4>
+
+<p>This will fetch all those lines that contain the pattern <code>foo</code></p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.LineContainsRegExp&quot;&gt;
   &lt;param type=&quot;regexp&quot; value=&quot;foo*&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
+&lt;/filterreader&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;linecontainsregexp&gt;
   &lt;regexp pattern=&quot;foo*&quot;/&gt;
-&lt;/linecontainsregexp&gt;
-</pre></blockquote>
+&lt;/linecontainsregexp&gt;</pre>
 
-Negation:
-<blockquote><pre>
+<p>Negation:</p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.LineContainsRegExp&quot;&gt;
   &lt;param type=&quot;negate&quot; value=&quot;true&quot;/&gt;
   &lt;param type=&quot;regexp&quot; value=&quot;foo*&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
-<i>or</i>
-<blockquote><pre>
+&lt;/filterreader&gt;</pre>
+<p><em>or</em></p>
+<pre>
 &lt;linecontainsregexp negate=&quot;true&quot;&gt;
   &lt;regexp pattern=&quot;foo*&quot;/&gt;
-&lt;/linecontainsregexp&gt;
-</pre></blockquote>
+&lt;/linecontainsregexp&gt;</pre>
 
-<h3><a name="prefixlines">PrefixLines</a></h3>
+<h3 id="prefixlines">PrefixLines</h3>
 
-Attaches a prefix to every line.
+<p>Attaches a prefix to every line.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>prefix</td>
-    <td vAlign=top align="center">Prefix to be attached to lines.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>prefix</td>
+    <td>Prefix to be attached to lines.</td>
+    <td>Yes</td>
   </tr>
 </table>
-<p>
-<h4>Example:</h4>
 
-This will attach the prefix <code>Foo</code> to all lines.
-<blockquote><pre>
+<h4>Example</h4>
+
+<p>This will attach the prefix <code>Foo</code> to all lines.</p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.PrefixLines&quot;&gt;
   &lt;param name=&quot;prefix&quot; value=&quot;Foo&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
+&lt;/filterreader&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
-&lt;prefixlines prefix=&quot;Foo&quot;/&gt;
-</pre></blockquote>
+<p>Convenience method:</p>
+<pre>&lt;prefixlines prefix=&quot;Foo&quot;/&gt;</pre>
 
-<h3><a name="suffixlines">SuffixLines</a></h3>
+<h3 id="suffixlines">SuffixLines</h3>
 
-Attaches a suffix to every line.
+<p><em>Since Ant 1.8.0</em></p>
 
-<p><em>since Ant 1.8.0</em></p>
+<p>Attaches a suffix to every line.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>suffix</td>
-    <td vAlign=top align="center">Suffix to be attached to lines.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>suffix</td>
+    <td>Suffix to be attached to lines.</td>
+    <td>Yes</td>
   </tr>
 </table>
-<p>
-<h4>Example:</h4>
 
-This will attach the suffix <code>Foo</code> to all lines.
-<blockquote><pre>
+<h4>Example</h4>
+
+<p>This will attach the suffix <code>Foo</code> to all lines.</p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.SuffixLines&quot;&gt;
   &lt;param name=&quot;suffix&quot; value=&quot;Foo&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
+&lt;/filterreader&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
-&lt;suffixlines suffix=&quot;Foo&quot;/&gt;
-</pre></blockquote>
+<p>Convenience method:</p>
+<pre>&lt;suffixlines suffix=&quot;Foo&quot;/&gt;</pre>
 
-<h3><a name="replacetokens">ReplaceTokens</a></h3>
+<h3 id="replacetokens">ReplaceTokens</h3>
 
-This filter reader replaces all strings that are
-sandwiched between begintoken and endtoken with
-user defined values.
+<p>This filter reader replaces all strings that are sandwiched between <var>begintoken</var>
+and <var>endtoken</var> with user defined values.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Type</b></td>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Type</th>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>tokenchar</td>
-    <td vAlign=top>begintoken</td>
-    <td vAlign=top>String marking the
-    beginning of a token.  Defaults to @</td>
-    <td vAlign=top align="center">No</td>
+    <td>tokenchar</td>
+    <td>begintoken</td>
+    <td>String marking the beginning of a token.</td>
+    <td>No; defaults to <q>@</q></td>
   </tr>
   <tr>
-    <td vAlign=top>tokenchar</td>
-    <td vAlign=top>endtoken</td>
-    <td vAlign=top>String marking the
-    end of a token.  Defaults to @</td>
-    <td vAlign=top align="center">No</td>
+    <td>tokenchar</td>
+    <td>endtoken</td>
+    <td>String marking the end of a token.</td>
+    <td>No; defaults to <q>@</q></td>
   </tr>
   <tr>
-    <td vAlign=top>User defined String.</td>
-    <td vAlign=top>token</td>
-    <td vAlign=top>User defined search String.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>token</td>
+    <td>User defined token string</td>
+    <td>Replacement value for the token.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td vAlign=top>Not applicable.</td>
-    <td vAlign=top>propertiesfile</td>
-    <td vAlign=top>Properties file to take tokens from.</td>
-    <td vAlign=top align="center">No</td>
+    <td>propertiesfile</td>
+    <td rowspan="2">Not applicable</td>
+    <td>Properties file to take tokens and replacement values from.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>Not applicable.</td>
-    <td vAlign=top>propertiesResource</td>
-    <td vAlign=top>Properties resource to take tokens from.
+    <td>propertiesResource</td>
+    <td>Properties resource to take tokens from.
       Note this only works is you use the
       "convenience" <code>&lt;replacetokens&gt;</code> syntax.
       <em>since Ant 1.8.0</em></td>
-    <td vAlign=top align="center">No</td>
+    <td>No</td>
   </tr>
-  <tr>
-    <td vAlign=top>User defined String.</td>
-    <td vAlign=top>value</td>
-    <td vAlign=top>Replace-value for the token</td>
-    <td vAlign=top align="center">No</td>
-  </tr></table>
-<p>
+</table>
 
-<h4>Example:</h4>
+<h4>Example</h4>
 
-This replaces occurrences of the string &#64;DATE&#64; in the data
-with today's date and stores it in the property ${src.file.replaced}.
-<blockquote><pre>
+<p>This replaces occurrences of the string <code>@DATE@</code> in the data with today's date and
+stores it in the property <code>${src.file.replaced}</code>.</p>
+<pre>
 &lt;tstamp/&gt;
 &lt;!-- just for explaining the use of the properties --&gt;
 &lt;property name=&quot;src.file&quot; value=&quot;orders.csv&quot;/&gt;
@@ -616,11 +549,10 @@
 &lt;/loadfile&gt;
 
 &lt;!-- just for explaining the use of the properties --&gt;
-&lt;echo message=&quot;${orders.replaced}&quot;/>
-</pre></blockquote>
+&lt;echo message=&quot;${orders.replaced}&quot;/&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;tstamp/&gt;
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.replaced}&quot;&gt;
   &lt;filterchain&gt;
@@ -628,12 +560,11 @@
       &lt;token key=&quot;DATE&quot; value=&quot;${TODAY}&quot;/&gt;
     &lt;/replacetokens&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-This replaces occurrences of the string {{DATE}} in the data
-with today's date and stores it in the property ${src.file.replaced}.
-<blockquote><pre>
+<p>This replaces occurrences of the string <q>{{DATE}}</q> in the data with today's date and
+stores it in the property <samp>${src.file.replaced}</samp>.</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.replaced}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.ReplaceTokens&quot;&gt;
@@ -641,11 +572,10 @@
       &lt;param type=&quot;tokenchar&quot; name=&quot;endtoken&quot; value=&quot;}}&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;tstamp/&gt;
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.replaced}&quot;&gt;
   &lt;filterchain&gt;
@@ -653,22 +583,20 @@
       &lt;token key=&quot;DATE&quot; value=&quot;${TODAY}&quot;/&gt;
     &lt;/replacetokens&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-This will treat each properties file entry in sample.properties as a token/key pair :
-<blockquote><pre>
+<p>This will treat each properties file entry in sample.properties as a token/key pair:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.replaced}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.ReplaceTokens&quot;&gt;
       &lt;param type=&quot;propertiesfile&quot; value=&quot;sample.properties&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-This reads the properties from an Ant resource referenced by its id:
-<blockquote><pre>
+<p>This reads the properties from an Ant resource referenced by its <var>id</var>:</p>
+<pre>
 &lt;string id=&quot;embedded-properties&quot;&gt;
 foo=bar
 baz=xyzzy
@@ -677,308 +605,270 @@
   &lt;filterchain&gt;
     &lt;replacetokens propertiesResource=&quot;${ant.refid:embedded-properties}&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<h3><a name="stripjavacomments">StripJavaComments</a></h3>
+<h3 id="stripjavacomments">StripJavaComments</h3>
 
-This filter reader strips away comments from the data,
-using Java syntax guidelines.  This filter does not
-take in any parameters.
-<p>
-<h4>Example:</h4>
+<p>This filter reader strips away comments from the data, using Java syntax guidelines.  This
+filter does not take in any parameters.</p>
 
-<blockquote><pre>
+<h4>Example</h4>
+
+<pre>
 &lt;loadfile srcfile=&quot;${java.src.file}&quot; property=&quot;${java.src.file.nocomments}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.StripJavaComments&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${java.src.file}&quot; property=&quot;${java.src.file.nocomments}&quot;&gt;
   &lt;filterchain&gt;
     &lt;stripjavacomments/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<h3><a name="striplinebreaks">StripLineBreaks</a></h3>
+<h3 id="striplinebreaks">StripLineBreaks</h3>
 
-This filter reader strips away specific characters
-from the data supplied to it.
+<p>This filter reader strips away specific characters from the data supplied to it.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>linebreaks</td>
-    <td vAlign=top align="center">Characters that are to
-    be stripped out.  Defaults to &quot;\r\n&quot;</td>
-    <td vAlign=top align="center">No</td>
+    <td>linebreaks</td>
+    <td>Characters that are to be stripped out.</td>
+    <td>No; defaults to <q>\r\n</q></td>
   </tr>
 </table>
-<p>
-<h4>Examples:</h4>
 
-This strips the '\r' and '\n' characters.
-<blockquote><pre>
+<h4>Examples</h4>
+
+<p>This strips the <q>\r</q> and <q>\n</q> characters.</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.contents}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.StripLineBreaks&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.contents}&quot;&gt;
   &lt;filterchain&gt;
     &lt;striplinebreaks/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-This treats the '(' and ')' characters as line break characters and
-strips them.
-<blockquote><pre>
+<p>This treats the <q>(</q> and <q>)</q> characters as line break characters and strips
+them.</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.contents}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.StripLineBreaks&quot;&gt;
       &lt;param name=&quot;linebreaks&quot; value=&quot;()&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<h3><a name="striplinecomments">StripLineComments</a></h3>
+<h3 id="striplinecomments">StripLineComments</h3>
 
-This filter removes all those lines that begin with strings
-that represent comments as specified by the user.
+<p>This filter removes all those lines that begin with strings that represent comments as specified
+by the user.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Type</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Type</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>comment</td>
-    <td vAlign=top align="center">Strings that identify a line as a comment
-    when they appear at the start of the line.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>comment</td>
+    <td>Strings that identify a line as a comment when they appear at the start of the
+    line.</td>
+    <td>Yes</td>
   </tr>
 </table>
 <p>
-<h4>Examples:</h4>
+<h4>Examples</h4>
 
-This removes all lines that begin with #, --, REM, rem and //
-<blockquote><pre>
+<p>This removes all lines that begin with <q>#</q>, <q>--</q>, <q>REM</q>, <q>rem</q>
+and <q>//</q></p>
+<pre>
 &lt;filterreader classname=&quot;org.apache.tools.ant.filters.StripLineComments&quot;&gt;
   &lt;param type=&quot;comment&quot; value=&quot;#&quot;/&gt;
   &lt;param type=&quot;comment&quot; value=&quot;--&quot;/&gt;
   &lt;param type=&quot;comment&quot; value=&quot;REM &quot;/&gt;
   &lt;param type=&quot;comment&quot; value=&quot;rem &quot;/&gt;
   &lt;param type=&quot;comment&quot; value=&quot;//&quot;/&gt;
-&lt;/filterreader&gt;
-</pre></blockquote>
+&lt;/filterreader&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;striplinecomments&gt;
   &lt;comment value=&quot;#&quot;/&gt;
   &lt;comment value=&quot;--&quot;/&gt;
   &lt;comment value=&quot;REM &quot;/&gt;
   &lt;comment value=&quot;rem &quot;/&gt;
   &lt;comment value=&quot;//&quot;/&gt;
-&lt;/striplinecomments&gt;
-</pre></blockquote>
+&lt;/striplinecomments&gt;</pre>
 
-<h3><a name="tabstospaces">TabsToSpaces</a></h3>
+<h3 id="tabstospaces">TabsToSpaces</h3>
 
-This filter replaces tabs with spaces
+<p>This filter replaces tabs with spaces</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>tablength</td>
-    <td vAlign=top align="center">Defaults to &quot;8&quot;</td>
-    <td vAlign=top align="center">No</td>
+    <td>tablength</td>
+    <td>Amount of space characters to replace a tab character with.</td>
+    <td>No; defaults to <q>8</q></td>
   </tr>
 </table>
-<p>
-<h4>Examples:</h4>
 
-This replaces tabs in ${src.file} with spaces.
-<blockquote><pre>
+<h4>Examples</h4>
+
+<p>This replaces tabs in <samp>${src.file}</samp> with spaces.</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.notab}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.TabsToSpaces&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.notab}&quot;&gt;
   &lt;filterchain&gt;
     &lt;tabstospaces/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<h3><a name="tailfilter">TailFilter</a></h3>
+<h3 id="tailfilter">TailFilter</h3>
 
-This filter reads the last few lines from the data supplied to it.
+<p>This filter reads the last few lines from the data supplied to it.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>lines</td>
-    <td vAlign=top align="center">Number of lines to be read.
-    Defaults to &quot;10&quot; <br> A negative value means that all lines are
-    passed (useful with <i>skip</i>)</td>
-    <td vAlign=top align="center">No</td>
+    <td>lines</td>
+    <td>Number of lines to be read.<br/>
+      A negative value means that all lines are passed
+      (useful with <var>skip</var>)</td>
+    <td>No; defaults to <q>10</q></td>
   </tr>
   <tr>
-    <td vAlign=top>skip</td>
-    <td vAlign=top align="center">Number of lines to be skipped (from the end).
-    Defaults to &quot;0&quot; </td>
-    <td vAlign=top align="center">No</td>
+    <td>skip</td>
+    <td>Number of lines to be skipped (from the end).</td>
+    <td>No; defaults to <q>0</q></td>
   </tr>
 </table>
 <p>
 
-<h4>Background:</h4>
-With HeadFilter and TailFilter you can extract each part of a text file you want.
-This graphic shows the dependencies:
+<h4>Background</h4>
+<p>With HeadFilter and TailFilter you can extract each part of a text file you want.  This graphic
+shows the dependencies:</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table>
 <tr>
- <th> Content </th>
- <th></th>
- <th></th>
- <th></th>
- <th> Filter </th>
+ <th scope="col">Content</th>
+ <th scope="col" colspan="3">Filter</th>
 </tr>
 <tr>
- <td> Line 1 </td>
- <td rowspan="2" bgcolor="#C0C0C0">&nbsp;</td>
- <td rowspan="9" bgcolor="#FF00FF">&nbsp;</td>
- <td rowspan="4">&nbsp;</td>
- <td rowspan="11">
-    <table>
-    <tr>
-     <td bgcolor="#C0C0C0">&nbsp;</td>
-     <td><pre>&lt;filterchain&gt;
+ <td>Line 1</td>
+ <td rowspan="2" style="background:limegreen;">
+   <pre style="background:limegreen;margin: 0 0 0 0;">&lt;filterchain&gt;
     &lt;headfilter lines="2"/&gt;
 &lt;/filterchain&gt;</pre></td>
-    </tr>
-    <tr>
-     <td bgcolor="#FF00FF">&nbsp;</td>
-     <td><pre>&lt;filterchain&gt;
+ <td rowspan="9" style="background:fuchsia;">
+   <pre style="background:fuchsia;margin: 0 0 0 0;">&lt;filterchain&gt;
     &lt;tailfilter lines="-1" skip="2"/&gt;
-&lt;/filterchain&gt;</pre></td>
-    </tr>
-    <tr>
-     <td bgcolor="#008000">&nbsp;</td>
-     <td><pre>&lt;filterchain&gt;
+&lt;/filterchain&gt;</pre>
+ </td>
+ <td rowspan="2">&nbsp;</td>
+</tr>
+<tr>
+ <td>Line 2</td>
+</tr>
+<tr>
+ <td>Line 3</td>
+ <td rowspan="9" style="background:tomato;">
+   <pre style="background:tomato;margin: 0 0 0 0;">&lt;filterchain&gt;
     &lt;headfilter lines="-1" skip="2"/&gt;
 &lt;/filterchain&gt;</pre></td>
-    </tr>
-    <tr>
-     <td bgcolor="#0000FF">&nbsp;</td>
-     <td><pre>&lt;filterchain&gt;
+ <td rowspan="7" style="background:dodgerblue;">
+   <pre style="background:dodgerblue;margin: 0 0 0 0;">&lt;filterchain&gt;
     &lt;headfilter lines="-1" skip="2"/&gt;
     &lt;tailfilter lines="-1" skip="2"/&gt;
 &lt;/filterchain&gt;</pre></td>
-    </tr>
-    <tr>
-     <td bgcolor="#00FF00">&nbsp;</td>
-     <td><pre>&lt;filterchain&gt;
+</tr>
+<tr>
+ <td>Line 4</td>
+</tr>
+<tr>
+ <td>Line 5</td>
+</tr>
+<tr>
+ <td>Lines ...</td>
+</tr>
+<tr>
+ <td>Line 95</td>
+</tr>
+<tr>
+ <td>Line 96</td>
+</tr>
+<tr>
+ <td>Line 97</td>
+</tr>
+<tr>
+ <td>Line 98</td>
+ <td rowspan="2" style="background:lime;">
+   <pre  style="background:lime;margin: 0 0 0 0;">&lt;filterchain&gt;
     &lt;tailfilter lines="2"/&gt;
 &lt;/filterchain&gt;</pre></td>
-    </tr>
-    </table>
- </td>
+ <td rowspan="2">&nbsp;</td>
 </tr>
 <tr>
- <td> Line 2 </td>
-</tr>
-<tr>
- <td> Line 3 </td>
- <td rowspan="9" bgcolor="#008000">&nbsp;</td>
-</tr>
-<tr>
- <td> Line 4 </td>
-</tr>
-<tr>
- <td> Line 5 </td>
- <td rowspan="3" bgcolor="#0000FF">&nbsp;</td>
-</tr>
-<tr>
- <td> Lines ... </td>
-</tr>
-<tr>
- <td> Line 95 </td>
-</tr>
-<tr>
- <td> Line 96 </td>
- <td rowspan="4">&nbsp;</td>
-</tr>
-<tr>
- <td> Line 97 </td>
-</tr>
-<tr>
- <td> Line 98 </td>
- <td rowspan="2" bgcolor="#00FF00">&nbsp;</td>
-</tr>
-<tr>
- <td> Line 99 </td>
+ <td>Line 99</td>
 </tr>
 </table>
 
+<h4>Examples</h4>
 
-
-<h4>Examples:</h4>
-
-This stores the last 15 lines of the supplied data in the property ${src.file.tail}
-<blockquote><pre>
+<p>This stores the last 15 lines of the supplied data in the
+property <samp>${src.file.tail}</samp></p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.tail}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.TailFilter&quot;&gt;
       &lt;param name=&quot;lines&quot; value=&quot;15&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.tail}&quot;&gt;
   &lt;filterchain&gt;
     &lt;tailfilter lines=&quot;15&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-
-This stores the last 5 lines of the first 15 lines of the supplied
-data in the property ${src.file.mid}
-<blockquote><pre>
+<p>This stores the last 5 lines of the first 15 lines of the supplied data in the
+property <samp>${src.file.mid}</samp></p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.mid}&quot;&gt;
   &lt;filterchain&gt;
     &lt;filterreader classname=&quot;org.apache.tools.ant.filters.HeadFilter&quot;&gt;
@@ -988,628 +878,668 @@
       &lt;param name=&quot;lines&quot; value=&quot;5&quot;/&gt;
     &lt;/filterreader&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-Convenience method:
-<blockquote><pre>
+<p>Convenience method:</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;${src.file.mid}&quot;&gt;
   &lt;filterchain&gt;
     &lt;headfilter lines=&quot;15&quot;/&gt;
     &lt;tailfilter lines=&quot;5&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-
-This stores the last 10 lines, skipping the last 2 lines, of the supplied data
-in the property src.file.head. (Means: if supplied data contains 60 lines,
-lines 49-58 are extracted)
-<blockquote><pre>
+<p>This stores the last 10 lines, skipping the last 2 lines, of the supplied data in the
+property <code>src.file.head</code>. (Means: if supplied data contains 60 lines, lines 49-58 are
+extracted)</p>
+<pre>
 &lt;loadfile srcfile=&quot;${src.file}&quot; property=&quot;src.file.head&quot;&gt;
   &lt;filterchain&gt;
     &lt;tailfilter lines=&quot;10&quot; skip=&quot;2&quot;/&gt;
   &lt;/filterchain&gt;
-&lt;/loadfile&gt;
-</pre></blockquote>
+&lt;/loadfile&gt;</pre>
 
-<h3><a name="deletecharacters">DeleteCharacters</a></h3>
+<h3 id="deletecharacters">DeleteCharacters</h3>
 
-  <p>This filter deletes specified characters.</p>
-  <p><em>since Ant 1.6</em></p>
-  <p>This filter is only available in the convenience form.</p>
+<p><em>Since Ant 1.6</em></p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<p>This filter deletes specified characters.</p>
+
+<p>This filter is only available in the convenience form.</p>
+
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>chars</td>
-    <td vAlign=top>
-      The characters to delete. This attribute is
-      <a href="#backslash">backslash enabled</a>.
+    <td>chars</td>
+    <td>
+      The characters to delete. This attribute is <a href="#backslash">backslash enabled</a>.
     </td>
-    <td vAlign=top align="center">Yes</td>
+    <td>Yes</td>
   </tr>
 </table>
 <p>
-<h4>Examples:</h4>
+<h4>Examples</h4>
 
-Delete tabs and returns from the data.
-<blockquote><pre>
-&lt;deletecharacters chars="\t\r"/&gt;
-</pre></blockquote>
+<p>Delete tabs and returns from the data.</p>
+<pre>&lt;deletecharacters chars="\t\r"/&gt;</pre>
 
-<h3><a name="concatfilter">ConcatFilter</a></h3>
-  <p>This filter prepends or appends the content file to the filtered files.</p>
-  <p><em>since Ant 1.6</em></p>
-<table cellSpacing=0 cellPadding=2 border=1>
+<h3 id="concatfilter">ConcatFilter</h3>
+<p><em>Since Ant 1.6</em></p>
+<p>This filter prepends or appends the content file to the filtered files.</p>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>prepend</td>
-    <td vAlign=top>
+    <td>prepend</td>
+    <td>
       The name of the file which content should be prepended to the file.
     </td>
-    <td vAlign=top align="center">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>append</td>
-    <td vAlign=top>
+    <td>append</td>
+    <td>
       The name of the file which content should be appended to the file.
     </td>
-    <td vAlign=top align="center">No</td>
+    <td>No</td>
   </tr>
 </table>
 <p>
 
-<h4>Examples:</h4>
+<h4>Examples</h4>
 
-Do nothing:
-<blockquote><pre>
+<p>Do nothing:</p>
+<pre>
 &lt;filterchain&gt;
     &lt;concatfilter/&gt;
-&lt;/filterchain&gt;
-</pre></blockquote>
+&lt;/filterchain&gt;</pre>
 
-Adds a license text before each java source:
-<blockquote><pre>
+<p>Adds a license text before each Java source file:</p>
+<pre>
 &lt;filterchain&gt;
     &lt;concatfilter prepend="apache-license-java.txt"/&gt;
-&lt;/filterchain&gt;
-</pre></blockquote>
+&lt;/filterchain&gt;</pre>
 
+<h3 id="sortfilter">SortFilter</h3>
+<p><em>Since Ant 1.8.0</em></p>
 
+<p>The sort filter reads all lines and sorts them.  The sort order can be reversed and it is
+possible to specify a custom implementation of the <code class="code">java.util.Comparator</code>
+interface to get even more control.</p>
 
-<h3><a name="tokenfilter">TokenFilter</a></h3>
-This filter tokenizes the inputstream into strings and passes these
-strings to filters of strings. Unlike the other filterreaders, this does
-not support params, only convenience methods are implemented.
-The tokenizer and the string filters are defined by nested elements.
-<p><em>since Ant 1.6</em></p>
-<p>
-Only one tokenizer element may be used, the LineTokenizer is the
-default if none are specified.  A tokenizer
-splits the input into token strings and trailing delimiter strings.
-<p>
-There may be zero or more string filters. A string filter processes
-a token and either returns a string or a null.
-It the string is not null it is passed to the next filter. This
-proceeds until all the filters are called.
-If a string is returned after all the filters, the string is
-outputs with its associated token delimiter
-(if one is present).
-The trailing delimiter may be overridden by the <i>delimOutput</i>
-attribute.
-<p>
-<a name="backslash"><em>backslash interpretation</em></a>
-A number of attributes (including <i>delimOutput</i>) interpret
-backslash escapes. The following are understood: \n, \r, \f, \t
-and \\.
-
-
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Parameter Name</th>
+    <th scope="col">Parameter Value</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>delimOutput</td>
-    <td vAlign=top>
-     This overrides the tokendelimiter
-        returned by the tokenizer if it is not empty. This
+    <td>reverse</td>
+    <td>Whether to reverse the sort order.<br/><strong>Note</strong>: this parameter is ignored
+      if the comparator parameter is present as well.</td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>comparator</td>
+    <td>Class name of a class that implements <code class="code">java.util.Comparator</code> for
+      Strings.  This class will be used to determine the sort order of lines.</td>
+    <td>No</td>
+  </tr>
+</table>
+
+<p>This filter is also available using the name <code>sortfilter</code>.
+The <code>reverse</code> parameter becomes an attribute, <code>comparator</code> can be
+specified by using a nested element.</p>
+
+<h4>Examples</h4>
+
+<pre>
+&lt;copy todir=&quot;build&quot;&gt;
+    &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
+    &lt;filterchain&gt;
+        &lt;sortfilter/&gt;
+    &lt;/filterchain&gt;
+&lt;/copy&gt;</pre>
+
+<p>
+Sort all files <samp>*.txt</samp> from <samp>src</samp> location into <samp>build</samp>
+location. The lines of each file are sorted in ascendant order comparing the lines via the
+<code>String.compareTo(Object o)</code> method.
+</p>
+
+<pre>
+&lt;copy todir=&quot;build&quot;&gt;
+    &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
+    &lt;filterchain&gt;
+        &lt;sortfilter reverse=&quot;true&quot;/&gt;
+    &lt;/filterchain&gt;
+&lt;/copy&gt;</pre>
+
+<p>
+Sort all files <samp>*.txt</samp> from <samp>src</samp> location into reverse order and copy
+them into <samp>build</samp> location.
+</p>
+
+<pre>
+&lt;copy todir=&quot;build&quot;&gt;
+    &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
+    &lt;filterchain&gt;
+        &lt;filterreader classname=&quot;org.apache.tools.ant.filters.SortFilter&quot;&gt;
+            &lt;param name=&quot;comparator&quot; value=&quot;org.apache.tools.ant.filters.EvenFirstCmp&quot;/&gt;
+        &lt;/filterreader&gt;
+    &lt;/filterchain&gt;
+&lt;/copy&gt;</pre>
+
+<p>
+Sort all files <samp>*.txt</samp> from <samp>src</samp> location using as sorting
+criterium <code class="code">EvenFirstCmp</code> class, that sorts the file lines putting even lines
+first then odd lines for example. The modified files are copied into <samp>build</samp>
+location. The <code class="code">EvenFirstCmp</code> has to an instanciable class
+via <code class="code">Class.newInstance()</code>, therefore in case of inner class has to
+be <em>static</em>. It also has to implement <code class="code">java.util.Comparator</code>
+interface, for example:
+</p>
+
+<pre>
+package org.apache.tools.ant.filters;
+... (omitted)
+public final class EvenFirstCmp implements &lt;b&gt;Comparator&lt;/b&gt; {
+   public int compare(Object o1, Object o2) {
+       ...(omitted)
+   }
+}</pre>
+
+<p>The example above is equivalent to:</p>
+
+<pre>
+&lt;componentdef name=&quot;evenfirst&quot;
+              classname=&quot;org.apache.tools.ant.filters.EvenFirstCmp&quot;/&gt;
+&lt;copy todir=&quot;build&quot;&gt;
+    &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
+    &lt;filterchain&gt;
+        &lt;sortfilter&gt;
+            &lt;evenfirst/&gt;
+        &lt;/sortfilter&gt;
+    &lt;/filterchain&gt;
+&lt;/copy&gt;</pre>
+
+<h3 id="tokenfilter">TokenFilter</h3>
+<p>This filter tokenizes the InputStream into strings and passes these strings to filters of
+strings. Unlike the other FilterReaders, this does not support <code>param</code>s, only
+convenience methods are implemented.  The tokenizer and the string filters are defined by nested
+elements.</p>
+<p><em>Since Ant 1.6</em></p>
+<p>
+Only one <code>tokenizer</code> element may be used, the LineTokenizer is the default if none
+are specified.  A tokenizer splits the input into token strings and trailing delimiter strings.
+<p>
+There may be zero or more string filters. A string filter processes a token and either returns a
+string or a null.  It the string is not null it is passed to the next filter. This proceeds
+until all the filters are called.  If a string is returned after all the filters, the string is
+outputs with its associated token delimiter (if one is present).  The trailing delimiter may be
+overridden by the <var>delimOutput</var> attribute.
+<h4 id="backslash">Backslash interpretation</h4>
+<p>
+A number of attributes (including <var>delimOutput</var>) interpret backslash escapes. The
+following are understood: <q>\n</q>, <q>\r</q>, <q>\f</q>, <q>\t</q> and <q>\\</q>.
+</p>
+
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>delimOutput</td>
+    <td>
+     This overrides the token delimiter returned by the tokenizer if it is not empty. This
      attribute is backslash enabled.
-</td>
-    <td vAlign=top align="center">No</td>
-  </tr>
-</table>
-<p>
-
-    The following tokenizers are provided by the default distribution.
-    <p>
-        <a href="#linetokenizer">LineTokenizer</a><br>
-        <a href="#filetokenizer">FileTokenizer</a><br>
-        <a href="#stringtokenizer">StringTokenizer</a><br>
-    </p>
-
-    The following string filters are provided by the default distribution.
-    <p>
-        <a href="#replacestring">ReplaceString</a><br>
-        <a href="#containsstring">ContainsString</a><br>
-        <a href="#replaceregex">ReplaceRegex</a><br>
-        <a href="#containsregex">ContainsRegex</a><br>
-        <a href="#trim">Trim</a><br>
-        <a href="#ignoreblank">IgnoreBlank</a><br>
-        <a href="#filterdeletecharacters">DeleteCharacters</a><br>
-        <a href="#uniqfilter">UniqFilter</a><br>
-        <a href="#native2asciifilter">Native2AsciiFilter</a><br>
-    </p>
-
-    The following string filters are provided by the optional distribution.
-    <p>
-        <a href="#scriptfilter">ScriptFilter</a><br>
-    </p>
-
-Some of the filters may be used directly within a filter chain. In this
-case a tokenfilter is created implicitly. An extra attribute "byline"
-is added to the filter to specify whether to use a linetokenizer
-(byline="true") or a filetokenizer (byline="false"). The default
-is "true".
-<p>
-
-<p><b><em><a name="linetokenizer">LineTokenizer</a></em></b></p>
-This tokenizer splits the input into lines.
-The tokenizer delimits lines
-by "\r", "\n" or "\r\n".
-This is the default tokenizer.
-<table cellSpacing=0 cellPadding=2 border=1>
-  <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
-  </tr>
-  <tr>
-    <td vAlign=top>includeDelims</td>
-    <td vAlign=top>
-      Include the line endings in the token.
-      Default is false.
     </td>
-    <td vAlign=top align="center">No</td>
+    <td>No</td>
   </tr>
 </table>
-<h4>Examples:</h4>
+<p>The following tokenizers are provided by the default distribution.</p>
+<p>
+  <a href="#linetokenizer">LineTokenizer</a><br/>
+  <a href="#filetokenizer">FileTokenizer</a><br/>
+  <a href="#stringtokenizer">StringTokenizer</a>
+</p>
+<p>The following string filters are provided by the default distribution.</p>
+<p>
+  <a href="#replacestring">ReplaceString</a><br/>
+  <a href="#containsstring">ContainsString</a><br/>
+  <a href="#replaceregex">ReplaceRegex</a><br/>
+  <a href="#containsregex">ContainsRegex</a><br/>
+  <a href="#trim">Trim</a><br/>
+  <a href="#ignoreblank">IgnoreBlank</a><br/>
+  <a href="#filterdeletecharacters">DeleteCharacters</a><br/>
+  <a href="#uniqfilter">UniqFilter</a><br/>
+  <a href="#native2asciifilter">Native2AsciiFilter</a>
+</p>
+<p>The following string filters are provided by the optional distribution.</p>
+<p>
+  <a href="#scriptfilter">ScriptFilter</a>
+</p>
+<p>
+  <a href="#custom">Custom</a> tokenizers and string filters can be declared
+  using <a href="../Tasks/typedef.html">typedef</a> task.
+</p>
+<p>
+Some of the filters may be used directly within a <code>filterchain</code>. In this case
+a <code>tokenfilter</code> is created implicitly. An extra attribute <var>byline</var> is added to
+the filter to specify whether to use a <code>linetokenizer</code> (<var>byline</var>=<q>true</q>) or
+a <code>filetokenizer</code> (<var>byline</var>=<q>false</q>). The default is <q>true</q>.
+</p>
 
-Convert input current line endings to unix style line endings.
-<blockquote><pre>
-&lt;tokenfilter delimoutput=&quot;\n&quot;/&gt;
-</pre></blockquote>
+<h4 id="linetokenizer">LineTokenizer</h4>
+<p>This tokenizer splits the input into lines.  The tokenizer delimits lines by <q>\r</q>, <q>\n</q>
+or <q>\r\n</q>.  This is the default tokenizer.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>includeDelims</td>
+    <td>
+      Include the line endings in the token.
+    </td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+</table>
+<h5>Examples</h5>
 
+<p>Convert input current line endings to Unix style line endings.</p>
+<pre>&lt;tokenfilter delimoutput=&quot;\n&quot;/&gt;</pre>
 
-Remove blank lines.
-<blockquote><pre>
+<p>Remove blank lines.</p>
+<pre>
 &lt;tokenfilter&gt;
     &lt;ignoreblank/&gt;
-&lt;/tokenfilter&gt;
+&lt;/tokenfilter&gt;</pre>
 
-</pre></blockquote>
+<h4 id="filetokenizer">FileTokenizer</h4>
+<p>This tokenizer treats <strong>all</strong> the input as a token. So be careful not to use
+this on very large input.</p>
+<h5>Examples</h5>
 
-<p><b><em><a name="filetokenizer">FileTokenizer</a></em></b></p>
-This tokenizer treats <b>all</b> the input as a token. So be
-careful not to use this on very large input.
-<h4>Examples:</h4>
-
-Replace the first occurrence of package with //package.
-<blockquote><pre>
+<p>Replace the first occurrence of <samp>package</samp> with <samp>//package</samp>.</p>
+<pre>
 &lt;tokenfilter&gt;
       &lt;filetokenizer/&gt;
       &lt;replaceregex pattern="([\n\r]+[ \t]*|^[ \t]*)package"
                     flags="s"
                     replace="\1//package"/&gt;
-&lt;/tokenfilter&gt;
-</pre></blockquote>
+&lt;/tokenfilter&gt;</pre>
 
-<p><b><em><a name="stringtokenizer">StringTokenizer</a></em></b></p>
-This tokenizer is based on java.util.StringTokenizer.
-It splits up the input into strings separated by white space, or
-by a specified list of delimiting characters.
-If the stream starts with delimiter characters, the first
-token will be the empty string (unless the <i>delimsaretokens</i>
-attribute is used).
+<h4 id="stringtokenizer">StringTokenizer</h4>
+<p>This tokenizer is based on <code class="code">java.util.StringTokenizer</code>.  It splits up the
+input into strings separated by white space, or by a specified list of delimiting characters.  If
+the stream starts with delimiter characters, the first token will be the empty string (unless
+the <var>delimsaretokens</var> attribute is used).</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>delims</td>
-    <td vAlign=top>The delimiter characters. White space
-      is used if this is not set. (White space is defined
-      in this case by java.lang.Character.isWhitespace()).
+    <td>delims</td>
+    <td>The delimiter characters.
     </td>
-    <td vAlign=top align="center">No</td>
+    <td>No; defaults to white space as defined
+      by <code>java.lang.Character.isWhitespace()</code></td>
   </tr>
   <tr>
-    <td valign="top">delimsaretokens</td>
-    <td valign="top">If this is true,
-      each delimiter character is returned as a token.
-      Default is false.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>delimsaretokens</td>
+    <td>If this is <q>true</q>, each delimiter character is returned as a token.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">suppressdelims</td>
-    <td valign="top">
-      If this is true, delimiters are not returned.
-      Default is false.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>suppressdelims</td>
+    <td>If this is <q>true</q>, delimiters are not returned.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td vAlign=top>includeDelims</td>
-    <td vAlign=top>
-      Include the delimiters in the token.
-      Default is false.
-    </td>
-    <td vAlign=top align="center">No</td>
+    <td>includeDelims</td>
+    <td>Include the delimiters in the token.</td>
+    <td>No; default is <q>false</q></td>
   </tr>
 </table>
 
-<h4>Examples:</h4>
+<h5>Examples</h5>
 
-Surround each non space token with a "[]".
+<p>Surround each non space token with a <q>[]</q>.</p>
 
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;stringtokenizer/&gt;
     &lt;replaceregex pattern="(.+)" replace="[\1]"/&gt;
-&lt;/tokenfilter&gt;
+&lt;/tokenfilter&gt;</pre>
 
-</pre></blockquote>
+<h4 id="replacestring">ReplaceString</h4>
+<p>This is a simple filter to replace strings.  This filter may be used directly within
+a <code>filterchain</code>.</p>
 
-<p><b><em><a name="replacestring">ReplaceString</a></em></b></p>
-This is a simple filter to replace strings.
-This filter may be used directly within a filterchain.
-
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>from</td>
-    <td vAlign=top>The string that must be replaced.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>from</td>
+    <td>The string that must be replaced.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">to</td>
-    <td valign="top">The new value for the replaced string. When omitted
-      an empty string is used.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>to</td>
+    <td>The new value for the replaced string.</td>
+    <td>No; defaults to empty string</td>
   </tr>
 </table>
 
-<h4>Examples:</h4>
+<h5>Examples</h5>
 
-Replace "sun" with "moon".
+<p>Replace <q>sun</q> with <q>moon</q>.</p>
 
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;replacestring from="sun" to="moon"/&gt;
-&lt;/tokenfilter&gt;
-</pre></blockquote>
+&lt;/tokenfilter&gt;</pre>
 
-<p><b><em><a name="containsstring">ContainsString</a></em></b></p>
-This is a simple filter to filter tokens that contains
-a specified string.
+<h4 id="containsstring">ContainsString</h4>
+<p>This is a simple filter to filter tokens that contains a specified string.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>contains</td>
-    <td vAlign=top>The string that the token must contain.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>contains</td>
+    <td>The string that the token must contain.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h4>Examples:</h4>
+<h5>Examples</h5>
 
-Include only lines that contain "foo";
+<p>Include only lines that contain <q>foo</q></p>
 
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;containsstring contains="foo"/&gt;
-&lt;/tokenfilter&gt;
+&lt;/tokenfilter&gt;</pre>
 
-</pre></blockquote>
-
-<p><b><em><a name="replaceregex">ReplaceRegex</a></em></b></p>
-This string filter replaces regular expressions.
-This filter may be used directly within a filterchain.
+<h4 id="replaceregex">ReplaceRegex</h4>
 <p>
- See <a href="regexp.html#implementation">Regexp Type</a>
-concerning the choice of the implementation.
+This string filter replaces regular expressions.  This filter may be used directly within
+a <code>filterchain</code>.
+</p>
+<p>
+See <a href="regexp.html#implementation">Regexp Type</a> concerning the choice of the
+implementation.
 </p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>pattern</td>
-    <td vAlign=top>The regular expression pattern to match in
-      the token.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>pattern</td>
+    <td>The regular expression pattern to match in the token.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td vAlign=top>replace</td>
-    <td vAlign=top>The substitution pattern to replace the matched
-      regular expression. When omitted an empty string is used.</td>
-    <td vAlign=top align="center">No</td>
+    <td>replace</td>
+    <td>The substitution pattern to replace the matched regular expression.</td>
+    <td>No; defaults to empty string</td>
   </tr>
   <tr>
-    <td vAlign=top>flags</td>
-    <td vAlign=top>See
-<a href="../Tasks/replaceregexp.html">ReplaceRegexp</a>
-for an explanation of regex flags.</td>
-    <td vAlign=top align="center">No</td>
+    <td>flags</td>
+    <td>See <a href="../Tasks/replaceregexp.html">ReplaceRegexp</a> for an explanation of regex
+      flags.</td>
+    <td>No</td>
   </tr>
 </table>
-<h4>Examples:</h4>
+<h5>Examples</h5>
 
-Replace all occurrences of "hello" with "world", ignoring case.
+<p>Replace all occurrences of <q>hello</q> with <q>world</q>, ignoring case.</p>
 
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;replaceregex pattern="hello" replace="world" flags="gi"/&gt;
-&lt;/tokenfilter&gt;
+&lt;/tokenfilter&gt;</pre>
 
-</pre></blockquote>
-
-<p><b><em><a name="containsregex">ContainsRegex</a></em></b></p>
-This filters strings that match regular expressions.
-The filter may optionally replace the matched regular expression.
-This filter may be used directly within a filterchain.
+<h4 id="containsregex">ContainsRegex</h4>
 <p>
-See
-<a href="regexp.html#implementation">Regexp Type</a>
-concerning the choice of regular expression implementation.
+This filters strings that match regular expressions.  The filter may optionally replace the
+matched regular expression.  This filter may be used directly within a <code>filterchain</code>.
 </p>
-<table cellSpacing=0 cellPadding=2 border=1>
+<p>
+See <a href="regexp.html#implementation">Regexp Type</a> concerning the choice of regular
+expression implementation.
+</p>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>pattern</td>
-    <td vAlign=top>The regular expression pattern to match in
-      the token.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>pattern</td>
+    <td>The regular expression pattern to match in the token.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td vAlign=top>replace</td>
-    <td vAlign=top>The substitution pattern to replace the matched
-      regular expression. When omitted the original token is returned.
-    </td>
-    <td vAlign=top align="center">No</td>
+    <td>replace</td>
+    <td>The substitution pattern to replace the matched regular expression.</td>
+    <td>No; defaults to returning the original token</td>
   </tr>
   <tr>
-    <td vAlign=top>flags</td>
-    <td vAlign=top>See
-<a href="../Tasks/replaceregexp.html">ReplaceRegexp</a>
-for an explanation of regex flags.</td>
-    <td vAlign=top align="center">No</td>
+    <td>flags</td>
+    <td>See <a href="../Tasks/replaceregexp.html">ReplaceRegexp</a> for an explanation of regex
+      flags.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4>Examples:</h4>
+<h5>Examples</h5>
 
-Filter lines that contain "hello" or "world", ignoring case.
+<p>Filter lines that contain <q>hello</q> or <q>world</q>, ignoring case.</p>
 
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;containsregex pattern="(hello|world)" flags="i"/&gt;
-&lt;/tokenfilter&gt;
+&lt;/tokenfilter&gt;</pre>
 
-</pre></blockquote>
+<p>This example replaces lines like <code>SUITE(TestSuite, bits);</code> with <code>void
+register_bits();</code> and removes other lines.</p>
 
-This example replaces lines like "SUITE(TestSuite, bits);" with
-"void register_bits();" and removes other lines.
-
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;containsregex
         pattern="^ *SUITE\(.*,\s*(.*)\s*\).*"
         replace="void register_\1();"/&gt;
-&lt;/tokenfilter&gt;
-</pre></blockquote>
+&lt;/tokenfilter&gt;</pre>
 
-<p><b><em><a name="trim">Trim</a></em></b></p>
-This filter trims whitespace from the start and end of
-tokens.
-This filter may be used directly within a filterchain.
-<p><b><em><a name="ignoreblank">IgnoreBlank</a></em></b></p>
-This filter removes empty tokens.
-This filter may be used directly within a filterchain.
-<p><b><em><a name="filterdeletecharacters">DeleteCharacters</a></em></b></p>
-This filter deletes specified characters from tokens.
+<h4 id="trim">Trim</h4>
+<p>This filter trims whitespace from the start and end of tokens.  This filter may be used
+directly within a <code>filterchain</code>.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<h4 id="ignoreblank">IgnoreBlank</h4>
+<p>This filter removes empty tokens.  This filter may be used directly within
+a <code>filterchain</code>.</p>
+
+<h4 id="filterdeletecharacters">DeleteCharacters</h4>
+<p>This filter deletes specified characters from tokens.</p>
+
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>chars</td>
-    <td vAlign=top>The characters to delete. This attribute
-      is backslash enabled.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>chars</td>
+    <td>The characters to delete. This attribute is backslash enabled.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h4>Examples:</h4>
+<h5>Examples</h5>
 
-Delete tabs from lines, trim the lines and removes empty lines.
+<p>Delete tabs from lines, trim the lines and removes empty lines.</p>
 
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
     &lt;deletecharacters chars="\t"/&gt;
     &lt;trim/&gt;
     &lt;ignoreblank/&gt;
-&lt;/tokenfilter&gt;
+&lt;/tokenfilter&gt;</pre>
 
-</pre></blockquote>
+<h4 id="uniqfilter">UniqFilter</h4>
 
-<p><b><em><a name="uniqfilter">UniqFilter</a></em></b></p>
+<p>Suppresses all tokens that match their ancestor token.  It is most useful if combined with a
+sort filter.</p>
 
-<p>Suppresses all tokens that match their ancestor token.  It is most
-  useful if combined with a sort filter.</p>
+<p>This filter may be used directly within a <code>filterchain</code>.</p>
 
-<p>This filter may be used directly within a filterchain.</p>
+<h5>Example</h5>
 
-<h4>Example:</h4>
-
-This suppresses duplicate lines.
-<blockquote><pre>
+<p>This suppresses duplicate lines.</p>
+<pre>
 &lt;tokenfilter&gt;
   &lt;uniqfilter/&gt;
-&lt;/tokenfilter&gt;
-</pre></blockquote>
+&lt;/tokenfilter&gt;</pre>
 
-<p><b><em><a name="native2asciifilter">Native2AsciiFilter</a></em></b></p>
+<h4 id="native2asciifilter">Native2AsciiFilter</h4>
+
+<p><em>Since Ant 1.9.8</em></p>
 
 <p>Uses the "builtin" implementation of
-  the <a href="../Tasks/native2ascii.html">native2ascii</a> task.</p>
+the <a href="../Tasks/native2ascii.html">native2ascii</a> task.</p>
 
-<p>Replaces non-ascii characters by their Unicode-escapes or
-  vice-versa.  <em>Since Ant 1.9.8</em>.</p>
+<p>Replaces non-ASCII characters by their Unicode-escapes or vice-versa.</p>
 
-<p>This filter may be used directly within a filterchain.</p>
+<p>This filter may be used directly within a <code>filterchain</code>.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>reverse</td>
-    <td vAlign=top>Reverse the sense of the conversion,
-      i.e. convert from ASCII to native.</td>
-    <td vAlign=top align="center">No</td>
+    <td>reverse</td>
+    <td>Reverse the sense of the conversion, i.e. convert from ASCII to native.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4>Example:</h4>
+<h5>Example</h5>
 
 <p>This replaces all non-ASCII characters by their Unicode-escapes.</p>
-<blockquote><pre>
+<pre>
 &lt;tokenfilter&gt;
   &lt;native2asciifilter/&gt;
-&lt;/tokenfilter&gt;
-</pre></blockquote>
+&lt;/tokenfilter&gt;</pre>
 
-<p><b><em><a name="scriptfilter">ScriptFilter</a></em></b></p>
-This is an optional filter that executes a script in a
-<a href="http://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
-  or
-  <a href="https://scripting.dev.java.net">JSR 223</a>
-supported language.</p>
-See the <a href="../Tasks/script.html">Script</a> task for
-an explanation of scripts and dependencies.
+<h4 id="scriptfilter">ScriptFilter</h4>
+<p>
+This is an optional filter that executes a script in a <a href="https://jakarta.apache.org/bsf"
+target="_top">Apache BSF</a>
+or <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr223/223ChangeLog.html"
+target="_top">JSR 223</a> supported language.
 </p>
 <p>
-The script is provided with an object <i>self</i> that has
-getToken() and setToken(String) methods.
-The getToken() method returns the current token. The setToken(String)
-method replaces the current token.
+See the <a href="../Tasks/script.html">Script</a> task for an explanation of scripts and
+dependencies.
 </p>
-
-This filter may be used directly within a filterchain.<p>
-<table cellSpacing=0 cellPadding=2 border=1>
+<p>
+The script is provided with an object <samp class="code">self</samp> that
+has <code class="code">getToken()</code> and <code class="code">setToken(String)</code> methods.
+The <code class="code">getToken()</code> method returns the current
+token. The <code class="code">setToken(String)</code> method replaces the current token.
+</p>
+<p>
+This filter may be used directly within a <code>filterchain</code>.
+</p>
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>language</td>
-    <td vAlign=top> The programming language the script is written in.
-Must be a supported Apache BSF or JSR 223 language</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>language</td>
+    <td>Programming language the script is written in.  Must be a supported Apache BSF or JSR 223
+      language</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">manager</td>
-    <td valign="top">
-      The script engine manager to use.
-      See the <a href="../Tasks/script.html">script</a> task
-      for using this attribute.
-    </td>
-    <td valign="top" align="center">No - default is "auto"</td>
+    <td>manager</td>
+    <td>Script engine manager to use.  See the <a href="../Tasks/script.html">script</a> task for
+      using this attribute.</td>
+    <td>No; default is <q>auto</q></td>
   </tr>
   <tr>
-    <td vAlign=top>src</td>
-    <td vAlign=top>The location of the script as a file, if not inline
-    </td>
-    <td vAlign=top align="center">No</td>
+    <td>src</td>
+    <td>Location of the script as a file, if not inline.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">setbeans</td>
-    <td valign="top">whether to have all properties, references and targets as
-      global variables in the script.  <em>since Ant 1.8.0</em></td>
-    <td valign="top" align="center">No, default is "true".</td>
+    <td>encoding</td>
+    <td>Encoding of the script as a file. <em>Since Ant 1.10.2</em></td>
+    <td>No; defaults to default JVM character encoding</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">
-      The classpath to pass into the script.
-    </td>
-    <td align="center" valign="top">No</td>
+    <td>setbeans</td>
+    <td>Whether to have all properties, references and targets as global variables in the
+      script.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">The classpath to use, given as a
-       <a href="../using.html#references">reference</a> to a path defined elsewhere.
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>The classpath to pass into the script.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a path
+      defined elsewhere.
+    <td>No</td>
   </tr>
 </table>
-  <p>
-    This filter can take a nested &lt;classpath&gt; element.
-    See the <a href="../Tasks/script.html">script</a> task
-    on how to use this element.
-  </p>
-<h4>Examples:</h4>
-
-Convert to uppercase:
-<blockquote><pre>
+<p>
+This filter can take a nested <code>&lt;classpath&gt;</code> element.  See
+the <a href="../Tasks/script.html">script</a> task on how to use this element.
+</p>
+<h5>Examples</h5>
+<p>Convert to uppercase:</p>
+<pre>
 &lt;tokenfilter&gt;
     &lt;scriptfilter language="javascript"&gt;
         self.setToken(self.getToken().toUpperCase());
     &lt;/scriptfilter&gt;
-&lt;/tokenfilter&gt;
-</pre></blockquote>
+&lt;/tokenfilter&gt;</pre>
 
-Remove lines containing the string "bad" while
-copying text files:
-  <blockquote>
-    <pre>
+<p>Remove lines containing the string <q>bad</q> while copying text files:</p>
+<pre>
 &lt;copy todir="dist"&gt;
   &lt;fileset dir="src" includes="**/*.txt"/&gt;
   &lt;filterchain&gt;
@@ -1619,19 +1549,17 @@
         }
     &lt;/scriptfilter&gt;
   &lt;/filterchain&gt;
-&lt;/copy&gt;
-    </pre>
-  </blockquote>
+&lt;/copy&gt;</pre>
 
-<h4>Custom tokenizers and string filters</h4>
+<h4 id="custom">Custom tokenizers and string filters</h4>
 
-Custom string filters and tokenizers may be plugged in by
-extending the interfaces org.apache.tools.ant.filters.TokenFilter.Filter
-and org.apache.tools.ant.util.Tokenizer respectly.
+<p>Custom string filters and tokenizers may be plugged in by extending the
+interfaces <code class="code">org.apache.tools.ant.filters.TokenFilter.Filter</code>
+and <code class="code">org.apache.tools.ant.util.Tokenizer</code> respectly.</p>
 
-They are defined the build file using <code>&lt;typedef/&gt;</code>. For
-example a string filter that capitalizes words may be declared as:
-<blockquote><pre>
+<p>They are defined in the build file using <code>&lt;typedef/&gt;</code>. For example, a string
+filter that capitalizes words may be declared as:</p>
+<pre>
 package my.customant;
 import org.apache.tools.ant.filters.TokenFilter;
 
@@ -1644,135 +1572,20 @@
         return token.substring(0, 1).toUpperCase() +
                 token.substring(1);
    }
-}
-</pre></blockquote>
+}</pre>
 
-This may be used as follows:
-<blockquote><pre>
-  &lt;typedef name="capitalize" classname="my.customant.Capitalize"
-           classpath="my.customant.path"/&gt;
-  &lt;copy file="input" tofile="output"&gt;
-    &lt;filterchain&gt;
-      &lt;tokenfilter&gt;
-        &lt;stringtokenizer/&gt;
-        &lt;capitalize/&gt;
-      &lt;/tokenfilter&gt;
-    &lt;/filterchain&gt;
-  &lt;/copy&gt;
-</pre></blockquote>
-
-
-<h3><a name="sortfilter">SortFilter</a></h3>
-  <p><em>since Ant 1.8.0</em></p>
-
-<p>The sort filter reads all lines and sorts them.  The sort order can
-  be reversed and it is possible to specify a custom implementation of
-  the <code>java.util.Comparator</code> interface to get even more
-  control.</p>
-
-<table cellSpacing=0 cellPadding=2 border=1>
-  <tr>
-    <td vAlign=top><b>Parameter Name</b></td>
-    <td vAlign=top><b>Parameter Value</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
-  </tr>
-  <tr>
-    <td vAlign=top>reverse</td>
-    <td vAlign=top align="center">whether to reverse the sort order,
-      defaults to false.  <b>Note:</b> this parameter is ignored if
-      the comparator parameter is present as well.</td>
-    <td vAlign=top align="center">No</td>
-  </tr>
-  <tr>
-    <td vAlign=top>comparator</td>
-    <td vAlign=top align="center">Class name of a class that
-      implements <code>java.util.Comparator</code> for Strings.  This
-      class will be used to determine the sort order of lines.</td>
-    <td vAlign=top align="center">No</td>
-  </tr>
-</table>
-
-<p>This filter is also available using the
-  name <code>sortfilter</code>.  The <code>reverse</code> parameter
-  becomes an attribute, <code>comparator</code> can be specified by
-  using a nested element.</p>
-
-<h4>Examples:</h4>
-
-<blockquote><pre>
-  &lt;copy todir=&quot;build&quot;&gt;
-      &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
-      &lt;filterchain&gt;
-          &lt;sortfilter/&gt;
-      &lt;/filterchain&gt;
-  &lt;/copy&gt;
-</pre></blockquote>
-
-<p>
-Sort all files <code>*.txt</code> from <i>src</i> location
-into <i>build</i> location. The lines of each file are sorted in
-ascendant order comparing the lines via the
-<code>String.compareTo(Object o)</code> method.
-</p>
-
-<blockquote><pre>
-  &lt;copy todir=&quot;build&quot;&gt;
-      &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
-      &lt;filterchain&gt;
-          &lt;sortfilter reverse=&quot;true&quot;/&gt;
-      &lt;/filterchain&gt;
-  &lt;/copy&gt;
-</pre></blockquote>
-
-<p>
-Sort all files <code>*.txt</code> from <i>src</i> location into reverse
-order and copy them into <i>build</i> location.
-</p>
-
-<blockquote><pre>
-  &lt;copy todir=&quot;build&quot;&gt;
-      &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
-      &lt;filterchain&gt;
-          &lt;filterreader classname=&quot;org.apache.tools.ant.filters.SortFilter&quot;&gt;
-            &lt;param name=&quot;comparator&quot; value=&quot;org.apache.tools.ant.filters.EvenFirstCmp&quot;/&gt;
-          &lt;/filterreader&gt;
-      &lt;/filterchain&gt;
-  &lt;/copy&gt;
-</pre></blockquote>
-
-<p>
-Sort all files <code>*.txt</code> from <i>src</i> location using as
-sorting criterium <code>EvenFirstCmp</code> class, that sorts the file
-lines putting even lines first then odd lines for example. The modified files
-are copied into <i>build</i> location. The <code>EvenFirstCmp</code>,
-has to an instanciable class via <code>Class.newInstance()</code>,
-therefore in case of inner class has to be <em>static</em>. It also has to
-implement <code>java.util.Comparator</code> interface, for example:
-</p>
-
+<p>This may be used as follows:</p>
 <pre>
-        package org.apache.tools.ant.filters;
-        ...(omitted)
-          public final class EvenFirstCmp implements &lt;b&gt;Comparator&lt;/b&gt; {
-            public int compare(Object o1, Object o2) {
-            ...(omitted)
-            }
-          }
-</pre>
+&lt;typedef name="capitalize" classname="my.customant.Capitalize"
+         classpath="my.customant.path"/&gt;
+&lt;copy file="input" tofile="output"&gt;
+  &lt;filterchain&gt;
+    &lt;tokenfilter&gt;
+      &lt;stringtokenizer/&gt;
+      &lt;capitalize/&gt;
+    &lt;/tokenfilter&gt;
+  &lt;/filterchain&gt;
+&lt;/copy&gt;</pre>
 
-<p>The example above is equivalent to:</p>
-
-<blockquote><pre>
-  &lt;componentdef name="evenfirst"
-                classname="org.apache.tools.ant.filters.EvenFirstCmp&quot;/&gt;
-  &lt;copy todir=&quot;build&quot;&gt;
-      &lt;fileset dir=&quot;input&quot; includes=&quot;*.txt&quot;/&gt;
-      &lt;filterchain&gt;
-          &lt;sortfilter&gt;
-              &lt;evenfirst/&gt;
-          &lt;/sortfilter&gt;
-      &lt;/filterchain&gt;
-  &lt;/copy&gt;
-</pre></blockquote>
-
-</body></html>
+</body>
+</html>
diff --git a/manual/Types/filterset.html b/manual/Types/filterset.html
index 8b0dfe1..ffc37e3 100644
--- a/manual/Types/filterset.html
+++ b/manual/Types/filterset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,156 +15,150 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html>
+<html lang="en">
 <head>
-  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>FilterSet Type</title>
 </head>
 
 <body>
-<h2><a name="filterset">FilterSet</a></h2>
+<h2 id="filterset">FilterSet</h2>
 
-<p>FilterSets are groups of filters. Filters can be defined as token-value
-pairs 
-or be read in from a file. FilterSets can appear inside tasks that support this 
-feature or at the same level as <code>&lt;target&gt;</code> - i.e., as
-children of 
-<code>&lt;project&gt;</code>.</p>
+<p>FilterSets are groups of filters. Filters can be defined as token-value pairs or be read in
+from a file. FilterSets can appear inside tasks that support this feature or at the same level
+as <code>&lt;target&gt;</code>&mdash;i.e., as children of <code>&lt;project&gt;</code>.</p>
 
-<p>FilterSets support the <code>id</code> and <code>refid</code>
-attributes.  You can define a FilterSet with an <code>id</code>
-attribute and then refer to that definition from another FilterSet
-with a <code>refid</code> attribute.  It is also possible to nest
-filtersets into filtersets to get a set union of the contained
-filters.</p>
+<p>FilterSets support the <var>id</var> and <var>refid</var> attributes.  You can define a
+FilterSet with an <var>id</var> attribute and then refer to that definition from another
+FilterSet with a <var>refid</var> attribute.  It is also possible to nest filtersets into
+filtersets to get a set union of the contained filters.</p>
 
-<p>In addition, FilterSets can specify
-<code>begintoken</code> and/or 
-<code>endtoken</code> attributes to define what to match.</p>
-<p>Filtersets are used for doing 
-replacements in tasks such as <code>&lt;copy&gt;</code>, etc.</p>
+<p>In addition, FilterSets can specify <var>begintoken</var> and/or <var>endtoken</var>
+attributes to define what to match.</p>
 
-<p>Filters can also by specified by one or more nested propertysets, the
-  contents of which are applied when the filterset is created.</p>
+<p>Filtersets are used for doing replacements in tasks such as <code>&lt;copy&gt;</code>,
+etc.</p>
 
-<p>If you specify multiple values for the same token, the last one
-  defined within a filterset will be used.</p>
+<p>Filters can also by specified by one or more nested propertysets, the contents of which are
+applied when the filterset is created.</p>
 
-<p>
-<strong>Note: </strong>When a filterset is used in an operation, the files are 
-processed in text mode and the filters applied line by line. This means that
-the copy operations will typically corrupt binary files. When applying filters
-you should ensure that the set of files being filtered are all text files.
-</p>
+<p>If you specify multiple values for the same token, the last one defined within a filterset
+will be used.</p>
 
-<h2>Filterset</h2>
+<p><strong>Note</strong>: When a filterset is used in an operation, the files are processed in
+text mode and the filters applied line by line. This means that the copy operations will
+typically corrupt binary files. When applying filters you should ensure that the set of files
+being filtered are all text files.</p>
 
-<table cellSpacing=0 cellPadding=2 border=1>
+<h3>Filterset</h3>
+
+<table class="attr">
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top><b>Default</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Default</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>begintoken</td>
-    <td vAlign=top>The string marking the beginning of a token (eg.,
-      <code>&#64;DATE&#64;</code>).</td>
-    <td vAlign=top>@</td>
-    <td vAlign=top align="center">No</td>
+    <td>begintoken</td>
+    <td>The string marking the beginning of a token (eg., <samp>@DATE@</samp>).</td>
+    <td><q>@</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>endtoken</td>
-    <td vAlign=top>The string marking the end of a token (eg.,
-      <code>&#64;DATE&#64;</code>).</td>
-    <td vAlign=top>@</td>
-    <td vAlign=top align="center">No</td>
+    <td>endtoken</td>
+    <td>The string marking the end of a token (eg., <samp>@DATE@</samp>).</td>
+    <td><q>@</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>filtersfile</td>
-    <td vAlign=top>Specify a single filtersfile.</td>
-    <td vAlign=top><i>none</i></td>
-    <td vAlign=top align="center">No</td>
+    <td>filtersfile</td>
+    <td>Specify a single filtersfile.</td>
+    <td><em>none</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>recurse</td>
-    <td vAlign=top>Indicates whether the replacement text of tokens
-      should be searched for more tokens. <b>Since Ant 1.6.3</b></td>
-    <td vAlign=top><i>true</i></td>
-    <td vAlign=top align="center">No</td>
+    <td>recurse</td>
+    <td>Indicates whether the replacement text of tokens should be searched for more
+      tokens. <em>Since Ant 1.6.3</em></td>
+    <td><q>true</q></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td vAlign=top>onmissingfiltersfile</td>
-    <td vAlign=top>Indicate behavior when a nonexistent <i>filtersfile</i>
-      is specified.  One of "fail", "warn", "ignore". <b>Since Ant 1.7</b></td>
-    <td vAlign=top>"fail"</td>
-    <td vAlign=top align="center">No</td>
+    <td>onmissingfiltersfile</td>
+    <td>Indicate behavior when a nonexistent <var>filtersfile</var> is specified.  One
+      of <q>fail</q>, <q>warn</q>, <q>ignore</q>. <em>Since Ant 1.7</em></td>
+    <td><q>fail</q></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>filterset</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>filterset</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h2>Filter</h2>
-<table cellSpacing=0 cellPadding=2 border=1>
+<h3>Filter</h3>
+<table>
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>token</td>
-    <td vAlign=top>The token to replace (eg., <code>&#64;DATE&#64;</code>)</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>token</td>
+    <td>The token to replace (eg., <samp>@DATE@</samp>)</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td vAlign=top>value</td>
-    <td vAlign=top>The value to replace it with
-     (eg., <code>Thursday, April 26, 2001</code>).</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>value</td>
+    <td>The value to replace it with (eg., <q>Thursday, April 26, 2001</q>).</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h2>Filtersfile</h2>
-<table cellSpacing=0 cellPadding=2 border=1>
+<h3>Filtersfile</h3>
+<table>
   <tr>
-    <td vAlign=top><b>Attribute</b></td>
-    <td vAlign=top><b>Description</b></td>
-    <td vAlign=top align="center"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td vAlign=top>file</td>
-    <td vAlign=top>A properties file of 
-      name-value pairs from which to load the tokens.</td>
-    <td vAlign=top align="center">Yes</td>
+    <td>file</td>
+    <td>A properties file of name-value pairs from which to load the tokens.</td>
+    <td>Yes</td>
   </tr>
 </table>
 
 <h4>Examples</h4>
 
-<p>You are copying the <code>version.txt</code> file to the <code>dist</code>
-directory from the <code>build</code> directory 
-but wish to replace the token <code>&#64;DATE&#64;</code> with today's date.</p>
-<blockquote><pre>
+<p>You are copying the <samp>version.txt</samp> file to the <samp>dist</samp> directory from
+the <samp>build</samp> directory but wish to replace the token <samp>@DATE@</samp> with today's
+date.</p>
+<pre>
 &lt;copy file=&quot;${build.dir}/version.txt&quot; toFile=&quot;${dist.dir}/version.txt&quot;&gt;
   &lt;filterset&gt;
     &lt;filter token=&quot;DATE&quot; value=&quot;${TODAY}&quot;/&gt;
   &lt;/filterset&gt;
 &lt;/copy&gt;
-</pre></blockquote>
+</pre>
 
-<p>You are copying the <code>version.txt</code> file to the <code>dist</code>
-directory from the build directory 
-but wish to replace the token <code>%DATE*</code> with today's date.</p>
-<blockquote><pre>
+<p>You are copying the <samp>version.txt</samp> file to the <samp>dist</samp> directory from the
+build directory but wish to replace the token <samp>%DATE*</samp> with today's date.</p>
+<pre>
 &lt;copy file=&quot;${build.dir}/version.txt&quot; toFile=&quot;${dist.dir}/version.txt&quot;&gt;
   &lt;filterset begintoken=&quot;%&quot; endtoken=&quot;*&quot;&gt;
     &lt;filter token=&quot;DATE&quot; value=&quot;${TODAY}&quot;/&gt;
   &lt;/filterset&gt;
 &lt;/copy&gt;
-</pre></blockquote>
+</pre>
 
 <p>Copy all the docs but change all dates and appropriate notices as stored in a file.</p>
-<blockquote><pre>
+<pre>
 &lt;copy toDir=&quot;${dist.dir}/docs&quot;&gt;
   &lt;fileset dir=&quot;${build.dir}/docs&quot;&gt;
     &lt;include name=&quot;**/*.html&quot;&gt;
@@ -172,10 +167,10 @@
     &lt;filtersfile file=&quot;${user.dir}/dist.properties&quot;/&gt;
   &lt;/filterset&gt;
 &lt;/copy&gt;
-</pre></blockquote>
+</pre>
 
 <p>Define a FilterSet and reference it later.</p>
-<blockquote><pre>
+<pre>
 &lt;filterset id=&quot;myFilterSet&quot; begintoken=&quot;%&quot; endtoken=&quot;*&quot;&gt;
   &lt;filter token=&quot;DATE&quot; value=&quot;${TODAY}&quot;/&gt;
 &lt;/filterset&gt;
@@ -183,12 +178,12 @@
 &lt;copy file=&quot;${build.dir}/version.txt&quot; toFile=&quot;${dist.dir}/version.txt&quot;&gt;
   &lt;filterset refid=&quot;myFilterSet&quot;/&gt;
 &lt;/copy&gt;
-</pre></blockquote>
+</pre>
 
-<p>You are copying the <code>version.txt</code> file to the <code>dist</code>
-directory from the <code>build</code> directory 
-but wish to replace the token <code>&#64;project.date&#64;</code> with the property of the same name.</p>
-<blockquote><pre>
+<p>You are copying the <samp>version.txt</samp> file to the <samp>dist</samp> directory from
+the <samp>build</samp> directory but wish to replace the token <samp>@project.date@</samp> with
+the property of the same name.</p>
+<pre>
 &lt;copy file=&quot;${build.dir}/version.txt&quot; toFile=&quot;${dist.dir}/version.txt&quot;&gt;
   &lt;filterset&gt;
     &lt;propertyset&gt;
@@ -196,5 +191,6 @@
     &lt;/propertyset&gt;
   &lt;/filterset&gt;
 &lt;/copy&gt;
-</pre></blockquote>
-</body></html>
+</pre>
+</body>
+</html>
diff --git a/manual/Types/mapper.html b/manual/Types/mapper.html
index da3181c..4e8fba5 100644
--- a/manual/Types/mapper.html
+++ b/manual/Types/mapper.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,134 +15,130 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Mapper Type</title>
 </head>
 
 <body>
 
-<h2><a name="mapper">Mapping File Names</a></h2>
-<p>Some tasks take source files and create target files. Depending on
-the task, it may be quite obvious which name a target file will have
-(using <a href="../Tasks/javac.html">javac</a>, you know there will be
-<code>.class</code> files for your <code>.java</code> files) - in
-other cases you may want to specify the target files, either to help
-Apache Ant or to get an extra bit of functionality.</p>
-<p>While source files are usually specified as <a
-href="fileset.html">fileset</a>s, you don't specify target files directly -
-instead, you tell Ant how to find the target file(s) for one source file. An
-instance of <code>org.apache.tools.ant.util.FileNameMapper</code> is
-responsible for this. It constructs target file names based on rules
-that can be parameterized with <code>from</code> and <code>to</code>
-attributes - the exact meaning of which is implementation-dependent.</p>
-<p>These instances are defined in <code>&lt;mapper&gt;</code> elements
-with the following attributes:</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h2 id="mapper">Mapping File Names</h2>
+<p>Some tasks take source files and create target files. Depending on the task, it may be quite
+obvious which name a target file will have (using <a href="../Tasks/javac.html">javac</a>, you know
+there will be <samp>.class</samp> files for your <samp>.java</samp> files)&mdash;in other cases you
+may want to specify the target files, either to help Apache Ant or to get an extra bit of
+functionality.</p>
+<p>While source files are usually specified as <a href="fileset.html">fileset</a>s, you don't
+specify target files directly&mdash;instead, you tell Ant how to find the target file(s) for one
+source file. An instance of <code class="code">org.apache.tools.ant.util.FileNameMapper</code> is
+responsible for this. It constructs target file names based on rules that can be parameterized
+with <var>from</var> and <var>to</var> attributes&mdash;the exact meaning of which is
+implementation-dependent.</p>
+<p>These instances are defined in <code>&lt;mapper&gt;</code> elements with the following
+attributes:</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">specifies one of the built-in implementations.</td>
-    <td rowspan="2" align="center" valign="middle">Exactly one of these</td>
+    <td>type</td>
+    <td>specifies one of the built-in implementations.</td>
+    <td rowspan="2">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">classname</td>
-    <td valign="top">specifies the implementation by class name.</td>
+    <td>classname</td>
+    <td class="left">specifies the implementation by class name.</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use when looking up
+    <td>classpath</td>
+    <td>the classpath to use when looking up
       <code>classname</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">the classpath to use, given as <a
-      href="../using.html#references">reference</a> to a path defined elsewhere.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>the classpath to use, given as <a href="../using.html#references">reference</a> to a
+      path defined elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">from</td>
-    <td valign="top">the <code>from</code> attribute for the given
-      implementation.</td>
-    <td align="center" valign="top">Depends on implementation.</td>
+    <td>from</td>
+    <td>the <code>from</code> attribute for the given implementation.</td>
+    <td>Depends on implementation</td>
   </tr>
   <tr>
-    <td valign="top">to</td>
-    <td valign="top">the <code>to</code> attribute for the given
-      implementation.</td>
-    <td align="center" valign="top">Depends on implementation.</td>
+    <td>to</td>
+    <td>the <code>to</code> attribute for the given implementation.</td>
+    <td>Depends on implementation</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>mapper</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>mapper</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
-<p>Note that Ant will not automatically convert / or \ characters in
-the <code>to</code> and <code>from</code> attributes to the correct
-directory separator of your current platform.  If you need to specify
-this separator, use <code>${file.separator}</code> instead.
-  For the regexpmapper, <code>${file.separator}</code> will not work,
-as on windows it is the '\' character, and this is an escape character
-for regular expressions, one should use the <code>handledirsep</code> attribute
-instead.
+<p>Note that Ant will not automatically convert <q>/</q> or <q>\</q> characters in the <var>to</var>
+and <var>from</var> attributes to the correct directory separator of your current platform.  If you
+need to specify this separator, use <code>${file.separator}</code> instead.  For the regexp
+mapper, <code>${file.separator}</code> will not work, as on Windows it is the <q>\</q> character,
+and this is an escape character for regular expressions, one should use
+the <code>handledirsep</code> attribute instead.
 </p>
 <h3>Parameters specified as nested elements</h3>
-<p>The classpath can be specified via a nested
-<code>&lt;classpath&gt;</code>, as well - that is,
-a <a href="../using.html#path">path</a>-like structure.</p>
-<p><b>Since Ant 1.7.0,</b> nested File Mappers can
-be supplied via either <CODE>&lt;mapper&gt;</CODE> elements or
-<a href="../Tasks/typedef.html"><code>&lt;typedef&gt;</code></a>'d
-implementations of <CODE>org.apache.tools.ant.util.FileNameMapper</CODE>.
-If nested File Mappers are specified by either means, the mapper will be
-implicitly configured as a <a href="#composite-mapper">composite mapper</a>.
-</p>
-<hr>
-<h3>The built-in mapper types are:</h3>
+<p>The classpath can be specified via a nested <code>&lt;classpath&gt;</code>, as well&mdash;that
+is, a <a href="../using.html#path">path</a>-like structure.</p>
+<p><em>Since Ant 1.7.0</em>, nested File Mappers can be supplied via
+either <code>&lt;mapper&gt;</code> elements
+or <a href="../Tasks/typedef.html"><code>&lt;typedef&gt;</code></a>'d implementations
+of <code class="code">org.apache.tools.ant.util.FileNameMapper</code>.  If nested File Mappers are
+specified by either means, the mapper will be implicitly configured as
+a <a href="#composite-mapper">composite mapper</a>.</p>
+<h3>The built-in mapper types</h3>
 <p>All built-in mappers are case-sensitive.</p>
-<p><b>As of Ant 1.7.0,</b> each of the built-in mapper implementation
-  types is directly accessible using a specific tagname. This makes it
-  possible for filename mappers to support attributes in addition to
-  the generally available <i>to</i> and <i>from</i>.<br>
-  The <code>&lt;mapper type|classname=&quot;...&quot;&gt;</code> usage
-  form remains valid for reasons of backward compatibility.</p>
+<p><em>Since Ant 1.7.0</em>, each of the built-in mapper implementation types is directly accessible
+using a specific tagname. This makes it possible for filename mappers to support attributes in
+addition to the generally available <var>to</var> and <var>from</var>.<br/>
+The <code>&lt;mapper <var>type</var>|<var>classname</var>=&quot;...&quot;&gt;</code> usage form
+remains valid for reasons of backward compatibility.</p>
 
     <!--                                        -->
     <!--             Identity Mapper            -->
     <!--                                        -->
 
-<h4><a name="identity-mapper">identity</a></h4>
-<p>The target file name is identical to the source file name. Both
-<code>to</code> and <code>from</code> will be ignored.</p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="identity-mapper">identity</h4>
+<p>The target file name is identical to the source file name. Both <var>to</var> and <var>from</var>
+will be ignored.</p>
+<h5>Examples</h5>
+<pre>
 &lt;mapper type=&quot;identity&quot;/&gt;
-&lt;identitymapper/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;identitymapper/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top"><code>A.java</code></td>
+    <td><code>A.java</code></td>
+    <td><code>A.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>foo/bar/B.java</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>foo/bar/B.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top"><code>C.properties</code></td>
+    <td><code>C.properties</code></td>
+    <td><code>C.properties</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
   </tr>
 </table>
 
@@ -149,35 +146,33 @@
     <!--             Flatten Mapper             -->
     <!--                                        -->
 
-<h4><a name="flatten-mapper">flatten</a></h4>
-<p>The target file name is identical to the source file name, with all
-leading directory information stripped off. Both <code>to</code> and
-<code>from</code> will be ignored.</p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="flatten-mapper">flatten</h4>
+<p>The target file name is identical to the source file name, with all leading directory information
+stripped off. Both <var>to</var> and <var>from</var> will be ignored.</p>
+<h5>Examples</h5>
+<pre>
 &lt;mapper type=&quot;flatten&quot;/&gt;
-&lt;flattenmapper/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;flattenmapper/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top"><code>A.java</code></td>
+    <td><code>A.java</code></td>
+    <td><code>A.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>B.java</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>B.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top"><code>C.properties</code></td>
+    <td><code>C.properties</code></td>
+    <td><code>C.properties</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top"><code>A.properties</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>A.properties</code></td>
   </tr>
 </table>
 
@@ -185,34 +180,33 @@
     <!--             Merge Mapper               -->
     <!--                                        -->
 
-<h4><a name="merge-mapper">merge</a></h4>
-<p>The target file name will always be the same, as defined by
-<code>to</code> - <code>from</code> will be ignored.</p>
-<h5>Examples:</h5>
-<blockquote><pre>
+<h4 id="merge-mapper">merge</h4>
+<p>The target file name will always be the same, as defined by <var>to</var>&mdash;<var>from</var>
+will be ignored.</p>
+<h5>Examples</h5>
+<pre>
 &lt;mapper type=&quot;merge&quot; to=&quot;archive.tar&quot;/&gt;
-&lt;mergemapper to=&quot;archive.tar&quot;/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;mergemapper to=&quot;archive.tar&quot;/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top"><code>archive.tar</code></td>
+    <td><code>A.java</code></td>
+    <td><code>archive.tar</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>archive.tar</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>archive.tar</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top"><code>archive.tar</code></td>
+    <td><code>C.properties</code></td>
+    <td><code>archive.tar</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top"><code>archive.tar</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>archive.tar</code></td>
   </tr>
 </table>
 
@@ -220,384 +214,325 @@
     <!--              Glob Mapper               -->
     <!--                                        -->
 
-<h4><a name="glob-mapper">glob</a></h4>
-<p>Both <code>to</code> and <code>from</code> are required and define patterns that may
-contain at most one <code>*</code>. For each source file that matches
-the <code>from</code> pattern, a target file name will be constructed
-from the <code>to</code> pattern by substituting the <code>*</code> in
-the <code>to</code> pattern with the text that matches the
-<code>*</code> in the <code>from</code> pattern. Source file names
-that don't match the <code>from</code> pattern will be ignored.</p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="glob-mapper">glob</h4>
+<p>Both <var>to</var> and <var>from</var> are required and define patterns that may contain at most
+one <q>*</q>. For each source file that matches the <var>from</var> pattern, a target file name will
+be constructed from the <var>to</var> pattern by substituting the <q>*</q> in the <var>to</var>
+pattern with the text that matches the <q>*</q> in the <var>from</var> pattern. Source file names
+that don't match the <var>from</var> pattern will be ignored.</p>
+<h5>Examples</h5>
+<pre>
 &lt;mapper type=&quot;glob&quot; from=&quot;*.java&quot; to=&quot;*.java.bak&quot;/&gt;
-&lt;globmapper from=&quot;*.java&quot; to=&quot;*.java.bak&quot;/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;globmapper from=&quot;*.java&quot; to=&quot;*.java.bak&quot;/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top"><code>A.java.bak</code></td>
+    <td><code>A.java</code></td>
+    <td><code>A.java.bak</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>foo/bar/B.java.bak</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>foo/bar/B.java.bak</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top">ignored</td>
+    <td><code>C.properties</code></td>
+    <td>ignored</td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top">ignored</td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td>ignored</td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;mapper type=&quot;glob&quot; from=&quot;C*ies&quot; to=&quot;Q*y&quot;/&gt;
-&lt;globmapper from=&quot;C*ies&quot; to=&quot;Q*y&quot;/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;globmapper from=&quot;C*ies&quot; to=&quot;Q*y&quot;/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top">ignored</td>
+    <td><code>A.java</code></td>
+    <td>ignored</td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top">ignored</td>
+    <td><code>foo/bar/B.java</code></td>
+    <td>ignored</td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top"><code>Q.property</code></td>
+    <td><code>C.properties</code></td>
+    <td><code>Q.property</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top"><code>Qlasses/dir/dir2/A.property</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>Qlasses/dir/dir2/A.property</code></td>
   </tr>
 </table>
-  <p>
-    The globmapper mapper can take the following extra attributes.
-  </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">casesensitive</td>
-      <td valign="top">
-        If this is false, the mapper will ignore case when matching the glob pattern.
-        This attribute can be true or false, the default is true.
-      <em>Since Ant 1.6.3.</em>
-      </td>
-      <td align="center" valign="top">No</td>
-    </tr>
-    <tr>
-      <td valign="top">handledirsep</td>
-      <td valign="top">
-        If this is specified, the mapper will ignore the difference between the normal
-        directory separator characters - \ and /.
-        This attribute can be true or false, the default is false.
-        This attribute is useful for cross-platform build files.
-        <em>Since Ant 1.6.3.</em>
-        <td align="center" valign="top">No</td>
-      </tr>
-    </table>
-    <p>
-      An example:
-    </p>
-    <pre>
-      &lt;pathconvert property="x" targetos="unix"&gt;
-        &lt;path path="Aj.Java"/&gt;
-        &lt;mapper&gt;
-        &lt;chainedmapper&gt;
-          &lt;flattenmapper/&gt;
-          &lt;globmapper from="a*.java" to="*.java.bak" casesensitive="no"/&gt;
-        &lt;/chainedmapper&gt;
-        &lt;/mapper&gt;
-      &lt;/pathconvert&gt;
-      &lt;echo&gt;x is ${x}&lt;/echo&gt;
-    </pre>
-    <p>
-      will output "x is j.java.bak".
-    </p>
-    <p>
-      and
-    </p>
-    <pre>
-      &lt;pathconvert property="x" targetos="unix"&gt;
-        &lt;path path="d/e/f/j.java"/&gt;
-        &lt;mapper&gt;
-          &lt;globmapper from="${basedir}\d/e\*" to="*" handledirsep="yes"/&gt;
-        &lt;/mapper&gt;
-      &lt;/pathconvert&gt;
-      &lt;echo&gt;x is ${x}&lt;/echo&gt;
-    </pre>
-    <p>
-      will output "x is f/j.java".
-    </p>
-
+<p>The <code>globmapper</code> mapper can take the following extra attributes.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>casesensitive</td>
+    <td>
+      This attribute can be <q>true</q> or <q>false</q>.  If this is <q>false</q>, the mapper will
+      ignore case when matching the glob pattern.  <em>Since Ant 1.6.3</em>
+    </td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>handledirsep</td>
+    <td>
+      This attribute can be <q>true</q> or <q>false</q>.  If this is specified, the mapper will
+      ignore the difference between the normal directory separator characters&mdash;<q>\</q>
+      and <q>/</q>.  This attribute is useful for cross-platform build files.  <em>Since Ant
+      1.6.3</em>
+    <td>No; default is <q>false</q></td>
+  </tr>
+</table>
+<p>An example:</p>
+<pre>
+&lt;pathconvert property="x" targetos="unix"&gt;
+  &lt;path path="Aj.Java"/&gt;
+  &lt;mapper&gt;
+  &lt;chainedmapper&gt;
+    &lt;flattenmapper/&gt;
+    &lt;globmapper from="a*.java" to="*.java.bak" casesensitive="no"/&gt;
+  &lt;/chainedmapper&gt;
+  &lt;/mapper&gt;
+&lt;/pathconvert&gt;
+&lt;echo&gt;x is ${x}&lt;/echo&gt;</pre>
+<p>will output <code>x is j.java.bak</code>, and</p>
+<pre>
+&lt;pathconvert property="x" targetos="unix"&gt;
+  &lt;path path="d/e/f/j.java"/&gt;
+  &lt;mapper&gt;
+    &lt;globmapper from="${basedir}\d/e\*" to="*" handledirsep="yes"/&gt;
+  &lt;/mapper&gt;
+&lt;/pathconvert&gt;
+&lt;echo&gt;x is ${x}&lt;/echo&gt;</pre>
+<p>will output <code>x is f/j.java</code>.</p>
 
     <!--                                        -->
     <!--             RegExp Mapper              -->
     <!--                                        -->
 
-<h4><a name="regexp-mapper">regexp</a></h4>
+<h4 id="regexp-mapper">regexp</h4>
 
-<p>Both <code>to</code> and <code>from</code> are required and define
-regular expressions. If the source file name (as a whole or in part)
-matches the <code>from</code> pattern, the target file name will be
-constructed from the
-<code>to</code> pattern, using <code>\0</code> to <code>\9</code> as
-back-references for the full match (<code>\0</code>) or the matches of
-the subexpressions in parentheses.  The <code>to</code> pattern
-determines the <strong>whole</strong> file name, so if you wanted to
-replace the extension of a file you should not use <code>from="\.old$"
-to=".new"</code> but rather <code>from="(.*)\.old$" to="\1.new"</code>
-(or rather use a glob mapper in this case).</p>
+<p>Both <var>to</var> and <var>from</var> are required and define regular expressions. If the source
+file name (as a whole or in part) matches the <var>from</var> pattern, the target file name will be
+constructed from the <var>to</var> pattern, using <code>\0</code> to <code>\9</code> as
+back-references for the full match (<code>\0</code>) or the matches of the subexpressions in
+parentheses.  The <var>to</var> pattern determines the <strong>whole</strong> file name, so if you
+wanted to replace the extension of a file you should not use <code>from="\.old$" to=".new"</code>
+but rather <code>from="(.*)\.old$" to="\1.new"</code> (or rather use a glob mapper in this
+case).</p>
 
-<p>Source files not matching the <code>from</code> pattern will be
-ignored.</p>
+<p>Source files not matching the <var>from</var> pattern will be ignored.</p>
 
-<p>Note that you need to escape a dollar-sign (<code>$</code>) with
-another dollar-sign in Ant.</p>
+<p>Note that you need to escape a dollar-sign (<q>$</q>) with another dollar-sign in Ant.</p>
 
-<p>The regexp mapper needs a supporting library and an implementation
-of <code>org.apache.tools.ant.util.regexp.RegexpMatcher</code> that
-  hides the specifics of the library.  <em>Since Ant 1.8.0</em> Ant
-  requires Java 1.4 to run, so the implementation based on
-  the <code>java.util.regex</code> package will always be available.
-  You can still use the now retired Jakarta ORO or Jakarta Regex instead if your
-  provide the corresponding jar in your CLASSPATH.</p>
-
-<p>For information about using <a
-href="http://www.cacas.org/~wes/java/" target="_top">gnu.regexp</a> or <a
-href="http://www.crocodile.org/~sts/Rex/" target="_top">gnu.rex</a> with Ant, see <a
-href="http://marc.theaimsgroup.com/?l=ant-dev&m=97550753813481&w=2" target="_top">this</a>
-article.</p>
+<p>For information about using <a href="https://savannah.gnu.org/projects/gnu-regexp/"
+target="_top">gnu.regexp</a> or <a href="https://github.com/kzn/regex4j/" target="_top">gnu.rex</a>
+with Ant, see <a href="https://marc.info/?l=ant-dev&m=97550753813481&w=2" target="_top">this</a>
+article. Please keep in mind that <a href="http://tusker.org/regex/regex_benchmark.html"
+target="_top">your mileage may vary</a> with different regexp engines.</p>
 
 <p>If you want to use one of the <a href="../install.html#librarydependencies">regular expression
-  libraries</a> other than <code>java.util.regex</code> you need to also use
-  the corresponding <code>ant-[apache-oro, apache-regexp].jar</code>
-from the Ant release you are using.
-Make sure, both will be loaded from the same
-classpath, that is either put them into your <code>CLASSPATH</code>,
-<code>ANT_HOME/lib</code> directory or a nested
-<code>&lt;classpath&gt;</code> element of the mapper - you cannot have
-<code>ant-[apache-oro, apache-regexp].jar</code> in <code>ANT_HOME/lib</code>
- and the library
+libraries</a> other than <code>java.util.regex</code> you need to also use the
+corresponding <samp>ant-[apache-oro, apache-regexp].jar</samp> from the Ant release you are using.
+Make sure that both will be loaded from the same classpath, that is either put them into
+your <code>CLASSPATH</code>, <samp>ANT_HOME/lib</samp> directory or a
+nested <code>&lt;classpath&gt;</code> element of the mapper&mdash;you cannot
+have <samp>ant-[apache-oro, apache-regexp].jar</samp> in <samp>ANT_HOME/lib</samp> and the library
 in a nested <code>&lt;classpath&gt;</code>.</p>
-<p>Ant will choose the regular-expression library based on the
-following algorithm:</p>
+<p>Ant will choose the regular expression library based on the following algorithm:</p>
 <ul>
-<li>If the system property
-<code>ant.regexp.matcherimpl</code> has been set, it is taken as the
-name of the class implementing
-<code>org.apache.tools.ant.util.regexp.RegexpMatcher</code> that
-should be used.</li>
-<li>If it has not been set, uses the JDK 1.4 classes.</li>
+<li>If the system property <code>ant.regexp.matcherimpl</code> has been set, it is taken as the name
+of the class implementing <code class="code">org.apache.tools.ant.util.regexp.RegexpMatcher</code>
+that should be used.</li>
+<li>If it has not been set, uses the default from the <code>java.util.regex</code> package.</li>
 </ul>
 
-<b>Examples:</b>
-<blockquote><pre>
+<h5>Examples</h5>
+<pre>
 &lt;mapper type=&quot;regexp&quot; from=&quot;^(.*)\.java$$&quot; to=&quot;\1.java.bak&quot;/&gt;
-&lt;regexpmapper from=&quot;^(.*)\.java$$&quot; to=&quot;\1.java.bak&quot;/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;regexpmapper from=&quot;^(.*)\.java$$&quot; to=&quot;\1.java.bak&quot;/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top"><code>A.java.bak</code></td>
+    <td><code>A.java</code></td>
+    <td><code>A.java.bak</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>foo/bar/B.java.bak</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>foo/bar/B.java.bak</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top">ignored</td>
+    <td><code>C.properties</code></td>
+    <td>ignored</td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top">ignored</td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td>ignored</td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;mapper type=&quot;regexp&quot; from=&quot;^(.*)/([^/]+)/([^/]*)$$&quot; to=&quot;\1/\2/\2-\3&quot;/&gt;
-&lt;regexpmapper from=&quot;^(.*)/([^/]+)/([^/]*)$$&quot; to=&quot;\1/\2/\2-\3&quot;/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;regexpmapper from=&quot;^(.*)/([^/]+)/([^/]*)$$&quot; to=&quot;\1/\2/\2-\3&quot;/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top">ignored</td>
+    <td><code>A.java</code></td>
+    <td>ignored</td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>foo/bar/bar-B.java</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>foo/bar/bar-B.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top">ignored</td>
+    <td><code>C.properties</code></td>
+    <td>ignored</td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top"><code>Classes/dir/dir2/dir2-A.properties</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>Classes/dir/dir2/dir2-A.properties</code></td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;mapper type="regexp" from="^(.*)\.(.*)$$" to="\2.\1"/&gt;
-&lt;regexpmapper from="^(.*)\.(.*)$$" to="\2.\1"/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;regexpmapper from="^(.*)\.(.*)$$" to="\2.\1"/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>A.java</code></td>
-    <td valign="top"><code>java.A</code></td>
+    <td><code>A.java</code></td>
+    <td><code>java.A</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo/bar/B.java</code></td>
-    <td valign="top"><code>java.foo/bar/B</code></td>
+    <td><code>foo/bar/B.java</code></td>
+    <td><code>java.foo/bar/B</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>C.properties</code></td>
-    <td valign="top"><code>properties.C</code></td>
+    <td><code>C.properties</code></td>
+    <td><code>properties.C</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>Classes/dir/dir2/A.properties</code></td>
-    <td valign="top"><code>properties.Classes/dir/dir2/A</code></td>
+    <td><code>Classes/dir/dir2/A.properties</code></td>
+    <td><code>properties.Classes/dir/dir2/A</code></td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;mapper type="regexp" from="^(.*?)(\$$[^/\\\.]*)?\.class$$" to="\1.java"/&gt;
-&lt;regexpmapper from="^(.*?)(\$$[^/\\\.]*)?\.class$$" to="\1.java"/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;regexpmapper from="^(.*?)(\$$[^/\\\.]*)?\.class$$" to="\1.java"/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>ClassLoader.class</code></td>
-    <td valign="top"><code>ClassLoader.java</code></td>
+    <td><code>ClassLoader.class</code></td>
+    <td><code>ClassLoader.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>java/lang/ClassLoader.class</code></td>
-    <td valign="top"><code>java/lang/ClassLoader.java</code></td>
+    <td><code>java/lang/ClassLoader.class</code></td>
+    <td><code>java/lang/ClassLoader.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>java\lang\ClassLoader$1.class</code></td>
-    <td valign="top"><code>java\lang\ClassLoader.java</code></td>
+    <td><code>java\lang\ClassLoader$1.class</code></td>
+    <td><code>java\lang\ClassLoader.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>java/lang/ClassLoader$foo$1.class</code></td>
-    <td valign="top"><code>java/lang/ClassLoader.java</code></td>
+    <td><code>java/lang/ClassLoader$foo$1.class</code></td>
+    <td><code>java/lang/ClassLoader.java</code></td>
   </tr>
 </table>
-  <p>
-    The regexpmapper mapper can take the following extra attributes.
-  </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">casesensitive</td>
-      <td valign="top">
-        If this is false, the mapper will ignore case when matching the pattern.
-        This attribute can be true or false, the default is true.
-      <em>Since Ant 1.6.3.</em>
-      </td>
-      <td align="center" valign="top">No</td>
-    </tr>
-    <tr>
-      <td valign="top">handledirsep</td>
-      <td valign="top">
-        If this is specified, the mapper will treat a \ character in a filename
-        as a / for the purposes of matching.
-        This attribute can be true or false, the default is false.
-        This attribute is useful for cross-platform build files.
-        <em>Since Ant 1.6.3.</em>
-        <td align="center" valign="top">No</td>
-      </tr>
-    </table>
-    <p>
-      An example:
-    </p>
-    <pre>
-      &lt;pathconvert property="x" targetos="unix"&gt;
-        &lt;path path="Aj.Java"/&gt;
-        &lt;chainedmapper&gt;
-          &lt;flattenmapper/&gt;
-          &lt;regexpmapper from="a(.*)\.java" to="\1.java.bak" casesensitive="no"/&gt;
-        &lt;/chainedmapper&gt;
-      &lt;/pathconvert&gt;
-      &lt;echo&gt;x is ${x}&lt;/echo&gt;
-    </pre>
-    <p>
-      will output "x is j.java.bak".
-    </p>
-    <p>
-      and
-    </p>
-    <pre>
-    &lt;pathconvert property="hd.prop" targetos="windows"&gt;
-      &lt;path path="d\e/f\j.java"/&gt;
-      &lt;chainedmapper&gt;
-        &lt;regexpmapper from="${basedir}/d/e/(.*)" to="\1" handledirsep="yes"/&gt;
-      &lt;/chainedmapper&gt;
-    &lt;/pathconvert&gt;
-    </pre>
-    <p>
-      will set <code>hd.prop</code> to "f\j.java".
-    </p>
+<p>The regexp mapper can take the following extra attributes.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>casesensitive</td>
+    <td>
+      This attribute can be <q>true</q> or <q>false</q>.  If this is <q>false</q>, the mapper will
+      ignore case when matching the pattern.
+      <em>Since Ant 1.6.3</em>
+    </td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>handledirsep</td>
+    <td>
+      This attribute can be <q>true</q> or <q>false</q>.  If this is specified, the mapper will
+      treat a <q>\</q> character in a filename as a <q>/</q> for the purposes of matching.  This
+      attribute is useful for cross-platform build files.
+      <em>Since Ant 1.6.3</em>
+    <td>No; default is <q>false</q></td>
+  </tr>
+</table>
+<p>An example:</p>
+<pre>
+&lt;pathconvert property="x" targetos="unix"&gt;
+  &lt;path path="Aj.Java"/&gt;
+  &lt;chainedmapper&gt;
+    &lt;flattenmapper/&gt;
+    &lt;regexpmapper from="a(.*)\.java" to="\1.java.bak" casesensitive="no"/&gt;
+  &lt;/chainedmapper&gt;
+&lt;/pathconvert&gt;
+&lt;echo&gt;x is ${x}&lt;/echo&gt;</pre>
+<p>will output <code>x is j.java.bak</code>, and</p>
+<pre>
+&lt;pathconvert property="hd.prop" targetos="windows"&gt;
+  &lt;path path="d\e/f\j.java"/&gt;
+  &lt;chainedmapper&gt;
+    &lt;regexpmapper from="${basedir}/d/e/(.*)" to="\1" handledirsep="yes"/&gt;
+  &lt;/chainedmapper&gt;
+&lt;/pathconvert&gt;</pre>
+<p>will set <code>hd.prop</code> to <code>f\j.java</code>.</p>
 
     <!--                                        -->
     <!--             Package Mapper             -->
     <!--                                        -->
 
-<h4><a name="package-mapper">package</a></h4>
-<p>Sharing the same syntax as the <a href="#glob-mapper">glob mapper</a>,
-the package mapper replaces
-directory separators found in the matched source pattern with dots in the target
-pattern placeholder. This mapper is particularly useful in combination
-with <code>&lt;uptodate&gt;</code> and <code>&lt;junit&gt;</code> output.</p>
-<p>The to and from attributes are both required.</p>
-<b>Example:</b>
-<blockquote><pre>
+<h4 id="package-mapper">package</h4>
+<p>Sharing the same syntax as the <a href="#glob-mapper">glob mapper</a>, the package mapper
+replaces directory separators found in the matched source pattern with dots in the target pattern
+placeholder. This mapper is particularly useful in combination with <code>&lt;uptodate&gt;</code>
+and <code>&lt;junit&gt;</code> output.</p>
+<p>The <var>to</var> and <var>from</var> attributes are both required.</p>
+<h5>Example</h5>
+<pre>
 &lt;mapper type="package" from="*Test.java" to="TEST-*Test.xml"/&gt;
-&lt;packagemapper from="*Test.java" to="TEST-*Test.xml"/&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;packagemapper from="*Test.java" to="TEST-*Test.xml"/&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>org/apache/tools/ant/util/PackageMapperTest.java</code></td>
-    <td valign="top"><code>TEST-org.apache.tools.ant.util.PackageMapperTest.xml</code></td>
+    <td><code>org/apache/tools/ant/util/PackageMapperTest.java</code></td>
+    <td><code>TEST-org.apache.tools.ant.util.PackageMapperTest.xml</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>org/apache/tools/ant/util/Helper.java</code></td>
-    <td valign="top">ignored</td>
+    <td><code>org/apache/tools/ant/util/Helper.java</code></td>
+    <td>ignored</td>
   </tr>
 </table>
 
@@ -605,27 +540,25 @@
     <!--           Unpackage Mapper             -->
     <!--                                        -->
 
-<h4><a name="unpackage-mapper">unpackage (since Ant 1.6.0)</a></h4>
-  <p>This mapper is the inverse of the <a href="#package-mapper">package</a> mapper.
-    It replaces the dots in a package name with directory separators. This
-    is useful for matching XML formatter results against their JUnit test
-    test cases. The mapper shares the sample syntax
-    as the <a href="#glob-mapper">glob mapper</a>.
-  </p>
-<p>The to and from attributes are both required.</p>
-<b>Example:</b>
-<blockquote><pre>
+<h4 id="unpackage-mapper">unpackage</h4>
+<p><em>Since Ant 1.6.0</em></p>
+<p>This mapper is the inverse of the <a href="#package-mapper">package</a> mapper.  It replaces the
+dots in a package name with directory separators. This is useful for matching XML formatter results
+against their JUnit test test cases. The mapper shares the sample syntax as
+the <a href="#glob-mapper">glob mapper</a>.</p>
+<p>The <var>to</var> and <var>from</var> attributes are both required.</p>
+<h5>Example</h5>
+<pre>
 &lt;mapper type="unpackage" from="TEST-*Test.xml" to="${test.src.dir}/*Test.java"&gt;
-&lt;unpackagemapper from="TEST-*Test.xml" to="${test.src.dir}/*Test.java"&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;unpackagemapper from="TEST-*Test.xml" to="${test.src.dir}/*Test.java"&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file name</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file name</th>
   </tr>
   <tr>
-    <td valign="top"><code>TEST-org.acme.AcmeTest.xml</code></td>
-    <td valign="top"><code>${test.src.dir}/org/acme/AcmeTest.java</code></td>
+    <td><code>TEST-org.acme.AcmeTest.xml</code></td>
+    <td><code>${test.src.dir}/org/acme/AcmeTest.java</code></td>
   </tr>
 </table>
 
@@ -633,50 +566,47 @@
     <!--           Composite Mapper             -->
     <!--                                        -->
 
-<h4><a name="composite-mapper">composite (since Ant 1.7.0)</a></h4>
-  <p>This mapper implementation can contain multiple nested mappers.
-    File mapping is performed by passing the source filename to each nested
-    <code>&lt;mapper&gt;</code> in turn, returning all results.
-    The <i>to</i> and <i>from</i> attributes are ignored.</p>
-  <p>Starting with Ant 1.8.0 the order of the mapped results is the
-    same as the order of the nested mappers; prior to Ant 1.8.0 the
-    order has been undefined.</p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="composite-mapper">composite</h4>
+<p><em>Since Ant 1.7.0</em></p>
+<p>This mapper implementation can contain multiple nested mappers.  File mapping is performed by
+passing the source filename to each nested <code>&lt;mapper&gt;</code> in turn, returning all
+results.  The <var>to</var> and <var>from</var> attributes are ignored.</p>
+<p><em>Since Ant 1.8.0</em>, the order of the mapped results is the same as the order of the nested
+mappers; prior to Ant 1.8.0 the order has been undefined.</p>
+<h5>Examples</h5>
+<pre>
 &lt;compositemapper&gt;
   &lt;identitymapper/&gt;
   &lt;packagemapper from="*.java" to="*"/&gt;
-&lt;/compositemapper&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;/compositemapper&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center" rowspan="2"><code>foo/bar/A.java</code></td>
-    <td valign="top"><code>foo/bar/A.java</code></td>
+    <td rowspan="2"><code>foo/bar/A.java</code></td>
+    <td><code>foo/bar/A.java</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo.bar.A</code></td>
+    <td><code>foo.bar.A</code></td>
   </tr>
 </table>
-  <p>The composite mapper has no corresponding
-    <code>&lt;mapper <b>type</b>&gt;</code> attribute.
-  </p>
+<p>The composite mapper has no corresponding <code>&lt;mapper&gt;</code> <var>type</var>
+attribute.</p>
 
     <!--                                        -->
     <!--            Chained Mapper              -->
     <!--                                        -->
 
-<h4><a name="chained-mapper">chained (since Ant 1.7.0)</a></h4>
-  <p>This mapper implementation can contain multiple nested mappers.
-    File mapping is performed by passing the source filename to the first
-    nested mapper, its results to the second, and so on.  The target filenames
-    generated by the last nested mapper comprise the ultimate results of the
-    mapping operation.  The <i>to</i> and <i>from</i> attributes are ignored.</p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="chained-mapper">chained</h4>
+<p><em>Since Ant 1.7.0</em></p>
+<p>This mapper implementation can contain multiple nested mappers.  File mapping is performed by
+passing the source filename to the first nested mapper, its results to the second, and so on.  The
+target filenames generated by the last nested mapper comprise the ultimate results of the mapping
+operation.  The <var>to</var> and <var>from</var> attributes are ignored.</p>
+<h5>Examples</h5>
+<pre>
 &lt;chainedmapper&gt;
   &lt;flattenmapper/&gt;
   &lt;globmapper from="*" to="new/path/*"/&gt;
@@ -684,289 +614,248 @@
     &lt;globmapper from="*" to="*1"/&gt;
     &lt;globmapper from="*" to="*2"/&gt;
   &lt;/mapper&gt;
-&lt;/chainedmapper&gt;
-</pre></blockquote>
-<table border="1" cellpadding="2" cellspacing="0">
+&lt;/chainedmapper&gt;</pre>
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center" rowspan="2"><code>foo/bar/A.java</code></td>
-    <td valign="top"><code>new/path/A.java1</code></td>
+    <td rowspan="2"><code>foo/bar/A.java</code></td>
+    <td><code>new/path/A.java1</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>new/path/A.java2</code></td>
+    <td><code>new/path/A.java2</code></td>
   </tr>
   <tr>
-    <td valign="center" rowspan="2"><code>boo/far/B.java</code></td>
-    <td valign="top"><code>new/path/B.java1</code></td>
+    <td rowspan="2"><code>boo/far/B.java</code></td>
+    <td><code>new/path/B.java1</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>new/path/B.java2</code></td>
+    <td><code>new/path/B.java2</code></td>
   </tr>
 </table>
-  <p>The chained mapper has no corresponding
-    <code>&lt;mapper <b>type</b>&gt;</code> attribute.
-  </p>
+<p>The chained mapper has no corresponding <code>&lt;mapper&gt;</code> <var>type</var>
+attribute.</p>
 
     <!--                                        -->
     <!--             Filter Mapper              -->
     <!--                                        -->
 
-<h4><a name="filter-mapper">filtermapper (since Ant 1.6.3)</a></h4>
-    <p>
-      This mapper implementation applies a <a href="filterchain.html">filterchain</a>
-      to the source file name.
-    </p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="filter-mapper">filtermapper</h4>
+<p><em>Since Ant 1.6.3</em></p>
+<p>This mapper implementation applies a <a href="filterchain.html">filterchain</a> to the source
+file name.</p>
+<h5>Examples</h5>
+<pre>
 &lt;filtermapper&gt;
   &lt;replacestring from="\" to="/"/&gt;
-&lt;/filtermapper&gt;
-</pre></blockquote>
+&lt;/filtermapper&gt;</pre>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center"><code>foo\bar\A.java</code></td>
-    <td valign="top"><code>foo/bar/A.java</code></td>
+    <td><code>foo\bar\A.java</code></td>
+    <td><code>foo/bar/A.java</code></td>
   </tr>
 </table>
-<blockquote><pre>
+<pre>
 &lt;filtermapper&gt;
   &lt;scriptfilter language="beanshell"&gt;
     self.setToken(self.getToken().toUpperCase());
   &lt;/scriptfilter&gt;
-&lt;/filtermapper&gt;
-</pre></blockquote>
+&lt;/filtermapper&gt;</pre>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center"><code>foo\bar\A.java</code></td>
-    <td valign="top"><code>FOO\BAR\A.JAVA</code></td>
+    <td><code>foo\bar\A.java</code></td>
+    <td><code>FOO\BAR\A.JAVA</code></td>
   </tr>
 </table>
 
-  <p>The filtermapper has no corresponding
-    <code>&lt;mapper <b>type</b>&gt;</code> attribute.
-  </p>
+<p>The filtermapper has no corresponding <code>&lt;mapper&gt;</code> <var>type</var> attribute.</p>
 
     <!--                                        -->
     <!--             Script Mapper              -->
     <!--                                        -->
 
-<h4><a name="script-mapper">scriptmapper (since Ant 1.7)</a></h4>
-<p>
-This mapper executes a script written in <a href="http://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
-or
-  <a href="https://scripting.dev.java.net">JSR 223</a>
-supported language, once per file to map.</p>
-The script can be declared inline or in a specified file.
-</p>
-<p>
-See the <a href="../Tasks/script.html">Script</a> task for
-an explanation of scripts and dependencies.
-</p>
+<h4 id="script-mapper">scriptmapper</h4>
+<p><em>Since Ant 1.7</em></p>
+<p>This mapper executes a script written in <a href="https://jakarta.apache.org/bsf"
+target="_top">Apache BSF</a>
+or <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr223/223ChangeLog.html"
+target="_top">JSR 223</a> supported language, once per file to map.</p>
+<p>The script can be declared inline or in a specified file.</p>
+<p>See the <a href="../Tasks/script.html">Script</a> task for an explanation of scripts and
+dependencies.</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">language</td>
-      <td valign="top">
-        Scripting language
-      </td>
-      <td align="center" valign="top">Yes</td>
-    </tr>
-    <tr>
-      <td valign="top">manager</td>
-      <td valign="top">
-        The script engine manager to use.
-        See the <a href="../Tasks/script.html">script</a> task
-        for using this attribute.
-      </td>
-      <td valign="top" align="center">No - default is "auto"</td>
-    </tr>
-    <tr>
-      <td valign="top">src</td>
-      <td valign="top">
-        File containing the script
-      </td>
-      <td align="center" valign="top">No</td>
-    </tr>
-    <tr>
-      <td valign="top">setbeans</td>
-      <td valign="top">whether to have all properties, references and targets as
-        global variables in the script.  <em>since Ant 1.8.0</em></td>
-      <td valign="top" align="center">No, default is "true".</td>
-    </tr>
-    <tr>
-      <td valign="top">classpath</td>
-      <td valign="top">
-        The classpath to pass into the script.
-      </td>
-      <td align="center" valign="top">No</td>
-    </tr>
-    <tr>
-      <td valign="top">classpathref</td>
-      <td valign="top">The classpath to use, given as a
-        <a href="../using.html#references">reference</a> to a path defined elsewhere.
-        <td align="center" valign="top">No</td>
-      </tr>
-    </table>
-  <p>
-    This filename mapper can take a nested &lt;classpath&gt; element.
-    See the <a href="../Tasks/script.html">script</a> task
-    on how to use this element.
-  </p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>language</td>
+    <td>Scripting language</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>manager</td>
+    <td>The script engine manager to use. See the <a href="../Tasks/script.html">script</a> task
+      for using this attribute.</td>
+    <td>No; default is <q>auto</q></td>
+  </tr>
+  <tr>
+    <td>src</td>
+    <td>File containing the script</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>encoding</td>
+    <td>The encoding of the script as a file. <em>Since Ant 1.10.2</em></td>
+    <td>No; defaults to default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>setbeans</td>
+    <td>whether to have all properties, references and targets as global variables in the
+      script.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>classpath</td>
+    <td>The classpath to pass into the script.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>classpathref</td>
+    <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to a
+      path defined elsewhere.
+    <td>No</td>
+  </tr>
+</table>
+<p>This filename mapper can take a nested <code>&lt;classpath&gt;</code> element.  See
+the <a href="../Tasks/script.html">script</a> task on how to use this element.</p>
 
-<p>
-  <b>Example:</b>
-</p>
-<blockquote><pre>
+<h5>Example</h5>
+<pre>
 &lt;scriptmapper language="javascript"&gt;
   self.addMappedName(source.toUpperCase());
   self.addMappedName(source.toLowerCase());
-&lt;/scriptmapper&gt;
-</pre></blockquote>
+&lt;/scriptmapper&gt;</pre>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center" rowspan="2"><code>foo\bar\A.java</code></td>
-    <td valign="top"><code>FOO\BAR\A.JAVA</code></td>
+    <td rowspan="2"><code>foo\bar\A.java</code></td>
+    <td><code>FOO\BAR\A.JAVA</code></td>
   </tr>
   <tr>
-    <td valign="top"><code>foo\bar\a.java</code></td>
+    <td><code>foo\bar\a.java</code></td>
   </tr>
 </table>
 
-<p>
-To use this mapper, the scripts need access to the source file,
-and the ability to return multiple mappings. Here are the relevant beans and
-their methods. The script is called once for every source file, with the
-list of mapped names reset after every invocation.
+<p>To use this mapper, the scripts need access to the source file, and the ability to return
+multiple mappings. Here are the relevant beans and their methods. The script is called once for
+every source file, with the list of mapped names reset after every invocation.</p>
 
-  <table border="1" cellpadding="2" cellspacing="0">
-    <tr>
-      <td valign="top"><b>Script bean</b></td>
-      <td valign="top"><b>Description</b></td>
-    </tr>
-    <tr>
-      <td valign="top"><code>source: String</code></td>
-      <td valign="top">
-        The file/path to map
-      </td>
-    </tr>
-    <tr>
-      <td valign="top"><code>self</code></td>
-      <td valign="top">
-        the scriptmapper itself
-      </td>
-    </tr>
-    <tr>
-      <td valign="top"><code>self.addMappedName(String name)</code></td>
-      <td valign="top">
-        Add a new mapping
-      </td>
-    </tr>
-    <tr>
-      <td valign="top"><code>self.clear()</code></td>
-      <td valign="top">
-        Reset the list of files.
-      </td>
-    </tr>
-    </table>
+<table>
+  <tr>
+    <th scope="col">Script bean</th>
+    <th scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><code>source: String</code></td>
+    <td>The file/path to map</td>
+  </tr>
+  <tr>
+    <td><code>self</code></td>
+    <td>The scriptmapper itself</td>
+  </tr>
+  <tr>
+    <td><code>self.addMappedName(String name)</code></td>
+    <td>Add a new mapping</td>
+  </tr>
+  <tr>
+    <td><code>self.clear()</code></td>
+    <td>Reset the list of files</td>
+  </tr>
+</table>
 
-  <p>The scriptmapper has no corresponding
-    <code>&lt;mapper <b>type</b>&gt;</code> attribute.
-  </p>
+<p>The scriptmapper has no corresponding <code>&lt;mapper&gt;</code> <var>type</var> attribute.</p>
 
-<h4><a name="firstmatch-mapper">firstmatchmapper (since Ant 1.8.0)</a></h4>
-    <p>
-      This mapper supports an arbitrary number of nested mappers and
-      returns the results of the first mapper that matches.  This is
-      different from <a href="#composite-mapper">composite mapper</a>
-      which collects the results of all matching children.</p>
-<b>Examples:</b>
-<blockquote><pre>
+<h4 id="firstmatch-mapper">firstmatchmapper</h4>
+<p><em>Since Ant 1.8.0</em></p>
+<p>This mapper supports an arbitrary number of nested mappers and returns the results of the first
+mapper that matches.  This is different from <a href="#composite-mapper">composite mapper</a> which
+collects the results of all matching children.</p>
+<h5>Examples</h5>
+<pre>
 &lt;firstmatchmapper&gt;
   &lt;globmapper from="*.txt" to="*.bak"/&gt;
   &lt;globmapper from="*A.*" to="*B.*"/&gt;
-&lt;/firstmatchmapper&gt;
-</pre></blockquote>
+&lt;/firstmatchmapper&gt;</pre>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center"><code>foo/bar/A.txt</code></td>
-    <td valign="top"><code>foo/bar/A.bak</code></td>
+    <td><code>foo/bar/A.txt</code></td>
+    <td><code>foo/bar/A.bak</code></td>
   </tr>
   <tr>
-    <td valign="center"><code>foo/bar/A.java</code></td>
-    <td valign="top"><code>foo/bar/B.java</code></td>
+    <td><code>foo/bar/A.java</code></td>
+    <td><code>foo/bar/B.java</code></td>
   </tr>
 </table>
 
-  <p>The firstmatchmapper has no corresponding
-    <code>&lt;mapper <b>type</b>&gt;</code> attribute.
-  </p>
+<p>The firstmatchmapper has no corresponding <code>&lt;mapper&gt;</code> <var>type</var>
+attribute.</p>
 
-<h4><a name="cutdirs-mapper">cutdirsmapper (since Ant 1.8.2)</a></h4>
+<h4 id="cutdirs-mapper">cutdirsmapper</h4>
+<p><em>Since Ant 1.8.2</em></p>
+<p>This mapper strips a configured number of leading directories from the source file name.</p>
 
-<p>This mapper strips a configured number of leading directories from
-  the source file name.</p>
+<h5>Examples</h5>
+<pre>&lt;cutdirsmapper dirs="1"/&gt;</pre>
 
-<b>Examples:</b>
-<blockquote><pre>
-&lt;cutdirsmapper dirs="1"/&gt;
-</pre></blockquote>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td valign="top"><b>Source file name</b></td>
-    <td valign="top"><b>Target file names</b></td>
+    <th scope="col">Source file name</th>
+    <th scope="col">Target file names</th>
   </tr>
   <tr>
-    <td valign="center"><code>foo/bar/A.txt</code></td>
-    <td valign="top"><code>bar/A.txt</code></td>
+    <td><code>foo/bar/A.txt</code></td>
+    <td><code>bar/A.txt</code></td>
   </tr>
 </table>
 
-<p>The cutdirsmapper has no
-corresponding <code>&lt;mapper <b>type</b>&gt;</code> attribute.</p>
+<p>The cutdirsmapper has no corresponding <code>&lt;mapper&gt;</code> <var>type</var> attribute.</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">dirs</td>
-      <td valign="top">
-        Number of directories to strip (must be a positive number).
-      </td>
-      <td align="center" valign="top">Yes</td>
-    </tr>
-  </table>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>dirs</td>
+    <td>Number of directories to strip (must be a positive number).</td>
+    <td>Yes</td>
+  </tr>
+</table>
 
 </body>
 </html>
diff --git a/manual/Types/multirootfileset.html b/manual/Types/multirootfileset.html
index 29a4f54..51c50a4 100644
--- a/manual/Types/multirootfileset.html
+++ b/manual/Types/multirootfileset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,160 +15,137 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>MultiRootFileSet Type</title>
 </head>
 
 <body>
 
-<h2><a name="multirootfileset">MultiRootFileSet</a></h2>
+<h2 id="multirootfileset">MultiRootFileSet</h2>
 
 <p><em>Since Ant 1.9.4</em></p>
 
-<p>A MultiRootFileSet is a group of files or directories. These files
-or directories can be found in a directory forrest starting with a set
-of base directories and are matched by patterns taken from a number of
-<a href="patternset.html">PatternSets</a> and <a
-href="selectors.html">Selectors</a>.</p>
+<p>A MultiRootFileSet is a group of files or directories. These files or directories can be
+found in a directory forrest starting with a set of base directories and are matched by patterns
+taken from a number of <a href="patternset.html">PatternSets</a>
+and <a href="selectors.html">Selectors</a>.</p>
 
-<p>MultiRootFileSet acts as a union of <a
-href="fileset.html">FileSets</a> and <a href="dirset.html">DirSets</a>
-that share the same patterns and selectors.</p>
+<p>MultiRootFileSet acts as a union of <a href="fileset.html">FileSets</a>
+and <a href="dirset.html">DirSets</a> that share the same patterns and selectors.</p>
 
-<p>MultiRootFileSet supports all attributes and nested elements of
-FileSet and DirSet except for the "dir" attribute.</p>
+<p>MultiRootFileSet supports all attributes and nested elements of FileSet and DirSet except for
+the <var>dir</var> attribute.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">basedirs</td>
-    <td valign="top">Comma separated list of directories that build
-    the roots of the MultiRootFileSet.</td>
-    <td valign="top" align="center">No</td>
+    <td>basedirs</td>
+    <td>Comma separated list of directories that build the roots of the MultiRootFileSet.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">cache</td>
-    <td valign="top">Whether to cache results; disabling
-    may seriously impact performance</td>
-    <td valign="top" align="center">No, default <i>true</i></td>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">type</td>
-    <td valign="top">The type of file system entities which will be
-    included in this set.
-    Acceptable values are:
+    <td>type</td>
+    <td>The type of file system entities which will be included in this set.  Acceptable values
+    are:
     <ul>
-      <li>file - regular files</li>
-      <li>dir - directories</li>
-      <li>both - regular files and directories</li>
+      <li><q>file</q>&mdash;regular files</li>
+      <li><q>dir</q>&mdash;directories</li>
+      <li><q>both</q>&mdash;regular files and directories</li>
     </ul>
     </td>
-    <td valign="top" align="center">No, defaults to <i>file</i></td>
+    <td>No; defaults to <q>file</q></td>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">A comma- or space-separated list of patterns of directories that
-     must be included; all directories are included when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>includes</td>
+    <td>A comma- or space-separated list of patterns of directories that must be included.</td>
+    <td>No; defaults to all directories</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">The name of a file; each line of this file is
-      taken to be an include pattern.</td>
-    <td valign="top" align="center">No</td>
+    <td>includesfile</td>
+    <td>Name of a file; each line of this file is taken to be an include pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">A comma- or space-separated list of patterns of directories that
-     must be excluded; no directories are excluded when omitted.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludes</td>
+    <td>A comma- or space-separated list of patterns of directories that must be excluded.</td>
+    <td>No; defaults to none</td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">The name of a file; each line of this file is
-      taken to be an exclude pattern.</td>
-    <td valign="top" align="center">No</td>
+    <td>excludesfile</td>
+    <td>Name of a file; each line of this file is taken to be an exclude pattern.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Specifies whether case-sensitivity should be applied
-     (<code>true</code>|<code>yes</code>|<code>on</code> or
-     <code>false</code>|<code>no</code>|<code>off</code>).</td>
-    <td valign="top" align="center">No; defaults to true.</td>
+    <td>casesensitive</td>
+    <td>Specifies whether case-sensitivity should be applied (<q>true</q>, <q>yes</q>, <q>on</q>
+     or <q>false</q>, <q>no</q>, <q>off</q>).</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">followsymlinks</td>
-    <td valign="top">Shall symbolic links be followed? Defaults to
-      true. See <a href="fileset.html#symlink">fileset's documentation</a>.</td>
-    <td valign="top" align="center">No</td>
+    <td>followsymlinks</td>
+    <td>Shall symbolic links be followed? See <a href="fileset.html#symlink">fileset's
+      documentation</a>.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">erroronmissingdir</td>
-    <td valign="top">
-      Specify what happens if one of the base directories does not exist.
-      If true a build error will happen, if false, the subtree
-      will be ignored/empty.
-      Defaults to true.
-    </td>
-    <td valign="top" align="center">No</td>
+    <td>erroronmissingdir</td>
+    <td>Specify what happens if one of the base directories does not exist.  If <q>true</q> a
+      build error will happen, if <q>false</q>, the subtree will be ignored/empty.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
 </table>
 
 <h3>Parameters specified as nested elements</h3>
 
-<p>PatternSets can be specified as nested
-<code>&lt;patternset&gt;</code> elements. In addition, MultiRootFileSet holds
-an implicit PatternSet and supports the nested
-<code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>,
-<code>&lt;exclude&gt;</code> and <code>&lt;excludesfile&gt;</code>
-elements of <code>&lt;patternset&gt;</code> directly, as well as
-<code>&lt;patternset&gt;</code>'s attributes.</p>
+<p>PatternSets can be specified as nested <code>&lt;patternset&gt;</code> elements. In addition,
+MultiRootFileSet holds an implicit PatternSet and supports the
+nested <code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;excludesfile&gt;</code> elements of <code>&lt;patternset&gt;</code> directly, as
+well as <code>&lt;patternset&gt;</code>'s attributes.</p>
 
-<p>Selectors are available as nested elements within the
-MultiRootFileSet.  If any of the selectors within the MultiRootFileSet
-do not select the file or directory, it is not considered part of the
-MultiRootFileSet. This makes a MultiRootFileSet equivalent to
+<p>Selectors are available as nested elements within the MultiRootFileSet.  If any of the
+selectors within the MultiRootFileSet do not select the file or directory, it is not considered
+part of the MultiRootFileSet. This makes a MultiRootFileSet equivalent to
 an <code>&lt;and&gt;</code> selector container.</p>
 
-<p>In addition basedirs for the MultiRootFileSet can be specified as
-  nested <code>basedir</code> elements that have a
-  single <code>file</code> attribute.</p>
+<p>In addition basedirs for the MultiRootFileSet can be specified as nested <code>basedir</code>
+elements that have a single <var>file</var> attribute.</p>
 
+<h3>Examples</h3>
 
-<h4>Examples</h4>
-
-<blockquote><pre>
+<pre>
 &lt;multirootfileset basedirs=&quot;${build.dir},${other.project.dir}&quot;&gt;
   &lt;include name=&quot;apps/**/classes&quot;/&gt;
   &lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
 &lt;/multirootfileset&gt;
-</pre></blockquote>
-<p>Groups all files inside <code>classes</code> found under the
-<code>apps</code> subdirectory of <code>${build.dir}</code> or
-<code>${other.project.dir}</code>, except those that have the text
-<code>Test</code> in their name.</p>
+</pre>
+<p>Groups all files inside <samp>classes</samp> found under the <samp>apps</samp> subdirectory
+of <samp>${build.dir}</samp> or <samp>${other.project.dir}</samp>, except those that have the
+text <samp>Test</samp> in their name.</p>
 
-<blockquote><pre>
+<pre>
 &lt;multirootfileset&gt;
   &lt;basedir file=&quot;${build.dir}&quot;/&gt;
   &lt;basedir file=&quot;${other.project.dir}&quot;
   &lt;include name=&quot;apps/**/classes&quot;/&gt;
   &lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
 &lt;/multirootfileset&gt;
-</pre></blockquote>
-<p>Is equivalent to the first example but used
-  nested <code>basedir</code> elements.  The nested elements and
-  the <code>basedirs</code> attribute can be used at the same time and
-  the will be merged.</p>
+</pre>
+<p>Is equivalent to the first example but used nested <code>basedir</code> elements.  The nested
+elements and the <var>basedirs</var> attribute can be used at the same time and the will be
+merged.</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/namespace.html b/manual/Types/namespace.html
index 3adfa80..48c5f14 100644
--- a/manual/Types/namespace.html
+++ b/manual/Types/namespace.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,146 +15,142 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html><head><link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>XmlNamespaceSupport</title></head>
+<html lang="en">
+<head>
+  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+  <title>XmlNamespaceSupport</title>
+</head>
   <body>
-    <h2><a name="namespace">XML Namespace Support</a></h2>
-    Apache Ant 1.6 introduces support for XML namespaces. 
+    <h2 id="namespace">XML Namespace Support</h2>
+    Apache Ant 1.6 introduces support for XML namespaces.
     <h3>History</h3>
-    
+
     <p>
-      All releases of Ant prior to Ant 1.6 do not support XML namespaces.
-      No support basically implies two things here:
+      All releases of Ant prior to Ant 1.6 do not support XML namespaces.  No support basically
+      implies two things here:
     </p>
     <ul>
-      <li> Element names correspond to the "qname" of the tags, which is
-        usually the same as the local name. But if the build file writer uses
-        colons in names of defined tasks/types, those become part of the
-        element name. Turning on namespace support gives colon-separated
-        prefixes in tag names a special meaning, and thus build files using
+      <li>Element names correspond to the "qname" of the tags, which is usually the same as the
+        local name. But if the build file writer uses colons in names of defined tasks/types,
+        those become part of the element name. Turning on namespace support gives
+        colon-separated prefixes in tag names a special meaning, and thus build files using
         colons in user-defined tasks and types will break.
       </li>
-      <li> Attributes with the names 'xmlns' and 'xmlns:<code>&lt;prefix&gt;</code>'
-        are not treated specially, which means that custom tasks and types have
-        actually been able to use such attributes as parameter names. Again,
-        such tasks/types are going to break when namespace support is enabled
-        on the parser.
+      <li>Attributes with the names <q>xmlns</q> and <q>xmlns:<em>prefix</em></q> are not
+        treated specially, which means that custom tasks and types have actually been able to
+        use such attributes as parameter names. Again, such tasks/types are going to break when
+        namespace support is enabled on the parser.
       </li>
     </ul>
-    <p>Use of colons in element names has been discouraged in the past,
-      and using any attribute starting with "xml" is actually strongly
-      discouraged by the XML spec to reserve such names for future use.
+    <p>Use of colons in element names has been discouraged in the past, and using any attribute
+      starting with <q>xml</q> is actually strongly discouraged by the XML spec to reserve such
+      names for future use.
     </p>
+
     <h3>Motivation</h3>
+    <p>In build files using a lot of custom and third-party tasks, it is easy to get into name
+      conflicts. When individual types are defined, the build file writer can do some
+      namespacing manually (for example, using <q>tomcat-deploy</q> instead of
+      just <q>deploy</q>). But when defining whole libraries of types using
+      the <code>&lt;typedef&gt;</code> <var>resource</var> attribute, the build file writer has
+      no chance to override or even prefix the names supplied by the library.</p>
 
-    <p>In build files using a lot of custom and third-party tasks, it is
-      easy to get into name conflicts. When individual types are defined, the
-      build file writer can do some namespacing manually (for example, using
-      "tomcat-deploy" instead of just "deploy"). But when defining whole
-      libraries of types using the <code>&lt;typedef&gt;</code> 'resource' attribute, the
-      build file writer has no chance to override or even prefix the names
-      supplied by the library. </p>
     <h3>Assigning Namespaces</h3>
-
     <p>
-      Adding a 'prefix' attribute to <code>&lt;typedef&gt;</code> might have been enough,
-      but XML already has a well-known method for namespacing. Thus, instead
-      of adding a 'prefix' attribute, the <code>&lt;typedef&gt;</code> and <code>&lt;taskdef&gt;</code>
-      tasks get a 'uri' attribute, which stores the URI of the XML namespace
-      with which the type should be associated:
-    </p><pre> &lt;typedef resource="org/example/tasks.properties" uri="<a href="http://example.org/tasks">http://example.org/tasks</a>"/&gt;
- &lt;my:task xmlns:my="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
+      Adding a <var>prefix</var> attribute to <code>&lt;typedef&gt;</code> might have been
+      enough, but XML already has a well-known method for namespacing. Thus, instead of adding
+      a <var>prefix</var> attribute, the <code>&lt;typedef&gt;</code>
+      and <code>&lt;taskdef&gt;</code> tasks get a <var>uri</var> attribute, which stores the
+      URI of the XML namespace with which the type should be associated:
+    </p>
+    <pre>
+&lt;typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/&gt;
+&lt;my:task xmlns:my="http://example.org/tasks"&gt;
     ...
- &lt;/my:task&gt;
-</pre>
-    <p>As the above example demonstrates, the namespace URI needs to be
-      specified at least twice: one time as the value of the 'uri' attribute,
-      and another time to actually map the namespace to occurrences of
-      elements from that namespace, by using the 'xmlns' attribute. This
-      mapping can happen at any level in the build file:
-    </p><pre> &lt;project name="test" xmlns:my="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt; 
-   &lt;typedef resource="org/example/tasks.properties" uri="<a href="http://example.org/tasks">http://example.org/tasks</a>"/&gt;
-   &lt;my:task&gt;
-     ...
-   &lt;/my:task&gt;
- &lt;/project&gt;
-</pre>
+&lt;/my:task&gt;</pre>
+    <p>As the above example demonstrates, the namespace URI needs to be specified at least
+      twice: one time as the value of the <var>uri</var> attribute, and another time to actually
+      map the namespace to occurrences of elements from that namespace, by using
+      the <var>xmlns</var> attribute. This mapping can happen at any level in the build file:
+    </p>
+    <pre>
+&lt;project name="test" xmlns:my="http://example.org/tasks"&gt;
+    &lt;typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/&gt;
+    &lt;my:task&gt;
+        ...
+    &lt;/my:task&gt;
+&lt;/project&gt;</pre>
     <p>
-      Use of a namespace prefix is of course optional. Therefore
-      the example could also look like this:
-    </p><pre> &lt;project name="test"&gt; 
-   &lt;typedef resource="org/example/tasks.properties" uri="<a href="http://example.org/tasks">http://example.org/tasks</a>"/&gt;
-   &lt;task xmlns="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
-     ...
-   &lt;/task&gt;
- &lt;/project&gt;
-</pre>
+      Use of a namespace prefix is of course optional. Therefore the example could also look
+      like this:
+    </p>
+    <pre>
+&lt;project name="test"&gt;
+    &lt;typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/&gt;
+    &lt;task xmlns="http://example.org/tasks"&gt;
+        ...
+    &lt;/task&gt;
+&lt;/project&gt;</pre>
     <p>
       Here, the namespace is set as the default namespace for the <code>&lt;task&gt;</code>
       element and all its descendants.
     </p>
-    <h3>Default namespace</h3>
+
+    <h3>Default Namespace</h3>
     <p>
-      The default namespace used by Ant is "antlib:org.apache.tools.ant".
+      The default namespace used by Ant is <code>antlib:org.apache.tools.ant</code>.
     </p>
     <pre>
 &lt;typedef resource="org/example/tasks.properties" uri="antlib:org.apache.tools.ant"/&gt;
 &lt;task&gt;
-      ....
-&lt;/task&gt;
-    </pre>
-
-     
+    ...
+&lt;/task&gt;</pre>
 
     <h3>Namespaces and Nested Elements</h3>
-
     <p>
-      Almost always in Ant 1.6, elements nested inside a namespaced
-      element have the same namespace as their parent. So if 'task' in the
-      example above allowed a nested 'config' element, the build file snippet
-      would look like this:
-    </p><pre> &lt;typedef resource="org/example/tasks.properties" uri="<a href="http://example.org/tasks">http://example.org/tasks</a>"/&gt;
- &lt;my:task xmlns:my="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
-   &lt;my:config a="foo" b="bar"/&gt;
-   ...
- &lt;/my:task&gt;
-</pre>
-    <p>If the element allows or requires a lot of nested elements, the
-      prefix needs to be used for every nested element. Making the namespace
-      the default can reduce the verbosity of the script:
-    </p><pre> &lt;typedef resource="org/example/tasks.properties" uri="<a href="http://example.org/tasks">http://example.org/tasks</a>"/&gt;
-          &lt;task xmlns="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
-          &lt;config a="foo" b="bar"/&gt;
-   ...
-          &lt;/task&gt;
-        </pre>
-    <p>
-      From Ant 1.6.2, elements nested inside a namespaced element may also be
-      in Ant's default namespace. This means that the following is now allowed:
+      Almost always in Ant 1.6, elements nested inside a namespaced element have the same
+      namespace as their parent. So if <code>task</code> in the example above allowed a
+      nested <code>config</code> element, the build file snippet would look like this:
     </p>
-    </p><pre> &lt;typedef resource="org/example/tasks.properties"
-   uri="<a href="http://example.org/tasks">http://example.org/tasks</a>"/&gt;
- &lt;my:task xmlns:my="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
-   &lt;config a="foo" b="bar"/&gt;
-   ...
- &lt;/my:task&gt;
-</pre>
-      
-    <h3>Namespaces and Attributes</h3>
+    <pre>
+&lt;typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/&gt;
+&lt;my:task xmlns:my="http://example.org/tasks"&gt;
+    &lt;my:config a="foo" b="bar"/&gt;
+    ...
+&lt;/my:task&gt;</pre>
+    <p>If the element allows or requires a lot of nested elements, the prefix needs to be used
+      for every nested element. Making the namespace the default can reduce the verbosity of the
+      script:
+    </p>
+    <pre>
+&lt;typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/&gt;
+&lt;task xmlns="http://example.org/tasks"&gt;
+    &lt;config a="foo" b="bar"/&gt;
+    ...
+&lt;/task&gt;</pre>
+    <p>
+      <em>Since Ant 1.6.2</em>, elements nested inside a namespaced element may also be in Ant's
+      default namespace. This means that the following is now allowed:
+    </p>
+    <pre>
+&lt;typedef resource="org/example/tasks.properties"
+    uri="http://example.org/tasks"/&gt;
+&lt;my:task xmlns:my="http://example.org/tasks"&gt;
+    &lt;config a="foo" b="bar"/&gt;
+    ...
+&lt;/my:task&gt;</pre>
 
+    <h3>Namespaces and Attributes</h3>
     <p>
       Attributes are only used to configure the element they belong to if:
     </p>
     <ul>
-      <li> they have no namespace (note that the default namespace does *not* apply to attributes)
-      </li>
-      <li> they are in the same namespace as the element they belong to
-      </li>
+      <li>they have no namespace (note that the default namespace does <strong>not</strong> apply to attributes)</li>
+      <li>they are in the same namespace as the element they belong to</li>
     </ul>
     <p>
-      In Ant 1.9.1 two attribute namespaces <code>ant:if</code> and <code>ant:unless</code> were added
-      to allow you to insert elements conditionally.
+      <em>Since Ant 1.9.1</em> two attribute namespaces <code>ant:if</code>
+      and <code>ant:unless</code> are available to allow you to insert elements conditionally.
     </p>
     <p>
       Other attributes are simply ignored.
@@ -162,62 +159,65 @@
       This means that both:
     </p>
     <p>
-    </p><pre> &lt;my:task xmlns:my="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
-   &lt;my:config a="foo" b="bar"/&gt;
-   ...
- &lt;/my:task&gt;
-</pre>
+    </p>
+    <pre>
+&lt;my:task xmlns:my="http://example.org/tasks"&gt;
+    &lt;my:config a="foo" b="bar"/&gt;
+    ...
+&lt;/my:task&gt;</pre>
     <p>
       and
     </p>
-    <pre> &lt;my:task xmlns:my="<a href="http://example.org/tasks">http://example.org/tasks</a>"&gt;
-   &lt;my:config my:a="foo" my:b="bar"/&gt;
-   ...
- &lt;/my:task&gt;
-</pre>
+    <pre>
+&lt;my:task xmlns:my="http://example.org/tasks"&gt;
+    &lt;my:config my:a="foo" my:b="bar"/&gt;
+    ...
+&lt;/my:task&gt;</pre>
     <p>
-      result in the parameters "a" and "b" being used as parameters to configure the nested "config" element.
+      result in the parameters <var>a</var> and <var>b</var> being used as parameters to
+      configure the nested <code>config</code> element.
     </p>
-    <p>It also means that you can use attributes from other namespaces
-      to markup the build file with extra metadata, such as RDF and
-      XML-Schema (whether that's a good thing or not). The same is not true
-      for elements from unknown namespaces, which result in a error.
+    <p>
+      It also means that you can use attributes from other namespaces to markup the build file
+      with extra metadata, such as RDF and XML-Schema (whether that's a good thing or not). The
+      same is not true for elements from unknown namespaces, which result in a error.
     </p>
     <h3>Mixing Elements from Different Namespaces</h3>
 
-    <p>Now comes the difficult part: elements from different namespaces can
-      be woven together under certain circumstances. This has a lot to do
-      with the Ant 1.6
-      <a href="../develop.html#nestedtype">add type introspection rules</a>:
-      Ant types and tasks are now free to accept arbitrary named types as
-      nested elements, as long as the concrete type implements the interface
-      expected by the task/type. The most obvious example for this is the
-      <code>&lt;condition&gt;</code> task, which supports various nested conditions, all
-      of which extend the interface <tt>Condition</tt>. To integrate a
-      custom condition in Ant, you can now simply <code>&lt;typedef&gt;</code> the
-      condition, and then use it anywhere nested conditions are allowed
-      (assuming the containing element has a generic <tt>add(Condition)</tt> or <tt>addConfigured(Condition)</tt> method):
-</p><pre> &lt;typedef resource="org/example/conditions.properties" uri="<a href="http://example.org/conditions">http://example.org/conditions</a>"/&gt;
- &lt;condition property="prop" xmlns="<a href="http://example.org/conditions">http://example.org/conditions</a>"&gt;
-   &lt;and&gt;
-     &lt;available file="bla.txt"/&gt;
-     &lt;my:condition a="foo"/&gt;
-   &lt;/and&gt;
- &lt;/condition&gt;
-</pre>
     <p>
-      In Ant 1.6, this feature cannot be used as much as we'd all like to: a
-      lot of code has not yet been adapted to the new introspection rules,
-      and elements like Ant's built-in conditions and selectors are not
-      really types in 1.6. This is expected to change in Ant 1.7.
+      Now comes the difficult part: elements from different namespaces can be woven together under
+      certain circumstances. This has a lot to do with the Ant
+      1.6 <a href="../develop.html#nestedtype">add type introspection rules</a>: Ant types and tasks
+      are now free to accept arbitrary named types as nested elements, as long as the concrete type
+      implements the interface expected by the task/type. The most obvious example for this is
+      the <code>&lt;condition&gt;</code> task, which supports various nested conditions, all of
+      which extend the interface <code class="code">Condition</code>. To integrate a custom
+      condition in Ant, you can now simply <code>&lt;typedef&gt;</code> the condition, and then use
+      it anywhere nested conditions are allowed (assuming the containing element has a
+      generic <code class="code">add(Condition)</code>
+      or <code class="code">addConfigured(Condition)</code> method):
+    </p>
+    <pre>
+&lt;typedef resource="org/example/conditions.properties" uri="http://example.org/conditions"/&gt;
+&lt;condition property="prop" xmlns="http://example.org/conditions"&gt;
+    &lt;and&gt;
+        &lt;available file="bla.txt"/&gt;
+        &lt;my:condition a="foo"/&gt;
+    &lt;/and&gt;
+&lt;/condition&gt;</pre>
+    <p>
+      In Ant 1.6, this feature cannot be used as much as we'd all like to: a lot of code has not
+      yet been adapted to the new introspection rules, and elements like Ant's built-in
+      conditions and selectors are not really types in 1.6. This is expected to change in Ant
+      1.7.
     </p>
     <h3>Namespaces and Antlib</h3>
 
     <p>
-      The new <a href="antlib.html">AntLib</a>
-      feature is also very much integrated with the namespace support in Ant
-      1.6. Basically, you can "import" Antlibs simply by using a special
-      scheme for the namespace URI: the <tt>antlib</tt> scheme, which expects the package name in which a special <tt>antlib.xml</tt> file is located.
+      The new <a href="antlib.html">AntLib</a> feature is also very much integrated with the
+      namespace support in Ant 1.6. Basically, you can "import" Antlibs simply by using a
+      special scheme for the namespace URI: the <code>antlib</code> scheme, which expects the
+      package name in which a special <samp>antlib.xml</samp> file is located.
     </p>
 
 </body>
diff --git a/manual/Types/patternset.html b/manual/Types/patternset.html
index 1cfcb8f..33030d6 100644
--- a/manual/Types/patternset.html
+++ b/manual/Types/patternset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,184 +15,183 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>PatternSet Type</title>
 </head>
 
 <body>
 
-<h2><a name="patternset">PatternSet</a></h2>
-<p><a href="../dirtasks.html#patterns">Patterns</a> can be grouped to
-sets and later be referenced by their <code>id</code> attribute. They
-are defined via a <code>patternset</code> element, which can appear
-nested into a <a href="fileset.html">FileSet</a> or a directory-based
-task that constitutes an implicit FileSet. In addition,
-<code>patternset</code>s can be defined as a stand alone element at
-the same level as <code>target</code> &#151; i.e., as children of
-<code>project</code> as well as as children of
-<code>target</code>.</p> <p>Patterns can be specified by nested
-<code>&lt;include&gt;</code>, or <code>&lt;exclude&gt;</code> elements
-or the following attributes.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h2 id="patternset">PatternSet</h2>
+<p><a href="../dirtasks.html#patterns">Patterns</a> can be grouped to sets and later be
+referenced by their <var>id</var> attribute. They are defined via a <code>patternset</code>
+element, which can appear nested into a <a href="fileset.html">FileSet</a> or a directory-based
+task that constitutes an implicit FileSet. In addition, <code>patternset</code>s can be defined
+as a stand alone element at the same level as <code>target</code>&mdash;i.e., as children of
+<code>project</code> as well as as children of <code>target</code>.</p>
+<p>Patterns can be specified by nested <code>&lt;include&gt;</code>,
+or <code>&lt;exclude&gt;</code> elements or the following attributes.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Default</th>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      included. All files are included when omitted.</td>
+    <td>includes</td>
+    <td>comma- or space-separated list of patterns of files that must be included.</td>
+    <td>All files are included.</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file; each line of this file is
-      taken to be an include pattern. You can specify more than one
-      include file by using a nested includesfile elements.
-      <b>Note:</b> if the file is empty and there are no other
+    <td>includesfile</td>
+    <td>name of a file; each line of this file is taken to be an include pattern. You can
+      specify more than one include file by using a nested <code>includesfile</code> elements.
+      <strong>Note:</strong> if the file is empty and there are no other
       patterns defined for the fileset, all files will be included.
     </td>
+    <td>See <var>includes</var></td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns of files that must be
-      excluded; no files (except default excludes) are excluded when omitted.</td>
+    <td>excludes</td>
+    <td>comma- or space-separated list of patterns of files that must be excluded.</td>
+    <td>No files except default excludes are excluded.</td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file; each line of this file is
-      taken to be an exclude pattern. You can specify more than one
-      exclude file by using a nested excludesfile elements.</td>
+    <td>excludesfile</td>
+    <td>name of a file; each line of this file is taken to be an exclude pattern. You can
+      specify more than one exclude file by using a nested <code>excludesfile</code>
+      elements.</td>
+    <td>See <var>excludes</var></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>patternset</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>patternset</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4><code>include</code> and <code>exclude</code></h4>
-<p>Each such element defines a single pattern for files to include or
-exclude.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Each such element defines a single pattern for files to include or exclude.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the <a href="../dirtasks.html#patterns">pattern</a>
-      to in/exclude.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>the <a href="../dirtasks.html#patterns">pattern</a> to in/exclude.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">Only use this pattern <a href="../properties.html#if+unless">if the named property is set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>if</td>
+    <td>Only use this pattern <a href="../properties.html#if+unless">if the named property is
+    set</a>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">Only use this pattern <a href="../properties.html#if+unless">if the named property is
-       <b>not</b> set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>unless</td>
+    <td>Only use this pattern <a href="../properties.html#if+unless">if the named property
+    is <strong>not</strong> set</a>.</td>
+    <td>No</td>
   </tr>
 </table>
 <h4><code>includesfile</code> and <code>excludesfile</code></h4>
-<p>If you want to list the files to include or exclude external to
-your build file, you should use the includesfile/excludesfile
-attributes or elements.  Using the attribute, you can only specify a
-single file of each type, while the nested elements can be specified
-more than once - the nested elements also support if/unless attributes
-you can use to test the existence of a property.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>If you want to list the files to include or exclude external to your build file, you should
+use the <var>includesfile</var>/<var>excludesfile</var> attributes or elements.  Using the
+attribute, you can only specify a single file of each type, while the nested elements can be
+specified more than once&mdash;the nested elements also support <var>if</var>/<var>unless</var>
+attributes you can use to test the existence of a property.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the file holding the patterns to
-      in/exclude.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>the name of the file holding the patterns to in/exclude.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">if</td>
-    <td valign="top">Only read this file <a href="../properties.html#if+unless">if the named property is set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>if</td>
+    <td>Only read this file <a href="../properties.html#if+unless">if the named property is
+    set</a>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">unless</td>
-    <td valign="top">Only read this file <a href="../properties.html#if+unless">if the named property is
-      <b>not</b> set</a>.</td>
-    <td align="center" valign="top">No</td>
+    <td>unless</td>
+    <td>Only read this file <a href="../properties.html#if+unless">if the named property
+    is <strong>not</strong> set</a>.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding of the file. <em>Since Ant 1.9.12</em></td>
-    <td valign="top" align="center">No, default is platform default</td>
+    <td>encoding</td>
+    <td>The encoding of the file. <em>Since Ant 1.10.4</em></td>
+    <td>No, default is platform default</td>
   </tr>
 </table>
 <h4><code>patternset</code></h4>
-<p>Patternsets may be nested within one another, adding the nested
-patterns to the parent patternset.</p>
+<p>Patternsets may be nested within one another, adding the nested patterns to the parent
+patternset.</p>
 <h4><code>invert</code></h4>
-<p>A nested patternset can be inverted using the <code>&lt;invert&gt;</code>
-element. <em>Since Apache Ant 1.7.1</em></p>
+<p><em>Since Apache Ant 1.7.1</em></p>
+<p>A nested patternset can be inverted using the <code>&lt;invert&gt;</code> element.</p>
 <h3>Examples</h3>
-<blockquote><pre>
+<pre>
 &lt;patternset id=&quot;non.test.sources&quot;&gt;
   &lt;include name=&quot;**/*.java&quot;/&gt;
   &lt;exclude name=&quot;**/*Test*&quot;/&gt;
 &lt;/patternset&gt;
-</pre></blockquote>
-<p>Builds a set of patterns that matches all <code>.java</code> files
-that do not contain the text <code>Test</code> in their name. This set
-can be <a href="../using.html#references">referred</a> to via
-<code>&lt;patternset refid=&quot;non.test.sources&quot;/&gt;</code>,
-by tasks that support this feature, or by FileSets.</p>
-<p>Note that while the <code>includes</code> and
-<code>excludes</code> attributes accept
-multiple elements separated by commas or spaces, the nested
-<code>&lt;include&gt;</code> and <code>&lt;exclude&gt;</code> elements expect their name
-attribute to hold a single pattern.</p>
-<p>The nested elements allow you to use if and unless arguments to
-specify that the element should only be used if a property is set, or
-that it should be used only if a property is not set.</p>
+</pre>
+<p>Builds a set of patterns that matches all <samp>.java</samp> files that do not contain the
+text <samp>Test</samp> in their name. This set can
+be <a href="../using.html#references">referred</a> to via <code>&lt;patternset
+refid=&quot;non.test.sources&quot;/&gt;</code>, by tasks that support this feature, or by
+FileSets.</p>
+<p>Note that while the <var>includes</var> and <var>excludes</var> attributes accept multiple
+elements separated by commas or spaces, the nested <code>&lt;include&gt;</code>
+and <code>&lt;exclude&gt;</code> elements expect their name attribute to hold a single
+pattern.</p>
+<p>The nested elements allow you to use <var>if</var> and <var>unless</var> attributes to
+specify that the element should only be used if a property is set, or that it should be used
+only if a property is not set.</p>
 <p>For example</p>
-<blockquote><pre>
+<pre>
 &lt;patternset id=&quot;sources&quot;&gt;
   &lt;include name=&quot;std/**/*.java&quot;/&gt;
   &lt;include name=&quot;prof/**/*.java&quot; if=&quot;professional&quot;/&gt;
   &lt;exclude name=&quot;**/*Test*&quot;/&gt;
 &lt;/patternset&gt;
-</pre></blockquote>
-<p>will only include the files in the sub-directory <em>prof</em> if the property
-<em>professional</em> is set to some value.</p>
+</pre>
+<p>will only include the files in the sub-directory <samp>prof</samp> if the
+property <code>professional</code> is set to some value.</p>
 <p>The two sets</p>
-<blockquote><pre>
+<pre>
 &lt;patternset includesfile=&quot;some-file&quot;/&gt;
-</pre></blockquote>
+</pre>
 <p>and</p>
-<blockquote><pre>
+<pre>
 &lt;patternset&gt;
-  &lt;includesfile name=&quot;some-file&quot;/&gt; 
+  &lt;includesfile name=&quot;some-file&quot;/&gt;
 &lt;patternset/&gt;
-</pre></blockquote>
-<p>are identical.  The include patterns will be read from the file
-<code>some-file</code>, one pattern per line.</p>
-<blockquote><pre>
+</pre>
+<p>are identical.  The include patterns will be read from the file <samp>some-file</samp>, one
+pattern per line.</p>
+<pre>
 &lt;patternset&gt;
-  &lt;includesfile name=&quot;some-file&quot;/&gt; 
-  &lt;includesfile name=&quot;${some-other-file}&quot; 
-                if=&quot;some-other-file&quot;
-  /&gt; 
+  &lt;includesfile name=&quot;some-file&quot;/&gt;
+  &lt;includesfile name=&quot;${some-other-file}&quot;
+                if=&quot;some-other-file&quot;/&gt;
 &lt;patternset/&gt;
-</pre></blockquote>
-<p>will also read include patterns from the file the property
-<code>some-other-file</code> points to, if a property of that name has
-been defined.</p>
-
+</pre>
+<p>will also read include patterns from the file the property <code>some-other-file</code>
+points to, if a property of that name has been defined.</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/permissions.html b/manual/Types/permissions.html
index f7b90b7..6118ab5 100644
--- a/manual/Types/permissions.html
+++ b/manual/Types/permissions.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,107 +15,87 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Permissions type</title>
 </head>
 
 <body>
 
-<h2><a name="permissions">Permissions</a></h2>
-<p>
-Permissions represents a set of security permissions granted or revoked to
-a specific part code executed in the JVM where Apache Ant is running in.
-The actual Permissions are specified via a set of nested permission items either
-<code>&lt;grant&gt;</code>ed or <code>&lt;revoke&gt;</code>d.</p>
-<p>
-In the base situation a <a href="#baseset">base set</a> of permissions granted. 
-Extra permissions can be
-granted. A granted permission can be overruled by revoking a permission.
-The security manager installed by the permissions will throw an 
-<code>SecurityException</code> if
-the code subject to these permissions try to use an permission that has not been 
-granted or that has been revoked.</p>
+<h2 id="permissions">Permissions</h2>
+<p>Permissions represents a set of security permissions granted or revoked to a specific part
+code executed in the JVM where Apache Ant is running in.  The actual Permissions are specified
+via a set of nested permission items either <code>&lt;grant&gt;</code>ed
+or <code>&lt;revoke&gt;</code>d.</p>
+<p>In the base situation a <a href="#baseset">base set</a> of permissions granted.  Extra
+permissions can be granted. A granted permission can be overruled by revoking a permission.  The
+security manager installed by the permissions will throw an <code>SecurityException</code> if
+the code subject to these permissions try to use an permission that has not been granted or that
+has been revoked.</p>
 <h3>Nested elements</h3>
 <h4>grant</h4>
-<p>
-Indicates a specific permission is always granted. Its attributes indicate which 
-permissions are granted.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Indicates a specific permission is always granted. Its attributes indicate which permissions
+are granted.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">class</td>
-    <td valign="top">The fully qualified name of the Permission class.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>class</td>
+    <td>The fully qualified name of the Permission class.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the Permission. The actual contents depends on the
-    Permission class.</td>
-    <td valign="top" align="center">No</td>
+    <td>name</td>
+    <td>The name of the Permission. The actual contents depends on the Permission class.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">actions</td>
-    <td valign="top">The actions allowed. The actual contents depend on the 
-    Permission class and name.</td>
-    <td valign="top" align="center">No</td>
+    <td>actions</td>
+    <td>The actions allowed. The actual contents depend on the Permission class and name.</td>
+    <td>No</td>
   </tr>
 </table>
-<p>
-Implied permissions are granted.
-</p>
-<p>
-Please note that some Permission classes may actually need a name and / or actions in order to function properly. The name and actions are parsed by the actual
-Permission class.
-</p>
+<p>Implied permissions are granted.</p>
+<p>Please note that some Permission classes may actually need a name and/or actions in order to
+function properly. The name and actions are parsed by the actual Permission class.</p>
 <h4>revoke</h4>
-<p>
-Indicates a specific permission is revoked.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>Indicates a specific permission is revoked.</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">class</td>
-    <td valign="top">The fully qualified name of the Permission class.</td>
-    <td valign="top" align="center">Yes</td>
+    <td>class</td>
+    <td>The fully qualified name of the Permission class.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the Permission. The actual contents depends on the
-    Permission class.</td>
-    <td valign="top" align="center">No</td>
+    <td>name</td>
+    <td>The name of the Permission. The actual contents depends on the Permission class.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">actions</td>
-    <td valign="top">The actions allowed. The actual contents depend on the 
-    Permission class and name.</td>
-    <td valign="top" align="center">No</td>
+    <td>actions</td>
+    <td>The actions allowed. The actual contents depend on the Permission class and name.</td>
+    <td>No</td>
   </tr>
 </table>
-<p>
-Implied permissions are not resolved and therefore also not revoked.
-</p>
-<p>
-The name can handle the * wildcard at the end of the name, in which case all 
-permissions of the specified class of which the name starts with the specified name
-(excluding the *) are revoked. Note that the - wildcard often supported by the
-granted properties is not supported.
-If the name is left empty all names match, and are revoked.
-If the actions are left empty all actions match, and are revoked.
-</p>
-<h3><a name="baseset">Base set</a></h3>
-A permissions set implicitly contains the following permissions:
-<blockquote><pre>
+<p>Implied permissions are not resolved and therefore also not revoked.</p>
+<p>The <var>name</var> can handle the <q>*</q> wildcard at the end of the name, in which case
+all permissions of the specified class of which the name starts with the specified name
+(excluding the <q>*</q>) are revoked. Note that the <q>-</q> wildcard often supported by the
+granted properties is not supported.  If the <var>name</var> is left empty all names match, and
+are revoked.  If the <var>actions</var> are left empty all actions match, and are revoked.</p>
+<h3 id="baseset">Base set</h3>
+<p>A permissions set implicitly contains the following permissions:</p>
+<pre>
 &lt;grant class=&quot;java.net.SocketPermission&quot; name=&quot;localhost:1024-&quot; actions=&quot;listen&quot;&gt;
 &lt;grant class=&quot;java.util.PropertyPermission&quot; name=&quot;java.version&quot; actions=&quot;read&quot;&gt;
 &lt;grant class=&quot;java.util.PropertyPermission&quot; name=&quot;java.vendor&quot; actions=&quot;read&quot;&gt;
@@ -136,29 +117,26 @@
 &lt;grant class=&quot;java.util.PropertyPermission&quot; name=&quot;java.vm.version&quot; actions=&quot;read&quot;&gt;
 &lt;grant class=&quot;java.util.PropertyPermission&quot; name=&quot;java.vm.vendor&quot; actions=&quot;read&quot;&gt;
 &lt;grant class=&quot;java.util.PropertyPermission&quot; name=&quot;java.vm.name&quot; actions=&quot;read&quot;&gt;
-</blockquote></pre>
-These permissions can be revoked via <code>&lt;revoke&gt;</code> elements if necessary.
+</pre>
+<p>These permissions can be revoked via <code>&lt;revoke&gt;</code> elements if necessary.</p>
 
 <h3>Examples</h3>
-<blockquote><pre>
+<pre>
 &lt;permissions&gt;
   &lt;grant class=&quot;java.security.AllPermission&quot;/&gt;
   &lt;revoke class=&quot;java.util.PropertyPermission&quot;/&gt;
 &lt;/permissions&gt;
-</pre></blockquote>
-<p>
-Grants all permissions to the code except for those handling Properties.
-</p>
-<blockquote><pre>
+</pre>
+<p>Grants all permissions to the code except for those handling Properties.</p>
+<pre>
 &lt;permissions&gt;
   &lt;grant class=&quot;java.net.SocketPermission&quot; name=&quot;foo.bar.com&quot; action=&quot;connect&quot;/&gt;
   &lt;grant class=&quot;java.util.PropertyPermission&quot; name=&quot;user.home&quot; action=&quot;read,write&quot;/&gt;
 &lt;/permissions&gt;
-</pre></blockquote>
-<p>
-Grants the base set of permissions with the addition of a SocketPermission to connect
-to foo.bar.com and the permission to read and write the user.home system property.
-</p>
+</pre>
+<p>Grants the base set of permissions with the addition of
+a <code class="code">SocketPermission</code> to connect to <samp>foo.bar.com</samp> and the
+permission to read and write the <code>user.home</code> system property.</p>
 
 </body>
 </html>
diff --git a/manual/Types/propertyset.html b/manual/Types/propertyset.html
index 81d491e..b010242 100644
--- a/manual/Types/propertyset.html
+++ b/manual/Types/propertyset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,80 +15,79 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>PropertySet Type</title>
 </head>
 
 <body>
 
-<h2><a name="propertyset">PropertySet</a></h2>
+<h2 id="propertyset">PropertySet</h2>
 <p><em>Since Apache Ant 1.6</em></p>
 
-<p>Groups a set of properties to be used by reference in a task that
-supports this.</p>
+<p>Groups a set of properties to be used by reference in a task that supports this.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">dynamic</td>
-    <td valign="top">Whether to reevaluate the set every time the set
-      is used.  Default is &quot;<code>true</code>&quot;.</td>
-    <td valign="top" align="center">No</td>
+    <td>dynamic</td>
+    <td>Whether to reevaluate the set every time the set is used.</td>
+    <td>No; default is <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">negate</td>
-    <td valign="top">Whether to negate results. If
-      &quot;<code>true</code>&quot;, all properties <i>not</i>
-      selected by nested elements will be returned. Default is
-      &quot;<code>false</code>&quot;. <em>Since Ant 1.6.2</em>
+    <td>negate</td>
+    <td>Whether to negate results. If <q>true</q>, all properties <em>not</em> selected by
+      nested elements will be returned. <em>Since Ant 1.6.2</em>
     </td>
-    <td valign="top" align="center">No</td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>propertyset</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>propertyset</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
 <h4>propertyref</h4>
 
-<p>Selects properties from the current project to be included in the
-set.</p>
+<p>Selects properties from the current project to be included in the set.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">Select the property with the given name.</td>
-    <td align="center" valign="top" rowspan="4">Exactly one of these.</td>
+    <td>name</td>
+    <td>Select the property with the given name.</td>
+    <td rowspan="4">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">Select the properties whose name starts with the
-      given string.</td>
+    <td>prefix</td>
+    <td class="left">Select the properties whose name starts with the given string.</td>
   </tr>
   <tr>
-    <td valign="top">regex</td>
-    <td valign="top">Select the properties that match the given
-      regular expression.  Similar to <a
-      href="mapper.html#regexp-mapper">regexp type mappers</a>, this
-      requires a supported regular expression library.</td>
+    <td>regex</td>
+    <td class="left">Select the properties that match the given regular expression.  Similar
+      to <a href="mapper.html#regexp-mapper">regexp type mappers</a>, this requires a supported
+      regular expression library.</td>
   </tr>
   <tr>
-    <td valign="top">builtin</td>
-    <td valign="top">Selects a builtin set of properties.  Valid
-      values for this attribute are <code>all</code> for all Ant
-      properties, <code>system</code> for the system properties and
-      <code>commandline</code> for all properties specified on the
+    <td>builtin</td>
+    <td class="left">Selects a builtin set of properties.  Valid values for this attribute
+      are <q>all</q> for all Ant properties, <q>system</q> for the system properties and
+      <q>commandline</q> for all properties specified on the
       command line when invoking Ant (plus a number of special
       internal Ant properties).</td>
   </tr>
@@ -95,12 +95,12 @@
 
 <h4>propertyset</h4>
 
-<p>A <code>propertyset</code> can be used as the set union of more
-<code>propertyset</code>s.</p>
+<p>A <code>propertyset</code> can be used as the set union of
+more <code>propertyset</code>s.</p>
 
 <p>For example:</p>
 
-<blockquote><pre>
+<pre>
 &lt;propertyset id=&quot;properties-starting-with-foo&quot;&gt;
   &lt;propertyref prefix=&quot;foo&quot;/&gt;
 &lt;/propertyset&gt;
@@ -111,33 +111,28 @@
   &lt;propertyset refid=&quot;properties-starting-with-foo&quot;/&gt;
   &lt;propertyset refid=&quot;properties-starting-with-bar&quot;/&gt;
 &lt;/propertyset&gt;
-</pre></blockquote>
+</pre>
 
-<p>collects all properties whose name starts with either
-&quot;foo&quot; or &quot;bar&quot; in the set named
-&quot;my-set&quot;.</p>
+<p>collects all properties whose name starts with either <q>foo</q> or <q>bar</q> in the set
+named <q>my-set</q>.</p>
 
 <h4>mapper</h4>
 
-<p>A <a href="mapper.html">mapper</a> - at maximum one mapper can be
-specified.  The mapper is used to change the names of the property
-keys, for example:
+<p>A <a href="mapper.html">mapper</a>&mdash;at maximum one mapper can be specified.  The mapper
+is used to change the names of the property keys, for example:
 
-<blockquote><pre>
+<pre>
 &lt;propertyset id=&quot;properties-starting-with-foo&quot;&gt;
   &lt;propertyref prefix=&quot;foo&quot;/&gt;
   &lt;mapper type=&quot;glob&quot; from=&quot;foo*&quot; to=&quot;bar*&quot;/&gt;
 &lt;/propertyset&gt;
-</pre></blockquote>
+</pre>
 
-<p>collects all properties whose name starts with &quot;foo&quot;, but
-changes the names to start with &quot;bar&quot; instead.</p>
+<p>collects all properties whose name starts with <q>foo</q>, but changes the names to start
+with <q>bar</q> instead.</p>
 
-<p>If supplied, the nested mapper will be applied
-subsequent to any negation of matched properties.</p>
-
-
+<p>If supplied, the nested mapper will be applied subsequent to any negation of matched
+properties.</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/redirector.html b/manual/Types/redirector.html
index d0e3683..94ecd48 100644
--- a/manual/Types/redirector.html
+++ b/manual/Types/redirector.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,180 +15,174 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Redirector Type</title>
 </head>
 
 <body>
 
-<h2><a name="redirector">I/O redirection</a></h2>
-<p>For many tasks, input and output can be defined in a fairly
-straightforward fashion.  The <a href="../Tasks/exec.html">exec</a>
-task, used to execute an external process, stands as a very
-basic example.  The executed process may accept input, produce
-output, or do either or both depending upon various circumstances.
-Output may be classified as &quot;output&quot; or as &quot;error
-output.&quot;  The <code>&lt;redirector&gt;</code> type provides a concrete means
-of redirecting input and output featuring the use of
-<a href="./mapper.html">File Mapper</a>s to specify
-source (input) and destination (output/error) files.  <em>Since Apache Ant 1.6.2</em>
+<h2 id="redirector">I/O redirection</h2>
+<p><em>Since Apache Ant 1.6.2</em></p>
+<p>For many tasks, input and output can be defined in a fairly straightforward fashion.
+The <a href="../Tasks/exec.html">exec</a> task, used to execute an external process, stands as a
+very basic example.  The executed process may accept input, produce output, or do either or both
+depending upon various circumstances.  Output may be classified as <em>output</em> or
+as <em>error output</em>.  The <code>&lt;redirector&gt;</code> type provides a concrete means of
+redirecting input and output featuring the use of <a href="./mapper.html">File Mapper</a>s to
+specify source (input) and destination (output/error) files.</p>
 <p>The <code>&lt;redirector&gt;</code> element accepts the following attributes:</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">output</td>
-    <td valign="top">Name of a file to which output should be written.
-      If the error stream is not also redirected to a file or property,
-      it will appear in this output.</td>
-    <td align="center" valign="top">No</td>
+    <td>output</td>
+    <td>Name of a file to which output should be written.  If the error stream is not also
+      redirected to a file or property, it will appear in this output.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">error</td>
-    <td valign="top">The file to which the standard error of the
-      command should be redirected.</td>
-    <td align="center" valign="top">No</td>
+    <td>error</td>
+    <td>The file to which the standard error of the command should be redirected.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">logError</td>
-    <td valign="top">This attribute is used when you wish to see
-      error output in Ant's log and you are redirecting output to
-      a file/property. The error output will not be included in
-      the output file/property. If you redirect error with the
-      <i>error</i> or <i>errorProperty</i> attributes, this will
-      have no effect.</td>
-    <td align="center" valign="top">No</td>
+    <td>logError</td>
+    <td>This attribute is used when you wish to see error output in Ant's log and you are
+      redirecting output to a file/property. The error output will not be included in the output
+      file/property.</td>
+    <td>No; ignored if <var>error</var> or <var>errorProperty</var>
+    is set</td>
   </tr>
   <tr>
-    <td valign="top">append</td>
-    <td valign="top">Whether output and error files should be
-      appended to rather than overwritten. Defaults to
-      <code>false</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>append</td>
+    <td>Whether output and error files should be appended to rather than overwritten.</td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">createemptyfiles</td>
-    <td valign="top">Whether output and error files should be
-      created even when empty.  Defaults to <code>true</code>.</td>
-    <td align="center" valign="top">No</td>
+    <td>createemptyfiles</td>
+    <td>Whether output and error files should be created even when empty.</td>
+    <td>No; defaults to <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">outputproperty</td>
-    <td valign="top">The name of a property in which the output of the
-      command should be stored. Unless the error stream is redirected
-      to a separate file or stream, this property will include the
+    <td>outputproperty</td>
+    <td>The name of a property in which the output of the command should be stored. Unless the
+      error stream is redirected to a separate file or stream, this property will include the
       error output.</td>
-    <td align="center" valign="top">No</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errorproperty</td>
-    <td valign="top">The name of a property in which the standard error
-      of the command should be stored.</td>
-    <td align="center" valign="top">No</td>
+    <td>errorproperty</td>
+    <td>The name of a property in which the standard error of the command should be stored.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">input</td>
-    <td valign="top">A file from which the executed command's standard input
-      is taken. This attribute is mutually exclusive with the
-      <i>inputstring</i> attribute.</td>
-    <td align="center" valign="top">No</td>
+    <td>input</td>
+    <td>A file from which the executed command's standard input is taken. This attribute is
+      mutually exclusive with the <var>inputstring</var> attribute.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputstring</td>
-    <td valign="top">A string which serves as the input stream for the
-      executed command. This attribute is mutually exclusive with the
-      <i>input</i> attribute.</td>
-    <td align="center" valign="top">No</td>
+    <td>inputstring</td>
+    <td>A string which serves as the input stream for the executed command. This attribute is
+      mutually exclusive with the <var>input</var> attribute.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">inputencoding</td>
-    <td valign="top">The input encoding.</td>
-    <td align="center" valign="top">No</td>
+    <td>inputencoding</td>
+    <td>The input encoding.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">outputencoding</td>
-    <td valign="top">The output encoding.</td>
-    <td align="center" valign="top">No</td>
+    <td>outputencoding</td>
+    <td>The output encoding.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">errorencoding</td>
-    <td valign="top">The error encoding.</td>
-    <td align="center" valign="top">No</td>
+    <td>errorencoding</td>
+    <td>The error encoding.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">alwayslog</td>
-    <td valign="top">Always send to the log in addition to
-        any other destination. <i>Since Ant 1.6.3</i>.
+    <td>alwayslog</td>
+    <td>Always send to the log in addition to any other destination. <em>Since Ant 1.6.3</em></td>
+    <td>No; default is <q>false</q></td>
+  </tr>
+  <tr>
+    <td>loginputstring</td>
+    <td>Controls the display of <var>inputstring</var>'s value in log messages. Set
+      to <q>false</q> when sending sensitive data (e.g. passwords) to external
+      processes. <em>Since Ant 1.6.3</em></td>
+    <td>No; default is <q>true</q></td>
+  </tr>
+  <tr>
+    <td>binaryOutput</td>
+    <td>When set to <q>true</q> Ant will not try to split the output into lines&mdash;which it
+      will usually do in order to separate error from normal output.  This setting will not
+      prevent binary output from getting corrupted if you also specify filter chains.
+      <em>Since Ant 1.9.4</em>
     </td>
-    <td align="center" valign="top">No, default is <code>false</code></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">loginputstring</td>
-    <td valign="top">Controls the display of <i>inputstring</i>'s value in
-        log messages. Set to <code>false</code> when sending sensitive data
-        (e.g. passwords) to external processes. <i>Since Ant 1.6.3</i>.
+    <td>discardOutput</td>
+    <td>Whether output should completely be discarded. This setting is
+      incompatible with any setting that redirects output to files or
+      properties.<br/>
+      If you set this to <q>true</q> error output will be discared as
+      well unless you redirect error output to files, properties or
+      enable <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
     </td>
-    <td align="center" valign="top">No, default is <code>true</code></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">binaryOutput</td>
-    <td valign="top">When set to true Ant will not try to split the
-      output into lines - which it will usually do in order to separate
-      error from normal output.  This setting will not prevent binary
-      output from getting corrupted if you also specify filter chains.
-      <i>Since Ant 1.9.4</i>.
+    <td>discardError</td>
+    <td>Whether error output should completely be discarded. This
+      setting is incompatible with any setting that redirects error
+      output to files or properties as well as <q>logError</q>.
+      <em>Since Ant 1.10.10</em>
     </td>
-    <td align="center" valign="top">No, default is <code>false</code></td>
+    <td>No; defaults to <q>false</q></td>
   </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 <h4>inputmapper</h4>
-<p>A single <a href="./mapper.html">File Mapper</a> used to redirect process
-input.  Multiple mapping results should concatenate all mapped files as input.
-Mapping will ordinarily be performed on a task-specified sourcefile;
-consult the documentation of the individual task for more details.
-A nested <code>&lt;inputmapper&gt;</code> is not compatible with either of the
-<i>input</i> or <i>inputstring</i> attributes.</p>
+<p>A single <a href="./mapper.html">File Mapper</a> used to redirect process input.  Multiple
+mapping results should concatenate all mapped files as input.  Mapping will ordinarily be
+performed on a task-specified sourcefile; consult the documentation of the individual task for
+more details.  A nested <code>&lt;inputmapper&gt;</code> is not compatible with either of the
+<var>input</var> or <var>inputstring</var> attributes.</p>
 <h4>outputmapper</h4>
-<p>A single <a href="./mapper.html">File Mapper</a> used to redirect process
-output.  Mapping will ordinarily be performed on a task-specified sourcefile;
-consult the documentation of the individual task for more details.
-A nested <code>&lt;outputmapper&gt;</code> is not compatible with the
-<i>output</i> attribute.</p>
+<p>A single <a href="./mapper.html">File Mapper</a> used to redirect process output.  Mapping
+will ordinarily be performed on a task-specified sourcefile; consult the documentation of the
+individual task for more details.  A nested <code>&lt;outputmapper&gt;</code> is not compatible
+with the <var>output</var> attribute.</p>
 <h4>errormapper</h4>
-<p>A single <a href="./mapper.html">File Mapper</a> used to redirect error
-output.  Mapping will ordinarily be performed on a task-specified sourcefile;
-consult the documentation of the individual task for more details.
-A nested <code>&lt;errormapper&gt;</code> is not compatible with the
-<i>error</i> attribute.</p>
+<p>A single <a href="./mapper.html">File Mapper</a> used to redirect error output.  Mapping will
+ordinarily be performed on a task-specified sourcefile; consult the documentation of the
+individual task for more details.  A nested <code>&lt;errormapper&gt;</code> is not compatible
+with the <var>error</var> attribute.</p>
 <h4>inputfilterchain</h4>
-<p>A <a href="./filterchain.html">FilterChain</a> can be
-applied to the process input.</p>
+<p>A <a href="./filterchain.html">FilterChain</a> can be applied to the process input.</p>
 <h4>outputfilterchain</h4>
-<p>A <a href="./filterchain.html">FilterChain</a> can be
-applied to the process output.</p>
+<p>A <a href="./filterchain.html">FilterChain</a> can be applied to the process output.</p>
 <h4>errorfilterchain</h4>
-<p>A <a href="./filterchain.html">FilterChain</a> can be
-applied to the error output.</p>
+<p>A <a href="./filterchain.html">FilterChain</a> can be applied to the error output.</p>
 <h3>Usage</h3>
-Tasks known to support I/O redirection:
+<p>Tasks known to support I/O redirection:</p>
 <ul>
 <li><a href="../Tasks/exec.html">Exec</a></li>
 <li><a href="../Tasks/apply.html">Apply</a></li>
 <li><a href="../Tasks/java.html">Java</a></li>
 </ul>
-<p>The expected behavior of a <code>&lt;redirector&gt;</code> is to a great degree
-dependent on the supporting task.  Any possible points of confusion
-should be noted at the task level.</p>
-
+<p>The expected behavior of a <code>&lt;redirector&gt;</code> is to a great degree dependent on
+the supporting task.  Any possible points of confusion should be noted at the task level.</p>
 
 </body>
 </html>
-
diff --git a/manual/Types/regexp.html b/manual/Types/regexp.html
index 0628bb9..3b661e8 100644
--- a/manual/Types/regexp.html
+++ b/manual/Types/regexp.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,96 +15,85 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Regexp Type</title>
 </head>
 
 <body>
 
-<h2><a name="regexp">Regexp</a></h2>
+<h2 id="regexp">Regexp</h2>
 <p>
 Regexp represents a regular expression.
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">pattern</td>
-    <td valign="top">regular expression pattern</td>
-    <td valign="top" align="center">Yes</td>
+    <td>pattern</td>
+    <td>regular expression pattern</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>regexp</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>regexp</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>Examples</h3>
-<blockquote><pre>
-     &lt;regexp id="myregexp" pattern="alpha(.+)beta"/&gt;<br>
-</pre></blockquote>
-<p>
-Defines a regular expression for later use with id myregexp.
-</p>
-<blockquote><pre>
-     &lt;regexp refid="myregexp"/&gt;<br>
-</pre></blockquote>
-<p>
-Use the regular expression with id myregexp.
-</p>
-<h3><a name="implementation">Choice of regular expression implementation</a></h3>
-<p>
-Apache Ant comes with
-wrappers for
-<a href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html" target="_top">the java.util.regex package</a>,
-<a href="http://attic.apache.org/projects/jakarta-regexp.html" target="_top">jakarta-regexp</a>
-and <a href="http://attic.apache.org/projects/jakarta-oro.html" target="_top">jakarta-ORO</a>,
-See <a href="../install.html#librarydependencies">installation dependencies</a>
- concerning the supporting libraries.</p>
-<p>
-The property <code>ant.regexp.regexpimpl</code> governs which regular expression implementation will be chosen.
-Possible values for this property are :
+<pre>&lt;regexp id="myregexp" pattern="alpha(.+)beta"/&gt;</pre>
+<p>Defines a regular expression for later use with <var>id</var> <q>myregexp</q>.</p>
+<pre>&lt;regexp refid="myregexp"/&gt;</pre>
+<p>Use the regular expression with <var>id</var> <q>myregexp</q>.</p>
+<h3 id="implementation">Choice of regular expression implementation</h3>
+<p>Apache Ant comes with wrappers for
+the <a href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html"
+target="_top"><code>java.util.regex</code>
+package</a>, <a href="https://attic.apache.org/projects/jakarta-regexp.html"
+target="_top">jakarta-regexp</a> and <a href="https://attic.apache.org/projects/jakarta-oro.html"
+target="_top">jakarta-ORO</a>, see <a href="../install.html#librarydependencies">installation
+dependencies</a> concerning the supporting libraries.</p>
+<p>The property <code>ant.regexp.regexpimpl</code> governs which regular expression implementation
+will be chosen.  Possible values for this property are:</p>
 <ul>
-<li>
-org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp
-</li>
-<li>
-org.apache.tools.ant.util.regexp.JakartaOroRegexp
-</li>
-<li>
-org.apache.tools.ant.util.regexp.JakartaRegexpRegexp
-</li>
+<li><code class="code">org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp</code></li>
+<li><code class="code">org.apache.tools.ant.util.regexp.JakartaOroRegexp</code></li>
+<li><code class="code">org.apache.tools.ant.util.regexp.JakartaRegexpRegexp</code></li>
 </ul>
-It can also be another implementation of the interface <code>org.apache.tools.ant.util.regexp.Regexp</code>.
-If <code>ant.regexp.regexpimpl</code> is not defined, Ant uses Jdk14Regexp as this is always available.</p>
+<p>It can also be another implementation of the
+interface <code class="code">org.apache.tools.ant.util.regexp.Regexp</code>.
+If <code>ant.regexp.regexpimpl</code> is not defined, Ant uses Jdk14Regexp as this is always
+available.</p>
 <p>
-There are cross-platform issues for matches related to line terminator.
-For example if you use $ to anchor your regular expression on the end of a line
-the results might be very different depending on both your platform and the regular
-expression library you use. It is 'highly recommended' that you test your pattern on
-both Unix and Windows platforms before you rely on it.
+There are cross-platform issues for matches related to line terminator.  For example if you
+use <q>$</q> to anchor your regular expression on the end of a line the results might be very
+different depending on both your platform and the regular expression library you use. It
+is <em>highly recommended</em> that you test your pattern on both Unix and Windows platforms before
+you rely on it.</p>
 <ul>
-    <li>Jakarta Oro defines a line terminator as '\n' and is consistent with Perl.</li>
-    <li>Jakarta RegExp uses a system-dependent line terminator.</li>
-    <li>JDK 1.4 uses '\n', '\r\n', '\u0085', '\u2028', '\u2029' as a default
-    but is configured in the wrapper to use only '\n' (UNIX_LINE)</li>
+  <li>Jakarta Oro defines a line terminator as <q>\n</q> and is consistent with Perl.</li>
+  <li>Jakarta RegExp uses a system-dependent line terminator.</li>
+  <li><code>java.util.regex</code> uses <q>\n</q>, <q>\r\n</q>, <q>\u0085</q>, <q>\u2028</q>, <q>\u2029</q> as a
+    default but is configured in the wrapper to use only <q>\n</q> (UNIX_LINE)</li>
 </ul>
-<em>We used to recommend that you use Jakarta ORO but since its
-  development has been retired Java's built-in regex package is likely
-  the best choice going forward.</em>
-</p>
-<h3>Usage</h3>
-The following tasks and types use the Regexp type :
+<p><em>We used to recommend that you use Jakarta ORO but since its development has been retired
+Java's built-in regex package is likely the best choice going forward.</em></p>
+<h3>Usage</h3> The following tasks and types use the Regexp type:
 <ul>
 <li><a href="../Tasks/replaceregexp.html">ReplaceRegExp task</a></li>
 <li><a href="filterchain.html#linecontainsregexp">LineContainsRegexp filter</a></li>
 </ul>
-<p>
-These string filters also use the mechanism of regexp to choose a regular expression implementation :
-</p>
+<p>These string filters also use the mechanism of regexp to choose a regular expression
+implementation:</p>
 <ul>
 <li><a href="filterchain.html#containsregex">ContainsRegex string filter</a></li>
 <li><a href="filterchain.html#replaceregex">ReplaceRegex string filter</a></li>
diff --git a/manual/Types/resources.html b/manual/Types/resources.html
index 5bdc231..5783fd1 100644
--- a/manual/Types/resources.html
+++ b/manual/Types/resources.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,351 +15,411 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Resources and Resource Collections</title>
 </head>
 
 <body>
 
-<h2><a name="resource">Resources</a></h2>
+<h2 id="resource">Resources</h2>
 <p>
-A file-like entity can be abstracted to the concept of a <i>resource</i>.
-In addition to providing access to file-like attributes, a resource
-implementation should, when possible, provide the means to read content
-from and/or write content to the underlying entity. Although the resource
-concept was introduced in <i>Apache Ant 1.5.2</i>, resources are available for
-explicit use beginning in <b>Ant 1.7</b>.
+A file-like entity can be abstracted to the concept of a <em>resource</em>.  In addition to
+providing access to file-like attributes, a resource implementation should, when possible,
+provide the means to read content from and/or write content to the underlying entity. Although
+the resource concept was introduced in Apache Ant 1.5.2, resources are available for explicit
+use <em>since Ant 1.7</em>.
 </p>
 
-<h3>The built-in resource types are:</h3>
-
+<h3>Built-in resource types</h3>
+The built-in resource types are:
 <ul>
-  <li><a href="#basic">resource</a> - a basic resource.</li>
-  <li><a href="#bzip2resource">bzip2resource</a> - a BZip2 compressed resource.</li>
-  <li><a href="#file">file</a> - a file.</li>
-  <li><a href="#gzipresource">gzipresource</a> - a GZip compressed resource.</li>
-  <li><a href="#javaresource">javaresource</a> - a resource loadable
-        via a Java classloader.</li>
-  <li><a href="#javaconstant">javaconstant</a> - a constant in a class loadable
-        via a Java classloader.</li>
-  <li><a href="#propertyresource">propertyresource</a> - an Ant property.</li>
-  <li><a href="#string">string</a> - a text string.</li>
-  <li><a href="#tarentry">tarentry</a> - an entry in a tar file.</li>
-  <li><a href="#url">url</a> - a URL.</li>
-  <li><a href="#zipentry">zipentry</a> - an entry in a zip file.</li>
+  <li><a href="#basic">resource</a>&mdash;a basic resource.</li>
+  <li><a href="#bzip2resource">bzip2resource</a>&mdash;a BZip2 compressed resource.</li>
+  <li><a href="#file">file</a>&mdash;a file.</li>
+  <li><a href="#gzipresource">gzipresource</a>&mdash;a GZip compressed resource.</li>
+  <li><a href="#javaresource">javaresource</a>&mdash;a resource loadable via a Java
+        classloader.</li>
+  <li><a href="#javaconstant">javaconstant</a>&mdash;a constant in a class loadable via a Java
+        classloader.</li>
+  <li><a href="#propertyresource">propertyresource</a>&mdash;an Ant property.</li>
+  <li><a href="#string">string</a>&mdash;a text string.</li>
+  <li><a href="#tarentry">tarentry</a>&mdash;an entry in a tar file.</li>
+  <li><a href="#url">url</a>&mdash;a URL.</li>
+  <li><a href="#xzresource">xzresource</a>&mdash;an XZ compressed resource.</li>
+  <li><a href="#zipentry">zipentry</a>&mdash;an entry in a zip file.</li>
 </ul>
 
-<h4><a name="basic">resource</a></h4>
+<h4 id="basic">resource</h4>
 
-<p>A basic resource. Other resource types derive from this basic
-type; as such all its attributes are available, though in most cases
-irrelevant attributes will be ignored. This and all resource
-implementations are also usable as single-element
-<a href="#collection">Resource Collections</a>.
+<p>
+A basic resource. Other resource types derive from this basic type; as such all its attributes
+are available, though in most cases irrelevant attributes will be ignored. This and all resource
+implementations are also usable as single-element <a href="#collection">resource
+collections</a>.
 </p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of this resource</td>
-    <td align="center" valign="top">No</td>
+    <td>name</td>
+    <td>The name of this resource</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">exists</td>
-    <td valign="top">Whether this resource exists</td>
-    <td align="center" valign="top">No, default <i>true</i></td>
+    <td>exists</td>
+    <td>Whether this resource exists</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">lastmodified</td>
-    <td valign="top">The last modification time of this resource</td>
-    <td align="center" valign="top">No</td>
+    <td>lastmodified</td>
+    <td>The last modification time of this resource</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">directory</td>
-    <td valign="top">Whether this resource is directory-like</td>
-    <td align="center" valign="top">No, default <i>false</i></td>
+    <td>directory</td>
+    <td>Whether this resource is directory-like</td>
+    <td>No; default <q>false</q></td>
   </tr>
   <tr>
-    <td valign="top">size</td>
-    <td valign="top">The size of this resource</td>
-    <td align="center" valign="top">No</td>
+    <td>size</td>
+    <td>The size of this resource</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>resource</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>resource</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="file">file</a></h4>
+<h4 id="file">file</h4>
 
 <p>Represents a file accessible via local filesystem conventions.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file represented by this resource</td>
-    <td align="center" valign="top">Yes</td>
+    <td>file</td>
+    <td>The file represented by this resource</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">The base directory of this resource.  When this
-      attribute is set, attempts to access the name of the resource
-      will yield a path relative to this location.</td>
-    <td align="center" valign="top">No</td>
+    <td>basedir</td>
+    <td>The base directory of this resource.  When this attribute is set, attempts to access the
+      name of the resource will yield a path relative to this location.</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>file</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>file</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="javaresource">javaresource</a></h4>
+<h4 id="javaresource">javaresource</h4>
 
 <p>Represents a resource loadable via a Java classloader.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the resource.</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the resource.</td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">classpath</td>
-    <td valign="top">the classpath to use when looking up a resource.</td>
-    <td align="center" valign="top">No</td>
+    <td>classpath</td>
+    <td>the classpath to use when looking up a resource.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">classpathref</td>
-    <td valign="top">the classpath to use when looking up a resource,
-      given as <a href="../using.html#references">reference</a>
-      to a <code>&lt;path&gt;</code> defined elsewhere..</td>
-    <td align="center" valign="top">No</td>
+    <td>classpathref</td>
+    <td>the classpath to use when looking up a resource, given
+      as <a href="../using.html#references">reference</a> to a <code>&lt;path&gt;</code> defined
+      elsewhere.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">loaderRef</td>
-    <td valign="top">the name of the loader that is
-      used to load the resource, constructed from the specified classpath.</td>
-    <td align="center" valign="top">No</td>
+    <td>loaderRef</td>
+    <td>the name of the loader that is used to load the resource, constructed from the specified
+      classpath.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">parentFirst</td>
-    <td valign="top">Whether to consult the parent classloader first -
-      the parent classloader most likely is the system classloader -
-      when using a nested classpath.  Defaults
-      to <code>true</code>.<br/>
+    <td>parentFirst</td>
+    <td>Whether to consult the parent classloader first&mdash;the parent classloader most likely
+      is the system classloader&mdash;when using a nested classpath.<br/>
       <em>Since Ant 1.8.0</em></td>
-    <td align="center" valign="top">No</td>
+    <td>No; defaults to <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>javaresource</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>javaresource</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
 <p>The classpath can also be specified as nested classpath element,
-where <b>&lt;classpath&gt;</b> is a <a
-href="../using.html#path">path-like structure</a>.</p>
+where <code>&lt;classpath&gt;</code> is a <a href="../using.html#path">path-like
+structure</a>.</p>
 
+<h4 id="javaconstant">javaconstant</h4>
+<p>Loads the value of a Java constant. As a specialisation
+of <a href="#javaresource">javaresource</a> all of its attributes and nested elements are
+supported. A constant must be specified as <code>public static</code> otherwise it could not be
+loaded.</p>
 
-<h4><a name="javaconstant">javaconstant</a></h4>
-<p>Loads the value of a java constant. As a specialisation of 
-<a href="#javaresource">javaresource</a> all of its attributes and nested elements are
-supported. A constant must be specified as <tt>public static</tt> otherwise it could not be loaded.</p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the resource. Must be specified as full qualified
-      field name.
-    </td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the resource. Must be specified as full qualified
+      field name.</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>javaconstant</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>javaconstant</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 <h5>Examples</h5>
-This loads the value of the constant <tt>VERSION</tt> of the <tt>org.acme.Main</tt> class
-into the <tt>version</tt>-property. The classpath for finding that class is provided via
-nested classpath element.
-<pre><code>&lt;loadresource property=&quot;version&quot;&gt;
-   &lt;javaconstant name=&quot;org.acme.Main.VERSION&quot;&gt;
-     &lt;classpath&gt;
-       &lt;pathelement location=&quot;${acme.lib.dir}&quot;/&gt;
-     &lt;/classpath&gt;
-   &lt;/javaconstant&gt;
- &lt;/loadresource&gt;
-</code></pre>
+<p>This loads the value of the constant <code>VERSION</code> of the <code>org.acme.Main</code>
+class into the <var>version</var>-property. The classpath for finding that class is provided via
+nested <code>classpath</code> element.</p>
+<pre>
+&lt;loadresource property=&quot;version&quot;&gt;
+  &lt;javaconstant name=&quot;org.acme.Main.VERSION&quot;&gt;
+    &lt;classpath&gt;
+      &lt;pathelement location=&quot;${acme.lib.dir}&quot;/&gt;
+    &lt;/classpath&gt;
+  &lt;/javaconstant&gt;
+&lt;/loadresource&gt;</pre>
 
-Create a new file <tt>c:/temp/org.apache.tools.ant.Main.DEFAULT_BUILD_FILENAME</tt> with the content
-of that constant (<tt>build.xml</tt>).
-<pre><code>&lt;copy todir=&quot;c:/temp&quot;&gt;
+<p>Create a new file <samp>c:/temp/org.apache.tools.ant.Main.DEFAULT_BUILD_FILENAME</samp> with
+the content of that constant (<q>build.xml</q>).</p>
+<pre>
+&lt;copy todir=&quot;c:/temp&quot;&gt;
   &lt;javaconstant name=&quot;org.apache.tools.ant.Main.DEFAULT_BUILD_FILENAME&quot;/&gt;
-&lt;/copy&gt;</code></pre>
+&lt;/copy&gt;</pre>
 
+<h4 id="zipentry">zipentry</h4>
 
-<h4><a name="zipentry">zipentry</a></h4>
+<p>Represents an entry in a ZIP archive. The archive can be specified using the archive
+attribute or a nested single-element resource collection.  <code>zipentry</code> only supports
+file system resources as nested elements.</p>
 
-<p>Represents an entry in a ZIP archive. The archive can be specified
-using the archive attribute or a nested single-element resource
-collection.  <code>zipentry</code> only supports file system resources
-as nested elements.</p>
-
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">zipfile or its alias name archive</td>
-    <td valign="top">The zip file containing this resource</td>
-    <td align="center" valign="top">Yes, unless a nested resource
-    collection has been specified.</td>
+    <td>zipfile</td>
+    <td>The zip file containing this resource</td>
+    <td rowspan="2">Yes, unless a nested resource collection has been
+    specified</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the archived resource</td>
-    <td align="center" valign="top">Yes</td>
+    <td>archive</td>
+    <td class="left">alias of <var>zipfile</var></td>
   </tr>
   <tr>
-    <td valign="top">encoding</td>
-    <td valign="top">The encoding of the zipfile</td>
-    <td align="center" valign="top">No;
-      platform default used if unspecified</td>
+    <td>name</td>
+    <td>The name of the archived resource</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>encoding</td>
+    <td>The encoding of the zipfile</td>
+    <td>No; defaults to default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>propertyresource</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>propertyresource</code> defined elsewhere. If specified
+      no other attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="tarentry">tarentry</a></h4>
+<h4 id="tarentry">tarentry</h4>
 
-<p>Represents an entry in a TAR archive.  The archive can be specified
-using the archive attribute or a nested single-element resource
-collection.</p>
+<p>Represents an entry in a TAR archive.  The archive can be specified using the archive
+attribute or a nested single-element resource collection.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">archive</td>
-    <td valign="top">The tar archive containing this resource</td>
-    <td align="center" valign="top">Yes, unless a nested resource
-    collection has been specified.</td>
+    <td>archive</td>
+    <td>The tar archive containing this resource</td>
+    <td>Yes, unless a nested resource
+    collection has been specified</td>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The name of the archived resource</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The name of the archived resource</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<h4><a name="gzipresource">gzipresource</a></h4>
+<h4 id="gzipresource">gzipresource</h4>
 
-<p>This is not a stand-alone resource, but a wrapper around another
-resource providing compression of the resource's contents on the fly.
-A single element resource collection must be specified as a nested
-element.</p>
+<p>This is not a stand-alone resource, but a wrapper around another resource providing
+compression of the resource's contents on the fly.  A single element resource collection must be
+specified as a nested element.</p>
 
-<h4><a name="bzip2resource">bzip2resource</a></h4>
+<h4 id="bzip2resource">bzip2resource</h4>
 
-<p>This is not a stand-alone resource, but a wrapper around another
-resource providing compression of the resource's contents on the fly.
-A single element resource collection must be specified as a nested
-element.</p>
+<p>This is not a stand-alone resource, but a wrapper around another resource providing
+compression of the resource's contents on the fly.  A single element resource collection must be
+specified as a nested element.</p>
 
-<h4><a name="url">url</a></h4>
+<h4 id="xzresource">xzresource</h4>
+
+<p>This is not a stand-alone resource, but a wrapper around another resource providing
+compression of the resource's contents on the fly.  A single element resource collection must be
+specified as a nested element.</p>
+
+<p>XZ compression support has been added <em>since Apache Ant 1.10.1</em> and depends on
+external libraries not included in the Ant
+distribution. See <a href="../install.html#librarydependencies">Library Dependencies</a> for
+more information.</p>
+
+<h4 id="url">url</h4>
 
 <p>Represents a URL.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">url</td>
-    <td valign="top">The url to expose</td>
-    <td rowspan="3" align="center" valign="middle">Exactly one of these</td>
+    <td>url</td>
+    <td>The URL to expose</td>
+    <td rowspan="3">Exactly one of these</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The file to expose as a file: url</td>
+    <td>file</td>
+    <td class="left">The file to expose as a <code>file:</code> URL</td>
   </tr>
   <tr>
-    <td valign="top">baseUrl</td>
-    <td valign="top">The base URL which must be combined with relativePath</td>
+    <td>baseUrl</td>
+    <td class="left">The base URL which must be combined
+    with <var>relativePath</var></td>
  </tr>
   <tr>
-    <td valign="top">relativePath</td>
-    <td valign="top">Relative path that defines the url combined with
-      baseUrl</td>
-    <td align="center" valign="top">If using baseUrl</td>
+    <td>relativePath</td>
+    <td>Relative path that defines the URL when combined with
+      <var>baseUrl</var></td>
+    <td>If using <var>baseUrl</var></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>url</code>
+      a <a href="../using.html#references">reference</a> to
+      an <code>url</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<h4><a name="string">string</a></h4>
+<h4 id="string">string</h4>
 
-<p>Represents a Java String. It can be written to, but only once, after which
-it will be an error to write to again.</p>
+<p>Represents a Java String. It can be written to, but only once, after which it will be an
+error to write to again.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">The value of this resource</td>
-    <td align="center" valign="top">No</td>
+    <td>value</td>
+    <td>The value of this resource</td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>string</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>string</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p>The resource also supports nested text, which can only be supplied if the <code>value</code> attribute is unset:
-  </p>
+<p>The resource also supports nested text, which can only be supplied if the <var>value</var>
+attribute is unset:</p>
 <pre>
-  &lt;string>
-        self.log("Ant version =${ant.version}");
-  &lt;/string>
-</pre>
-    
-</p>
+&lt;string&gt;
+    self.log("Ant version =${ant.version}");
+&lt;/string&gt;</pre>
 
-<h4><a name="propertyresource">propertyresource</a></h4>
+<h4 id="propertyresource">propertyresource</h4>
 
 <p>Represents an Ant property.</p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">The property name</td>
-    <td align="center" valign="top">Yes</td>
+    <td>name</td>
+    <td>The property name</td>
+    <td>Yes</td>
   </tr>
 </table>
 
-<hr>
-<h2><a name="collection">Resource Collections</a></h2>
+<hr/>
+<h2 id="collection">Resource Collections</h2>
 <p>
-A Resource Collection is an abstraction of an entity that groups
-together a number of <a href="#resource">resources</a>. Several of
-Ant's "legacy" datatypes have been modified to behave as Resource Collections:
+A resource collection is an abstraction of an entity that groups together a number
+of <a href="#resource">resources</a>. Several of Ant's "legacy" datatypes have been modified to
+behave as resource collections:
+</p>
 <ul>
   <li><a href="fileset.html">fileset</a>,
     <a href="dirset.html">dirset</a>,
@@ -379,1012 +440,1036 @@
     exposes <a href="#propertyresource">property</a> resources
   </li>
 </ul>
-</p>
-<p>Strangely, some tasks can even legitimately behave as resource collections:
+<p>Strangely, some tasks can even legitimately behave as resource
+collections:</p>
 <ul>
-  <li><a href="../Tasks/concat.html">concat</a>
-    exposes a concatenated resource, and adds e.g.
-    <a href="filterchain.html">filtering</a>
+  <li><a href="../Tasks/concat.html">concat</a> exposes a concatenated
+    resource, and adds e.g.  <a href="filterchain.html">filtering</a>
     to Ant's resource-related capabilities.
   </li>
 </ul>
-</p>
-<h3>The additional built-in resource collections are:</h3>
+<h3>Additional built-in resource collections</h3>
+The additional built-in resource collections are:
 <ul>
-  <li><a href="#resources">resources</a> - generic resource collection</li>
-  <li><a href="#files">files</a> - collection of files similar to
-    <a href="fileset.html">fileset</a></li>
-  <li><a href="#restrict">restrict</a> - restrict a resource collection
-    to include only resources meeting specified criteria</li>
-  <li><a href="#sort">sort</a> - sorted resource collection</li>
-  <li><a href="#first">first</a> - first <i>n</i> resources from a
+  <li><a href="#resources">resources</a>&mdash;generic resource collection</li>
+  <li><a href="#files">files</a>&mdash;collection of files similar
+  to <a href="fileset.html">fileset</a></li>
+  <li><a href="#restrict">restrict</a>&mdash;restrict a resource collection to include only
+  resources meeting specified criteria</li>
+  <li><a href="#sort">sort</a>&mdash;sorted resource collection</li>
+  <li><a href="#first">first</a>&mdash;first <em>n</em> resources from a nested collection</li>
+  <li><a href="#last">last</a>&mdash;last <em>n</em> resources from a nested collection</li>
+  <li><a href="#allbutfirst">allbutfirst</a>&mdash;all except the first <em>n</em> resources
+    from a nested collection</li>
+  <li><a href="#allbutlast">allbutlast</a>&mdash;all except the last <em>n</em> resources from a
     nested collection</li>
-  <li><a href="#last">last</a> - last <i>n</i> resources from a
+  <li><a href="#tokens">tokens</a>&mdash;<a href="#string">string</a> tokens gathered from a
     nested collection</li>
-  <li><a href="#allbutfirst">allbutfirst</a> - all except the
-    first <i>n</i> resources from a nested collection</li>
-  <li><a href="#allbutlast">allbutlast</a> - all except the last <i>n</i>
-    resources from a nested collection</li>
-  <li><a href="#tokens">tokens</a> - <a href="#string">string</a> tokens
-    gathered from a nested collection</li>
-  <li><a href="#union">union</a> - set union of nested resource collections</li>
-  <li><a href="#intersect">intersect</a> - set intersection
-    of nested resource collections</li>
-  <li><a href="#difference">difference</a> - set difference
-    of nested resource collections</li>
-  <li><a href="#mappedresources">mappedresources</a> - generic
-    resource collection wrapper that maps the names of the nested
-    resources using a <a href="mapper.html">mapper</a>.</li>
-  <li><a href="#archives">archives</a> - wraps around different
-    resource collections and treats the nested resources as ZIP or TAR
-    archives that will be extracted on the fly.</li>
-  <li><a href="#resourcelist">resourcelist</a> - a collection of
-    resources whose names have been read from another resource.</li>
+  <li><a href="#union">union</a>&mdash;set union of nested resource collections</li>
+  <li><a href="#intersect">intersect</a>&mdash;set intersection of nested resource
+    collections</li>
+  <li><a href="#difference">difference</a>&mdash;set difference of nested resource
+    collections</li>
+  <li><a href="#mappedresources">mappedresources</a>&mdash;generic resource collection wrapper
+    that maps the names of the nested resources using a <a href="mapper.html">mapper</a>.</li>
+  <li><a href="#archives">archives</a>&mdash;wraps around different resource collections and
+    treats the nested resources as ZIP or TAR archives that will be extracted on the fly.</li>
+  <li><a href="#resourcelist">resourcelist</a>&mdash;a collection of resources whose names have
+    been read from another resource.</li>
 </ul>
-<h4><a name="resources">resources</a></h4>
-<p>A generic resource collection, designed for use with
-  <a href="../using.html#references">references</a>.
-  For example, if a third-party Ant task generates a Resource Collection
-  of an unknown type, it can still be accessed via a
-  <code>&lt;resources&gt;</code> collection. The secondary use of this
-  collection type is as a container of other resource collections,
-  preserving the order of nested collections as well as
-  duplicate resources (contrast with <a href="#union">union</a>).
+
+<h4 id="resources">resources</h4>
+<p>
+A generic resource collection, designed for use
+with <a href="../using.html#references">references</a>.  For example, if a third-party Ant task
+generates a resource collection of an unknown type, it can still be accessed via
+a <code>&lt;resources&gt;</code> collection. The secondary use of this collection type is as a
+container of other resource collections, preserving the order of nested collections as well as
+duplicate resources (contrast with <a href="#union">union</a>).
 </p>
-<blockquote>
-  <table border="1" cellpadding="2" cellspacing="0">
+  <table class="attr">
     <tr>
-      <td valign="top"><b>Attribute</b></td>
-      <td valign="top"><b>Description</b></td>
-      <td align="center" valign="top"><b>Required</b></td>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="top">cache</td>
-      <td valign="top">Whether to cache results.  <em>since Ant 1.8.0</em></td>
-      <td valign="top" align="center">No, default <i>false</i></td>
+      <td>cache</td>
+      <td>Whether to cache results.  <em>since Ant 1.8.0</em></td>
+      <td>No; default <q>false</q></td>
+    </tr>
+    <tr>
+      <td>refid</td>
+      <td>Makes this <code>resourcecollection</code>
+        a <a href="../using.html#references">reference</a> to
+        a <code>resourcecollection</code> defined elsewhere. If
+        specified no other attributes or nested elements are
+        allowed.</td>
+      <td>No</td>
     </tr>
   </table>
-</blockquote>
 
-<h4><a name="files">files</a></h4>
-<p>A group of files. These files are matched by <b>absolute</b> patterns
-  taken from a number of <a href="patternset.html">PatternSets</a>.
-  These can be specified as nested <code>&lt;patternset&gt;</code>
-  elements. In addition, <code>&lt;files&gt;</code> holds an implicit
-  PatternSet and supports the nested <code>&lt;include&gt;</code>,
-  <code>&lt;includesfile&gt;</code>, <code>&lt;exclude&gt;</code>
-  and <code>&lt;excludesfile&gt;</code> elements of PatternSet directly,
-  as well as PatternSet's attributes.
+<h4 id="files">files</h4>
+<p>A group of files. These files are matched by <strong>absolute</strong> patterns taken from a
+number of <a href="patternset.html">PatternSets</a>.  These can be specified as
+nested <code>&lt;patternset&gt;</code> elements. In addition, <code>&lt;files&gt;</code> holds
+an implicit PatternSet and supports the
+nested <code>&lt;include&gt;</code>, <code>&lt;includesfile&gt;</code>, <code>&lt;exclude&gt;</code>
+and <code>&lt;excludesfile&gt;</code> elements of PatternSet directly, as well as PatternSet's
+attributes.
 </p>
-<p><a href="selectors.html">File Selectors</a> are available as nested
-  elements. A file must be selected by all selectors in order to be included;
-  <code>&lt;files&gt;</code> is thus equivalent to an
-  <code>&lt;and&gt;</code> file selector container.
+<p><a href="selectors.html">File Selectors</a> are available as nested elements. A file must be
+selected by all selectors in order to be included; <code>&lt;files&gt;</code> is thus equivalent
+to an <code>&lt;and&gt;</code> file selector container.
 </p>
-<p><b>More simply put</b>, this type is equivalent to a
-  <a href="fileset.html">fileset</a> with no base directory.
-  <b>Please note</b> that without a base directory,
-  filesystem scanning is based entirely on include and exclude patterns.
-  A <a href="selectors.html#filenameselect">filename</a> (or any)
-  selector can <i>only</i> influence the scanning process <i>after</i>
-  the file has been included based on pattern-based selection.
+<p><strong>More simply put</strong>, this type is equivalent
+to <a href="fileset.html">fileset</a> with no base directory.  <strong>Please note</strong> that
+without a base directory, filesystem scanning is based entirely on include and exclude patterns.
+A <a href="selectors.html#filenameselect">filename</a> (or any) selector can <em>only</em>
+influence the scanning process <em>after</em> the file has been included based on pattern-based
+selection.
 </p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">includes</td>
-    <td valign="top">comma- or space-separated list of patterns
-      of files that must be included</td>
-    <td rowspan="2" valign="middle" align="center">At least one of these</td>
+    <td>includes</td>
+    <td>Comma- or space-separated list of patterns of files that must be included</td>
+    <td rowspan="2">At least one of these</td>
   </tr>
   <tr>
-    <td valign="top">includesfile</td>
-    <td valign="top">the name of a file; each line of this file is
-      taken to be an include pattern.</td>
+    <td>includesfile</td>
+    <td class="left">Name of a file; each line of this file is taken to be an include
+    pattern.</td>
   </tr>
   <tr>
-    <td valign="top">excludes</td>
-    <td valign="top">comma- or space-separated list of patterns
-      of files that must be excluded</td>
-    <td rowspan="2" valign="top" align="center">No, default none
-      (except default excludes when true)</td>
+    <td>excludes</td>
+    <td>Comma- or space-separated list of patterns of files that must be excluded</td>
+    <td rowspan="2">No; defaults to default excludes or none if <var>defaultexcludes</var>
+    is <q>no</q></td>
   </tr>
   <tr>
-    <td valign="top">excludesfile</td>
-    <td valign="top">the name of a file; each line of this file is
-      taken to be an exclude pattern.</td>
+    <td>excludesfile</td>
+    <td class="left">Name of a file; each line of this file is taken to be an exclude
+    pattern.</td>
   </tr>
   <tr>
-    <td valign="top">defaultexcludes</td>
-    <td valign="top">Whether
-      <a href="../dirtasks.html#defaultexcludes">default excludes</a>
-      should be used</td>
-    <td valign="top" align="center">No, default <i>true</i></td>
+    <td>defaultexcludes</td>
+    <td>Whether <a href="../dirtasks.html#defaultexcludes">default excludes</a> should be
+      used</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">casesensitive</td>
-    <td valign="top">Whether patterns are case-sensitive</td>
-    <td valign="top" align="center">No, default <i>true</i></td>
+    <td>casesensitive</td>
+    <td>Whether patterns are case-sensitive</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr id="followsymlinks">
+    <td>followsymlinks</td>
+    <td>Whether to follow symbolic links (see note <a href="#symlink">below</a>)</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td valign="top">followsymlinks</td>
-    <td valign="top">Whether to follow symbolic links
-      (see note <a href="#symlink">below</a>)</td>
-    <td valign="top" align="center">No, default <i>true</i></td>
+    <td>refid</td>
+    <td>Makes this <code>files</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>files</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p><a name="symlink"><b>Note</b></a>: All files/directories for which
-the canonical path is different from its path are considered symbolic
-links.  On Unix systems this usually means the file really is a
-symbolic link but it may lead to false results on other
-platforms.
-</p>
+<p id="symlink"><a href="#followsymlinks"><strong>Note</strong></a>: All files/directories for which
+the canonical path is different from its path are considered symbolic links.  On Unix systems this
+usually means the file really is a symbolic link but it may lead to false results on other
+platforms.</p>
 
-<h4><a name="restrict">restrict</a></h4>
-<p>Restricts a nested resource collection using resource selectors:
-<blockquote>
-  <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">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-  <p>Nested resource selectors are used to "narrow down" the included
-    resources, combined via a logical <i>AND</i>. These are patterned 
-    after <a href="selectors.html">file selectors</a> but are, 
-    unsurprisingly, targeted to resources.
-    Several built-in resource selectors are available in the internal
-    <a href="antlib.html">antlib</a>
-    <code>org.apache.tools.ant.types.resources.selectors</code>:
-  </p>
+<h4 id="restrict">restrict</h4>
+<p>Restricts a nested resource collection using resource selectors:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling
+      may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>restrict</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>restrict</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
+<p>Nested resource selectors are used to "narrow down" the included resources, combined via a
+logical <em>AND</em>. These are patterned after <a href="selectors.html">file selectors</a> but
+are, unsurprisingly, targeted to resources.  Several built-in resource selectors are available
+in the
+internal <a href="antlib.html">antlib</a> <code>org.apache.tools.ant.types.resources.selectors</code>:</p>
 
-  <ul>
-    <li><a href="#rsel.name">name</a> - select resources by name.</li>
-    <li><a href="#rsel.exists">exists</a> - select existing resources.</li>
-    <li><a href="#rsel.date">date</a> - select resources by date.</li>
-    <li><a href="#rsel.type">type</a> - select resources by type.</li>
-    <li><a href="#rsel.size">size</a> - select resources by size.</li>
-    <li><a href="#rsel.instanceof">instanceof</a>
-      - select resources by class or Ant datatype.</li>
-    <li><a href="#rsel.and">and</a> - "and" nested resource selectors.</li>
-    <li><a href="#rsel.or">or</a> - "or" nested resource selectors.</li>
-    <li><a href="#rsel.not">not</a> - "not" a nested resource selector.</li>
-    <li><a href="#rsel.none">none</a>
-      - select resources selected by no nested resource selectors.</li>
-    <li><a href="#rsel.majority">majority</a> - select resources selected
-      by a majority of nested resource selectors.</li>
-    <li><a href="selectors.html#modified">modified</a> - select resources which
-      content has changed.</li>
-    <li><a href="selectors.html#containsselect">contains</a> - select resources 
-      containing a particular text string.</li>
-    <li><a href="selectors.html#regexpselect">containsregexp</a> - select
-      resources whose contents match a particular regular expression.</li>
-    <li><a href="#rsel.compare">compare</a> - select resources
-      based on comparison to other resources.</li>
-    <li><a href="selectors.html#readable">readable</a> -
-      Select files (resources must be files) if they are readable.</li>
-    <li><a href="selectors.html#writable">writable</a> -
-      Select files (resources must be files) if they are writable.</li>
-  </ul>
+<ul>
+  <li><a href="#rsel.name">name</a>&mdash;select resources by name.</li>
+  <li><a href="#rsel.exists">exists</a>&mdash;select existing resources.</li>
+  <li><a href="#rsel.date">date</a>&mdash;select resources by date.</li>
+  <li><a href="#rsel.type">type</a>&mdash;select resources by type.</li>
+  <li><a href="#rsel.size">size</a>&mdash;select resources by size.</li>
+  <li><a href="#rsel.instanceof">instanceof</a>&mdash;select resources by class or Ant
+    datatype.</li>
+  <li><a href="#rsel.and">and</a>&mdash;<q>and</q> nested resource selectors.</li>
+  <li><a href="#rsel.or">or</a>&mdash;<q>or</q> nested resource selectors.</li>
+  <li><a href="#rsel.not">not</a>&mdash;<q>not</q> a nested resource selector.</li>
+  <li><a href="#rsel.none">none</a>&mdash;select resources selected by no nested resource
+    selectors.</li>
+  <li><a href="#rsel.majority">majority</a>&mdash;select resources selected by a majority of
+    nested resource selectors.</li>
+  <li><a href="selectors.html#modified">modified</a>&mdash;select resources which content has
+    changed.</li>
+  <li><a href="selectors.html#containsselect">contains</a>&mdash;select resources containing a
+    particular text string.</li>
+  <li><a href="selectors.html#regexpselect">containsregexp</a>&mdash;select resources whose
+    contents match a particular regular expression.</li>
+  <li><a href="#rsel.compare">compare</a>&mdash;select resources based on comparison to other
+    resources.</li>
+  <li><a href="selectors.html#readable">readable</a>&mdash;select files (resources must be
+    files) if they are readable.</li>
+  <li><a href="selectors.html#writable">writable</a>&mdash;select files (resources must be
+    files) if they are writable.</li>
+</ul>
 
-  <h4><a name="rsel.name">name</a></h4>
-  <p>Selects resources by name.</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">name</td>
-      <td valign="top">The name pattern to test using standard Ant
-        patterns.</td>
-      <td valign="top" align="center" rowspan="2">Exactly one of
-        the two</td>
-    </tr>
-    <tr>
-      <td valign="top">regex</td>
-      <td valign="top">The regular expression matching files to select.</td>
-    </tr>
-    <tr>
-      <td valign="top">casesensitive</td>
-      <td valign="top">Whether name comparisons are case-sensitive</td>
-      <td align="center" valign="top">No, default <i>true</i></td>
-    </tr>
-    <tr>
-      <td valign="top">handledirsep</td>
-      <td valign="top">
-        If this is specified, the mapper will treat a \ character in a
-        resource name or name attribute as a / for the purposes of
-        matching.  This attribute can be true or false, the default is
-        false.
-        <em>Since Ant 1.8.0.</em>
-        <td align="center" valign="top">No</td>
-      </tr>
-  </table>
+<h5 id="rsel.name">name</h5>
+<p>Selects resources by name.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>name</td>
+    <td>The name pattern to test using standard Ant patterns.</td>
+    <td rowspan="2">Exactly one of the two</td>
+  </tr>
+  <tr>
+    <td>regex</td>
+    <td class="left">The regular expression matching files to select.</td>
+  </tr>
+  <tr>
+    <td>casesensitive</td>
+    <td>Whether name comparisons are case-sensitive</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>handledirsep</td>
+    <td>
+      If this is specified, the mapper will treat a \ character in a resource name or name
+      attribute as a / for the purposes of matching.  This attribute can be <q>true</q>
+      or <q>false</q>.
+      <em>Since Ant 1.8.0</em>
+    <td>No; default <q>false</q></td>
+  </tr>
+</table>
 
-  <h4><a name="rsel.exists">exists</a></h4>
-  <p>Selects existing resources.</p>
+<h5 id="rsel.exists">exists</h5>
+<p>Selects existing resources.</p>
 
-  <h4><a name="rsel.date">date</a></h4>
-  <p>Selects resources by date.</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">millis</td>
-      <td valign="top">The comparison date/time in ms since January 1, 1970</td>
-      <td rowspan="2" align="center" valign="middle">One of these</td>
-    </tr>
-    <tr>
-      <td valign="top">datetime</td>
-      <td valign="top">The formatted comparison date/time</td>
-    </tr>
-    <tr>
-      <td valign="top">pattern</td>
-      <td valign="top">SimpleDateFormat-compatible pattern
-        for use with the <code>datetime</code> attribute using the
-        current locale</td>
-      <td align="center" valign="top">
-        No, default is "MM/dd/yyyy hh:mm a" using the US locale</td>
-    </tr>
-    <tr>
-      <td valign="top">granularity</td>
-      <td valign="top">The number of milliseconds leeway to use when
-        comparing file modification times. This is needed because not
-        every file system supports tracking the last modified time to
-        the millisecond level.</td>
-      <td align="center" valign="top">No; default varies by platform:
-        FAT filesystems = 2 sec; Unix = 1 sec; NTFS = 1 ms.</td>
-    </tr>
-    <tr>
-      <td valign="top">when</td>
-      <td valign="top">One of "before", "after", "equal"</td>
-      <td align="center" valign="top">No, default "equal"</td>
-    </tr>
-  </table>
+<h5 id="rsel.date">date</h5>
+<p>Selects resources by date.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>millis</td>
+    <td>The comparison date/time in ms since January 1, 1970</td>
+    <td rowspan="2">One of these</td>
+  </tr>
+  <tr>
+    <td>datetime</td>
+    <td class="left">The formatted comparison date/time</td>
+  </tr>
+  <tr>
+    <td>pattern</td>
+    <td>SimpleDateFormat-compatible pattern for use with the <code>datetime</code> attribute
+    using the current locale</td>
+    <td>No; default is <q>MM/dd/yyyy hh:mm a</q> using the US locale</td>
+  </tr>
+  <tr>
+    <td>granularity</td>
+    <td>The number of milliseconds leeway to use when comparing file modification times. This is
+    needed because not every file system supports tracking the last modified time to the
+    millisecond level.</td>
+    <td>No; default varies by platform: FAT filesystems = 2 sec; Unix = 1 sec; NTFS = 1 ms.</td>
+  </tr>
+  <tr>
+    <td>when</td>
+    <td>One of <q>before</q>, <q>after</q>, <q>equal</q></td>
+    <td>No; default <q>equal</q></td>
+  </tr>
+</table>
 
-  <h4><a name="rsel.type">type</a></h4>
-  <p>Selects resources by type (file or directory).</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">type</td>
-      <td valign="top">One of "file", "dir", "any" (since Ant 1.8)</td>
-      <td align="center" valign="top">Yes</td>
-    </tr>
-  </table>
+<h5 id="rsel.type">type</h5>
+<p>Selects resources by type (file or directory).</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>type</td>
+    <td>One of <q>file</q>, <q>dir</q>, <q>any</q> (<em>since Ant 1.8</em>)</td>
+    <td>Yes</td>
+  </tr>
+</table>
 
-  <h4><a name="rsel.size">size</a></h4>
-  <p>Selects resources by size.</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">size</td>
-      <td valign="top">The size to compare</td>
-      <td align="center" valign="top">Yes</td>
-    </tr>
-    <tr>
-      <td valign="top">when</td>
-      <td valign="top">One of "equal", "eq", "greater", "gt", "less", "lt",
-        "ge" (greater or equal), "ne" (not equal), "le" (less or equal)</td>
-      <td align="center" valign="top">No, default "equal"</td>
-    </tr>
-  </table>
+<h5 id="rsel.size">size</h5>
+<p>Selects resources by size.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>size</td>
+    <td>The size to compare</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>when</td>
+    <td>One
+    of <q>equal</q>, <q>eq</q>, <q>greater</q>, <q>gt</q>, <q>less</q>, <q>lt</q>, <q>ge</q>
+    (greater or equal), <q>ne</q> (not equal), <q>le</q> (less or equal)</td>
+    <td>No; default <q>equal</q></td>
+  </tr>
+</table>
 
-  <h4><a name="rsel.instanceof">instanceof</a></h4>
-  <p>Selects resources by type.</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">class</td>
-      <td valign="top">The class of which the resource must be an instance</td>
-      <td rowspan="2" align="center" valign="middle">One of these</td>
-    </tr>
-    <tr>
-      <td valign="top">type</td>
-      <td valign="top">The Ant type that must
-        be assignable from the resource</td>
-    </tr>
-    <tr>
-      <td valign="top">uri</td>
-      <td valign="top">The uri in which <i>type</i> must be defined</td>
-      <td valign="top">No</td>
-    </tr>
-  </table>
+<h5 id="rsel.instanceof">instanceof</h5>
+<p>Selects resources by type.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>class</td>
+    <td>The class of which the resource must be an instance</td>
+    <td rowspan="2">One of these</td>
+  </tr>
+  <tr>
+    <td>type</td>
+    <td class="left">The Ant type that must be assignable from the resource</td>
+  </tr>
+  <tr>
+    <td>uri</td>
+    <td>The URI in which <var>type</var> must be defined</td>
+    <td>No</td>
+  </tr>
+</table>
 
-  <h4><a name="rsel.and">and</a></h4>
-  <p>Selects a resource if it is selected by all nested resource selectors.</p>
+<h5 id="rsel.and">and</h5>
+<p>Selects a resource if it is selected by all nested resource selectors.</p>
 
-  <h4><a name="rsel.or">or</a></h4>
-  <p>Selects a resource if it is selected
-    by at least one nested resource selector.</p>
+<h5 id="rsel.or">or</h5>
+<p>Selects a resource if it is selected by at least one nested resource selector.</p>
 
-  <h4><a name="rsel.not">not</a></h4>
-  <p>Negates the selection result of the single
-    nested resource selector allowed.</p>
+<h5 id="rsel.not">not</h5>
+<p>Negates the selection result of the single nested resource selector allowed.</p>
 
-  <h4><a name="rsel.none">none</a></h4>
-  <p>Selects a resource if it is selected
-    by no nested resource selectors.</p>
+<h5 id="rsel.none">none</h5>
+<p>Selects a resource if it is selected by no nested resource selectors.</p>
 
-  <h4><a name="rsel.majority">majority</a></h4>
-  <p>Selects a resource if it is selected
-    by the majority of nested resource selectors.</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">allowtie</td>
-      <td valign="top">Whether a tie (when there is an even number
-        of nested resource selectors) is considered a majority</td>
-      <td valign="top">No, default <i>true</i></td>
-    </tr>
-  </table>
+<h5 id="rsel.majority">majority</h5>
+<p>Selects a resource if it is selected by the majority of nested resource selectors.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>allowtie</td>
+    <td>Whether a tie (when there is an even number of nested resource selectors) is considered
+      a majority</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+</table>
 
-  <h4><a name="rsel.compare">compare</a></h4>
-  <p>Selects a resource based on its comparison to one or more "control"
-     resources using nested <a href="#rcmp">resource comparators</a>.</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">when</td>
-      <td valign="top">Comparison ("equal"/"eq", "greater"/"gt", "less"/"lt",
-        "le" (less or equal), "ge" (greater or equal), "ne" (not equal).</td>
-      <td valign="top">No, default "equal"</td>
-    </tr>
-    <tr>
-      <td valign="top">against</td>
-      <td valign="top">Quantifier ("all"/"each"/"every", "any"/"some",
-        (exactly) "one", "most"/"majority", "none".</td>
-      <td valign="top">No, default "all"</td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>The resources against which comparisons will be made must be specified
-    using the nested &lt;control&gt; element, which denotes a
-    <a href="#resources">resources</a> collection.</p>
-  <h4>Examples</h4>
-  <p>Assuming the namespace settings
-<pre><code>  rsel="antlib:org.apache.tools.ant.types.resources.selectors"
-  rcmp="antlib:org.apache.tools.ant.types.resources.comparators"
-</code></pre></p>
+<h5 id="rsel.compare">compare</h5>
+<p>Selects a resource based on its comparison to one or more "control" resources using
+nested <a href="#rcmp">resource comparators</a>.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>when</td>
+    <td>Comparison
+    (<q>equal</q>/<q>eq</q>, <q>greater</q>/<q>gt</q>, <q>less</q>/<q>lt</q>, <q>le</q> (less or
+    equal), <q>ge</q> (greater or equal), <q>ne</q> (not equal).</td>
+    <td>No; default <q>equal</q></td>
+  </tr>
+  <tr>
+    <td>against</td>
+    <td>Quantifier (<q>all</q>/<q>each</q>/<q>every</q>, <q>any</q>/<q>some</q>,
+    (exactly) <q>one</q>, <q>most</q>/<q>majority</q>, <q>none</q>.</td>
+    <td>No; default <q>all</q></td>
+  </tr>
+</table>
+<h6>Parameters specified as nested elements</h6>
+<p>The resources against which comparisons will be made must be specified using the nested
+&lt;control&gt; element, which denotes a <a href="#resources">resources</a> collection.</p>
+<h6>Examples</h6>
+<p>Assuming the namespace settings</p>
+<pre>
+rsel="antlib:org.apache.tools.ant.types.resources.selectors"
+rcmp="antlib:org.apache.tools.ant.types.resources.comparators"</pre>
   <pre>
 &lt;restrict&gt;
-  &lt;fileset dir="src" includes="a,b,c,d,e,f,g" /&gt;
+  &lt;fileset dir="src" includes="a,b,c,d,e,f,g"/&gt;
   &lt;rsel:compare when="le" against="all"&gt;
     &lt;control&gt;
-      &lt;resource name="d" /&gt;
+      &lt;resource name="d"/&gt;
     &lt;/control&gt;
-    &lt;rcmp:name /&gt;
+    &lt;rcmp:name/&gt;
   &lt;/rsel:compare&gt;
-&lt;/restrict&gt;
-  </pre>
-  <p>Selects files a, b, c, and d.</p>
-  <pre>
-    &lt;project rsel=&quot;antlib:org.apache.tools.ant.types.resources.selectors&quot;&gt;
-        &lt;macrodef name=&quot;copyFromPath&quot;&gt;
-            &lt;attribute name=&quot;todir&quot;/&gt;
-            &lt;attribute name=&quot;refid&quot;/&gt;
-            &lt;element name=&quot;nested-resource-selectors&quot; optional=&quot;yes&quot; implicit=&quot;true&quot;/&gt;
-            &lt;sequential&gt;
-                &lt;mkdir dir=&quot;@{todir}&quot; taskname=&quot;copyFromPath&quot;/&gt;
-                &lt;copy todir=&quot;@{todir}&quot; taskname=&quot;copyFromPath&quot;&gt;
-                    &lt;restrict&gt;
-                        &lt;path refid=&quot;@{refid}&quot;/&gt;
-                        &lt;rsel:or&gt;
-                            &lt;nested-resource-selectors/&gt;
-                        &lt;/rsel:or&gt;
-                    &lt;/restrict&gt;
-                    &lt;flattenmapper/&gt;
-                &lt;/copy&gt;
-            &lt;/sequential&gt;
-        &lt;/macrodef&gt;
-        &lt;copyFromPath refid=&quot;classpath&quot; todir=&quot;todir&quot;&gt;
-            &lt;rsel:name name=&quot;log4j.properties&quot;/&gt;
-            &lt;rsel:name name=&quot;default.properties&quot;/&gt;
-        &lt;/copyFromPath&gt;
-     &lt;/project&gt;
-  </pre>
-  <p>Creates the <tt>todir</tt> directory and copies (if present) the
-     files <tt>log4j.properties</tt> and <tt>default.properties</tt>
-     from the Classpath (already used while compiling).
-  </p>
+&lt;/restrict&gt;</pre>
+<p>Selects files <samp>a</samp>, <samp>b</samp>, <samp>c</samp>, and <samp>d</samp>.</p>
+<pre>
+&lt;project rsel=&quot;antlib:org.apache.tools.ant.types.resources.selectors&quot;&gt;
+    &lt;macrodef name=&quot;copyFromPath&quot;&gt;
+        &lt;attribute name=&quot;todir&quot;/&gt;
+        &lt;attribute name=&quot;refid&quot;/&gt;
+        &lt;element name=&quot;nested-resource-selectors&quot; optional=&quot;yes&quot; implicit=&quot;true&quot;/&gt;
+        &lt;sequential&gt;
+            &lt;mkdir dir=&quot;@{todir}&quot; taskname=&quot;copyFromPath&quot;/&gt;
+            &lt;copy todir=&quot;@{todir}&quot; taskname=&quot;copyFromPath&quot;&gt;
+                &lt;restrict&gt;
+                    &lt;path refid=&quot;@{refid}&quot;/&gt;
+                    &lt;rsel:or&gt;
+                        &lt;nested-resource-selectors/&gt;
+                    &lt;/rsel:or&gt;
+                &lt;/restrict&gt;
+                &lt;flattenmapper/&gt;
+            &lt;/copy&gt;
+        &lt;/sequential&gt;
+    &lt;/macrodef&gt;
+    &lt;copyFromPath refid=&quot;classpath&quot; todir=&quot;todir&quot;&gt;
+        &lt;rsel:name name=&quot;log4j.properties&quot;/&gt;
+        &lt;rsel:name name=&quot;default.properties&quot;/&gt;
+    &lt;/copyFromPath&gt;
+&lt;/project&gt;</pre>
+<p>Creates the <samp>todir</samp> directory and copies (if present) the
+files <samp>log4j.properties</samp> and <samp>default.properties</samp> from the classpath
+(already used while compiling).</p>
 
-  <pre>
-  &lt;project&gt;
-      &lt;filelist id=&quot;allfiles&quot; dir=&quot;${ant.home}/bin&quot; files=&quot;ant.cmd,foo.txt,ant.bat,bar.txt,ant&quot;/&gt;
-      &lt;restrict id=&quot;missingfiles&quot;&gt;
-          &lt;filelist refid=&quot;allfiles&quot;/&gt;
-          &lt;rsel:not xmlns:rsel=&quot;antlib:org.apache.tools.ant.types.resources.selectors&quot;&gt;
-              &lt;rsel:exists/&gt;
-          &lt;/rsel:not&gt;
-      &lt;/restrict&gt;
-      &lt;echo&gt;These files are missed: ${toString:missingfiles}&lt;/echo&gt;
-  &lt;/project&gt;
-  </pre>
-  <p>The resource collection <i>allfiles</i> defines a list of files which are expected. The restrict
-  <i>missingfiles</i> uses the <tt>&lt;not&gt;&lt;exists&gt;</tt> selector for getting all files
-  which are not present. Finally we use the <i>toString:</i> <a href="../using.html#pathshortcut">pathshortcut</a> for
-  getting them in a readable form: <tt>[echo] These files are missed: ....foo.txt;....bar.txt</tt></p>
+<pre>
+&lt;project&gt;
+    &lt;filelist id=&quot;allfiles&quot; dir=&quot;${ant.home}/bin&quot; files=&quot;ant.cmd,foo.txt,ant.bat,bar.txt,ant&quot;/&gt;
+    &lt;restrict id=&quot;missingfiles&quot;&gt;
+        &lt;filelist refid=&quot;allfiles&quot;/&gt;
+        &lt;rsel:not xmlns:rsel=&quot;antlib:org.apache.tools.ant.types.resources.selectors&quot;&gt;
+            &lt;rsel:exists/&gt;
+        &lt;/rsel:not&gt;
+    &lt;/restrict&gt;
+    &lt;echo&gt;These files are missed: ${toString:missingfiles}&lt;/echo&gt;
+&lt;/project&gt;</pre>
+<p>The resource collection <q>allfiles</q> defines a list of files which are expected. The
+restrict <q>missingfiles</q> uses the <code>&lt;not&gt;&lt;exists&gt;</code> selector for
+getting all files which are not present. Finally we use
+the <code>toString:</code> <a href="../using.html#pathshortcut">pathshortcut</a> for getting
+them in a readable form: <code>[echo] These files are missed: ....foo.txt;....bar.txt</code></p>
 
-</blockquote>
+<h4 id="sort">sort</h4>
 
-<h4><a name="sort">sort</a></h4>
+<p>Sorts a nested resource collection according to the resources' natural order, or by one or
+more nested <a href="#rcmp">resource comparators</a>:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>sort</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>sort</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
+<p>The sort can be controlled and customized by specifying one or more resource
+comparators. Resources can be sorted according to multiple criteria; the first specified is the
+"outermost", while the last specified is the "innermost". Several built-in resource comparators
+are available in the
+internal <a href="antlib.html">antlib</a> <code>org.apache.tools.ant.types.resources.comparators</code>:</p>
+<h5 id="rcmp">Resource Comparators</h5>
+<ul>
+  <li><a href="#rcmp.name">name</a>&mdash;sort resources by name</li>
+  <li><a href="#rcmp.exists">exists</a>&mdash;sort resources by existence</li>
+  <li><a href="#rcmp.date">date</a>&mdash;sort resources by date</li>
+  <li><a href="#rcmp.type">type</a>&mdash;sort resources by type</li>
+  <li><a href="#rcmp.size">size</a>&mdash;sort resources by size</li>
+  <li><a href="#rcmp.content">content</a>&mdash;sort resources by content</li>
+  <li><a href="#rcmp.reverse">reverse</a>&mdash;reverse the natural sort order, or that of a
+    single nested resource comparator</li>
+</ul>
 
-<p>Sorts a nested resource collection according to the resources'
-   natural order, or by one or more nested <a href="#rcmp">resource
-   comparators</a>:</p>
-<blockquote>
-  <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">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-  <p>The sort can be controlled and customized by specifying one or more
-    resource comparators. Resources can be sorted according to multiple
-    criteria; the first specified is the "outermost", while the last
-    specified is the "innermost". Several built-in resource comparators
-    are available in the internal <a href="antlib.html">antlib</a>
-    <code>org.apache.tools.ant.types.resources.comparators</code>:
-  </p>
-  <h4><a name="rcmp">Resource Comparators:</a></h4>
-  <ul>
-    <li><a href="#rcmp.name">name</a> - sort resources by name</li>
-    <li><a href="#rcmp.exists">exists</a> - sort resources by existence</li>
-    <li><a href="#rcmp.date">date</a> - sort resources by date</li>
-    <li><a href="#rcmp.type">type</a> - sort resources by type</li>
-    <li><a href="#rcmp.size">size</a> - sort resources by size</li>
-    <li><a href="#rcmp.content">content</a> - sort resources by content</li>
-    <li><a href="#rcmp.reverse">reverse</a> - reverse the natural sort order,
-      or that of a single nested resource comparator</li>
-  </ul>
+<h6 id="rcmp.name">name</h6>
+<p>Sort resources by name.</p>
 
-  <h4><a name="rcmp.name">name</a></h4>
-  <p>Sort resources by name.</p>
+<h6 id="rcmp.exists">exists</h6>
+<p>Sort resources by existence.  Not existing is considered "less than" existing.</p>
 
-  <h4><a name="rcmp.exists">exists</a></h4>
-  <p>Sort resources by existence.
-    Not existing is considered "less than" existing.</p>
+<h6 id="rcmp.date">date</h6>
+<p>Sort resources by date.</p>
 
-  <h4><a name="rcmp.date">date</a></h4>
-  <p>Sort resources by date.</p>
+<h6 id="rcmp.type">type</h6>
+<p>Sort resources by type (file or directory).  Because directories contain files, they are
+considered "greater".</p>
 
-  <h4><a name="rcmp.type">type</a></h4>
-  <p>Sort resources by type (file or directory).
-    Because directories contain files, they are considered "greater".</p>
+<h6 id="rcmp.size">size</h6>
+<p>Sort resources by size.</p>
 
-  <h4><a name="rcmp.size">size</a></h4>
-  <p>Sort resources by size.</p>
+<h6 id="rcmp.content">content</h6>
+<p>Sort resources by content.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>binary</td>
+    <td>Whether content should be compared in binary mode.  If <q>false</q>, content will be
+    compared without regard to platform-specific line-ending conventions.</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+</table>
 
-  <h4><a name="rcmp.content">content</a></h4>
-  <p>Sort resources by content.</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">binary</td>
-      <td valign="top">Whether content should be compared in binary mode.
-        If <i>false<i>, content will be compared without regard to
-        platform-specific line-ending conventions.</td>
-      <td valign="top">No, default <i>true</i></td>
-    </tr>
-  </table>
+<h6 id="rcmp.reverse">reverse</h6>
+<p>Reverse the natural sort order, or that of a single nested comparator.</p>
 
-  <h4><a name="rcmp.reverse">reverse</a></h4>
-  <p>Reverse the natural sort order, or that of a single nested comparator.</p>
+<h5>Examples</h5>
+<pre>
+&lt;property name=&quot;eol&quot; value=&quot;${line.separator}&quot;/&gt;
+&lt;pathconvert property=&quot;sorted&quot; pathsep=&quot;${eol}&quot;&gt;
+  &lt;sort&gt;
+    &lt;tokens&gt;
+      &lt;string value=&quot;foo bar etc baz&quot;/&gt;
+      &lt;stringtokenizer/&gt;
+    &lt;/tokens&gt;
+  &lt;/sort&gt;
+&lt;/pathconvert&gt;</pre>
+<p>The resource of type string <q>foo bar etc baz</q> is split into four tokens by
+the <code>stringtokenizer</code>. These tokens are sorted and there <code>sorted</code> gets the
+value of <q>bar baz etc foo</q>.</p>
 
-  <h4>Examples</h4>
-  <pre>
-    &lt;property name=&quot;eol&quot; value=&quot;${line.separator}&quot; /&gt;
-    &lt;pathconvert property=&quot;sorted&quot; pathsep=&quot;${eol}&quot;&gt;
-      &lt;sort&gt;
-        &lt;tokens&gt;
-          &lt;string value=&quot;foo bar etc baz&quot; /&gt;
-          &lt;stringtokenizer /&gt;
-        &lt;/tokens&gt;
-      &lt;/sort&gt;
-    &lt;/pathconvert&gt;</pre>
-  <p>The resource of type string &quot;foo bar etc baz&quot; is split into four tokens by 
-  the stringtokenizer. These tokens are sorted and there <i>sorted</i> gets the value
-  of &quot;bar baz etc foo&quot;.</p>
-  
-  <pre>
-    &lt;sort&gt;
-      &lt;fileset dir=&quot;foo&quot; /&gt;
-      &lt;reverse xmlns=&quot;antlib:org.apache.tools.ant.types.resources.comparators&quot;&gt;
-        &lt;date /&gt;
-      &lt;/reverse&gt;
-    &lt;/sort&gt;</pre>
-  <p>This takes all files from <i>foo</i>
-     and sorts them by modification date in reverse order.
-     Because the resource comparators used (<code>&lt;reverse&gt;</code>
-     and <code>&lt;date&gt;</code>) are in an internal antlib
-     their namespace must be set explicitly.
-  </p>
+<pre>
+&lt;sort&gt;
+  &lt;fileset dir=&quot;foo&quot;/&gt;
+  &lt;reverse xmlns=&quot;antlib:org.apache.tools.ant.types.resources.comparators&quot;&gt;
+    &lt;date/&gt;
+  &lt;/reverse&gt;
+&lt;/sort&gt;</pre>
+<p>This takes all files from <samp>foo</samp> and sorts them by modification date in reverse
+order.  Because the resource comparators used (<code>&lt;reverse&gt;</code>
+and <code>&lt;date&gt;</code>) are in an internal antlib their namespace must be set explicitly.
+</p>
 
-</blockquote>
+<h4 id="first">first</h4>
+<p>Includes the first <var>count</var> resources from a nested resource collection.  This can be
+used in conjunction with the <a href="#sort">sort</a> collection, for example, to select the
+first few oldest, largest, etc. resources from a larger collection.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>count</td>
+    <td>The number of resources to include</td>
+    <td>No; default <q>1</q></td>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>first</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>first</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
 
-<h4><a name="first">first</a></h4>
-<p>Includes the first <i>count</i> resources from a nested resource collection.
-This can be used in conjunction with the <a href="#sort">sort</a> collection,
-for example, to select the first few oldest, largest, etc. resources from a
-larger collection.</p>
-<blockquote>
-  <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">count</td>
-      <td valign="top">The number of resources to include</td>
-      <td valign="top" align="center">No, default 1</td>
-    </tr>
-    <tr>
-      <td valign="top">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-</blockquote>
+<h4 id="last">last</h4>
+<p><em>Since Ant 1.7.1</em></p>
+<p>Includes the last <var>count</var> resources from a nested resource collection.  This can be
+used in conjunction with the <a href="#sort">sort</a> collection, for example, to select the
+last few oldest, largest, etc. resources from a larger collection.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>count</td>
+    <td>The number of resources to include</td>
+    <td>No; default <q>1</q></td>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>last</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>last</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
 
-<h4><a name="last">last</a></h4>
-<p>Includes the last <i>count</i> resources from a nested resource collection.
-This can be used in conjunction with the <a href="#sort">sort</a> collection,
-for example, to select the last few oldest, largest, etc. resources from a
-larger collection. <strong>Since Ant 1.7.1</strong>.</p>
-<blockquote>
-  <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">count</td>
-      <td valign="top">The number of resources to include</td>
-      <td valign="top" align="center">No, default 1</td>
-    </tr>
-    <tr>
-      <td valign="top">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-</blockquote>
+<h4 id="allbutfirst">allbutfirst</h4>
+<p><em>Since Ant 1.9.5</em></p>
+<p>Includes all elements except for the first <var>count</var> resources from a nested resource
+collection.  This can be used in conjunction with the <a href="#sort">sort</a> collection, for
+example, to select all but the first few oldest, largest, etc. resources from a larger
+collection.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>count</td>
+    <td>The number of resources to exclude</td>
+    <td>No; default <q>1</q></td>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>allbutfirst</code>
+      a <a href="../using.html#references">reference</a> to
+      an <code>allbutfirst</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
 
-<h4><a name="allbutfirst">allbutfirst</a></h4>
-<p>Includes all elements except for the first <i>count</i> resources
-from a nested resource collection.  This can be used in conjunction
-with the <a href="#sort">sort</a> collection, for example, to select
-all but the first few oldest, largest, etc. resources from a larger
-collection. <strong>Since Ant 1.9.5</strong>.</p>
-<blockquote>
-  <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">count</td>
-      <td valign="top">The number of resources to exclude</td>
-      <td valign="top" align="center">No, default 1</td>
-    </tr>
-    <tr>
-      <td valign="top">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-</blockquote>
+<h4 id="allbutlast">allbutlast</h4>
+<p><em>Since Ant 1.9.5</em></p>
+<p>Includes all elements except for the last <var>count</var> resources from a nested resource
+collection.  This can be used in conjunction with the <a href="#sort">sort</a> collection, for
+example, to select all but the last few oldest, largest, etc. resources from a larger
+collection.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>count</td>
+    <td>The number of resources to exclude</td>
+    <td>No; default <q>1</q></td>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>allbutlast</code>
+      a <a href="../using.html#references">reference</a> to
+      an <code>allbutlast</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
 
-<h4><a name="allbutlast">allbutlast</a></h4>
-<p>Includes all elements except for the last <i>count</i> resources
-from a nested resource collection.  This can be used in conjunction
-with the <a href="#sort">sort</a> collection, for example, to select
-all but the last few oldest, largest, etc. resources from a larger
-collection. <strong>Since Ant 1.9.5</strong>.</p>
-<blockquote>
-  <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">count</td>
-      <td valign="top">The number of resources to exclude</td>
-      <td valign="top" align="center">No, default 1</td>
-    </tr>
-    <tr>
-      <td valign="top">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-</blockquote>
-
-<h4><a name="tokens">tokens</a></h4>
-<p>Includes the <a href="#string">string</a> tokens gathered from a nested
- resource collection. Uses the same tokenizers supported by the
-<a href="filterchain.html#tokenfilter">TokenFilter</a>. Imaginative
-  use of this resource collection can implement equivalents for such Unix
-  functions as <code>sort</code>, <code>grep -c</code>, <code>wc</code> and
-  <code>wc -l</code>.</p>
-<blockquote>
-  <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">encoding</td>
-      <td valign="top">The encoding of the nested resources</td>
-      <td valign="top" align="center">No, default is platform default</td>
-    </tr>
-    <tr>
-      <td valign="top">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  <h4>Parameters specified as nested elements</h4>
-  <ul>
-    <li>A single resource collection is required.</li>
-    <li>One nested tokenizer may be specified.  If omitted, a
-        <a href="filterchain.html#linetokenizer">LineTokenizer</a> will be used.
-    </li>
-  </ul>
-  <h4>Examples</h4>
-  <pre>&lt;concat&gt;
+<h4 id="tokens">tokens</h4>
+<p>Includes the <a href="#string">string</a> tokens gathered from a nested resource collection. Uses
+the same tokenizers supported by
+the <a href="filterchain.html#tokenfilter">TokenFilter</a>. Imaginative use of this resource
+collection can implement equivalents for such Unix functions as <kbd>sort</kbd>, <kbd>grep
+-c</kbd>, <kbd>wc</kbd> and <kbd>wc -l</kbd>.</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>encoding</td>
+    <td>The encoding of the nested resources</td>
+    <td>No; default is default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>tokens</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>tokens</code> defined elsewhere. If specified no other
+      attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+<h5>Parameters specified as nested elements</h5>
+<ul>
+  <li>A single resource collection is required.</li>
+  <li>One nested tokenizer may be specified.  If omitted,
+    a <a href="filterchain.html#linetokenizer">LineTokenizer</a> will be used.
+  </li>
+</ul>
+<h5>Examples</h5>
+<pre>
+&lt;concat&gt;
   &lt;union&gt;
     &lt;sort&gt;
       &lt;tokens&gt;
-        &lt;resources refid="input" /&gt;
-        &lt;linetokenizer includedelims="true" /&gt;
+        &lt;resources refid="input"/&gt;
+        &lt;linetokenizer includedelims="true"/&gt;
       &lt;/tokens&gt;
     &lt;/sort&gt;
   &lt;/union&gt;
-&lt;/concat&gt;
-  </pre>
-  <p>Implements Unix <i>sort -u</i> against resource collection <i>input</i>.</p>
-</blockquote>
+&lt;/concat&gt;</pre>
+<p>Implements Unix <kbd>sort -u</kbd> against resource collection <q>input</q>.</p>
 
-<h4><a name="setlogic">Set operations</a></h4>
-<blockquote>
-  <p>The following resource collections implement set operations:</p>
-  <ul>
-    <li><a href="#union">union</a></li>
-    <li><a href="#intersect">intersect</a></li>
-    <li><a href="#difference">difference</a></li>
-  </ul>
+<h4 id="setlogic">Set operations</h4>
+<p>The following resource collections implement set operations:</p>
+<ul>
+  <li><a href="#union">union</a></li>
+  <li><a href="#intersect">intersect</a></li>
+  <li><a href="#difference">difference</a></li>
+</ul>
 
-  <h4><a name="union">union</a></h4>
-  <p>Union of nested resource collections.</p>
+<h4 id="union">union</h4>
+<p>Union of nested resource collections.</p>
 
-  <h4><a name="intersect">intersect</a></h4>
-  <p>Intersection of nested resource collections.</p>
+<p>The only supported attribute is <code>refid</code> which makes this
+  <code>union</code>
+  a <a href="../using.html#references">reference</a> to
+  an <code>union</code> defined elsewhere. If specified no other
+  attributes or nested elements are allowed.</p>
 
-  <h4><a name="difference">difference</a></h4>
-  <p>Difference of nested resource collections.</p>
+<h4 id="intersect">intersect</h4>
+<p>Intersection of nested resource collections.</p>
 
-  <p>The following attributes apply to all set-operation resource collections:
-  </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">cache</td>
-      <td valign="top">Whether to cache results; disabling
-        may seriously impact performance</td>
-      <td valign="top" align="center">No, default <i>true</i></td>
-    </tr>
-  </table>
-  
-  <h4>Examples</h4>
-  <pre>
-    &lt;resources id=&quot;A&quot;&gt;
-        &lt;string value=&quot;a&quot;/&gt;
-        &lt;string value=&quot;b&quot;/&gt;
-    &lt;/resources&gt;
-    &lt;resources id=&quot;B&quot;&gt;
-        &lt;string value=&quot;b&quot;/&gt;
-        &lt;string value=&quot;c&quot;/&gt;
-    &lt;/resources&gt;
-    &lt;union id=&quot;union&quot;&gt;&lt;resources refid=&quot;A&quot;/&gt;&lt;resources refid=&quot;B&quot;/&gt;&lt;/union&gt;
-    &lt;intersect id=&quot;intersect&quot;&gt;&lt;resources refid=&quot;A&quot;/&gt;&lt;resources refid=&quot;B&quot;/&gt;&lt;/intersect&gt;
-    &lt;difference id=&quot;difference&quot;&gt;&lt;resources refid=&quot;A&quot;/&gt;&lt;resources refid=&quot;B&quot;/&gt;&lt;/difference&gt;
-    &lt;echo&gt;
-      A: ${toString:A}                    = a;b
-      B: ${toString:B}                    = b;c
+<p>The only supported attribute is <code>refid</code> which makes this
+  <code>intersect</code>
+  a <a href="../using.html#references">reference</a> to
+  an <code>intersect</code> defined elsewhere. If specified no other
+  attributes or nested elements are allowed.</p>
 
-      union     : ${toString:union}       = a;b;c
-      intersect : ${toString:intersect}   = b
-      difference: ${toString:difference}  = a;c
-    &lt;/echo&gt;
-  </pre>
-</blockquote>
+<h4 id="difference">difference</h4>
+<p>Difference of nested resource collections.</p>
 
-<h4><a name="mappedresources">mappedresources</a></h4>
+<p>The following attributes apply to all set-operation resource collections:</p>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; disabling may seriously impact performance</td>
+    <td>No; default <q>true</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>difference</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>difference</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
+
+<h5>Examples</h5>
+<pre>
+&lt;resources id=&quot;A&quot;&gt;
+    &lt;string value=&quot;a&quot;/&gt;
+    &lt;string value=&quot;b&quot;/&gt;
+&lt;/resources&gt;
+&lt;resources id=&quot;B&quot;&gt;
+    &lt;string value=&quot;b&quot;/&gt;
+    &lt;string value=&quot;c&quot;/&gt;
+&lt;/resources&gt;
+&lt;union id=&quot;union&quot;&gt;&lt;resources refid=&quot;A&quot;/&gt;&lt;resources refid=&quot;B&quot;/&gt;&lt;/union&gt;
+&lt;intersect id=&quot;intersect&quot;&gt;&lt;resources refid=&quot;A&quot;/&gt;&lt;resources refid=&quot;B&quot;/&gt;&lt;/intersect&gt;
+&lt;difference id=&quot;difference&quot;&gt;&lt;resources refid=&quot;A&quot;/&gt;&lt;resources refid=&quot;B&quot;/&gt;&lt;/difference&gt;
+&lt;echo&gt;
+  A: ${toString:A}                    = a;b
+  B: ${toString:B}                    = b;c
+
+  union     : ${toString:union}       = a;b;c
+  intersect : ${toString:intersect}   = b
+  difference: ${toString:difference}  = a;c
+&lt;/echo&gt;</pre>
+
+<h4 id="mappedresources">mappedresources</h4>
 
 <p><em>Since Ant 1.8.0</em></p>
 
-<p>Wraps another resource collection and maps the names of the nested
-  resources using a <a href="mapper.html">mapper</a>.</p>
+<p>Wraps another resource collection and maps the names of the nested resources using
+a <a href="mapper.html">mapper</a>.</p>
 
-<p>Even if <em>mappedresources</em> wraps a resource collection that
-  consists of file-system based resources, <em>mappedresources</em>
-  will not appear to be file-system based.  This means you can't
-  use <em>mappedresources</em> with tasks that only allow file-system
-  based resources.</p>
+<p>Even if <var>mappedresources</var> wraps a resource collection that consists of file-system
+based resources, <var>mappedresources</var> will not appear to be file-system based.  This means
+you can't use <var>mappedresources</var> with tasks that only allow file-system based
+resources.</p>
 
-<blockquote>
-  <h4>Parameters specified as attributes</h4>
+<h5>Parameters specified as attributes</h5>
 
-  <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">cache</td>
-      <td valign="top">Whether to cache results; enabling
-        may improve performance.  <em>Since Ant 1.8.1</em></td>
-      <td valign="top" align="center">No, default <i>false</i></td>
-    </tr>
-    <tr>
-      <td valign="top">enablemultiplemappings</td>
-      <td valign="top">
-        If true the the collection will use all the mappings for a
-        given source path. If false the it will only process the first
-        resource.
-        <em>since Ant 1.8.1</em>.</td>
-      <td align="center">No - defaults to false.</td>
-    </tr>
-  </table>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>cache</td>
+    <td>Whether to cache results; enabling may improve performance.  <em>Since Ant
+      1.8.1</em></td>
+    <td>No; default <q>false</q></td>
+  </tr>
+  <tr>
+    <td>enablemultiplemappings</td>
+    <td>If <q>true</q> the collection will use all the mappings for a given source
+      path. If <q>false</q> it will only process the first resource.
+      <em>since Ant 1.8.1</em></td>
+    <td>No; defaults to <q>false</q></td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>mappedresources</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>mappedresources</code> defined elsewhere. If specified
+      no other attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
 
-  <h4>Parameters specified as nested elements</h4>
-  <p>A single resource collection is required.</p>
-  <p>A single <a href="mapper.html">mapper</a> can be used to map
-    names.  If no mapper has been given (which doesn't make any sense,
-    honestly), an identity mapper will be used.</p>
+<h5>Parameters specified as nested elements</h5>
+<p>A single resource collection is required.</p>
+<p>A single <a href="mapper.html">mapper</a> can be used to map names.  If no mapper has been
+given (which doesn't make any sense, honestly), an identity mapper will be used.</p>
 
-  <h4>Examples</h4>
+<h5>Examples</h5>
 
-  <p>Copies all files from a given directory to a target directory
-    adding ".bak" as an extension.  Note this could be done with a
-    <em>mapper</em> nested into <em>copy</em> directly as well.</p>
+<p>Copies all files from a given directory to a target directory adding <samp>.bak</samp> as an
+extension.  Note this could be done with a <code>mapper</code> nested into <code>copy</code>
+directly as well.</p>
 
-  <pre>
-    &lt;copy todir="${target}"&gt;
-      &lt;mappedresources&gt;
-        &lt;fileset dir="${src}"/&gt;
-        &lt;globmapper from="*" to="*.bak"/&gt;
-      &lt;/mappedresources&gt;
-    &lt;/copy&gt;
-  </pre>
+<pre>
+&lt;copy todir="${target}"&gt;
+  &lt;mappedresources&gt;
+    &lt;fileset dir="${src}"/&gt;
+    &lt;globmapper from="*" to="*.bak"/&gt;
+  &lt;/mappedresources&gt;
+&lt;/copy&gt;</pre>
 
-  <p>Creates a WAR archive adding all CLASSPATH entries that are files
-    to the <code>WEB-INF/lib</code> directory without keeping their
-    files-system structure.</p>
+<p>Creates a WAR archive adding all <code>CLASSPATH</code> entries that are files to
+the <samp>WEB-INF/lib</samp> directory without keeping their files-system structure.</p>
 
-  <pre>
-    &lt;war destfile="${output}"&gt;
-      &lt;mappedresources&gt;
-        &lt;restrict&gt;
-          &lt;path path="${java.class.path}"/&gt;
-          &lt;type type="file"/&gt;
-        &lt;/restrict&gt;
-        &lt;chainedmapper&gt;
-          &lt;flattenmapper/&gt;
-          &lt;globmapper from="*" to="WEB-INF/lib/*"/&gt;
-        &lt;/chainedmapper&gt;
-      &lt;/mappedresources&gt;
-    &lt;/war&gt;
-  </pre>    
-</blockquote>
+<pre>
+&lt;war destfile="${output}"&gt;
+  &lt;mappedresources&gt;
+    &lt;restrict&gt;
+      &lt;path path="${java.class.path}"/&gt;
+      &lt;type type="file"/&gt;
+    &lt;/restrict&gt;
+    &lt;chainedmapper&gt;
+      &lt;flattenmapper/&gt;
+      &lt;globmapper from="*" to="WEB-INF/lib/*"/&gt;
+    &lt;/chainedmapper&gt;
+  &lt;/mappedresources&gt;
+&lt;/war&gt;</pre>
 
-<h4><a name="archives">archives</a></h4>
+<h4 id="archives">archives</h4>
 
 <p><em>Since Ant 1.8.0</em></p>
 
-<p>This resource collection accepts an arbitrary number of nested
-  resources and assumes that all those resources must be either ZIP or
-  TAR archives.  The resources returned
-  by <code>&lt;archives&gt;</code> are the contents of the nested
-  archives.</p>
+<p>This resource collection accepts an arbitrary number of nested resources and assumes that all
+those resources must be either ZIP or TAR archives.  The resources returned
+by <code>&lt;archives&gt;</code> are the contents of the nested archives.</p>
 
 <p>This resource collection is a generalization
-  of <a href="../Tasks/zip.html#zipgroupfileset">zipgroupfileset</a>
-  which is only supported by the zip family of tasks.</p>
+of <a href="../Tasks/zip.html#zipgroupfileset">zipgroupfileset</a> which is only supported by
+the zip family of tasks.</p>
 
-<p><em>archives</em> doesn't support any attributes.</p>
+<p>The only supported attribute is <code>refid</code> which makes this
+  <code>archives</code>
+  a <a href="../using.html#references">reference</a> to
+  an <code>archives</code> defined elsewhere. If specified no other
+  attributes or nested elements are allowed.</p>
 
-<blockquote>
-  <h4>Parameters specified as nested elements</h4>
+<h5>Parameters specified as nested elements</h5>
 
-  <p><code>&lt;archives&gt;</code> has two nested
-    elements <code>&lt;zips&gt;</code> and
-    <code>&lt;tars&gt;</code> that are <a href="#union">unions</a>
-    themselves, i.e. they accept arbitrary many resource(collection)s
-    as nested elements.</p>
+<p><code>&lt;archives&gt;</code> has two nested elements <code>&lt;zips&gt;</code>
+and <code>&lt;tars&gt;</code> that are <a href="#union">unions</a> themselves, i.e. they accept
+arbitrary many resource(collection)s as nested elements.</p>
 
-  <p>The nested resources of &lt;zips&gt; are treated as ZIP archives,
-    the nested resources of &lt;tars&gt; as TAR archives.</p>
+<p>The nested resources of <code>&lt;zips&gt;</code> are treated as ZIP archives, the nested
+resources of <code>&lt;tars&gt;</code> as TAR archives.</p>
 
-  <h4>Examples</h4>
+<h5>Examples</h5>
 
-  <p>Copies all files from all jars that are on the classpath
-    to <code>${target}</code>.</p>
+<p>Copies all files from all jars that are on the classpath to <samp>${target}</samp>.</p>
 
-  <pre>
-    &lt;copy todir="${target}"&gt;
-      &lt;archives&gt;
-        &lt;zips&gt;
-          &lt;restrict&gt;
-            &lt;path path="${java.class.path}"/&gt;
-            &lt;name name="*.jar"/&gt;
-          &lt;/restrict&gt;
-        &lt;/zips&gt;
-      &lt;/archives&gt;
-    &lt;/copy&gt;
-  </pre>
-</blockquote>
+<pre>
+&lt;copy todir="${target}"&gt;
+  &lt;archives&gt;
+    &lt;zips&gt;
+      &lt;restrict&gt;
+        &lt;path path="${java.class.path}"/&gt;
+        &lt;name name="*.jar"/&gt;
+      &lt;/restrict&gt;
+    &lt;/zips&gt;
+  &lt;/archives&gt;
+&lt;/copy&gt;</pre>
 
-<h4><a name="resourcelist">resourcelist</a></h4>
+<h4 id="resourcelist">resourcelist</h4>
 
 <p><em>Since Ant 1.8.0</em></p>
 
-<p>This resource collection accepts an arbitrary number of nested
-  resources, reads those resources and returns a resource for each
-  line read.</p>
+<p>This resource collection accepts an arbitrary number of nested resources, reads those
+resources and returns a resource for each line read.</p>
 
-<p>If the line contains a colon, Ant will try to use it as an URL and
-  if that fails (or the line doesn't contain a colon) will return a
-  file resource with the line's content as its name.</p>
+<p>If the line contains a colon, Ant will try to use it as an URL and if that fails (or the line
+doesn't contain a colon) will return a file resource with the line's content as its name.</p>
 
-<p>Properties will be expanded for each line.  If the property
-  expansion yields a resource object rather than a string (for example
-  because of custom property helpers), the resources will be returned
-  directly.</p>
+<p>Properties will be expanded for each line.  If the property expansion yields a resource
+object rather than a string (for example because of custom property helpers), the resources will
+be returned directly.</p>
 
 <p><code>&lt;resourcelist&gt;</code> is a generalization
-  of <a href="filelist.html"><code>&lt;filelist&gt;</code></a>.</p>
+of <a href="filelist.html"><code>&lt;filelist&gt;</code></a>.</p>
 
-<blockquote>
-  <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">encoding</td>
-      <td valign="top">The encoding of the nested resources</td>
-      <td valign="top" align="center">No, default is platform default</td>
-    </tr>
-    <tr>
-      <td valign="top">basedir</td>
-      <td valign="top">Base directory that is used to resolve
-        relative file names against. Is also used to provide a base
-        directory to the FileResources created by this resource
-        collection. <em>Since Ant 1.9.12</em>
-      </td>
-      <td valign="top" align="center">No</td>
-    </tr>
-  </table>
-</blockquote>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>encoding</td>
+    <td>The encoding of the nested resources</td>
+    <td>No; default is default JVM character encoding</td>
+  </tr>
+  <tr>
+    <td>basedir</td>
+    <td>Base directory that is used to resolve relative file names
+      against. Is also used to provide a base directory to the
+      FileResources created by this resource collection. <em>Since Ant
+      1.10.4</em>
+    </td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>preserveduplicates</td>
+    <td>Makes this <code>resourcelist</code> return all resources as
+      many times as they are specified. Otherwise
+      <code>resourcelist</code> will only return each resource, in the
+      order they first appear. <em>Since Ant 1.10.10</em></td>
+    <td>No</td>
+  </tr>
+  <tr>
+    <td>refid</td>
+    <td>Makes this <code>resourcelist</code>
+      a <a href="../using.html#references">reference</a> to
+      a <code>resourcelist</code> defined elsewhere. If specified no
+      other attributes or nested elements are allowed.</td>
+    <td>No</td>
+  </tr>
+</table>
 
-<blockquote>
-  <h4>Parameters specified as nested elements</h4>
+<h5>Parameters specified as nested elements</h5>
 
-  <p><code>&lt;resourcelist&gt;</code> accepts arbitrary many
-    resource(collection)s as nested elements.</p>
+<p><code>&lt;resourcelist&gt;</code> accepts arbitrary many resource(collection)s as nested
+elements.</p>
 
-  <p>In addition <code>&lt;resourcelist&gt;</code> supports
-    nested <code>&lt;filterchain&gt;</code> elements that can be used
-    to filter/modify the read resources before their lines get
-    expanded.  Such a nested element corresponds to
-    a <a href="filterchain.html">filterchain</a>.</p>
+<p>In addition <code>&lt;resourcelist&gt;</code> supports
+nested <code>&lt;filterchain&gt;</code> elements that can be used to filter/modify the read
+resources before their lines get expanded.  Such a nested element corresponds to
+a <a href="filterchain.html">filterchain</a>.</p>
 
-  <h4>Examples</h4>
+<h5>Examples</h5>
 
-  <p>The following example copies a file from the first URL of
-    several alternatives that can actually be reached.  It assumes
-    that the file mirrors.txt looks like</p>
+<p>The following example copies a file from the first URL of several alternatives that can
+actually be reached.  It assumes that the file <samp>mirrors.txt</samp> looks like</p>
 
-  <pre>
+<pre>
     mirrors.txt:
-http://best.mirror.example.org/
+https://best.mirror.example.org/
 http://second.best.mirror.example.org/mirror/of/best/
 https://yet.another.mirror/
-http://the.original.site/
-  </pre>
-    
-  <pre>
-    &lt;copy todir="${target}"&gt;
-      &lt;first&gt;
-        &lt;restrict&gt;
-          &lt;resourcelist&gt;
-            &lt;file file="mirrors.txt"/&gt;
-          &lt;/resourcelist&gt;
-          &lt;exists/&gt;
-        &lt;/restrict&gt;
-      &lt;/first&gt;
-    &lt;/copy&gt;
-  </pre>
-</blockquote>
+https://the.original.site/</pre>
+
+<pre>
+&lt;copy todir="${target}"&gt;
+  &lt;first&gt;
+    &lt;restrict&gt;
+      &lt;resourcelist&gt;
+        &lt;file file="mirrors.txt"/&gt;
+      &lt;/resourcelist&gt;
+      &lt;exists/&gt;
+    &lt;/restrict&gt;
+  &lt;/first&gt;
+&lt;/copy&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Types/selectors-program.html b/manual/Types/selectors-program.html
index 074a542..47d4dcb 100644
--- a/manual/Types/selectors-program.html
+++ b/manual/Types/selectors-program.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,11 +15,10 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
   <head>
-    <meta http-equiv="Content-Language" content="en-us">
     <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>Programming Selectors in Apache Ant</title>
+    <title>Programming Selectors in Apache Ant</title>
   </head>
 
   <body>
@@ -28,138 +28,119 @@
 
     <p>Want to define your own selectors? It's easy!</p>
 
-    <p>First, pick the type of selector that you want to define. There
-    are three types, and a recipe for each one follows. Chances are
-    you'll want to work with the first one, Custom Selectors.</p>
+    <p>First, pick the type of selector that you want to define. There are three types, and a
+    recipe for each one follows. Chances are you'll want to work with the first one, Custom
+    Selectors.</p>
 
     <ol>
       <li>Custom Selectors
 
-        <p>This is the category that Apache Ant provides specifically for you to
-        define your own Selectors. Anywhere you want to use your selector
-        you use the <code>&lt;custom&gt;</code> element and specify
-        the class name of your selector within it. See the
-        <a href="selectors.html#customselect">Custom Selectors</a>
-        section of the Selector page for details. The
-        <code>&lt;custom&gt;</code> element can be used anywhere
-        the core selectors can be used. It can be contained within
-        <a href="selectors.html#selectcontainers">Selector Containers</a>,
-        for example.</p>
+        <p>This is the category that Apache Ant provides specifically for you to define your own
+        Selectors. Anywhere you want to use your selector you use
+        the <code>&lt;custom&gt;</code> element and specify the class name of your selector
+        within it. See the <a href="selectors.html#customselect">Custom Selectors</a> section of
+        the Selector page for details. The <code>&lt;custom&gt;</code> element can be used
+        anywhere the core selectors can be used. It can be contained
+        within <a href="selectors.html#selectcontainers">Selector Containers</a>, for
+        example.</p>
 
         <p>To create a new Custom Selector, you have to create a class that
-        implements
-        <code>org.apache.tools.ant.types.selectors.ExtendFileSelector</code>.
-        The easiest way to do that is through the convenience base class
-        <code>org.apache.tools.ant.types.selectors.BaseExtendSelector</code>,
-        which provides all of the methods for supporting
-        <code>&lt;param&gt;</code> tags. First, override the
-        <code>isSelected()</code> method, and optionally the
-        <code>verifySettings()</code> method. If your custom
-        selector requires parameters to be set, you can also override
-        the <code>setParameters()</code> method and interpret the
-        parameters that are passed in any way you like. Several of the
-        core selectors demonstrate how to do that because they can
-        also be used as custom selectors.</p>
+        implements <code class="code">org.apache.tools.ant.types.selectors.ExtendFileSelector</code>.
+        The easiest way to do that is through the convenience base
+        class <code class="code">org.apache.tools.ant.types.selectors.BaseExtendSelector</code>,
+        which provides all of the methods for supporting <code>&lt;param&gt;</code> tags. First,
+        override the <code class="code">isSelected()</code> method, and optionally
+        the <code class="code">verifySettings()</code> method. If your custom selector requires
+        parameters to be set, you can also override the <code class="code">setParameters()</code>
+        method and interpret the parameters that are passed in any way you like. Several of the core
+        selectors demonstrate how to do that because they can also be used as custom selectors.</p>
 
       <li>Core Selectors
 
-        <p>These are the selectors used by Ant itself. To implement one of
-        these, you will have to alter some of the classes contained within
-        Ant.</p>
+        <p>These are the selectors used by Ant itself. To implement one of these, you will have
+        to alter some of the classes contained within Ant.</p>
 
         <ul>
-          <li><p>First, create a class that implements
-            <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
-            You can either choose to implement all methods yourself from
-            scratch, or you can extend
-            <code>org.apache.tools.ant.types.selectors.BaseSelector</code>
-            instead, a convenience class that provides reasonable default
-            behaviour for many methods.</p>
+          <li><p>First, create a class that
+            implements <code class="code">org.apache.tools.ant.types.selectors.FileSelector</code>.
+            You can either choose to implement all methods yourself from scratch, or you can
+            extend <code class="code">org.apache.tools.ant.types.selectors.BaseSelector</code>
+            instead, a convenience class that provides reasonable default behaviour for many
+            methods.</p>
 
-            <p>There is only one method required.
-            <code>public boolean isSelected(File basedir, String filename,
-              File file)</code>
-              is the real purpose of the whole exercise. It returns true
-              or false depending on whether the given file should be
-              selected from the list or not.</p>
+            <p>There is only one method required.  <code class="code">public boolean isSelected(File
+            basedir, String filename, File file)</code> is the real purpose of the whole
+            exercise. It returns <q>true</q> or <q>false</q> depending on whether the given file
+            should be selected from the list or not.</p>
 
-            <p>If you are using
-            <code>org.apache.tools.ant.types.selectors.BaseSelector</code>
-            there are also some predefined behaviours you can take advantage
-            of. Any time you encounter a problem when setting attributes or
-            adding tags, you can call setError(String errmsg) and the class
-            will know that there is a problem. Then, at the top of your
-            <code>isSelected()</code> method call <code>validate()</code> and
-            a BuildException will be thrown with the contents of your error
-            message. The <code>validate()</code> method also gives you a
-            last chance to check your settings for consistency because it
-            calls <code>verifySettings()</code>. Override this method and
-            call <code>setError()</code> within it if you detect any
-            problems in how your selector is set up.</p>
+            <p>If you are
+            using <code class="code">org.apache.tools.ant.types.selectors.BaseSelector</code> there
+            are also some predefined behaviours you can take advantage of. Any time you encounter a
+            problem when setting attributes or adding tags, you can
+            call <code class="code">setError(String errmsg)</code> and the class will know that
+            there is a problem. Then, at the top of your <code class="code">isSelected()</code>
+            method call <code class="code">validate()</code> and a <code>BuildException</code> will
+            be thrown with the contents of your error
+            message. The <code class="code">validate()</code> method also gives you a last chance to
+            check your settings for consistency because it
+            calls <code class="code">verifySettings()</code>. Override this method and
+            call <code class="code">setError()</code> within it if you detect any problems in how
+            your selector is set up.</p>
 
-            <p>You may also want to override <code>toString()</code>.</p>
+            <p>You may also want to override <code class="code">toString()</code>.</p></li>
 
-          <li><p>Put an <code>add</code> method for your selector in
-            <code>org.apache.tools.ant.types.selectors.SelectorContainer</code>.
-            This is an interface, so you will also have to add an implementation
-            for the method in the classes which implement it, namely
-            <code>org.apache.tools.ant.types.AbstractFileSet</code>,
-            <code>org.apache.tools.ant.taskdefs.MatchingTask</code> and
-            <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
-            Once it is in there, it will be available everywhere that core
-            selectors are appropriate.</p>
+          <li>Put an <code class="code">add()</code> method for your selector
+            in <code class="code">org.apache.tools.ant.types.selectors.SelectorContainer</code>.
+            This is an interface, so you will also have to add an implementation for the method in
+            the classes which implement it,
+            namely <code class="code">org.apache.tools.ant.types.AbstractFileSet</code>, <code class="code">org.apache.tools.ant.taskdefs.MatchingTask</code>
+            and <code class="code">org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
+            Once it is in there, it will be available everywhere that core selectors are
+            appropriate.</li>
         </ul>
 
       <li>Selector Containers
-        <p>Got an idea for a new Selector Container? Creating a new one is
-        no problem:</p>
+        <p>Got an idea for a new Selector Container? Creating a new one is no problem:</p>
         <ul>
-          <li><p>Create a new class that implements
-            <code>org.apache.tools.ant.types.selectors.SelectorContainer</code>.
-            This will ensure that your new
-            Container can access any new selectors that come along. Again, there
-            is a convenience class available for you called
-            <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
-            </p>
-          <li><p>Implement the
-            <code>public boolean isSelected(String filename, File file)</code>
-            method to do the right thing. Chances are you'll want to iterate
-            over the selectors under you, so use
-            <code>selectorElements()</code> to get an iterator that will do
-            that.</p>
-          <li><p>Again, put an <code>add</code> method for your container in
-            <code>org.apache.tools.ant.types.selectors.SelectorContainer</code>
-            and its implementations
-            <code>org.apache.tools.ant.types.AbstractFileSet</code> and
-            <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
-            </p>
+          <li>Create a new class that
+            implements <code class="code">org.apache.tools.ant.types.selectors.SelectorContainer</code>.
+            This will ensure that your new Container can access any new selectors that come
+            along. Again, there is a convenience class available for you
+            called <code class="code">org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.</li>
+          <li>Implement the <code class="code">public boolean isSelected(String filename, File
+            file)</code> method to do the right thing. Chances are you'll want to iterate over the
+            selectors under you, so use <code class="code">selectorElements()</code> to get an
+            iterator that will do that.</li>
+          <li>Again, put an <code class="code">add()</code> method for your container
+            in <code class="code">org.apache.tools.ant.types.selectors.SelectorContainer</code> and
+            its implementations <code class="code">org.apache.tools.ant.types.AbstractFileSet</code>
+            and <code class="code">org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.</li>
         </ul>
     </ol>
 
     <h3>Testing Selectors</h3>
 
-    <p>For a robust component (and selectors are (Project)Components) tests are
-    necessary. For testing Tasks we use JUnit TestCases - more specific
-    <tt>org.apache.tools.ant.BuildFileRule extends org.junit.rules.ExternalResource</tt>.
-    Some of its features like configure the (test) project by reading its buildfile and
-    execute targets we need for selector tests also. Therefore we use that BuildFileRule.
-    But testing selectors requires some more work: having a set of files, instantiate
-    and configure the selector, check the selection work and more. Because we usually
-    extend <tt>BaseExtendSelector</tt> its features have to be tested also (e.g. setError()).
-    </p>
+    <p>For a robust component (and selectors are (Project)Components) tests are necessary. For
+    testing Tasks we use JUnit Tests and Rules&mdash;more
+    specific <code class="code">org.apache.tools.ant.BuildFileRule extends
+    org.junit.rules.ExternalResource</code>.  Some of its features like configure the (test) project
+    by reading its buildfile and execute targets we need for selector tests also. Therefore we use
+    that BuildFileRule.  But testing selectors requires some more work: having a set of files,
+    instantiate and configure the selector, check the selection work and more. Because we usually
+    extend <code class="code">BaseExtendSelector</code> its features have to be tested also
+    (e.g. <code class="code">setError()</code>).</p>
 
-    <p>That's why we have a test rule for doing our selector tests:
-    <tt>org.apache.tools.ant.types.selectors.BaseSelectorRule</tt>.</p>
+    <p>That's why we have a test rule for doing our selector
+    tests: <code class="code">org.apache.tools.ant.types.selectors.BaseSelectorRule</code>.</p>
 
-    <p>This class extends ExternalResource and therefore can included in the set of Ant's
-    unit tests. It holds an instance of preconfigured BuildFileRule. Configuration
-    is done by parsing the src/etc/testcases/types/selectors.xml. BaseSelectorRule
-    then gives us helper methods for handling multiple selections. </p>
+    <p>This class extends ExternalResource and therefore can included in the set of Ant's unit
+    tests. It holds an instance of preconfigured BuildFileRule. Configuration is done by parsing
+    the <samp>src/etc/testcases/types/selectors.xml</samp>. BaseSelectorRule then gives us
+    helper methods for handling multiple selections.</p>
 
-    <p>Because the term "testcase" or "testenvironment" are so often used, this
-    special testenvironment got a new name: <i>bed</i>. The setup and cleanup of
-    the bed is all handled by the BaseSelectorRule so any test only has to handle
-    the actual test scenarios</p>
+    <p>Because the term "testcase" or "testenvironment" are so often used, this special
+    testenvironment got a new name: <em>bed</em>. The setup and cleanup of the bed is all
+    handled by the BaseSelectorRule so any test only has to handle the actual test scenarios</p>
 
     <p>A usual test scenario is:</p>
     <ol>
@@ -169,9 +150,8 @@
        <li>verify the work</li>
     </ol>
 
-
-
-    <p>An example test would be:<pre>
+    <p>An example test would be:</p>
+    <pre>
 package org.apache.tools.ant.types.selectors;
 
 public class MySelectorTest {
@@ -182,7 +162,6 @@
     @Test
     public void testCase1() {
 
-
         // Configure the selector
         MySelector s = new MySelector();
         s.addParam("key1", "value1");
@@ -193,52 +172,44 @@
         // do the tests
         assertEquals("FTTTTTTTT", selectorRule.selectionString(s));
     }
-}
-    </pre>
-    As an example of an error JUnit could log<pre>
-    [junit]     FAILED
-    [junit] Error for files: <font color=blue>.;copy.filterset.filtered;tar/gz/asf-logo.gif.tar.gz</font>
-    [junit] expected:&lt;<font color=blue>FTTTFTTTF...</font>&gt; but was:&lt;TTTTTTTTT...&gt;
-    [junit] junit.framework.ComparisonFailure: Error for files: .;copy.filterset.filtered;tar/gz/asf-logo.gif.tar.gz
-    [junit] expected:&lt;FTTTFTTTF...&gt; but was:&lt;TTTTTTTTT...&gt;
-    [junit]     at junit.framework.Assert.assertEquals(Assert.java:81)
-    [junit]     at org.apache.tools.ant.types.selectors.BaseSelectorTest.performTest(BaseSelectorTest.java:194)
-    </pre></p>
+}</pre>
+    <p>As an example of an error JUnit could log</p>
+    <pre>
+[junit]     FAILED
+[junit] Error for files: <span style="color:blue">.;copy.filterset.filtered;tar/gz/asf-logo.gif.tar.gz</span>
+[junit] expected:&lt;<span style="color:blue">FTTTFTTTF...</span>&gt; but was:&lt;TTTTTTTTT...&gt;
+[junit] junit.framework.ComparisonFailure: Error for files: .;copy.filterset.filtered;tar/gz/asf-logo.gif.tar.gz
+[junit] expected:&lt;FTTTFTTTF...&gt; but was:&lt;TTTTTTTTT...&gt;
+[junit]     at junit.framework.Assert.assertEquals(Assert.java:81)
+[junit]     at org.apache.tools.ant.types.selectors.BaseSelectorTest.performTest(BaseSelectorTest.java:194)</pre>
 
-    <p>Described above the test class should provide a <tt>getInstance()</tt>
-    method. But that isn't used here. The used <tt>getSelector()</tt> method is
-    implemented in the base class and gives an instance of an Ant Project to
-    the selector. This is usually done inside normal build file runs, but not
-    inside this special environment, so this method gives the selector the
-    ability to use its own Project object (<tt>getProject()</tt>), for example
-    for logging.</p>
-
+    <p>Described above the test class should provide a <code class="code">getInstance()</code>
+    method. But that isn't used here. The used <code class="code">getSelector()</code> method is
+    implemented in the base class and gives an instance of an Ant Project to the selector. This is
+    usually done inside normal build file runs, but not inside this special environment, so this
+    method gives the selector the ability to use its own Project object
+    (<code class="code">getProject()</code>), for example for logging.</p>
 
     <h3>Logging</h3>
 
-    <p>During development and maybe later you sometimes need the output of information.
-    Therefore Logging is needed. Because the selector extends BaseExtendSelector or directly
-    BaseSelector it is an Ant <tt>DataType</tt> and therefore a <tt>ProjectComponent</tt>. <br>
-    That means that you have access to the project object and its logging capability.
-    <tt>ProjectComponent</tt> itself provides <i>log</i> methods which will do the
-    access to the project instance. Logging is therefore done simply with:
-    <pre>
-        log( "message" );
-    </pre>
-    or
-    <pre>
-        log( "message" , loglevel );
-    </pre>
-    where the <tt>loglevel</tt> is one of the values <ul>
-    <li> org.apache.tools.ant.Project.MSG_ERR </li>
-    <li> org.apache.tools.ant.Project.MSG_WARN </li>
-    <li> org.apache.tools.ant.Project.MSG_INFO  (= default) </li>
-    <li> org.apache.tools.ant.Project.MSG_VERBOSE </li>
-    <li> org.apache.tools.ant.Project.MSG_DEBUG </li>
+    <p>During development and maybe later you sometimes need the output of information.  Therefore
+    Logging is needed. Because the selector extends BaseExtendSelector or directly BaseSelector it
+    is an Ant <code class="code">DataType</code> and therefore
+    a <code class="code">ProjectComponent</code>.<br/>  That means that you have access to the
+    project object and its logging capability.  <code class="code">ProjectComponent</code> itself
+    provides <code class="code">log()</code> methods which will do the access to the project
+    instance. Logging is therefore done simply with:</p>
+    <pre>log("message");</pre>
+    <p>or</p>
+    <pre>log("message", loglevel);</pre>
+    <p>where the <code>loglevel</code> is one of the values</p>
+    <ul>
+      <li><code class="code">org.apache.tools.ant.Project.MSG_ERR</code></li>
+      <li><code class="code">org.apache.tools.ant.Project.MSG_WARN</code></li>
+      <li><code class="code">org.apache.tools.ant.Project.MSG_INFO</code> (default)</li>
+      <li><code class="code">org.apache.tools.ant.Project.MSG_VERBOSE</code></li>
+      <li><code class="code">org.apache.tools.ant.Project.MSG_DEBUG</code></li>
     </ul>
-    </p>
 
-    
   </body>
-
 </html>
diff --git a/manual/Types/selectors.html b/manual/Types/selectors.html
index f622e72..4539992 100644
--- a/manual/Types/selectors.html
+++ b/manual/Types/selectors.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,9 +15,8 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
   <head>
-    <meta http-equiv="Content-Language" content="en-us">
     <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
     <title>Selectors in Apache Ant</title>
   </head>
@@ -24,1204 +24,1145 @@
   <body>
     <h2>Selectors</h2>
 
-    <p>Selectors are a mechanism whereby the files that make up a
-    <code>&lt;fileset&gt;</code> can be selected based on criteria
-    other than filename as provided by the <code>&lt;include&gt;</code>
-    and <code>&lt;exclude&gt;</code> tags.</p>
+    <p>Selectors are a mechanism whereby the files that make up a <code>&lt;fileset&gt;</code> can
+    be selected based on criteria other than filename as provided by
+    the <code>&lt;include&gt;</code> and <code>&lt;exclude&gt;</code> tags.</p>
 
     <h3>How to use a Selector</h3>
 
-    <p>A selector is an element of FileSet, and appears within it. It can
-    also be defined outside of any target by using the <code>&lt;selector&gt;</code> tag
-    and then using it as a reference.
-    </p>
+    <p>A selector is an element of FileSet, and appears within it. It can also be defined outside of
+    any target by using the <code>&lt;selector&gt;</code> tag and then using it as a reference.</p>
 
-    <p>Different selectors have different attributes. Some selectors can
-    contain other selectors, and these are called
-    <a href="#selectcontainers"><code>Selector Containers</code></a>.
-    There is also a category of selectors that allow
-    user-defined extensions, called
-    <a href="#customselect"><code>Custom Selectors</code></a>.
-    The ones built in to Apache Ant are called
-    <a href="#coreselect"><code>Core Selectors</code></a>.
-    </p>
+    <p>Different selectors have different attributes. Some selectors can contain other selectors,
+    and these are called <a href="#selectcontainers"><q>Selector Containers</q></a>.  There is also
+    a category of selectors that allow user-defined extensions,
+    called <a href="#customselect"><q>Custom Selectors</q></a>.  The ones built in to Apache Ant are
+    called <a href="#coreselect"><q>Core Selectors</q></a>.</p>
 
-    <h3><a name="coreselect">Core Selectors</a></h3>
+    <h3 id="coreselect">Core Selectors</h3>
 
-    <p>Core selectors are the ones that come standard
-    with Ant. They can be used within a fileset and can be contained
-    within Selector Containers.</p>
+    <p>Core selectors are the ones that come standard with Ant. They can be used within a
+    fileset and can be contained within Selector Containers.</p>
 
     <p>The core selectors are:</p>
 
     <ul>
-      <li><a href="#containsselect"><code>&lt;contains&gt;</code></a> - Select
-        files that contain a particular text string</li>
-      <li><a href="#dateselect"><code>&lt;date&gt;</code></a> - Select files
-        that have been modified either before or after a particular date
-        and time</li>
-      <li><a href="#dependselect"><code>&lt;depend&gt;</code></a> - Select files
-        that have been modified more recently than equivalent files
-        elsewhere</li>
-      <li><a href="#depthselect"><code>&lt;depth&gt;</code></a> - Select files
-        that appear so many directories down in a directory tree</li>
-      <li><a href="#differentselect"><code>&lt;different&gt;</code></a> - Select files
-        that are different from those elsewhere</li>
-      <li><a href="#filenameselect"><code>&lt;filename&gt;</code></a> - Select
-        files whose name matches a particular pattern. Equivalent to
-        the include and exclude elements of a patternset.</li>
-      <li><a href="#presentselect"><code>&lt;present&gt;</code></a> - Select
-        files that either do or do not exist in some other location</li>
-      <li><a href="#regexpselect"><code>&lt;containsregexp&gt;</code></a> - Select
-        files that match a regular expression</li>
-      <li><a href="#sizeselect"><code>&lt;size&gt;</code></a> - Select files
-        that are larger or smaller than a particular number of bytes.</li>
-      <li><a href="#typeselect"><code>&lt;type&gt;</code></a> - Select files
-        that are either regular files or directories.</li>
-      <li><a href="#modified"><code>&lt;modified&gt;</code></a> - Select files if
-        the return value of the configured algorithm is different from that
-        stored in a cache.</li>
-      <li><a href="#signedselector"><code>&lt;signedselector&gt;</code></a> - Select files if
-        they are signed, and optionally if they have a signature of a certain name.
-      </li>
-      <li><a href="#scriptselector"><code>&lt;scriptselector&gt;</code></a> - 
-        Use a BSF or JSR 223 scripting language to create
-        your own selector
-      </li>
-      <li><a href="#readable"><code>&lt;readable&gt;</code></a> -
-        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="#containsselect"><code>&lt;contains&gt;</code></a>&mdash;Select files that
+        contain a particular text string</li>
+      <li><a href="#dateselect"><code>&lt;date&gt;</code></a>&mdash;Select files that have been
+        modified either before or after a particular date and time</li>
+      <li><a href="#dependselect"><code>&lt;depend&gt;</code></a>&mdash;Select files that have been
+        modified more recently than equivalent files elsewhere</li>
+      <li><a href="#depthselect"><code>&lt;depth&gt;</code></a>&mdash;Select files that appear so
+        many directories down in a directory tree</li>
+      <li><a href="#differentselect"><code>&lt;different&gt;</code></a>&mdash;Select files that are
+        different from those elsewhere</li>
+      <li><a href="#filenameselect"><code>&lt;filename&gt;</code></a>&mdash;Select files whose name
+        matches a particular pattern. Equivalent to the include and exclude elements of a
+        patternset.</li>
+      <li><a href="#presentselect"><code>&lt;present&gt;</code></a>&mdash;Select files that either
+        do or do not exist in some other location</li>
+      <li><a href="#regexpselect"><code>&lt;containsregexp&gt;</code></a>&mdash;Select files that
+        match a regular expression</li>
+      <li><a href="#sizeselect"><code>&lt;size&gt;</code></a>&mdash;Select files that are larger or
+        smaller than a particular number of bytes.</li>
+      <li><a href="#typeselect"><code>&lt;type&gt;</code></a>&mdash;Select files that are either
+        regular files or directories.</li>
+      <li><a href="#modified"><code>&lt;modified&gt;</code></a>&mdash;Select files if the return
+        value of the configured algorithm is different from that stored in a cache.</li>
+      <li><a href="#signedselector"><code>&lt;signedselector&gt;</code></a>&mdash;Select files if
+        they are signed, and optionally if they have a signature of a certain name.</li>
+      <li><a href="#scriptselector"><code>&lt;scriptselector&gt;</code></a>&mdash;Use a BSF or JSR
+        223 scripting language to create your own selector</li>
+      <li><a href="#readable"><code>&lt;readable&gt;</code></a>&mdash;Select files if they are
+        readable.</li>
+      <li><a href="#writable"><code>&lt;writable&gt;</code></a>&mdash;Select files if they are
+        writable.</li>
+      <li><a href="#executable"><code>&lt;executable&gt;</code></a>&mdash;Select files if they
+        are executable.</li>
+      <li><a href="#symlink"><code>&lt;symlink&gt;</code></a>&mdash;Select files if they are
+        symlinks.</li>
+      <li><a href="#ownedBy"><code>&lt;ownedBy&gt;</code></a>&mdash;Select files if they are owned
+        by a given user.</li>
+      <li><a href="#posixGroup"><code>&lt;posixGroup&gt;</code></a>&mdash;Select
+        files if they have a given POSIX group.</li>
+      <li><a href="#posixPermissions"><code>&lt;posixPermissions&gt;</code></a>&mdash;Select
+        files if they have given POSIX permissions.</li>
     </ul>
 
-    <h4><a name="containsselect">Contains Selector</a></h4>
+    <h4 id="containsselect">Contains Selector</h4>
 
-    <p>The <code>&lt;contains&gt;</code> tag in a FileSet limits
-    the files defined by that fileset to only those which contain the
-    string specified by the <code>text</code> attribute.
-    .</p>
-    <p>The <code>&lt;contains&gt;</code> selector can be used as a
-      ResourceSelector (see the
-      <a href="resources.html#restrict">&lt;restrict&gt;</a>
-      ResourceCollection).</p>
+    <p>The <code>&lt;contains&gt;</code> tag in a FileSet limits the files defined by that fileset
+    to only those which contain the string specified by the <code>text</code> attribute.</p>
+    <p>The <code>&lt;contains&gt;</code> selector can be used as a ResourceSelector (see
+    the <a href="resources.html#restrict">&lt;restrict&gt;</a> ResourceCollection).</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">text</td>
-        <td valign="top">Specifies the text that every file must contain
+        <td>text</td>
+        <td>Specifies the text that every file must contain
         </td>
-        <td valign="top" align="center">Yes</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">casesensitive</td>
-        <td valign="top">Whether to pay attention to case when looking
-          for the string in the <code>text</code> attribute. Default is
-          true.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>casesensitive</td>
+        <td>Whether to pay attention to case when looking for the string in the <var>text</var>
+          attribute.</td>
+        <td>No; default is <q>true</q></td>
       </tr>
       <tr>
-        <td valign="top">ignorewhitespace</td>
-        <td valign="top">Whether to eliminate whitespace before checking
-          for the string in the <code>text</code> attribute. Default is
-          false.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>ignorewhitespace</td>
+        <td>Whether to eliminate whitespace before checking for the string in the <var>text</var>
+          attribute.</td>
+        <td>No; default is <q>false</q></td>
       </tr>
-        <tr>
-            <td valign="top">encoding</td>
-            <td valign="top">Encoding of the resources being selected.
-                Required in practice if the encoding of the files being
-                selected is different from the default encoding of the JVM
-                where Ant is running.
-                Since Ant 1.9.0
-            </td>
-            <td valign="top" align="center">No</td>
-        </tr>
+      <tr>
+        <td>encoding</td>
+        <td>Encoding of the resources being selected.
+          <em>Since Ant 1.9.0</em>
+        </td>
+        <td>No; defaults to default JVM character encoding</td>
+      </tr>
     </table>
 
     <p>Here is an example of how to use the Contains Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${doc.path}&quot; includes=&quot;**/*.html&quot;&gt;
     &lt;contains text=&quot;script&quot; casesensitive=&quot;no&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the HTML files that contain the string
-    <code>script</code>.</p>
+    <p>Selects all the HTML files that contain the string <code>script</code>.</p>
 
+    <h4 id="dateselect">Date Selector</h4>
 
-    <h4><a name="dateselect">Date Selector</a></h4>
+    <p>The <code>&lt;date&gt;</code> tag in a FileSet will put a limit on the files specified by the
+    include tag, so that tags whose last modified date does not meet the date limits specified by
+    the selector will not end up being selected.</p>
 
-    <p>The <code>&lt;date&gt;</code> tag in a FileSet will put
-    a limit on the files specified by the include tag, so that tags
-    whose last modified date does not meet the date limits specified
-    by the selector will not end up being selected.</p>
-
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">datetime</td>
-        <td valign="top">Specifies the date and time to test for.
-          Should be in the format "MM/dd/yyyy hh:mm a" using the US
-          locale, or an alternative pattern specified via
-          the <i>pattern</i> attribute.
-        </td>
-        <td valign="top" align="center" rowspan="2">At least one of the two.</td>
-      </tr>
-      <tr>
-        <td valign="top">millis</td>
-        <td valign="top">The number of milliseconds since 1970 that should
-          be tested for. It is usually much easier to use the datetime
+        <td>datetime</td>
+        <td>Specifies the date and time to test for.  Should be in the format <q>MM/dd/yyyy hh:mm
+          a</q> using the US locale, or an alternative pattern specified via the <var>pattern</var>
           attribute.
         </td>
+        <td rowspan="2">At least one of the two</td>
       </tr>
       <tr>
-        <td valign="top">when</td>
-        <td valign="top">Indicates how to interpret the date, whether
-          the files to be selected are those whose last modified times should
-          be before, after, or equal to the specified value. Acceptable
-          values for this attribute are:
+        <td>millis</td>
+        <td class="left">The number of milliseconds since 1970 that should be tested for. It is
+          usually much easier to use the <var>datetime</var> attribute.
+        </td>
+      </tr>
+      <tr>
+        <td>when</td>
+        <td>Indicates how to interpret the date, whether the files to be selected are those
+          whose last modified times should be before, after, or equal to the specified
+          value. Acceptable values for this attribute are:
           <ul>
-            <li>before - select files whose last modified date is before the indicated date
-            <li>after - select files whose last modified date is after the indicated date
-            <li>equal - select files  whose last modified date is this exact date
-          </ul>
-          The default is equal.
-        <td valign="top" align="center">No</td>
+            <li><q>before</q>&mdash;select files whose last modified date is before the indicated
+              date</li>
+            <li><q>after</q>&mdash;select files whose last modified date is after the indicated
+              date</li>
+            <li><q>equal</q>&mdash;select files whose last modified date is this exact date</li>
+          </ul></td>
+        <td>No; default is <q>equal</q></td>
       </tr>
       <tr>
-        <td valign="top">granularity</td>
-        <td valign="top">The number of milliseconds leeway to use when
-          comparing file modification times. This is needed because not every
-          file system supports tracking the last modified time to the
-          millisecond level. Default is 0 milliseconds, or 2 seconds on DOS systems.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>granularity</td>
+        <td>The number of milliseconds leeway to use when comparing file modification times. This is
+          needed because not every file system supports tracking the last modified time to the
+          millisecond level.</td>
+        <td>No; default is 0 milliseconds, or 2 seconds on DOS systems</td>
       </tr>
       <tr>
-        <td valign="top">pattern</td>
-        <td valign="top">The <CODE>SimpleDateFormat</CODE>-compatible pattern
-          to use when interpreting the <i>datetime</i> attribute using
-          the current locale.
-          <i>Since Ant 1.6.2</i>
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>pattern</td>
+        <td>The <code>SimpleDateFormat</code>-compatible pattern to use when interpreting
+          the <var>datetime</var> attribute using the current locale.
+          <em>Since Ant 1.6.2</em></td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">checkdirs</td>
-        <td valign="top">
-          Indicates whether or not to check dates on directories.
-        </td>
-        <td valign="top" align="center">No, defaults to <i>false</i></td>
+        <td>checkdirs</td>
+        <td>Indicates whether or not to check dates on directories.</td>
+        <td>No; defaults to <q>false</q></td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Date Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${jar.path}&quot; includes=&quot;**/*.jar&quot;&gt;
     &lt;date datetime=&quot;01/01/2001 12:00 AM&quot; when=&quot;before&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all JAR files which were last modified before midnight
-    January 1, 2001.</p>
+    <p>Selects all JAR files which were last modified before midnight January 1, 2001.</p>
 
+    <h4 id="dependselect">Depend Selector</h4>
 
-    <h4><a name="dependselect">Depend Selector</a></h4>
-
-    <p>The <code>&lt;depend&gt;</code> tag selects files
-    whose last modified date is later than another, equivalent file in
-    another location.</p>
+    <p>The <code>&lt;depend&gt;</code> tag selects files whose last modified date is later than
+    another, equivalent file in another location.</p>
 
     <p>The <code>&lt;depend&gt;</code> tag supports the use of a
-    contained <a href="mapper.html"><code>&lt;mapper&gt;</code></a> element
-    to define the location of the file to be compared against. If no
-    <code>&lt;mapper&gt;</code> element is specified, the
-    <code>identity</code> type mapper is used.</p>
+    contained <a href="mapper.html"><code>&lt;mapper&gt;</code></a> element to define the location
+    of the file to be compared against. If no <code>&lt;mapper&gt;</code> element is specified,
+    the <code>identity</code> type mapper is used.</p>
 
     <p>The <code>&lt;depend&gt;</code> selector is case-sensitive.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">targetdir</td>
-        <td valign="top">The base directory to look for the files to compare
-          against. The precise location depends on a combination of this
-          attribute and the <code>&lt;mapper&gt;</code> element, if any.
-        </td>
-        <td valign="top" align="center">Yes</td>
+        <td>targetdir</td>
+        <td>The base directory to look for the files to compare against. The precise location
+          depends on a combination of this attribute and the <code>&lt;mapper&gt;</code> element, if
+          any.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">granularity</td>
-        <td valign="top">The number of milliseconds leeway to give before
-          deciding a file is out of date. This is needed because not every
-          file system supports tracking the last modified time to the
-          millisecond level. Default is 0 milliseconds, or 2 seconds on DOS systems.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>granularity</td>
+        <td>The number of milliseconds leeway to give before deciding a file is out of date. This is
+          needed because not every file system supports tracking the last modified time to the
+          millisecond level.</td>
+        <td>No; default is 0 milliseconds, or 2 seconds on DOS systems</td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Depend Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${ant.1.5}/src/main&quot; includes=&quot;**/*.java&quot;&gt;
     &lt;depend targetdir=&quot;${ant.1.4.1}/src/main&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the Java source files which were modified in the
-      1.5 release.
-    </p>
+    <p>Selects all the Java source files which were modified in the 1.5 release.</p>
 
+    <h4 id="depthselect">Depth Selector</h4>
 
-    <h4><a name="depthselect">Depth Selector</a></h4>
+    <p>The <code>&lt;depth&gt;</code> tag selects files based on how many directory levels deep they
+    are in relation to the base directory of the fileset.</p>
 
-    <p>The <code>&lt;depth&gt;</code> tag selects files based on
-    how many directory levels deep they are in relation to the base
-    directory of the fileset.
-    </p>
-
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">min</td>
-        <td valign="top">The minimum number of directory levels below
-          the base directory that a file must be in order to be selected.
-          Default is no limit.
-        </td>
-        <td valign="top" align="center" rowspan="2">At least one of the two.</td>
+        <td>min</td>
+        <td>The minimum number of directory levels below the base directory that a file must be in
+          order to be selected.</td>
+        <td rowspan="2">At least one of the two; default is no limit</td>
       </tr>
       <tr>
-        <td valign="top">max</td>
-        <td valign="top">The maximum number of directory levels below
-          the base directory that a file can be and still be selected.
-          Default is no limit.
-        </td>
+        <td>max</td>
+        <td class="left">The maximum number of directory levels below the base directory that a file
+          can be and still be selected.</td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Depth Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${doc.path}&quot; includes=&quot;**/*&quot;&gt;
     &lt;depth max=&quot;1&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all files in the base directory and one directory below
-    that.</p>
+    <p>Selects all files in the base directory and one directory below that.</p>
 
-    
-    <h4><a name="differentselect">Different Selector</a></h4>
+    <h4 id="differentselect">Different Selector</h4>
 
-    <p>The <code>&lt;different&gt;</code> selector will select a file
-    if it is deemed to be 'different' from an equivalent file in
-    another location. The rules for determining difference between
-    the two files are as follows:
+    <p>The <code>&lt;different&gt;</code> selector will select a file if it is deemed to be
+    'different' from an equivalent file in another location. The rules for determining difference
+    between the two files are as follows:<p>
     <ol>
-    <li>If a file is only present in the resource collection you apply
-      the selector to but not in targetdir (or after applying the
-      mapper) the file is selected.
-    <li>If a file is only present in targetdir (or after applying the
-      mapper) it is ignored.
-    <li> Files with different lengths are different.
-    <li> If <tt>ignoreFileTimes</tt> is turned off, then differing file
-    timestamps will cause files to be regarded as different.
-    <li> Unless <tt>ignoreContents</tt> is set to true,
-         a byte-for-byte check is run against the two files.
+    <li>If a file is only present in the resource collection you apply the selector to but not
+      in <var>targetdir</var> (or after applying the mapper) the file is selected.</li>
+    <li>If a file is only present in <var>targetdir</var> (or after applying the mapper) it is
+      ignored.</li>
+    <li>Files with different lengths are different.</li>
+    <li>If <var>ignoreFileTimes</var> is turned <q>off</q>, then differing file timestamps will
+      cause files to be regarded as different.</li>
+    <li>Unless <var>ignoreContents</var> is set to <q>true</q>, a byte-for-byte check is run against
+      the two files.</li>
     </ol>
+    <p>This is a useful selector to work with programs and tasks that don't handle dependency
+    checking properly; even if a predecessor task always creates its output files, followup tasks
+    can be driven off copies made with a different selector, so their dependencies are driven on the
+    absolute state of the files, not just a timestamp. For example: anything fetched from a web
+    site, or the output of some program. To reduce the amount of checking, when using this task
+    inside a <code>&lt;copy&gt;</code> task, set <var>preservelastmodified</var> to <q>true</q> to
+    propagate the timestamp from the source file to the destination file.</p>
 
-    This is a useful selector to work with programs and tasks that don't handle
-    dependency checking properly; even if a predecessor task always creates its
-    output files, followup tasks can be driven off copies made with a different
-    selector, so their dependencies are driven on the absolute state of the
-    files, not just a timestamp. For example: anything fetched from a web site,
-    or the output of some program. To reduce the amount of checking, when using
-    this task inside a <code>&lt;copy&gt;</code> task, set
-    <tt>preservelastmodified</tt> to <i>true</i> to propagate the timestamp
-    from the source file to the destination file.<p>
+    <p>The <code>&lt;different&gt;</code> selector supports the use of a
+    contained <a href="mapper.html"><code>&lt;mapper&gt;</code></a> element to define the location
+    of the file to be compared against. If no <code>&lt;mapper&gt;</code> element is specified,
+    the <code>identity</code> type mapper is used.</p>
 
-    The <code>&lt;different&gt;</code> selector supports the use of a
-    contained <a href="mapper.html"><code>&lt;mapper&gt;</code></a> element
-    to define the location of the file to be compared against. If no
-    <code>&lt;mapper&gt;</code> element is specified, the
-    <code>identity</code> type mapper is used.</p>
-
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">targetdir</td>
-        <td valign="top">The base directory to look for the files to compare
-          against. The precise location depends on a combination of this
-          attribute and the <code>&lt;mapper&gt;</code> element, if any.
-        </td>
-        <td valign="top" align="center">Yes</td>
+        <td>targetdir</td>
+        <td>The base directory to look for the files to compare against. The precise location
+          depends on a combination of this attribute and the <code>&lt;mapper&gt;</code> element, if
+          any.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">ignoreFileTimes</td>
-        <td valign="top">Whether to use file times in the comparison or not.
-          Default is true (time differences are ignored).
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>ignoreFileTimes</td>
+        <td>Whether to use file times in the comparison or not.</td>
+        <td>No; default is <q>true</q> (time differences are ignored)</td>
       </tr>
       <tr>
-        <td valign="top">ignoreContents</td>
-        <td valign="top">Whether to do a byte per byte compare.
-          Default is false (contents are compared).
-          Since Ant 1.6.3
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>ignoreContents</td>
+        <td>Whether to do a byte per byte compare.
+          <em>Since Ant 1.6.3</em></td>
+        <td>No; default is <q>false</q> (contents are compared)</td>
       </tr>
       <tr>
-        <td valign="top">granularity</td>
-        <td valign="top">The number of milliseconds leeway to give before
-          deciding a file is out of date. This is needed because not every
-          file system supports tracking the last modified time to the
-          millisecond level. Default is 0 milliseconds, or 2 seconds on DOS systems.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>granularity</td>
+        <td>The number of milliseconds leeway to give before deciding a file is out of date. This is
+          needed because not every file system supports tracking the last modified time to the
+          millisecond level.</td>
+        <td>No; default is 0 milliseconds, or 2 seconds on DOS systems</td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Different Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${ant.1.5}/src/main&quot; includes=&quot;**/*.java&quot;&gt;
     &lt;different targetdir=&quot;${ant.1.4.1}/src/main&quot;
         ignoreFileTimes="true"/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Compares all the Java source files between the 1.4.1 and the 1.5 release
-    and selects those who are different, disregarding file times.
-    </p>
+    <p>Compares all the Java source files between the 1.4.1 and the 1.5 release and selects those
+    who are different, disregarding file times.</p>
 
-    <h4><a name="filenameselect">Filename Selector</a></h4>
+    <h4 id="filenameselect">Filename Selector</h4>
 
-    <p>The <code>&lt;filename&gt;</code> tag acts like the
-    <code>&lt;include&gt;</code> and <code>&lt;exclude&gt;</code>
-    tags within a fileset. By using a selector instead, however,
-    one can combine it with all the other selectors using whatever
-    <a href="#selectcontainers">selector container</a> is desired.
-    </p>
+    <p>The <code>&lt;filename&gt;</code> tag acts like the <code>&lt;include&gt;</code>
+    and <code>&lt;exclude&gt;</code> tags within a fileset. By using a selector instead, however,
+    one can combine it with all the other selectors using
+    whatever <a href="#selectcontainers">selector container</a> is desired.</p>
 
-    <p>The <code>&lt;filename&gt;</code> selector is
-    case-sensitive.</p>
+    <p>The <code>&lt;filename&gt;</code> selector is case-sensitive.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">name</td>
-        <td valign="top">The name of files to select. The name parameter
-          can contain the standard Ant wildcard characters.
-        </td>
-        <td valign="top" align="center" rowspan="2">Exactly one of
-          the two</td>
+        <td>name</td>
+        <td>The name of files to select. The name parameter can contain the standard Ant wildcard
+          characters.</td>
+        <td rowspan="2">Exactly one of the two</td>
       </tr>
       <tr>
-        <td valign="top">regex</td>
-        <td valign="top">The regular expression matching files to select.</td>
+        <td>regex</td>
+        <td class="left">The regular expression matching files to select.</td>
       </tr>
       <tr>
-        <td valign="top">casesensitive</td>
-        <td valign="top">Whether to pay attention to case when looking
-          at file names. Default is "true".
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>casesensitive</td>
+        <td>Whether to pay attention to case when looking at file names.</td>
+        <td>No; default is <q>true</q></td>
       </tr>
       <tr>
-        <td valign="top">negate</td>
-        <td valign="top">Whether to reverse the effects of this filename
-          selection, therefore emulating an exclude rather than include
-          tag. Default is "false".
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>negate</td>
+        <td>Whether to reverse the effects of this filename selection, therefore emulating
+          an <code>exclude</code> rather than <code>include</code> tag.</td>
+        <td>No; default is <q>false</q></td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Filename Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${doc.path}&quot; includes=&quot;**/*&quot;&gt;
     &lt;filename name=&quot;**/*.css&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
     <p>Selects all the cascading style sheet files.</p>
 
+    <h4 id="presentselect">Present Selector</h4>
 
-    <h4><a name="presentselect">Present Selector</a></h4>
-
-    <p>The <code>&lt;present&gt;</code> tag selects files
-    that have an equivalent file in another directory tree.</p>
+    <p>The <code>&lt;present&gt;</code> tag selects files that have an equivalent file in
+    another directory tree.</p>
 
     <p>The <code>&lt;present&gt;</code> tag supports the use of a
-    contained <a href="mapper.html"><code>&lt;mapper&gt;</code></a> element
-    to define the location of the file to be tested against. If no
-    <code>&lt;mapper&gt;</code> element is specified, the
-    <code>identity</code> type mapper is used.</p>
+    contained <a href="mapper.html"><code>&lt;mapper&gt;</code></a> element to define the location
+    of the file to be tested against. If no <code>&lt;mapper&gt;</code> element is specified,
+    the <code>identity</code> type mapper is used.</p>
 
     <p>The <code>&lt;present&gt;</code> selector is case-sensitive.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">targetdir</td>
-        <td valign="top">The base directory to look for the files to compare
-          against. The precise location depends on a combination of this
-          attribute and the <code>&lt;mapper&gt;</code> element, if any.
-        </td>
-        <td valign="top" align="center">Yes</td>
+        <td>targetdir</td>
+        <td>The base directory to look for the files to compare against. The precise location
+          depends on a combination of this attribute and the <code>&lt;mapper&gt;</code> element, if
+          any.</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">present</td>
-        <td valign="top">Whether we are requiring that a file is present in
-          the src directory tree only, or in both the src and the target
-          directory tree. Valid values are:
+        <td>present</td>
+        <td>Whether we are requiring that a file is present in the source directory tree only, or in
+          both the source and the target directory tree. Valid values are:
           <ul>
-            <li>srconly - select files only if they are in the src
-              directory tree but not in the target directory tree
-            <li>both - select files only if they are present both in the
-              src and target directory trees
+            <li><q>srconly</q>&mdash;select files only if they are in the source directory tree but
+              not in the target directory tree</li>
+            <li><q>both</q >-- select files only if they are present both in the source and target
+              directory trees</li>
           </ul>
-          Default is both. Setting this attribute to &quot;srconly&quot;
-          is equivalent to wrapping the selector in the <code>&lt;not&gt;</code>
-          selector container.
-        </td>
-        <td valign="top" align="center">No</td>
+          Setting this attribute to <q>srconly</q> is equivalent to wrapping the selector in
+          the <code>&lt;not&gt;</code> selector container.</td>
+        <td>No; default is <q>both</q></td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Present Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${ant.1.5}/src/main&quot; includes=&quot;**/*.java&quot;&gt;
     &lt;present present=&quot;srconly&quot; targetdir=&quot;${ant.1.4.1}/src/main&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the Java source files which are new in the
-      1.5 release.
-    </p>
+    <p>Selects all the Java source files which are new in the 1.5 release.</p>
 
-    <h4><a name="regexpselect">Regular Expression Selector</a></h4>
+    <h4 id="regexpselect">Regular Expression Selector</h4>
 
-    <p>The <code>&lt;containsregexp&gt;</code> tag in a FileSet limits
-    the files defined by that fileset to only those which contents contain a
-    match to the regular expression specified by the <code>expression</code> attribute.
-    </p>
-    <p>The <code>&lt;containsregexp&gt;</code> selector can be used as a
-      ResourceSelector (see the
-      <a href="resources.html#restrict">&lt;restrict&gt;</a>
-      ResourceCollection).</p>
+    <p>The <code>&lt;containsregexp&gt;</code> tag in a FileSet limits the files defined by that
+    fileset to only those which contents contain a match to the regular expression specified by
+    the <code>expression</code> attribute.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <p>The <code>&lt;containsregexp&gt;</code> selector can be used as a ResourceSelector (see
+    the <a href="resources.html#restrict">&lt;restrict&gt;</a> ResourceCollection).</p>
+
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">expression</td>
-        <td valign="top">Specifies the regular expression that must
-        match true in every file</td>
-        <td valign="top" align="center">Yes</td>
+        <td>expression</td>
+        <td>Specifies the regular expression that must match true in every file</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">casesensitive</td>
-        <td valign="top">Perform a case sensitive match.  Default is
-          true. <em>since Ant 1.8.2</em></td>
-        <td valign="top" align="center">No</td>
+        <td>casesensitive</td>
+        <td>Perform a case sensitive match. <em>Since Ant 1.8.2</em></td>
+        <td>No; default is <q>true</q></td>
       </tr>
       <tr>
-        <td valign="top">multiline</td>
-        <td valign="top">
-          Perform a multi line match.
-          Default is false. <em>since Ant 1.8.2</em></td>
-        <td valign="top" align="center">No</td>
+        <td>multiline</td>
+        <td>Perform a multi line match. <em>Since Ant 1.8.2</em></td>
+        <td>No; default is <q>false</q></td>
       </tr>
       <tr>
-        <td valign="top">singleline</td>
-        <td valign="top">
-          This allows '.' to match new lines.
-          SingleLine is not to be confused with multiline, SingleLine is a perl
-          regex term, it corresponds to dotall in java regex.
-          Default is false. <em>since Ant 1.8.2</em></td>
-        <td valign="top" align="center">No</td>
+        <td>singleline</td>
+        <td>This allows <q>.</q> to match new lines.  SingleLine is not to be confused with
+          multiline, SingleLine is a perl regex term, it corresponds to dotall in Java regex.
+          <em>Since Ant 1.8.2</em></td>
+        <td>No; default is <q>false</q></td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the regular expression Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${doc.path}&quot; includes=&quot;*.txt&quot;&gt;
     &lt;containsregexp expression=&quot;[4-6]\.[0-9]&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the text files that match the regular expression
-    (have a 4,5 or 6 followed by a period and a number from 0 to 9).
+    <p>Selects all the text files that match the regular expression (have a 4, 5 or 6 followed by a
+    period and a number from 0 to 9).
 
+    <h4 id="sizeselect">Size Selector</h4>
 
-    <h4><a name="sizeselect">Size Selector</a></h4>
-
-    <p>The <code>&lt;size&gt;</code> tag in a FileSet will put
-    a limit on the files specified by the include tag, so that tags
-    which do not meet the size limits specified by the selector will not
+    <p>The <code>&lt;size&gt;</code> tag in a FileSet will put a limit on the files specified by the
+    include tag, so that tags which do not meet the size limits specified by the selector will not
     end up being selected.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">value</td>
-        <td valign="top">The size of the file which should be tested for.
+        <td>value</td>
+        <td>The size of the file which should be tested for.
         </td>
-        <td valign="top" align="center">Yes</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">units</td>
-        <td valign="top">The units that the <code>value</code> attribute
-          is expressed in. When using the standard single letter SI
-          designations, such as &quot;k&quot;,&quot;M&quot;, or
-          &quot;G&quot;, multiples of 1000 are used. If you want to use
-          power of 2 units, use the IEC standard: &quot;Ki&quot; for 1024,
-          &quot;Mi&quot; for 1048576, and so on. The default is no units,
-          which means the <code>value</code> attribute expresses the exact
-          number of bytes.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>units</td>
+        <td>The units that the <code>value</code> attribute is expressed in. When using the standard
+        single letter SI designations, such as <q>k</q>, <q>M</q>, or <q>G</q>, multiples of 1000
+        are used. If you want to use power of 2 units, use the IEC standard: <q>Ki</q> for
+        1024, <q>Mi</q> for 1048576, and so on. The default is no units, which means
+        the <var>value</var> attribute expresses the exact number of bytes.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">when</td>
-        <td valign="top">Indicates how to interpret the size, whether
-          the files to be selected should be larger, smaller, or equal to
-          that value. Acceptable values for this attribute are:
+        <td>when</td>
+        <td>Indicates how to interpret the size, whether the files to be selected should be larger,
+          smaller, or equal to that value. Acceptable values for this attribute are:
           <ul>
-            <li>less - select files less than the indicated size
-            <li>more - select files greater than the indicated size
-            <li>equal - select files this exact size
-          </ul>
-          The default is equal.
-        <td valign="top" align="center">No</td>
+            <li><q>less</q>&mdash;select files less than the indicated size</li>
+            <li><q>more</q>&mdash;select files greater than the indicated size</li>
+            <li><q>equal</q>&mdash;select files this exact size</li>
+          </ul></td>
+        <td>No; default is <q>equal</q></td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Size Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${jar.path}&quot;&gt;
   &lt;patternset&gt;
     &lt;include name=&quot;**/*.jar&quot;/&gt;
   &lt;/patternset&gt;
   &lt;size value=&quot;4&quot; units=&quot;Ki&quot; when=&quot;more&quot;/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
     <p>Selects all JAR files that are larger than 4096 bytes.</p>
 
-    <h4><a name="typeselect">Type Selector</a></h4>
+    <h4 id="typeselect">Type Selector</h4>
 
-    <p>The <code>&lt;type&gt;</code> tag selects files of a certain type:
-    directory or regular.</p>
+    <p>The <code>&lt;type&gt;</code> tag selects files of a certain type: directory or
+    regular.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">type</td>
-        <td valign="top">The type of file which should be tested for.
-            Acceptable values are:
-            <ul>
-                <li>file - regular files</li>
-                <li>dir - directories</li>
-            </ul>
-        </td>
-        <td valign="top" align="center">Yes</td>
+        <td>type</td>
+        <td>The type of file which should be tested for.  Acceptable values are:
+          <ul>
+            <li><q>file</q>&mdash;regular files</li>
+            <li><q>dir</q>&mdash;directories</li>
+          </ul></td>
+        <td>Yes</td>
       </tr>
     </table>
 
-    <p>Here is an example of how to use the Type Selector to select only
-    directories in <code>${src}</code></p>
+    <p>Here is an example of how to use the Type Selector to select only directories
+    in <code>${src}</code></p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${src}&quot;&gt;
   &lt;type type="dir"/&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>The Type Selector is often used in conjunction with other selectors.
-    For example, to select files that also exist in a <code>template</code>
-    directory, but avoid selecting empty directories, use:
+    <p>The Type Selector is often used in conjunction with other selectors.  For example, to select
+    files that also exist in a <samp>template</samp> directory, but avoid selecting empty
+    directories, use:</p>
 
-<blockquote><pre>
+    <pre>
 &lt;fileset dir="${src}"&gt;
     &lt;and&gt;
         &lt;present targetdir="template"/&gt;
         &lt;type type="file"/&gt;
     &lt;/and&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
+    <h4 id="modified">Modified Selector</h4>
+    <p>The <code>&lt;modified&gt;</code> selector computes a value for a file, compares that to the
+    value stored in a cache and select the file, if these two values differ.</p>
+    <p>Because this selector is highly configurable the order in which the selection is done is:</p>
+    <ol>
+      <li>get the absolute path for the file</li>
+      <li>get the cached value from the configured cache (absolute path as key)</li>
+      <li>get the new value from the configured algorithm</li>
+      <li>compare these two values with the configured comparator</li>
+      <li>update the cache if needed and requested</li>
+      <li>do the selection according to the comparison result</li>
+    </ol>
+    <p>The comparison, computing of the hashvalue and the store is done by implementation of special
+    interfaces. Therefore they may provide additional parameters.</p>
 
-    <h4><a name="modified">Modified Selector</a></h4>
-    <p>The <code>&lt;modified&gt;</code> selector computes a value for a file, compares that
-    to the value stored in a cache and select the file, if these two values
-    differ.</p>
-    <p>Because this selector is highly configurable the order in which the selection is done
-    is: <ol>
-        <li> get the absolute path for the file </li>
-        <li> get the cached value from the configured cache (absolute path as key) </li>
-        <li> get the new value from the configured algorithm </li>
-        <li> compare these two values with the configured comparator </li>
-        <li> update the cache if needed and requested </li>
-        <li> do the selection according to the comparison result </li>
-        </ol>
-    <p>The comparison, computing of the hashvalue and the store is done by implementation
-    of special interfaces. Therefore they may provide additional parameters.</p>
-
-    <p>The <code>&lt;modified&gt;</code> selector can be used as a
-      ResourceSelector (see the
-      <a href="resources.html#restrict">&lt;restrict&gt;</a>
-      ResourceCollection).
-    In that case it maps simple file resources to files and does its job. If the
-    resource is from another type, the <code>&lt;modified&gt;</code> selector tries
-    to (<b>attention!</b>) copy the content into a local file for computing the
-    hashvalue.</p>
+    <p>The <code>&lt;modified&gt;</code> selector can be used as a ResourceSelector (see
+    the <a href="resources.html#restrict">&lt;restrict&gt;</a> ResourceCollection).  In that case it
+    maps simple file resources to files and does its job. If the resource is from another type,
+    the <code>&lt;modified&gt;</code> selector tries to (<strong>attention!</strong>) copy the
+    content into a local file for computing the hashvalue.</p>
 
     <p>If the source resource is not a filesystem resource the
     modified selector will download it to
     the <a href="../running.html#tmpdir">temporary directory</a>.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top"> algorithm </td>
-        <td valign="top"> The type of algorithm should be used.
-            Acceptable values are (further information see later):
-            <ul>
-                <li> hashvalue - HashvalueAlgorithm </li>
-                <li> digest - DigestAlgorithm </li>
-                <li> checksum - ChecksumAlgorithm </li>
-                <li> lastmodified - LastModifiedAlgorithm </li>
-            </ul>
+        <td>algorithm</td>
+        <td>The type of algorithm should be used.  Acceptable values are (further information
+          see later):
+          <ul>
+            <li><q>hashvalue</q>&mdash;HashvalueAlgorithm</li>
+            <li><q>digest</q>&mdash;DigestAlgorithm</li>
+            <li><q>checksum</q>&mdash;ChecksumAlgorithm</li>
+            <li><q>lastmodified</q>&mdash;LastModifiedAlgorithm</li>
+          </ul>
         </td>
-        <td valign="top" align="center"> No, defaults to <i>digest</i> </td>
+        <td>No; defaults to <q>digest</q></td>
       </tr>
       <tr>
-        <td valign="top"> cache </td>
-        <td valign="top"> The type of cache should be used.
-            Acceptable values are (further information see later):
-            <ul>
-                <li> propertyfile - PropertyfileCache </li>
-            </ul>
+        <td>cache</td>
+        <td>The type of cache should be used.  Acceptable values are (further information see
+          later):
+          <ul>
+            <li><q>propertyfile</q>&mdash;PropertyfileCache</li>
+          </ul>
         </td>
-        <td valign="top" align="center"> No, defaults to <i>propertyfile</i> </td>
+        <td>No; defaults to <q>propertyfile</q></td>
       </tr>
       <tr>
-        <td valign="top"> comparator </td>
-        <td valign="top"> The type of comparator should be used.
-            Acceptable values are (further information see later):
-            <ul>
-                <li> equal - EqualComparator </li>
-                <li> rule - java.text.RuleBasedCollator
-                  <!-- NOTE -->
-                  <i>(see <a href="#ModSelNote">note</a> for restrictions)</i>
-                </li>
-            </ul>
+        <td>comparator</td>
+        <td>The type of comparator should be used.  Acceptable values are:
+          <ul>
+            <li><q>equal</q>&mdash;EqualComparator</li>
+            <li><q>rule</q>&mdash;java.text.RuleBasedCollator
+              <!-- NOTE -->
+              <em>(see <a href="#ModSelNote">note</a> for restrictions)</em></li>
+          </ul>
         </td>
-        <td valign="top" align="center"> No, defaults to <i>equal</i> </td>
+        <td>No; defaults to <q>equal</q></td>
       </tr>
       <tr>
-        <td valign="top"> algorithmclass </td>
-        <td valign="top"> Classname of custom algorithm implementation. Lower
-          priority than <i>algorithm</i>. </td>
-        <td valign="top" align="center"> No </td>
+        <td>algorithmclass</td>
+        <td>Classname of custom algorithm implementation. Lower priority
+          than <var>algorithm</var>.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top"> cacheclass </td>
-        <td valign="top"> Classname of custom cache implementation. Lower
-          priority than <i>cache</i>. </td>
-        <td valign="top" align="center"> No </td>
+        <td>cacheclass</td>
+        <td>Classname of custom cache implementation. Lower priority than <var>cache</var>.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top"> comparatorclass </td>
-        <td valign="top"> Classname of custom comparator implementation. Lower
-          priority than <i>comparator</i>. </td>
-        <td valign="top" align="center"> No </td>
+        <td>comparatorclass</td>
+        <td>Classname of custom comparator implementation. Lower priority
+          than <var>comparator</var>.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top"> update </td>
-        <td valign="top"> Should the cache be updated when values differ? (boolean) </td>
-        <td valign="top" align="center"> No, defaults to <i>true</i> </td>
+        <td>update</td>
+        <td>Should the cache be updated when values differ? (boolean)</td>
+        <td>No; defaults to <q>true</q></td>
       </tr>
       <tr>
-        <td valign="top"> seldirs </td>
-        <td valign="top"> Should directories be selected? (boolean) </td>
-        <td valign="top" align="center"> No, defaults to <i>true</i> </td>
+        <td>seldirs</td>
+        <td>Should directories be selected? (boolean)</td>
+        <td>No; defaults to <q>true</q></td>
       </tr>
       <tr>
-        <td valign="top"> selres </td>
-        <td valign="top"> Should Resources without an InputStream, and
-           therefore without checking, be selected?  (boolean) </td>
-        <td valign="top" align="center"> No, defaults to <i>true</i>. Only relevant
-           when used as ResourceSelector. </td>
+        <td>selres</td>
+        <td>Should Resources without an InputStream, and therefore without checking, be selected?
+          (boolean)</td>
+        <td>No; defaults to <q>true</q>. Only relevant when used as ResourceSelector.</td>
       </tr>
       <tr>
-        <td valign="top"> delayupdate </td>
-        <td valign="top"> If set to <i>true</i>, the storage of the cache will be delayed until the
-             next finished BuildEvent; task finished, target finished or build finished,
-             whichever comes first.  This is provided for increased performance.  If set
-             to <i>false</i>, the storage of the cache will happen with each change.  This
-             attribute depends upon the <i>update</i> attribute. (boolean)</td>
-        <td valign="top" align="center"> No, defaults to <i>true</i> </td>
+        <td>delayupdate</td>
+        <td>If set to <q>true</q>, the storage of the cache will be delayed until the next finished
+          BuildEvent; task finished, target finished or build finished, whichever comes first.  This
+          is provided for increased performance.  If set to <q>false</q>, the storage of the cache
+          will happen with each change.  This attribute depends upon the <var>update</var>
+          attribute. (boolean)</td>
+        <td>No; defaults to <q>true</q></td>
       </tr>
     </table>
 
-    <p>These attributes can be set with nested <code>&lt;param/&gt;</code> tags. With <code>&lt;param/&gt;</code>
-    tags you can set other values too - as long as they are named according to
-    the following rules: <ul>
-        <li> <b> algorithm </b>: same as attribute algorithm </li>
-        <li> <b> cache </b>: same as attribute cache </li>
-        <li> <b> comparator </b>: same as attribute comparator </li>
-        <li> <b> algorithmclass </b>: same as attribute algorithmclass </li>
-        <li> <b> cacheclass </b>: same as attribute cacheclass </li>
-        <li> <b> comparatorclass </b>: same as attribute comparatorclass </li>
-        <li> <b> update </b>: same as attribute update </li>
-        <li> <b> seldirs </b>: same as attribute seldirs </li>
-        <li> <b> algorithm.* </b>: Value is transferred to the algorithm via its
-                                   <i>set</i>XX-methods </li>
-        <li> <b> cache.* </b>: Value is transferred to the cache via its
-                                   <i>set</i>XX-methods </li>
-        <li> <b> comparator.* </b>: Value is transferred to the comparator via its
-                                   <i>set</i>XX-methods </li>
-    </ul>
+    <h5>Parameters specified as nested elements</h5>
 
-    <table border="1" cellpadding="2" cellspacing="0">
-      <tr><td colspan="2"><font size="+1"><b> Algorithm options</b></font></td></tr>
-      <tr>
-        <td valign="top"><b>Name</b></td>
-        <td valign="top"><b>Description</b></td>
+    <p>The <code>&lt;modified&gt;</code> selector supports a nested <code>&lt;classpath&gt;</code>
+    element that represents a <a href="../using.html#path">path-like structure</a> for finding
+    custom interface implementations.</p>
+
+    <p>All attributes of a <code>&lt;modified&gt;</code> selector can be set with
+    nested <code>&lt;param/&gt;</code> tags. Additional values can be set
+    with <code>&lt;param/&gt;</code> tags according to the rules below.</p>
+
+    <h6>algorithm</h6>
+    <p>Same as <var>algorithm</var> attribute, with the following additional values:</p>
+    <table>
+     <tr>
+        <th scope="col">Name</th>
+        <th scope="col">Description</th>
       </tr>
       <tr>
-        <td valign="top"> hashvalue </td>
-        <td valign="top"> Reads the content of a file into a java.lang.String
-          and use thats hashValue(). No additional configuration required.
-        </td>
+        <td>hashvalue</td>
+        <td>Reads the content of a file into a <code>java.lang.String</code> and uses
+          that <code>hashValue()</code>. No additional configuration required.</td>
       </tr>
       <tr>
-        <td valign="top"> digest </td>
-        <td valign="top"> Uses java.security.MessageDigest. This Algorithm supports
-          the following attributes:
+        <td>digest</td>
+        <td>Uses <code>java.security.MessageDigest</code>. This Algorithm supports the following
+          attributes:
           <ul>
-            <li><i>algorithm.algorithm</i> (optional): Name of the Digest algorithm
-                (e.g. 'MD5' or 'SHA', default = <i>MD5</i>) </li>
-            <li><i>algorithm.provider</i> (optional): Name of the Digest provider
-                (default = <i>null</i>) </li>
+            <li><var>algorithm.algorithm</var> (optional): Name of the Digest algorithm
+              (e.g. <q>MD5</q> or <q>SHA</q>); default is <q>MD5</q></li>
+            <li><var>algorithm.provider</var> (optional): Name of the Digest provider; default
+              is <q>null</q></li>
           </ul>
         </td>
       </tr>
-      <tr>
-        <td valign="top"> checksum </td>
-        <td valign="top"> Uses java.util.zip.Checksum. This Algorithm supports
-          the following attributes:
-          <ul>
-            <li><i>algorithm.algorithm</i> (optional): Name of the algorithm
-                (e.g. 'CRC' or 'ADLER', default = <i>CRC</i>) </li>
-          </ul>
-        </td>
-      </tr>
-      <tr>
-        <td valign="top"> lastmodified </td>
-        <td valign="top"> Uses the lastModified property of a file. No additional
-          configuration is required.
-        </td>
-      </tr>
-      <tr><td colspan="2"><font size="+1"><b> Cache options </b></font></td></tr>
-      <tr>
-        <td valign="top"> propertyfile </td>
-        <td valign="top"> Use the java.util.Properties class and its possibility
-          to load and store to file.
-          This Cache implementation supports the following attributes:
-          <ul>
-            <li><i>cache.cachefile</i> (optional): Name of the properties-file
-                (default = <i>cache.properties</i>) </li>
-          </ul>
-        </td>
-      </tr>
-      <tr><td colspan="2"><font size="+1"><b> Comparator options</b></font></td></tr>
-      <tr>
-        <td valign="top"> equal </td>
-        <td valign="top"> Very simple object comparison. </td>
-      </tr>
-      <tr>
-        <td valign="top"> rule </td>
-        <td valign="top"> Uses <i>java.text.RuleBasedCollator</i> for Object
-          comparison.
-          <!-- NOTE -->
-          <i>(see <a href="#ModSelNote">note</a> for restrictions)</i>
-        </td>
-      </tr>
+     <tr>
+       <td>checksum</td>
+       <td>Uses <code>java.util.zip.Checksum</code>. This Algorithm supports the following
+         attributes:
+         <ul>
+           <li><var>algorithm.algorithm</var> (optional): Name of the algorithm (e.g. <q>CRC</q>
+             or <q>ADLER</q>); default is <q>CRC</q>)</li>
+         </ul>
+       </td>
+     </tr>
+     <tr>
+       <td>lastmodified</td>
+       <td>Uses the lastModified property of a file. No additional configuration is required.</td>
+     </tr>
     </table>
+    <h6>cache</h6>
+    <p>Same as <var>cache</var> attribute, with the following additional values:</p>
+    <table>
+     <tr>
+       <th scope="col">Name</th>
+       <th scope="col">Description</th>
+     </tr>
+     <tr>
+       <td>propertyfile</td>
+       <td>Use the <code>java.util.Properties</code> class and its possibility to load and store to
+         file.  This Cache implementation supports the following attributes:
+         <ul>
+           <li><var>cache.cachefile</var> (optional): Name of the properties file; default
+             is <q>cache.properties</q></li>
+         </ul>
+       </td>
+     </tr>
+    </table>
+    <h6>comparator</h6>
+    <p>Same as <var>comparator</var> attribute.</p>
+    <h6>algorithmclass</h6>
+    <p>Same as <var>algorithmclass</var> attribute.</p>
+    <h6>comparatorclass</h6>
+    <p>Same as <var>comparatorclass</var> attribute.</p>
+    <h6>cacheclass</h6>
+    <p>Same as <var>cacheclass</var> attribute.</p>
+    <h6>update</h6>
+    <p>Same as <var>update</var> attribute.</p>
+    <h6>seldirs</h6>
+    <p>Same as <var>comparatorclass</var> attribute.</p>
 
-    <p>The <code>&lt;modified&gt;</code> selector supports a nested
-    <code>&lt;classpath&gt;</code> element that represents a <a href="../using.html#path">
-    PATH like structure</a> for finding custom interface implementations. </p>
-
+    <h5>Examples</h5>
     <p>Here are some examples of how to use the Modified Selector:</p>
 
-    <blockquote><pre>
-    &lt;copy todir="dest"&gt;
-        &lt;fileset dir="src"&gt;
-            &lt;modified/&gt;
-        &lt;/fileset&gt;
-    &lt;/copy&gt;
-    </pre></blockquote>
-    <p>This will copy all files from <i>src</i> to <i>dest</i> which content has changed.
-    Using an updating PropertyfileCache with cache.properties and
+    <pre>
+&lt;copy todir="dest"&gt;
+    &lt;fileset dir="src"&gt;
+        &lt;modified/&gt;
+    &lt;/fileset&gt;
+&lt;/copy&gt;</pre>
+
+    <p>This will copy all files from <samp>src</samp> to <samp>dest</samp> which content has
+    changed.  Using an updating PropertyfileCache with <samp>cache.properties</samp> and
     MD5-DigestAlgorithm.</p>
 
-    <blockquote><pre>
-    &lt;copy todir="dest"&gt;
-        &lt;fileset dir="src"&gt;
-            &lt;modified update="true"
-                      seldirs="true"
-                      cache="propertyfile"
-                      algorithm="digest"
-                      comparator="equal"&gt;
-                &lt;param name="cache.cachefile"     value="cache.properties"/&gt;
-                &lt;param name="algorithm.algorithm" value="MD5"/&gt;
-            &lt;/modified&gt;
+    <pre>
+&lt;copy todir="dest"&gt;
+    &lt;fileset dir="src"&gt;
+        &lt;modified update="true"
+                  seldirs="true"
+                  cache="propertyfile"
+                  algorithm="digest"
+                  comparator="equal"&gt;
+            &lt;param name="cache.cachefile"     value="cache.properties"/&gt;
+            &lt;param name="algorithm.algorithm" value="MD5"/&gt;
+        &lt;/modified&gt;
+    &lt;/fileset&gt;
+&lt;/copy&gt;</pre>
+
+    <p>This is the same example rewritten as CoreSelector with setting the all the values (same as
+    defaults are).</p>
+
+    <pre>
+&lt;copy todir="dest"&gt;
+    &lt;fileset dir="src"&gt;
+        &lt;custom class="org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector"&gt;
+            &lt;param name="update"     value="true"/&gt;
+            &lt;param name="seldirs"    value="true"/&gt;
+            &lt;param name="cache"      value="propertyfile"/&gt;
+            &lt;param name="algorithm"  value="digest"/&gt;
+            &lt;param name="comparator" value="equal"/&gt;
+            &lt;param name="cache.cachefile"     value="cache.properties"/&gt;
+            &lt;param name="algorithm.algorithm" value="MD5"/&gt;
+        &lt;/custom&gt;
+    &lt;/fileset&gt;
+&lt;/copy&gt;</pre>
+
+    <p>And this is the same rewritten as CustomSelector.</p>
+
+    <pre>
+&lt;target name="generate-and-upload-site"&gt;
+    &lt;echo&gt; generate the site using forrest &lt;/echo&gt;
+    &lt;antcall target="site"/&gt;
+
+    &lt;echo&gt; upload the changed file &lt;/echo&gt;
+    &lt;ftp server="${ftp.server}" userid="${ftp.user}" password="${ftp.pwd}"&gt;
+        &lt;fileset dir="htdocs/manual"&gt;
+            &lt;modified/&gt;
         &lt;/fileset&gt;
-    &lt;/copy&gt;
-    </pre></blockquote>
-  <p>This is the same example rewritten as CoreSelector with setting the all the values
-  (same as defaults are).</p>
+    &lt;/ftp&gt;
+&lt;/target&gt;</pre>
 
-    <blockquote><pre>
-    &lt;copy todir="dest"&gt;
-        &lt;fileset dir="src"&gt;
-            &lt;custom class="org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector"&gt;
-                &lt;param name="update"     value="true"/&gt;
-                &lt;param name="seldirs"    value="true"/&gt;
-                &lt;param name="cache"      value="propertyfile"/&gt;
-                &lt;param name="algorithm"  value="digest"/&gt;
-                &lt;param name="comparator" value="equal"/&gt;
-                &lt;param name="cache.cachefile"     value="cache.properties"/&gt;
-                &lt;param name="algorithm.algorithm" value="MD5"/&gt;
-            &lt;/custom&gt;
-        &lt;/fileset&gt;
-    &lt;/copy&gt;
-    </pre></blockquote>
-  <p>And this is the same rewritten as CustomSelector.</p>
+    <p>A useful scenario for this selector inside a build environment for homepage generation
+    (e.g. with <a href="https://forrest.apache.org/" target="_top">Apache Forrest</a>). Here
+    all <strong>changed</strong> files are uploaded to the server. The CacheSelector saves therefore
+    much upload time.</p>
 
-    <blockquote><pre>
-  &lt;target name="generate-and-upload-site"&gt;
-      &lt;echo&gt; generate the site using forrest &lt;/echo&gt;
-      &lt;antcall target="site"/&gt;
+    <pre>
+&lt;modified cacheclassname="com.mycompany.MyCache"&gt;
+    &lt;classpath&gt;
+        &lt;pathelement location="lib/mycompany-antutil.jar"/&gt;
+    &lt;/classpath&gt;
+&lt;/modified&gt;</pre>
 
-      &lt;echo&gt; upload the changed file &lt;/echo&gt;
-      &lt;ftp server="${ftp.server}" userid="${ftp.user}" password="${ftp.pwd}"&gt;
-          &lt;fileset dir="htdocs/manual"&gt;
-              &lt;modified/&gt;
-          &lt;/fileset&gt;
-      &lt;/ftp&gt;
-  &lt;/target&gt;
-    </pre></blockquote>
-  <p>A useful scenario for this selector inside a build environment
-  for homepage generation (e.g. with <a href="http://xml.apache.org/forrest/">
-  Apache Forrest</a>). Here all <b>changed</b> files are uploaded to the server. The
-  CacheSelector saves therefore much upload time.</p>
+    <p>Uses <code>com.mycompany.MyCache</code> from a jar outside of Ant's own classpath as
+    cache implementation</p>
 
-    <blockquote><pre>
-  &lt;modified cacheclassname="com.mycompany.MyCache"&gt;
-      &lt;classpath&gt;
-          &lt;pathelement location="lib/mycompany-antutil.jar"/&gt;
-      &lt;/classpath&gt;
-  &lt;/modified&gt;
-    </pre></blockquote>
-    <p>Uses <tt>com.mycompany.MyCache</tt> from a jar outside of Ants own classpath
-    as cache implementation</p>
+    <h4 id="ModSelNote">Note on RuleBasedCollator</h4>
+    <p>The RuleBasedCollator needs a format for its work, but its needed while instantiating. There
+    is a problem in the initialization algorithm for this case. Therefore you should not use this
+    (or tell me the workaround :-).</p>
 
-  <h4><a name="ModSelNote">Note on RuleBasedCollator</a></h4>
-  <p>The RuleBasedCollator needs a format for its work, but its needed while
-  instantiation. There is a problem in the initialization algorithm for this
-  case. Therefore you should not use this (or tell me the workaround :-).</p>
+    <h4 id="signedselector">Signed Selector</h4>
 
-      <h4><a name="signedselector">Signed Selector</a></h4>
+    <p>The <code>&lt;signedselector&gt;</code> tag selects signed files and optionally signed with a
+    certain name.</p>
+    <p><em>Since Apache Ant 1.7</em></p>
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>name</td>
+        <td>The signature name to check for.</td>
+        <td>No</td>
+      </tr>
+    </table>
 
-      <p>
-        The <code>&lt;signedselector&gt;</code> tag selects signed files and optionally
-        signed with a certain name.
-      </p>
-      <p>
-        This selector has been added in Apache Ant 1.7.
-      </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">name</td>
-          <td valign="top"> The signature name to check for.</td>
-          <td valign="top" align="center">no</td>
-        </tr>
-      </table>
+    <h4 id="readable">Readable Selector</h4>
 
-      <h4><a name="readable">Readable Selector</a></h4>
+    <p>The <code>&lt;readable&gt;</code> selector selects only files that are readable.  Ant only
+    invokes <code class="code">java.io.File#canRead</code> so if a file is unreadable but JVM cannot
+    detect this state, this selector will still select the file.</p>
 
-      <p>The <code>&lt;readable&gt;</code> selector selects only files
-        that are readable.  Ant only invokes
-        <code>java.io.File#canRead</code> so if a file is unreadable
-        but the Java VM cannot detect this state, this selector will
-        still select the file.</p>
+    <h4 id="writable">Writable Selector</h4>
 
-      <h4><a name="writable">Writable Selector</a></h4>
+    <p>The <code>&lt;writable&gt;</code> selector selects only files that are writable.  Ant only
+    invokes <code class="code">java.io.File#canWrite</code> so if a file is nonwritable but JVM
+    cannot detect this state, this selector will still select the file.</p>
 
-      <p>The <code>&lt;writable&gt;</code> selector selects only files
-        that are writable.  Ant only invokes
-        <code>java.io.File#canWrite</code> so if a file is unwritable
-        but the Java VM cannot detect this state, this selector will
-        still select the file.</p>
+    <h4 id="executable">Executable Selector</h4>
 
-      <h4><a name="scriptselector">Script Selector</a></h4>
+    <p>The <code>&lt;executable&gt;</code> selector selects only files that are executable.  Ant
+    only invokes <code class="code">java.nio.file.Files#isExecutable</code> so if a file is not
+    executable but JVM cannot detect this state, this selector will still select the file.</p>
 
-      <p>
-        The <code>&lt;scriptselector&gt;</code> element enables you
-        to write a complex selection algorithm in any
-        <a href="http://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
-        or
-        <a href="https://scripting.dev.java.net">JSR 223</a>
-        supported language.
-        See the <a href="../Tasks/script.html">Script</a> task for
-        an explanation of scripts and dependencies.
-      </p>
-      <p>
-        This selector was added in Apache Ant 1.7.
-      </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">language</td>
-          <td valign="top">language of the script.</td>
-          <td valign="top" align="center">yes</td>
-        </tr>
-        <tr>
-          <td valign="top">manager</td>
-          <td valign="top">
-            The script engine manager to use.
-            See the <a href="../Tasks/script.html">script</a> task
-            for using this attribute.
-          </td>
-          <td valign="top" align="center">No - default is "auto"</td>
-        </tr>
-        <tr>
-          <td valign="top">src</td>
-          <td valign="top">filename of the script</td>
-          <td valign="top" align="center">no</td>
-        </tr>
-        <tr>
-          <td valign="top">setbeans</td>
-          <td valign="top">whether to have all properties, references and targets as
-            global variables in the script.</td>
-          <td valign="top" align="center">No, default is "true".</td>
-        </tr>
-        <tr>
-          <td valign="top">classpath</td>
-          <td valign="top">
-            The classpath to pass into the script.
-          </td>
-          <td align="center" valign="top">No</td>
-        </tr>
-        <tr>
-          <td valign="top">classpathref</td>
-          <td valign="top">The classpath to use, given as a
-            <a href="../using.html#references">reference</a> to a path defined elsewhere.
-            <td align="center" valign="top">No</td>
-          </tr>
-      </table>
-  <p>
-    This selector can take a nested &lt;classpath&gt; element.
-    See the <a href="../Tasks/script.html">script</a> task
-    on how to use this element.
-  </p>
-      <p>
-      If no <code>src</code> attribute is supplied, the script must be nested
-      inside the selector declaration.
-      </p>
-      <p>The embedded script is invoked for every test, with
-         the bean <code>self</code>
-        is bound to the selector. It has an attribute <code>selected</code>
-        must can be set using <code>setSelected(boolean)</code> to select that
-        file.
+    <p><em>Since Ant 1.10.0</em></p>
 
-      <p>
+    <h4 id="symlink">Symlink Selector</h4>
 
-      The following beans are configured for every script, alongside
-      the classic set of project, properties, and targets.
+    <p>The <code>&lt;symlink&gt;</code> selector selects only files that are symbolic links.  Ant
+    only invokes <code class="code">java.nio.file.Files#isSymbolicLink</code> so if a file is a
+    symbolic link but JVM cannot detect this state, this selector will not select the file.</p>
 
-      <table border="1" cellpadding="2" cellspacing="0">
-        <tr>
-          <td valign="top"><b>Bean</b></td>
-          <td valign="top"><b>Description</b></td>
-          <td valign="top"><b>Type</b></td>
-        </tr>
-        <tr>
-          <td valign="top">self</td>
-          <td valign="top">selector instance</td>
-          <td valign="top">org.apache.tools.ant.types.optional</td>
-        </tr>
-        <tr>
-          <td valign="top">filename</td>
-          <td valign="top">filename of the selection</td>
-          <td valign="top" >String</td>
-        </tr>
-        <tr>
-          <td valign="top">file</td>
-          <td valign="top">file of the selection</td>
-          <td valign="top" >java.io.File</td>
-        </tr>
-        <tr>
-          <td valign="top">basedir</td>
-          <td valign="top">Fileset base directory</td>
-          <td valign="top" >java.io.File</td>
-        </tr>
+    <p><em>Since Ant 1.10.0</em></p>
 
-      </table>
-      <p>
-      The <code>self</code> bean maps to the selector, which has the following
-      attributes. Only the <code>selected</code> flag is writable, the rest
-      are read only via their getter methods.
+    <h4 id="ownedBy">OwnedBy Selector</h4>
 
-            <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>Type</b></td>
-        </tr>
-        <tr>
-          <td valign="top">selected</td>
-          <td valign="top">writeable flag to select this file</td>
-          <td valign="top" align="center">boolean</td>
-        </tr>
-        <tr>
-          <td valign="top">filename</td>
-          <td valign="top">filename of the selection</td>
-          <td valign="top" >String</td>
-        </tr>
-        <tr>
-          <td valign="top">file</td>
-          <td valign="top">file of the selection</td>
-          <td valign="top" >java.io.File</td>
-        </tr>
-        <tr>
-          <td valign="top">basedir</td>
-          <td valign="top">Fileset base directory</td>
-          <td valign="top" >java.io.File</td>
-        </tr>
-      </table>
+    <p>The <code>&lt;ownedBy&gt;</code> selector selects only files that are owned by the given
+    user.  Ant only invokes <code class="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>
-      Example
-      </p>
-<pre>
-    &lt;scriptselector language=&quot;javascript&quot;&gt;
-      self.setSelected(true);
-    &lt;/scriptselector&gt;
-</pre>
-    <p>
-    Selects every file.
-    </p>
+    <p><em>Since Ant 1.10.0</em></p>
 
-<pre>
-    &lt;scriptselector language=&quot;javascript&quot;&gt;
-      self.setSelected((filename.length%2)==0);
-    &lt;/scriptselector&gt;
-</pre>
-Select files whose filename length is even.
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>owner</td>
+        <td>Username of the expected owner</td>
+        <td>Yes</td>
+      </tr>
+      <tr>
+        <td>followsymlinks</td>
+        <td>Must the selector follow symbolic links? (see also how the attribute interacts with the
+          corresponding attribute of the <a href="fileset.html#symlink">FileSet</a>)</td>
+        <td>No; defaults to <q>true</q></td>
+      </tr>
+    </table>
 
-    <h3><a name="selectcontainers">Selector Containers</a></h3>
+    <h4 id="posixGroup">PosixGroup Selector</h4>
 
-    <p>To create more complex selections, a variety of selectors that
-    contain other selectors are available for your use. They combine the
-    selections of their child selectors in various ways.</p>
+    <p>The <code>&lt;posixGroup&gt;</code> selector selects only files that are owned by the given
+      POSIX group.  Ant only invokes <code class="code">java.nio.file.Files#readAttributes</code> so
+      if a file system doesn't support the operation or POSIX attributes this selector will not
+      select the file.</p>
+
+    <p><em>Since Ant 1.10.4</em></p>
+
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>group</td>
+        <td>POSIX group name</td>
+        <td>Yes</td>
+      </tr>
+      <tr>
+        <td>followsymlinks</td>
+        <td>Must the selector follow symbolic links? (see also how the attribute interacts with the
+          corresponding attribute of the <a href="fileset.html#symlink">FileSet</a>)</td>
+        <td>No; defaults to <q>true</q></td>
+      </tr>
+    </table>
+
+    <h4 id="posixPermissions">PosixPermissions Selector</h4>
+
+    <p>The <code>&lt;posixPermissions&gt;</code> selector selects only files that have the given
+      POSIX permissions.  Ant only
+      invokes <code class="code">java.nio.file.Files#getPosixFilePermissions</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.4</em></p>
+
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>permissions</td>
+        <td>POSIX permissions in string (<q>rwxrwxrwx</q>) or octal (<q>777</q>) format</td>
+        <td>Yes</td>
+      </tr>
+      <tr>
+        <td>followsymlinks</td>
+        <td>Must the selector follow symbolic links? (see also how the attribute interacts with
+          the corresponding attribute of the <a href="fileset.html#symlink">FileSet</a>)</td>
+        <td>No; defaults to <q>true</q></td>
+      </tr>
+    </table>
+
+    <h4 id="scriptselector">Script Selector</h4>
+
+    <p>The <code>&lt;scriptselector&gt;</code> element enables you to write a complex selection
+    algorithm in any <a href="https://jakarta.apache.org/bsf" target="_top">Apache BSF</a>
+    or <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr223/223ChangeLog.html"
+    target="_top">JSR 223</a> supported language.  See the <a href="../Tasks/script.html">Script</a>
+    task for an explanation of scripts and dependencies.</p>
+    <p><em>Since Apache Ant 1.7</em></p>
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
+      </tr>
+      <tr>
+        <td>language</td>
+        <td>language of the script.</td>
+        <td>Yes</td>
+      </tr>
+      <tr>
+        <td>manager</td>
+        <td>The script engine manager to use.  See the <a href="../Tasks/script.html">script</a>
+        task for using this attribute.</td>
+        <td>No; default is <q>auto</q></td>
+      </tr>
+      <tr>
+        <td>src</td>
+        <td>filename of the script</td>
+        <td>No</td>
+      </tr>
+      <tr>
+        <td>encoding</td>
+        <td>The encoding of the script as a file. <em>since Ant 1.10.2</em></td>
+        <td>No; defaults to default JVM character encoding</td>
+      </tr>
+      <tr>
+        <td>setbeans</td>
+        <td>Whether to have all properties, references and targets as global variables in the
+        script.</td>
+        <td>No; default is <q>true</q></td>
+      </tr>
+      <tr>
+        <td>classpath</td>
+        <td>The classpath to pass into the script.</td>
+        <td>No</td>
+      </tr>
+      <tr>
+        <td>classpathref</td>
+        <td>The classpath to use, given as a <a href="../using.html#references">reference</a> to
+        a path defined elsewhere.
+        <td>No</td>
+      </tr>
+    </table>
+    <p>This selector can take a nested <code>&lt;classpath&gt;</code> element.  See
+    the <a href="../Tasks/script.html">script</a> task on how to use this element.</p>
+    <p>If no <var>src</var> attribute is supplied, the script must be nested inside the selector
+    declaration.</p>
+    <p>The embedded script is invoked for every test, with the bean <code class="code">self</code>
+    is bound to the selector. It has an attribute <var>selected</var> which can be set
+    using <code class="code">setSelected(boolean)</code> to select a file.</p>
+
+    <p>The following beans are configured for every script, alongside the classic set of project,
+    properties, and targets.</p>
+
+    <table>
+      <tr>
+        <th scope="col">Bean</th>
+        <th scope="col">Description</th>
+        <th scope="col">Type</th>
+      </tr>
+      <tr>
+        <td>self</td>
+        <td>selector instance</td>
+        <td>org.apache.tools.ant.types.optional</td>
+      </tr>
+      <tr>
+        <td>filename</td>
+        <td>filename of the selection</td>
+        <td>String</td>
+      </tr>
+      <tr>
+        <td>file</td>
+        <td>file of the selection</td>
+        <td>java.io.File</td>
+      </tr>
+      <tr>
+        <td>basedir</td>
+        <td>Fileset base directory</td>
+        <td>java.io.File</td>
+      </tr>
+    </table>
+
+    <p>The <code>self</code> bean maps to the selector, which has the following attributes. Only
+    the <var>selected</var> flag is writable, the rest are read only via their getter methods.</p>
+    <table class="attr">
+      <tr>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Type</th>
+      </tr>
+      <tr>
+        <td>selected</td>
+        <td>writeable flag to select this file</td>
+        <td>boolean</td>
+      </tr>
+      <tr>
+        <td>filename</td>
+        <td>filename of the selection</td>
+        <td>String</td>
+      </tr>
+      <tr>
+        <td>file</td>
+        <td>file of the selection</td>
+        <td>java.io.File</td>
+      </tr>
+      <tr>
+        <td>basedir</td>
+        <td>Fileset base directory</td>
+        <td>java.io.File</td>
+      </tr>
+    </table>
+
+    <p>Example</p>
+    <pre>
+&lt;scriptselector language=&quot;javascript&quot;&gt;
+  self.setSelected(true);
+&lt;/scriptselector&gt;</pre>
+    <p>Selects every file.</p>
+
+    <pre>
+&lt;scriptselector language=&quot;javascript&quot;&gt;
+  self.setSelected((filename.length%2)==0);
+&lt;/scriptselector&gt;</pre>
+    <p>Select files whose filename length is even.</p>
+
+    <h3 id="selectcontainers">Selector Containers</h3>
+
+    <p>To create more complex selections, a variety of selectors that contain other selectors are
+    available for your use. They combine the selections of their child selectors in various
+    ways.</p>
 
     <p>The selector containers are:</p>
 
     <ul>
-      <li><a href="#andselect"><code>&lt;and&gt;</code></a> - select a file only if all
-        the contained selectors select it.
-      <li><a href="#majorityselect"><code>&lt;majority&gt;</code></a> - select a file
-        if a majority of its selectors select it.
-      <li><a href="#noneselect"><code>&lt;none&gt;</code></a> - select a file only if
-        none of the contained selectors select it.
-      <li><a href="#notselect"><code>&lt;not&gt;</code></a> - can contain only one
-        selector, and reverses what it selects and doesn't select.
-      <li><a href="#orselect"><code>&lt;or&gt;</code></a> - selects a file if any one
-        of the contained selectors selects it.
-      <li><a href="#selectorselect"><code>&lt;selector&gt;</code></a> - contains only one
-        selector and forwards all requests to it without alteration, provided
-        that any <code>&quot;if&quot;</code> or
-        <code>&quot;unless&quot;</code> conditions are met. This
-        is the selector to use if you want to define a reference. It is
-        usable as an element of <code>&lt;project&gt;</code>. It is also
-        the one to use if you want selection of files to be dependent on
-        Ant property settings.
+      <li><a href="#andselect"><code>&lt;and&gt;</code></a>&mdash;select a file only if all the
+        contained selectors select it.</li>
+      <li><a href="#majorityselect"><code>&lt;majority&gt;</code></a>&mdash;select a file if a
+        majority of its selectors select it.</li>
+      <li><a href="#noneselect"><code>&lt;none&gt;</code></a>&mdash;select a file only if none
+        of the contained selectors select it.</li>
+      <li><a href="#notselect"><code>&lt;not&gt;</code></a>&mdash;can contain only one selector, and
+        reverses what it selects and doesn't select.</li>
+      <li><a href="#orselect"><code>&lt;or&gt;</code></a>&mdash;selects a file if any one of the
+        contained selectors selects it.</li>
+      <li><a href="#selectorselect"><code>&lt;selector&gt;</code></a>&mdash;contains only one
+        selector and forwards all requests to it without alteration, provided that
+        any <code>&quot;if&quot;</code> or <code>&quot;unless&quot;</code> conditions are met. This
+        is the selector to use if you want to define a reference. It is usable as an element
+        of <code>&lt;project&gt;</code>. It is also the one to use if you want selection of files to
+        be dependent on Ant property settings.</li>
     </ul>
 
-    <p>All selector containers can contain any other selector, including
-    other containers, as an element. Using containers, the selector tags
-    can be arbitrarily deep. Here is a complete list of allowable
-    selector elements within a container:</p>
+    <p>All selector containers can contain any other selector, including other containers, as an
+    element. Using containers, the selector tags can be arbitrarily deep. Here is a complete list of
+    allowable selector elements within a container:</p>
 
     <ul>
       <li><code>&lt;and&gt;</code></li>
@@ -1240,83 +1181,69 @@
       <li><code>&lt;size&gt;</code></li>
     </ul>
 
-    <h4><a name="andselect">And Selector</a></h4>
+    <h4 id="andselect">And Selector</h4>
 
-    <p>The <code>&lt;and&gt;</code> tag selects files that are
-    selected by all of the elements it contains. It returns as
-    soon as it finds a selector that does not select the file,
-    so it is not guaranteed to check every selector.
-    </p>
+    <p>The <code>&lt;and&gt;</code> tag selects files that are selected by all of the elements it
+    contains. It returns as soon as it finds a selector that does not select the file, so it is not
+    guaranteed to check every selector.</p>
 
     <p>Here is an example of how to use the And Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${dist}&quot; includes=&quot;**/*.jar&quot;&gt;
     &lt;and&gt;
         &lt;size value=&quot;4&quot; units=&quot;Ki&quot; when=&quot;more&quot;/&gt;
         &lt;date datetime=&quot;01/01/2001 12:00 AM&quot; when=&quot;before&quot;/&gt;
     &lt;/and&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the JAR file larger than 4096 bytes which haven't been update
-      since the last millennium.
-    </p>
+    <p>Selects all the JAR file larger than 4096 bytes which haven't been update since the last
+    millennium.</p>
 
+    <h4 id="majorityselect">Majority Selector</h4>
 
-    <h4><a name="majorityselect">Majority Selector</a></h4>
+    <p>The <code>&lt;majority&gt;</code> tag selects files provided that a majority of the contained
+    elements also select it. Ties are dealt with as specified by the <var>allowtie</var>
+    attribute.</p>
 
-    <p>The <code>&lt;majority&gt;</code> tag selects files provided
-    that a majority of the contained elements also select it. Ties are
-    dealt with as specified by the <code>allowtie</code> attribute.
-    </p>
-
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">allowtie</td>
-        <td valign="top">Whether files should be selected if there
-          are an even number of selectors selecting them as are
-          not selecting them. Default is true.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>allowtie</td>
+        <td>Whether files should be selected if there are an even number of selectors selecting them
+          as are not selecting them.</td>
+        <td>No; default is <q>true</q></td>
       </tr>
     </table>
 
-
     <p>Here is an example of how to use the Majority Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${docs}&quot; includes=&quot;**/*.html&quot;&gt;
     &lt;majority&gt;
         &lt;contains text=&quot;project&quot; casesensitive="false"/&gt;
         &lt;contains text=&quot;taskdef&quot; casesensitive="false"/&gt;
         &lt;contains text=&quot;IntrospectionHelper&quot; casesensitive="true"/&gt;
     &lt;/majority&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
     <p>Selects all the HTML files which contain at least two of the three
-    phrases "project", "taskdef", and "IntrospectionHelper" (this last phrase must
-    match case exactly).
-    </p>
+    phrases <q>project</q>, <q>taskdef</q>, and <q>IntrospectionHelper</q> (this last phrase must
+    match case exactly).</p>
 
+    <h4 id="noneselect">None Selector</h4>
 
-    <h4><a name="noneselect">None Selector</a></h4>
-
-    <p>The <code>&lt;none&gt;</code> tag selects files that are
-    not selected by any of the elements it contains. It returns as
-    soon as it finds a selector that selects the file,
-    so it is not guaranteed to check every selector.
-    </p>
+    <p>The <code>&lt;none&gt;</code> tag selects files that are not selected by any of the elements
+    it contains. It returns as soon as it finds a selector that selects the file, so it is not
+    guaranteed to check every selector.</p>
 
     <p>Here is an example of how to use the None Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${src}&quot; includes=&quot;**/*.java&quot;&gt;
     &lt;none&gt;
         &lt;present targetdir=&quot;${dest}&quot;/&gt;
@@ -1324,46 +1251,36 @@
             &lt;mapper type=&quot;glob&quot; from=&quot;*.java&quot; to=&quot;*.class&quot;/&gt;
         &lt;/present&gt;
     &lt;/none&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects only Java files which do not have equivalent java or
-    class files in the dest directory.
-    </p>
+    <p>Selects only <samp>.java</samp> files which do not have equivalent <samp>.java</samp>
+    or <samp>.class</samp> files in the <samp>dest</samp> directory.</p>
 
+    <h4 id="notselect">Not Selector</h4>
 
-    <h4><a name="notselect">Not Selector</a></h4>
-
-    <p>The <code>&lt;not&gt;</code> tag reverses the meaning of the
-    single selector it contains.
-    </p>
+    <p>The <code>&lt;not&gt;</code> tag reverses the meaning of the single selector it contains.</p>
 
     <p>Here is an example of how to use the Not Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${src}&quot; includes=&quot;**/*.java&quot;&gt;
     &lt;not&gt;
         &lt;contains text=&quot;test&quot;/&gt;
     &lt;/not&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the files in the src directory that do not contain the
-    string "test".
-    </p>
+    <p>Selects all the files in the <samp>src</samp> directory that do not contain the
+    string <q>test</q>.</p>
 
+    <h4 id="orselect">Or Selector</h4>
 
-    <h4><a name="orselect">Or Selector</a></h4>
-
-    <p>The <code>&lt;or&gt;</code> tag selects files that are
-    selected by any one of the elements it contains. It returns as
-    soon as it finds a selector that selects the file,
-    so it is not guaranteed to check every selector.
-    </p>
+    <p>The <code>&lt;or&gt;</code> tag selects files that are selected by any one of the elements it
+    contains. It returns as soon as it finds a selector that selects the file, so it is not
+    guaranteed to check every selector.</p>
 
     <p>Here is an example of how to use the Or Selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${basedir}&quot;&gt;
     &lt;or&gt;
         &lt;depth max=&quot;0&quot;/&gt;
@@ -1371,57 +1288,48 @@
         &lt;filename name="*.gif"/&gt;
         &lt;filename name="*.jpg"/&gt;
     &lt;/or&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all the files in the top directory along with all the
-    image files below it.
-    </p>
+    <p>Selects all the files in the top directory along with all the image files below it.</p>
 
+    <h4 id="selectorselect">Selector Reference</h4>
 
-    <h4><a name="selectorselect">Selector Reference</a></h4>
+    <p>The <code>&lt;selector&gt;</code> tag is used to create selectors that can be reused through
+    references. It is the only selector which can be used outside of any target, as an element of
+    the <code>&lt;project&gt;</code> tag. It can contain only one other selector, but of course that
+    selector can be a container.</p>
 
-    <p>The <code>&lt;selector&gt;</code> tag is used to create selectors
-    that can be reused through references. It is the only selector which can
-    be used outside of
-    any target, as an element of the <code>&lt;project&gt;</code> tag. It
-    can contain only one other selector, but of course that selector can
-    be a container.
-    </p>
+    <p>The <code>&lt;selector&gt;</code> tag can also be used to select files conditionally based on
+    whether an Ant property exists or not.  This functionality is realized using the <var>if</var>
+    and <var>unless</var> attributes in exactly the same way they are used on targets or on
+    the <code>&lt;include&gt;</code> and <code>&lt;exclude&gt;</code> tags within
+    a <code>&lt;patternset&gt;</code>.</p>
 
-    <p>The <code>&lt;selector&gt;</code> tag can also be used to select
-    files conditionally based on whether an Ant property exists or not.
-    This functionality is realized using the <code>&quot;if&quot;</code> and
-    <code>&quot;unless&quot;</code> attributes in exactly the same way they
-    are used on targets or on the <code>&lt;include&gt;</code> and
-    <code>&lt;exclude&gt;</code> tags within a
-    <code>&lt;patternset&gt;</code>.</p>
-
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">if</td>
-        <td valign="top">Allow files to be selected only <a href="../properties.html#if+unless">if the named
+        <td>if</td>
+        <td>Allow files to be selected only <a href="../properties.html#if+unless">if the named
           property is set</a>.
         </td>
-        <td valign="top" align="center">No</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">unless</td>
-        <td valign="top">Allow files to be selected only <a href="../properties.html#if+unless">if the named
-          property is <b>not</b> set</a>.
+        <td>unless</td>
+        <td>Allow files to be selected only <a href="../properties.html#if+unless">if the named
+          property is <strong>not</strong> set</a>.
         </td>
-        <td valign="top" align="center">No</td>
+        <td>No</td>
       </tr>
     </table>
 
     <p>Here is an example of how to use the Selector Reference:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;project default=&quot;all&quot; basedir=&quot;./ant&quot;&gt;
 
     &lt;selector id=&quot;completed&quot;&gt;
@@ -1443,17 +1351,14 @@
         &lt;/zip&gt;
     &lt;/target&gt;
 
-&lt;/project&gt;
-</pre></blockquote>
+&lt;/project&gt;</pre>
 
-    <p>Zips up all the Java files which have an up-to-date equivalent
-    class file and javadoc file associated with them.
-    </p>
+    <p>Zips up all the java files which have an up-to-date equivalent class file and javadoc file
+    associated with them.</p>
 
-    <p>And an example of selecting files conditionally, based on whether
-    properties are set:</p>
+    <p>And an example of selecting files conditionally, based on whether properties are set:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${working.copy}&quot;&gt;
     &lt;or&gt;
         &lt;selector if=&quot;include.tests&quot;&gt;
@@ -1470,109 +1375,93 @@
             &lt;/and&gt;
         &lt;/selector&gt;
     &lt;/or&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>A fileset that conditionally contains Java source files and Test
-    source and class files.</p>
+    <p>A fileset that conditionally contains Java source files and Test source and class
+    files.</p>
 
-    <h3><a name="customselect">Custom Selectors</a></h3>
+    <h3 id="customselect">Custom Selectors</h3>
 
-    <p>You can write your own selectors and use them within the selector
-    containers by specifying them within the <code>&lt;custom&gt;</code> tag.</p>
+    <p>You can write your own selectors and use them within the selector containers by specifying
+    them within the <code>&lt;custom&gt;</code> tag.</p>
 
-    <p>First, you have to write your selector class in Java. The only
-    requirement it must meet in order to be a selector is that it implements
-    the <code>org.apache.tools.ant.types.selectors.FileSelector</code>
-    interface, which contains a single method. See
-    <a href="selectors-program.html">Programming Selectors in Ant</a> for
-    more information.</p>
+    <p>First, you have to write your selector class in Java. The only requirement it must meet in
+    order to be a selector is that it implements
+    the <code class="code">org.apache.tools.ant.types.selectors.FileSelector</code> interface, which
+    contains a single method. See <a href="selectors-program.html">Programming Selectors in Ant</a>
+    for more information.</p>
 
     <p>Once that is written, you include it in your build file by using
-    the <code>&lt;custom&gt;</code> tag.
-    </p>
+    the <code>&lt;custom&gt;</code> tag.</p>
 
-    <table border="1" cellpadding="2" cellspacing="0">
+    <table class="attr">
       <tr>
-        <td valign="top"><b>Attribute</b></td>
-        <td valign="top"><b>Description</b></td>
-        <td align="center" valign="top"><b>Required</b></td>
+        <th scope="col">Attribute</th>
+        <th scope="col">Description</th>
+        <th scope="col">Required</th>
       </tr>
       <tr>
-        <td valign="top">classname</td>
-        <td valign="top">The name of your class that implements
-          <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
+        <td>classname</td>
+        <td>The name of your class that
+        implements <code class="code">org.apache.tools.ant.types.selectors.FileSelector</code>.
         </td>
-        <td valign="top" align="center">Yes</td>
+        <td>Yes</td>
       </tr>
       <tr>
-        <td valign="top">classpath</td>
-        <td valign="top">The classpath to use in order to load the
-          custom selector class. If neither this classpath nor the
-          classpathref are specified, the class will be
-          loaded from the classpath that Ant uses.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>classpath</td>
+        <td>The classpath to use in order to load the custom selector class. If
+        neither <var>classpath</var> nor <var>classpathref</var> are specified, the class will be
+        loaded from the classpath that Ant uses.</td>
+        <td>No</td>
       </tr>
       <tr>
-        <td valign="top">classpathref</td>
-        <td valign="top">A reference to a classpath previously
-          defined. If neither this reference nor the
-          classpath above are specified, the class will be
-          loaded from the classpath that Ant uses.
-        </td>
-        <td valign="top" align="center">No</td>
+        <td>classpathref</td>
+        <td>A reference to a classpath previously defined. If neither <var>classpathref</var>
+        nor <var>classpath</var> are specified, the class will be loaded from the classpath that Ant
+        uses.</td>
+        <td>No</td>
       </tr>
     </table>
 
-    <p>Here is how you use <code>&lt;custom&gt;</code> to
-    use your class as a selector:
-    </p>
+    <p>Here is how you use <code>&lt;custom&gt;</code> to use your class as a selector:</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${mydir}&quot; includes=&quot;**/*&quot;&gt;
     &lt;custom classname=&quot;com.mydomain.MySelector&quot;&gt;
         &lt;param name=&quot;myattribute&quot; value=&quot;myvalue&quot;/&gt;
     &lt;/custom&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>A number of core selectors can also be used as custom selectors
-    by specifying their attributes using <code>&lt;param&gt;</code> elements. These
-    are</p>
+    <p>A number of core selectors can also be used as custom selectors by specifying their
+    attributes using <code>&lt;param&gt;</code> elements. These are</p>
 
     <ul>
       <li><a href="#containsselect">Contains Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.ContainsSelector</code>
+        classname <code class="code">org.apache.tools.ant.types.selectors.ContainsSelector</code>
       <li><a href="#dateselect">Date Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.DateSelector</code>
+        classname <code class="code">org.apache.tools.ant.types.selectors.DateSelector</code>
       <li><a href="#depthselect">Depth Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.DepthSelector</code>
+        classname <code class="code">org.apache.tools.ant.types.selectors.DepthSelector</code>
       <li><a href="#filenameselect">Filename Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.FilenameSelector</code>
+        classname <code class="code">org.apache.tools.ant.types.selectors.FilenameSelector</code>
       <li><a href="#sizeselect">Size Selector</a> with
-        classname <code>org.apache.tools.ant.types.selectors.SizeSelector</code>
+        classname <code class="code">org.apache.tools.ant.types.selectors.SizeSelector</code>
     </ul>
 
-    <p>Here is the example from the Depth Selector section rewritten
-    to use the selector through <code>&lt;custom&gt;</code>.</p>
+    <p>Here is the example from the Depth Selector section rewritten to use the selector
+    through <code>&lt;custom&gt;</code>.</p>
 
-    <blockquote><pre>
+    <pre>
 &lt;fileset dir=&quot;${doc.path}&quot; includes=&quot;**/*&quot;&gt;
     &lt;custom classname=&quot;org.apache.tools.ant.types.selectors.DepthSelector&quot;&gt;
         &lt;param name=&quot;max&quot; value=&quot;1&quot;/&gt;
     &lt;/custom&gt;
-&lt;/fileset&gt;
-</pre></blockquote>
+&lt;/fileset&gt;</pre>
 
-    <p>Selects all files in the base directory and one directory below
-    that.</p>
+    <p>Selects all files in the base directory and one directory below that.</p>
 
-    <p>For more details concerning writing your own selectors, consult
-    <a href="selectors-program.html">Programming Selectors in Ant</a>.</p>
-
-    
+    <p>For more details concerning writing your own selectors,
+    consult <a href="selectors-program.html">Programming Selectors in Ant</a>.</p>
 
   </body>
-
 </html>
diff --git a/manual/Types/tarfileset.html b/manual/Types/tarfileset.html
index 499ed79..d6dfefb 100644
--- a/manual/Types/tarfileset.html
+++ b/manual/Types/tarfileset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,169 +15,134 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
-  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>TarFileSet Type</title>
 </head>
 <body>
-<h2><a name="fileset">TarFileSet</a></h2>
+<h2 id="fileset">TarFileSet</h2>
 
-<p><em>TarFileSet</em> has been added as a stand-alone type in Apache Ant
-1.7.</p>
+<p><code>TarFileSet</code> has been a stand-alone type <em>since Apache Ant 1.7</em>.</p>
 
-<p>A <code>&lt;tarfileset&gt;</code> is a special form of a <code>&lt;<a
- href="fileset.html">fileset</a>&gt;</code> which can behave in 2
-different ways : <br>
-</p>
+<p>A <code>&lt;tarfileset&gt;</code> is a special form of
+a <code>&lt;<a href="fileset.html">fileset</a>&gt;</code> which can behave in 2 different ways:</p>
 <ul>
-  <li>When the <span style="font-style: italic;">src</span> attribute
-  is used - or a nested resource collection has been specified, the
-  tarfileset is populated with tar entries found in the file <span
-  style="font-style: italic;">src</span>.<br>
-  </li>
-  <li>When the <span style="font-style: italic;">dir</span> attribute
-is used, the tarfileset is populated with filesystem files found under <span
- style="font-style: italic;">dir</span>.<br>
-  </li>
+  <li>When the <var>src</var> attribute is used&mdash;or a nested resource collection has been
+  specified, the tarfileset is populated with tar entries found in the file <var>src</var>.</li>
+  <li>When the <var>dir</var> attribute is used, the tarfileset is populated with filesystem files
+  found under <var>dir</var>.</li>
 </ul>
-<p><code>&lt;tarfileset&gt;</code> supports all attributes of <code>&lt;<a
- href="fileset.html">fileset</a>&gt;</code>
- in addition to those listed below.  Note that tar archives in general
- don't contain entries with leading slashes so you shouldn't use
- include/exclude patterns that start with slashes either.
-</p>
-<p>A tarfileset can be defined with the <span style="font-style:
-italic;">id </span>attribute and referred to with the <span
-style="font-style: italic;">refid</span> attribute.  This is also true
-for tarfileset which has been added in Ant 1.7.<br>
-</p>
+<p><code>&lt;tarfileset&gt;</code> supports all attributes
+of <code>&lt;<a href="fileset.html">fileset</a>&gt;</code> in addition to those listed below.  Note
+that tar archives in general don't contain entries with leading slashes so you shouldn't use
+include/exclude patterns that start with slashes either.</p>
+<p><em>Since Ant 1.7</em>, a tarfileset can be defined with the <var>id</var> attribute and referred
+to with the <var>refid</var> attribute.</p>
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tbody>
     <tr>
-      <td valign="top"><b>Attribute</b></td>
-      <td valign="top"><b>Description</b></td>
-      <td valign="top" align="center"><b>Required</b></td>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="top">prefix</td>
-      <td valign="top">all files in the fileset are prefixed with that 
-path in the archive.</td>
-      <td align="center" valign="top">No</td>
+      <td>prefix</td>
+      <td>all files in the fileset are prefixed with that path in the archive.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">fullpath</td>
-      <td valign="top">the file described by the fileset is placed at  
-that exact location in the archive.</td>
-      <td align="center" valign="top">No</td>
+      <td>fullpath</td>
+      <td>the file described by the fileset is placed at that exact location in the archive.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">src</td>
-      <td valign="top">may be used in place of the <i>dir</i> attribute
- to specify a tar file whose contents will be extracted and     included
-in the archive.</td>
-      <td align="center" valign="top">No</td>
+      <td>src</td>
+      <td>may be used in place of the <var>dir</var> attribute to specify a tar file whose contents
+        will be extracted and included in the archive.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">filemode</td>
-      <td valign="top">A 3 digit octal string, specify the user, group 
-and other modes in the standard Unix fashion.  Only applies to    
-plain files.  Default is 644.</td>
-      <td align="center" valign="top">No</td>
+      <td>filemode</td>
+      <td>A 3 digit octal string, specify the user, group and other modes in the standard Unix
+        fashion.  Only applies to plain files.</td>
+      <td>No; default is <q>644</q></td>
     </tr>
     <tr>
-      <td valign="top">dirmode</td>
-      <td valign="top">A 3 digit octal string, specify the user, group 
-and other modes in the standard Unix fashion.  Only applies to    
-directories.  Default is 755.</td>
-      <td align="center" valign="top">No</td>
+      <td>dirmode</td>
+      <td>A 3 digit octal string, specify the user, group and other modes in the standard Unix
+        fashion.  Only applies to directories.</td>
+      <td>No; default is <q>755</q></td>
     </tr>
     <tr>
-      <td valign="top">username</td>
-      <td valign="top">The username for the tar entry. This is not the same as the UID.
-       </td>
-      <td align="center" valign="top">No</td>
+      <td>username</td>
+      <td>The username for the tar entry. This is not the same as the UID.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">group</td>
-      <td valign="top">The groupname for the tar entry. This is not the same as the GID.
-      </td>
-      <td align="center" valign="top">No</td>
+      <td>group</td>
+      <td>The groupname for the tar entry. This is not the same as the GID.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">uid</td>
-      <td valign="top">The user identifier (UID) for the tar entry. This is an integer value
-        and is not the same as the username.
-      </td>
-      <td align="center" valign="top">No</td>
+      <td>uid</td>
+      <td>The user identifier (UID) for the tar entry. This is an integer value and is not the
+        same as the username.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">gid</td>
-      <td valign="top">The group identifier (GID) for the tar entry.
-      </td>
-      <td align="center" valign="top">No</td>
+      <td>gid</td>
+      <td>The group identifier (GID) for the tar entry.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">erroronmissingarchive</td>
-      <td valign="top">
-        Specify what happens if the archive does not exist.
-        If true, a build error will happen; if false, the fileset
-        will be ignored/empty.
-        Defaults to true.
-        <em>Since Ant 1.8.0</em>
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>erroronmissingarchive</td>
+      <td>Specify what happens if the archive does not exist.  If <q>true</q>, a build error will
+        happen; if <q>false</q>, the fileset will be ignored/empty.  <em>Since Ant 1.8.0</em></td>
+      <td>No; defaults to <q>true</q></td>
     </tr>
     <tr>
-      <td valign="top">encoding</td>
-      <td valign="top">The character encoding to use for filenames
-      inside the zip file.  For a list of possible values see the <a
-      href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">Supported Encodings</a>.
-      Defaults to the platform's default character encoding.
-        <em>Since Ant 1.9.5</em>
-      <td align="center" valign="top">No</td>
+      <td>encoding</td>
+      <td>The character encoding to use for filenames inside the zip file.  For a list of possible
+      values see
+      the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+      target="_top">Supported Encodings</a>.  <em>Since Ant 1.9.5</em></td>
+      <td>No; defaults to default JVM character encoding</td>
     </tr>
   </tbody>
 </table>
-<p>The <i>fullpath</i> attribute can only be set for filesets that
-represent a single file. The <i>prefix</i> and <i>fullpath</i>
-attributes cannot both be set on the same fileset.</p>
-<p>When using the <i>src</i> attribute, include and exclude patterns
-may be used to specify a subset of the archive for inclusion in the
-archive as with the <i>dir</i> attribute.</p>
+<p>The <var>fullpath</var> attribute can only be set for filesets that represent a single
+file. The <var>prefix</var> and <var>fullpath</var> attributes cannot both be set on the same
+fileset.</p>
+<p>When using the <var>src</var> attribute, <var>include</var> and <var>exclude</var> patterns may
+be used to specify a subset of the archive for inclusion in the archive as with the <var>dir</var>
+attribute.</p>
 
-<p>Please note that currently only the <a
-href="../Tasks/tar.html">tar</a> task uses the permission and
-ownership attributes.</p>
+<p>Please note that currently only the <a href="../Tasks/tar.html">tar</a> task uses the permission
+and ownership attributes.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>any <a href="resources.html">resource</a> or single element
-resource collection</h4>
+<h4>any <a href="resources.html">resource</a> or single element resource collection</h4>
 
 <p>The specified resource will be used as src.</p>
 
 <h4>Examples</h4>
-<blockquote>
+
 <pre>
-  &lt;copy todir="some-dir"&gt;
-    &lt;tarfileset includes="lib/**"&gt;
-      &lt;bzip2resource&gt;
-        &lt;url url="http://example.org/dist/some-archive.tar.bz2"/&gt;
-      &lt;/bzip2resource&gt;
-    &lt;/tarfileset&gt;
-  &lt;/copy&gt;
-      </pre></blockquote>
+&lt;copy todir="some-dir"&gt;
+ &lt;tarfileset includes="lib/**"&gt;
+   &lt;bzip2resource&gt;
+     &lt;url url="https://example.org/dist/some-archive.tar.bz2"/&gt;
+   &lt;/bzip2resource&gt;
+ &lt;/tarfileset&gt;
+&lt;/copy&gt;</pre>
 
-<p>downloads the archive some-archive.tar.bz2, uncompresses and
-extracts it on the fly, copies the contents of the lib directory into
-some-dir and discards the rest of the archive.  File timestamps will
-be compared between the archive's entries and files inside the target
-directory, no files get overwritten unless they are out-of-date.</p>
-
+<p>downloads the archive <samp>some-archive.tar.bz2</samp>, uncompresses and extracts it on the fly,
+copies the contents of the <samp>lib</samp> directory into <samp>some-dir</samp> and discards the
+rest of the archive.  File timestamps will be compared between the archive's entries and files
+inside the target directory, no files get overwritten unless they are out-of-date.</p>
 
 </body>
 </html>
diff --git a/manual/Types/xmlcatalog.html b/manual/Types/xmlcatalog.html
index a0ddafc..4650c8a 100644
--- a/manual/Types/xmlcatalog.html
+++ b/manual/Types/xmlcatalog.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,293 +15,228 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>XMLCatalog Type</title>
 </head>
 
 <body>
 
-<h2><a name="XMLCatalog">XMLCatalog</a></h2>
+<h2 id="XMLCatalog">XMLCatalog</h2>
 
-<p>An XMLCatalog is a catalog of public resources such as DTDs or
-entities that are referenced in an XML document.  Catalogs are
-typically used to make web references to resources point to a locally
+<p>An XMLCatalog is a catalog of public resources such as DTDs or entities that are referenced in an
+XML document.  Catalogs are typically used to make web references to resources point to a locally
 cached copy of the resource.</p>
 
-<p>This allows the XML Parser, XSLT Processor or other consumer of XML 
-documents
-to efficiently allow a local substitution for a resource available on the 
-web.
-</p>
-<p><b>Note:</b> This task <em>uses, but does not depend on</em> external
-libraries not included in the Apache Ant distribution.  See <a
-  href="../install.html#librarydependencies">Library Dependencies</a> for more
-information.</p>
-<p>This data type provides a catalog of resource locations based
-on the <a
-href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
-OASIS "Open Catalog" standard</a>.  The catalog entries are used
-both for Entity resolution and URI resolution, in accordance with
-the <code>org.xml.sax.EntityResolver</code> and <code>
-javax.xml.transform.URIResolver</code> interfaces as defined
-in the <a href="https://jaxp.dev.java.net/">Java API for XML
-Processing (JAXP) Specification</a>.</p>
-<p>For example, in a <code>web.xml</code> file, the DTD is referenced as:
+<p>This allows the XML Parser, XSLT Processor or other consumer of XML documents to efficiently
+allow a local substitution for a resource available on the web.</p>
+<p><strong>Note:</strong> This task <em>uses, but does not depend on</em> external libraries not
+included in the Apache Ant distribution.  See <a href="../install.html#librarydependencies">Library
+Dependencies</a> for more information.</p>
+<p>This data type provides a catalog of resource locations based on
+the <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html"
+target="_top">OASIS XML Catalog standard</a>.  The catalog entries are used both for Entity
+resolution and URI resolution, in accordance with
+the <code class="code">org.xml.sax.EntityResolver</code>
+and <code class="code">javax.xml.transform.URIResolver</code> interfaces as defined in
+the <a href="https://download.oracle.com/otn-pub/jcp/jaxp-1_6-mrel3-spec/JAXP1_6-FinalSpec.pdf"
+target="_top">Java API for XML Processing (JAXP) Specification</a>.</p>
+<p>For example, in a <code>web.xml</code> file, the DTD is referenced as:</p>
 <pre>
 &lt;!DOCTYPE web-app PUBLIC &quot;-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN&quot;
-  &quot;http://java.sun.com/j2ee/dtds/web-app_2_2.dtd&quot;&gt;
-</pre>
-The XML processor, without XMLCatalog support, would need to retrieve the 
-DTD from
-the URL specified whenever validation of the document was required.
-</p>
-<p>This can be very time consuming during the build process,
-especially where network throughput is limited.  Alternatively, you
-can do the following:
+  &quot;http://java.sun.com/j2ee/dtds/web-app_2_2.dtd&quot;&gt;</pre>
+<p>The XML processor, without XMLCatalog support, would need to retrieve the DTD from the URL
+specified whenever validation of the document was required.</p>
+<p>This can be very time consuming during the build process, especially where network throughput
+is limited.  Alternatively, you can do the following:</p>
 <ol>
-<li>Copy <code>web-app_2_2.dtd</code> onto your local disk somewhere (either in the
-filesystem or even embedded inside a jar or zip file on the classpath).</li>
-<li>Create an <code>&lt;xmlcatalog&gt;</code> with a <code>&lt;dtd&gt;</code> 
-element whose <code>location</code> attribute points to the file.</li>
-<li>Success! The XML processor will now use the local copy instead of calling out
-to the internet.</li>
+<li>Copy <samp>web-app_2_2.dtd</samp> onto your local disk somewhere (either in the filesystem
+or even embedded inside a jar or zip file on the classpath).</li>
+<li>Create an <code>&lt;xmlcatalog&gt;</code> with a <code>&lt;dtd&gt;</code> element
+whose <var>location</var> attribute points to the file.</li>
+<li>Success! The XML processor will now use the local copy instead of calling out to the
+internet.</li>
 </ol>
-</p>
-<p>XMLCatalogs can appear inside tasks
-that support this feature or at the same level as <code>target</code>
-- i.e., as children of <code>project</code> for reuse across different 
-tasks,
-e.g. XML Validation and XSLT Transformation.  The XML Validate task
-uses XMLCatalogs for entity resolution.  The XSLT Transformation
-task uses XMLCatalogs for both entity and URI resolution.</p>
-<p>XMLCatalogs are specified as either a reference to another
-XMLCatalog, defined previously in a build file, or as a list of
-<code>dtd</code> or <code>entity</code> locations.  In addition,
-external catalog files may be specified in a nested <code>catalogpath</code> ,
-but they will be ignored unless the resolver library from
-xml-commons is available in the system classpath.  <b>Due to backwards
-incompatible changes in the resolver code after the release of
-resolver 1.0, Ant will not support resolver.jar in version 1.0 - we
-expect a resolver release 1.1 to happen before Ant 1.6 gets
-released.</b>  A separate classpath for entity resolution may be
-specified inline via nested <code>classpath</code> elements; otherwise
+<p>XMLCatalogs can appear inside tasks that support this feature or at the same level
+as <code>target</code>&mdash;i.e., as children of <code>project</code> for reuse across
+different tasks, e.g. XML Validation and XSLT Transformation.  The XML Validate task uses
+XMLCatalogs for entity resolution.  The XSLT Transformation task uses XMLCatalogs for both
+entity and URI resolution.</p>
+<p>XMLCatalogs are specified as either a reference to another XMLCatalog, defined previously in
+a build file, or as a list of <code>dtd</code> or <code>entity</code> locations.  In addition,
+external catalog files may be specified in a nested <code>catalogpath</code>, but they will be
+ignored unless the resolver library from xml-commons is available in the system
+classpath.  <strong>Due to backwards incompatible changes in the resolver code after the release
+of resolver 1.0, Ant supports only resolver 1.1 or later.</strong>  A separate classpath for
+entity resolution may be specified inline via nested <code>classpath</code> elements; otherwise
 the system classpath is used for this as well.</p>
-<p>XMLCatalogs can also be nested inside other XMLCatalogs.  For
-example, a "superset" XMLCatalog could be made by including several
-nested XMLCatalogs that referred to other, previously defined
-XMLCatalogs.</p>
-<p>Resource locations can be specified either in-line or in
-external catalog file(s), or both.  In order to use an external
-catalog file, the xml-commons resolver library ("resolver.jar")
-must be in your path.  External catalog files may be either <a
-href="http://oasis-open.org/committees/entity/background/9401.html">
-plain text format</a> or <a
-href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
-XML format</a>.  If the xml-commons resolver library is not found in the
-classpath, external catalog files, specified in <code>catalogpath</code>, 
-will be ignored and a warning
-will be logged.  In this case, however, processing of inline entries will
-proceed normally.</p>
-<p>Currently, only <code>&lt;dtd&gt;</code> and
-<code>&lt;entity&gt;</code> elements may be specified inline; these
-roughly correspond to OASIS catalog entry types <code>PUBLIC</code> and
-<code>URI</code> respectively.  By contrast, external catalog files
-may use any of the entry types defined in the 
-<a href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
-+OASIS specification</a>.</p>
-<h3><a name="ResolverAlgorithm">Entity/DTD/URI Resolution Algorithm</a></h3>
-
-When an entity, DTD, or URI is looked up by the XML processor, the
-XMLCatalog searches its list of entries to see if any match.  That is,
-it attempts to match the <code>publicId</code> attribute of each entry
-with the PublicID or URI of the entity to be resolved.  Assuming a
-matching entry is found, XMLCatalog then executes the following steps:
+<p>XMLCatalogs can also be nested inside other XMLCatalogs.  For example, a "superset"
+XMLCatalog could be made by including several nested XMLCatalogs that referred to other,
+previously defined XMLCatalogs.</p>
+<p>Resource locations can be specified either in-line or in external catalog file(s), or both.  In
+order to use an external catalog file, the xml-commons resolver library (<samp>resolver.jar</samp>)
+must be in your path.  External catalog files may be
+either <a href="https://oasis-open.org/committees/entity/background/9401.html" target="_top">plain
+text format</a> or <a href="https://www.oasis-open.org/committees/entity/spec-2001-08-06.html"
+target="_top">XML format</a>.  If the xml-commons resolver library is not found in the classpath,
+external catalog files, specified in <code>catalogpath</code>, will be ignored and a warning will be
+logged.  In this case, however, processing of inline entries will proceed normally.</p>
+<p>Currently, only <code>&lt;dtd&gt;</code> and <code>&lt;entity&gt;</code> elements may be
+specified inline; these roughly correspond to OASIS catalog entry types <code>PUBLIC</code>
+and <code>URI</code> respectively.  By contrast, external catalog files may use any of the entry
+types defined in
+the <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html"
+target="_top">OASIS specification</a>.</p>
+<h3 id="ResolverAlgorithm">Entity/DTD/URI resolution algorithm</h3>
+<p>When an entity, DTD, or URI is looked up by the XML processor, the XMLCatalog searches its list
+of entries to see if any match.  That is, it attempts to match the <var>publicId</var> attribute of
+each entry with the PublicID or URI of the entity to be resolved.  Assuming a matching entry is
+found, XMLCatalog then executes the following steps:</p>
 
 <h4>1. Filesystem lookup</h4>
 
-<p>The <code>location</code> is first looked up in the filesystem.  If
-the <code>location</code> is a relative path, the ant project basedir
-attribute is used as the base directory.  If the <code>location</code>
-specifies an absolute path, it is used as is.  Once we have an
-absolute path in hand, we check to see if a valid and readable file
-exists at that path.  If so, we are done.  If not, we proceed to the
-next step.</p>
+<p>The <var>location</var> is first looked up in the filesystem.  If the <var>location</var> is a
+relative path, the Ant project <var>basedir</var> attribute is used as the base directory.  If
+the <var>location</var> specifies an absolute path, it is used as is.  Once we have an absolute path
+in hand, we check to see if a valid and readable file exists at that path.  If so, we are done.  If
+not, we proceed to the next step.</p>
 
 <h4>2. Classpath lookup</h4>
 
-<p>The <code>location</code> is next looked up in the classpath.
-Recall that jar files are merely fancy zip files.  For classpath
-lookup, the <code>location</code> is used as is (no base is
-prepended).  We use a Classloader to attempt to load the resource from
-the classpath.  For example, if hello.jar is in the classpath and it
-contains <code>foo/bar/blat.dtd</code> it will resolve an entity whose
-<code>location</code> is <code>foo/bar/blat.dtd</code>.  Of course, it
-will <em>not</em> resolve an entity whose <code>location</code> is
-<code>blat.dtd</code>.
-
+<p>The <var>location</var> is next looked up in the classpath.  Recall that jar files are merely
+fancy zip files.  For classpath lookup, the <var>location</var> is used as is (no base is
+prepended).  We use a Classloader to attempt to load the resource from the classpath.  For example,
+if <samp>hello.jar</samp> is in the classpath and it contains <samp>foo/bar/blat.dtd</samp> it will
+resolve an entity whose <var>location</var> is <samp>foo/bar/blat.dtd</samp>.  Of course, it
+will <em>not</em> resolve an entity whose <var>location</var> is <code>blat.dtd</code>.</p>
 
 <h4>3a. Apache xml-commons resolver lookup</h4>
 
-<p>What happens next depends on whether the resolver library from
-xml-commons is available on the classpath.  If so, we defer all
-further attempts at resolving to it.  The resolver library supports
-extremely sophisticated functionality like URL rewriting and so on,
-which can be accessed by making the appropriate entries in external
-catalog files (XMLCatalog does not yet provide inline support for all
-of the entries defined in the <a
-href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">OASIS
-standard</a>).</p>
+<p>What happens next depends on whether the resolver library from xml-commons is available on the
+classpath.  If so, we defer all further attempts at resolving to it.  The resolver library supports
+extremely sophisticated functionality like URL rewriting and so on, which can be accessed by making
+the appropriate entries in external catalog files (XMLCatalog does not yet provide inline support
+for all of the entries defined in
+the <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html"
+target="_top">OASIS standard</a>).</p>
 
 <h4>3. URL-space lookup</h4>
 
-<p>Finally, we attempt to make a URL out of the <code>location</code>.
-At first this may seem like this would defeat the purpose of
-XMLCatalogs -- why go back out to the internet?  But in fact, this can
-be used to (in a sense) implement HTTP redirects, substituting one URL
-for another.  The mapped-to URL might also be served by a local web
-server.  If the URL resolves to a valid and readable resource, we are
-done.  Otherwise, we give up.  In this case, the XML processor will
-perform its normal resolution algorithm.  Depending on the processor
-configuration, further resolution failures may or may not result in
-fatal (i.e. build-ending) errors.</p>
+<p>Finally, we attempt to make a URL out of the <var>location</var>.  At first this may seem like
+this would defeat the purpose of XMLCatalogs&mdash;why go back out to the internet?  But in fact,
+this can be used to (in a sense) implement HTTP redirects, substituting one URL for another.  The
+mapped-to URL might also be served by a local web server.  If the URL resolves to a valid and
+readable resource, we are done.  Otherwise, we give up.  In this case, the XML processor will
+perform its normal resolution algorithm.  Depending on the processor configuration, further
+resolution failures may or may not result in fatal (i.e. build-ending) errors.</p>
 
 <h3>XMLCatalog attributes</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">id</td>
-    <td valign="top">a unique name for an XMLCatalog, used for referencing 
-the
-    XMLCatalog's contents from another XMLCatalog</td>
-    <td valign="top" align="center">No</td>
+    <td>id</td>
+    <td>a unique name for an XMLCatalog, used for referencing the XMLCatalog's contents from
+    another XMLCatalog</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">refid</td>
-    <td valign="top">the <code>id</code> of another XMLCatalog whose 
-contents
-    you would like to be used for this XMLCatalog</td>
-    <td valign="top" align="center">No</td>
+    <td>refid</td>
+    <td>the <var>id</var> of another XMLCatalog whose contents you would like to be used for
+    this XMLCatalog</td>
+    <td>No</td>
   </tr>
 </table>
 
 <h3>XMLCatalog nested elements</h3>
 <h4>dtd/entity</h4>
-<p>The <code>dtd</code> and <code>entity</code> elements used to specify
-XMLCatalogs are identical in their structure</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<p>The <code>dtd</code> and <code>entity</code> elements used to specify XMLCatalogs are
+identical in their structure</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">publicId</td>
-    <td valign="top">The public identifier used when defining a dtd or 
-entity,
-    e.g. <code>&quot;-//Sun Microsystems, Inc.//DTD Web Application 
-2.2//EN&quot;</code>
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>publicId</td>
+    <td>The public identifier used when defining a dtd or entity, e.g.
+    <code>&quot;-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN&quot;</code></td>
+    <td>Yes</td>
   </tr>
   <tr>
-    <td valign="top">location</td>
-    <td valign="top">The location of the local replacement to be used for 
-the public identifier specified. This may be specified as a file name, 
-resource name found on the classpath, or a URL.  Relative paths will
-be resolved according to the base, which by default is the Ant project
-basedir.
-    </td>
-    <td valign="top" align="center">Yes</td>
+    <td>location</td>
+    <td>The location of the local replacement to be used for the public identifier specified. This
+    may be specified as a file name, resource name found on the classpath, or a URL.  Relative paths
+    will be resolved according to the base, which by default is the Ant
+    project <var>basedir</var>.</td>
+    <td>Yes</td>
   </tr>
 </table>
 <h4>classpath</h4>
-<p>The classpath to use for <a href="#ResolverAlgorithm">entity
-resolution</a>.  The nested <code>&lt;classpath&gt;</code> is a
-<a href="../using.html#path">path</a>-like structure.</p>
+<p>The classpath to use for <a href="#ResolverAlgorithm">entity resolution</a>.  The
+nested <code>&lt;classpath&gt;</code> is a <a href="../using.html#path">path</a>-like structure.</p>
 <h4>catalogpath</h4>
-<p>
-The nested <code>catalogpath</code> element is a <a
-href="../using.html#path">path</a>-like structure listing catalog files to
-search.  All files in this path are assumed to be OASIS catalog files, in
-either
-<a href="http://oasis-open.org/committees/entity/background/9401.html">
-plain text format</a> or <a
-href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
-XML format</a>. Entries specifying nonexistent files will be ignored. If the
-resolver library from xml-commons is not available in the classpath, all
-<code>catalogpaths</code> will be ignored and a warning will be logged.
-</p>
+<p>The nested <code>catalogpath</code> element is a <a href="../using.html#path">path</a>-like
+structure listing catalog files to search.  All files in this path are assumed to be OASIS catalog
+files, in either <a href="https://oasis-open.org/committees/entity/background/9401.html"
+target="_top">plain text format</a>
+or <a href="https://www.oasis-open.org/committees/entity/spec-2001-08-06.html" target="_top">XML
+format</a>. Entries specifying nonexistent files will be ignored. If the resolver library from
+xml-commons is not available in the classpath, all <code>catalogpath</code>s will be ignored and a
+warning will be logged.</p>
 <h3>Examples</h3>
-<p>Set up an XMLCatalog with a single dtd referenced locally in a user's 
-home 
-directory:</p>
-<blockquote><pre>
-    &lt;xmlcatalog&gt;
-        &lt;dtd 
-            publicId=&quot;-//OASIS//DTD DocBook XML V4.1.2//EN&quot;
-            location=&quot;/home/dion/downloads/docbook/docbookx.dtd&quot;/&gt;
-    &lt;/xmlcatalog&gt;
-</pre></blockquote>
-<p>Set up an XMLCatalog with a multiple dtds to be found either in the
-filesystem (relative to the Ant project basedir) or in the classpath:
+<p>Set up an XMLCatalog with a single DTD referenced locally in a user's home directory:</p>
+<pre>
+&lt;xmlcatalog&gt;
+    &lt;dtd publicId=&quot;-//OASIS//DTD DocBook XML V4.1.2//EN&quot;
+         location=&quot;/home/dion/downloads/docbook/docbookx.dtd&quot;/&gt;
+&lt;/xmlcatalog&gt;</pre>
+<p>Set up an XMLCatalog with a multiple DTDs to be found either in the filesystem (relative to
+the Ant project <var>basedir</var>) or in the classpath:
 </p>
-<blockquote><pre>
-    &lt;xmlcatalog id=&quot;commonDTDs&quot;&gt;
-        &lt;dtd 
-            publicId=&quot;-//OASIS//DTD DocBook XML V4.1.2//EN&quot;
-            location=&quot;docbook/docbookx.dtd&quot;/&gt;
-        &lt;dtd 
-            publicId=&quot;-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN&quot;
-            location=&quot;web-app_2_2.dtd&quot;/&gt;
-    &lt;/xmlcatalog&gt;
-</pre></blockquote>
+<pre>
+&lt;xmlcatalog id=&quot;commonDTDs&quot;&gt;
+    &lt;dtd publicId=&quot;-//OASIS//DTD DocBook XML V4.1.2//EN&quot;
+         location=&quot;docbook/docbookx.dtd&quot;/&gt;
+    &lt;dtd publicId=&quot;-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN&quot;
+         location=&quot;web-app_2_2.dtd&quot;/&gt;
+&lt;/xmlcatalog&gt;</pre>
 
-<p>Set up an XMLCatalog with a combination of DTDs and entities as
-well as a nested XMLCatalog and external catalog files in both
-formats:</p>
+<p>Set up an XMLCatalog with a combination of DTDs and entities as well as a nested XMLCatalog
+and external catalog files in both formats:</p>
 
-<blockquote><pre>
-    &lt;xmlcatalog id=&quot;allcatalogs&quot;&gt;
-        &lt;dtd 
-            publicId=&quot;-//ArielPartners//DTD XML Article V1.0//EN&quot;
-            location=&quot;com/arielpartners/knowledgebase/dtd/article.dtd&quot;/&gt;
-        &lt;entity 
-            publicId=&quot;LargeLogo&quot;
+<pre>
+&lt;xmlcatalog id=&quot;allcatalogs&quot;&gt;
+    &lt;dtd publicId=&quot;-//ArielPartners//DTD XML Article V1.0//EN&quot;
+         location=&quot;com/arielpartners/knowledgebase/dtd/article.dtd&quot;/&gt;
+    &lt;entity publicId=&quot;LargeLogo&quot;
             location=&quot;com/arielpartners/images/ariel-logo-large.gif&quot;/&gt;
-        &lt;xmlcatalog refid="commonDTDs"/&gt;
-            &lt;catalogpath&gt;
-                &lt;pathelement location="/etc/sgml/catalog"/&gt;
-                &lt;fileset 
-                    dir=&quot;/anetwork/drive&quot;
-                    includes=&quot;**/catalog&quot;/&gt;
-                &lt;fileset 
-                    dir=&quot;/my/catalogs&quot;
-                    includes=&quot;**/catalog.xml&quot;/&gt;
-            &lt;/catalogpath&gt;
-        &lt;/xmlcatalog&gt;
+    &lt;xmlcatalog refid="commonDTDs"/&gt;
+        &lt;catalogpath&gt;
+            &lt;pathelement location="/etc/sgml/catalog"/&gt;
+            &lt;fileset dir=&quot;/anetwork/drive&quot;
+                     includes=&quot;**/catalog&quot;/&gt;
+            &lt;fileset dir=&quot;/my/catalogs&quot;
+                     includes=&quot;**/catalog.xml&quot;/&gt;
+        &lt;/catalogpath&gt;
     &lt;/xmlcatalog&gt;
-</pre></blockquote>
+&lt;/xmlcatalog&gt;</pre>
 <p>To reference the above XMLCatalog in an <code>xslt</code> task:<p>
-<blockquote><pre>
-    &lt;xslt basedir="${source.doc}"
-           destdir="${dest.xdocs}"
-           extension=".xml"
-           style="${source.xsl.converter.docbook}"
-           includes="**/*.xml"
-           force="true"&gt;
-        &lt;xmlcatalog refid=&quot;allcatalogs&quot;/&gt;
-    &lt;/xslt&gt;
-</pre></blockquote>
-
-
+<pre>
+&lt;xslt basedir="${source.doc}"
+      destdir="${dest.xdocs}"
+      extension=".xml"
+      style="${source.xsl.converter.docbook}"
+      includes="**/*.xml"
+      force="true"&gt;
+    &lt;xmlcatalog refid=&quot;allcatalogs&quot;/&gt;
+&lt;/xslt&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/Types/zipfileset.html b/manual/Types/zipfileset.html
index 955e271..7150fda 100644
--- a/manual/Types/zipfileset.html
+++ b/manual/Types/zipfileset.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,135 +15,115 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
-  <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>ZipFileSet Type</title>
 </head>
 <body>
-<h2><a name="fileset">ZipFileSet</a></h2>
+<h2 id="fileset">ZipFileSet</h2>
 
-<p>A <code>&lt;zipfileset&gt;</code> is a special form of a <code>&lt;<a
- href="fileset.html">fileset</a>&gt;</code> which can behave in 2
-different ways : <br>
-</p>
+<p>A <code>&lt;zipfileset&gt;</code> is a special form of
+a <code>&lt;<a href="fileset.html">fileset</a>&gt;</code> which can behave in 2 different ways:</p>
 <ul>
-  <li>When the <span style="font-style: italic;">src</span> attribute
-  is used - or a nested resource collection has been specified
-  (<em>since Apache Ant 1.7</em>), the zipfileset is populated with 
-  zip entries found in the file <span style="font-style:
-  italic;">src</span>.<br>
-  </li>
-  <li>When the <span style="font-style: italic;">dir</span> attribute
-is used, the zipfileset is populated with filesystem files found under <span
- style="font-style: italic;">dir</span>.<br>
-  </li>
+  <li>When the <var>src</var> attribute is used&mdash;or a nested resource collection has been
+    specified (<em>since Apache Ant 1.7</em>), the zipfileset is populated with zip entries found in
+    the file <var>src</var>.</li>
+  <li>When the <var>dir</var> attribute is used, the zipfileset is populated with filesystem files
+    found under <var>dir</var>.</li>
 </ul>
-<p><code>&lt;zipfileset&gt;</code> supports all attributes of <code>&lt;<a
- href="fileset.html">fileset</a>&gt;</code>
- in addition to those listed below.  Note that zip archives in general
- don't contain entries with leading slashes so you shouldn't use
- include/exclude patterns that start with slashes either.</p>
+<p><code>&lt;zipfileset&gt;</code> supports all attributes
+of <code>&lt;<a href="fileset.html">fileset</a>&gt;</code> in addition to those listed below.  Note
+that zip archives in general don't contain entries with leading slashes so you shouldn't
+use <var>includes</var>/<var>excludes</var> patterns that start with slashes either.</p>
 
-<p>Since Ant 1.6, a zipfileset can be defined with the <span
- style="font-style: italic;">id </span>attribute and referred to with
-the <span style="font-style: italic;">refid</span> attribute.<br>
-</p>
+<p><em>Since Ant 1.6</em>, a zipfileset can be defined with the <var>id</var> attribute and referred
+to with the <var>refid</var> attribute.</p>
+
 <h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+<table class="attr">
   <tbody>
     <tr>
-      <td valign="top"><b>Attribute</b></td>
-      <td valign="top"><b>Description</b></td>
-      <td valign="top" align="center"><b>Required</b></td>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="top">prefix</td>
-      <td valign="top">all files in the fileset are prefixed with that 
-path in the archive.</td>
-      <td align="center" valign="top">No</td>
+      <td>prefix</td>
+      <td>all files in the fileset are prefixed with that path in the archive.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">fullpath</td>
-      <td valign="top">the file described by the fileset is placed at  
-that exact location in the archive.</td>
-      <td align="center" valign="top">No</td>
+      <td>fullpath</td>
+      <td>the file described by the fileset is placed at that exact location in the archive.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">src</td>
-      <td valign="top">may be used in place of the <i>dir</i> attribute
- to specify a zip file whose contents will be extracted and     included
-in the archive.</td>
-      <td align="center" valign="top">No</td>
+      <td>src</td>
+      <td>may be used in place of the <var>dir</var> attribute to specify a zip file whose contents
+        will be extracted and included in the archive.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">filemode</td>
-      <td valign="top">A 3 digit octal string, specify the user, group 
-and other modes in the standard Unix fashion.  Only applies to    
-plain files.  Default is 644. <em>since Ant 1.5.2</em>.</td>
-      <td align="center" valign="top">No</td>
+      <td>filemode</td>
+      <td>A 3 digit octal string, specify the user, group and other modes in the standard Unix
+        fashion. Only applies to plain files. <em>Since Ant 1.5.2</em></td>
+      <td>No; default is <q>644</q></td>
     </tr>
     <tr>
-      <td valign="top">dirmode</td>
-      <td valign="top">A 3 digit octal string, specify the user, group 
-and other modes in the standard Unix fashion.  Only applies to    
-directories.  Default is 755. <em>since Ant 1.5.2</em>.</td>
-      <td align="center" valign="top">No</td>
+      <td>dirmode</td>
+      <td>A 3 digit octal string, specify the user, group and other modes in the standard Unix
+        fashion. Only applies to directories. <em>Since Ant 1.5.2</em></td>
+      <td>No; default is <q>755</q></td>
     </tr>
     <tr>
-      <td valign="top">encoding</td>
-      <td valign="top">The character encoding to use for filenames
-      inside the zip file.  For a list of possible values see the <a
-      href="http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html">Supported Encodings</a>.
-      Defaults to the platform's default character encoding.
-      <td align="center" valign="top">No</td>
+      <td>encoding</td>
+      <td>The character encoding to use for filenames inside the zip file.  For a list of possible
+        values see
+        the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html"
+        target="_top">Supported Encodings</a>.
+      <td>No; defaults to default JVM character encoding</td>
     </tr>
     <tr>
-      <td valign="top">erroronmissingarchive</td>
-      <td valign="top">
-        Specify what happens if the archive does not exist.
-        If true, a build error will happen; if false, the fileset
-        will be ignored/empty.
-        Defaults to true.
-        <em>Since Ant 1.8.0</em>
-      </td>
-      <td valign="top" align="center">No</td>
+      <td>erroronmissingarchive</td>
+      <td>Specify what happens if the archive does not exist.  If <q>true</q>, a build error will
+        happen; if <q>false</q>, the fileset will be ignored/empty.  <em>Since Ant 1.8.0</em></td>
+      <td>No; defaults to <q>true</q></td>
     </tr>
   </tbody>
 </table>
-<p>The <i>fullpath</i> attribute can only be set for filesets that
-represent a single file. The <i>prefix</i> and <i>fullpath</i>
-attributes cannot both be set on the same fileset.</p>
-<p>When using the <i>src</i> attribute, include and exclude patterns
-may be used to specify a subset of the archive for inclusion in the
-archive as with the <i>dir</i> attribute.</p>
+<p>The <var>fullpath</var> attribute can only be set for filesets that represent a single
+file. The <var>prefix</var> and <var>fullpath</var> attributes cannot both be set on the same
+fileset.</p>
+<p>When using the <var>src</var> attribute, <var>includes</var> and <var>excludes</var> patterns
+may be used to specify a subset of the archive for inclusion in the archive as with
+the <var>dir</var> attribute.</p>
 
-<p>Please note that currently only the <a
-href="../Tasks/tar.html">tar</a> and <a
-href="../Tasks/zip.html">zip</a> tasks use the permission.</p>
+<p>Please note that currently only the <a href="../Tasks/tar.html">tar</a>
+and <a href="../Tasks/zip.html">zip</a> tasks use the permission.</p>
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>any file system based <a href="resources.html">resource</a> or
-single element resource collection</h4>
+<h4>any file system based <a href="resources.html">resource</a> or single element resource
+collection</h4>
 
-<p>The specified resource will be used as src.</p>
+<p>The specified resource will be used as <var>src</var>.</p>
 
 <h4>Examples</h4>
-<blockquote>
-  <pre>  &lt;zip destfile="${dist}/manual.zip"&gt;<br>    &lt;zipfileset dir="htdocs/manual" prefix="docs/user-guide"/&gt;<br>    &lt;zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/&gt;<br>    &lt;zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/&gt;<br>  &lt;/zip&gt;<br></pre>
-  <p>zips all files in the <code>htdocs/manual</code> directory into
-the <code>docs/user-guide</code> directory in the archive, adds the
-file <code>ChangeLog27.txt</code> in the current directory as <code>docs/ChangeLog.txt</code>,
-and includes all the html files in <code>examples.zip</code> under <code>docs/examples</code>.
+<pre>
+&lt;zip destfile="${dist}/manual.zip"&gt;
+  &lt;zipfileset dir="htdocs/manual" prefix="docs/user-guide"/&gt;
+  &lt;zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/&gt;
+  &lt;zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/&gt;
+&lt;/zip&gt;</pre>
+<p>zips all files in the <samp>htdocs/manual</samp> directory into
+the <samp>docs/user-guide</samp> directory in the archive, adds the
+file <samp>ChangeLog27.txt</samp> in the current directory as <samp>docs/ChangeLog.txt</samp>,
+and includes all the html files in <samp>examples.zip</samp> under <samp>docs/examples</samp>.
 The archive might end up containing the files:</p>
-  <code> docs/user-guide/html/index.html<br>
-docs/ChangeLog.txt<br>
-docs/examples/index.html<br>
-  </code></blockquote>
-
+<pre>docs/user-guide/html/index.html
+docs/ChangeLog.txt
+docs/examples/index.html</pre>
 
 </body>
 </html>
diff --git a/manual/antexternal.html b/manual/antexternal.html
index 02d2f7b..39a49aa 100644
--- a/manual/antexternal.html
+++ b/manual/antexternal.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,8 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>InputHandler</title>
 </head>
@@ -29,16 +28,16 @@
 
 <p>Apache Ant provides a rich set of tasks for buildfile creators and
 administrators.  But what about programmers?  Can the functionality
-provided by Ant tasks be used in java programs?</p>
+provided by Ant tasks be used in Java programs?</p>
 
-<p>Yes, and its quite easy.  Before getting into the details, however, 
+<p>Yes, and its quite easy.  Before getting into the details, however,
 we should mention the pros and cons of this approach:
 
 <h3>Pros</h3>
 
-<table cellpadding="0" margin="0" border="1">
+<table>
 <tr>
-<td><b>Robust</b></td>
+<td><strong>Robust</strong></td>
 <td>
 Ant tasks are very robust.  They have been banged on by many people.
 Ant tasks have been used in many different contexts, and have
@@ -47,7 +46,7 @@
 </td>
 </tr>
 <tr>
-<td><b>Cross Platform</b></td>
+<td><strong>Cross Platform</strong></td>
 <td>
 Ant tasks are cross platform.  They have been tested on all of the
 volume platforms, and several rather unusual ones (Netware and OS/390, to
@@ -55,7 +54,7 @@
 </td>
 </tr>
 <tr>
-<td><b>Community Support</b></td>
+<td><strong>Community Support</strong></td>
 <td>
 Using Ant tasks means you have less of your own code to support.  Ant
 code is supported by the entire Apache Ant community.
@@ -65,18 +64,18 @@
 
 <h3>Cons</h3>
 
-<table cellpadding="0" margin="0" border="1">
+<table>
 <tr>
-<td><b>Dependency on Ant Libraries</b></td>
+<td><strong>Dependency on Ant Libraries</strong></td>
 <td>
 Obviously, if you use an Ant task in your code, you will have to add
-"ant.jar" to your path.  Of course, you could use a code optimizer to
+<q>ant.jar</q> to your path.  Of course, you could use a code optimizer to
 remove the unnecessary classes, but you will still probably require a
 chunk of the Ant core.
 </td>
 </tr>
 <tr>
-<td><b>Loss of Flexibility</b></td>
+<td><strong>Loss of Flexibility</strong></td>
 <td>
 At some point, if you find yourself having to modify the Ant code, it
 probably makes more sense to "roll your own."  Of course, you can
@@ -86,7 +85,6 @@
 </tr>
 </table>
 
-
 <h2>Example</h2>
 
 <p>Let's say you want to unzip a zip file programmatically from java
@@ -109,8 +107,8 @@
 </pre>
 
 <p>
-The Ant task to perform this function is
-<code>org.apache.tools.ant.taskdefs.Expand</code>.  All we have to do
+The Ant task to perform this function
+is <code>org.apache.tools.ant.taskdefs.Expand</code>.  All we have to do
 is create a dummy Ant <code>Project</code> and <code>Target</code>,
 set the <code>Task</code> parameters that would normally be set in a
 buildfile, and call <code>execute()</code>.</p>
@@ -121,8 +119,7 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Target;
 import org.apache.tools.ant.taskdefs.Expand;
-import java.io.File;
-</pre>
+import java.io.File;</pre>
 
 <p>The function call is actually quite simple:</p>
 
@@ -131,30 +128,30 @@
 
     final class Expander extends Expand {
         public Expander() {
- 	    project = new Project();
-	    project.init();
-	    taskType = "unzip";
-	    taskName = "unzip";
-	    target = new Target();
-	}	
+            project = new Project();
+            project.init();
+            taskType = "unzip";
+            taskName = "unzip";
+            target = new Target();
+        }
     }
     Expander expander = new Expander();
     expander.setSrc(new File(zipfile));
     expander.setDest(new File(destdir));
     expander.execute();
-</pre>
+}</pre>
 
 <p>In actual practice, you will probably want to add your own error
 handling code and you may not want to use a local inner class.
 However, the point of the example is to show how an Ant task can be
 called programmatically in relatively few lines of code.</p>
 
-<p>The question you are probably asking yourself at this point is:
-<i>How would I know which classes and methods have to be called in
-order to set up a dummy Project and Target?</i> The answer is: you
+<p>The question you are probably asking yourself at this point
+is: <em>How would I know which classes and methods have to be called in
+order to set up a dummy Project and Target?</em> The answer is: you
 don't.  Ultimately, you have to be willing to get your feet wet and
 read the source code.  The above example is merely designed to whet
 your appetite and get you started.  Go for it!</p>
 
-
+</body>
 </html>
diff --git a/manual/anttaskslist.html b/manual/anttaskslist.html
index bd12049..266f6be 100644
--- a/manual/anttaskslist.html
+++ b/manual/anttaskslist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -25,16 +25,13 @@
 
 <body>
 
-
 <h2><a href="toc.html" target="navFrame">Table of Contents</a></h2>
 
 <h3>Apache Ant Tasks</h3>
 <ul class="inlinelist">
-<li><a href="tasksoverview.html" target="mainFrame">Overview of Ant Tasks</a></li>
-<li><a href="tasklist.html" target="navFrame">List of Tasks</a></li>
-<div style="padding-left:1em">
-  <li><a href="install.html#librarydependencies" target="mainFrame">Library Dependencies</a></li>
-</div>
+  <li><a href="tasksoverview.html" target="mainFrame">Overview of Ant Tasks</a></li>
+  <li><a href="tasklist.html" target="navFrame">List of Tasks</a></li>
+  <li class="indent"><a href="install.html#librarydependencies" target="mainFrame">Library Dependencies</a></li>
 </ul>
 
 </body>
diff --git a/manual/api/index.html b/manual/api/index.html
index 718d8d4..0f2fc90 100644
--- a/manual/api/index.html
+++ b/manual/api/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,23 +15,21 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
 <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
 <title>Apache Ant API</title>
 </head>
 <body>
-<b>Apache Ant API has not been generated</b>
+<h2>Apache Ant API has not been generated</h2>
 
-<p>If you see this page online at <a
-href="http://ant.apache.org/">ant.apache.org</a>, it is not a bug, but
-on purpose.  We do not provide an online version of the API docs, they
-are included with all our distributions.</p>
+<p>If you see this page online at <a target="_top"
+href="https://ant.apache.org/">ant.apache.org</a>, it is not a bug, but on purpose.  We do not
+provide an online version of the API docs, they are included with all our distributions.</p>
 
-<p align="left">Ant's manual and API documentation is part of
-  the <a href="http://ant.apache.org/bindownload.cgi">binary</a>
-  distributions or available as a
-  separate <a href="http://ant.apache.org/manualdownload.cgi">archive</a>.
-</p>
+<p>Ant's manual and API documentation is part of
+the <a href="https://ant.apache.org/bindownload.cgi" target="_top">binary</a> distributions or
+available as a separate <a href="https://ant.apache.org/manualdownload.cgi"
+target="_top">archive</a>.</p>
 </body>
 </html>
diff --git a/manual/argumentprocessor.html b/manual/argumentprocessor.html
index 2cd5202..236222d 100644
--- a/manual/argumentprocessor.html
+++ b/manual/argumentprocessor.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>The Command Line Processor Plugin: ArgumentProcessor</title>
 </head>
@@ -25,52 +25,45 @@
 <body>
 <h1>The Command Line Processor Plugin: ArgumentProcessor</h1>
 
-<h2><a name="definition">What is an ArgumentProcessor?</a></h2>
+<h2 id="definition">What is an ArgumentProcessor?</h2>
 
 <p>
-An <code>ArgumentProcessor</code> is a parser of command line argument which is
-then call before and after the build file is being parsed. Third party
-libraries may then be able to have custom argument line argument which modify
-Ant behaviour.
+An <code class="code">ArgumentProcessor</code> is a parser of command line argument which is then
+call before and after the build file is being parsed. Third party libraries may then be able to have
+custom argument line argument which modify Ant behaviour.
 </p>
 
 <p>
-An <code>ArgumentProcessor</code> is called each time Ant parse an unknown
-argument, an <code>ArgumentProcessor</code> doesn't take precedence over Ant to
-parse already suported options. It is then recommended to third party
-<code>ArgumentProcessor</code> implementation to chose specific 'enough'
-argument name, avoiding for instance one letter arguments.
+An <code class="code">ArgumentProcessor</code> is called each time Ant parse an unknown argument,
+an <code class="code">ArgumentProcessor</code> doesn't take precedence over Ant to parse already
+supported options. It is then recommended to third party <code class="code">ArgumentProcessor</code>
+implementation to chose specific 'enough' argument name, avoiding for instance one letter arguments.
 </p>
 
 <p>
-It is also called at the different phases so different behaviour can be
-implemented. It is called just after every arguments are parsed, just
-before the project is being configured (the build file being parsed),
-and just after. Some of the methods to be implemented return a boolean:
-if <code>true</code> is returned, Ant will terminate immediately, without
-error.
+It is also called at the different phases so different behaviour can be implemented. It is called
+just after every arguments are parsed, just before the project is being configured (the build file
+being parsed), and just after. Some of the methods to be implemented return a boolean:
+if <q>true</q> is returned, Ant will terminate immediately, without error.
 </p>
 
 <p>
-Being called during all these phases, an <code>ArgumentProcessor</code>
-can just print some specific system properties and quit (like
-<code>-diagnose</code>), or print some specific properties of a project after
-being parsed and quit (like <code>-projectHelp</code>), or just set some
+Being called during all these phases, an <code class="code">ArgumentProcessor</code> can just print
+some specific system properties and quit (like <kbd>-diagnose</kbd>), or print some specific
+properties of a project after being parsed and quit (like <kbd>-projectHelp</kbd>), or just set some
 custom properties on the project and let it run.
 </p>
 
-<h2><a name="repository">How to register it's own ArgumentProcessor</a></h2>
+<h2 id="repository">How to register it's own ArgumentProcessor</h2>
 
-<p>First, the <code>ArgumentProcessor</code> must be an implementation of
-<code>org.apache.tools.ant.ArgumentProcessor</code>.
+<p>First, the <code class="code">ArgumentProcessor</code> must be an implementation
+of <code class="code">org.apache.tools.ant.ArgumentProcessor</code>.
 </p>
 
-<p>Then to decare it: create a file
-<code>META-INF/services/org.apache.tools.ant.ArgumentProcessor</code> which
-contains only one line the fully qualified name of the class of the
-implementation. This file together with the implementation class need then to
-be found in Ant's classpath.
+<p>Then to declare it: create a
+file <samp>META-INF/services/org.apache.tools.ant.ArgumentProcessor</samp> which contains only one
+line the fully qualified name of the class of the implementation. This file together with the
+implementation class need then to be found in Ant's classpath.
 </p>
 </body>
 </html>
-
diff --git a/manual/base_task_classes.html b/manual/base_task_classes.html
index 1b058eb..c01af61 100644
--- a/manual/base_task_classes.html
+++ b/manual/base_task_classes.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Tasks Designed for Extension</title>
 </head>
@@ -29,15 +29,11 @@
 
 <p><strong>The links will not work in the online version of this document.</strong></p>
 
-<table border="1">
+<table>
 <thead>
 <tr>
-<th>
-Class
-</th>
-<th>
-Description
-</th>
+<th scope="col">Class</th>
+<th scope="col">Description</th>
 </tr>
 </thead>
 <tbody>
@@ -55,7 +51,7 @@
 <a href="api/org/apache/tools/ant/taskdefs/AbstractCvsTask.html">AbstractCvsTask</a>
 </td>
 <td>
-Another task can extend this with some customized output processing
+Another task can extend this with some customized output processing.
 </td>
 </tr>
 
@@ -86,7 +82,6 @@
 </td>
 </tr>
 
-
 <tr>
 <td>
 <a href="api/org/apache/tools/ant/taskdefs/Unpack.html">Unpack</a>
@@ -104,11 +99,8 @@
 Abstract Base class for tasks that may have multiple actions.
 </td>
 </tr>
-
 </tbody>
 </table>
 
-
-
 </body>
 </html>
diff --git a/manual/clonevm.html b/manual/clonevm.html
index b0a5342..b702d27 100644
--- a/manual/clonevm.html
+++ b/manual/clonevm.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,39 +15,35 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>ant.build.clonevm</title>
 </head>
 
 <body>
 
-<h2><a name="clonevm">ant.build.clonevm</a></h2>
+<h2 id="clonevm">ant.build.clonevm</h2>
 
 <p><em>Since Apache Ant 1.7</em></p>
 
-<p>The value of the ant.build.clonevm system property controls how Ant
-instruments forked Java Virtual Machines.  The <a
-href="Tasks/java.html">java</a> and <a
-href="Tasks/junit.html">junit</a> tasks support clonevm
-attributes to control the VMs on a task-by-task basis while the system
-property applies to all forked Java VMs.</p>
+<p>The value of the <code>ant.build.clonevm</code> system property
+controls how Ant instruments forked JVMs.  The <a href="Tasks/java.html">java</a>
+and <a href="Tasks/junit.html">junit</a> tasks support <var>clonevm</var>
+attributes to control JVMs on a task-by-task basis while the system
+property applies to all forked JVMs.</p>
 
-<p>If the value of the property is true, then all system properties of
-the forked Java Virtual Machine will be the same as those of the Java
-VM running Ant.  In addition, if you set ant.build.clonevm to true and <a
-href="sysclasspath.html">build.sysclasspath</a> has not been set, the
-bootclasspath of forked Java VMs gets constructed as if
-build.sysclasspath had the value "last".</p>
+<p>If the value of the property is <q>true</q>, then all system properties of
+the forked JVM will be the same as those of the JVM running Ant. In
+addition, if you set <code>ant.build.clonevm</code> to <q>true</q>
+and <a href="sysclasspath.html">build.sysclasspath</a> has not been
+set, the <var>bootclasspath</var> of forked JVMs gets constructed as
+if <code>build.sysclasspath</code> had the value <q>last</q>.</p>
 
 <p>Note that this has to be a system property, so it cannot be
-specified on the Ant command line.  Use the ANT_OPTS environment
-variable instead.</p>
-
+specified on the Ant command line.  Use the <code>ANT_OPTS</code>
+environment variable instead.</p>
 
 </body>
 </html>
-
diff --git a/manual/conceptstypeslist.html b/manual/conceptstypeslist.html
index ae6ca1a..d7ffae4 100644
--- a/manual/conceptstypeslist.html
+++ b/manual/conceptstypeslist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
diff --git a/manual/cover.html b/manual/cover.html
index 62ae2d3..83e044f 100644
--- a/manual/cover.html
+++ b/manual/cover.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,39 +15,30 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
-<title>Apache Ant 1.9.17 User Manual</title>
+<title>Apache Ant 1.10.13 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.17 Manual</h1>
-  <p align="left">This is the manual for version 1.9.17 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 
-    version then this is not the correct manual set. Please use the documentation 
-    appropriate to your current version. Also, if you are using a version
-    older than the most recent release, we recommend an upgrade to fix bugs
-    as well as provide new functionality. </p>
-  <p>&nbsp;</p>
+<body>
+  <h1 class="center"><img src="images/ant_logo_large.gif" width="190" height="120" alt="Apache Ant logo"></h1>
+  <h1 class="center">Apache Ant&trade; 1.10.13 Manual</h1>
+  <p>This is the manual for version 1.10.13 of <a href="https://ant.apache.org/" target="_top">Apache Ant</a>. If your
+    version of Ant (as verified with <kbd>ant -version</kbd>) is older or newer than this version then this is not the
+    correct manual set. Please use the documentation appropriate to your current version. Also, if you are using a
+    version older than the most recent release, we recommend an upgrade to fix bugs as well as provide new
+    functionality.</p>
 
-  <p align="left">Ant's manual and API documentation is part of
-    the <a href="http://ant.apache.org/bindownload.cgi">binary</a>
-    distributions or available as a
-    separate <a href="http://ant.apache.org/manualdownload.cgi">archive</a>.
-    Manuals for older releases are available for
-    download
-    <a href="http://ant.apache.org/bindownload.cgi#Old Ant Releases">as
-      well</a>.</p>
+  <p>Ant's manual and API documentation is part of the <a href="https://ant.apache.org/bindownload.cgi"
+     target="_top">binary</a> distributions or available as a
+     separate <a href="https://ant.apache.org/manualdownload.cgi" target="_top">archive</a>.  Manuals for older releases
+     are available for download <a href="https://ant.apache.org/bindownload.cgi#Old%20Ant%20Releases" target="_top">as
+     well</a>.</p>
 
-  <p>Apache Ant, Apache Ivy, Ant, Ivy, Apache, the Apache feather logo, and the Apache Ant project logos are trademarks of The Apache Software Foundation.</p>
-</div>
+  <p class="center">Apache Ant, Apache Ivy, Ant, Ivy, Apache, the Apache feather logo, and the Apache Ant project logos
+    are trademarks of The Apache Software Foundation.</p>
 
 
 </body>
diff --git a/manual/credits.html b/manual/credits.html
index c29df94..d048dfa 100644
--- a/manual/credits.html
+++ b/manual/credits.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,19 +15,19 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
+<link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Apache Ant User Manual - Credits</title>
 </head>
 
 <body>
 
-<div align="center">
-<h1>Apache Ant User Manual</h1>
-<p>by</p>
-</div>
+<h1 class="center">Apache Ant User Manual</h1>
+
+<p class="center">by</p>
+
 <!-- Names are in alphabetical order, on last name -->
 <ul>
   <li>Stephane Bailliez (<a href="mailto:sbailliez@imediation.com">sbailliez@imediation.com</a>)</li>
@@ -37,7 +38,7 @@
   <li>James Duncan Davidson (<a href="mailto:duncan@x180.com">duncan@x180.com</a>)</li>
   <li>Tom Dimock (<a href="mailto:tad1@cornell.edu">tad1@cornell.edu</a>)</li>
   <li>Peter Donald (<a href="mailto:donaldp@apache.org">donaldp@apache.org</a>)</li>
-  <li>dIon Gillard (<a href="mailto:dion@apache.org">dion@apache.org</a>)</li>
+  <li>Dion Gillard (<a href="mailto:dion@apache.org">dion@apache.org</a>)</li>
   <li>Erik Hatcher (<a href="mailto:ehatcher@apache.org">ehatcher@apache.org</a>)</li>
   <li>Diane Holt (<a href="mailto:holtdl@yahoo.com">holtdl@yahoo.com</a>)</li>
   <li>Bill Kelly (<a href="mailto:bill.kelly@softwired-inc.com">bill.kelly@softwired-inc.com</a>)</li>
@@ -60,10 +61,7 @@
   <li>Craeg Strong (<a href="mailto:cstrong@arielpartners.com">cstrong@arielpartners.com</a>)</li>
 </ul>
 
-<center>
-<p>Version: 1.9.17</p>
-</center>
-
+<p class="center">Version: 1.10.13</p>
 
 </body>
 </html>
diff --git a/manual/develop.html b/manual/develop.html
index aa4cfd7..5f738fc 100644
--- a/manual/develop.html
+++ b/manual/develop.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Writing Your Own Task</title>
 </head>
@@ -25,258 +25,210 @@
 <body>
 <h1>Developing with Apache Ant</h1>
 
-<h2><a name="writingowntask">Writing Your Own Task</a></h2>
+<h2 id="writingowntask">Writing Your Own Task</h2>
 <p>It is very easy to write your own task:</p>
 <ol>
-  <li>Create a Java class that extends <code>org.apache.tools.ant.Task</code>
-      or <a href="base_task_classes.html">another class</a> that was designed to be extended.</li>
+  <li>Create a Java class that extends <code class="code">org.apache.tools.ant.Task</code>
+    or <a href="base_task_classes.html">another class</a> that was designed to be extended.</li>
 
-  <li>For each attribute, write a <i>setter</i> method. The setter method must be a
-    <code>public void</code> method that takes a single argument. The
-    name of the method must begin with <code>set</code>, followed by the
-    attribute name, with the first character of the name in uppercase, and the rest in
-    lowercase<a href="#footnote-1"><sup>*</sup></a>.  That is, to support an attribute named
-    <code>file</code> you create a method <code>setFile</code>.
-    Depending on the type of the argument, Ant will perform some
-    conversions for you, see <a href="#set-magic">below</a>.</li>
+  <li id="footnote-1-back">For each attribute, write a <em>setter</em> method. The setter method
+    must be a <code>public void</code> method that takes a single argument. The name of the method
+    must begin with <code>set</code>, followed by the attribute name, with the first character of
+    the name in uppercase, and the rest in lowercase<a href="#footnote-1">*</a>.  That is, to
+    support an attribute named <var>file</var> you create a
+    method <code class="code">setFile</code>.  Depending on the type of the argument, Ant will
+    perform some conversions for you, see <a href="#set-magic">below</a>.</li>
 
-  <li>If your task shall contain other tasks as nested elements (like
-    <a href="Tasks/parallel.html"><code>parallel</code></a>), your
-    class must implement the interface
-    <code>org.apache.tools.ant.TaskContainer</code>.  If you do so, your
-    task can not support any other nested elements.  See 
-    <a href="#taskcontainer">below</a>.</li>
+  <li>If your task shall contain other tasks as nested elements
+    (like <a href="Tasks/parallel.html"><code>parallel</code></a>), your class must implement the
+    interface <code class="code">org.apache.tools.ant.TaskContainer</code>.  If you do so, your task
+    can not support any other nested elements.  See <a href="#taskcontainer">below</a>.</li>
 
-  <li>If the task should support character data (text nested between the
-    start end end tags), write a <code>public void addText(String)</code>
-    method.  Note that Ant does <strong>not</strong> expand properties on
-    the text it passes to the task.</li>
+  <li>If the task should support character data (text nested between the start and end tags), write
+    a <code class="code">public void addText(String)</code> method.  Note that Ant
+    does <strong>not</strong> expand properties on the text it passes to the task.</li>
 
-  <li>For each nested element, write a <i>create</i>, <i>add</i> or
-    <i>addConfigured</i> method.  A create method must be a
-    <code>public</code> method that takes no arguments and returns an
-    <code>Object</code> type. The name of the create method must begin
-    with <code>create</code>, followed by the element name. An add (or
-    addConfigured) method must be a <code>public void</code> method that
-    takes a single argument of an <code>Object</code> type with a
-    no-argument constructor.  The name of the add (addConfigured) method
-    must begin with <code>add</code> (<code>addConfigured</code>),
-    followed by the element name.  For a more complete discussion see 
-    <a href="#nested-elements">below</a>.</li>
+  <li>For each nested element, write a <em>create</em>, <em>add</em> or <em>addConfigured</em>
+    method.  A create method must be a <code>public</code> method that takes no arguments and
+    returns an <code>Object</code> type. The name of the create method must begin
+    with <code>create</code>, followed by the element name. An add (or addConfigured) method must be
+    a <code>public void</code> method that takes a single argument of an <code>Object</code> type
+    with a no-argument constructor.  The name of the add (addConfigured) method must begin
+    with <code>add</code> (<code>addConfigured</code>), followed by the element name.  For a more
+    complete discussion see <a href="#nested-elements">below</a>.</li>
 
-  <li>Write a <code>public void execute</code> method, with no arguments, that
-    throws a <code>BuildException</code>. This method implements the task
-    itself.</li>
+  <li>Write a <code class="code">public void execute()</code> method, with no arguments, that throws
+    a <code>BuildException</code>. This method implements the task itself.</li>
 </ol>
 
-<hr>
-<p><a name="footnote-1">*</a> Actually the case of the letters after
-the first one doesn't really matter to Ant, using all lower case is a
-good convention, though.</p>
+<hr/>
+<p id="footnote-1"><a href="#footnote-1-back">*</a> Actually the case of the letters after the first
+one doesn't really matter to Ant, using all lower case is a good convention, though.</p>
 
 <h3>The Life-cycle of a Task</h3>
 <ol>
-  <li>
-    The xml element that contains the tag corresponding to the
-    task gets converted to an UnknownElement at parser time.
-    This UnknownElement gets placed in a list within a target
-    object, or recursively within another UnknownElement.
-  </li>
-  <li>
-    When the target is executed, each UnknownElement is invoked
-    using an <code>perform()</code> method. This instantiates
-    the task. This means that tasks only gets
-    instantiated at run time.
+  <li>The xml element that contains the tag corresponding to the task gets converted to
+    an <code class="code">UnknownElement</code> at parse time.
+    This <code class="code">UnknownElement</code> gets placed in a list within a target object, or
+    recursively within another <code class="code">UnknownElement</code>.
   </li>
 
-  <li>The task gets references to its project and location inside the
-    buildfile via its inherited <code>project</code> and
-    <code>location</code> variables.</li>
+  <li>When the target is executed, each <code class="code">UnknownElement</code> is invoked using
+    an <code class="code">perform()</code> method. This instantiates the task. This means that tasks
+    only gets instantiated at run time.
+  </li>
 
-  <li>If the user specified an <code>id</code> attribute to this task,
-    the project
-    registers a reference to this newly created task, at run
-    time.</li>
+  <li>The task gets references to its project and location inside the buildfile via its
+    inherited <code>project</code> and <code>location</code> variables.</li>
 
-  <li>The task gets a reference to the target it belongs to via its
-    inherited <code>target</code> variable.</li>
+  <li>If the user specified an <var>id</var> attribute to this task, the project registers a
+    reference to this newly created task, at run time.</li>
 
-  <li><code>init()</code> is called at run time.</li>
+  <li>The task gets a reference to the target it belongs to via its inherited <code>target</code>
+    variable.</li>
 
-  <li>All child elements of the XML element corresponding to this task
-    are created via this task's <code>createXXX()</code> methods or
-    instantiated and added to this task via its <code>addXXX()</code>
-    methods, at run time.  Child elements corresponding
-    to <code>addConfiguredXXX()</code> are created at this point but
-    the actual <code>addConfigured</code> method is not called.</li>
+  <li><code class="code">init()</code> is called at run time.</li>
 
-  <li>All attributes of this task get set via their corresponding
-    <code>setXXX</code> methods, at runtime.</li>
+  <li>All child elements of the XML element corresponding to this task are created via this
+    task's <code class="code">createXXX()</code> methods or instantiated and added to this task via
+    its <code class="code">addXXX()</code> methods, at run time.  Child elements corresponding
+    to <code class="code">addConfiguredXXX()</code> are created at this point but the
+    actual <em>addConfigured</em> method is not called.</li>
 
-  <li>The content character data sections inside the XML element
-    corresponding to this task is added to the task via its
-    <code>addText</code> method, at runtime.</li>
+  <li>All attributes of this task get set via their corresponding <code class="code">setXXX()</code>
+    methods, at run time.</li>
 
-  <li>All attributes of all child elements get set via their corresponding
-    <code>setXXX</code> methods, at runtime.</li>
+  <li>The content character data sections inside the XML element corresponding to this task is added
+    to the task via its <code class="code">addText()</code> method, at run time.</li>
 
-  <li>If child elements of the XML element corresponding to this task
-    have been created for <code>addConfiguredXXX()</code> methods,
-    those methods get invoked now.</li>
+  <li>All attributes of all child elements get set via their
+    corresponding <code class="code">setXXX()</code> methods, at run time.</li>
 
-  <li><a name="execute"><code>execute()</code></a> is called at runtime.
-    If <code>target1</code> and <code>target2</code> both depend
-    on <code>target3</code>, then running
-    <code>'ant target1 target2'</code> will run all tasks in
-    <code>target3</code> twice.</li>
+  <li>If child elements of the XML element corresponding to this task have been created
+    for <code class="code">addConfiguredXXX()</code> methods, those methods get invoked now.</li>
+
+  <li id="execute"><code class="code">execute()</code> is called at run time.  If <q>target1</q>
+    and <q>target2</q> both depend on <q>target3</q>, then running <kbd>ant target1 target2</kbd>
+    will run all tasks in <q>target3</q> twice.</li>
 </ol>
 
-<h3><a name="set-magic">Conversions Ant will perform for attributes</a></h3>
+<h3 id="set-magic">Conversions Ant will perform for attributes</h3>
 
-<p>Ant will always expand properties before it passes the value of an
-attribute to the corresponding setter method. <b>Since Ant 1.8</b>, it is
-possible to <a href="Tasks/propertyhelper.html">extend Ant's property handling</a>
-such that a non-string Object may be the result of the evaluation of a string
-containing a single property reference. These will be assigned directly via
-setter methods of matching type. Since it requires some beyond-the-basics
-intervention to enable this behavior, it may be a good idea to flag attributes
-intended to permit this usage paradigm.
-</p>
+<p>Ant will always expand properties before it passes the value of an attribute to the corresponding
+setter method. <em>Since Ant 1.8</em>, it is possible to <a href="Tasks/propertyhelper.html">extend
+Ant's property handling</a> such that a non-string Object may be the result of the evaluation of a
+string containing a single property reference. These will be assigned directly via setter methods of
+matching type. Since it requires some beyond-the-basics intervention to enable this behavior, it may
+be a good idea to flag attributes intended to permit this usage paradigm.</p>
 
-<p>The most common way to write an attribute setter is to use a
-<code>java.lang.String</code> argument.  In this case Ant will pass
-the literal value (after property expansion) to your task.  But there
-is more!  If the argument of you setter method is</p>
+<p>The most common way to write an attribute setter is to use
+a <code class="code">java.lang.String</code> argument.  In this case Ant will pass the literal value
+(after property expansion) to your task.  But there is more!  If the argument of you setter method
+is</p>
 
 <ul>
+  <li><code>boolean</code>, your method will be passed the value <q>true</q> if the value specified
+    in the build file is one of <q>true</q>, <q>yes</q>, or <q>on</q> and <q>false</q>
+    otherwise.</li>
 
-  <li><code>boolean</code>, your method will be passed the value
-  <i>true</i> if the value specified in the build file is one of
-  <code>true</code>, <code>yes</code>, or <code>on</code> and
-  <i>false</i> otherwise.</li>
+  <li><code>char</code> or <code class="code">java.lang.Character</code>, your method will be passed
+    the first character of the value specified in the build file.</li>
 
-  <li><code>char</code> or <code>java.lang.Character</code>, your
-  method will be passed the first character of the value specified in
-  the build file.</li>
+  <li>any other primitive type (<code class="code">int</code>, <code class="code">short</code> and
+    so on), Ant will convert the value of the attribute into this type, thus making sure that you'll
+    never receive input that is not a number for that attribute.</li>
 
-  <li>any other primitive type (<code>int</code>, <code>short</code>
-  and so on), Ant will convert the value of the attribute into this
-  type, thus making sure that you'll never receive input that is not a
-  number for that attribute.</li>
+  <li><code class="code">java.io.File</code>, Ant will first determine whether the value given in
+    the build file represents an absolute path name.  If not, Ant will interpret the value as a path
+    name relative to the project's <var>basedir</var>.</li>
 
-  <li><code>java.io.File</code>, Ant will first determine whether the
-  value given in the build file represents an absolute path name.  If
-  not, Ant will interpret the value as a path name relative to the
-  project's basedir.</li>
+  <li><code class="code">org.apache.tools.ant.types.Resource</code>, Ant will resolve the string as
+    a <code class="code">java.io.File</code> as above, then pass in as
+    a <code class="code">org.apache.tools.ant.types.resources.FileResource</code>.  <em>Since Ant
+    1.8</em></li>
 
-  <li><code>org.apache.tools.ant.types.Resource</code>
-  <code>org.apache.tools.ant.types.Resource</code>, Ant will
-  resolve the string as a <code>java.io.File</code> as above, then
-  pass in as a <code>org.apache.tools.ant.types.resources.FileResource</code>.
-  <b>Since Ant 1.8</b>
-  </li>
+  <li><code class="code">org.apache.tools.ant.types.Path</code>, Ant will tokenize the value
+    specified in the build file, accepting <q>:</q> and <q>;</q> as path separators.  Relative path
+    names will be interpreted as relative to the project's <var>basedir</var>.</li>
 
-  <li><code>org.apache.tools.ant.types.Path</code>, Ant will tokenize
-  the value specified in the build file, accepting <code>:</code> and
-  <code>;</code> as path separators.  Relative path names will be
-  interpreted as relative to the project's basedir.</li>
+  <li><code class="code">java.lang.Class</code>, Ant will interpret the value given in the build
+    file as a Java class name and load the named class from the system class loader.</li>
 
-  <li><code>java.lang.Class</code>, Ant will interpret the value
-  given in the build file as a Java class name and load the named
-  class from the system class loader.</li>
+  <li>any other type that has a constructor with a single <code class="code">String</code> argument,
+    Ant will use this constructor to create a new instance from the value given in the build
+    file.</li>
 
-  <li>any other type that has a constructor with a single
-  <code>String</code> argument, Ant will use this constructor to
-  create a new instance from the value given in the build file.</li>
+  <li>A subclass of <code class="code">org.apache.tools.ant.types.EnumeratedAttribute</code>, Ant
+    will invoke this class's <code class="code">setValue</code> method.  Use this if your task
+    should support enumerated attributes (attributes with values that must be part of a predefined
+    set of values).  See <code>org/apache/tools/ant/taskdefs/FixCRLF.java</code> and the
+    inner <code class="code">AddAsisRemove</code> class used in <code class="code">setCr</code> for
+    an example.</li>
 
-  <li>A subclass of
-  <code>org.apache.tools.ant.types.EnumeratedAttribute</code>, Ant
-  will invoke this classes <code>setValue</code> method.  Use this if
-  your task should support enumerated attributes (attributes with
-  values that must be part of a predefined set of values).  See
-  <code>org/apache/tools/ant/taskdefs/FixCRLF.java</code> and the
-  inner <code>AddAsisRemove</code> class used in <code>setCr</code>
-  for an example.</li>
-
-  <li>A (Java 5) enumeration. Ant will call the setter with the enum constant
-  matching the value given in the build file. This is easier than using
-  <code>EnumeratedAttribute</code> and can result in cleaner code, but of course
-  your task will not run on JDK 1.4 or earlier. Note that any override of
-  <code>toString()</code> in the enumeration is ignored; the build file must use
-  the declared name (see <code>Enum.getName()</code>). You may wish to use lowercase
-  enum constant names, in contrast to usual Java style, to look better in build files.
-  <em>As of Ant 1.7.0.</em></li>
-
+  <li>An enumeration, Ant will call the setter with the enum constant matching the value
+    given in the build file. This is easier than using <code class="code">EnumeratedAttribute</code>
+    and can result in cleaner code. Note
+    that any override of <code class="code">toString()</code> in the enumeration is ignored; the
+    build file must use the declared name (see <code>Enum.getName()</code>). You may wish to use
+    lowercase enum constant names, in contrast to usual Java style, to look better in build
+    files.  <em>Since Ant 1.7.0</em></li>
 </ul>
 
-<p>What happens if more than one setter method is present for a given
-attribute?  A method taking a <code>String</code> argument will always
-lose against the more specific methods.  If there are still more
-setters Ant could chose from, only one of them will be called, but we
-don't know which, this depends on the implementation of your Java
-virtual machine.</p>
+<p>What happens if more than one setter method is present for a given attribute?  A method taking
+a <code class="code">String</code> argument will always lose against the more specific methods.  If
+there are still more setters Ant could chose from, only one of them will be called, but we don't
+know which, this depends on the implementation of your Java virtual machine.</p>
 
-<h3><a name="nested-elements">Supporting nested elements</a></h3>
+<h3 id="nested-elements">Supporting nested elements</h3>
 
-<p>Let's assume your task shall support nested elements with the name
-<code>inner</code>.  First of all, you need a class that represents
-this nested element.  Often you simply want to use one of Ant's
-classes like <code>org.apache.tools.ant.types.FileSet</code> to
-support nested <code>fileset</code> elements.</p>
+<p>Let's assume your task shall support nested elements with the name <code>inner</code>.  First of
+all, you need a class that represents this nested element.  Often you simply want to use one of
+Ant's classes like <code class="code">org.apache.tools.ant.types.FileSet</code> to support
+nested <code>fileset</code> elements.</p>
 
-<p>Attributes of the nested elements or nested child elements of them
-will be handled using the same mechanism used for tasks (i.e. setter
-methods for attributes, addText for nested text and
-create/add/addConfigured methods for child elements).</p>
+<p>Attributes of the nested elements or nested child elements of them will be handled using the same
+mechanism used for tasks (i.e. <em>setter</em> methods for
+attributes, <code class="code">addText()</code> for nested text
+and <em>create</em>/<em>add</em>/<em>addConfigured</em> methods for child elements).</p>
 
-<p>Now you have a class <code>NestedElement</code> that is supposed to
-be used for your nested <code>&lt;inner&gt;</code> elements, you have
-three options:</p>
+<p>Now you have a class <code class="code">NestedElement</code> that is supposed to be used for your
+nested <code>&lt;inner&gt;</code> elements, you have three options:</p>
 
 <ol>
-  <li><code>public NestedElement createInner()</code></li>
-  <li><code>public void addInner(NestedElement anInner)</code></li>
-  <li><code>public void addConfiguredInner(NestedElement anInner)</code></li>
+  <li><code class="code">public NestedElement createInner()</code></li>
+  <li><code class="code">public void addInner(NestedElement anInner)</code></li>
+  <li><code class="code">public void addConfiguredInner(NestedElement anInner)</code></li>
 </ol>
 
 <p>What is the difference?</p>
 
-<p>Option 1 makes the task create the instance of
-<code>NestedElement</code>, there are no restrictions on the type.
-For the options 2 and 3, Ant has to create an instance of
-<code>NestedInner</code> before it can pass it to the task, this
-means, <code>NestedInner</code> must have a <code>public</code> no-arg
-  constructor or a <code>public</code> one-arg constructor
-  taking a Project class as a parameter.
-This is the only difference between options 1 and 2.</p>
+<p>Option 1 makes the task create the instance of <code class="code">NestedElement</code>, there are
+no restrictions on the type.  For the options 2 and 3, Ant has to create an instance
+of <code class="code">NestedInner</code> before it can pass it to the task, this
+means, <code class="code">NestedInner</code> must have a <code>public</code> no-arg constructor or
+a <code>public</code> one-arg constructor taking a <code class="code">Project</code> class as a
+parameter.  This is the only difference between options 1 and 2.</p>
 
-<p>The difference between 2 and 3 is what Ant has done to the object
-before it passes it to the method.  <code>addInner</code> will receive
-an object directly after the constructor has been called, while
-<code>addConfiguredInner</code> gets the object <em>after</em> the
-attributes and nested children for this new object have been
-handled.</p>
+<p>The difference between 2 and 3 is what Ant has done to the object before it passes it to the
+method.  <code class="code">addInner()</code> will receive an object directly after the constructor
+has been called, while <code class="code">addConfiguredInner()</code> gets the object <em>after</em>
+the attributes and nested children for this new object have been handled.</p>
 
-<p>What happens if you use more than one of the options?  Only one of
-the methods will be called, but we don't know which, this depends on
-the implementation of your Java virtual machine.</p>
+<p>What happens if you use more than one of the options?  Only one of the methods will be called,
+but we don't know which, this depends on the implementation of your JVM.</p>
 
-<h3><a name="nestedtype">Nested Types</a></h3>
-If your task needs to nest an arbitrary type that has been defined
-  using <code>&lt;typedef&gt;</code> you have two options.
-  <ol>
-    <li><code>public void add(Type type)</code></li>
-    <li><code>public void addConfigured(Type type)</code></li>
-  </ol>
-  The difference between 1 and 2 is the same as between 2 and 3 in the
-  previous section.
-  <p>
-    For example suppose one wanted to handle objects object of type
-    org.apache.tools.ant.taskdefs.condition.Condition, one may
-    have a class:
-  </p>
-  <blockquote>
-  <pre>
+<h3 id="nestedtype">Nested Types</h3>
+<p>If your task needs to nest an arbitrary type that has been defined
+using <code>&lt;typedef&gt;</code> you have two options.</p>
+<ol>
+  <li><code class="code">public void add(Type type)</code></li>
+  <li><code class="code">public void addConfigured(Type type)</code></li>
+</ol>
+<p>The difference between 1 and 2 is the same as between 2 and 3 in the previous section.</p>
+<p>For example suppose one wanted to handle objects object of
+type <code class="code">org.apache.tools.ant.taskdefs.condition.Condition</code>, one may have a
+class:</p>
+<pre>
 public class MyTask extends Task {
     private List conditions = new ArrayList();
     public void add(Condition c) {
@@ -285,27 +237,17 @@
     public void execute() {
      // iterator over the conditions
     }
-}
-  </pre>
-  </blockquote>
-  <p>
-    One may define and use this class like this:
-  </p>
-  <blockquote>
-    <pre>
+}</pre>
+<p>One may define and use this class like this:</p>
+<pre>
 &lt;taskdef name="mytask" classname="MyTask" classpath="classes"/&gt;
 &lt;typedef name="condition.equals"
          classname="org.apache.tools.ant.taskdefs.conditions.Equals"/&gt;
 &lt;mytask&gt;
     &lt;condition.equals arg1="${debug}" arg2="true"/&gt;
-&lt;/mytask&gt;
-    </pre>
-  </blockquote>
-  <p>
-    A more complicated example follows:
-  </p>
-  <blockquote>
-    <pre>
+&lt;/mytask&gt;</pre>
+<p>A more complicated example follows:</p>
+<pre>
 public class Sample {
     public static class MyFileSelector implements FileSelector {
          public void setAttrA(int a) {}
@@ -318,13 +260,13 @@
 
     interface MyInterface {
         void setVerbose(boolean val);
-    }        
+    }
 
     public static class BuildPath extends Path {
         public BuildPath(Project project) {
             super(project);
         }
-        
+
         public void add(MyInterface inter) {}
         public void setUrl(String url) {}
     }
@@ -333,16 +275,11 @@
         public void setVerbose(boolean x) {}
         public void setCount(int c) {}
     }
-}
-    </pre>
-  </blockquote>
-  <p>
-    This class defines a number of static classes that implement/extend
-    Path, MyFileSelector and MyInterface. These may be defined and used
-    as follows:
-  </p>
-  <pre>
-    <blockquote>
+}</pre>
+<p>This class defines a number of static classes that
+implement/extend <code class="code">Path</code>, <code class="code">MyFileSelector</code>
+and <code class="code">MyInterface</code>. These may be defined and used as follows:</p>
+<pre>
 &lt;typedef name="myfileselector" classname="Sample$MyFileSelector"
          classpath="classes" loaderref="classes"/&gt;
 &lt;typedef name="buildpath" classname="Sample$BuildPath"
@@ -358,33 +295,28 @@
          &lt;/buildpath&gt;
       &lt;/myfileselector&gt;
    &lt;/fileset&gt;
-&lt;/copy&gt;
-    </blockquote>
-  </pre>
+&lt;/copy&gt;</pre>
 
-<h3><a name="taskcontainer">TaskContainer</a></h3>
+<h3 id="taskcontainer">TaskContainer</h3>
 
-<p>The <code>TaskContainer</code> consists of a single method,
-<code>addTask</code> that basically is the same as an <a
-href="#nested-elements">add method</a> for nested elements.  The task
-instances will be configured (their attributes and nested elements
-have been handled) when your task's <code>execute</code> method gets
-invoked, but not before that.</p>
+<p>The <code class="code">TaskContainer</code> consists of a single
+method, <code class="code">addTask</code> that basically is the same as
+an <a href="#nested-elements">add method</a> for nested elements.  The task instances will be
+configured (their attributes and nested elements have been handled) when your
+task's <code class="code">execute</code> method gets invoked, but not before that.</p>
 
-<p>When we <a href="#execute">said</a> <code>execute</code> would be
-called, we lied ;-).  In fact, Ant will call the <code>perform</code>
-method in <code>org.apache.tools.ant.Task</code>, which in turn calls
-<code>execute</code>.  This method makes sure that <a
-href="#buildevents">Build Events</a> will be triggered.  If you
-execute the task instances nested into your task, you should also
-invoke <code>perform</code> on these instances instead of
-<code>execute</code>.</p>
+<p>When we <a href="#execute">said</a> <code class="code">execute</code> would be called, we lied
+;-).  In fact, Ant will call the <code class="code">perform</code> method
+in <code class="code">org.apache.tools.ant.Task</code>, which in turn
+calls <code class="code">execute</code>.  This method makes sure that <a href="#buildevents">Build
+Events</a> will be triggered.  If you execute the task instances nested into your task, you should
+also invoke <code class="code">perform</code> on these instances instead
+of <code class="code">execute</code>.</p>
 
 <h3>Example</h3>
-<p>Let's write our own task, which prints a message on the
-<code>System.out</code> stream.
-The task has one attribute, called <code>message</code>.</p>
-<blockquote>
+<p>Let's write our own task, which prints a message on the <code>System.out</code> stream.  The task
+has one attribute, called <code>message</code>.</p>
+
 <pre>
 package com.mydomain;
 
@@ -403,21 +335,19 @@
     public void setMessage(String msg) {
         this.msg = msg;
     }
-}
-</pre>
-</blockquote>
+}</pre>
+
 <p>It's really this simple ;-)</p>
 <p>Adding your task to the system is rather simple too:</p>
 <ol>
-  <li>Make sure the class that implements your task is in the classpath when
-    starting Ant.</li>
-  <li>Add a <code>&lt;taskdef&gt;</code> element to your project.
-    This actually adds your task to the system.</li>
+  <li>Make sure the class that implements your task is in the classpath when starting Ant.</li>
+  <li>Add a <code>&lt;taskdef&gt;</code> element to your project.  This actually adds your task to
+    the system.</li>
   <li>Use your task in the rest of the buildfile.</li>
 </ol>
 
 <h3>Example</h3>
-<blockquote>
+
 <pre>
 &lt;?xml version=&quot;1.0&quot;?&gt;
 
@@ -427,17 +357,14 @@
   &lt;target name=&quot;main&quot;&gt;
     &lt;mytask message=&quot;Hello World! MyVeryOwnTask works!&quot;/&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre>
-</blockquote>
+&lt;/project&gt;</pre>
 
 <h3>Example 2</h3>
-To use a task directly from the buildfile which created it, place the
-<code>&lt;taskdef&gt;</code> declaration inside a target
-<i>after the compilation</i>. Use the <code>classpath</code> attribute of
-<code>&lt;taskdef&gt;</code> to point to where the code has just been
-compiled.
-<blockquote>
+<p>To use a task directly from the buildfile which created it, place
+the <code>&lt;taskdef&gt;</code> declaration inside a target <em>after the compilation</em>. Use
+the <var>classpath</var> attribute of <code>&lt;taskdef&gt;</code> to point to where the code has
+just been compiled.</p>
+
 <pre>
 &lt;?xml version=&quot;1.0&quot;?&gt;
 
@@ -457,27 +384,23 @@
   &lt;target name=&quot;main&quot; depends=&quot;declare&quot;&gt;
     &lt;mytask message=&quot;Hello World! MyVeryOwnTask works!&quot;/&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre>
-</blockquote>
+&lt;/project&gt;</pre>
 
-<p>Another way to add a task (more permanently), is to add the task name and
-implementing class name to the <code>default.properties</code> file in the
-<code>org.apache.tools.ant.taskdefs</code>
-package. Then you can use it as if it were a built-in task.</p>
+<p>Another way to add a task (more permanently) is to add the task name and implementing class name
+to the <samp>default.properties</samp> file in
+the <code class="code">org.apache.tools.ant.taskdefs</code> package. Then you can use it as if it
+were a built-in task.</p>
 
-
-
-<hr>
-<h2><a name="buildevents">Build Events</a></h2>
+<hr/>
+<h2 id="buildevents">Build Events</h2>
 <p>Ant is capable of generating build events as it performs the tasks necessary to build a project.
-Listeners can be attached to Ant to receive these events. This capability could be used, for example,
-to connect Ant to a GUI or to integrate Ant with an IDE.
-</p>
-<p>To use build events you need to create an ant <code>Project</code> object. You can then call the
-<code>addBuildListener</code> method to add your listener to the project. Your listener must implement
-the <code>org.apache.tools.antBuildListener</code> interface. The listener will receive BuildEvents
-for the following events</p>
+Listeners can be attached to Ant to receive these events. This capability could be used, for
+example, to connect Ant to a GUI or to integrate Ant with an IDE.</p>
+<p>To use build events you need to create an ant <code class="code">Project</code> object. You can
+then call the <code class="code">addBuildListener</code> method to add your listener to the
+project. Your listener must implement
+the <code class="code">org.apache.tools.antBuildListener</code> interface. The listener will receive
+BuildEvents for the following events</p>
 <ul>
   <li>Build started</li>
   <li>Build finished</li>
@@ -488,55 +411,49 @@
   <li>Message logged</li>
 </ul>
 
-<p>If the build file invokes another build file via 
-<a href="Tasks/ant.html"><code>&lt;ant&gt;</code></a> or 
-<a href="Tasks/subant.html"><code>&lt;subant&gt;</code></a> or uses 
-<a href="Tasks/antcall.html"><code>&lt;antcall&gt;</code></a>, you are creating a
-new Ant "project" that will send target and task level events of its
-own but never sends build started/finished events.  Ant 1.6.2
-introduces an extension of the BuildListener interface named
-SubBuildListener that will receive two new events for</p>
+<p>If the build file invokes another build file
+via <a href="Tasks/ant.html"><code>&lt;ant&gt;</code></a>
+or <a href="Tasks/subant.html"><code>&lt;subant&gt;</code></a> or
+uses <a href="Tasks/antcall.html"><code>&lt;antcall&gt;</code></a>, you are creating a new Ant
+"project" that will send target and task level events of its own but never sends build
+started/finished events. <em>Since Ant 1.6.2</em>, <code class="code">BuildListener</code> interface
+has an extension named <code class="code">SubBuildListener</code> that will receive two new events
+for</p>
 <ul>
   <li>SubBuild started</li>
   <li>SubBuild finished</li>
 </ul>
-<p>If you are interested in those events, all you need to do is to
-implement the new interface instead of BuildListener (and register the
-listener, of course).</p>
+<p>If you are interested in those events, all you need to do is to implement the new interface
+instead of <code class="code">BuildListener</code> (and register the listener, of course).</p>
 
-<p>If you wish to attach a listener from the command line you may use the
-<code>-listener</code> option. For example:</p>
-<blockquote>
-  <pre>ant -listener org.apache.tools.ant.XmlLogger</pre>
-</blockquote>
+<p>If you wish to attach a listener from the command line you may use the <kbd>-listener</kbd>
+option. For example:</p>
+
+<pre class="input">ant -listener org.apache.tools.ant.XmlLogger</pre>
+
 <p>will run Ant with a listener that generates an XML representation of the build progress. This
-listener is included with Ant, as is the default listener, which generates the logging to standard output.</p>
+listener is included with Ant, as is the default listener, which generates the logging to standard
+output.</p>
 
-<p><b>Note: </b>A listener must not access System.out and System.err directly since output on 
-these streams is redirected by Ant's core to the build event system. Accessing these 
-streams can cause an infinite loop in Ant. Depending on the version of Ant, this will
-either cause the build to terminate or the Java VM to run out of Stack space. A logger, also, may 
-not access System.out and System.err directly. It must use the streams with which it has
-been configured.</p>
+<p><strong>Note</strong>: A listener must not access <code class="code">System.out</code>
+and <code class="code">System.err</code> directly since output on these streams is redirected by
+Ant's core to the build event system. Accessing these streams can cause an infinite loop in
+Ant. Depending on the version of Ant, this will either cause the build to terminate or the JVM to
+run out of Stack space. A logger, also, may not access <code class="code">System.out</code>
+and <code class="code">System.err</code> directly. It must use the streams with which it has been
+configured.</p>
 
-<p><b>Note2:</b> All methods of a BuildListener except for the "Build
-  Started" and "Build Finished" events may occur on several threads
-  simultaneously - for example while Ant is executing
-  a <code>&lt;parallel&gt;</code> task.</p>
-
-
-
-
+<p><strong>Note</strong>: All methods of a <code class="code">BuildListener</code> except for the
+"Build Started" and "Build Finished" events may occur on several threads simultaneously&mdash;for
+example while Ant is executing a <code>&lt;parallel&gt;</code> task.</p>
 
 <h3>Example</h3>
-Writing an adapter to your favourite log library is very easy.
-Just implent the BuildListener interface, instantiate your logger and delegate
-the message to that instance. <br>
-When starting your build provide your adapter class and the log library to the
-build classpath and activate your logger via <code>-listener</code> option as
-described above.
+<p>Writing an adapter to your favourite log library is very easy.  Just implement
+the <code class="code">BuildListener</code> interface, instantiate your logger and delegate the
+message to that instance.</p>
+<p>When starting your build provide your adapter class and the log library to the build classpath
+and activate your logger via <kbd>-listener</kbd> option as described above.</p>
 
-<blockquote>
 <pre>
 public class MyLogAdapter implements BuildListener {
 
@@ -561,29 +478,22 @@
     }
 
     // implement all methods in that way
-}
-</pre>
-</blockquote>
+}</pre>
 
+<hr/>
+<h2 id="integration">Source code integration</h2>
 
+<p>The other way to extend Ant through Java is to make changes to existing tasks, which is
+positively encouraged.  Both changes to the existing source and new tasks can be incorporated back
+into the Ant codebase, which benefits all users and spreads the maintenance load around.</p>
 
-<hr>
-<h2><a name="integration">Source code integration</a></h2>
+<p>Please consult the <a href="https://www.apache.org/foundation/getinvolved.html"
+target="_top">Getting Involved</a> pages on the Apache web site for details on how to fetch the
+latest source and how to submit changes for reincorporation into the source tree.</p>
 
-<p>The other way to extend Ant through Java is to make changes to existing tasks, which is positively encouraged.
-Both changes to the existing source and new tasks can be incorporated back into the Ant codebase, which
-benefits all users and spreads the maintenance load around.</p>
-
-<p>Please consult the
-<a href="http://www.apache.org/foundation/getinvolved.html">Getting Involved</a> pages on the Apache web site
-for details on how to fetch the latest source and how to submit changes for reincorporation into the
-source tree.</p>
-
-<p>Ant also has some
-<a href="http://ant.apache.org/ant_task_guidelines.html">task guidelines</a>
-which provides some advice to people developing and testing tasks. Even if you intend to
-keep your tasks to yourself, you should still read this as it should be informative.</p>
+<p>Ant also has some <a href="https://ant.apache.org/ant_task_guidelines.html" target="_top">task
+guidelines</a> which provides some advice to people developing and testing tasks. Even if you intend
+to keep your tasks to yourself, you should still read this as it should be informative.</p>
 
 </body>
 </html>
-
diff --git a/manual/developlist.html b/manual/developlist.html
index 1bbdc4e..5dd9a54 100644
--- a/manual/developlist.html
+++ b/manual/developlist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -30,8 +30,8 @@
 <h3>Developing with Apache Ant</h3>
 
 <ul class="inlinelist">
-<li><a href="http://ant.apache.org/ant_in_anger.html">Ant in Anger</a> <small>(online)</small></li>
-<li><a href="http://ant.apache.org/ant_task_guidelines.html">Ant Task Guidelines</a> <small>(online)</small></li>
+<li><a href="https://ant.apache.org/ant_in_anger.html" target="_top">Ant in Anger</a> <small>(online)</small></li>
+<li><a href="https://ant.apache.org/ant_task_guidelines.html" target="_top">Ant Task Guidelines</a> <small>(online)</small></li>
 <li><a href="develop.html#writingowntask">Writing Your Own Task</a></li>
 <li><a href="base_task_classes.html">Tasks Designed for Extension</a></li>
 <li><a href="develop.html#buildevents">Build Events</a></li>
@@ -39,7 +39,7 @@
 <li><a href="inputhandler.html">InputHandler</a></li>
 <li><a href="antexternal.html">Using Ant Tasks Outside of Ant</a></li>
 <li><a href="projecthelper.html">The Ant frontend: ProjectHelper</a></li>
-<li><a href="argumentprocessor.html">The Command Line Processor Plugin:ArgumentProcessor</a></li>
+<li><a href="argumentprocessor.html">The Command Line Processor Plugin: ArgumentProcessor</a></li>
 </ul>
 
 <h3>Tutorials</h3>
diff --git a/manual/dirtasks.html b/manual/dirtasks.html
index 5c23229..d748feb 100644
--- a/manual/dirtasks.html
+++ b/manual/dirtasks.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,54 +15,55 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Directory-based Tasks</title>
 </head>
 
 <body>
 
-<h2><a name="directorybasedtasks">Directory-based Tasks</a></h2>
+<h2 id="directorybasedtasks">Directory-based Tasks</h2>
 <p>Some tasks use directory trees for the actions they perform.
 For example, the <a href="Tasks/javac.html">javac</a> task, which
-compiles a directory tree with <code>.java</code> files into
-<code>.class</code> files, is one of these directory-based tasks. Because
+compiles a directory tree with <samp>.java</samp> files into
+<samp>.class</samp> files, is one of these directory-based tasks. Because
 some of these tasks do so much work with a directory tree, the task itself
 can act as an implicit <a href="Types/fileset.html">FileSet</a>.</p>
+
 <p>Whether the fileset is implicit or not, it can often be very useful to
 work on a subset of the directory tree. This section describes how you can
 select a subset of such a directory tree when using one of these
 directory-based tasks.</p>
-<p>Apache Ant gives you two ways to create a subset of files in a fileset, both of
-which can be used at the same time:</p>
+
+<p>Apache Ant gives you two ways to create a subset of files in a
+fileset, both of which can be used at the same time:</p>
 <ul>
   <li>Only include files and directories that match any
-    <code>include</code> patterns and do not match any
-    <code>exclude</code> patterns in a given
+    <var>include</var> patterns and do not match any
+    <var>exclude</var> patterns in a given
     <a href="Types/patternset.html">PatternSet</a>.</li>
   <li>Select files based on selection criteria defined by a collection of
     <a href="Types/selectors.html">selector</a> nested elements.</li>
 </ul>
-<h3><a name="patternset">Patternset</a></h3>
+<h3 id="patternset">Patternset</h3>
 
-<p>We said that Directory-based tasks can sometimes act as an implicit
-<a href="Types/fileset.html"><code>&lt;fileset&gt;</code></a>,
-but in addition to that, a FileSet acts as an implicit
-<a href="Types/patternset.html"><code>&lt;patternset&gt;</code></a>.</p>
+<p>We said that Directory-based tasks can sometimes act as an
+implicit <a href="Types/fileset.html"><code>&lt;fileset&gt;</code></a>,
+but in addition to that, a FileSet acts as an
+implicit <a href="Types/patternset.html"><code>&lt;patternset&gt;</code></a>.</p>
 
 <p>The inclusion and exclusion elements of the implicit PatternSet can be
 specified inside the directory-based task (or explicit fileset) via
 either:</p>
 <ul>
-  <li>the attributes <code>includes</code> and
-    <code>excludes</code>.</li>
+  <li>the attributes <var>includes</var> and
+    <var>excludes</var>.</li>
   <li>nested elements <code>&lt;include&gt;</code> and
     <code>&lt;exclude&gt;</code>.</li>
   <li>external files specified with the attributes
-    <code>includesfile</code> and <code>excludesfile</code>.</li>
+    <var>includesfile</var> and <var>excludesfile</var>.</li>
   <li>external files specified with the nested elements
     <code>&lt;includesfile&gt;</code> and <code>&lt;excludesfile&gt;</code>.
   </li>
@@ -77,142 +79,139 @@
 are assumed to match the include pattern (with the possible exception of
 the default excludes).</p>
 
-<h4><a name="patterns">Patterns</a></h4>
+<h4 id="patterns">Patterns</h4>
 
 <p>As described earlier, patterns are used for the inclusion and exclusion
 of files. These patterns look very much like the patterns used in DOS and
 UNIX:</p>
-<p>'*' matches zero or more characters, '?' matches one character.</p>
+
+<p><q>*</q> matches zero or more characters, <q>?</q> matches one character.</p>
 
 <p>In general, patterns are considered relative paths, relative to a
-task dependent base directory (the dir attribute in the case of
-<code>&lt;fileset&gt;</code>).  Only files found below that base
-directory are considered.  So while a pattern like
-<code>../foo.java</code> is possible, it will not match anything when
-applied since the base directory's parent is never scanned for
-files.</p>
+task dependent base directory (the <var>dir</var> attribute in the
+case of <code>&lt;fileset&gt;</code>).  Only files found below that base
+directory are considered.  So while a pattern
+like <samp>../foo.java</samp> is possible, it will not match
+anything when applied since the base directory's parent is never
+scanned for files.</p>
 
-<p><b>Examples:</b></p>
+<h5>Examples</h5>
 <p>
-<code>*.java</code>&nbsp;&nbsp;matches&nbsp;&nbsp;<code>.java</code>,
-<code>x.java</code> and <code>FooBar.java</code>, but
-not <code>FooBar.xml</code> (does not end with <code>.java</code>).</p>
+<samp>*.java</samp>&nbsp;&nbsp;matches&nbsp;&nbsp;<samp>.java</samp>,
+<samp>x.java</samp> and <samp>FooBar.java</samp>, but
+not <samp>FooBar.xml</samp> (does not end with <samp>.java</samp>).</p>
+
 <p>
-<code>?.java</code>&nbsp;&nbsp;matches&nbsp;&nbsp;<code>x.java</code>,
-<code>A.java</code>, but not <code>.java</code> or <code>xyz.java</code>
-(both don't have one character before <code>.java</code>).</p>
-<p>
-Combinations of <code>*</code>'s and <code>?</code>'s are allowed.</p>
+<samp>?.java</samp>&nbsp;&nbsp;matches&nbsp;&nbsp;<samp>x.java</samp>,
+<samp>A.java</samp>, but not <samp>.java</samp> or <samp>xyz.java</samp>
+(both don't have one character before <samp>.java</samp>).</p>
+
+<p>Combinations of <q>*</q>'s and <q>?</q>'s are allowed.</p>
+
 <p>Matching is done per-directory. This means that first the first directory in
 the pattern is matched against the first directory in the path to match. Then
-the second directory is matched, and so on. For example, when we have the pattern
-<code>/?abc/*/*.java</code>
-and the path <code>/xabc/foobar/test.java</code>,
-the first <code>?abc</code> is matched with <code>xabc</code>,
-then <code>*</code> is matched with <code>foobar</code>,
-and finally <code>*.java</code> is matched with <code>test.java</code>.
+the second directory is matched, and so on. For example, when we have
+the pattern <samp>/?abc/*/*.java</samp>
+and the path <samp>/xabc/foobar/test.java</samp>,
+the first <samp>?abc</samp> is matched with <samp>xabc</samp>,
+then <samp>*</samp> is matched with <samp>foobar</samp>,
+and finally <samp>*.java</samp> is matched with <samp>test.java</samp>.
 They all match, so the path matches the pattern.</p>
+
 <p>To make things a bit more flexible, we add one extra feature, which makes it
 possible to match multiple directory levels. This can be used to match a
 complete directory tree, or a file anywhere in the directory tree.
-To do this, <code>**</code>
-must be used as the name of a directory.
-When <code>**</code> is used as the name of a
-directory in the pattern, it matches zero or more directories.
-For example:
-<code>/test/**</code> matches all files/directories under <code>/test/</code>,
-such as <code>/test/x.java</code>,
-or <code>/test/foo/bar/xyz.html</code>, but not <code>/xyz.xml</code>.</p>
-<p>There is one &quot;shorthand&quot;: if a pattern ends
-with <code>/</code>
-or <code>\</code>, then <code>**</code>
-is appended.
-For example, <code>mypackage/test/</code> is interpreted as if it were
-<code>mypackage/test/**</code>.</p>
-<p><b>Example patterns:</b></p>
-<table border="1" cellpadding="2" cellspacing="0">
+To do this, <q>**</q> must be used as the name of a
+directory. When <samp>**</samp> is used as the name of a directory in
+the pattern, it matches zero or more directories. For
+example: <samp>/test/**</samp> matches all files/directories
+under <samp>/test/</samp>, such as <samp>/test/x.java</samp>,
+or <samp>/test/foo/bar/xyz.html</samp>, but not <samp>/xyz.xml</samp>.</p>
+
+<p>There is one &quot;shorthand&quot;: if a pattern ends with <q>/</q>
+or <q>\</q>, then <q>**</q> is appended. For
+example, <samp>mypackage/test/</samp> is interpreted as if it
+were <samp>mypackage/test/**</samp>.</p>
+
+<h5>Example patterns</h5>
+<table>
   <tr>
-    <td valign="top"><code>**/CVS/*</code></td>
-    <td valign="top">Matches all files in <code>CVS</code>
+    <td>Example</td>
+    <td>Explanation</td>
+  </tr>
+  <tr>
+    <td><samp>**/CVS/*</samp></td>
+    <td>Matches all files in <samp>CVS</samp>
       directories that can be located
-      anywhere in the directory tree.<br>
+      anywhere in the directory tree.<br/>
       Matches:
-      <pre>
-      CVS/Repository
-      org/apache/CVS/Entries
-      org/apache/jakarta/tools/ant/CVS/Entries
-      </pre>
-      But not:
-      <pre>
-      org/apache/CVS/foo/bar/Entries (<code>foo/bar/</code>
-      part does not match)
-      </pre>
+<pre>
+CVS/Repository
+org/apache/CVS/Entries
+org/apache/jakarta/tools/ant/CVS/Entries</pre>
+But not:
+<pre>org/apache/CVS/foo/bar/Entries</pre>
+(<samp>foo/bar/</samp> part does not match)
     </td>
   </tr>
   <tr>
-    <td valign="top"><code>org/apache/jakarta/**</code></td>
-    <td valign="top">Matches all files in the <code>org/apache/jakarta</code>
-      directory tree.<br>
+    <td><samp>org/apache/jakarta/**</samp></td>
+    <td>Matches all files in the <samp>org/apache/jakarta</samp>
+      directory tree.<br/>
       Matches:
-      <pre>
-      org/apache/jakarta/tools/ant/docs/index.html
-      org/apache/jakarta/test.xml
-      </pre>
-      But not:
-      <pre>
-      org/apache/xyz.java
-      </pre>
-      (<code>jakarta/</code> part is missing).</td>
+<pre>
+org/apache/jakarta/tools/ant/docs/index.html
+org/apache/jakarta/test.xml
+</pre>
+But not:
+<pre>org/apache/xyz.java</pre>
+(<code>jakarta/</code> part is missing).</td>
   </tr>
   <tr>
-    <td valign="top"><code>org/apache/**/CVS/*</code></td>
-    <td valign="top">Matches all files in <code>CVS</code> directories
+    <td><samp>org/apache/**/CVS/*</samp></td>
+    <td>Matches all files in <samp>CVS</samp> directories
       that are located anywhere in the directory tree under
-      <code>org/apache</code>.<br>
+      <samp>org/apache</samp>.<br/>
       Matches:
-      <pre>
-      org/apache/CVS/Entries
-      org/apache/jakarta/tools/ant/CVS/Entries
-      </pre>
-      But not:
-      <pre>
-      org/apache/CVS/foo/bar/Entries
-      </pre>
-      (<code>foo/bar/</code> part does not match)</td>
+<pre>
+org/apache/CVS/Entries
+org/apache/jakarta/tools/ant/CVS/Entries</pre>
+But not:
+<pre>org/apache/CVS/foo/bar/Entries</pre>
+(<samp>foo/bar/</samp> part does not match)</td>
   </tr>
   <tr>
-    <td valign="top"><code>**/test/**</code></td>
-    <td valign="top">Matches all files that have a <code>test</code>
-        element in their path, including <code>test</code> as a filename.</td>
+    <td><samp>**/test/**</samp></td>
+    <td>Matches all files that have a <samp>test</samp>
+        element in their path, including <samp>test</samp> as a filename.</td>
   </tr>
 </table>
 <p>When these patterns are used in inclusion and exclusion, you have a powerful
 way to select just the files you want.</p>
 
-<h3><a name="selectors">Selectors</a></h3>
+<h3 id="selectors">Selectors</h3>
 <p>The <a href="Types/fileset.html"><code>&lt;fileset&gt;</code></a>,
-whether implicit or explicit in the
-directory-based task, also acts as an
-<a href="Types/selectors.html#andselect"><code>&lt;and&gt;</code></a>
+whether implicit or explicit in the directory-based task, also acts as
+an <a href="Types/selectors.html#andselect"><code>&lt;and&gt;</code></a>
 selector container. This can be used to create arbitrarily complicated
-selection criteria for the files the task should work with. See the
-<a href="Types/selectors.html">Selector</a> documentation for more
-information.</p>
+selection criteria for the files the task should work with. See
+the <a href="Types/selectors.html">Selector</a> documentation for
+more information.</p>
 
-<h3><a name="tasklist">Standard Tasks/Filesets</a></h3>
+<h3 id="tasklist">Standard Tasks/FileSets</h3>
 <p>Many of the standard tasks in ant take one or more filesets which follow
 the rules given here. This list, a subset of those, is a list of standard ant
 tasks that can act as an implicit fileset:</p>
 <ul>
-      <li><a href="Tasks/checksum.html"><code>&lt;checksum&gt;</code></a></li>
-  <li><a href="Tasks/copydir.html"><code>&lt;copydir&gt;</code></a> (deprecated)</li>
+  <li><a href="Tasks/checksum.html"><code>&lt;checksum&gt;</code></a></li>
+  <li><a href="Tasks/copydir.html"><code>&lt;copydir&gt;</code></a> (<em>deprecated</em>)</li>
   <li><a href="Tasks/delete.html"><code>&lt;delete&gt;</code></a></li>
   <li><a href="Tasks/dependset.html"><code>&lt;dependset&gt;</code></a></li>
   <li><a href="Tasks/fixcrlf.html"><code>&lt;fixcrlf&gt;</code></a></li>
   <li><a href="Tasks/javac.html"><code>&lt;javac&gt;</code></a></li>
   <li><a href="Tasks/replace.html"><code>&lt;replace&gt;</code></a></li>
   <li><a href="Tasks/rmic.html"><code>&lt;rmic&gt;</code></a></li>
-  <li><a href="Tasks/style.html"><code>&lt;style&gt;</code> (aka <code>&lt;xslt&gt;</code>)</a></li>
+  <li><a href="Tasks/style.html"><code>&lt;xslt&gt;</code> (aka <code>&lt;style&gt;</code>)</a></li>
   <li><a href="Tasks/tar.html"><code>&lt;tar&gt;</code></a></li>
   <li><a href="Tasks/zip.html"><code>&lt;zip&gt;</code></a></li>
   <li><a href="Tasks/ejb.html#ddcreator"><code>&lt;ddcreator&gt;</code></a></li>
@@ -221,38 +220,34 @@
   <li><a href="Tasks/cab.html"><code>&lt;cab&gt;</code></a></li>
   <li><a href="Tasks/native2ascii.html"><code>&lt;native2ascii&gt;</code></a></li>
   <li><a href="Tasks/netrexxc.html"><code>&lt;netrexxc&gt;</code></a></li>
-  <li>
-    <a href="Tasks/renameextensions.html"><code>&lt;renameextensions&gt;</code></a>
-  </li>
+  <li><a href="Tasks/renameextensions.html"><code>&lt;renameextensions&gt;</code></a></li>
   <li><a href="Tasks/depend.html"><code>&lt;depend&gt;</code></a></li>
   <li><a href="Tasks/translate.html"><code>&lt;translate&gt;</code></a></li>
   <li><a href="Tasks/image.html"><code>&lt;image&gt;</code></a></li>
-  <li><a href="Tasks/jlink.html"><code>&lt;jlink&gt;</code></a> (deprecated)</li>
-  <li><a href="Tasks/jspc.html"><code>&lt;jspc&gt;</code></a></li>
+  <li><a href="Tasks/jlink.html"><code>&lt;jlink&gt;</code></a> (<em>deprecated</em>)</li>
+  <li><a href="Tasks/jspc.html"><code>&lt;jspc&gt;</code></a> (<em>deprecated</em>)</li>
   <li><a href="Tasks/wljspc.html"><code>&lt;wljspc&gt;</code></a></li>
 </ul>
 
-<h3><a name="examples">Examples</a></h3>
+<h3 id="examples">Examples</h3>
 <pre>
 &lt;copy todir=&quot;${dist}&quot;&gt;
   &lt;fileset dir=&quot;${src}&quot;
            includes=&quot;**/images/*&quot;
-           excludes=&quot;**/*.gif&quot;
-  /&gt;
+           excludes=&quot;**/*.gif&quot;/&gt;
 &lt;/copy&gt;</pre>
-<p>This copies all files in directories called <code>images</code> that are
-located in the directory tree defined by <code>${src}</code> to the
-destination directory defined by <code>${dist}</code>,
-but excludes all <code>*.gif</code> files from the copy.</p>
+<p>This copies all files in directories called <samp>images</samp> that are
+located in the directory tree defined by <samp>${src}</samp> to the
+destination directory defined by <samp>${dist}</samp>,
+but excludes all <samp>*.gif</samp> files from the copy.</p>
 <pre>
 &lt;copy todir=&quot;${dist}&quot;&gt;
   &lt;fileset dir=&quot;${src}&quot;&gt;
     &lt;include name=&quot;**/images/*&quot;/&gt;
     &lt;exclude name=&quot;**/*.gif&quot;/&gt;
   &lt;/fileset&gt;
-&lt;/copy&gt;
-</pre>
-<p> The same as the example above, but expressed using nested elements.</p>
+&lt;/copy&gt;</pre>
+<p>The same as the example above, but expressed using nested elements.</p>
 
 <pre>
 &lt;delete dir=&quot;${dist}&quot;&gt;
@@ -263,52 +258,46 @@
 <p>Deleting the original set of files, the <code>delete</code> task can act
 as an implicit fileset.</p>
 
-<h3><a name="defaultexcludes">Default Excludes</a></h3>
+<h3 id="defaultexcludes">Default Excludes</h3>
 <p>There are a set of definitions that are excluded by default from all
-directory-based tasks. As of Ant 1.8.1 they are:</p>
+directory-based tasks. <em>Since Ant 1.8.1</em> they are:</p>
 <pre>
-     **/*~
-     **/#*#
-     **/.#*
-     **/%*%
-     **/._*
-     **/CVS
-     **/CVS/**
-     **/.cvsignore
-     **/SCCS
-     **/SCCS/**
-     **/vssver.scc
-     **/.svn
-     **/.svn/**
-     **/.DS_Store
-</pre>
-<p>Ant 1.8.2 adds the following default excludes:</p>
+**/*~
+**/#*#
+**/.#*
+**/%*%
+**/._*
+**/CVS
+**/CVS/**
+**/.cvsignore
+**/SCCS
+**/SCCS/**
+**/vssver.scc
+**/.svn
+**/.svn/**
+**/.DS_Store</pre>
+<p><em>Since Ant 1.8.2</em>, additional default excludes are:</p>
 <pre>
-     **/.git
-     **/.git/**
-     **/.gitattributes
-     **/.gitignore
-     **/.gitmodules
-     **/.hg
-     **/.hg/**
-     **/.hgignore
-     **/.hgsub
-     **/.hgsubstate
-     **/.hgtags
-     **/.bzr
-     **/.bzr/**
-     **/.bzrignore
-</pre>
+**/.git
+**/.git/**
+**/.gitattributes
+**/.gitignore
+**/.gitmodules
+**/.hg
+**/.hg/**
+**/.hgignore
+**/.hgsub
+**/.hgsubstate
+**/.hgtags
+**/.bzr
+**/.bzr/**
+**/.bzrignore</pre>
 <p>If you do not want these default excludes applied, you may disable
-them with the <code>defaultexcludes=&quot;no&quot;</code>
-attribute.</p>
+them with the <var>defaultexcludes</var>=<q>no</q> attribute.</p>
 
 <p>This is the default list; note that you can modify the list of
-default excludes by using the <a
-href="Tasks/defaultexcludes.html">defaultexcludes</a> task.</p>
-
-
+default excludes by using
+the <a href="Tasks/defaultexcludes.html">defaultexcludes</a> task.</p>
 
 </body>
 </html>
-
diff --git a/manual/feedback.html b/manual/feedback.html
index 70027f6..eefc8aa 100644
--- a/manual/feedback.html
+++ b/manual/feedback.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,59 +15,54 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
-<title>Apache Ant User Manual - Feedback</title>
+<title>Apache Ant User Manual&mdash;Feedback</title>
 </head>
 
 <body>
 
-<h1><a name="feedback">Feedback</a> and Troubleshooting</h1>
-<p>If things do not work, especially simple things like <tt>ant -version</tt>, 
-  then something is wrong with your configuration. Before filing bug reports and 
-  emailing all the Apache Ant mailing lists</p>
+<h1 id="feedback">Feedback and Troubleshooting</h1>
+<p>If things do not work, especially simple things like <kbd>ant -version</kbd>, then something is
+  wrong with your configuration. Before filing bug reports and emailing all the Apache Ant mailing
+  lists</p>
 <ol>
-  <li>Check your environment variables. Are ANT_HOME and JAVA_HOME correct? If 
-    they have quotes or trailing slashes, remove them.</li>
-  <li>Unset CLASSPATH; if that is wrong things go horribly wrong. Ant does not 
-    need the CLASSPATH variable defined to anything to work.</li>
-  <li>Make sure there are no versions of crimson.jar or other XML parsers in JRE/ext</li>
-  <li>Is your path correct? is Ant on it? What about JDK/bin? have you tested 
-    this? If you are using Jikes, is it on the path? A createProcess error (especially 
-    with ID=2 on windows) usually means executable not found on the path.</li>
-  <li>Which version of ant are you running? Other applications distribute a copy 
-    -it may be being picked up by accident.</li>
-  <li>If a task is failing to run is optional.jar in ANT_HOME/lib? Are there any 
-    libraries which it depends on missing?</li>
-  <li>If a task doesn't do what you expect, run <tt>ant -verbose</tt> or <tt>ant 
-    -debug</tt> to see what is happening</li>
+  <li>Check your environment variables. Are <code>ANT_HOME</code> and <code>JAVA_HOME</code>
+    correct? If they have quotes or trailing slashes, remove them.</li>
+  <li>Unset <code>CLASSPATH</code>; if that is wrong things go horribly wrong. Ant does not need
+    the <code>CLASSPATH</code> variable defined to anything to work.</li>
+  <li>Make sure there are no versions of <samp>crimson.jar</samp> or other XML parsers
+    in <samp>JAVA_HOME/jre/lib/ext</samp></li>
+  <li>Is your path correct? is Ant on it? What about <samp>JAVA_HOME/bin</samp>? have you tested
+    this? If you are using Jikes, is it on the path? A CreateProcess error (especially
+    with <code>error=2</code>) on Windows usually means executable not found on the path.</li>
+  <li>Which version of ant are you running? Other applications distribute a copy&mdash;it may be
+    being picked up by accident.</li>
+  <li>If a task failing to run is from <samp>optional.jar</samp> in <samp>ANT_HOME/lib</samp>? Are
+    there any libraries which it depends on missing?</li>
+  <li>If a task doesn't do what you expect, run <kbd>ant -verbose</kbd> or <kbd>ant -debug</kbd>
+    to see what is happening</li>
 </ol>
-<p>If you can't fix your problem, start with the <a href="http://ant.apache.org/mail.html" target="_top">Ant 
-  User Mailing List</a> . These are other ant users who will help you learn to 
-  use ant. If they cannot fix it then someone may suggest filing a bug report, 
-  which will escalate the issue. Remember of course, that support, like all open 
-  source development tasks, is voluntary. If you haven't invested time in helping 
-  yourself by following the steps above, it is unlikely that anyone will invest 
-  the time in helping you. </p>
-<p>Also, if you don't understand something, the <a href="http://ant.apache.org/mail.html" target="_top">Ant 
-  User Mailing List</a> is the place to ask questions. Not the developer list, 
-  nor the individuals whose names appears in the source and documentation. If 
-  they answered all such emails, nobody would have any time to improve ant. </p>
-<p>To provide feedback on this software, please subscribe to the <a href="http://ant.apache.org/mail.html" target="_top">Ant 
-  User Mailing List</a> </p>
-
-<p>If you want to contribute to Ant or stay current with the latest
-development, join the
-<a href="http://ant.apache.org/mail.html" target="_top">Ant Development Mailing List</a>
-</p>
-<p>A searchable archive can be found at <a
-href="http://marc.theaimsgroup.com" target="_top">http://marc.theaimsgroup.com</a>.
-Other archives will be documented online at  <a href="http://ant.apache.org/mail.html#Archives" target="_top">Mailing Lists Archives</a> </p>
-
+<p>If you can't fix your problem, start with the <a href="https://ant.apache.org/mail.html"
+  target="_top">Ant User Mailing List</a>. These are other ant users who will help you learn to use
+  ant. If they cannot fix it then someone may suggest filing a bug report, which will escalate the
+  issue. Remember of course, that support, like all open source development tasks, is voluntary. If
+  you haven't invested time in helping yourself by following the steps above, it is unlikely that
+  anyone will invest the time in helping you.</p>
+<p>Also, if you don't understand something, the <a href="https://ant.apache.org/mail.html"
+  target="_top">Ant User Mailing List</a> is the place to ask questions. Not the developer list, nor
+  the individuals whose names appears in the source and documentation. If they answered all such
+  emails, nobody would have any time to improve Ant.</p>
+<p>To provide feedback on this software, please subscribe to
+  the <a href="https://ant.apache.org/mail.html" target="_top">Ant User Mailing List</a></p>
+<p>If you want to contribute to Ant or stay current with the latest development, join
+  the <a href="https://ant.apache.org/mail.html" target="_top">Ant Development Mailing List</a></p>
+<p>A searchable archive can be found at <a href="https://marc.info"
+  target="_top">https://marc.info</a>. Other archives will be documented online
+  at <a href="https://ant.apache.org/mail.html#Archives" target="_top">Mailing Lists
+  Archives</a></p>
 
 </body>
 </html>
-
diff --git a/manual/ide.html b/manual/ide.html
index 7f2bc6d..dfafe10 100644
--- a/manual/ide.html
+++ b/manual/ide.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>IDE Integration</title>
 <base target="mainFrame"/>
@@ -34,72 +34,42 @@
 
 <ul>
   <li>
-    <a href="http://antrunner.sourceforge.net/">
-      AntRunner For JBuilder (unbundled)
-    </a>
+    <a href="Integration/jext-plugin.html">AntWork Plugin for the Jext Java Text Editor
+    (unbundled)</a>
   </li>
   <li>
-    <a href="Integration/jext-plugin.html">
-      AntWork Plugin for the Jext Java Text Editor (unbundled)
-    </a>
+    <a href="http://jdee.sourceforge.net/" target="_top">JDEE (Java Development Environment for
+    Emacs)</a> has built-in text Ant integration: selection of target through text field, execution,
+    hyperlink to compilation errors. Installation: built-in JDEE 2.2.8 or later. Configuration:
+    through customize menu "Jde Build Function"
   </li>
   <li>
-    <a href="http://jdee.sunsite.dk/">
-      JDEE (Java Development Environment for Emacs)
-    </a> has built-in text ANT integration: selection of target through text
-    field, execution, hyperlink to compilation errors. Installation: built-in
-    JDEE 2.2.8 or later. Configuration: through customize menu
-    "Jde Build Function"
+    <a href="https://www.jetbrains.com/idea/" target="_top">IDEA</a> has built-in GUI ANT
+    integration: GUI selection of targets, execution, hyperlink to compilation errors
   </li>
   <li>
-    <a href="http://www.intellij.com/idea/">
-      IDEA
-    </a> has built-in GUI ANT integration: GUI selection of targets, execution,
-    hyperlink to compilation errors
+    <a href="https://netbeans.org/" target="_top">NetBeans</a> IDE uses Ant as the basis for its
+    project system starting with the 4.0 release
   </li>
   <li>
-    <a href="http://ant.netbeans.org/">
-      NetBeans
-    </a>
-    NetBeans IDE uses Ant as the basis for its project system starting with the 4.0 release.
+    <a href="http://jedit.org/" target="_top">jEdit</a> is an open source Java IDE with some great
+    plugins for Java dev, a good XML editor and the Antfarm plugin to execute targets in a build
+    file
   </li>
   <li>
-    <a href="http://jedit.org/">
-      jEdit
-    </a>
-    jEdit is an open source java IDE with some great plugins for Java dev, a
-    good XML editor and the Antfarm plugin to execute targets in a build
-    file.
+    <a href="https://eclipse.org/" target="_top">Eclipse</a> is IBM's counterpoint to NetBeans; an
+    open source IDE with Java and Ant support
   </li>
   <li>
-    <a href="http://eclipse.org/">
-      Eclipse
-    </a>
-    Eclipse is IBM's counterpoint to NetBeans; an open source IDE with
-    Java and Ant support.
+    <a href="http://www.placidsystems.com/virtualant/" target="_top">Virtual Ant</a> GUI allows you
+    to work on a Virtual File System without dealing with the XML; plugs into Eclipse, Netbeans
+    &amp; IntelliJ
   </li>
   <li>
-    <a href="http://www.placidsystems.com/virtualant/">
-      Virtual Ant</a> GUI allows you to work on a Virtual File System without dealing with the XML. Plugs into Eclipse, Netbeans &amp; Intellij.
-  </li>
-  <li>
-    <a href="http://www7b.software.ibm.com/wsdd/library/techarticles/0203_searle/searle1.html">
-      WebSphere Studio Application Developer
-    </a>
-  </li>
-  <li>
-    <a href="http://www.borland.com/jbuilder/pdf/jb9_feamatrix.pdf">
-      JBuilder 9 Personal
-    </a>
-    JBuilder supports Ant with the following features. Add Ant nodes to
-    projects and execute Ant targets from within JBuilder. Add custom Ant-based
-    build tasks with custom Ant libraries to run Ant from within JBuilder.
-    Rapid navigation from Ant build error messages to source files.
-    Customize build menu and toolbar with custom build targets.
+    <a href="https://www.ibm.com/developerworks/offers/wsad2.html" target="_top">WebSphere Studio
+    Application Developer</a>
   </li>
 </ul>
 
-
-
 </body>
 </html>
diff --git a/manual/ifunless.html b/manual/ifunless.html
index abbdce1..924b517 100644
--- a/manual/ifunless.html
+++ b/manual/ifunless.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,39 +15,33 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us"/>
   <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
   <title>If and Unless on all tasks/nested elements</title>
 </head>
 
 <body>
-  <h1><a name="if_and_unless">If And Unless</a></h1>
+  <h1 id="if_and_unless">If And Unless</h1>
 
-  <p>Since Ant 1.9.1 it is possible to add if and unless attributes on all tasks and nested elements using special namespaces.</p>
+  <p><em>Since Ant 1.9.1</em>, it is possible to add <var>if</var> and <var>unless</var> attributes on all tasks and nested elements using special namespaces.</p>
 
   <p>In order to use this feature you need to add the following namespace declarations</p>
-  <blockquote><pre>
-    xmlns:if=&quot;ant:if&quot;
-    xmlns:unless=&quot;ant:unless&quot;
-    </pre>
-  </blockquote>
+  <pre>
+xmlns:if=&quot;ant:if&quot;
+xmlns:unless=&quot;ant:unless&quot;</pre>
 
-  <p>The if and unless namespaces support the following 3 conditions :
-  <ul>
-    <li>true</li>true if the value of the attribute evaluates to true
-    <li>blank</li>true if the value of the attribute is null or empty
-    <li>set</li>true if the specified property is set
-  </ul></p>
-
-<blockquote>
-<pre>
+  <p>The <code>if</code> and <code>unless</code> namespaces support the following 3 conditions:</p>
+  <dl>
+      <dt><q>true</q></dt><dd>true if the value of the attribute evaluates to true</dd>
+      <dt><q>blank</q></dt><dd>true if the value of the attribute is null or empty</dd>
+      <dt><q>set</q></dt><dd>true if the specified property is set</dd>
+  </dl>
+  <pre>
 &lt;project name=&quot;tryit&quot;
  xmlns:if=&quot;ant:if&quot;
- xmlns:unless=&quot;ant:unless&quot;
-&gt;
+ xmlns:unless=&quot;ant:unless&quot;&gt;
  &lt;exec executable=&quot;java&quot;&gt;
    &lt;arg line=&quot;-X&quot; if:true=&quot;${showextendedparams}&quot;/&gt;
    &lt;arg line=&quot;-version&quot; unless:true=&quot;${showextendedparams}&quot;/&gt;
@@ -56,9 +51,7 @@
  &lt;/condition&gt;
  &lt;echo if:set=&quot;onmac&quot;&gt;running on MacOS&lt;/echo&gt;
  &lt;echo unless:set=&quot;onmac&quot;&gt;not running on MacOS&lt;/echo&gt;
-&lt;/project&gt;
-</pre>
-</blockquote>
+&lt;/project&gt;</pre>
 
 </body>
 </html>
diff --git a/manual/index.html b/manual/index.html
index 9df48a0..ebf78d6 100644
--- a/manual/index.html
+++ b/manual/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Apache Ant&trade; User Manual</title>
 </head>
@@ -27,7 +27,7 @@
 <frame src="cover.html" name="mainFrame">
 </frameset>
 <noframes>
-<H2>Apache Ant&trade; User Manual</H2>
+<h2>Apache Ant&trade; User Manual</h2>
 
 <a href="toc.html">Apache Ant User Manual</a></noframes>
 
diff --git a/manual/inputhandler.html b/manual/inputhandler.html
index 1333157..a773ab1 100644
--- a/manual/inputhandler.html
+++ b/manual/inputhandler.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,8 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>InputHandler</title>
 </head>
@@ -27,90 +26,77 @@
 
 <h2>Overview</h2>
 
-<p>When a task wants to prompt a user for input, it doesn't simply
-read the input from the console as this would make it impossible to
-embed Apache Ant in an IDE.  Instead it asks an implementation of the
-<code>org.apache.tools.ant.input.InputHandler</code> interface to
-prompt the user and hand the user input back to the task.</p>
+<p>When a task wants to prompt a user for input, it doesn't simply read the input from the console
+as this would make it impossible to embed Apache Ant in an IDE.  Instead it asks an implementation
+of the <code class="code">org.apache.tools.ant.input.InputHandler</code> interface to prompt the
+user and hand the user input back to the task.</p>
 
-<p>To do this, the task creates an <code>InputRequest</code> object
-and passes it to the <code>InputHandler</code> Such an
-<code>InputRequest</code> may know whether a given user input is valid
-and the <code>InputHandler</code> is supposed to reject all invalid
-input.</p>
+<p>To do this, the task creates an <code class="code">InputRequest</code> object and passes it to
+the <code class="code">InputHandler</code>. Such an <code class="code">InputRequest</code> may know
+whether a given user input is valid and the <code class="code">InputHandler</code> is supposed to
+reject all invalid input.</p>
 
-<p>Exactly one <code>InputHandler</code> instance is associated with
-every Ant process, users can specify the implementation using the
-<code>-inputhandler</code> command line switch.</p>
+<p>Exactly one <code class="code">InputHandler</code> instance is associated with every Ant process,
+users can specify the implementation using the <kbd>-inputhandler</kbd> command line switch.</p>
 
 <h2>InputHandler</h2>
 
-<p>The <code>InputHandler</code> interface contains exactly one
-method</p>
+<p>The <code class="code">InputHandler</code> interface contains exactly one method</p>
 
 <pre>
-    void handleInput(InputRequest request) 
-        throws org.apache.tools.ant.BuildException;
-</pre>
+void handleInput(InputRequest request)
+    throws org.apache.tools.ant.BuildException;</pre>
 
-<p>with some pre- and postconditions.  The main postcondition is that
-this method must not return unless the <code>request</code> considers
-the user input valid, it is allowed to throw an exception in this
-situation.</p>
+<p>with some pre- and postconditions.  The main postcondition is that this method must not return
+unless the <code>request</code> considers the user input valid; it is allowed to throw an exception
+in this situation.</p>
 
 <p>Ant comes with three built-in implementations of this interface:</p>
 
-<h3><a name="defaulthandler">DefaultInputHandler</a></h3>
+<h3 id="defaulthandler">DefaultInputHandler</h3>
 
-<p>This is the implementation you get, when you don't use the
-<code>-inputhandler</code> command line switch at all.  This
-implementation will print the prompt encapsulated in the
-<code>request</code> object to Ant's logging system and re-prompt for
-input until the user enters something that is considered valid input
-by the <code>request</code> object.  Input will be read from the
-console and the user will need to press the Return key.</p>
+<p>This is the implementation you get, when you don't use the <kbd>-inputhandler</kbd> command line
+switch at all.  This implementation will print the prompt encapsulated in the <code>request</code>
+object to Ant's logging system and re-prompt for input until the user enters something that is
+considered valid input by the <code>request</code> object.  Input will be read from the console and
+the user will need to press the Return key.</p>
 
 <h3>PropertyFileInputHandler</h3>
 
-<p>This implementation is useful if you want to run unattended build
-processes.  It reads all input from a properties file and makes the
-build fail if it cannot find valid input in this file.  The name of
-the properties file must be specified in the Java system property
-<code>ant.input.properties</code>.</p>
+<p>This implementation is useful if you want to run unattended build processes.  It reads all input
+from a properties file and makes the build fail if it cannot find valid input in this file.  The
+name of the properties file must be specified in the Java system
+property <code>ant.input.properties</code>.</p>
 
-<p>The prompt encapsulated in a <code>request</code> will be used as
-the key when looking up the input inside the properties file.  If no
-input can be found, the input is considered invalid and an exception
-will be thrown.</p>
+<p>The prompt encapsulated in a <code>request</code> will be used as the key when looking up the
+input inside the properties file.  If no input can be found, the input is considered invalid and an
+exception will be thrown.</p>
 
-<p><strong>Note</strong> that <code>ant.input.properties</code> must
-be a Java system property, not an Ant property.  I.e. you cannot
-define it as a simple parameter to <code>ant</code>, but you can
+<p><strong>Note</strong> that <code>ant.input.properties</code> must be a Java system property, not
+an Ant property.  I.e. you cannot define it as a simple parameter to <kbd>ant</kbd>, but you can
 define it inside the <code>ANT_OPTS</code> environment variable.</p>
 
 <h3>GreedyInputHandler</h3>
-
-<p>Like the default implementation, this InputHandler reads from standard
-input. However, it consumes <i>all</i> available input. This behavior is
-useful for sending Ant input via an OS pipe. <b>Since Ant 1.7</b>.</p>
+<p><em>Since Ant 1.7</em></p>
+<p>Like the default implementation, this InputHandler reads from standard input. However, it
+consumes <em>all</em> available input. This behavior is useful for sending Ant input via an OS
+pipe.</p>
 
 <h3>SecureInputHandler</h3>
-
-<p>This InputHandler calls <code>System.console().readPassword()</code>,
-available since Java 1.6.  On earlier platforms it falls back to the
-behavior of DefaultInputHandler. <b>Since Ant 1.7.1</b>.</p>
+<p><em>Since Ant 1.7.1</em></p>
+<p>This InputHandler calls <code class="code">System.console().readPassword()</code>, available
+since Java 6.  On earlier platforms it falls back to the behavior
+of <code class="code">DefaultInputHandler</code>.</p>
 
 <h2>InputRequest</h2>
 
-<p>Instances of <code>org.apache.tools.ant.input.InputRequest</code>
-encapsulate the information necessary to ask a user for input and
-validate this input.</p>
+<p>Instances of <code class="code">org.apache.tools.ant.input.InputRequest</code> encapsulate the
+information necessary to ask a user for input and validate this input.</p>
 
-<p>The instances of <code>InputRequest</code> itself will accept any
-input, but subclasses may use stricter validations.
-<code>org.apache.tools.ant.input.MultipleChoiceInputRequest</code>
-should be used if the user input must be part of a predefined set of
-choices.</p>
+<p>The instances of <code class="code">InputRequest</code> itself will accept any input, but
+subclasses may use stricter
+validations. <code class="code">org.apache.tools.ant.input.MultipleChoiceInputRequest</code> should
+be used if the user input must be part of a predefined set of choices.</p>
 
-
+</body>
 </html>
diff --git a/manual/install.html b/manual/install.html
index 93a09f1..c959dbe 100644
--- a/manual/install.html
+++ b/manual/install.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Installing Apache Ant</title>
 </head>
@@ -31,18 +31,18 @@
 To get up and running with the binary distribution of Ant quickly, follow these steps:
 </p>
 <ol>
-<li>Make sure you have a Java environment installed, See <a href="#sysrequirements">System Requirements</a> for
+<li>Make sure you have a Java environment installed. See <a href="#sysrequirements">System Requirements</a> for
 details.</li>
 <li>Download Ant. See <a href="#getBinary">Binary Distribution</a> for details.</li>
 <li>Uncompress the downloaded file into a directory.</li>
-<li>Set environmental variables <code>JAVA_HOME</code> to your Java environment, <code>ANT_HOME</code> to the directory
-you uncompressed Ant to, and add <code>${ANT_HOME}/bin</code> (Unix) or <code>%ANT_HOME%/bin</code> (Windows) to
+<li>Set environmental variables: <code>JAVA_HOME</code> to your Java environment, <code>ANT_HOME</code> to the directory
+you uncompressed Ant to, and add <samp>${ANT_HOME}/bin</samp> (Unix) or <samp>%ANT_HOME%\bin</samp> (Windows) to
 your <code>PATH</code>. See <a href="#setup">Setup</a> for details.</li>
-<li>Optionally, from the <code>ANT_HOME</code> directory run <code>ant -f fetch.xml -Ddest=system</code> to get the
+<li>Optionally, from the <code>ANT_HOME</code> directory run <kbd>ant -f fetch.xml -Ddest=system</kbd> to get the
 library dependencies of most of the Ant tasks that require them. If you don't do this, many of the dependent Ant tasks
 will not be available. See <a href="#optionalTasks">Optional Tasks</a> for details and other options for
-the <code>-Ddest</code> parameter.</li>
-<li>Optionally, add any desired Antlibs. See <a href="http://ant.apache.org/antlibs/proper.html" target="_top">Ant
+the <kbd>-Ddest</kbd> parameter.</li>
+<li>Optionally, add any desired Antlibs. See <a href="https://ant.apache.org/antlibs/proper.html" target="_top">Ant
 Libraries</a> for a list.</li>
 </ol>
 <p>
@@ -63,17 +63,17 @@
 <h3 id="getBinary">Binary Distribution</h3>
 
 <p>
-The latest stable version of Ant is available from the Ant web page <a href="http://ant.apache.org/"
-target="_top">http://ant.apache.org/</a>
+The latest stable version of Ant is available from the Ant web page <a href="https://ant.apache.org/"
+target="_top">https://ant.apache.org/</a>
 </p>
 <p>
 The binary distribution of Ant is available as 3 different archives
 </p>
 <ol>
-<li><b>.zip</b> - Recommended compression format for Windows, can also be used on other platforms. Supported by many
-programs and some operating systems natively.</li>
-<li><b>.tar.gz</b> - Using the tar program to gather files together, and gzip to compress and uncompress.</li>
-<li><b>.tar.bz2</b> - Using the tar program to gather files together, and bzip2 to compress and uncompress.</li>
+<li><samp>.zip</samp>&mdash;Recommended compression format for Windows, can also be used on other platforms. Supported
+by many programs and some operating systems natively.</li>
+<li><samp>.tar.gz</samp>&mdash;Using the tar program to gather files together, and gzip to compress and uncompress.</li>
+<li><samp>.tar.bz2</samp>&mdash;Using the tar program to gather files together, and bzip2 to compress and uncompress.</li>
 </ol>
 <p>
 Choose the format that is best supported for your platform.
@@ -97,122 +97,130 @@
 eliminate inconsistencies between command-line and IDE Ant.
 </p>
 
-<h3>Bundled in Java applications</h3>
+<h3>Bundled in Java Applications</h3>
 
 <p>
 Many Java applications, most particularly application servers, ship with a version of Ant. These are primarily for
 internal use by the application, using the Java APIs to delegate tasks such as JSP page compilation to the Ant
 runtime. Such distributions are usually unsupported by everyone. Particularly troublesome are those products that not
-only ship with their own Ant release, they add their own version of ANT.BAT or ant.sh to the <code>PATH</code>. If Ant
-starts behaving weirdly after installing something, try the <a href="#diagnostics">diagnostics</a> advice.
+only ship with their own Ant release, they add their own version of <samp>ANT.BAT</samp> or <samp>ant.sh</samp> to
+the <code>PATH</code>. If Ant starts behaving weirdly after installing something, try
+the <a href="#diagnostics">diagnostics</a> advice.
 </p>
 
 <h3 id="sourceEdition">Source Distribution</h3>
 
 <p>
-If you prefer the source distribution, you can download the source for the latest Ant release from
-<a href="http://ant.apache.org/srcdownload.cgi" target="_top">http://ant.apache.org/srcdownload.cgi</a>.
+If you prefer the source distribution, you can download the source for the latest Ant release
+from <a href="https://ant.apache.org/srcdownload.cgi" target="_top">https://ant.apache.org/srcdownload.cgi</a>.
 </p>
 <p>
 If you prefer the leading-edge code, you can access the code as it is being developed via Git. The Ant website has
-details on <a href="http://ant.apache.org/git.html" target="_top">accessing Git</a>. All bug fixes will go in against
-the HEAD of the source tree, and the first response to many bugreps will be "have you tried the latest version". Don't
-be afraid to download and build a prerelease distribution, as everything other than new features are usually stable.
+details on <a href="https://ant.apache.org/git.html" target="_top">accessing Git</a>. All bug fixes will go in against
+the HEAD of the source tree, and the first response to many bug reports will be "have you tried the latest
+version". Don't be afraid to download and build a prerelease distribution, as everything other than new features are
+usually stable.
 </p>
 <p>
 See the section <a href="#buildingant">Building Ant</a> on how to build Ant from the source code. You can also access
-the <a href="https://git-wip-us.apache.org/repos/asf?p=ant.git;a=summary" target="_top">Ant Git repository</a> on-line.
+the <a href="https://gitbox.apache.org/repos/asf?p=ant.git;a=summary" target="_top">Ant Git repository</a> on-line.
 </p>
 
 <h3 id="archives">Archive Download Area Layout</h3>
 
 <p>
-Older versions of Ant are available in the archives at <a href="http://archive.apache.org/dist/ant/"
-target="_top">http://archive.apache.org/dist/ant/</a>. The files are organized as follows.
+Older versions of Ant are available in the archives at <a href="https://archive.apache.org/dist/ant/"
+target="_top">https://archive.apache.org/dist/ant/</a>. The files are organized as follows.
 </p>
 <table>
 <tr>
-  <th>Filename or Path</th>
-  <th>Description</th>
+  <th scope="col">Filename or Path</th>
+  <th scope="col">Description</th>
 </tr>
 <tr>
-  <td>KEYS</td>
+  <td><samp>KEYS</samp></td>
   <td>PGP keyfile. It contains the PGP keys of Ant developers so you can 'trust' the distribution.</td>
 </tr>
 <tr>
-  <td>RELEASE-NOTES-{version}.html</td>
+  <td><samp>RELEASE-NOTES-{version}.html</samp></td>
   <td>
     Release notes of the given version in HTML format. When upgrading your Ant installation you
-    should have a look at the <i>Changes that could break older environments</i> section.
+    should have a look at the <em>Changes that could break older environments</em> section.
   </td>
 </tr>
 <tr>
-  <td>ant-current-bin.zip</td>
+  <td><samp>ant-current-bin.zip</samp></td>
   <td>
-    ZIP archive containing the compiled version of Ant in the last released version. It is recommended that
-    you do not download the latest version this way, as the standard way of downloading described above will
-    redirect you to a mirror closer to you, thus making the download faster for you and reducing the load
+    ZIP archive containing the compiled version of Ant in the last released version. It is recommended that you do not
+    download the latest version this way, as the standard way of downloading described above will redirect you to a
+    mirror closer to you, thus making the download faster for you and reducing the load on Apache servers.
+  </td>
+</tr>
+<tr>
+  <td><samp>ant-current-src.zip</samp></td>
+  <td>
+    ZIP archive containing the sources of Ant. If you have this you can compile Ant. If you do not have
+    the <em>required</em> dependencies, the classes depending on them are just not built. Again, it is preferred to use
+    the standard way of getting the source package described above to make your download quicker and to reduce the load
     on Apache servers.
   </td>
 </tr>
 <tr>
-  <td>ant-current-src.zip</td>
+  <td><samp>ant-current-*.asc</samp></td>
   <td>
-    ZIP archive containing the sources of Ant. If you have this you can compile Ant. If you do not have the
-    <i>required</i> dependencies, the classes depending on them are just not built. Again, it is preferred to use the
-    standard way of getting the source package described above to make your download quicker and to reduce the load on
-    Apache servers.
+    Security file for checking the correctness of the zip file. This one is
+    the <a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy" target="_top">PGP</a> signature.
   </td>
 </tr>
 <tr>
-  <td>ant-current-*.asc</td>
+  <td><samp>ant-current-*.md5</samp></td>
   <td>
-    Security file for checking the correctness of the zip file. This one is the
-    <a href="http://en.wikipedia.org/wiki/Pretty_Good_Privacy" target="_blank">PGP</a> signature.
+    Security file for checking the correctness of the zip file. This one is
+    the <a href="https://en.wikipedia.org/wiki/Md5" target="_top">MD5</a> checksum.
   </td>
 </tr>
 <tr>
-  <td>ant-current-*.md5</td>
+  <td><samp>ant-current-*.sha1</samp></td>
   <td>
-    Security file for checking the correctness of the zip file. This one is the
-    <a href="http://en.wikipedia.org/wiki/Md5" target="_blank">MD5</a> checksum.
+    Security file for checking the correctness of the zip file. This one is
+    the <a href="https://en.wikipedia.org/wiki/SHA-1" target="_top">SHA1</a> checksum.
   </td>
 </tr>
 <tr>
-  <td>ant-current-*.sha1</td>
+  <td><samp>ant-current-*.sha512</samp></td>
   <td>
-    Security file for checking the correctness of the zip file. This one is the
-    <a href="http://en.wikipedia.org/wiki/SHA-1" target="_blank">SHA1</a> checksum.
+    Security file for checking the correctness of the zip file. This one is
+    the <a href="https://en.wikipedia.org/wiki/SHA-2" target="_top">SHA512</a> checksum.
   </td>
 </tr>
 <tr>
-  <td>antlibs/</td>
+  <td><samp>antlibs/</samp></td>
   <td>
     This directory holds the Antlibs that are made of available by the Apache Ant project. Antlibs are bundles of Ant
     tasks that are not delivered as part of the Ant core but are available as optional downloads.
   </td>
 </tr>
 <tr>
-  <td>binaries/</td>
+  <td><samp>binaries/</samp></td>
   <td>
     The binaries directory holds specific Ant releases bundled in both ZIP and tar.gz archive formats. The named
-    releases are in contrast to the ant-current-bin.zip file in the parent directory, which is always guaranteed to be
-    the most current release of Ant.
+    releases are in contrast to the <samp>ant-current-bin.zip</samp> file in the parent directory, which is always
+    guaranteed to be the most current release of Ant.
   </td>
 </tr>
 <tr>
-  <td>common/</td>
+  <td><samp>common/</samp></td>
   <td>
     The common directory holds various files, such as the Apache License file that Ant is licensed under, that people
     may wish to examine without having to download the whole Ant distribution.
   </td>
 </tr>
 <tr>
-  <td>source/</td>
+  <td><samp>source/</samp></td>
   <td>
     The source directory holds the source code for specific Ant releases bundled in both ZIP and tar.gz archive
-    formats. The named releases are in contrast to the ant-current-src.zip file in the parent directory, which is always
-    guaranteed to hold the source code for the most current release of Ant.
+    formats. The named releases are in contrast to the <samp>ant-current-src.zip</samp> file in the parent directory,
+    which is always guaranteed to hold the source code for the most current release of Ant.
   </td>
 </tr>
 </table>
@@ -221,26 +229,27 @@
 <h2 id="sysrequirements">System Requirements</h2>
 <p>
 Ant has been used successfully on many platforms, including Linux, commercial flavours of Unix such as Solaris and
-HP-UX, macOS, Windows NT descendants, OS/2 Warp, Novell Netware 6, OpenVMS. The platforms used most for development
-are, in no particular order, Linux, macOS, Microsoft Windows and Unix; these are therefore that platforms that tend to
-work best. As of Ant 1.7, Windows 9x is no longer supported.
+HP-UX, macOS, Windows NT descendants, OS/2 Warp, Novell Netware 6, OpenVMS. The platforms used most for development are,
+in no particular order, Linux, macOS, Microsoft Windows and Unix; these are therefore that platforms that tend to work
+best. <em>Since Ant 1.7</em>, Windows 9x is no longer supported.
 </p>
 <p>
-For the current version of Ant (1.9), you will also need a JDK installed on your system, version 1.5 or later required.
+For the current version of Ant (1.10), you will also need a JDK installed on your system, version 8 or later required.
 The more up-to-date the version of Java, the more Ant tasks you get.
 </p>
 <p>
-<strong>Note:</strong> If a JDK is not present, only the runtime (JRE), then many tasks will not work.
+<strong>Note</strong>: If a JDK is not present, only the runtime (JRE), then many tasks will not work.
 </p>
 <p>
-  <strong>Note:</strong>
-    Ant 1.8.* works with JDK 1.4 and higher, Ant 1.7.* works with JDK 1.3 and higher,
+  <strong>Note</strong>:
+    Ant 1.10.* works with JDK 8 and higher,
+    Ant 1.9.* works with JDK 1.5 and higher, Ant 1.8.* works with JDK 1.4 and higher, Ant 1.7.* works with JDK 1.3 and higher,
     Ant 1.6.* works with JDK 1.2 and higher, Ant 1.2 to Ant 1.5.* work with JDK 1.1 and higher.
 </p>
 
 <h3>Open Source Java Runtimes</h3>
 <p>
-The Ant team strongly supports users running Ant on <a target="_blank" href="http://openjdk.java.net/">OpenJDK</a> and
+The Ant team strongly supports users running Ant on <a href="https://openjdk.java.net/" target="_top">OpenJDK</a> and
 other open source Java runtimes, and so strives to have a product that works well on those platforms.
 </p>
 
@@ -261,54 +270,37 @@
    +--- etc // contains xsl goodies to:
             //   - create an enhanced report from xml output of various tasks.
             //   - migrate your build files and get rid of 'deprecated' warning
-            //   - ... and more ;-)
-</pre>
+            //   - ... and more ;-)</pre>
 <p>
-Only the <code>bin</code> and <code>lib</code> directories are required to run Ant.
+Only the <samp>bin</samp> and <samp>lib</samp> directories are required to run Ant.
 </p>
 <p>
-To install Ant, choose a directory and copy the distribution files there. This directory will be known as
-<code>ANT_HOME</code>.
+To install Ant, choose a directory and copy the distribution files there. This directory will be known
+as <code>ANT_HOME</code>.
 </p>
 
-<table width="80%">
-<tr>
-  <td colspan="2">
-    <b>Windows 95, Windows 98 &amp; Windows ME Note:</b>
-  </td>
-</tr>
-<tr>
-  <td width="5%">&nbsp;</td>
-  <td>
-    <i>Note that current releases of Ant no longer support these systems. If you are using an older version of Ant,
+<h3>Windows 95, Windows 98 &amp; Windows ME Note</h3>
+  <p>
+    <em>Note that current releases of Ant no longer support these systems. If you are using an older version of Ant,
     however, the script used to launch Ant will have problems if <code>ANT_HOME</code> is a long filename (i.e. a
     filename which is not of the format known as &quot;8.3&quot;). This is due to limitations in the OS's handling of
-    the <code>&quot;for&quot;</code> batch file statement. It is recommended, therefore, that Ant be installed in a
-    <b>short</b>, 8.3 path, such as <code>C:\Ant</code>.</i>
-  </td>
-</tr>
-<tr>
-  <td width="5%">&nbsp;</td>
-  <td>
-    <p>
+    the <code>&quot;for&quot;</code> batch file statement. It is recommended, therefore, that Ant be installed in
+    a <strong>short</strong>, 8.3 path, such as <samp>C:\Ant</samp>.</em>
+  </p>
+  <p>
     On these systems you will also need to configure more environment space to cater for the environment variables used
-    in the Ant launch script. To do this, you will need to add or update the following line in the
-    <code>config.sys</code> file
-    </p>
-    <p>
-    <code>shell=c:\command.com c:\ /p /e:32768</code>
-    </p>
-  </td>
-</tr>
-</table>
+    in the Ant launch script. To do this, you will need to add or update the following line in
+    the <samp>config.sys</samp> file
+  </p>
+  <pre>shell=c:\command.com c:\ /p /e:32768</pre>
 
 <h3 id="setup">Setup</h3>
 <p>
-Before you can run Ant there is some additional setup you will need to do unless you are installing the
-<a href="#jpackage">RPM version from jpackage.org</a>:
+Before you can run Ant there is some additional setup you will need to do unless you are installing
+the <a href="#jpackage">RPM Version from jpackage.org</a>:
 </p>
 <ul>
-<li>Add the <code>bin</code> directory to your path.</li>
+<li>Add the <samp>bin</samp> directory to your path.</li>
 <li>Set the <code>ANT_HOME</code> environment variable to the directory where you installed Ant. On some operating
 systems, Ant's startup scripts can guess <code>ANT_HOME</code> (Unix dialects and Windows NT descendants), but it is
 better to not rely on this behavior.</li>
@@ -316,47 +308,39 @@
 below). This should be set to the directory where your JDK is installed.</li>
 </ul>
 <p>
-Operating System-specific instructions for doing this from the command line are in the <a href="#windows">Windows</a>,
-<a href="#bash">Linux/Unix (bash)</a>, and <a href="#tcshcsh">Linux/Unix (csh)</a> sections. Note that using this
-method, the settings will only be valid for the command line session you run them in.
+Operating System-specific instructions for doing this from the command line are in
+the <a href="#windows">Windows</a>, <a href="#bash">Linux/Unix (bash)</a>, and <a href="#tcshcsh">Linux/Unix (csh)</a>
+sections. Note that using this method, the settings will only be valid for the command line session you run them in.
 </p>
 <p>
-<strong>Note:</strong> Do not install Ant's <code>ant.jar</code> file into the <code>lib/ext</code> directory of the
+<strong>Note</strong>: Do not install Ant's <samp>ant.jar</samp> file into the <samp>lib/ext</samp> directory of the
 JDK/JRE. Ant is an application, whilst the extension directory is intended for JDK extensions. In particular there are
 security restrictions on the classes which may be loaded by an extension.
 </p>
 
-<table width="80%">
-<tr>
-  <td colspan="2">
-    <b>Windows Note:</b>
-  </td>
-</tr>
-<tr>
-  <td width="5%">&nbsp;</td>
-  <td>
-    The <code>ant.bat</code> script makes use of three environment variables - <code>ANT_HOME</code>,
-    <code>CLASSPATH</code> and <code>JAVA_HOME</code>. <b>Ensure</b> that <code>ANT_HOME</code> and
-    <code>JAVA_HOME</code> variables are set, and that they do <b><u>not</u></b> have quotes (either ' or &quot;) and
-    they do <b><u>not</u></b> end with \ or with /. <code>CLASSPATH</code> should be unset or empty.
-  </td>
-</tr>
-</table>
+<h3>Windows Note</h3>
+<p>
+    The <samp>ant.bat</samp> script makes use of three environment
+    variables&mdash;<code>ANT_HOME</code>, <code>CLASSPATH</code> and <code>JAVA_HOME</code>. <strong>Ensure</strong>
+    that <code>ANT_HOME</code> and <code>JAVA_HOME</code> variables are set, and that they do <strong>not</strong> have
+    quotes (either ' or &quot;) and they do <strong>not</strong> end with \ or with /. <code>CLASSPATH</code> should be
+    unset or empty.
+</p>
 
 <h3 id="checkInstallation">Check Installation</h3>
 <p>
-You can check the basic installation with opening a new shell and typing <code>ant</code>. You should get a message like
+You can check the basic installation with opening a new shell and typing <kbd>ant</kbd>. You should get a message like
 this
 </p>
-<pre>
+<pre class="output">
 Buildfile: build.xml does not exist!
 Build failed
 </pre>
 <p>
-So Ant works. This message is there because you need to write a buildfile for your project. With a <code>ant
--version</code> you should get an output like
+So Ant works. This message is there because you need to write a buildfile for your project. With a <kbd>ant
+-version</kbd> you should get an output like
 </p>
-<pre>
+<pre class="output">
 Apache Ant(TM) version 1.9.2 compiled on July 8 2013
 </pre>
 <p>
@@ -368,11 +352,11 @@
   <li>required: <code>%PATH%=...<i>maybe-other-entries</i>...;%ANT_HOME%\bin;...<i>maybe-other-entries</i>...</code></li>
 </ul>
 <p>
-<b>ANT_HOME</b> is used by the launcher script for finding the libraries.
-<b>JAVA_HOME</b> is used by the launcher for finding the JDK/JRE to use. (JDK is recommended as some tasks require the
-Java tools.) If not set, the launcher tries to find one via the <code>%PATH%</code> environment variable.
-<b>PATH</b> is set for user convenience. With that set you can just start <i>ant</i> instead of always typing
-<i>the/complete/path/to/your/ant/installation/bin/ant</i>.
+<code>ANT_HOME</code> is used by the launcher script for finding the libraries. <code>JAVA_HOME</code> is used by the
+launcher for finding the JDK/JRE to use. (JDK is recommended as some tasks require the Java tools.) If not set, the
+launcher tries to find one via the <code>%PATH%</code> environment variable. <code>PATH</code> is set for user
+convenience. With that set you can just start <kbd>ant</kbd> instead of always
+typing <samp>the/complete/path/to/your/ant/installation/bin/ant</samp>.
 </p>
 
 <h3 id="optionalTasks">Optional Tasks</h3>
@@ -394,28 +378,28 @@
 
 <li>
 <p>
-In <code>${user.home}/.ant/lib</code> (as of Ant 1.6). This allows different users to add new libraries to Ant. All JAR
-files added to this directory are available to command-line Ant.
+In <code>${user.home}/.ant/lib</code> (<em>since Ant 1.6</em>). This allows different users to add new libraries to
+Ant. All JAR files added to this directory are available to command-line Ant.
 </p>
 </li>
 
 <li>
 <p>
-On the command line with a <code>-lib</code> parameter. This lets you add new JAR files on a case-by-case basis.
+On the command line with a <kbd>-lib</kbd> parameter. This lets you add new JAR files on a case-by-case basis.
 </p>
 </li>
 
 <li>
 <p>
-In the <code>CLASSPATH</code> environment variable. Avoid this; it makes the JAR files visible to <i>all</i> Java
+In the <code>CLASSPATH</code> environment variable. Avoid this; it makes the JAR files visible to <em>all</em> Java
 applications, and causes no end of support calls. See <a href="#classpath">below</a> for details.
 </p>
 </li>
 
 <li>
 <p>
-In some <code>&lt;classpath&gt;</code> accepted by the task itself. For example, as of Ant 1.7.0 you can run
-the <code>&lt;junit&gt;</code> task without <code>junit.jar</code> in Ant's own classpath, so long as it is included
+In some <code>&lt;classpath&gt;</code> accepted by the task itself. <em>Since Ant 1.7.0</em>, you can run
+the <code>&lt;junit&gt;</code> task without <samp>junit.jar</samp> in Ant's own classpath, so long as it is included
 (along with your program and tests) in the classpath passed when running the task.
 </p>
 <p>
@@ -429,7 +413,7 @@
 <p>
 If you are using the binary distribution of Ant, or if you are working from source code, you can easily gather most of
 the dependencies and install them for use with your Ant tasks. In your <code>ANT_HOME</code> directory you should see a
-file called <code>fetch.xml</code>. This is an Ant script that you can run to install almost all the dependencies that
+file called <samp>fetch.xml</samp>. This is an Ant script that you can run to install almost all the dependencies that
 the optional Ant tasks need.
 </p>
 
@@ -437,17 +421,15 @@
 To do so, change to the <code>ANT_HOME</code> directory and execute the command:
 </p>
 
-<blockquote>
-  <pre>ant -f fetch.xml -Ddest=<i>[option]</i></pre>
-</blockquote>
+<pre class="input">ant -f fetch.xml -Ddest=<em>[option]</em></pre>
 
 <p>
 where option is one of the following, as described above:
 </p>
 <ul>
-<li><code>system</code> - store in Ant's lib directory <i>(Recommended)</i></li>
-<li><code>user</code> - store in the user's home directory</li>
-<li><code>optional</code> - store in Ant's source code <code>lib/optional</code> directory, used when building Ant
+<li><code>system</code>&mdash;store in Ant's lib directory (<em>Recommended</em>)</li>
+<li><code>user</code>&mdash;store in the user's home directory</li>
+<li><code>optional</code>&mdash;store in Ant's source code <samp>lib/optional</samp> directory, used when building Ant
 source code</li>
 </ul>
 
@@ -456,18 +438,18 @@
 </p>
 
 <p>
-Note that not all dependencies are gathered using <code>fetch.xml</code>. Tasks that depend on commercial software, in
+Note that not all dependencies are gathered using <samp>fetch.xml</samp>. Tasks that depend on commercial software, in
 particular, will require you to have the commercial software installed in order to be used.
 </p>
 
 <p>
 The Apache Ant Project also provides additional tasks and types that are available as separately downloaded Ant
-Libraries. You can see the the list of available Antlibs at the <a href="http://ant.apache.org/antlibs/proper.html"
+Libraries. You can see the the list of available Antlibs at the <a href="https://ant.apache.org/antlibs/proper.html"
 target="_top">Ant Libraries</a> page.
 </p>
 
 <p>
-You can also find tasks and types provided by third-party projects at the <a href="http://ant.apache.org/external.html"
+You can also find tasks and types provided by third-party projects at the <a href="https://ant.apache.org/external.html"
 target="_top">External Tools and Tasks</a> page.
 </p>
 
@@ -476,7 +458,7 @@
 configuration dialog. Sometimes JAR files added to a project are automatically added to Ant's classpath.
 </p>
 
-<h3 id="classpath">The <code>CLASSPATH</code> environment variable</h3>
+<h3 id="classpath">The <code>CLASSPATH</code> Environment Variable</h3>
 <p>
 The <code>CLASSPATH</code> environment variable is a source of many Ant support queries. As the round trip time for
 diagnosis on the Ant user mailing list can be slow, and because filing bug reports complaining about 'ant.bat' not
@@ -493,14 +475,14 @@
 Ant's ability to quote the string. Again, this is not needed for the correct operation of the <code>CLASSPATH</code>
 environment variable, even if a DOS directory is to be added to the path.</li>
 
-<li>You can stop Ant using the <code>CLASSPATH</code> environment variable by setting the <code>-noclasspath</code>
+<li>You can stop Ant using the <code>CLASSPATH</code> environment variable by setting the <kbd>-noclasspath</kbd>
 option on the command line. This is an easy way to test for classpath-related problems.</li>
 </ol>
 
 <p>
-The usual symptom of <code>CLASSPATH</code> problems is that ant will not run with some error about not being able to
-find <code>org.apache.tools.ant.launch.Launcher</code>, or, if you have got the quotes/backslashes wrong, some very
-weird Java startup error. To see if this is the case, run <code>ant -noclasspath</code> or unset
+The usual symptom of <code>CLASSPATH</code> problems is that Ant will not run with some error about not being able to
+find <code class="code">org.apache.tools.ant.launch.Launcher</code>, or, if you have got the quotes/backslashes wrong,
+some very weird Java startup error. To see if this is the case, run <kbd>ant -noclasspath</kbd> or unset
 the <code>CLASSPATH</code> environment variable.
 </p>
 
@@ -529,16 +511,16 @@
 </p>
 
 <ul>
-<li><b>With Java 5 or above</b><br/>
+<li><strong>With Java 5 or above</strong><br/>
 <p>
 When you run Ant on Java 5 or above, you could try to use the automatic proxy setup mechanism
-with <code>-autoproxy</code>.
+with <kbd>-autoproxy</kbd>.
 </p>
 </li>
 
-<li><b>With explicit JVM properties.</b><br/>
+<li><strong>With explicit JVM properties.</strong><br/>
 <p>
-These are documented in <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/net/properties.html"
+These are documented in <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html"
 target="_top">Java's Networking Properties</a>, and control the proxy behaviour of the entire JVM. To set them in Ant,
 declare them in the <code>ANT_OPTS</code> environment variable. This is the best option for a non-mobile system. For a
 laptop, you have to change these settings as you roam. To set <code>ANT_OPTS</code>:
@@ -547,29 +529,23 @@
 <p>
 For csh/tcsh:
 </p>
-<pre>
-    setenv ANT_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
-</pre>
+<pre class="input">setenv ANT_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"</pre>
 <p>
 For bash:
 </p>
-<pre>
-    export ANT_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
-</pre>
+<pre class="input">export ANT_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"</pre>
 <p>
 For Windows, set the environment variable in the appropriate dialog box and open a new console or, by hand
 </p>
-<pre>
-    set ANT_OPTS = -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080
-</pre>
+<pre class="input">set ANT_OPTS = -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080</pre>
 </blockquote>
 </li>
 
-<li><b>In the build file itself</b><br/>
+<li><strong>In the build file itself</strong><br/>
 <p>
 If you are writing a build file that is always to be used behind the firewall,
 the <a href="Tasks/setproxy.html">setproxy</a> task lets you configure the proxy (which it does by setting the JVM
-properties). If you do this, we strongly recommend using ant properties to define the proxy host, port, etc, so that
+properties). If you do this, we strongly recommend using Ant properties to define the proxy host, port, etc, so that
 individuals can override the defaults.
 </p>
 </li>
@@ -578,11 +554,11 @@
 <p>
 The Ant team acknowledges that this is unsatisfactory. Until the JVM automatic proxy setup works properly everywhere,
 explicit JVM options via <code>ANT_ARGS</code> are probably the best solution. Setting properties on Ant's command line
-do not work, because those are <i>Ant properties</i> being set, not JVM options. This means the following does not set
+do not work, because those are <em>Ant properties</em> being set, not JVM options. This means the following does not set
 up the command line:
 </p>
 
-<pre>ant -Dhttp.proxyHost=proxy -Dhttp.proxyPort=81</pre>
+<pre class="input">ant -Dhttp.proxyHost=proxy -Dhttp.proxyPort=81</pre>
 
 <p>
 All it does is set up two Ant properties.
@@ -595,22 +571,22 @@
 </p>
 
 <h3 id="windows">Windows and OS/2</h3>
-<p>Assume Ant is installed in <code>c:\ant\</code>. The following sets up the
+<p>Assume Ant is installed in <samp>c:\ant\</samp>. The following sets up the
 environment:</p>
-<pre>set ANT_HOME=c:\ant
-set JAVA_HOME=c:\jdk1.7.0_51
+<pre class="input">set ANT_HOME=c:\ant
+set JAVA_HOME=c:\jdk11.0.8_10
 set PATH=%PATH%;%ANT_HOME%\bin</pre>
 
 <h3 id="bash">Linux/Unix (bash)</h3>
-<p>Assume Ant is installed in <code>/usr/local/ant</code>. The following sets up
+<p>Assume Ant is installed in <samp>/usr/local/ant</samp>. The following sets up
 the environment:</p>
-<pre>export ANT_HOME=/usr/local/ant
-export JAVA_HOME=/usr/local/jdk1.7.0_51
+<pre class="input">export ANT_HOME=/usr/local/ant
+export JAVA_HOME=/usr/local/jdk-11.0.8+10
 export PATH=${PATH}:${ANT_HOME}/bin</pre>
 
 <h3 id="tcshcsh">Linux/Unix (csh)</h3>
-<pre>setenv ANT_HOME /usr/local/ant
-setenv JAVA_HOME /usr/local/jdk/jdk1.7.0_51
+<pre class="input">setenv ANT_HOME /usr/local/ant
+setenv JAVA_HOME=/usr/local/jdk-11.0.8+10
 set path=( $path $ANT_HOME/bin )</pre>
 
 <p>
@@ -619,18 +595,18 @@
 <h3 id="jpackage">RPM version from jpackage.org</h3>
 <p>
 The <a href="http://www.jpackage.org" target="_top">JPackage project</a> distributes an RPM version of Ant. With this
-version, it is not necessary to set <code> JAVA_HOME</code> or <code>ANT_HOME</code> environment variables and the RPM
-installer will correctly place the Ant executable on your path.
+version, it is not necessary to set <code>JAVA_HOME</code> or <code>ANT_HOME</code> environment variables and the RPM
+installer will correctly place the <kbd>ant</kbd> executable on your path.
 </p>
 <p>
-<b>NOTE:</b> <i>Since Ant 1.7.0</i>, if the <code>ANT_HOME</code> environment variable is set, the JPackage
+<strong>Note</strong>: <em>Since Ant 1.7.0</em>, if the <code>ANT_HOME</code> environment variable is set, the JPackage
 distribution will be ignored.
 </p>
 <p>
 Optional JARs for the JPackage version are handled in two ways. The easiest, and best way is to get these external
 libraries from JPackage if JPackage has them available. (Note: for each such library, you will have to get both the
-external package itself (e.g. <code>oro-2.0.8-2jpp.noarch.rpm</code>) and the small library that links Ant and the
-external package (e.g. <code>ant-apache-oro-1.6.2-3jpp.noarch.rpm</code>).
+external package itself (e.g. <samp>oro-2.0.8-2jpp.noarch.rpm</samp>) and the small library that links Ant and the
+external package (e.g. <samp>ant-apache-oro-1.6.2-3jpp.noarch.rpm</samp>).
 </p>
 <p>
 However, JPackage does not package proprietary software, and since some of the optional packages depend on proprietary
@@ -640,32 +616,32 @@
 
 <ol>
 <li>Decide where you want to deploy the extra JARs. One option is in <code>$ANT_HOME/lib</code>, which, for JPackage is
-usually <code>/usr/share/ant/lib</code>. Another, less messy option is to create an <code>.ant/lib</code> subdirectory
+usually <samp>/usr/share/ant/lib</samp>. Another, less messy option is to create an <samp>.ant/lib</samp> subdirectory
 of your home directory and place your non-JPackage Ant JARs there, thereby avoiding mixing JPackage libraries with
 non-JPackage stuff in the same folder. More information on where Ant finds its libraries is
-available <a href="http://ant.apache.org/manual/running.html#libs">here</a></li>
-<li>Download a non-JPackage binary distribution from the regular <a href="http://ant.apache.org/bindownload.cgi"
+available <a href="running.html#libs">here</a></li>
+<li>Download a non-JPackage binary distribution from the regular <a href="https://ant.apache.org/bindownload.cgi"
 target="_top">Apache Ant site</a></li>
 <li>Unzip or untar the distribution into a temporary directory</li>
-<li>Copy the linking JAR, in this case <code>ant-jai.jar</code>, into the library directory you chose in step 1
+<li>Copy the linking JAR, in this case <samp>ant-jai.jar</samp>, into the library directory you chose in step 1
 above.</li>
 <li>Copy the proprietary JAR itself into the same directory.</li>
 </ol>
 
 Finally, if for some reason you are running on a system with both the JPackage and Apache versions of Ant available, if
 you should want to run the Apache version (which will have to be specified with an absolute file name, not found on the
-path), you should use Ant's <code>--noconfig</code> command-line switch to avoid JPackage's classpath mechanism.
+path), you should use Ant's <kbd>--noconfig</kbd> command-line switch to avoid JPackage's classpath mechanism.
 
 <h3 id="advanced">Advanced</h3>
 
 <p>There are many different ways to run Ant. What you need is at least the following:</p>
 
 <ul>
-<li>The classpath for Ant must contain <code>ant.jar</code> and any JARs/classes needed for your chosen JAXP-compliant
+<li>The classpath for Ant must contain <samp>ant.jar</samp> and any JARs/classes needed for your chosen JAXP-compliant
 XML parser.</li>
 <li>When you need JDK functionality (such as for the <a href="Tasks/javac.html">javac</a> task or
-the <a href="Tasks/rmic.html">rmic</a> task), then <code>tools.jar</code> must be added. The scripts supplied with Ant,
-in the <code>bin</code> directory, will add the required JDK classes automatically, if the <code>JAVA_HOME</code>
+the <a href="Tasks/rmic.html">rmic</a> task), then <samp>tools.jar</samp> must be added. The scripts supplied with Ant,
+in the <samp>bin</samp> directory, will add the required JDK classes automatically, if the <code>JAVA_HOME</code>
 environment variable is set.</li>
 <li>When you are executing platform-specific applications, such as the <a href="Tasks/exec.html">exec</a> task or
 the <a href="Tasks/cvs.html">cvs</a> task, the property <code>ant.home</code> must be set to the directory containing
@@ -693,13 +669,13 @@
 </p>
 
 <p>
-<b>Note</b>: The bootstrap process of Ant requires a greedy compiler like OpenJDK or Oracle's javac. It does not work
-with gcj or kjc.
+<strong>Note</strong>: The bootstrap process of Ant requires a greedy compiler like OpenJDK or
+Oracle's <kbd>javac</kbd>. It does not work with <kbd>gcj</kbd> or <kbd>kjc</kbd>.
 </p>
 
 <p>
 Make sure you have downloaded any auxiliary JARs required to build tasks you are interested in. These should be added to
-the <code>lib/optional</code> directory of the source tree. See <a href="#librarydependencies">Library Dependencies</a>
+the <samp>lib/optional</samp> directory of the source tree. See <a href="#librarydependencies">Library Dependencies</a>
 for a list of JAR requirements for various features. Note that this will make the auxiliary JAR available for the
 building of Ant only. For running Ant you will still need to make the JARs available as described
 under <a href="#installing">Installing Ant</a>.
@@ -707,22 +683,22 @@
 
 <p>
 You can also get most of the auxiliary JAR files (i.e. the JAR files that various optional Ant tasks depend on) by
-running Ant on the <code>fetch.xml</code> build file. See <a href="#optionalTasks">Optional Tasks</a> for instructions
+running Ant on the <samp>fetch.xml</samp> build file. See <a href="#optionalTasks">Optional Tasks</a> for instructions
 on how to do this.
 </p>
 
 <p>
-As of version 1.7.0 Ant has a hard dependency on JUnit. The <code>fetch.xml</code> build script will download JUnit
-automatically, but if you don't use this you must install it manually into <code>lib/optional</code> (download it
-from <a href="http://junit.org/" target="_top">JUnit.org</a>) if you are using a source distribution of Ant.
+<em>Since Ant 1.7.0</em>, Ant has a hard dependency on JUnit. The <samp>fetch.xml</samp> build script will download
+JUnit automatically, but if you don't use this you must install it manually into <samp>lib/optional</samp> (download it
+from <a href="https://junit.org/" target="_top">JUnit.org</a>) if you are using a source distribution of Ant.
 </p>
 
 <p>
 Your are now ready to build Ant:
 </p>
 <blockquote>
-  <p><code>build -Ddist.dir=&lt;<i>directory_to_contain_Ant_distribution</i>&gt; dist</code>&nbsp;&nbsp;&nbsp;&nbsp;(<i>Windows</i>)</p>
-  <p><code>sh build.sh -Ddist.dir=&lt;<i>directory_to_contain_Ant_distribution</i>&gt; dist</code>&nbsp;&nbsp;&nbsp;&nbsp;(<i>Unix</i>)</p>
+  <p><kbd>build -Ddist.dir=&lt;<i>directory-to-contain-Ant-distribution</i>&gt; dist</kbd>&nbsp;&nbsp;&nbsp;&nbsp;(<em>Windows</em>)</p>
+  <p><kbd>sh build.sh -Ddist.dir=&lt;<i>directory-to-contain-Ant-distribution</i>&gt; dist</kbd>&nbsp;&nbsp;&nbsp;&nbsp;(<em>Unix</em>)</p>
 </blockquote>
 
 <p>
@@ -736,49 +712,49 @@
 <li>If necessary it will bootstrap the Ant code. Bootstrapping involves the manual compilation of enough Ant code to be
 able to run Ant. The bootstrapped Ant is used for the remainder of the build steps.</li>
 <li>Invokes the bootstrapped Ant with the parameters passed to the build script. In this case, these parameters define
-an Ant property value and specify the &quot;dist&quot; target in Ant's own <code>build.xml</code> file.</li>
-<li>Create the <code>ant.jar</code> and <code>ant-launcher.jar</code> JAR files</li>
+an Ant property value and specify the <q>dist</q> target in Ant's own <samp>build.xml</samp> file.</li>
+<li>Create the <samp>ant.jar</samp> and <samp>ant-launcher.jar</samp> JAR files</li>
 <li>Create optional JARs for which the build had the relevant libraries. If a particular library is missing
-from <code>lib/optional</code>, then the matching ant-library JAR file will not be created. For
-example, <code>ant-junit.jar</code> is only built if there is a <code>junit.jar</code> in the <code>lib/optional</code>
+from <samp>lib/optional</samp>, then the matching ant-library JAR file will not be created. For
+example, <samp>ant-junit.jar</samp> is only built if there is a <samp>junit.jar</samp> in the <samp>lib/optional</samp>
 directory.</li>
 </ul>
 
 <p>
 On most occasions you will not need to explicitly bootstrap Ant since the build scripts do that for you. However, if the
 build file you are using makes use of features not yet compiled into the bootstrapped Ant, you will need to manually
-bootstrap. Run <code>bootstrap.bat</code> (Windows) or <code>bootstrap.sh</code> (UNIX) to build a new bootstrap version
+bootstrap. Run <kbd>bootstrap.bat</kbd> (Windows) or <kbd>bootstrap.sh</kbd> (UNIX) to build a new bootstrap version
 of Ant.
 </p>
 
 If you wish to install the build into the current <code>ANT_HOME</code>
 directory, you can use:
 <blockquote>
-  <p><code>build install</code>&nbsp;&nbsp;&nbsp;&nbsp;(<i>Windows</i>)</p>
-  <p><code>sh build.sh install</code>&nbsp;&nbsp;&nbsp;&nbsp;(<i>Unix</i>)</p>
+  <p><kbd>build install</kbd>&nbsp;&nbsp;&nbsp;&nbsp;(<em>Windows</em>)</p>
+  <p><kbd>sh build.sh install</kbd>&nbsp;&nbsp;&nbsp;&nbsp;(<em>Unix</em>)</p>
 </blockquote>
 
 You can avoid the lengthy Javadoc step, if desired, with:
 <blockquote>
-  <p><code>build install-lite</code>&nbsp;&nbsp;&nbsp;&nbsp;(<i>Windows</i>)</p>
-  <p><code>sh build.sh install-lite</code>&nbsp;&nbsp;&nbsp;&nbsp;(<i>Unix</i>)</p>
+  <p><kbd>build install-lite</kbd>&nbsp;&nbsp;&nbsp;&nbsp;(<em>Windows</em>)</p>
+  <p><kbd>sh build.sh install-lite</kbd>&nbsp;&nbsp;&nbsp;&nbsp;(<em>Unix</em>)</p>
 </blockquote>
-This will only install the <code>bin</code> and <code>lib</code> directories.
+This will only install the <samp>bin</samp> and <samp>lib</samp> directories.
 
 <p>
-Both the <code>install</code> and <code>install-lite</code> targets will overwrite the current Ant version
+Both the <var>install</var> and <var>install-lite</var> targets will overwrite the current Ant version
 in <code>ANT_HOME</code>.
 </p>
 
 <p>
-Ant's build script will try to set executable flags for its shell scripts on Unix-like systems. There are various
+Ant's build script will try to set executable flags for its shell scripts on Unix(-like) systems. There are various
 reasons why the <a href="Tasks/chmod.html">chmod</a> task might fail (like when you are running the build script as a
 different user than the one who installed Ant initially). In this case you can set the Ant
 property <code>chmod.fail</code> to false when starting the build like in
 </p>
-<blockquote>
-  <p><code>sh build.sh install -Dchmod.fail=false</code></p>
-</blockquote>
+
+<pre class="input">sh build.sh install -Dchmod.fail=false</pre>
+
 <p>
 and any error to change permission will not result in a build failure.
 </p>
@@ -790,33 +766,34 @@
 The following libraries are needed in Ant's classpath if you are using the indicated feature. Note that only one of the
 regexp libraries is needed for use with the mappers (and Java includes a regexp implementation which Ant will find
 automatically). You will also need to install the particular Ant optional JAR containing the task definitions to make
-these tasks available. Please refer to the <a href="#optionalTasks"> Installing Ant / Optional Tasks</a> section above.
+these tasks available. Please refer to the <a href="#optionalTasks">Installing Ant / Optional Tasks</a> section above.
 </p>
 
-<table border="1" cellpadding="2" cellspacing="0">
+<table>
   <tr>
-    <td><b>JAR Name</b></td>
-    <td><b>Needed For</b></td>
-    <td><b>Available At</b></td>
+    <th scope="col">JAR Name</th>
+    <th scope="col">Needed For</th>
+    <th scope="col">Available At</th>
   </tr>
   <tr>
     <td>jakarta-regexp-1.4.jar</td>
     <td><a href="Types/mapper.html#regexp-mapper">regexp</a> type with mappers (if you do not wish to use
-    java.util.regex)</td>
+      <code>java.util.regex</code>)</td>
     <td><a href="https://attic.apache.org/projects/jakarta-regexp.html"
-    target="_top">https://attic.apache.org/projects/jakarta-regexp.html</a></td>
+           target="_top">https://attic.apache.org/projects/jakarta-regexp.html</a></td>
   </tr>
   <tr>
     <td>jakarta-oro-2.0.8.jar</td>
     <td><a href="Types/mapper.html#regexp-mapper">regexp</a> type with mappers (if you do not wish to use
-    java.util.regex) or <a href="Tasks/ftp.html">ftp</a> task with <a href="#commons-net">commons-net</a> 1.4.1</td>
+      <code>java.util.regex</code>) or <a href="Tasks/ftp.html">ftp</a> task with <a href="#commons-net">commons-net</a> 1.4.1</td>
     <td><a href="https://attic.apache.org/projects/jakarta-oro.html"
-    target="_top">https://attic.apache.org/projects/jakarta-oro.html</a></td>
+           target="_top">https://attic.apache.org/projects/jakarta-oro.html</a></td>
   </tr>
   <tr>
     <td>junit.jar</td>
-    <td><a href="Tasks/junit.html">junit</a> task (may be in classpath passed to task rather than Ant's classpath)</td>
-    <td><a href="http://junit.org/" target="_top">http://junit.org/</a></td>
+    <td><a href="Tasks/junit.html">junit</a> task (may be in classpath passed to task rather than
+      Ant's classpath)</td>
+    <td><a href="https://junit.org/" target="_top">https://junit.org/</a></td>
   </tr>
   <tr>
     <td>xalan.jar</td>
@@ -826,7 +803,7 @@
   <tr>
     <td>antlr.jar</td>
     <td><a href="Tasks/antlr.html">antlr</a> task</td>
-    <td><a href="http://www.antlr.org/" target="_top">http://www.antlr.org/</a></td>
+    <td><a href="https://www.antlr.org/" target="_top">https://www.antlr.org/</a></td>
   </tr>
   <tr>
     <td>bsf.jar</td>
@@ -841,29 +818,41 @@
     <td>Groovy JARs</td>
     <td>Groovy Ant tasks with bindings or Groovy with <a href="Tasks/script.html">script</a>
     and <a href="Tasks/scriptdef.html">scriptdef</a> tasks</td>
-    <td>
-      <a href="http://groovy-lang.org/" target="_top">http://groovy-lang.org/</a><br/>
-      Use either groovy-ant for Groovy Ant tasks with bindings or groovy-bsf for Groovy with script and scriptdef tasks
-      (or groovy-all)
+    <td><a href="http://groovy-lang.org/" target="_top">http://groovy-lang.org/</a><br/> Use either groovy-ant for
+      Groovy Ant tasks with bindings or groovy-bsf for Groovy with script and scriptdef tasks (or groovy-all)
     </td>
   </tr>
   <tr>
     <td>netrexx.jar</td>
     <td><a href="Tasks/netrexxc.html">netrexxc</a> task, Rexx with <a href="Tasks/script.html">script</a> task</td>
     <td><a href="https://www.ibm.com/software/awdtools/netrexx/library.html"
-    target="_top">https://www.ibm.com/software/awdtools/netrexx/library.html</a></td>
+           target="_top">https://www.ibm.com/software/awdtools/netrexx/library.html</a></td>
   </tr>
   <tr>
-    <td>rhino.jar<br/>
-    (included in Java 7 runtime, replaced by Nashorn in Java&nbsp;8 and later)</td>
-    <td>JavaScript with <a href="Tasks/script.html">script</a> task<br/>
-    <strong>Note:</strong> Apache BSF 2.4.0 works only with Rhino 1.5R4 and later versions.</td>
+    <td>rhino.jar<br/>(included in Java 7 runtime, replaced by Nashorn
+      in Java&nbsp;8 and later, dropped with Java 15)</td>
+    <td>JavaScript with <a href="Tasks/script.html">script</a> task<br/><strong>Note</strong>: Apache BSF 2.4.0 works
+      only with Rhino 1.5R4 and later versions.</td>
     <td><a href="https://www.mozilla.org/rhino/" target="_top">https://www.mozilla.org/rhino/</a></td>
   </tr>
   <tr>
+    <td>graalvm js.jar and js-scriptengine.jar<br/></td>
+    <td>JavaScript with <a href="Tasks/script.html">script</a> task for Java 15 and later<br/>
+    </td>
+    <td>Java 15 has dropped Nashorn
+      and <a href="https://github.com/graalvm/graaljs">GraalVM JavaScript</a>
+      is meant to replace it - outside of the Java class
+      library.<br/>
+      <strong>Note</strong> GraalVM JavaScript is not a drop-in
+      replacement for Nashorn, see the script task documentation for
+      details. Also GraakVM JavaScript requires a couple of more
+      dependencies, in particular GraalVM regex, truffle, the GraalVM
+      SDK and ICU.</td>
+  </tr>
+  <tr>
     <td>jython.jar</td>
     <td>Python with <a href="Tasks/script.html">script</a> task</td>
-    <td><a href="http://www.jython.org/" target="_top">http://www.jython.org/</a></td>
+    <td><a href="https://www.jython.org/" target="_top">https://www.jython.org/</a></td>
   </tr>
   <tr>
     <td>jacl.jar and tcljava.jar</td>
@@ -877,19 +866,19 @@
   </tr>
   <tr>
     <td>BeanShell JAR(s)</td>
-    <td>BeanShell with <a href="Tasks/script.html">script</a> task.<br/>
-    <strong>Note</strong>: Ant requires BeanShell version 1.3 or later</td>
+    <td>BeanShell with <a href="Tasks/script.html">script</a> task.<br/><strong>Note</strong>: Ant requires BeanShell
+      version 1.3 or later</td>
     <td><a href="http://www.beanshell.org/" target="_top">http://www.beanshell.org/</a></td>
   </tr>
   <tr>
     <td>jruby.jar</td>
     <td>Ruby with <a href="Tasks/script.html">script</a> task</td>
-    <td><a href="http://jruby.org/" target="_top">http://jruby.org/</a></td>
+    <td><a href="https://jruby.org/" target="_top">https://jruby.org/</a></td>
   </tr>
   <tr>
     <td>judo.jar</td>
     <td>Judo language with <a href="Tasks/script.html">script</a> task</td>
-    <td><a href="http://www.judoscript.org/" target="_top">http://www.judoscript.org/</a></td>
+    <td>used to be at http://www.judoscript.org/ which is now not available anymore.</td>
   </tr>
   <tr>
     <td>commons-logging.jar</td>
@@ -904,90 +893,115 @@
   <tr id="commons-net">
     <td>commons-net.jar</td>
     <td><a href="Tasks/ftp.html">ftp</a>, <a href="Tasks/rexec.html">rexec</a>
-    and <a href="Tasks/telnet.html">telnet</a> tasks<br/>
-    A minimum version of commons-net of 1.4.0 is needed to compile Ant, earlier versions did not support the full range
-    of configuration options.<br/>
-    jakarta-oro 2.0.8 is required together with commons-net 1.4.x at run time.<br/>
-    <strong>Note</strong>: do not use commons-net 3.2 because
-    of <a href="https://issues.apache.org/jira/browse/NET-493">performance issues</a>
+      and <a href="Tasks/telnet.html">telnet</a> tasks<br/> A minimum version of commons-net of 1.4.0 is needed to
+      compile Ant, earlier versions did not support the full range of configuration options.<br/>jakarta-oro 2.0.8 is
+      required together with commons-net 1.4.x at run time.<br/><strong>Note</strong>: do not use commons-net 3.2
+      because of <a href="https://issues.apache.org/jira/browse/NET-493" target="_top">performance issues</a>
     </td>
     <td><a href="https://commons.apache.org/net/" target="_top">https://commons.apache.org/net/</a></td>
   </tr>
   <tr>
     <td>bcel.jar</td>
     <td><a href="Types/classfileset.html">classfileset</a> data type, JavaClassHelper used by the ClassConstants filter
-    reader and optionally used by <a href="Tasks/ejb.html#ejbjar">ejbjar</a> task for dependency determination</td>
+      reader and optionally used by <a href="Tasks/ejb.html#ejbjar">ejbjar</a> task for dependency determination</td>
     <td><a href="https://commons.apache.org/bcel/" target="_top">https://commons.apache.org/bcel/</a></td>
   </tr>
   <tr>
-    <td>javax.mail.jar</td>
-    <td><a href="Tasks/mail.html">mail</a> task and <i>deprecated</i> <a href="Tasks/mimemail.html">mimemail</a> task</td>
-    <td><a href="https://javaee.github.io/javamail/"
-        target="_top">https://javaee.github.io/javamail/</a></td>
+    <td>jakarta.mail.jar</td>
+    <td><a href="Tasks/mail.html">mail</a> task
+      and <em><u>deprecated</u></em> <a href="Tasks/mimemail.html">mimemail</a> task</td>
+    <td><a href="https://eclipse-ee4j.github.io/mail/"
+           target="_top">https://eclipse-ee4j.github.io/mail/</a></td>
   </tr>
   <tr>
     <td>activation.jar<br/>
-    (included in Java 6 to Java 10 but
-    the <code>java.activation</code> module is deprecated and marked
-    for removal in Java 9 and needs to be enabled explicitly on Java
-    10)</td>
+      <ul>
+        <li>Included in Java 6 to Java 10 but the <code>java.activation</code> module is deprecated and marked for removal in
+      Java 9 and needs to be enabled explicitly on Java 10.</li>
+       <li>Starting Java 11, the <code>java.activation</code> module has been <a href="https://openjdk.java.net/jeps/320">removed</a> and the jar has to be explicitly made available in the classpath.</li>
+      </ul>
+    </td>
     <td><a href="Tasks/mail.html">mail</a> task with MIME encoding,
-    and <i>deprecated</i> <a href="Tasks/mimemail.html">mimemail</a> task</td>
-    <td><a href="https://github.com/javaee/activation"
-        target="_top">https://github.com/javaee/activation</a></td>
+      and <em><u>deprecated</u></em> <a href="Tasks/mimemail.html">mimemail</a> task</td>
+    <td><a href="https://github.com/eclipse-ee4j/jaf">https://github.com/eclipse-ee4j/jaf</a></td>
   </tr>
   <tr>
     <td>jdepend.jar</td>
     <td><a href="Tasks/jdepend.html">jdepend</a> task</td>
-    <td><a href="https://github.com/clarkware/jdepend"
-        target="_top">https://github.com/clarkware/jdepend</a></td>
+    <td><a href="https://github.com/clarkware/jdepend" target="_top">https://github.com/clarkware/jdepend</a></td>
   </tr>
   <tr>
-    <td>resolver.jar <b>1.1 or later</b></td>
-    <td><a href="Types/xmlcatalog.html">xmlcatalog</a> datatype <i>only if support for external catalog files is
-    desired</i></td>
+    <td>resolver.jar <strong>1.1 or later</strong></td>
+    <td><a href="Types/xmlcatalog.html">xmlcatalog</a> datatype <em>only if support for external catalog files is
+      desired</em></td>
     <td><a href="https://xerces.apache.org/xml-commons/components/resolver/"
-    target="_top">https://xerces.apache.org/xml-commons/components/resolver/</a></td>
+           target="_top">https://xerces.apache.org/xml-commons/components/resolver/</a></td>
   </tr>
   <tr>
-    <td>jsch.jar <b>0.1.55 or later</b></td>
+    <td>jsch.jar <strong>0.1.55 or later</strong></td>
     <td><a href="Tasks/sshexec.html">sshexec</a> and <a href="Tasks/scp.html">scp</a> tasks</td>
     <td><a href="http://www.jcraft.com/jsch/" target="_top">http://www.jcraft.com/jsch/</a></td>
   </tr>
   <tr>
-    <td>JAI - Java Advanced Imaging</td>
+    <td>JAI&mdash;Java Advanced Imaging</td>
     <td><a href="Tasks/image.html">image</a> task</td>
     <td><a href="https://download.java.net/media/jai/builds/release/1_1_3/INSTALL.html"
-    target="_top">https://download.java.net/media/jai/builds/release/1_1_3/INSTALL.html</a></td>
+           target="_top">https://download.java.net/media/jai/builds/release/1_1_3/INSTALL.html</a></td>
+  </tr>
+  <tr>
+    <td>jai-imageio-core.jar</td>
+    <td><a href="Tasks/imageio.html">imageio</a> task for TIFF support on Java 8, as well as PCX, PNM, RAW support</td>
+    <td><a href="https://github.com/jai-imageio/jai-imageio-core/releases"
+           target="_top">https://github.com/jai-imageio/jai-imageio-core/releases</a></td>
+  </tr>
+  <tr>
+    <td>XZ&mdash;XZ for Java <strong>1.6 or later</strong></td>
+    <td><a href="Tasks/pack.html">xz</a> and <a href="Tasks/unpack.html">unxz</a>
+      tasks, <a href="Types/resources.html#xzresource">xzresource</a>, xz compression
+      in <a href="Tasks/tar.html">tar</a>/<a href="Tasks/unzip.html">untar</a> tasks</td>
+    <td><a href="https://www.tukaani.org/xz/java.html" target="_top">https://www.tukaani.org/xz/java.html</a></td>
+  </tr>
+  <tr>
+    <td>JUnit 5 Platform jars:
+      <ul>
+          <li>junit-platform-commons.jar</li>
+          <li>junit-platform-engine.jar</li>
+          <li>junit-platform-launcher.jar</li>
+      </ul>
+    </td>
+    <td><a href="Tasks/junitlauncher.html">junitlauncher</a> task. Additional libraries maybe needed depending
+      on the selected test engines, details of which are available in that task's documentation</td>
+    <td><a href="https://junit.org/junit5/" target="_top">https://junit.org/junit5/</a></td>
   </tr>
 </table>
 
-<li>Which optional tasks are available. If a task is not listed as being available, either it is not present, or
-libraries that it depends on are absent.</li>
+<h2 id="Troubleshooting">Troubleshooting</h2>
 
 <h3 id="diagnostics">Diagnostics</h3>
 
 <p>
-Ant has a built in diagnostics feature. If you run <code>ant -diagnostics</code> ant will look at its internal state and
-print it out. This code will check and print the following things.
+Ant has a built in diagnostics feature. If you run <kbd>ant -diagnostics</kbd>, Ant will look at its internal state
+and print it out. This code will check and print the following things.
 </p>
 
 <ul>
 
 <li>Where Ant is running from. Sometimes you can be surprised.</li>
 
-<li>The version of ant.jar and of the ant-*.jar containing the optional tasks - and whether they match</li>
+<li>The version of <samp>ant.jar</samp> and of the <samp>ant-*.jar</samp> containing the optional tasks&mdash;and
+whether they match</li>
 
 <li>Which JAR files are in <code>ANT_HOME/lib</code></li>
 
-<h2 id="Troubleshooting">Troubleshooting</h2>
+<li>Which optional tasks are available. If a task is not listed as being available, either it is not present, or
+libraries that it depends on are absent.</li>
 
 <li>XML Parser information</li>
 
 <li>JVM system properties</li>
 
-<li>The status of the temp directory. If this is not writable, or its clock is horribly wrong (possible if it is on a
-network drive), a lot of tasks will fail with obscure error messages.</li>
+<li>The status of the <samp>temp</samp> directory. If this is not writable, or its timestamp is horribly wrong (possible
+if it is on a network drive), a lot of tasks may fail with obscure error messages.</li>
 
 <li>The current time zone as Java sees it. If this is not what it should be for your location, then dependency logic may
 get confused.</li>
@@ -995,7 +1009,7 @@
 </ul>
 
 <p>
-Running <code>ant -diagnostics</code> is a good way to check that Ant is installed. It is also a first step towards
+Running <kbd>ant -diagnostics</kbd> is a good way to check that Ant is installed. It is also a first step towards
 self-diagnosis of any problem. Any configuration problem reported to the user mailing list will probably result ins
 someone asking you to run the command and show the results, so save time by using it yourself.
 </p>
@@ -1006,7 +1020,7 @@
 what the XML parser and classpath is, etc.
 </p>
 
-<h3 id="ant-user">user mailing list</h3>
+<h3 id="ant-user">User Mailing List</h3>
 
 <p>
 If you cannot get Ant installed or working, the Ant user mailing list is the best place to start with any
diff --git a/manual/installlist.html b/manual/installlist.html
index 6bbe3dd..f505608 100644
--- a/manual/installlist.html
+++ b/manual/installlist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -41,4 +41,3 @@
 </ul>
 </body>
 </html>
-
diff --git a/manual/intro.html b/manual/intro.html
index e5673ed..068a404 100644
--- a/manual/intro.html
+++ b/manual/intro.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,24 +15,23 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
-<title>Apache Ant User Manual - Introduction</title>
+<title>Apache Ant User Manual&mdash;Introduction</title>
 </head>
 
 <body>
-<h1><a name="introduction">Introduction</a></h1>
+<h1 id="introduction">Introduction</h1>
 <p>Apache Ant is a Java-based build tool. In theory, it is kind of like
-<i>make</i>, without <i>make</i>'s wrinkles.</p>
+<em>make</em>, without <em>make</em>'s wrinkles.</p>
 <h3>Why?</h3>
 <p>Why another build tool when there is already
-<i>make</i>,
-<i>gnumake</i>,
-<i>nmake</i>,
-<i>jam</i>,
+<em>make</em>,
+<em>gnumake</em>,
+<em>nmake</em>,
+<em>jam</em>,
 and
 others? Because all those tools have limitations that Ant's original author
 couldn't live with when developing software across multiple platforms.
@@ -54,16 +54,13 @@
 Task interface.</p>
 <p>Granted, this removes some of the expressive power that is inherent in being
 able to construct a shell command such as
-<nobr><code>`find . -name foo -exec rm {}`</code></nobr>, but it
-gives you the ability to be cross-platform--to work anywhere and
+<code>`find . -name foo -exec rm {}`</code>, but it
+gives you the ability to be cross-platform&mdash;to work anywhere and
 everywhere. And
 hey, if you really need to execute a shell command, Ant has an
 <code>&lt;exec&gt;</code> task that
 allows different commands to be executed based on the OS it is executing
 on.</p>
 
-
-
 </body>
 </html>
-
diff --git a/manual/javacprops.html b/manual/javacprops.html
index 6cab07c..d482ecd 100644
--- a/manual/javacprops.html
+++ b/manual/javacprops.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,40 +15,38 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Properties controlling javac</title>
 </head>
 
 <body>
 
-<p>The source and target attributes of <code>&lt;javac&gt;</code>
-don't have any default values for historical reasons.  Since the
-underlying javac compiler's default depends on the JDK you use, you
-may encounter build files that don't explicitly set those attributes
-and that will no longer compile using a newer JDK.  If you cannot
-change the build file, Apache Ant provides two properties that help you
-setting default values for these attributes.  If the attributes have
-been set explicitly, the properties listed here will be ignored.</p>
+<p>The <var>source</var> and <var>target</var> attributes
+of <code>&lt;javac&gt;</code> don't have any default values for
+historical reasons.  Since the underlying <kbd>javac</kbd>
+compiler defaults depends on the JDK you use, you may encounter
+build files that don't explicitly set those attributes and that will
+no longer compile using a newer JDK.  If you cannot change the build
+file, Apache Ant provides two properties that help you setting
+default values for these attributes.  If the attributes have been
+set explicitly, the properties listed here will be ignored.</p>
 
-<h2><a name="source">ant.build.javac.source</a></h2>
+<h2 id="source">ant.build.javac.source</h2>
 
 <p><em>Since Ant 1.7</em></p>
 
-<p>Provides a default value for <code>&lt;javac&gt;</code>'s and
-<code>&lt;javadoc&gt;</code>'s source attribute.</p>
+<p>Provides a default value for <code>&lt;javac&gt;</code>'s
+and <code>&lt;javadoc&gt;</code>'s <var>source</var> attribute.</p>
 
-<h2><a name="target">ant.build.javac.target</a></h2>
+<h2 id="target">ant.build.javac.target</h2>
 
 <p><em>Since Ant 1.7</em></p>
 
-<p>Provides a default value for <code>&lt;javac&gt;</code>'s target
-attribute.</p>
-
+<p>Provides a default value
+for <code>&lt;javac&gt;</code>'s <var>target</var> attribute.</p>
 
 </body>
 </html>
-
diff --git a/manual/listeners.html b/manual/listeners.html
index 7387288..4c1b878 100644
--- a/manual/listeners.html
+++ b/manual/listeners.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Listeners &amp; Loggers</title>
 </head>
@@ -25,12 +25,12 @@
 <body>
 <h1>Listeners &amp; Loggers</h1>
 
-<h2><a name="Overview">Overview</a></h2>
+<h2 id="Overview">Overview</h2>
 
-<p>Apache Ant has two related features to allow the build process to be monitored:
-listeners and loggers.</p>
+<p>Apache Ant has two related features to allow the build process to be monitored: listeners and
+loggers.</p>
 
-<h3><a name="Listeners">Listeners</a></h3>
+<h3 id="Listeners">Listeners</h3>
 
 <p>A listener is alerted of the following events:</p>
 
@@ -44,365 +44,326 @@
   <li>message logged</li>
 </ul>
 
-<p>
-  These are used internally for various recording and housekeeping operations,
-  however new listeners may registered on the command line through the <code>-listener</code>
-  argument.
-</p>
+<p>These are used internally for various recording and housekeeping operations, however new
+listeners may registered on the command line through the <kbd>-listener</kbd> argument.</p>
 
-<h3><a name="Loggers">Loggers</a></h3>
+<h3 id="Loggers">Loggers</h3>
 
 <p>Loggers extend the capabilities of listeners and add the following features:</p>
 
 <ul>
-  <li>Receives a handle to the standard output and error print streams and
-  therefore can log information to the console or the <code>-logfile</code> specified file.</li>
-  <li>Logging level (-quiet, -verbose, -debug) aware</li>
+  <li>Receives a handle to the standard output and error print streams and therefore can log
+    information to the console or the <kbd>-logfile</kbd> specified file.</li>
+  <li>Logging level (<kbd>-quiet</kbd>, <kbd>-verbose</kbd>, <kbd>-debug</kbd>) aware</li>
   <li>Emacs-mode aware</li>
 </ul>
 
-<h2><a name="builtin">Built-in Listeners/Loggers</a></h2>
+<h2 id="builtin">Built-in Listeners/Loggers</h2>
 
-<table border="1" cellspacing="1" width="100%" id="AutoNumber1">
+<table>
   <tr>
-    <td width="33%">Classname</td>
-    <td width="33%">Description</td>
-    <td width="34%">Type</td>
+    <th scope="col">Classname</th>
+    <th scope="col">Description</th>
+    <th scope="col">Type</th>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#DefaultLogger">org.apache.tools.ant.DefaultLogger</a></code></td>
-    <td width="33%">The logger used implicitly unless overridden with the
-    <code>-logger</code> command-line switch.</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#DefaultLogger">org.apache.tools.ant.DefaultLogger</a></code></td>
+    <td>The logger used implicitly unless overridden with the <kbd>-logger</kbd> command-line
+      switch.</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#NoBannerLogger">
-    org.apache.tools.ant.NoBannerLogger</a></code></td>
-    <td width="33%">This logger omits output of empty target output.</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#NoBannerLogger">org.apache.tools.ant.NoBannerLogger</a></code></td>
+    <td>This logger omits output of empty target output.</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#MailLogger">
-    org.apache.tools.ant.listener.MailLogger</a></code></td>
-    <td width="33%">Extends DefaultLogger such that output is still generated
-    the same, and when the build is finished an e-mail can be sent.</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#MailLogger">org.apache.tools.ant.listener.MailLogger</a></code></td>
+    <td>Extends DefaultLogger such that output is still generated the same, and when the build is
+      finished an e-mail can be sent.</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#AnsiColorLogger">
-    org.apache.tools.ant.listener.AnsiColorLogger</a></code></td>
-    <td width="33%">Colorifies the build output.</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#AnsiColorLogger">org.apache.tools.ant.listener.AnsiColorLogger</a></code></td>
+    <td>Colorifies the build output.</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#Log4jListener">
-    org.apache.tools.ant.listener.Log4jListener</a></code></td>
-    <td width="33%">
-        Passes events to Apache Log4j for highly customizable logging.<br>
-        <b>Deprecated:</b> Apache Log4j (1.x) is not developed any more. Last
-        release is 1.2.17 from 26-May-2012 and contains vulnerability issues.
-    </td>
-    <td width="34%">BuildListener</td>
+    <td><code><a href="#Log4jListener">org.apache.tools.ant.listener.Log4jListener</a></code></td>
+    <td>Passes events to Apache Log4j for highly customizable
+      logging.<br/><em><u>Deprecated</u></em>: Apache Log4j (1.x) is not developed any more. Last
+      release is 1.2.17 from 26 May 2012 and contains vulnerability issues.</td>
+    <td>BuildListener</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#XmlLogger">org.apache.tools.ant.XmlLogger</a></code></td>
-    <td width="33%">Writes the build information to an XML file.</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#XmlLogger">org.apache.tools.ant.XmlLogger</a></code></td>
+    <td>Writes the build information to an XML file.</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#TimestampedLogger">org.apache.tools.ant.TimestampedLogger</a></code></td>
-    <td width="33%">Prints the time that a build finished</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#TimestampedLogger">org.apache.tools.ant.TimestampedLogger</a></code></td>
+    <td>Prints the time that a build finished</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#BigProjectLogger">org.apache.tools.ant.listener.BigProjectLogger</a></code></td>
-    <td width="33%">Prints the project name every target</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#BigProjectLogger">org.apache.tools.ant.listener.BigProjectLogger</a></code></td>
+    <td>Prints the project name every target</td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#SimpleBigProjectLogger">org.apache.tools.ant.listener.SimpleBigProjectLogger</a></code></td>
-    <td width="33%">Prints the project name for subprojects only, otherwise like NoBannerLogger <em>Since Ant 1.8.1</em></td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#SimpleBigProjectLogger">org.apache.tools.ant.listener.SimpleBigProjectLogger</a></code></td>
+    <td>Prints the project name for subprojects only, otherwise like NoBannerLogger <em>Since Ant
+    1.8.1</em></td>
+    <td>BuildLogger</td>
   </tr>
   <tr>
-    <td width="33%"><code><a href="#ProfileLogger">org.apache.tools.ant.listener.ProfileLogger</a></code></td>
-    <td width="33%">The default logger, with start times, end times and
-    durations added for each task and target.</td>
-    <td width="34%">BuildLogger</td>
+    <td><code><a href="#ProfileLogger">org.apache.tools.ant.listener.ProfileLogger</a></code></td>
+    <td>The default logger, with start times, end times and durations added for each task and
+      target.</td>
+    <td>BuildLogger</td>
   </tr>
 </table>
 
-
-
-<h3><a name="DefaultLogger">DefaultLogger</a></h3>
+<h3 id="DefaultLogger">DefaultLogger</h3>
 <p>Simply run Ant normally, or:</p>
-<blockquote>
-<p><code>ant -logger org.apache.tools.ant.DefaultLogger</code></p>
-</blockquote>
 
+<pre class="input">ant -logger org.apache.tools.ant.DefaultLogger</pre>
 
-
-<h3><a name="NoBannerLogger">NoBannerLogger</a></h3>
+<h3 id="NoBannerLogger">NoBannerLogger</h3>
 <p>Removes output of empty target output.</p>
-<blockquote>
-<p><code>ant -logger org.apache.tools.ant.NoBannerLogger</code></p>
-</blockquote>
 
+<pre class="input">ant -logger org.apache.tools.ant.NoBannerLogger</pre>
 
-
-<h3><a name="MailLogger">MailLogger</a></h3>
-<p>The MailLogger captures all output logged through DefaultLogger (standard Ant
-output) and will send success and failure messages to unique e-mail lists, with
-control for turning off success or failure messages individually.</p>
+<h3 id="MailLogger">MailLogger</h3>
+<p>The MailLogger captures all output logged through DefaultLogger (standard Ant output) and will
+send success and failure messages to unique e-mail lists, with control for turning off success or
+failure messages individually.</p>
 
 <p>Properties controlling the operation of MailLogger:</p>
-<table border="1" cellspacing="1" width="100%" id="AutoNumber2">
+<table>
   <tr>
-    <th width="337">Property</th>
-    <th width="63%">Description</th>
-    <th width="63%">Required</th>
+    <th scope="col">Property</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td width="337">MailLogger.mailhost </td>
-    <td width="63%">Mail server to use</td>
-    <td width="63%">No, default &quot;localhost&quot;</td>
+    <td><code>MailLogger.mailhost</code></td>
+    <td>Mail server to use</td>
+    <td>No; default <q>localhost</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.port </td>
-    <td width="63%">SMTP Port for the Mail server</td>
-    <td width="63%">No, default &quot;25&quot;</td>
+    <td><code>MailLogger.port</code></td>
+    <td>SMTP Port for the Mail server</td>
+    <td>No; default <q>25</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.user</td>
-    <td width="63%">user name for SMTP auth</td>
-    <td width="63%">Yes, if SMTP auth is required on your SMTP server<br>
-    the email message will be then sent using Mime and requires JavaMail</td>
+    <td><code>MailLogger.user</code></td>
+    <td>user name for SMTP auth</td>
+    <td>Yes, if SMTP auth is required on your SMTP server<br/> the email message will be then sent
+      using MIME and requires JavaMail</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.password</td>
-    <td width="63%">password for SMTP auth</td>
-    <td width="63%">Yes, if SMTP auth is required on your SMTP server<br>
-    the email message will be then sent using Mime and requires JavaMail</td>
+    <td><code>MailLogger.password</code></td>
+    <td>password for SMTP auth</td>
+    <td>Yes, if SMTP auth is required on your SMTP server<br/> the email message will be then sent
+      using MIME and requires JavaMail</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.ssl</td>
-    <td width="63%">on or true if ssl is needed<br>
-    This feature requires JavaMail</td>
-    <td width="63%">
-    no</td>
+    <td><code>MailLogger.ssl</code></td>
+    <td>on or true if SSL is needed<br/>This feature requires JavaMail</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.from</td>
-    <td width="63%">Mail &quot;from&quot; address</td>
-    <td width="63%">Yes, if mail needs to be sent</td>
+    <td><code>MailLogger.from</code></td>
+    <td>Mail <q>from</q> address</td>
+    <td>Yes, if mail needs to be sent</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.replyto</td>
-    <td width="63%">Mail &quot;replyto&quot; address(es), comma-separated</td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.replyto</code></td>
+    <td>Mail <q>replyto</q> address(es), comma-separated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.failure.notify </td>
-    <td width="63%">Send build failure e-mails?</td>
-    <td width="63%">No, default &quot;true&quot;</td>
+    <td><code>MailLogger.failure.notify</code></td>
+    <td>Send build failure e-mails?</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.success.notify </td>
-    <td width="63%">Send build success e-mails?</td>
-    <td width="63%">No, default &quot;true&quot;</td>
+    <td><code>MailLogger.success.notify</code></td>
+    <td>Send build success e-mails?</td>
+    <td>No; default <q>true</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.failure.to </td>
-    <td width="63%">Address(es) to send failure messages to, comma-separated</td>
-    <td width="63%">Yes, if failure mail is to be sent</td>
+    <td><code>MailLogger.failure.to</code></td>
+    <td>Address(es) to send failure messages to, comma-separated</td>
+    <td>Yes, if failure mail is to be sent</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.success.to </td>
-    <td width="63%">Address(es) to send success messages to, comma-separated</td>
-    <td width="63%">Yes, if success mail is to be sent</td>
+    <td><code>MailLogger.success.to</code></td>
+    <td>Address(es) to send success messages to, comma-separated</td>
+    <td>Yes, if success mail is to be sent</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.failure.cc </td>
-    <td width="63%">Address(es) to send failure messages to carbon copy (cc), comma-separated</td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.failure.cc</code></td>
+    <td>Address(es) to send failure messages to carbon copy (cc), comma-separated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.success.cc </td>
-    <td width="63%">Address(es) to send success messages to carbon copy (cc), comma-separated</td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.success.cc</code></td>
+    <td>Address(es) to send success messages to carbon copy (cc), comma-separated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.failure.bcc </td>
-    <td width="63%">Address(es) to send failure messages to blind carbon copy (bcc), comma-separated</td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.failure.bcc</code></td>
+    <td>Address(es) to send failure messages to blind carbon copy (bcc), comma-separated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.success.bcc </td>
-    <td width="63%">Address(es) to send success messages to blind carbon copy (bcc), comma-separated</td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.success.bcc</code></td>
+    <td>Address(es) to send success messages to blind carbon copy (bcc), comma-separated</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.failure.subject </td>
-    <td width="63%">Subject of failed build</td>
-    <td width="63%">No, default &quot;Build Failure&quot;</td>
+    <td><code>MailLogger.failure.subject</code></td>
+    <td>Subject of failed build</td>
+    <td>No; default <q>Build Failure</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.success.subject </td>
-    <td width="63%">Subject of successful build</td>
-    <td width="63%">No, default &quot;Build Success&quot;</td>
+    <td><code>MailLogger.success.subject</code></td>
+    <td>Subject of successful build</td>
+    <td>No; default <q>Build Success</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.failure.body</td>
-    <td width="63%">Fixed body of the email for a failed
-      build.  <em>Since Ant 1.8.0</em></td>
-    <td width="63%">No, default is to send the full log output.</td>
+    <td><code>MailLogger.failure.body</code></td>
+    <td>Fixed body of the email for a failed build.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is to send the full log output</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.success.body</td>
-    <td width="63%">Fixed body of the email for a successful
-      build.  <em>Since Ant 1.8.0</em></td>
-    <td width="63%">No, default is to send the full log output.</td>
+    <td><code>MailLogger.success.body</code></td>
+    <td>Fixed body of the email for a successful build.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is to send the full log output</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.mimeType</td>
-    <td width="63%">MIME-Type of the message.  <em>Since Ant 1.8.0</em></td>
-    <td width="63%">No, default is text/plain</td>
+    <td><code>MailLogger.mimeType</code></td>
+    <td>MIME-Type of the message.  <em>Since Ant 1.8.0</em></td>
+    <td>No; default is <q>text/plain</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.charset</td>
-    <td width="63%">Character set of the message.  <em>Since Ant 1.8.0</em></td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.charset</code></td>
+    <td>Character set of the message.  <em>Since Ant 1.8.0</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td width="337">MailLogger.starttls.enable</td>
-    <td width="63%">on or true if STARTTLS should be supported
-    (requires JavaMail).  <em>Since Ant 1.8.0</em></td>
-    <td width="63%">No, default is false</td>
+    <td><code>MailLogger.starttls.enable</code></td>
+    <td>on or true if <code>STARTTLS</code> should be supported (requires JavaMail).  <em>Since Ant
+      1.8.0</em></td>
+    <td>No; default is <q>false</q></td>
   </tr>
   <tr>
-    <td width="337">MailLogger.properties.file </td>
-    <td width="63%">Filename of properties file that will override other values.</td>
-    <td width="63%">No</td>
+    <td><code>MailLogger.properties.file</code></td>
+    <td>Filename of properties file that will override other values.</td>
+    <td>No</td>
   </tr>
 </table>
 
-<blockquote>
-<p><code>ant -logger org.apache.tools.ant.listener.MailLogger</code></p>
-</blockquote>
+<pre class="input">ant -logger org.apache.tools.ant.listener.MailLogger</pre>
 
+<h3 id="AnsiColorLogger">AnsiColorLogger</h3>
 
-
-<h3><a name="AnsiColorLogger">AnsiColorLogger</a></h3>
-
-<p>The AnsiColorLogger adds color to the standard Ant output
-by prefixing and suffixing ANSI color code escape sequences to
-it.  It is just an extension of <a href="#DefaultLogger">DefaultLogger</a>
+<p>The AnsiColorLogger adds color to the standard Ant output by prefixing and suffixing ANSI color
+code escape sequences to it.  It is just an extension of <a href="#DefaultLogger">DefaultLogger</a>
 and hence provides all features that DefaultLogger does.</p>
-<p>AnsiColorLogger differentiates the output by assigning
-different colors depending upon the type of the message.</p>
-<p>If used with the -logfile option, the output file
-will contain all the necessary escape codes to
-display the text in colorized mode when displayed
-in the console using applications like cat, more, etc.</p>
-<p>This is designed to work on terminals that support ANSI
-color codes.  It works on XTerm, ETerm, Win9x Console
-(with ANSI.SYS loaded.), etc.</p>
-<p><Strong>NOTE:</Strong>
-It doesn't work on WinNT and successors, even when a COMMAND.COM console loaded with
-ANSI.SYS is used.</p>
-<p>If the user wishes to override the default colors
-with custom ones, a file containing zero or more of the
-custom color key-value pairs must be created.  The recognized keys
-and their default values are shown below:</p><code><pre>
+<p>AnsiColorLogger differentiates the output by assigning different colors depending upon the type
+of the message.</p>
+<p>If used with the <kbd>-logfile</kbd> option, the output file will contain all the necessary
+escape codes to display the text in colorized mode when displayed in the console using applications
+like <code>cat</code>, <code>more</code>, etc.</p>
+<p>This is designed to work on terminals that support ANSI color codes.  It works on XTerm, ETerm,
+Win9x Console (with <code>ANSI.SYS</code> loaded.), etc.</p>
+<p><strong>Note</strong>: It doesn't work on WinNT and successors, even when
+a <code>COMMAND.COM</code> console loaded with <code>ANSI.SYS</code> is used.</p>
+<p>If the user wishes to override the default colors with custom ones, a file containing zero or
+more of the custom color key-value pairs must be created.  The recognized keys and their default
+values are shown below:</p>
+<pre>
 AnsiColorLogger.ERROR_COLOR=2;31
 AnsiColorLogger.WARNING_COLOR=2;35
 AnsiColorLogger.INFO_COLOR=2;36
 AnsiColorLogger.VERBOSE_COLOR=2;32
-AnsiColorLogger.DEBUG_COLOR=2;34</pre></code>
-<p>Each key takes as value a color combination defined as
-<b>Attribute;Foreground;Background</b>.  In the above example, background
-value has not been used.</p>
+AnsiColorLogger.DEBUG_COLOR=2;34</pre>
+<p>Each key takes as value a color combination defined as <q>Attribute;Foreground;Background</q>.
+In the above example, background value has not been used.</p>
 <p>This file must be specified as the value of a system variable
-named ant.logger.defaults and passed as an argument using the -D
-option to the <b>java</b> command that invokes the Ant application.
-An easy way to achieve this is to add -Dant.logger.defaults=
-<i>/path/to/your/file</i> to the ANT_OPTS environment variable.
-Ant's launching script recognizes this flag and will pass it to
-the java command appropriately.</p>
-<p>Format:</p><pre>
+named <code>ant.logger.defaults</code> and passed as an argument using the <kbd>-D</kbd> option to
+the <kbd>java</kbd> command that invokes the Ant application. An easy way to achieve this is to
+add <kbd>-Dant.logger.defaults=</kbd><samp class="input">/path/to/your/file</samp> to
+the <code>ANT_OPTS</code> environment variable. Ant's launching script recognizes this flag and will
+pass it to the <kbd>java</kbd> command appropriately.</p>
+<p>Format:</p>
+<pre>
 AnsiColorLogger.*=Attribute;Foreground;Background
 
 Attribute is one of the following:
-0 -&gt; Reset All Attributes (return to normal mode)
-1 -&gt; Bright (Usually turns on BOLD)
-2 -&gt; Dim
-3 -&gt; Underline
-5 -&gt; link
-7 -&gt; Reverse
-8 -&gt; Hidden
+0 &rarr; Reset All Attributes (return to normal mode)
+1 &rarr; Bright (Usually turns on BOLD)
+2 &rarr; Dim
+3 &rarr; Underline
+5 &rarr; link
+7 &rarr; Reverse
+8 &rarr; Hidden
 
 Foreground is one of the following:
-30 -&gt; Black
-31 -&gt; Red
-32 -&gt; Green
-33 -&gt; Yellow
-34 -&gt; Blue
-35 -&gt; Magenta
-36 -&gt; Cyan
-37 -&gt; White
+30 &rarr; Black
+31 &rarr; Red
+32 &rarr; Green
+33 &rarr; Yellow
+34 &rarr; Blue
+35 &rarr; Magenta
+36 &rarr; Cyan
+37 &rarr; White
 
 Background is one of the following:
-40 -&gt; Black
-41 -&gt; Red
-42 -&gt; Green
-43 -&gt; Yellow
-44 -&gt; Blue
-45 -&gt; Magenta
-46 -&gt; Cyan
-47 -&gt; White</pre>
+40 &rarr; Black
+41 &rarr; Red
+42 &rarr; Green
+43 &rarr; Yellow
+44 &rarr; Blue
+45 &rarr; Magenta
+46 &rarr; Cyan
+47 &rarr; White</pre>
 
-<blockquote>
-<p><code>ant -logger org.apache.tools.ant.listener.AnsiColorLogger</code></p>
-</blockquote>
+<pre class="input">ant -logger org.apache.tools.ant.listener.AnsiColorLogger</pre>
 
-
-
-<h3><a name="Log4jListener">Log4jListener</a></h3>
-<p><b>Deprecated:</b> Apache Log4j (1) is not developed any more. Last
-release is 1.2.17 from 26-May-2012 and contains vulnerability issues.</p>
-<p>Passes build events to Log4j, using the full classname's of the generator of
-each build event as the category:</p>
+<h3 id="Log4jListener">Log4jListener</h3>
+<p><em><u>Deprecated</u></em>: Apache Log4j (1) is not developed any more. Last release is 1.2.17
+from 26 May 2012 and contains vulnerability issues.</p>
+<p>Passes build events to Log4j, using the full classname's of the generator of each build event as
+the category:</p>
 <ul>
-  <li>build started / build finished - org.apache.tools.ant.Project</li>
-  <li>target started / target finished - org.apache.tools.ant.Target</li>
-  <li>task started / task finished - the fully qualified classname of the task</li>
-  <li>message logged - the classname of one of the above, so if a task logs a
-  message, its classname is the category used, and so on.</li>
+  <li>build started / build finished&mdash;<code class="code">org.apache.tools.ant.Project</code></li>
+  <li>target started / target finished&mdash;<code class="code">org.apache.tools.ant.Target</code></li>
+  <li>task started / task finished&mdash;the fully qualified classname of the task</li>
+  <li>message logged&mdash;the classname of one of the above, so if a task logs a message, its
+    classname is the category used, and so on.</li>
 </ul>
-<p>All start events are logged as INFO.&nbsp; Finish events are either logged as
-INFO or ERROR depending on whether the build failed during that stage. Message
-events are logged according to their Ant logging level, mapping directly to a
-corresponding Log4j level.</p>
+<p>All start events are logged as INFO. Finish events are either logged as INFO or ERROR depending
+on whether the build failed during that stage. Message events are logged according to their Ant
+logging level, mapping directly to a corresponding Log4j level.</p>
 
-<blockquote>
-<p><code>ant -listener org.apache.tools.ant.listener.Log4jListener</code></p>
-</blockquote>
+<pre class="input">ant -listener org.apache.tools.ant.listener.Log4jListener</pre>
 
-<p>To use Log4j you will need the Log4j JAR file and a 'log4j.properties'
-configuration file.  Both should be placed somewhere in your Ant
-classpath. If the log4j.properties is in your project root folder you can
-add this with <i>-lib</i> option:</p>
+<p>To use Log4j you will need the Log4j JAR file and a <samp>log4j.properties</samp> configuration
+file.  Both should be placed somewhere in your Ant classpath. If the <samp>log4j.properties</samp>
+is in your project root folder you can add this with <kbd>-lib</kbd> option:</p>
 
-<blockquote>
-<pre><code>ant -listener org.apache.tools.ant.listener.Log4jListener -lib .</code></pre>
-</blockquote>
+<pre class="input">ant -listener org.apache.tools.ant.listener.Log4jListener -lib .</pre>
 
-<p>If, for example, you wanted to capture the same information output to the
-console by the DefaultLogger and send it to a file named 'build.log', you
-could use the following configuration:</p>
+<p>If, for example, you wanted to capture the same information output to the console by the
+DefaultLogger and send it to a file named <samp>build.log</samp>, you could use the following
+configuration:</p>
 
-<blockquote>
-<pre><code>log4j.rootLogger=ERROR, LogFile
+<pre>
+log4j.rootLogger=ERROR, LogFile
 log4j.logger.org.apache.tools.ant.Project=INFO
 log4j.logger.org.apache.tools.ant.Target=INFO
 log4j.logger.org.apache.tools.ant.taskdefs=INFO
@@ -411,28 +372,26 @@
 log4j.appender.LogFile=org.apache.log4j.FileAppender
 log4j.appender.LogFile.layout=org.apache.log4j.PatternLayout
 log4j.appender.LogFile.layout.ConversionPattern=[%6r] %8c{1} : %m%n
-log4j.appender.LogFile.file=build.log
-</code></pre>
-</blockquote>
+log4j.appender.LogFile.file=build.log</pre>
 
-<p>For more information about configuring Log4J see <a href="http://logging.apache.org/log4j/docs/documentation.html">its
-documentation page</a>.</p>
+<p>For more information about configuring Log4J see <a href="https://logging.apache.org/log4j/1.2/"
+target="_top">its documentation page</a>.</p>
 
 <h4>Using the Log4j 1.2 Bridge</h4>
-You could use the <a href="http://logging.apache.org/log4j/2.x/log4j-1.2-api/index.html">Log4j Bridge</a>
-if your application is written against the Log4j (1.x) API, but you want to use the Log4j 2.x runtime.
-For using the bridge with Ant you have to add
+<p>You could use the <a href="https://logging.apache.org/log4j/2.x/log4j-1.2-api/index.html"
+target="_top">Log4j Bridge</a> if your application is written against the Log4j (1.x) API, but you
+want to use the Log4j 2.x runtime.  For using the bridge with Ant you have to add</p>
 <ul>
-  <li>log4j-1.2-api-${log4j.version}.jar</li>
-  <li>log4j-api-${log4j.version}.jar</li>
-  <li>log4j-core-${log4j.version}.jar</li>
-  <li>log4j2.xml</li>
+  <li><samp>log4j-1.2-api-${log4j.version}.jar</samp></li>
+  <li><samp>log4j-api-${log4j.version}.jar</samp></li>
+  <li><samp>log4j-core-${log4j.version}.jar</samp></li>
+  <li><samp>log4j2.xml</samp></li>
 </ul>
-to your classpath (e.g. via the <code>-lib</code> option).
-(For using the bridge Ant 1.9.10/1.10.2 or higher is required.)
-Translating the 1.x properties file into the 2.x xml syntax would result in
-<blockquote>
-<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+<p>to your classpath, e.g. via the <kbd>-lib</kbd> option.  (For using the bridge, Ant
+1.9.10/1.10.2 or higher is required.)  Translating the 1.x properties file into the 2.x XML syntax
+would result in</p>
+<pre>
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
 &lt;Configuration status=&quot;WARN&quot;&gt;
   &lt;Appenders&gt;
     &lt;File name=&quot;file&quot; fileName=&quot;build.log&quot;&gt;
@@ -450,55 +409,34 @@
     &lt;Logger name=&quot;org.apache.tools.ant.taskdefs&quot; level=&quot;INFO&quot;/&gt;
     &lt;Logger name=&quot;org.apache.tools.ant.taskdefs.Echo&quot; level=&quot;WARN&quot;/&gt;
   &lt;/Loggers&gt;
-&lt;/Configuration&gt;
-</code></pre>
-</blockquote>
+&lt;/Configuration&gt;</pre>
 
+<h3 id="XmlLogger">XmlLogger</h3>
+<p>Writes all build information out to an XML file named <samp>log.xml</samp>, or the value of
+the <code>XmlLogger.file</code> property if present, when used as a listener. When used as a logger,
+it writes all output to either the console or to the value of <kbd>-logfile</kbd>. Whether used as
+a listener or logger, the output is not generated until the build is complete, as it buffers the
+information in order to provide timing information for task, targets, and the project.</p>
+<p>By default the XML file creates a reference to an XSLT file <samp>log.xsl</samp> in the current
+directory; look in <samp>ANT_HOME/etc</samp> for one of these. You can set the
+property <code>ant.XmlLogger.stylesheet.uri</code> to provide a URI to a style sheet. This can be a
+relative or absolute file path, or an HTTP URL. If you set the property to the empty
+string, <q></q>, no XSLT transform is declared at all.</p>
 
+<pre class="input">ant -listener org.apache.tools.ant.XmlLogger
+ant -logger org.apache.tools.ant.XmlLogger -verbose -logfile build_log.xml</pre>
 
-<h3><a name="XmlLogger">XmlLogger</a></h3>
-<p>Writes all build information out to an XML file named log.xml, or the value
-of the <code>XmlLogger.file</code> property if present, when used as a
-listener. When used as a logger, it writes all output to either the
-console or to the value of <code>-logfile</code>. Whether used as a listener
-or logger, the output is not generated until the build is complete, as it
-buffers the information in order to provide timing information for task,
-targets, and the project.</p>
-<p>By default the XML file creates a reference to an XSLT file "log.xsl" in the current directory;
-look in ANT_HOME/etc for one of these. You can set the property
-<code>ant.XmlLogger.stylesheet.uri</code> to provide a uri to a style sheet.
-this can be a relative or absolute file path, or an http URL.
-If you set the property to the empty string, "", no XSLT transform
-is declared at all.</p>
-
-<blockquote>
-<p><code>ant -listener org.apache.tools.ant.XmlLogger</code><br>
-<code>ant -logger org.apache.tools.ant.XmlLogger -verbose -logfile build_log.xml</code></p>
-</blockquote>
-
-
-
-<h3><a name="TimestampedLogger">TimestampedLogger</a></h3>
-<p>
-  Acts like the default logger, except that the final success/failure message also includes
-  the time that the build completed. For example:
-</p>
-<pre>
-  BUILD SUCCESSFUL - at 16/08/05 16:24
-</pre>
+<h3 id="TimestampedLogger">TimestampedLogger</h3>
+<p>Acts like the default logger, except that the final success/failure message also includes the
+time that the build completed. For example:</p>
+<pre class="output">BUILD SUCCESSFUL - at 16/08/05 16:24</pre>
 <p>To use this listener, use the command:</p>
 
-<blockquote>
-<code>ant  -logger org.apache.tools.ant.listener.TimestampedLogger</code>
-</blockquote>
+<pre class="input">ant -logger org.apache.tools.ant.listener.TimestampedLogger</pre>
 
-
-
-<h3><a name="BigProjectLogger">BigProjectLogger</a></h3>
-<p>
-  This logger is designed to make examining the logs of a big build easier,
-  especially those run under continuous integration tools. It
-</p>
+<h3 id="BigProjectLogger">BigProjectLogger</h3>
+<p>This logger is designed to make examining the logs of a big build easier, especially those run
+under continuous integration tools. It</p>
 <ol>
   <li>When entering a child project, prints its name and directory</li>
   <li>When exiting a child project, prints its name</li>
@@ -506,14 +444,10 @@
   <li>Omits logging the names of all targets that have no direct task output</li>
   <li>Includes the build finished timestamp of the TimeStamp logger</li>
 </ol>
-<p>
-  This is useful when using &lt;subant&gt; to build a large project
-  from many smaller projects -the output shows which particular
-  project is building. Here is an example in which "clean" is being called
-  on all a number of child projects, only some of which perform work:
-</p>
-<pre>
-
+<p>This is useful when using <code>&lt;subant&gt;</code> to build a large project from many smaller
+projects&mdash;the output shows which particular project is building. Here is an example in which
+"clean" is being called on all a number of child projects, only some of which perform work:</p>
+<pre class="output">
 ======================================================================
 Entering project "xunit"
 In /home/ant/components/xunit
@@ -534,25 +468,19 @@
 
 ======================================================================
 Exiting project "junit"
-======================================================================
-</pre>
+======================================================================</pre>
 
-<p>
-  The entry and exit messages are very verbose in this example, but in
-  a big project compiling or testing many child components, the messages
-  are reduced to becoming clear delimiters of where different projects
-  are in charge -or more importantly, which project is failing.
-</p>
+<p>The entry and exit messages are very verbose in this example, but in a big project compiling or
+testing many child components, the messages are reduced to becoming clear delimiters of where
+different projects are in charge&mdash;or, more importantly, which project is failing.</p>
 <p>To use this listener, use the command:</p>
-<blockquote>
-<code>ant  -logger org.apache.tools.ant.listener.BigProjectLogger</code>
-</blockquote>
+<pre class="input">ant -logger org.apache.tools.ant.listener.BigProjectLogger</pre>
 
-<h3><a name="SimpleBigProjectLogger">SimpleBigProjectLogger</a></h3>
-<p>Like <code>BigProjectLogger</code>, project-qualified target names are printed,
-useful for big builds with subprojects.
-Otherwise it is as quiet as <code>NoBannerLogger</code>:</p>
-<pre>
+<h3 id="SimpleBigProjectLogger">SimpleBigProjectLogger</h3>
+<p><em>Since Ant 1.8.1</em></p>
+<p>Like <code>BigProjectLogger</code>, project-qualified target names are printed, useful for big
+builds with subprojects. Otherwise it is as quiet as <code>NoBannerLogger</code>:</p>
+<pre class="output">
 Buildfile: /sources/myapp/build.xml
 
 myapp-lib.compile:
@@ -570,20 +498,16 @@
 Building jar: /sources/myapp/build/myapp.jar
 
 BUILD SUCCESSFUL
-Total time: 1 second
-</pre>
-<p><b>since Ant 1.8.1</b></p>
+Total time: 1 second</pre>
 <p>To use this listener, use the command:</p>
-<blockquote>
-<code>ant -logger org.apache.tools.ant.listener.SimpleBigProjectLogger</code>
-</blockquote>
+<pre class="input">ant -logger org.apache.tools.ant.listener.SimpleBigProjectLogger</pre>
 
-<h3><a name="ProfileLogger">ProfileLogger</a></h3>
-<p>This logger stores the time needed for executing a task, target and the whole build and prints
-these information. The output contains a timestamp when entering the build, target or task and a timestamp and the needed time when exiting.
-</p>
+<h3 id="ProfileLogger">ProfileLogger</h3>
 <!-- This is the 'since' as described in the Loggers JavaDoc -->
-<p><b>since Ant 1.8.0</b></p>
+<p><em>Since Ant 1.8.0</em></p>
+<p>This logger stores the time needed for executing a task, target and the whole build and prints
+these information. The output contains a timestamp when entering the build, target or task and a
+timestamp and the needed time when exiting.</p>
 <h4>Example</h4>
 Having that buildfile
 <pre>
@@ -597,10 +521,10 @@
     &lt;target name=&quot;anotherTarget&quot; depends=&quot;aTarget&quot;&gt;
         &lt;echo&gt;another-echo-task&lt;/echo&gt;
     &lt;/target&gt;
-&lt;/project&gt;
-</pre>
-and executing with <tt>ant -logger org.apache.tools.ant.listener.ProfileLogger anotherTarget</tt> gives that output (with other timestamps and duration of course ;) :
-<pre>
+&lt;/project&gt;</pre>
+<p>and executing with <kbd>ant -logger org.apache.tools.ant.listener.ProfileLogger
+anotherTarget</kbd> gives that output (with other timestamps and duration of course ;-):</p>
+<pre class="output">
 Buildfile: ...\build.xml
 
 Target aTarget: started Thu Jan 22 09:01:00 CET 2009
@@ -627,36 +551,34 @@
 Target anotherTarget: finished Thu Jan 22 09:01:01 CET 2009 (0ms)
 
 BUILD SUCCESSFUL
-Total time: 2 seconds
-</pre>
+Total time: 2 seconds</pre>
 
+<h2 id="dev">Writing your own</h2>
 
-
-<h2><a name="dev">Writing your own</a></h2>
-
-<p>See the <a href="develop.html#buildevents">Build Events</a> section for
-developers.</p>
+<p>See the <a href="develop.html#buildevents">Build Events</a> section for developers.</p>
 
 <p>Notes:</p>
 
 <ul>
   <li>
-    A listener or logger should not write to standard output or error in the <code>messageLogged()</code> method;
-    Ant captures these internally and it will trigger an infinite loop.
+    A listener or logger should not write to standard output or error in
+    the <code class="code">messageLogged()</code> method; Ant captures these internally and it will
+    trigger an infinite loop.
   </li>
   <li>
-    Logging is synchronous; all listeners and loggers are called one after the other, with the build blocking until
-    the output is processed. Slow logging means a slow build.
+    Logging is synchronous; all listeners and loggers are called one after the other, with the build
+    blocking until the output is processed. Slow logging means a slow build.
   </li>
-  <li>When a build is started, and <code>BuildListener.buildStarted(BuildEvent event)</code> is called,
-    the project is not fully functional. The build has started, yes, and the <code>event.getProject()</code> method call
-    returns the Project instance, but that project is initialized with JVM and ant properties, nor has it
-    parsed the build file yet. You cannot call <code>Project.getProperty()</code> for property lookup, or
-    <code>Project.getName()</code> to get the project name (it will return null).
+  <li>When a build is started, and <code class="code">BuildListener.buildStarted(BuildEvent
+    event)</code> is called, the project is not fully functional. The build has started, yes, and
+    the <code class="code">event.getProject()</code> method call returns the Project instance, but
+    that project is initialized with JVM and Ant properties, nor has it parsed the build file
+    yet. You cannot call <code class="code">Project.getProperty()</code> for property lookup, or
+    <code class="code">Project.getName()</code> to get the project name (it will return null).
   </li>
   <li>
-    Classes that implement <code>org.apache.tools.ant.SubBuildListener</code> receive notifications when child projects
-    start and stop.
+    Classes that implement <code class="code">org.apache.tools.ant.SubBuildListener</code> receive
+    notifications when child projects start and stop.
   </li>
 </ul>
 
diff --git a/manual/platform.html b/manual/platform.html
index 8b38731..cfa42b1 100644
--- a/manual/platform.html
+++ b/manual/platform.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,115 +15,99 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
-
+<html lang="en">
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Platform Issues</title>
 </head>
+<body>
 
 <h1>Platform Issues</h1>
 
 <h2>Java versions</h2>
-<h3>Java 1.5</h3>
-
-You may need a bigger stack than default, especially if you are using the built in
-XSLT engine. We recommend you use Apache Xalan; indeed, some tasks (JUnit report in XML,
-for example) may not work against the shipping XSL engine.
+<h3>Java 5</h3>
+<p>
+You may need a bigger stack than default, especially if you are using the built in XSLT engine. We
+recommend you use Apache Xalan; indeed, some tasks (JUnit report in XML, for example) may not work
+against the shipping XSL engine.
+</p>
 
 <h2>Unix and Linux</h2>
-
 <ul>
-<li> You should use a GNU version of <tt>tar</tt> to untar the Apache 
-Ant source tree, if you have downloaded this as a tar file. If you get
-weird errors about missing files, this is the problem. 
-</li>
-<li> Ant does not preserve file permissions when a file is copied, moved or 
-archived, because Java does not let it read or write the permissions.
- Use <tt>&lt;chmod&gt;</tt> to set permissions, and when creating a 
-tar archive, use the <tt>mode</tt> attribute of <tt>&lt;tarfileset&gt;</tt>
-to set the permissions in the tar file, or <code>&lt;apply&gt;</code> the real tar program.
-</li>
-<li> Ant is not symbolic link aware in moves, deletes and when recursing down a tree
-of directories to build up a list of files. Unexpected things can happen.
-</li>
-<li> Linux on IA-64: apparently you need a larger heap than the default
-one (64M) to compile big projects. If you get out of heap
-errors, either increase the heap or use a forking javac. Better yet,
-use jikes for extra compilation speed.   
-</li>
-
+<li>You should use a GNU version of <kbd>tar</kbd> to untar the Apache Ant source tree, if you have
+downloaded this as a tar file. If you get weird errors about missing files, this is the
+problem.</li>
+<li>Ant does not preserve file permissions when a file is copied, moved or archived, because Java
+does not let it read or write the permissions.  Use <code>&lt;chmod&gt;</code> to set permissions,
+and when creating a tar archive, use the <var>mode</var> attribute
+of <code>&lt;tarfileset&gt;</code> to set the permissions in the tar file,
+or <code>&lt;apply&gt;</code> the real <kbd>tar</kbd> program.</li>
+<li>Ant is not symbolic link aware in moves, deletes and when recursing down a tree of directories
+to build up a list of files. Unexpected things can happen.</li>
+<li>Linux on IA-64: apparently you need a larger heap than the default one (64M) to compile big
+projects. If you get out of heap errors, either increase the heap or use a
+forking <code>&lt;javac&gt;</code>. Better yet, use <kbd>jikes</kbd> for extra compilation
+speed.</li>
 </ul>
 
-
 <h2>Microsoft Windows</h2>
 <p>
-Windows 9x (win95, win98, win98SE and winME) are not supported in Ant1.7,
+Windows 9x (win95, win98, win98SE and winME) are not supported <em>since Ant 1.7</em>.
+</p>
+<p>
+The Ant team has retired support for these products because they are outdated and can expose
+customers to security risks. We recommend that customers who are still running Windows 98 or Windows
+ME upgrade to a newer, more secure operating system, as soon as possible.
+</p>
+<p>
+Customers who upgrade to Linux report improved security, richer functionality, and increased
+productivity.
 </p>
 
+<h2>Microsoft Windows 2K, XP and Server 2K03</h2>
 <p>
-The Ant team has retired support for these products because they are outdated and
-can expose customers to security risks. We recommend that customers who are
-still running Windows 98 or Windows Me upgrade to a newer, more secure 
-operating system, as soon as possible.
+Windows 9x (win95, win98, win98SE and winME) has a batch file system which does not work fully with
+long file names, so we recommend that Ant and JDK are installed into directories without spaces, and
+with 8.3 filenames.  The Perl and Python launcher scripts do not suffer from this limitation.
 </p>
 <p>
-Customers who upgrade to Linux report improved security, richer
-functionality, and increased productivity. 
-</p>
-<h2>Microsoft Windows 2K, XP and Server 2K03 </h2>
-
-<p>
-Windows 9x (win95, win98, win98SE and winME) has a batch file system which
-does not work fully with long file names, so we recommend that ant and the JDK
-are installed into directories without spaces, and with 8.3 filenames. 
-The Perl and Python launcher scripts do not suffer from this limitation.
+All versions of Windows are usually case insensitive, although mounted file systems (Unix drives,
+ClearCase views) can be case sensitive underneath, confusing patternsets.
 </p>
 <p>
-All versions of windows are usually case insensitive, although mounted 
-file systems (Unix drives, Clearcase views) can be case sensitive underneath,
-confusing patternsets.
+Ant can often not delete a directory which is open in an Explorer window.  There is nothing we can
+do about this short of spawning a program to kill the shell before deleting directories.  Nor can
+files that are in use be overwritten.
 </p>
 <p>
-Ant can often not delete a directory which is open in an Explorer window. 
-There is nothing we can do about this short of spawning a program to kill
-the shell before deleting directories.
-Nor can files that are in use be overwritten.
-</p>
-<p>
-    Finally, if any Ant task fails with an IOError=2, it means that whatever
-    native program Ant is trying to run, it is not on the path.
+Finally, if any Ant task fails with an <code>error=2</code>, it means that whatever native program
+Ant is trying to run, it is not on the <code>Path</code>.
 </p>
 
 <h2>Microsoft Windows Vista</h2>
 <p>
-    There are reports of problems with Windows Vista security bringing up
-    dialog boxes asking if the user wants to run an untrusted executable
-    during an ant run, such as when the &lt;signjar&gt task runs the jarsigner.exe
-    program. This is beyond Ant's control, and stems from the OS trying to provide
-    some illusion of security by being reluctant to run unsigned native executables.
-    The latest Java versions appear to resolve this problem by having signed
-    binaries. 
+There are reports of problems with Windows Vista security bringing up dialog boxes asking if the
+user wants to run an untrusted executable during an Ant run, such as when
+the <code>&lt;signjar&gt;</code> task runs the <kbd>jarsigner.exe</kbd> program. This is beyond
+Ant's control, and stems from the OS trying to provide some illusion of security by being reluctant
+to run unsigned native executables.  The latest Java versions appear to resolve this problem by
+having signed binaries.
 </p>
 
-
 <h2>Cygwin</h2>
-
-Cygwin is not an operating system; rather it is an application suite 
-running under Windows and providing some UNIX like functionality. Sun has 
-not created any specific Java Development Kit or Java Runtime Environment for 
-cygwin. See this link : 
-<a href="http://www.inonit.com/cygwin/faq/">http://www.inonit.com/cygwin/faq/</a> . 
-Only Windows path 
-names are supported by JDK and JRE tools under Windows or cygwin. Relative path 
-names such as "src/org/apache/tools" are supported, but Java tools do not 
-understand /cygdrive/c to mean c:\.
 <p>
-The utility cygpath (used industrially in the ant script to support cygwin) can 
-convert cygwin path names to Windows.
-You can use the <code>&lt;exec&gt;</code> task in ant to convert cygwin paths to Windows path, for 
-instance like that :
+Cygwin is not an operating system; rather it is an application suite running under Windows and
+providing some UNIX like functionality. Sun has not created any specific Java Development Kit or
+Java Runtime Environment for cygwin. See this link: <a href="http://www.inonit.com/cygwin/faq/"
+target="_top">http://www.inonit.com/cygwin/faq/</a>.  Only Windows path names are supported by JDK
+and JRE tools under Windows or cygwin. Relative path names such as <samp>src/org/apache/tools</samp>
+are supported, but Java tools do not understand <samp>/cygdrive/c</samp> to mean <samp>c:\</samp>.
+</p>
+<p>
+The utility <kbd>cygpath</kbd> (used industrially in the <kbd>ant</kbd> script to support
+cygwin) can convert cygwin path names to Windows.  You can use the <code>&lt;exec&gt;</code> task in
+Ant to convert cygwin paths to Windows path, for instance like that:
+</p>
 <pre>
 &lt;property name=&quot;some.cygwin.path&quot; value=&quot;/cygdrive/h/somepath&quot;/&gt;
 &lt;exec executable=&quot;cygpath&quot; outputproperty=&quot;windows.pathname&quot;&gt;
@@ -131,48 +116,24 @@
 &lt;/exec&gt;
 &lt;echo message=&quot;${windows.pathname}&quot;/&gt;
 </pre>
+<p>
+We get lots of support calls from Cygwin users. Either it is incredibly popular, or it is
+trouble. If you do use it, remember that Java is a Windows application, so Ant is running in a
+Windows process, not a Cygwin one. This will save us having to mark your bug reports as invalid.
+</p>
 
-We get lots of support calls from Cygwin users. Either it is incredibly
-popular, or it is trouble. If you do use it, remember that Java is a
-Windows application, so Ant is running in a Windows process, not a
-Cygwin one. This will save us having to mark your bug reports as invalid. 
-
-<h2>Apple MacOS X</h2>
-
-MacOS X is the first of the Apple platforms that Ant supports completely;
-it is treated like any other Unix. 
-
-<h2>Novell Netware</h2>
-
-<p>To give the same level of sophisticated control as Ant's startup scripts on other platforms, it was decided to make the main ant startup on NetWare be via a Perl Script, "runant.pl".  This is found in the bin directory (for instance - bootstrap\bin or dist\bin).</p>
-
-<p>One important item of note is that you need to set up the following to run ant:</p>
-<ul><li><code>CLASSPATH</code> - put ant.jar and any other needed jars on the system classpath.</li>
-   <li><code>ANT_OPTS</code> - On NetWare, <code>ANT_OPTS</code> needs to include a parameter of the form, <nobr>"-envCWD=<code>ANT_HOME</code>"</nobr>, with <code>ANT_HOME</code> being the fully expanded location of Ant, <b>not</b> an environment variable.  This is due to the fact that the NetWare System Console has no notion of a current working directory.</li>
-</ul>
-<p>It is suggested that you create up an ant.ncf that sets up these parameters, and calls <code>perl ANT_HOME/dist/bin/runant.pl</code></p>
-<p>The following is an example of such an NCF file(assuming ant is installed in <nobr>'sys:/apache-ant/'):</nobr></p>
-<code>
-   &nbsp;&nbsp;&nbsp;envset CLASSPATH=SYS:/apache-ant/bootstrap/lib/ant.jar<br>
-   &nbsp;&nbsp;&nbsp;envset CLASSPATH=$CLASSPATH;SYS:/apache-ant/lib/optional/junit.jar <br>
-   &nbsp;&nbsp;&nbsp;envset CLASSPATH=$CLASSPATH;SYS:/apache-ant/bootstrap/lib/optional.jar <br>
-<br>
-   &nbsp;&nbsp;&nbsp;setenv ANT_OPTS=-envCWD=sys:/apache-ant <br>
-   &nbsp;&nbsp;&nbsp;envset ANT_OPTS=-envCWD=sys:/apache-ant <br>
-   &nbsp;&nbsp;&nbsp;setenv ANT_HOME=sys:/apache-ant/dist/lib <br>
-   &nbsp;&nbsp;&nbsp;envset ANT_HOME=sys:/apache-ant/dist/lib <br>
-<br>
-   &nbsp;&nbsp;&nbsp;perl sys:/apache-ant/dist/bin/runant.pl <br>
-</code>
-
-<p>Ant works on JVM version 1.3 or higher.  You may have some luck running it on JVM 1.2, but serious problems have been found running Ant on JVM 1.1.7B.  These problems are caused by JVM bugs that will not be fixed.</p>
-<p>JVM 1.3 is supported on Novell NetWare versions 5.1 and higher.</p>
-
+<h2>Apple MacOS X/macOS</h2>
+<p>
+MacOS X a.k.a. macOS is the first of the Apple platforms that Ant supports completely; it is treated
+like any other Unix.
+</p>
 
 <h2>Other platforms</h2>
-Support for other platforms is not guaranteed to be complete, as certain 
-techniques to hide platform details from build files need to be written and
-tested on every particular platform. Contributions in this area are welcome.
+<p>
+Support for other platforms is not guaranteed to be complete, as certain techniques to hide platform
+details from build files need to be written and tested on every particular platform. Contributions
+in this area are welcome.
+</p>
 
-
+</body>
 </html>
diff --git a/manual/projecthelper.html b/manual/projecthelper.html
index 2e43f79..02a12e7 100644
--- a/manual/projecthelper.html
+++ b/manual/projecthelper.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>The Apache Ant frontend: ProjectHelper</title>
 </head>
@@ -25,126 +25,118 @@
 <body>
 <h1>The Apache Ant frontend: ProjectHelper</h1>
 
-<h2><a name="definition">What is a ProjectHelper?</a></h2>
+<h2 id="definition">What is a ProjectHelper?</h2>
 
 <p>
-The <code>ProjectHelper</code> in Apache Ant is responsible for parsing the build file
-and creating java instances representing the build workflow. It also signals which
-kind of file it can parse, and which file name it expects as default input file.
+The <code class="code">ProjectHelper</code> in Apache Ant is responsible for parsing the build file
+and creating Java instances representing the build workflow. It also signals which kind of file it
+can parse, and which file name it expects as default input file.
 </p>
 
 <p>
-Ant' default <code>ProjectHelper</code>
-(<code>org.apache.tools.ant.helper.ProjectHelper2</code>) parses the
-usual build.xml files. And if no build file is specified on the command line, it
-will expect to find a file named <code>build.xml</code>.
+Ant's default <code class="code">ProjectHelper</code>
+(<code class="code">org.apache.tools.ant.helper.ProjectHelper2</code>) parses the
+usual <code>build.xml</code> files. And if no build file is specified on the command line, it will
+expect to find a file named <code>build.xml</code>.
 </p>
 
 <p>
-The immediate benefit of a such abstraction it that it is possible to make Ant
-understand other kind of descriptive languages than XML. Some experiments have
-been done around a pure java frontend, and a groovy one too (ask the dev mailing
-list for further info about these).
+The immediate benefit of a such abstraction it that it is possible to make Ant understand other kind
+of descriptive languages than XML. Some experiments have been done around a pure Java frontend, and
+a Groovy one too (ask the dev mailing list for further info about these).
 </p>
 
-<p>Since Ant 1.8.2, the <a href="Tasks/import.html">import</a> task will also
-try to use the proper helper to parse the imported file. So it is possible to
-write different build files in different languages and have them import each
-other.
-</p>
-
-<h2><a name="repository">How is Ant is selecting the proper ProjectHelper</a></h2>
-
 <p>
-Ant knows about several implementations of <code>ProjectHelper</code>
-and has to decide which to use for each build file.
+<em>Since Ant 1.8.2</em>, the <a href="Tasks/import.html">import</a> task will also try to use the
+proper helper to parse the imported file. So it is possible to write different build files in
+different languages and have them import each other.
 </p>
 
-<p>At startup Ant lists the all implementations found and keeps them
-in the same order they've been found in an internal 'repository':
+<h2 id="repository">How is Ant is selecting the proper ProjectHelper</h2>
+
+<p>
+Ant knows about several implementations of <code class="code">ProjectHelper</code> and has to decide
+which to use for each build file.
+</p>
+
+<p>
+At startup Ant lists the all implementations found and keeps them in the same order they've been
+found in an internal 'repository':
+</p>
 <ul>
-    <li>the first to be searched for is the one declared by the system property
-        <code>org.apache.tools.ant.ProjectHelper</code> (see
-        <a href="running.html#sysprops">Java System Properties</a>);</li>
-    <li>then it searches with its class loader for a <code>ProjectHelper</code>
-        service declarations in the META-INF: it searches in the classpath for a
-        file <code>META-INF/services/org.apache.tools.ant.ProjectHelper</code>.
-        This file will just contain the fully qualified name of the
-        implementation of <code>ProjectHelper</code> to instantiate;</li>
-    <li>it will also search with the system class loader for
-        <code>ProjectHelper</code> service declarations in the META-INF;</li>
-    <li>last but not least it will add its default <code>ProjectHelper</code>
-        that can parse classical build.xml files.</li>
+  <li>the first to be searched for is the one declared by the system
+    property <code class="code">org.apache.tools.ant.ProjectHelper</code>
+    (see <a href="running.html#sysprops">Java System Properties</a>);</li>
+  <li>then it searches with its class loader for a <code>ProjectHelper</code> service declarations
+    in the <samp>META-INF</samp>: it searches in the classpath for a
+    file <samp>META-INF/services/org.apache.tools.ant.ProjectHelper</samp>.  This file will just
+    contain the fully qualified name of the implementation
+    of <code class="code">ProjectHelper</code> to instantiate;</li>
+  <li>it will also search with the system class loader for <code class="code">ProjectHelper</code>
+    service declarations in the <samp>META-INF</samp>;</li>
+  <li>last but not least it will add its default <code class="code">ProjectHelper</code> that can
+    parse classical <samp>build.xml</samp> files.</li>
 </ul>
-In case of an error while trying to instantiate a <code>ProjectHelper</code>, Ant
-will log an error but won't stop.  If you want further debugging
-info about the <code>ProjectHelper</code> internal 'repository', use the <b>system</b>
-property <code>ant.project-helper-repo.debug</code> and set it to
-<code>true</code>; the full stack trace will then also be printed.
+<p>
+In case of an error while trying to instantiate a <code class="code">ProjectHelper</code>, Ant will
+log an error but won't stop.  If you want further debugging info about
+the <code class="code">ProjectHelper</code> internal 'repository', use the <strong>system</strong>
+property <code>ant.project-helper-repo.debug</code> and set it to <q>true</q>; the full stack trace
+will then also be printed.
 </p>
 
 <p>
-When Ant is expected to parse a file, it will ask the
-<code>ProjectHelper</code> repository to find an implementation that will be
-able to parse the input file. Actually it will just iterate over the ordered list
-and the first implementation that returns <code>true</code> to
-<code>supportsBuildFile(File buildFile)</code> will be selected.
+When Ant is expected to parse a file, it will ask the <code class="code">ProjectHelper</code>
+repository to find an implementation that will be able to parse the input file. Actually it will
+just iterate over the ordered list and the first implementation that returns <q>true</q>
+to <code class="code">supportsBuildFile(File buildFile)</code> will be selected.
 </p>
 
 <p>
-When Ant is started and no input file has been specified, it will search for
-a default input file. It will iterate over list of <code>ProjectHelper</code>s
-and will select the first one that expects a default file that actually exist.
+When Ant is started and no input file has been specified, it will search for a default input
+file. It will iterate over list of <code class="code">ProjectHelper</code>s and will select the
+first one that expects a default file that actually exist.
 </p>
 
-<h2><a name="writing">Writing your own ProjectHelper</a></h2>
+<h2 id="writing">Writing your own ProjectHelper</h2>
 
 <p>
-The class <code>org.apache.tools.ant.ProjectHelper</code> is the API expected to
-be implemented. So write your own <code>ProjectHelper</code> by extending that
-abstract class. You are then expected to implement at least the function
-<code>parse(Project project, Object source)</code>. Note also that your
-implementation will be instantiated by Ant, and it is expecting a default
-constructor with no arguments.
+The class <code class="code">org.apache.tools.ant.ProjectHelper</code> is the API expected to be
+implemented. So write your own <code class="code">ProjectHelper</code> by extending that abstract
+class. You are then expected to implement at least the function <code class="code">parse(Project
+project, Object source)</code>. Note also that your implementation will be instantiated by Ant, and
+it is expecting a default constructor with no arguments.
 </p>
 
 <p>
-There are some functions that will help you define what your helper is
-capable of and what is is expecting:
+There are some functions that will help you define what your helper is capable of and what is is
+expecting:
+</p>
 <ul>
-    <li><code>getDefaultBuildFile()</code>: defines which file name is expected if
-    none provided</li>
-    <li><code>supportsBuildFile(File buildFile)</code>: defines if your parser
-    can parse the input file</li>
-
-    <li><code>canParseAntlibDescriptor(URL url)</code>: whether your
-      implementation is capable of parsing a given Antlib
-      descriptor.  The base class returns <code>false</code></li>
-    <li><code>parseAntlibDescriptor(Project containingProject, URL
-        source)</code>: invoked to actually parse the Antlib
-      descriptor if your implementation returned <code>true</code>
-      for the previous method.</li>
+  <li><code class="code">getDefaultBuildFile()</code>: defines which file name is expected if none
+    provided</li>
+  <li><code class="code">supportsBuildFile(File buildFile)</code>: defines if your parser can parse
+    the input file</li>
+  <li><code class="code">canParseAntlibDescriptor(URL url)</code>: whether your implementation is
+    capable of parsing a given Antlib descriptor.  The base class returns <q>false</q></li>
+  <li><code class="code">parseAntlibDescriptor(Project containingProject, URL source)</code>:
+    invoked to actually parse the Antlib descriptor if your implementation returned <q>true</q> for
+    the previous method.</li>
 </ul>
-</p>
 
 <p>
-Now that you have your implementation ready, you have to declare it to Ant. Three
-solutions here:
-<ul>
-    <li>use the system property <code>org.apache.tools.ant.ProjectHelper</code>
-        (see also the <a href="running.html#sysprops">Java System Properties</a>);</li>
-    <li>use the service file in META-INF: in the jar you will build with your
-        implementation, add a file
-        <code>META-INF/services/org.apache.tools.ant.ProjectHelper</code>.
-        And then in this file just put the fully qualified name of your
-        implementation</li>
-    <li>use the <a href="Tasks/projecthelper.html">projecthelper</a> task (since
-        Ant 1.8.2) which will install dynamically an helper in the internal helper
-        'repository'. Then your helper can be used on the next call to the
-        <a href="Tasks/import.html">import</a> task.</li>
-</ul>
+Now that you have your implementation ready, you have to declare it to Ant. Three solutions here:
 </p>
+<ul>
+  <li>use the system property <code class="code">org.apache.tools.ant.ProjectHelper</code> (see also
+    the <a href="running.html#sysprops">Java System Properties</a>);</li>
+  <li>use the service file in <samp>META-INF</samp>: in the jar you will build with your
+    implementation, add a file <samp>META-INF/services/org.apache.tools.ant.ProjectHelper</samp>.
+    And then in this file just put the fully qualified name of your implementation</li>
+  <li>use the <a href="Tasks/projecthelper.html">projecthelper</a> task (<em>since Ant 1.8.2</em>)
+    which will install dynamically a helper in the internal helper 'repository'. Then your helper
+    can be used on the next call to the <a href="Tasks/import.html">import</a> task.</li>
+</ul>
 
 </body>
 </html>
-
diff --git a/manual/properties.html b/manual/properties.html
index 226972a..22476c4 100644
--- a/manual/properties.html
+++ b/manual/properties.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us"/>
   <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
   <title>Properties and PropertyHelpers</title>
 </head>
@@ -25,152 +25,152 @@
 <body>
   <h1>Properties</h1>
 
-  <p>Properties are key-value-pairs where Apache Ant tries to
-    expand <code>${key}</code> to <code>value</code> at runtime.</p>
+  <p>Properties are key-value pairs where Apache Ant tries to expand <code>${key}</code>
+    to <code>value</code> at run time.</p>
 
-  <p>There are many tasks that can set properties, the most common one
-    is the <a href="Tasks/property.html">property</a> task.  In
-    addition properties can be defined
-    via <a href="running.html">command line arguments</a> or similar
-    mechanisms from outside of Ant.</p>
+  <p>There are many tasks that can set properties; the most common one is
+    the <a href="Tasks/property.html">property</a> task.  In addition properties can be defined
+    via <a href="running.html">command line arguments</a> or similar mechanisms from outside of
+    Ant.</p>
 
-  <p>Normally property values can not be changed, once a property is
-    set, most tasks will not allow its value to be modified.  In
-    general properties are of global scope, i.e. once they have been
-    defined they are available for any task or target invoked
-    subsequently - it is not possible to set a property in a child
-    build process created via
-    the <a href="Tasks/ant.html">ant</a>, antcall or subant tasks
-    and make it available to the calling build process, though.</p>
+  <p>Normally property values can not be changed: once a property is set, most tasks will not allow
+    its value to be modified.  In general properties are of global scope, i.e., once they have been
+    defined they are available for any task or target invoked subsequently&mdash;it is not possible
+    to set a property in a child build process created via
+    the <a href="Tasks/ant.html">ant</a>, <a href="Tasks/antcall.html">antcall</a>
+    or <a href="Tasks/subant.html">subant</a> tasks and make it available to the calling build
+    process, though.</p>
 
-  <p>Starting with Ant 1.8.0
-    the <a href="Tasks/local.html">local</a> task can be used to
-    create properties that are locally scoped to a target or
-    a <a href="Tasks/sequential.html">sequential</a> element like
-    the one of the <a href="Tasks/macrodef.html">macrodef</a>
-    task.</p>
+  <p><em>Since Ant 1.8.0</em> the <a href="Tasks/local.html">local</a> task can be used to create
+    properties that are locally scoped to a target or
+    a <a href="Tasks/sequential.html">sequential</a> element like the one of
+    the <a href="Tasks/macrodef.html">macrodef</a> task.</p>
 
-  <h2><a name="built-in-props">Built-in Properties</a></h2>
+  <h2 id="built-in-props">Built-in Properties</h2>
 
-  <p>Ant provides access to all system properties as if they had been
-    defined using a <code>&lt;property&gt;</code> task.  For
-    example, <code>${os.name}</code> expands to the name of the
-    operating system.</p>
-  <p>For a list of system properties see
-    <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#getProperties%28%29">the Javadoc of System.getProperties</a>.
+  <p>Ant provides access to all system properties as if they had been defined using
+    a <code>&lt;property&gt;</code> task.  For example, <samp>${os.name}</samp> expands to the name
+    of the operating system.</p>
+
+  <p>For a list of system properties,
+    see <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getProperties--"
+    target="_top">the javadoc of System.getProperties</a>.
   </p>
 
   <p>In addition, Ant has some built-in properties:</p>
-<pre><!-- TODO use <dl><dt><code>...</code></dt><dd>...</dd></dl> instead -->
-basedir             the absolute path of the project's basedir (as set
-                    with the basedir attribute of <a href="using.html#projects">&lt;project&gt;</a>).
-ant.file            the absolute path of the buildfile.
-ant.version         the version of Ant
-ant.project.name    the name of the project that is currently executing;
-                    it is set in the name attribute of &lt;project&gt;.
-ant.project.default-target
-                    the name of the currently executing project's
-                    default target;  it is set via the default
-                    attribute of &lt;project&gt;.
-ant.project.invoked-targets
-                    a comma separated list of the targets that have
-                    been specified on the command line (the IDE,
-                    an &lt;ant&gt; task ...) when invoking the current
-                    project.
-                    This property is set properly when the first target is executed.
-                    If you use it in the implicit target (directly
-                    under the &lt;project&gt; tag) the list will be
-                    empty if no target has been specified while it
-                    will contain the project's default target in this
-                    case for tasks nested into targets..
-ant.java.version    the JVM version Ant detected; currently it can hold
-                    the values &quot;9&quot;, &quot;1.8&quot;,
-                    &quot;1.7&quot;, &quot;1.6&quot;, &quot;1.5&quot;,
-                    &quot;1.4&quot;, &quot;1.3&quot; and
-                    &quot;1.2&quot;.
-ant.core.lib        the absolute path of the <code>ant.jar</code> file.
-</pre>
+  <dl>
+    <dt><code>basedir</code></dt>
+    <dd>the absolute path of the project's basedir (as set with
+      the <var>basedir</var> attribute
+      of <a href="using.html#projects">&lt;project&gt;</a>).</dd>
+    <dt><code>ant.file</code></dt>
+    <dd>the absolute path of the buildfile.</dd>
+    <dt><code>ant.version</code></dt>
+    <dd>the version of Ant</dd>
+    <dt><code>ant.project.name</code></dt>
+    <dd>the name of the project that is currently executing; it is set in the <var>name</var>
+      attribute of <code>&lt;project&gt;</code>.</dd>
+    <dt><code>ant.project.default-target</code></dt>
+    <dd>the name of the currently executing project's default target; it is set via
+      the <var>default</var> attribute of <code>&lt;project&gt;</code>.</dd>
+    <dt><code>ant.project.invoked-targets</code></dt>
+    <dd>a comma-separated list of the targets that have been specified (on the command line, inside
+      of an IDE, by an <code>&lt;ant&gt;</code> task, etc...) when invoking the current
+      project.<br/>This property is set properly when the first target is executed. If you use it in
+      the implicit target (directly under the <code>&lt;project&gt;</code> tag) the list will be
+      empty if no target has been specified while it will contain the project's default target in
+      this case for tasks nested into targets.</dd>
+    <dt><code>ant.java.version</code></dt>
+    <dd>the JVM version Ant detected; currently it can hold the
+      values <q>9</q>, <q>1.8</q>, <q>1.7</q>, <q>1.6</q>, <q>1.5</q>, <q>1.4</q>, <q>1.3</q>
+      and <q>1.2</q>.</dd>
+    <dt><code>ant.core.lib</code></dt>
+    <dd>the absolute path of the <samp>ant.jar</samp> file.</dd>
+  </dl>
 
-  <p>There is also another property, but this is set by the launcher
-    script and therefore maybe not set inside IDEs:</p>
-<pre>
-ant.home            home directory of Ant
-</pre>
+  <p>There is also another property, but this is set by the launcher script and therefore maybe not
+    set inside IDEs:</p>
+  <dl>
+    <dt><code>ant.home</code></dt>
+    <dd>home directory of Ant</dd>
+  </dl>
 
-  <p>The following property is only set if Ant is started via the
-    Launcher class (which means it may not be set inside IDEs
-    either):</p>
-<pre>
-ant.library.dir     the directory that has been used to load Ant's
-                    jars from.  In most cases this is ANT_HOME/lib.
-</pre>
+  <p>The following property is only set if Ant is started via the Launcher class (which means it may
+    not be set inside IDEs either):</p>
+  <dl>
+    <dt><code>ant.library.dir</code></dt>
+    <dd>the directory that has been used to load Ant's jars from.  In most cases this
+      is <samp>ANT_HOME/lib</samp>.</dd>
+  </dl>
 
-  <h1><a name="propertyHelper">PropertyHelpers</a></h1>
+  <h1 id="propertyHelper">PropertyHelpers</h1>
 
-  <p>Ant's property handling is accomplished by an instance of
-    <code>org.apache.tools.ant.PropertyHelper</code> associated with
-    the current Project.  You can learn more about this class by
-    examining Ant's Java API. In Ant 1.8 the PropertyHelper class was
-    much reworked and now itself employs a number of helper classes
-    (actually instances of
-    the <code>org.apache.tools.ant.PropertyHelper$Delegate</code>
-    marker interface) to take care of discrete tasks such as property
-    setting, retrieval, parsing, etc. This makes Ant's property
-    handling highly extensible; also of interest is the
-    new <a href="Tasks/propertyhelper.html">propertyhelper</a>
-    task used to manipulate the PropertyHelper and its delegates from
-    the context of the Ant buildfile.
+  <p>Ant's property handling is accomplished by an instance
+    of <code class="code">org.apache.tools.ant.PropertyHelper</code> associated with the current
+    Project.  You can learn more about this class by examining Ant's Java API. In Ant 1.8 the
+    <code class="code">PropertyHelper</code> class was much reworked and now itself employs a number
+    of helper classes (actually instances of
+    the <code class="code">org.apache.tools.ant.PropertyHelper$Delegate</code> marker interface) to
+    take care of discrete tasks such as property setting, retrieval, parsing, etc. This makes Ant's
+    property handling highly extensible; also of interest is the
+    new <a href="Tasks/propertyhelper.html">propertyhelper</a> task used to manipulate the
+    PropertyHelper and its delegates from the context of the Ant buildfile.</p>
 
-  <p>There are three sub-interfaces of <code>Delegate</code> that may be
-    useful to implement.</p>
+  <p>There are three sub-interfaces of <code class="code">Delegate</code> that may be useful to
+  implement:</p>
 
   <ul>
-    <li><code>org.apache.tools.ant.property.PropertyExpander</code> is
-      responsible for finding the property name inside a string in the
-      first place (the default extracts <code>foo</code>
-      from <code>${foo}</code>).
+    <li><code>org.apache.tools.ant.property.PropertyExpander</code> is responsible for finding the
+      property name inside a string in the first place (the default extracts <samp>foo</samp>
+      from <samp>${foo}</samp>).
 
-      <p>This is the interface you'd implement if you wanted to invent
-        your own property syntax - or allow nested property expansions
-        since the default implementation doesn't balance braces
-        (see <a href="https://git-wip-us.apache.org/repos/asf?p=ant-antlibs-props.git;a=blob;f=src/main/org/apache/ant/props/NestedPropertyExpander.java;hb=HEAD"><code>NestedPropertyExpander</code>
-        in the "props" Antlib</a> for an example).</p>
+      <p>This is the interface you'd implement if you wanted to invent your own property
+        syntax&mdash;or allow nested property expansions since the default implementation doesn't
+        balance braces
+        (see <a href="https://gitbox.apache.org/repos/asf?p=ant-antlibs-props.git;a=blob;f=src/main/org/apache/ant/props/NestedPropertyExpander.java;hb=HEAD"
+        target="_top"><code class="code">NestedPropertyExpander</code> in the <samp>props</samp> Antlib</a> for
+        an example).</p>
     </li>
 
-    <li><code>org.apache.tools.ant.PropertyHelper$PropertyEvaluator</code>
-      is used to expand <code>${some-string}</code> into
-      an <code>Object</code>.
+    <li><code class="code">org.apache.tools.ant.PropertyHelper$PropertyEvaluator</code> is used to
+      expand <samp>${some-string}</samp> into an <code>Object</code>.
+
+      <p>This is the interface you'd implement if you want to provide your own storage independent
+        of Ant's project instance&mdash;the interface represents the reading end.  An example for
+        this would be <code class="code">org.apache.tools.ant.property.LocalProperties</code> which
+        implements storage for <a href="Tasks/local.html">local properties</a>.</p>
+
+      <p>Another reason to implement this interface is if you wanted to provide your own "property
+        protocol" like expanding <code>toString:foo</code> by looking up the project
+        reference <samp>foo</samp> and invoking <code class="code">toString()</code> on it (which is
+        already implemented in Ant, see below).</p>
+    </li>
+
+    <li><code class="code">org.apache.tools.ant.PropertyHelper$PropertySetter</code> is responsible
+      for setting properties.
+
+      <p>This is the interface you'd implement if you want to provide your own storage independent
+        of Ant's project instance&mdash;the interface represents the writing end.  An example for
+        this would be <code class="code">org.apache.tools.ant.property.LocalProperties</code> which
+        implements storage for <a href="Tasks/local.html">local properties</a>.</p>
+    </li>
+
+    <li><code class="code">org.apache.tools.ant.PropertyHelper$PropertyEnumerator</code>
+      is responsible for enumerating property names.
 
       <p>This is the interface you'd implement if you want to provide
-        your own storage independent of Ant's project instance - the
-        interface represents the reading end.  An example for this
-        would
-        be <code>org.apache.tools.ant.property.LocalProperties</code>
-        which implements storage
-        for <a href="Tasks/local.html">local properties</a>.</p>
+        your own storage independent of Ant's project
+        instance&mdash;the interface represents part of the reading
+        end.  An example for this would
+        be <code class="code">org.apache.tools.ant.property.LocalProperties</code>
+        which implements storage for <a href="Tasks/local.html">local
+        properties</a>.</p>
 
-      <p>Another reason to implement this interface is if you wanted
-        to provide your own "property protocol" like
-        expanding <code>toString:foo</code> by looking up the project
-        reference foo and invoking <code>toString()</code> on it
-        (which is already implemented in Ant, see below).</p>
+      <p><em>This interface has been added with Ant 1.10.9.</em></p>
     </li>
-
-    <li><code>org.apache.tools.ant.PropertyHelper$PropertySetter</code>
-      is responsible for setting properties.
-
-      <p>This is the interface you'd implement if you want to provide
-        your own storage independent of Ant's project instance - the
-        interface represents the reading end.  An example for this
-        would
-        be <code>org.apache.tools.ant.property.LocalProperties</code>
-        which implements storage
-        for <a href="Tasks/local.html">local properties</a>.</p>
-    </li>
-
   </ul>
 
-  <p>The default <code>PropertyExpander</code> looks similar to:</p>
+  <p>The default <code class="code">PropertyExpander</code> looks similar to:</p>
 
 <pre>
 public class DefaultExpander implements PropertyExpander {
@@ -179,7 +179,7 @@
         int index = pos.getIndex();
         if (s.indexOf("${", index) == index) {
             int end = s.indexOf('}', index);
-            if (end < 0) {
+            if (end &lt; 0) {
                 throw new BuildException("Syntax error in property: " + s);
             }
             int start = index + 2;
@@ -188,13 +188,12 @@
         }
         return null;
     }
-}
-</pre>
+}</pre>
 
-  <p>The logic that replaces <code>${toString:some-id}</code> with the
-    stringified representation of the object with
-    id <code>some-id</code> inside the current build is contained in a
-    PropertyEvaluator similar to the following code:</p>
+  <p>The logic that replaces <samp>${toString:<i>some-id</i>}</samp> with the stringified
+    representation of the object with <var>id</var> <samp><i>some-id</i></samp> inside the current
+    build is contained in a <code class="code">PropertyEvaluator</code> similar to the following
+    code:</p>
 
 <pre>
 public class ToStringEvaluator implements PropertyHelper.PropertyEvaluator {
@@ -207,198 +206,163 @@
         }
         return o == null ? null : o.toString();
     }
-}
-</pre>
-
+}</pre>
 
   <h1>Property Expansion</h1>
 
-  <p>When Ant encounters a construct <code>${some-text}</code> the
-    exact parsing semantics are subject to the configured property
-    helper delegates.</p>
+  <p>When Ant encounters a construct <samp>${some-text}</samp> the exact parsing semantics are
+    subject to the configured property helper delegates.</p>
 
   <h2><code>$$</code> Expansion</h2>
 
-  <p>In its default configuration Ant will expand the
-    text <code>$$</code> to a single <code>$</code> and suppress the
-    normal property expansion mechanism for the text immediately
-    following it, i.e. <code>$${key}</code> expands
-    to <code>${key}</code> and not <code>value</code> even though a
-    property named <code>key</code> was defined and had the
-    value <code>value</code>.  This can be used to escape
-    literal <code>$</code> characters and is useful in constructs that
-    only look like property expansions or when you want to provide
-    diagnostic output like in</p>
+  <p>In its default configuration Ant will expand the text <q>$$</q> to a single <q>$</q> and
+    suppress the normal property expansion mechanism for the text immediately following it,
+    i.e., <samp>$${key}</samp> expands to <samp>${key}</samp> and not <code>value</code> even though
+    a property named <code>key</code> was defined and had the value <samp>value</samp>.  This can be
+    used to escape literal <q>$</q> characters and is useful in constructs that only look like
+    property expansions or when you want to provide diagnostic output like in</p>
 
-<pre>  &lt;echo&gt;$${builddir}=${builddir}&lt;/echo&gt;</pre>
+<pre>&lt;echo&gt;$${builddir}=${builddir}&lt;/echo&gt;</pre>
 
-    <p>which will echo this message:</p>
+  <p>which will echo this message:</p>
 
-<pre>  ${builddir}=build/classes</pre>
+<pre class="output">${builddir}=build/classes</pre>
 
-  <p>if the property <code>builddir</code> has the
-    value <code>build/classes</code>.</p>
-    
-  <p>In order to maintain backward compatibility with older Ant
-    releases, a single '$' character encountered apart from a
-    property-like construct (including a matched pair of french
-    braces) will be interpreted literally; that is, as '$'.  The
-    "correct" way to specify this literal character, however, is by
-    using the escaping mechanism unconditionally, so that "$$" is
-    obtained by specifying "$$$$".  Mixing the two approaches yields
-    unpredictable results, as "$$$" results in "$$".</p>
+  <p>if the property <code>builddir</code> has the value <samp>build/classes</samp>.</p>
+
+  <p>In order to maintain backward compatibility with older Ant releases, a single <q>$</q>
+    character encountered apart from a property-like construct (including a matched pair of french
+    braces) will be interpreted literally, that is, as <q>$</q>.  The "correct" way to specify this
+    literal character, however, is by using the escaping mechanism unconditionally, so
+    that <q>$$</q> is obtained by specifying <q>$$$$</q>.  Mixing the two approaches yields
+    unpredictable results, as <q>$$$</q> results in <q>$$</q>.</p>
 
   <h2>Nesting of Braces</h2>
 
-  <p>In its default configuration Ant will not try to balance braces
-    in property expansions, it will only consume the text up to the
-    first closing brace when creating a property name.  I.e. when
-    expanding something like <code>${a${b}}</code> it will be
-    translated into two parts:</p>
+  <p>In its default configuration Ant will not try to balance braces in property expansions, it will
+    only consume the text up to the first closing brace when creating a property name.  I.e. when
+    expanding something like <samp>${a${b}}</samp> it will be translated into two parts:</p>
 
   <ol>
-    <li>the expansion of property <code>a${b</code> - likely nothing
-      useful.</li>
-    <li>the literal text <code>}</code> resulting from the second
-      closing brace</li>
+    <li>the expansion of property <samp>a${b</samp>&mdash;likely nothing useful.</li>
+    <li>the literal text <samp>}</samp> resulting from the second closing brace</li>
   </ol>
 
-  <p>This means you can't use easily expand properties whose names are
-    given by properties, but there
-    are <a href="http://ant.apache.org/faq.html#propertyvalue-as-name-for-property">some
-    workarounds</a> for older versions of Ant.  With Ant 1.8.0 and the
-    <a href="http://ant.apache.org/antlib/props/">the props Antlib</a>
-    you can configure Ant to use
-    the <code>NestedPropertyExpander</code> defined there if you need
-    such a feature.</p>
+  <p>This means you can't use easily expand properties whose names are stored in properties, but
+    there are <a href="https://ant.apache.org/faq.html#propertyvalue-as-name-for-property"
+    target="_top">some workarounds</a> for older versions of Ant. <em>Since Ant 1.8.0</em> using
+    the <a href="https://ant.apache.org/antlibs/props/" target="_top">props Antlib</a> you can
+    configure Ant to use the <code class="code">NestedPropertyExpander</code> defined there if you
+    need such a feature.</p>
 
-  <h2>Expanding a "Property Name"</h2>
+  <h2>Expanding a Property Reference</h2>
 
-  <p>In its most simple form <code>${key}</code> is supposed to look
-    up a property named <code>key</code> and expand to the value of
-    the property.  Additional <code>PropertyEvaluator</code>s may
-    result in a different interpretation of <code>key</code>,
-    though.</p>
+  <p>In its most simple form <samp>${key}</samp> is supposed to look up a property
+    named <code>key</code> and expand to the value of the property.
+    Additional <code>PropertyEvaluator</code>s may result in a different interpretation
+    of <code>key</code>, though.</p>
 
-  <p>The <a href="http://ant.apache.org/antlibs/props/">props
-      Antlib</a> provides a few interesting evaluators but there are
-      also a few built-in ones.</p>
+  <p>The <a href="https://ant.apache.org/antlibs/props/" target="_top">props Antlib</a> provides a
+    few interesting evaluators but there are also a few built-in ones.</p>
 
-  <h3><a name="toString">Getting the value of a Reference with
-      ${toString:}</a></h3>
+  <h3 id="toString">Getting the value of a Reference with <samp>${toString:}</samp></h3>
 
-  <p>Any Ant type which has been declared with a reference can also
-    its string value extracted by using the <code>${toString:}</code>
-    operation, with the name of the reference listed after
-    the <code>toString:</code> text.  The <code>toString()</code>
-    method of the Java class instance that is referenced is invoked
-    -all built in types strive to produce useful and relevant output
-    in such an instance.</p>
+  <p>Any Ant type item which has been declared with a reference can also its string value extracted
+    by using the <samp>${toString:}</samp> operation, with the name of the reference listed after
+    the <code>toString:</code> text.  The <code class="code">toString()</code> method of the Java
+    class instance that is referenced is invoked&mdash;all built in types strive to produce useful
+    and relevant output in such an instance.</p>
 
-  <p>For example, here is how to get a listing of the files in a fileset,<p>
+  <p>For example, here is how to get a listing of the files in a fileset:<p>
 
 <pre>
-&lt;fileset id=&quot;sourcefiles&quot; dir=&quot;src&quot; includes=&quot;**/*.java&quot; /&gt;
-&lt;echo&gt; sourcefiles = ${toString:sourcefiles} &lt;/echo&gt;
-</pre>
+&lt;fileset id=&quot;sourcefiles&quot; dir=&quot;src&quot; includes=&quot;**/*.java&quot;/&gt;
+&lt;echo&gt; sourcefiles = ${toString:sourcefiles} &lt;/echo&gt;</pre>
 
-  <p>There is no guarantee that external types provide meaningful
-    information in such a situation</p>
+  <p>There is no guarantee that external types provide meaningful information in such a
+    situation</p>
 
-  <h3><a name="ant.refid">Getting the value of a Reference with
-      ${ant.refid:}</a></h3>
+  <h3 id="ant.refid">Getting the value of a Reference with <samp>${ant.refid:}</samp></h3>
 
-  <p>Any Ant type which has been declared with a reference can also be
-    used as a property by using the <code>${ant.refid:}</code>
-    operation, with the name of the reference listed after
-    the <code>ant.refid:</code> text.  The difference between this
-    operation and <a href="#toString"><code>${toString:}</code></a> is
-    that <code>${ant.refid:}</code> will expand to the referenced
-    object itself.  In most circumstances the toString method will be
-    invoked anyway, for example if the <code>${ant.refid:}</code> is
-    surrounded by other text.</p>
+  <p>Any Ant type item which has been declared with a reference can also be used as a property by
+    using the <samp>${ant.refid:}</samp> operation, with the name of the reference listed after
+    the <code>ant.refid:</code> text.  The difference between this operation
+    and <a href="#toString"><samp>${toString:}</samp></a> is that <samp>${ant.refid:}</samp> will
+    expand to the referenced object itself.  In most circumstances
+    the <code class="code">toString()</code> method will be invoked anyway, for example if
+    the <samp>${ant.refid:}</samp> is surrounded by other text.</p>
 
-  <p>This syntax is most useful when using a task with attribute
-    setters that accept objects other than String.  For example if the
-    setter accepts a Resource object as in</p>
+  <p>This syntax is most useful when using a task with attribute setters that accept objects other
+    than <code class="code">String</code>.  For example, if the setter accepts
+    a <code class="code">Resource</code> object as in</p>
+
+  <pre>public void setAttr(Resource r) { ... }</pre>
+
+  <p>then the syntax can be used to pass in resource subclasses previously defined as references
+    like</p>
 <pre>
-public void setAttr(Resource r) { ... }
-</pre>
+&lt;url url="https://ant.apache.org/" id="anturl"/&gt;
+&lt;my:task attr="${ant.refid:anturl}"/&gt;</pre>
 
-  <p>then the syntax can be used to pass in resource subclasses
-    previously defined as references like</p>
-<pre>
-  &lt;url url="http://ant.apache.org/" id="anturl"/&gt;
-  &lt;my:task attr="${ant.refid:anturl}"/&gt;
-</pre>
-
-  <h2><a name="if+unless">If/Unless Attributes</a></h2>
+  <h2 id="if+unless">If/Unless Attributes</h2>
   <p>
-      The <code>&lt;target></code> element and various tasks (such as
-      <code>&lt;fail></code>) and task elements (such as <code>&lt;test></code>
-      in <code>&lt;junit></code>) support <code>if</code> and <code>unless</code>
-      attributes which can be used to control whether the item is run or otherwise
-      takes effect.
+    The <code>&lt;target&gt;</code> element and various tasks (such as <code>&lt;fail&gt;</code>)
+    and task elements (such as <code>&lt;test&gt;</code> in <code>&lt;junit&gt;</code>)
+    support <var>if</var> and <var>unless</var> attributes which can be used to control whether the
+    item is run or otherwise takes effect.
   </p>
   <p>
-      In Ant 1.7.1 and earlier, these attributes could only be property names.
-      The item was enabled if a property with that name was defined - even to be
-      the empty string or <tt>false</tt> - and disabled if the property was not
-      defined. For example, the following works but there is no way to override
-      the file existence check negatively (only positively):
+    In Ant 1.7.1 and earlier, these attributes could only be property names.  The item was enabled
+    if a property with that name was defined&mdash;even to be the empty string
+    or <q>false</q>&mdash;and disabled if the property was not defined. For example, the following
+    works but there is no way to override the file existence check negatively (only positively):
   </p>
   <pre>
-&lt;target name="-check-use-file">
-    &lt;available property="file.exists" file="some-file"/>
+&lt;target name="-check-use-file"&gt;
+    &lt;available property="file.exists" file="some-file"/&gt;
+&lt;/target&gt;
+&lt;target name="use-file" depends="-check-use-file" <strong>if="file.exists"</strong>&gt;
+    &lt;!-- do something requiring that file... --&gt;
 &lt;/target>
-&lt;target name="use-file" depends="-check-use-file" <b>if="file.exists"</b>>
-    &lt;!-- do something requiring that file... -->
-&lt;/target>
-&lt;target name="lots-of-stuff" depends="use-file,other-unconditional-stuff"/>
-  </pre>
+&lt;target name="lots-of-stuff" depends="use-file,other-unconditional-stuff"/&gt;</pre>
   <p>
-      As of Ant 1.8.0, you may instead use property expansion; a value of
-      <tt>true</tt> (or <tt>on</tt> or <tt>yes</tt>) will enable the
-      item, while <tt>false</tt> (or <tt>off</tt> or <tt>no</tt>) will
-      disable it. Other values are still assumed to be property
-      names and so the item is enabled only if the named property is defined.
+    <em>Since Ant 1.8.0</em>, you may instead use property expansion; a value of <q>true</q>
+    (or <q>on</q> or <q>yes</q>) will enable the item, while <q>false</q> (or <q>off</q>
+    or <q>no</q>) will disable it. Other values are still assumed to be property names and so the
+    item is enabled only if the named property is defined.
   </p>
   <p>
-      Compared to the older style, this gives you additional flexibility, because
-      you can override the condition from the command line or parent scripts:
+    Compared to the older style, this gives you additional flexibility, because you can override the
+    condition from the command line or parent scripts:
   </p>
   <pre>
-&lt;target name="-check-use-file" <b>unless="file.exists"</b>>
-    &lt;available property="file.exists" file="some-file"/>
+&lt;target name="-check-use-file" <strong>unless="file.exists"</strong>&gt;
+    &lt;available property="file.exists" file="some-file"/&gt;
 &lt;/target>
-&lt;target name="use-file" depends="-check-use-file" <b>if="${file.exists}"</b>>
-    &lt;!-- do something requiring that file... -->
+&lt;target name="use-file" depends="-check-use-file" <strong>if="${file.exists}"</strong>&gt;
+    &lt;!-- do something requiring that file... --&gt;
 &lt;/target>
-&lt;target name="lots-of-stuff" depends="use-file,other-unconditional-stuff"/>
-  </pre>
+&lt;target name="lots-of-stuff" depends="use-file,other-unconditional-stuff"/&gt;</pre>
   <p>
-      Now <code>ant -Dfile.exists=false lots-of-stuff</code> will run
-      <code>other-unconditional-stuff</code> but not <code>use-file</code>,
-      as you might expect, and you can disable the condition from another script
-      too:
+    Now <kbd>ant -Dfile.exists=false lots-of-stuff</kbd> will run <q>other-unconditional-stuff</q>
+    but not <q>use-file</q>, as you might expect, and you can disable the condition from another
+    script too:
   </p>
   <pre>
-&lt;antcall target="lots-of-stuff">
-    &lt;param name="file.exists" value="false"/>
-&lt;/antcall>
-  </pre>
+&lt;antcall target="lots-of-stuff"&gt;
+    &lt;param name="file.exists" value="false"/&gt;
+&lt;/antcall&gt;</pre>
   <p>
-      Similarly, an <code>unless</code> attribute disables the item if it is
-      either the name of property which is defined, or if it evaluates to a
-      <tt>true</tt>-like value. For example, the following allows you to define
-      <tt>skip.printing.message=true</tt> in <tt>my-prefs.properties</tt> with
-      the results you might expect:
+    Similarly, an <var>unless</var> attribute disables the item if it is either the name of property
+    which is defined, or if it evaluates to a <q>true</q>-like value. For example, the following
+    allows you to define <code>skip.printing.message=true</code> in <samp>my-prefs.properties</samp>
+    with the results you might expect:
   </p>
   <pre>
-&lt;property file="my-prefs.properties"/>
-&lt;target name="print-message" <b>unless="${skip.printing.message}"</b>>
+&lt;property file="my-prefs.properties"/&gt;
+&lt;target name="print-message" <strong>unless="${skip.printing.message}"</strong>&gt;
     &lt;echo>hello!&lt;/echo>
-&lt;/target>
-  </pre>
+&lt;/target&gt;</pre>
 
 </body>
+</html>
diff --git a/manual/proxy.html b/manual/proxy.html
index 13ef6e8..76ca30b 100644
--- a/manual/proxy.html
+++ b/manual/proxy.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Proxy Configuration</title>
 </head>
@@ -26,84 +26,83 @@
 <h2>Proxy Configuration</h2>
 
 <p>
-This page discussing proxy issues on command-line Apache Ant.
-Consult your IDE documentation for IDE-specific information upon proxy setup.
+  This page discussing proxy issues on command-line Apache Ant.
+  Consult your IDE documentation for IDE-specific information upon
+  proxy setup.
 </p>
 
 <p>
-
-All tasks and threads running in Ant's JVM share the same HTTP/FTP/Socks
-proxy configuration.
+  All tasks and threads running in Ant's JVM share the same
+  HTTP/FTP/Socks proxy configuration.
 </p>
 
 <p>
-    When any task tries to retrieve content from an HTTP page, including the
-    <code>&lt;get&gt;</code> task, any automated URL retrieval in
-    an XML/XSL task, or any third-party task that uses the <code>java.net.URL</code>
-    classes, the proxy settings may make the difference between success and failure.
+  When any task tries to retrieve content from an HTTP page, including
+  the <code>&lt;get&gt;</code> task, any automated URL retrieval in an
+  XML/XSL task, or any third-party task that uses
+  the <code>java.net.URL</code> classes, the proxy settings may make
+  the difference between success and failure.
 </p>
 <p>
-    Anyone authoring a build file behind a blocking firewall will immediately appreciate
-    the problems and may want to write a build file to deal with the problem, but
-    users of third party build build files may find that the build file itself
-    does not work behind the firewall.
+  Anyone authoring a build file behind a blocking firewall will
+  immediately appreciate the problems and may want to write a build
+  file to deal with the problem, but users of third party build build
+  files may find that the build file itself does not work behind the
+  firewall.
 </p>
 <p>
-    This is a long standing problem with Java and Ant. The only way to fix
-    it is to explicitly configure Ant with the proxy settings, either
-    by passing down the proxy details as JVM properties, or to
-    tell Ant on a Java1.5+ system to have the JVM work it out for itself.
-
+  This is a long standing problem with Java and Ant. The only way to
+  fix it is to explicitly configure Ant with the proxy settings,
+  either by passing down the proxy details as JVM properties, or to
+  tell Ant on a Java 5+ system to have the JVM work it out for itself.
 </p>
 
-
-
-<h3>Java1.5+ proxy support (new for Ant1.7)</h3>
+<h3>Java 5+ proxy support</h3>
+<p><em>Since Ant 1.7</em></p>
 <p>
-    When Ant starts up, if the <code>-autoproxy</code>
-    command is supplied, Ant sets the
-    <code>java.net.useSystemProxies</code> system property. This tells 
-    a Java1.5+ JVM to use the current set of property settings of the host
-    environment. Other JVMs, such as the Kaffe and Apache Harmony runtimes,
-    may also use this property in future.
-    It is ignored on the Java1.4 and earlier runtimes.
+  When Ant starts up, if the <kbd>-autoproxy</kbd> command is
+  supplied, Ant sets the <code>java.net.useSystemProxies</code> system
+  property. This tells a Java 5+ runtime to use the current set of
+  property settings of the host environment. Other JVMs, such as
+  Kaffe and Apache Harmony, may also use this property in
+  future.  It is ignored on the Java 1.4 and earlier runtimes.
 </p>
 <p>
-    This property maybe enough to give command-line Ant
-    builds network access, although in practise the results
-    are inconsistent.
+  This property maybe enough to give command-line Ant builds network
+  access, although in practise the results are inconsistent.
 </p>
 <p>
-    It is has also been reported a breaking the IBM Java 5 JRE on AIX,
-    and does not always work on Linux (presumably due to missing gconf settings)
-    Other odd things can go wrong, like Oracle JDBC drivers or pure Java SVN clients.
+  It is has also been reported a breaking the IBM Java 5 runtime on AIX,
+  and does not always work on Linux (presumably due to
+  missing <code>gconf</code> settings) Other odd things can go wrong,
+  like Oracle JDBC drivers or pure Java SVN clients.
 </p>
-
 <p>
-    To make the <code>-autoproxy</code> option the default, add it to the environment variable
-    <code>ANT_ARGS</code>, which contains a list of arguments to pass to Ant on every
-    command line run.
+  To make the <kbd>-autoproxy</kbd> option the default, add it to
+  the environment variable <code>ANT_ARGS</code>, which contains a
+  list of arguments to pass to Ant on every command line run.
 </p>
 
 <h4>How Autoproxy works</h4>
 <p>
-The <code>java.net.useSystemProxies</code> is checked only
-once, at startup time, the other checks (registry, gconf, system properties) are done
-dynamically whenever needed (socket connection, URL connection etc..).
+  The <code>java.net.useSystemProxies</code> is checked only once, at
+  startup time, the other checks (registry, <code>gconf</code>, system
+  properties) are done dynamically whenever needed (socket connection,
+  URL connection etc..).
 </p>
-<h5>Windows</h5>
 
+<h5>Windows</h5>
 <p>
-The JVM goes straight to the registry, bypassing WinInet, as it is not
-present/consistent on all supported Windows platforms (it is part of IE,
-really). Java 7 may use the Windows APIs on the platforms when it is present.
+  The JVM goes straight to the registry, bypassing WinInet, as it is
+  not present/consistent on all supported Windows platforms (it is
+  part of IE, really). Java 7 may use the Windows APIs on the
+  platforms when it is present.
 </p>
 
 <h5>Linux</h5>
-
 <p>
-The JVM uses the gconf library to look at specific entries.
-The GConf-2 settings used are:
+  The JVM uses the <code>gconf</code> library to look at specific
+  entries.  The <code>GConf-2</code> settings used are:
 </p>
 <pre>
  - /system/http_proxy/use_http_proxy            boolean
@@ -124,168 +123,167 @@
  - /system/proxy/gopher_port                    int
 </pre>
 <p>
-If you are using KDE or another GUI than Gnome, you can still use the
-<code>gconf-editor</code> tool to add these entries.
+  If you are using KDE or another GUI than Gnome, you can still use
+  the <code>gconf-editor</code> tool to add these entries.
 </p>
 
-
 <h3>Manual JVM options</h3>
 <p>
-    Any JVM can have its proxy options explicitly configured by passing
-    the appropriate <code>-D</code> system property options to the runtime.
-    Ant can be configured through all its shell scripts via the
-    <code>ANT_OPTS</code> environment variable, which is a list of options to
-    supply to Ant's JVM:
+  Any JVM can have its proxy options explicitly configured by passing
+  the appropriate <kbd>-D</kbd> system property options to the
+  runtime.  Ant can be configured through all its shell scripts via
+  the <code>ANT_OPTS</code> environment variable, which is a list of
+  options to supply to Ant's JVM:
 </p>
 <p>
   For bash:
-</p>  
-<pre>
-    export ANT_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
-</pre>
-  For csh/tcsh:
-<pre>
-    setenv ANT_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
-</pre>
+</p>
+<pre>export ANT_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"</pre>
 <p>
-If you insert this line into the Ant shell script itself, it gets picked up
-by all continuous integration tools running on the system that call Ant via the
-command line.
+For csh/tcsh:
+</p>
+<pre>setenv ANT_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"</pre>
+<p>
+  If you insert this line into the Ant shell script itself, it gets
+  picked up by all continuous integration tools running on the system
+  that call Ant via the command line.
 </p>
 <p>
-  For Windows, set the <code>ANT_OPTS</code> environment variable in the appropriate "My Computer" 
-  properties dialog box (winXP), "Computer" properties (Vista)
+  For Windows, set the <code>ANT_OPTS</code> environment variable in
+  the appropriate "My Computer" properties dialog box (XP), "Computer"
+  properties (Vista)
 </p>
 <p>
-  This mechanism works across Java versions, is cross-platform and reliable. 
-  Once set, all build files run via the command line will automatically have
-  their proxy setup correctly, without needing any build file changes. It also
-  apparently overrides Ant's automatic proxy settings options.
+  This mechanism works across Java versions, is cross-platform and
+  reliable.  Once set, all build files run via the command line will
+  automatically have their proxy setup correctly, without needing any
+  build file changes. It also apparently overrides Ant's automatic
+  proxy settings options.
 </p>
-<p>  
+<p>
   It is limited in the following ways:
-</p>  
-  <ol>
+</p>
+<ol>
   <li>Does not work under IDEs. These need their own proxy settings changed</li>
   <li>Not dynamic enough to deal with laptop configuration changes.</li>
-  </ol>
-
+</ol>
 
 <h3>SetProxy Task</h3>
 <p>
-    The <a href="Tasks/setproxy.html">setproxy task</a> can be used to
-    explicitly set a proxy in a build file. This manipulates the many proxy 
-    configuration properties of a JVM, and controls the proxy settings for all 
-    network operations in the same JVM from that moment. 
+  The <a href="Tasks/setproxy.html">setproxy task</a> can be used to
+  explicitly set a proxy in a build file. This manipulates the many
+  proxy configuration properties of a JVM, and controls the proxy
+  settings for all network operations in the same JVM from that
+  moment.
 </p>
 <p>
-    If you have a build file that is only to be used in-house, behind a firewall, on
-    an older JVM, <i>and you cannot change Ant's JVM proxy settings</i>, then
-    this is your best option. It is ugly and brittle, because the build file now contains
-    system configuration information. It is also hard to get this right across
-    the many possible proxy options of different users (none, HTTP, SOCKS).
+  If you have a build file that is only to be used in-house, behind a
+  firewall, on an older JVM, <em>and you cannot change Ant's JVM proxy
+  settings</em>, then this is your best option. It is ugly and
+  brittle, because the build file now contains system configuration
+  information. It is also hard to get this right across the many
+  possible proxy options of different users (none, HTTP, SOCKS).
 </p>
-
-
 <p>
-    Note that proxy configurations set with this task will probably override
-    any set by other mechanisms. It can also be used with fancy tricks to 
-    only set a proxy if the proxy is considered reachable:
+  Note that proxy configurations set with this task will probably
+  override any set by other mechanisms. It can also be used with fancy
+  tricks to only set a proxy if the proxy is considered reachable:
 </p>
 
 <pre>
-  &lt;target name="probe-proxy" depends="init"&gt;
-    &lt;condition property="proxy.enabled"&gt;
-      &lt;and&gt;
-        &lt;isset property="proxy.host"/&gt;
-        &lt;isreachable host="${proxy.host}"/&gt;
-      &lt;/and&gt;
-    &lt;/condition&gt;
-  &lt;/target&gt;
+&lt;target name="probe-proxy" depends="init"&gt;
+  &lt;condition property="proxy.enabled"&gt;
+    &lt;and&gt;
+      &lt;isset property="proxy.host"/&gt;
+      &lt;isreachable host="${proxy.host}"/&gt;
+    &lt;/and&gt;
+  &lt;/condition&gt;
+&lt;/target&gt;
 
-  &lt;target name="proxy" depends="probe-proxy" if="proxy.enabled"&gt;
-    &lt;property name="proxy.port" value="80"/&gt;
-    &lt;property name="proxy.user" value=""/&gt;
-    &lt;property name="proxy.pass" value=""/&gt;
-    &lt;setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"
-      proxyuser="${proxy.user}" proxypassword="${proxy.pass}"/&gt;
-  &lt;/target&gt;
-</pre>
+&lt;target name="proxy" depends="probe-proxy" if="proxy.enabled"&gt;
+  &lt;property name="proxy.port" value="80"/&gt;
+  &lt;property name="proxy.user" value=""/&gt;
+  &lt;property name="proxy.pass" value=""/&gt;
+  &lt;setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"
+            proxyuser="${proxy.user}" proxypassword="${proxy.pass}"/&gt;
+&lt;/target&gt;</pre>
 
 <h3>Custom ProxySelector implementations</h3>
 <p>
-    As Java lets developers write their own ProxySelector implementations, it 
-    is theoretically possible for someone to write their own proxy selector class that uses
-    different policies to determine proxy settings. There is no explicit support
-    for this in Ant, and it has not, to the team's knowledge, been attempted. 
+  As Java lets developers write their own ProxySelector
+  implementations, it is theoretically possible for someone to write
+  their own proxy selector class that uses different policies to
+  determine proxy settings. There is no explicit support for this in
+  Ant, and it has not, to the team's knowledge, been attempted.
 </p>
 <p>
-    This could be the most flexible of solutions, as one could easily imagine
-    an Ant-specific proxy selector that was driven off ant properties, rather
-    than system properties. Developers could set proxy options in their
-    custom build.properties files, and have this propagate.
+  This could be the most flexible of solutions, as one could easily
+  imagine an Ant-specific proxy selector that was driven off ant
+  properties, rather than system properties. Developers could set
+  proxy options in their custom build.properties files, and have this
+  propagate.
 </p>
 <p>
-    One issue here is with concurrency: the default proxy selector is per-JVM,
-    not per-thread, and so the proxy settings will apply to all sockets opened
-    on all threads; we also have the problem of how to propagate options from
-    one build to the JVM-wide selector.
+  One issue here is with concurrency: the default proxy selector is
+  per-JVM, not per-thread, and so the proxy settings will apply to all
+  sockets opened on all threads; we also have the problem of how to
+  propagate options from one build to the JVM-wide selector.
 </p>
 
 <h3>Configuring the Proxy settings of Java programs under Ant</h3>
 
 <p>
-    Any program that is executed with <code>&lt;java&gt;</code> without setting
-    <code>fork="true"</code> will pick up the Ant's settings. If you need
-    different values, set <code>fork="false"</code> and provide the values
-    in <code>&lt;sysproperty&gt;</code> elements.
-</p>    
-    If you wish to have
-    a forked process pick up the Ant's settings, use the 
-    <a href="Types/propertyset.html"><code>&lt;syspropertyset&gt;</code></a>
-    element to propagate the normal proxy settings. The following propertyset
-    is a datatype which can be referenced in a <code>&lt;java&gt;</code> task to
-    pass down the current values.
-    
+  Any program that is executed with <code>&lt;java&gt;</code> without
+  setting <var>fork</var>=<q>true</q> will pick up the Ant's
+  settings. If you need different values,
+  set <var>fork</var>=<q>false</q> and provide the values
+  in <code>&lt;sysproperty&gt;</code> elements.
+</p>
+<p>
+  If you wish to have a forked process pick up the Ant's settings, use
+  the <a href="Types/propertyset.html"><code>&lt;syspropertyset&gt;</code></a>
+  element to propagate the normal proxy settings. The following
+  propertyset is a datatype which can be referenced in
+  a <code>&lt;java&gt;</code> task to pass down the current values.
 </p>
 <pre>
-&lt;propertyset id="proxy.properties">
-  &lt;propertyref prefix="java.net.useSystemProxies"/>
-  &lt;propertyref prefix="http."/>
-  &lt;propertyref prefix="https."/>
-  &lt;propertyref prefix="ftp."/>
-  &lt;propertyref prefix="socksProxy"/>
-&lt;/propertyset>
-</pre>
+&lt;propertyset id="proxy.properties"&gt;
+  &lt;propertyref prefix="java.net.useSystemProxies"/&gt;
+  &lt;propertyref prefix="http."/&gt;
+  &lt;propertyref prefix="https."/&gt;
+  &lt;propertyref prefix="ftp."/&gt;
+  &lt;propertyref prefix="socksProxy"/&gt;
+&lt;/propertyset&gt;</pre>
 
 <h3>Summary and conclusions</h3>
 <p>
-There are four ways to set up proxies in Ant.
+  There are four ways to set up proxies in Ant.
 </p>
 <ol>
-<li>With Ant1.7 and Java 1.5+ using the <code>-autoproxy</code> parameter.</li>
-<li>Via JVM system properties -set these in the ANT_ARGS environment variable.</li>
-<li>Via the &lt;setproxy&gt; task.</li>
-<li>Custom ProxySelector implementations</li>
+  <li>With Ant 1.7 and Java 5+ using the <kbd>-autoproxy</kbd> parameter.</li>
+  <li>Via JVM system properties&mdash;set these in the <code>ANT_ARGS</code> environment variable.</li>
+  <li>Via the <code>&lt;setproxy&gt;</code> task.</li>
+  <li>Custom ProxySelector implementations</li>
 </ol>
 <p>
-Proxy settings are automatically shared with Java programs started under Ant <i>
-that are not forked</i>; to pass proxy settings down to subsidiary programs, use
-a propertyset.
+  Proxy settings are automatically shared with Java programs started
+  under Ant <em>that are not forked</em>; to pass proxy settings down
+  to subsidiary programs, use a propertyset.
 </p>
 <p>
-Over time, we expect the Java 5+ proxy features to stabilize, and for Java code
-to adapt to them. However, given the fact that it currently does break some
-builds, it will be some time before Ant enables the automatic proxy feature by
-default. Until then, you have to enable the <code>-autoproxy</code> option or
-use one of the alternate mechanisms to configure the JVM.
+  Over time, we expect the Java 5+ proxy features to stabilize, and
+  for Java code to adapt to them. However, given the fact that it
+  currently does break some builds, it will be some time before Ant
+  enables the automatic proxy feature by default. Until then, you have
+  to enable the <kbd>-autoproxy</kbd> option or use one of the
+  alternate mechanisms to configure the JVM.
+</p>
 
 <h4>Further reading</h4>
 
 <ul>
-<li><a href="http://docs.oracle.com/javase/7/docs/technotes/guides/net/properties.html">
-Java Networking Properties</a>.
-</li>
+  <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html"
+         target="_top">Java Networking Properties</a>.</li>
 </ul>
 
 </body>
diff --git a/manual/running.html b/manual/running.html
index 8a39268..7248cd1 100644
--- a/manual/running.html
+++ b/manual/running.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Running Apache Ant</title>
 </head>
@@ -25,80 +25,74 @@
 <body>
 
 <h1>Running Apache Ant</h1>
-<h2><a name="commandline">Command Line</a></h2>
-<p> If you've installed Apache Ant as described in the
-<a href="install.html"> Installing Ant</a> section,
-running Ant from the command-line is simple: just type
-<code>ant</code>.</p>
-<p>When no arguments are specified, Ant looks for a <code>build.xml</code>
-file in the current directory and, if found, uses that file as the
-build file and runs the target specified in the <code>default</code>
-attribute of the <code>&lt;project&gt;</code> tag.
-To make Ant use
-a build file other than <code>build.xml</code>, use the command-line
-option <nobr><code>-buildfile <i>file</i></code></nobr>,
-where <i>file</i> is the name of the build file you want to use
-(or a directory containing a <code>build.xml</code> file).</p>
-If you use the <nobr><code>-find [<i>file</i>]</code></nobr> option,
-Ant will search for a build file first in the current directory, then in
-the parent directory, and so on, until either a build file is found or the root
-of the filesystem has been reached. By default, it will look for a build file
-called <code>build.xml</code>. To have it search for a build file other
-than <code>build.xml</code>, specify a file argument.
-<strong>Note:</strong> If you include any other flags or arguments
-on the command line after
-the <nobr><code>-find</code></nobr> flag, you must include the file argument
-for the <nobr><code>-find</code></nobr> flag, even if the name of the
-build file you want to find is <code>build.xml</code>.
+<h2 id="commandline">Command Line</h2>
 
-<p>You can also set <a href="using.html#properties">properties</a> on the
-command line.  This can be done with
-the <nobr><code>-D<i>property</i>=<i>value</i></code></nobr> option,
-where <i>property</i> is the name of the property,
-and <i>value</i> is the value for that property. If you specify a
-property that is also set in the build file
-(see the <a href="Tasks/property.html">property</a> task),
-the value specified on the
-command line will override the value specified in the
-build file.
-Defining properties on the command line can also be used to pass in
-the value of environment variables; just pass
-<nobr><code>-DMYVAR=%MYVAR%</code></nobr> (Windows) or
-<nobr><code>-DMYVAR=$MYVAR</code></nobr> (Unix)
-to Ant. You can then access
-these variables inside your build file as <code>${MYVAR}</code>.
-You can also access environment variables using the
-<a href="Tasks/property.html"> property</a> task's
-<code>environment</code> attribute.
-</p>
+<p>If you've installed Apache Ant as described in
+the <a href="install.html">Installing Ant</a> section, running Ant
+from the command-line is simple: just type <kbd>ant</kbd>.</p>
 
-<p>Options that affect the amount of logging output by Ant are:
-<nobr><code>-quiet</code></nobr>,
-which instructs Ant to print less
-information to the console;
-<nobr><code>-verbose</code></nobr>, which causes Ant to print
-additional information to the console; <nobr><code>-debug</code></nobr>,
-which causes Ant to print considerably more additional information; and
-<nobr><code>-silent</code></nobr> which makes Ant print nothing but task
-output and build failures (useful to capture Ant output by scripts).
-</p>
+<p>When no arguments are specified, Ant looks for
+a <samp>build.xml</samp> file in the current directory and, if found,
+uses that file as the build file and runs the target specified in
+the <var>default</var> attribute of the <code>&lt;project&gt;</code>
+tag.  To make Ant use a build file other than <samp>build.xml</samp>,
+use the command-line option <kbd>-buildfile <i>file</i></kbd>,
+where <code><i>file</i></code> is the name of the build file you want to use (or
+a directory containing a <samp>build.xml</samp> file).</p>
 
-<p>It is also possible to specify one or more targets that should be executed.
-When omitted, the target that is specified in the
-<code>default</code> attribute of the
-<a href="using.html#projects"><code>project</code></a> tag is
+<p>If you use the <kbd>-find [<i>file</i>]</kbd> option, Ant will
+search for a build file first in the current directory, then in the
+parent directory, and so on, until either a build file is found or the
+root of the filesystem has been reached. By default, it will look for
+a build file called <samp>build.xml</samp>. To have it search for a
+build file other than <samp>build.xml</samp>, specify a file
+argument. <strong>Note</strong>: If you include any other flags or
+arguments on the command line after the <kbd>-find</kbd> flag, you
+must include the file argument for the <kbd>-find</kbd> flag, even
+if the name of the build file you want to find
+is <samp>build.xml</samp>.</p>
+
+<p>You can also set <a href="using.html#properties">properties</a> on
+the command line.  This can be done with
+the <kbd>-D<i>property</i>=<i>value</i></kbd> option,
+where <em>property</em> is the name of the property,
+and <em>value</em> is the value for that property. If you specify a
+property that is also set in the build file (see
+the <a href="Tasks/property.html">property</a> task), the value
+specified on the command line will override the value specified in the
+build file.  Defining properties on the command line can also be used
+to pass in the value of environment variables; just
+pass <kbd>-DMYVAR=%MYVAR%</kbd> (Windows)
+or <kbd>-DMYVAR=$MYVAR</kbd> (Unix) to Ant. You can then access
+these variables inside your build file as <code>${MYVAR}</code>.  You
+can also access environment variables using
+the <a href="Tasks/property.html">property</a>
+task's <var>environment</var> attribute.</p>
+
+<p>Options that affect the amount of logging output by Ant
+are: <kbd>-quiet</kbd>, which instructs Ant to print less
+information to the console; <kbd>-verbose</kbd>, which causes Ant to
+print additional information to the console; <kbd>-debug</kbd>,
+which causes Ant to print considerably more additional information;
+and <kbd>-silent</kbd> which makes Ant print nothing but task output
+and build failures (useful to capture Ant output by scripts).</p>
+
+<p>It is also possible to specify one or more targets that should be
+executed. When omitted, the target that is specified in
+the <var>default</var> attribute of
+the <a href="using.html#projects"><code>project</code></a> tag is
 used.</p>
 
-<p>The <nobr><code>-projecthelp</code></nobr> option prints out a list
-of the build file's targets. Targets that include a
-<code>description</code> attribute are listed as &quot;Main targets&quot;,
-those without a <code>description</code> are listed as
-&quot;Other targets&quot;, then the &quot;Default&quot; target is listed
-("Other targets" are only displayed if there are no main
-targets, or if Ant is invoked in -verbose or -debug mode).
+<p>The <kbd>-projecthelp</kbd> option prints out a list of the build
+file's targets. Targets that include a <var>description</var>
+attribute are listed as &quot;Main targets&quot;, those without
+a <var>description</var> are listed as &quot;Other targets&quot;, then
+the &quot;Default&quot; target is listed ("Other targets" are only
+displayed if there are no main targets, or if Ant is invoked
+in <kbd>-verbose</kbd> or <kbd>-debug</kbd> mode).</p>
 
-<h3><a name="options">Command-line Options Summary</a></h3>
-<pre>ant [options] [target [target2 [target3] ...]]
+<h3 id="options">Command-line Options Summary</h3>
+<pre class="output">ant [options] [target [target2 [target3] ...]]
 Options:
   -help, -h              print this message and exit
   -projecthelp, -p       print project help information and exit
@@ -131,397 +125,387 @@
                          1 (lowest) to 10 (highest); 5 is the default
   -nouserlib             Run ant without using the jar files from ${user.home}/.ant/lib
   -noclasspath           Run ant without using CLASSPATH
-  -autoproxy             Java 1.5+ : use the OS proxies
+  -autoproxy             Java 5+ : use the OS proxies
   -main &lt;class&gt;          override Ant's normal entry point
 </pre>
-<p>For more information about <code>-logger</code> and
-<code>-listener</code> see
-<a href="listeners.html">Loggers &amp; Listeners</a>.
-<p>For more information about <code>-inputhandler</code> see
-<a href="inputhandler.html">InputHandler</a>.
-<p>Easiest way of changing the exit-behaviour is subclassing the original main class:
+<p>For more information about <kbd>-logger</kbd>
+and <kbd>-listener</kbd> see <a href="listeners.html">Loggers &amp;
+Listeners</a>.
+<p>For more information about <kbd>-inputhandler</kbd>
+see <a href="inputhandler.html">InputHandler</a>.
+<p>Easiest way of changing the exit-behaviour is subclassing the
+original main class:</p>
 <pre>
 public class CustomExitCode extends org.apache.tools.ant.Main {
     protected void exit(int exitCode) {
         // implement your own behaviour, e.g. NOT exiting the JVM
     }
 }
-</pre> and starting Ant with access (<tt>-lib path-to-class</tt>) to this class.
-</p>
+</pre>
+<p>and starting Ant with access (<kbd>-lib <i>path-to-class</i></kbd>)
+to this class.</p>
 
-<h3><a name="libs">Library Directories</a></h3>
-<p>
-Prior to Ant 1.6, all jars in the ANT_HOME/lib would be added to the CLASSPATH
-used to run Ant. This was done in the scripts that started Ant. From Ant 1.6,
-two directories are scanned by default and more can be added as required. The
-default directories scanned are ANT_HOME/lib and a user specific directory,
-${user.home}/.ant/lib. This arrangement allows the Ant installation to be
-shared by many users while still allowing each user to deploy additional jars.
-Such additional jars could be support jars for Ant's optional tasks or jars
-containing third-party tasks to be used in the build. It also allows the main Ant installation to be locked down which will please system administrators.
-</p>
+<h3 id="libs">Library Directories</h3>
 
-<p>
-Additional directories to be searched may be added by using the -lib option.
-The -lib option specifies a search path. Any jars or classes in the directories
-of the path will be added to Ant's classloader. The order in which jars are
-added to the classpath is as follows:
-</p>
+<p>Prior to Ant 1.6, all jars in the <samp>ANT_HOME/lib</samp> would
+be added to the <samp>CLASSPATH</samp> used to run Ant. This was done
+in the scripts that started Ant. <em>Since Ant 1.6</em>, two
+directories are scanned by default and more can be added as
+required. The default directories scanned
+are <samp>ANT_HOME/lib</samp> and a user specific
+directory, <samp>${user.home}/.ant/lib</samp>. This arrangement allows
+the Ant installation to be shared by many users while still allowing
+each user to deploy additional jars.  Such additional jars could be
+support jars for Ant's optional tasks or jars containing third-party
+tasks to be used in the build. It also allows the main Ant
+installation to be locked down which will please system
+administrators.</p>
+
+<p>Additional directories to be searched may be added by using
+the <kbd>-lib</kbd> option.  The <kbd>-lib</kbd> option specifies
+a search path. Any jars or classes in the directories of the path will
+be added to Ant's classloader. The order in which jars are added to
+the classpath is as follows:</p>
 
 <ul>
-  <li>-lib jars in the order specified by the -lib elements on the command line</li>
-  <li>jars from ${user.home}/.ant/lib (unless -nouserlib is set)</li>
-  <li>jars from ANT_HOME/lib</li>
+  <li>jars in the order specified by the <kbd>-lib</kbd> options on the command line</li>
+  <li>jars from <samp>${user.home}/.ant/lib</samp> (unless <kbd>-nouserlib</kbd> is set)</li>
+  <li>jars from <samp>ANT_HOME/lib</samp></li>
 </ul>
 
-<p>
-Note that the CLASSPATH environment variable is passed to Ant using a -lib
-option. Ant itself is started with a very minimalistic classpath.
-Ant should work perfectly well with an empty CLASSPATH environment variable,
-something the the -noclasspath option actually enforces. We get many more support calls related to classpath problems (especially quoting problems) than
-we like.
+<p>Note that the <code>CLASSPATH</code> environment variable is passed
+to Ant using a <kbd>-lib</kbd> option. Ant itself is started with a
+very minimalistic classpath.  Ant should work perfectly well with an
+empty <code>CLASSPATH</code> environment variable, something the
+the <kbd>-noclasspath</kbd> option actually enforces. We get many more
+support calls related to classpath problems (especially quoting
+problems) than we like.</p>
 
-</p>
-
-<p>
-The location of ${user.home}/.ant/lib is somewhat dependent on the JVM. On Unix
-systems ${user.home} maps to the user's home directory whilst on recent
-versions of Windows it will be somewhere such as
-C:\Documents&nbsp;and&nbsp;Settings\username\.ant\lib. You should consult your
-JVM documentation for more details.
-</p>
+<p>The location of <samp>${user.home}/.ant/lib</samp> is somewhat
+dependent on the JVM. On Unix systems <samp>${user.home}</samp> maps
+to the user's home directory whilst on recent versions of Windows it
+will be somewhere such
+as <code>C:\Users\<i>username</i>\.ant\lib</code>. You should consult
+your JVM documentation for more details.</p>
 
 <h3>Examples</h3>
-<blockquote>
-  <pre>ant</pre>
-</blockquote>
-<p>runs Ant using the <code>build.xml</code> file in the current directory, on
-the default target.</p>
 
-<blockquote>
-  <pre>ant -buildfile test.xml</pre>
-</blockquote>
-<p>runs Ant using the <code>test.xml</code> file in the current directory, on
-the default target.</p>
+<pre class="input">ant</pre>
+<p>runs Ant using the <samp>build.xml</samp> file in the current
+directory, on the default target.</p>
 
-<blockquote>
-  <pre>ant -buildfile test.xml dist</pre>
-</blockquote>
-<p>runs Ant using the <code>test.xml</code> file in the current directory, on
-the target called <code>dist</code>.</p>
+<pre class="input">ant -buildfile test.xml</pre>
+<p>runs Ant using the <samp>test.xml</samp> file in the current
+directory, on the default target.</p>
 
-<blockquote>
-  <pre>ant -buildfile test.xml -Dbuild=build/classes dist</pre>
-</blockquote>
-<p>runs Ant using the <code>test.xml</code> file in the current directory, on
-the target called <code>dist</code>, setting the <code>build</code> property
-to the value <code>build/classes</code>.</p>
+<pre class="input">ant -buildfile test.xml dist</pre>
+<p>runs Ant using the <samp>test.xml</samp> file in the current
+directory, on the target called <samp>dist</samp>.</p>
 
-<blockquote>
-  <pre>ant -lib /home/ant/extras</pre>
-</blockquote>
-<p>runs Ant picking up additional task and support jars from the
-/home/ant/extras location</p>
+<pre class="input">ant -buildfile test.xml -Dbuild=build/classes dist</pre>
+<p>runs Ant using the <samp>test.xml</samp> file in the current
+directory, on the target called <samp>dist</samp>, setting
+the <code>build</code> property to the value <q>build/classes</q>.</p>
 
-<blockquote>
-  <pre>ant -lib one.jar;another.jar</pre>
-  <pre>ant -lib one.jar -lib another.jar</pre>
-</blockquote>
+<pre class="input">ant -lib /home/ant/extras</pre>
+<p>runs Ant picking up additional task and support jars from
+the <samp>/home/ant/extras</samp> location</p>
+
+<pre class="input">ant -lib one.jar;another.jar</pre>
+<pre class="input">ant -lib one.jar -lib another.jar</pre>
 <p>adds two jars to Ants classpath.</p>
 
-
-
-<h3><a name="files">Files</a></h3>
+<h3 id="files">Files</h3>
 
 <p>The Ant wrapper script for Unix will source (read and evaluate) the
-file <code>~/.antrc</code> before it does anything. On Windows, the Ant
-wrapper batch-file invokes <code>%HOME%\antrc_pre.bat</code> at the start and
-<code>%HOME%\antrc_post.bat</code> at the end.  You can use these
-files, for example, to set/unset environment variables that should only be
-visible during the execution of Ant.  See the next section for examples.</p>
+file <samp>~/.antrc</samp> before it does anything. On Windows, the
+Ant wrapper batch-file invokes <samp>%HOME%\antrc_pre.bat</samp> at
+the start and <samp>%HOME%\antrc_post.bat</samp> at the end.  You can
+use these files, for example, to set/unset environment variables that
+should only be visible during the execution of Ant.  See the next
+section for examples.</p>
 
-<h3><a name="envvars">Environment Variables</a></h3>
+<h3 id="envvars">Environment Variables</h3>
 
-<p>The wrapper scripts use the following environment variables (if
-set):</p>
+<p>The wrapper scripts use the following environment variables (if set):</p>
 
 <ul>
-  <li><code>JAVACMD</code> - full path of the Java executable.  Use this
-  to invoke a different JVM than <code>JAVA_HOME/bin/java(.exe)</code>.</li>
+  <li><code>JAVACMD</code>&mdash;full path of the Java executable.  Use this
+  to invoke a different JVM than <samp>JAVA_HOME/bin/java(.exe)</samp>.</li>
 
-  <li><code>ANT_OPTS</code> - command-line arguments that should be
+  <li><code>ANT_OPTS</code>&mdash;command-line arguments that should be
   passed to the JVM. For example, you can define system properties or set
   the maximum Java heap size here.</li>
 
-  <li><code>ANT_ARGS</code> - Ant command-line arguments. For example,
+  <li><code>ANT_ARGS</code>&mdash;Ant command-line arguments. For example,
   set <code>ANT_ARGS</code> to point to a different logger, include a
-  listener, and to include the <code>-find</code> flag.</li>
-  <strong>Note:</strong> If you include <code>-find</code>
+  listener, and to include the <kbd>-find</kbd> flag.<br/>
+  <strong>Note</strong>: If you include <kbd>-find</kbd>
   in <code>ANT_ARGS</code>, you should include the name of the build file
-  to find, even if the file is called <code>build.xml</code>.
+  to find, even if the file is called <samp>build.xml</samp>.</li>
 </ul>
 
-<h3><a name="sysprops">Java System Properties</a></h3>
+<h3 id="sysprops">Java System Properties</h3>
 <p>Some of Ant's core classes can be configured via system properties.</p>
-<p>Here is the result of a search through the codebase. Because system properties are
-available via Project instance, I searched for them with a
-<pre>
-    grep -r -n "getPropert" * &gt; ..\grep.txt
-</pre>
-command. After that I filtered out the often-used but not-so-important values (most of them
-read-only values): <i>path.separator, ant.home, basedir, user.dir, os.name,
-line.separator, java.home, java.version, java.version, user.home, java.class.path</i><br>
-And I filtered out the <i>getPropertyHelper</i> access.</p>
-<table border="1">
+<p>Here is the result of a search through the codebase. Because system
+properties are available via Project instance, I searched for them with a</p>
+<pre class="input">grep -r -n "getPropert" * &gt; ..\grep.txt</pre>
+<p>command. After that I filtered out the often-used but
+not-so-important values (most of them read-only
+values): <code>path.separator</code>, <code>ant.home</code>, <code>basedir</code>,
+<code>user.dir</code>, <code>os.name</code>, <code>line.separator</code>,
+<code>java.home</code>, <code>java.version</code>, <code>java.version</code>,
+<code>user.home</code>, <code>java.class.path</code><br/>
+And I filtered out the <code>getPropertyHelper</code> access.</p>
+
+<table>
 <tr>
-  <th>property name</th>
-  <th>valid values /default value</th>
-  <th>description</th>
+  <th scope="col">property name</th>
+  <th scope="col">valid values/default value</th>
+  <th scope="col">description</th>
 </tr>
 <tr>
   <td><code>ant.build.javac.source</code></td>
   <td>Source-level version number</td>
-  <td>Default <em>source</em> value for &lt;javac&gt;/&lt;javadoc&gt;</td>
+  <td>Default <var>source</var> value
+  for <code>&lt;javac&gt;</code>/<code>&lt;javadoc&gt;</code></td>
 </tr>
 <tr>
   <td><code>ant.build.javac.target</code></td>
   <td>Class-compatibility version number</td>
-  <td>Default <em>target</em> value for &lt;javac&gt;</td>
+  <td>Default <var>target</var> value for <code>&lt;javac&gt;</code></td>
 </tr>
 <tr>
   <td><code>ant.executor.class</code></td>
-  <td>classname; default is org. apache. tools. ant. helper. DefaultExecutor</td>
-  <td><b>Since Ant 1.6.3</b> Ant will delegate Target invocation to the
-org.apache.tools.ant.Executor implementation specified here.
-  </td>
+  <td>classname; default is <q>org.<wbr>apache.<wbr>tools.<wbr>ant.<wbr>helper.<wbr>DefaultExecutor</q></td>
+  <td><em>Since Ant 1.6.3</em> Ant will delegate Target invocation to
+  the <code class="code">org.apache.tools.ant.Executor</code>
+  implementation specified here.</td>
 </tr>
-
-<tr>
+  <tr>
   <td><code>ant.file</code></td>
   <td>read only: full filename of the build file</td>
-  <td>This is set to the name of the build file. In
-  <a href="Tasks/import.html">
-  &lt;import&gt;-ed</a> files, this is set to the containing build file.
-  </td>
+  <td>This is set to the name of the build
+  file. In <a href="Tasks/import.html">&lt;import&gt;-ed</a> files,
+  this is set to the containing build file.</td>
 </tr>
-
-<tr>
+  <tr>
   <td><code>ant.file.*</code></td>
-  <td>read only: full filename of the build file of Ant projects
-  </td>
-  <td>This is set to the name of a file by project;
-  this lets you determine the location of <a href="Tasks/import.html">
-  &lt;import&gt;-ed</a> files,
-  </td>
+  <td>read only: full filename of the build file of Ant projects</td>
+  <td>This is set to the name of a file by project; this lets you
+  determine the location
+  of <a href="Tasks/import.html">&lt;import&gt;-ed</a> files.</td>
 </tr>
-
-<tr>
+  <tr>
   <td><code>ant.input.properties</code></td>
   <td>filename (required)</td>
-  <td>Name of the file holding the values for the
-      <a href="inputhandler.html">PropertyFileInputHandler</a>.
-  </td>
+  <td>Name of the file holding the values for
+  the <a href="inputhandler.html">PropertyFileInputHandler</a>.</td>
 </tr>
 <tr>
   <td><code>ant.logger.defaults</code></td>
-  <!-- add the blank after the slash, so the browser can do a line break -->
-  <td>filename (optional, default '/org/ apache/ tools/ ant/ listener/ defaults.properties')</td>
-  <td>Name of the file holding the color mappings for the
-      <a href="listeners.html#AnsiColorLogger">AnsiColorLogger</a>.
-  </td>
+  <td>filename (optional, default <q>/org/<wbr>apache/<wbr>tools/<wbr>ant/<wbr>listener/<wbr>defaults.properties</q>)</td>
+  <td>Name of the file holding the color mappings for
+  the <a href="listeners.html#AnsiColorLogger">AnsiColorLogger</a>.</td>
 </tr>
 <tr>
   <td><code>ant.netrexxc.*</code></td>
   <td>several formats</td>
-  <td>Use specified values as defaults for <a href="Tasks/netrexxc.html">netrexxc</a>.
-  </td>
+  <td>Use specified values as defaults
+  for <a href="Tasks/netrexxc.html">netrexxc</a>.</td>
 </tr>
 <tr>
   <td><code>ant.PropertyHelper</code></td>
-  <td>ant-reference-name (optional)</td>
-  <td>Specify the PropertyHelper to use. The object must be of the type
-      org.apache.tools.ant.PropertyHelper. If not defined an object of
-      org.apache.tools.ant.PropertyHelper will be used as PropertyHelper.
-  </td>
+  <td>Ant reference name (optional)</td>
+  <td>Specify the PropertyHelper to use. The object must be of the
+  type <code class="code">org.apache.tools.ant.PropertyHelper</code>. By
+  default, an object
+  of <code class="code">org.apache.tools.ant.PropertyHelper</code>
+  will be used as PropertyHelper.</td>
 </tr>
 <tr>
   <td><code>ant.regexp.regexpimpl</code></td>
   <td>classname</td>
-  <td>classname for a RegExp implementation; if not set Ant uses JDK 1.4's implementation;
-      <a href="Types/mapper.html#regexp-mapper">RegExp-Mapper</a>
-      "Choice of regular expression implementation"
-  </td>
+  <td>classname for a RegExp implementation; by default the <code>java.util.regex</code>
+  implementation; <a href="Types/mapper.html#regexp-mapper">RegExp
+  Mapper</a> "Choice of regular expression implementation".</td>
 </tr>
 <tr>
   <td><code>ant.reuse.loader</code></td>
   <td>boolean</td>
-  <td>allow to reuse classloaders
-      used in org.apache.tools.ant.util.ClasspathUtil
-  </td>
+  <td>allow to reuse classloaders used
+  in <code class="code">org.apache.tools.ant.util.ClasspathUtil</code>.</td>
 </tr>
 <tr>
   <td><code>ant.XmlLogger.stylesheet.uri</code></td>
-  <td>filename (default 'log.xsl')</td>
-  <td>Name for the stylesheet to include in the logfile by
-      <a href="listeners.html#XmlLogger">XmlLogger</a>.
-  </td>
+  <td>filename (default <q>log.xsl</q>)</td>
+  <td>Name for the stylesheet to include in the logfile
+  by <a href="listeners.html#XmlLogger">XmlLogger</a>.</td>
 </tr>
 <tr>
   <td><code>build.compiler</code></td>
   <td>name</td>
-  <td>Specify the default compiler to use.
-      see <a href="Tasks/javac.html">javac</a>,
-      <a href="Tasks/ejb.html#ejbjar_weblogic">EJB Tasks</a>
-      (compiler attribute),
-      <a href="Tasks/javah.html">javah</a>
-  </td>
+  <td>Specify the default compiler to use;
+  see <a href="Tasks/javac.html">javac</a>, <a href="Tasks/ejb.html#ejbjar_weblogic">EJB
+  Tasks</a> (<var>compiler</var>
+  attribute), <a href="Tasks/javah.html">javah</a>.</td>
 </tr>
 <tr>
   <td><code>build.compiler.emacs</code></td>
-  <td>boolean (default false)</td>
-  <td>Enable emacs-compatible error messages.
-      see <a href="Tasks/javac.html">javac</a> "Jikes Notes"
-  </td>
+  <td>boolean (default <q>false</q>)</td>
+  <td>Enable emacs-compatible error messages;
+  see <a href="Tasks/javac.html#jikes">javac</a> "Jikes Notes".</td>
 </tr>
 <tr>
   <td><code>build.compiler.fulldepend</code></td>
   <td>boolean (default false)</td>
-  <td>Enable full dependency checking
-      see <a href="Tasks/javac.html">javac</a> "Jikes Notes"
-  </td>
+  <td>Enable full dependency checking;
+  see <a href="Tasks/javac.html#jikes">javac</a> "Jikes Notes".</td>
 </tr>
 <tr>
   <td><code>build.compiler.jvc.extensions</code></td>
-  <td>boolean (default true)</td>
-  <td>enable Microsoft extensions of their java compiler
-      see <a href="Tasks/javac.html">javac</a> "Jvc Notes"
-  </td>
+  <td><em><u>Deprecated</u></em></td>
+  <td>Enable Microsoft extensions of their Java compiler;
+  see <a href="Tasks/javac.html#jvc">javac</a> "Jvc Notes".</td>
 </tr>
 <tr>
   <td><code>build.compiler.pedantic</code></td>
-  <td>boolean (default false)</td>
-  <td>Enable pedantic warnings.
-      see <a href="Tasks/javac.html">javac</a> "Jikes Notes"
-  </td>
+  <td>boolean (default <q>false</q>)</td>
+  <td>Enable pedantic warnings;
+  see <a href="Tasks/javac.html#jikes">javac</a> "Jikes Notes".</td>
 </tr>
 <tr>
   <td><code>build.compiler.warnings</code></td>
-  <td>Deprecated flag</td>
-  <td> see <a href="Tasks/javac.html">javac</a> "Jikes Notes" </td>
+  <td><em><u>Deprecated</u></em></td>
+  <td>See <a href="Tasks/javac.html#jikes">javac</a> "Jikes Notes"</td>
 </tr>
 <tr>
   <td><code>build.rmic</code></td>
   <td>name</td>
-  <td>control the <a href="Tasks/rmic.html">rmic</a> compiler </td>
+  <td>Control the <a href="Tasks/rmic.html">rmic</a> compiler</td>
 </tr>
 <tr>
   <td><code>build.sysclasspath</code></td>
-  <td>see <a href="sysclasspath.html">its dedicated page</a>, no
-    default value</td>
-  <td>see <a href="sysclasspath.html">its dedicated page</a></td>
+  <td>No default value</td>
+  <td>See <a href="sysclasspath.html">its dedicated page</a></td>
 </tr>
 <tr>
   <td><code>file.encoding</code></td>
   <td>name of a supported character set (e.g. UTF-8, ISO-8859-1, US-ASCII)</td>
-  <td>use as default character set of email messages; use as default for source-, dest- and bundleencoding
-      in <a href="Tasks/translate.html">translate</a> <br>
-      see JavaDoc of <a target="_blank" href="http://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">java.nio.charset.Charset</a>
-      for more information about character sets (not used in Ant, but has nice docs).
-  </td>
+  <td>use as default character set of email messages; use as default
+  for <var>srcencoding</var>, <var>destencoding</var>
+  and <var>bundleencoding</var>
+  in <a href="Tasks/translate.html">translate</a><br/> see JavaDoc
+  of <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html"
+  target="_top">java.nio.charset.Charset</a> for more information
+  about character sets (not used in Ant, but has nice docs).</td>
 </tr>
 <tr>
   <td><code>jikes.class.path</code></td>
   <td>path</td>
-  <td>The specified path is added to the classpath if jikes is used as compiler.</td>
+  <td>The specified path is added to the classpath if Jikes is used as compiler.</td>
 </tr>
 <tr>
-  <td><code>MailLogger.properties.file, MailLogger.*</code></td>
+  <td><code>MailLogger.properties.file</code>, <code>MailLogger.*</code></td>
   <td>filename (optional, defaults derived from Project instance)</td>
-  <td>Name of the file holding properties for sending emails by the
-      <a href="listeners.html#MailLogger">MailLogger</a>. Override properties set
-      inside the buildfile or via command line.
-  </td>
+  <td>Name of the file holding properties for sending emails by
+  the <a href="listeners.html#MailLogger">MailLogger</a>. Override
+  properties set inside the buildfile or via command line.</td>
 </tr>
 <tr>
   <td><code>org.apache.tools.ant.ProjectHelper</code></td>
-  <!-- add the blank after the slash, so the browser can do a line break -->
-  <td>classname (optional, default 'org.apache.tools.ant.ProjectHelper2')</td>
-  <td>specifies the classname to use as ProjectHelper. The class must extend
-      org.apache.tools.ant.ProjectHelper.
-  </td>
+  <td>classname (optional, default <q>org.<wbr>apache.<wbr>tools.<wbr>ant.<wbr>ProjectHelper2</q>)</td>
+  <td>specifies the classname to use as ProjectHelper. The class must
+  extend <code class="code">org.apache.tools.ant.ProjectHelper</code>.</td>
 </tr>
 <tr>
   <td><code>org.apache.tools.ant.ArgumentProcessor</code></td>
   <td>classname (optional)</td>
-  <td>specifies the classname to use as ArgumentProcessor. The class must extend
-      org.apache.tools.ant.ArgumentProcessor.
-  </td>
+  <td>specifies the classname to use as ArgumentProcessor. The class
+  must extend <code class="code">org.apache.tools.ant.ArgumentProcessor</code>.</td>
 </tr>
-
 <tr>
   <td><code>websphere.home</code></td>
   <td>path</td>
-  <td>Points to home directory of websphere.
-      see <a href="Tasks/ejb.html#ejbjar_websphere">EJB Tasks</a>
-  </td>
+  <td>Points to home directory of WebSphere;
+  see <a href="Tasks/ejb.html#ejbjar_websphere">EJB Tasks</a></td>
 </tr>
 <tr>
   <td><code>XmlLogger.file</code></td>
-  <td>filename (default 'log.xml')</td>
-  <td>Name for the logfile for <a href="listeners.html#MailLogger">MailLogger</a>.
-  </td>
+  <td>filename (default <q>log.xml</q>)</td>
+  <td>Name for the logfile
+  for <a href="listeners.html#MailLogger">MailLogger</a>.</td>
 </tr>
 <tr>
   <td><code>ant.project-helper-repo.debug</code></td>
-  <td>boolean (default 'false')</td>
-  <td>Set it to true to enable debugging with Ant's
-  <a href="projecthelper.html#repository">ProjectHelper internal repository</a>.
-  </td>
+  <td>boolean (default <q>false</q>)</td>
+  <td>Set it to <q>true</q> to enable debugging with
+  Ant's <a href="projecthelper.html#repository">ProjectHelper internal
+  repository</a>.</td>
 </tr>
 <tr>
   <td><code>ant.argument-processor-repo.debug</code></td>
-  <td>boolean (default 'false')</td>
-  <td>Set it to true to enable debugging with Ant's
-  <a href="argumentprocessor.html#repository">ArgumentProcessor internal repository</a>.
-  </td>
+  <td>boolean (default <q>false</q>)</td>
+  <td>Set it to <q>true</q> to enable debugging with
+  Ant's <a href="argumentprocessor.html#repository">ArgumentProcessor
+  internal repository</a>.</td>
 </tr>
 <tr>
   <td><code>ant.tstamp.now</code></td>
   <td>number, seconds since the epoch (midnight 1970-01-01)</td>
-  <td>The value to use as current time and date for &lt;tstamp&gt;</td>
+  <td rowspan="2">The value to use as current time and date
+  for <code>&lt;tstamp&gt;</code></td>
+</tr>
+<tr>
+  <td><code>ant.tstamp.now.iso</code></td>
+  <td>ISO-8601 timestamp string like <code>1972-04-17T08:07:00Z</code></td>
 </tr>
 <tr>
   <td><code>java.io.tmpdir</code></td>
+  <td>path</td>
   <td>Some tasks need to create temporary files and will write them to
   the directory specified by this property. This property is set by
   the Java VM but can be overridden when Ant is started.<br/>
   See also <a href="#tmpdir">Temporary Directories</a>.</td>
-</table>
+</tr>
 <tr>
   <td><code>ant.tmpdir</code></td>
-  <td><em>Since Ant 1.9.15</em><br/>
+  <td>path</td>
+  <td><em>Since Ant 1.10.8</em><br/>
   Some tasks need to create temporary files and will write them to
   the directory specified by this property. This property takes
   precedence over <code>java.io.tmpdir</code> if it has been
   set. Unlike <code>java.io.tmpdir</code> this property can be set
   from within the build file.<br/>
   See also <a href="#tmpdir">Temporary Directories</a>.</td>
+</tr>
+<tr>
+  <td><code>ant.disable.graal.nashorn.compat</code></td>
+  <td>boolean (default <q>false</q>)</td>
+  <td><em>Since Ant 1.10.9</em><br/>
+  By default Ant will enable GraalVM JavaScript's Nashorn
+  compatibility mode for <code>script</code> and friends. You can
+  disable this behavior by setting this property to <q>true</q>.<br/>
+  See also the <a href="Tasks/script.html">script task manual</a>.</td>
+</tr>
 </table>
 
 <p>
-If new properties get added (it happens), expect them to appear under the
-"ant." and "org.apache.tools.ant" prefixes, unless the developers have a
-very good reason to use another prefix. Accordingly, please avoid using
-properties that begin with these prefixes. This protects you from future
-Ant releases breaking your build file.
+If new properties get added (it happens), expect them to appear under
+the <code>ant.</code> and <code>org.apache.tools.ant.</code> prefixes,
+unless the developers have a very good reason to use another
+prefix. Accordingly, please avoid using properties that begin with
+these prefixes. This protects you from future Ant releases breaking
+your build file.
 </p>
 <h3>return code</h3>
-<p>the ant start up scripts (in their Windows and Unix version) return
-the return code of the java program. So a successful build returns 0,
-failed builds return other values.
+<p>
+Ant start up scripts (in their Windows and Unix version) return the
+return code of the <code>java</code> program. So a successful build
+returns <q>0</q>, failed builds return other values.
 </p>
 
-<h2><a name="tmpdir">Temporary Directories</a></h2>
+<h2 id="tmpdir">Temporary Directories</h2>
 
 Some Ant tasks and types need to create temporary files. By default
 they use the default temporary directory of the Java VM they are
@@ -535,7 +519,7 @@
   the <code>ant(.cmd)</code> wrapper scripts you can do so with the
   help of the <code>ANT_OPTS</code> environment variable.</p>
 
-<p>Starting with Ant 1.9.15 we've introduced a new Ant
+<p>Starting with Ant 1.10.8 we've introduced a new Ant
   property <code>ant.tmpdir</code> that takes precedence
   over <code>java.io.tmpdir</code> when set. As this is a normal Ant
   property it can be set via the command line or even from within a
@@ -546,38 +530,54 @@
   of an external command on OpenVMS will create a temporary file
   holding a DCL script that invokes the actual command.</p>
 
+<p>Starting with Ant 1.10.9 Ant will try to create a build process
+  specific temporary directory inside <code>java.io.tmpdir</code> with
+  permissions set to be accessible by the current user only and use
+  that if <code>ant.tmpdir</code> has not been set and Ant is able to
+  set permissions on the filesystem in question.</p>
+
 <p>Tasks not provided with the Ant distribution will ignore
-  the <code>ant.tmpdir</code> property and
+  the <code>ant.tmpdir</code> property or the process subdirectory and
   use <code>java.io.tmpdir</code> unless they have been adapted to the
-  changed API of Ant 1.9.15.</p>
+  changed API of Ant 1.10.8.</p>
 
 <p><b>Security Note:</b> Using the default temporary directory
 specified by <code>java.io.tmpdir</code> can result in the leakage of
 sensitive information or possibly allow an attacker to inject source
 files into the build process. This is especially true in multi-user
-is recommended that <code>ant.tmpdir</code> be set to a directory
-owned by the user running Ant with 0700 permissions.</p>
+environments. It is recommended that <code>ant.tmpdir</code> be set to
+a directory owned by the user running Ant with 0700 permissions. Ant
+1.10.8 and later will try to make temporary files created by it only
+readable/writable by the current user but may silently fail to do so
+depending on the OS and filesystem.</p>
 
-<h2><a name="cygwin">Cygwin Users</a></h2>
-<p>The Unix launch script that come with Ant works correctly with Cygwin. You
-should not have any problems launching Ant from the Cygwin shell. It is
-important to note, however, that once Ant is running it is part of the JDK
-which operates as a native Windows application. The JDK is not a Cygwin
-executable, and it therefore has no knowledge of Cygwin paths, etc. In
-particular when using the <code>&lt;exec&gt;</code> task, executable names such
-as &quot;/bin/sh&quot; will not work, even though these work from the Cygwin
-shell from which Ant was launched. You can use an executable name such as
-&quot;sh&quot; and rely on that command being available in the Windows path.
+<h2 id="cygwin">Cygwin Users</h2>
+<p>
+Unix launch script that come with Ant works correctly with Cygwin. You
+should not have any problems launching Ant from the Cygwin shell. It
+is important to note, however, that once Ant is running it is part of
+the JDK which operates as a native Windows application. The JDK is not
+a Cygwin executable, and it therefore has no knowledge of Cygwin
+paths, etc. In particular when using the <code>&lt;exec&gt;</code>
+task, executable names such as <q>/bin/sh</q> will not work, even
+though these work from the Cygwin shell from which Ant was
+launched. You can use an executable name such as <q>sh</q> and rely on
+that command being available in the Windows path.
+
+<h2 id="os2">OS/2 Users</h2>
+<p>
+The OS/2 launch script was developed to perform complex tasks. It has
+two parts: <kbd>ant.cmd</kbd> which calls Ant
+and <kbd>antenv.cmd</kbd> which sets the environment for Ant.  Most
+often you will just call <kbd>ant.cmd</kbd> using the same command
+line options as described above. The behaviour can be modified by a
+number of ways explained below.
 </p>
 
-<h2><a name="os2">OS/2 Users</a></h2>
-<p>The OS/2 launch script was developed to perform complex tasks. It has two parts:
-<code>ant.cmd</code> which calls Ant and <code>antenv.cmd</code> which sets the environment for Ant.
-Most often you will just call <code>ant.cmd</code> using the same command line options as described
-above. The behaviour can be modified by a number of ways explained below.</p>
-
-<p>Script <code>ant.cmd</code> first verifies whether the Ant environment is set correctly. The
-requirements are:</p>
+<p>
+Script <kbd>ant.cmd</kbd> first verifies whether the Ant environment
+is set correctly. The requirements are:
+</p>
 <ol>
 <li>Environment variable <code>JAVA_HOME</code> is set.</li>
 <li>Environment variable <code>ANT_HOME</code> is set.</li>
@@ -585,82 +585,94 @@
 <code>JAVA_HOME</code> and at least one element from <code>ANT_HOME</code>.</li>
 </ol>
 
-<p>If any of these conditions is violated, script <code>antenv.cmd</code> is called. This script
-first invokes configuration scripts if there exist: the system-wide configuration
-<code>antconf.cmd</code> from the <code>%ETC%</code> directory and then the user configuration
-<code>antrc.cmd</code> from the <code>%HOME%</code> directory. At this moment both
-<code>JAVA_HOME</code> and <code>ANT_HOME</code> must be defined because <code>antenv.cmd</code>
-now adds <code>classes.zip</code> or <code>tools.jar</code> (depending on version of JVM) and
-everything from <code>%ANT_HOME%\lib</code> except <code>ant-*.jar</code> to
-<code>CLASSPATH</code>. Finally <code>ant.cmd</code> calls per-directory configuration
-<code>antrc.cmd</code>. All settings made by <code>ant.cmd</code> are local and are undone when the
-script ends. The settings made by <code>antenv.cmd</code> are persistent during the lifetime of the
-shell (of course unless called automatically from <code>ant.cmd</code>). It is thus possible to call
-<code>antenv.cmd</code> manually and modify some settings before calling <code>ant.cmd</code>.</p>
-
-<p>Scripts <code>envset.cmd</code> and <code>runrc.cmd</code> perform auxiliary tasks. All scripts
-have some documentation inside.</p>
-
-<h2><a name="background">Running Ant as a background process on
-    Unix(-like) systems</a></h2>
-
-<p>If you start Ant as a background process (like in <code>ant
-    &amp;</code>) and the build process creates another process, Ant will
-    immediately try to read from standard input, which in turn will
-    most likely suspend the process.  In order to avoid this, you must
-    redirect Ant's standard input or explicitly provide input to each
-    spawned process via the input related attributes of the
-    corresponding tasks.</p>
-
-<p>Tasks that create such new processes
-  include <code>&lt;exec&gt;</code>, <code>&lt;apply&gt;</code>
-  or <code>&lt;java&gt;</code> when the <code>fork</code> attribute is
-  <code>true</code>.</p>
-
-<h2><a name="viajava">Running Ant via Java</a></h2>
-<p>If you have installed Ant in the do-it-yourself way, Ant can be started
-from one of two entry points:</p>
-<blockquote>
-  <pre>java -Dant.home=c:\ant org.apache.tools.ant.Main [options] [target]</pre>
-</blockquote>
-
-<blockquote>
-  <pre>java -Dant.home=c:\ant org.apache.tools.ant.launch.Launcher [options] [target]</pre>
-</blockquote>
+<p>
+If any of these conditions is violated, script <kbd>antenv.cmd</kbd>
+is called. This script first invokes configuration scripts if there
+exist: the system-wide configuration <kbd>antconf.cmd</kbd> from
+the <samp>%ETC%</samp> directory and then the user
+configuration <kbd>antrc.cmd</kbd> from the <samp>%HOME%</samp>
+directory. At this moment both <code>JAVA_HOME</code>
+and <code>ANT_HOME</code> must be defined
+because <kbd>antenv.cmd</kbd> now adds <samp>classes.zip</samp>
+or <samp>tools.jar</samp> (depending on version of JVM) and everything
+from <samp>%ANT_HOME%\lib</samp> except <samp>ant-*.jar</samp>
+to <code>CLASSPATH</code>. Finally <kbd>ant.cmd</kbd> calls
+per-directory configuration <kbd>antrc.cmd</kbd>. All settings made
+by <kbd>ant.cmd</kbd> are local and are undone when the script
+ends. The settings made by <kbd>antenv.cmd</kbd> are persistent
+during the lifetime of the shell (of course unless called
+automatically from <kbd>ant.cmd</kbd>). It is thus possible to
+call <kbd>antenv.cmd</kbd> manually and modify some settings before
+calling <kbd>ant.cmd</kbd>.
+</p>
 
 <p>
-The first method runs Ant's traditional entry point. The second method uses
-the Ant Launcher introduced in Ant 1.6. The former method does not support
-the -lib option and all required classes are loaded from the CLASSPATH. You must
-ensure that all required jars are available. At a minimum the CLASSPATH should
-include:
+Scripts <kbd>envset.cmd</kbd> and <kbd>runrc.cmd</kbd> perform
+auxiliary tasks. All scripts have some documentation inside.
+</p>
+
+<h2 id="background">Running Ant as a background process on Unix(-like) systems</h2>
+
+<p>
+If you start Ant as a background process (like in <kbd>ant
+&amp;</kbd>) and the build process creates another process, Ant will
+immediately try to read from standard input, which in turn will most
+likely suspend the process.  In order to avoid this, you must redirect
+Ant's standard input or explicitly provide input to each spawned
+process via the input related attributes of the corresponding tasks.
+</p>
+
+<p>
+Tasks that create such new processes
+include <code>&lt;exec&gt;</code>, <code>&lt;apply&gt;</code>
+or <code>&lt;java&gt;</code> when the <var>fork</var> attribute
+is <q>true</q>.
+</p>
+
+<h2 id="viajava">Running Ant via Java</h2>
+<p>
+If you have installed Ant in the do-it-yourself way, Ant can be
+started from one of two entry points:
+</p>
+
+<pre class="input">java -Dant.home=c:\ant org.apache.tools.ant.Main [options] [target]</pre>
+<pre class="input">java -Dant.home=c:\ant org.apache.tools.ant.launch.Launcher [options] [target]</pre>
+
+<p>
+The first method runs Ant's traditional entry point. The second method
+uses the Ant Launcher introduced in Ant 1.6. The former method does
+not support the <kbd>-lib</kbd> option and all required classes are
+loaded from the <code>CLASSPATH</code>. You must ensure that all
+required jars are available. At a minimum the <code>CLASSPATH</code>
+should include:
 </p>
 
 <ul>
-<li><code>ant.jar</code> and <code>ant-launcher.jar</code></li>
+<li><samp>ant.jar</samp> and <samp>ant-launcher.jar</samp></li>
 <li>jars/classes for your XML parser</li>
 <li>the JDK's required jar/zip files</li>
 </ul>
 
 <p>
-The latter method supports the -lib, -nouserlib, -noclasspath options and will
-    load jars from the specified ANT_HOME. You should start the latter with the most minimal
-classpath possible, generally just the ant-launcher.jar.
+The latter method supports
+the <kbd>-lib</kbd>, <kbd>-nouserlib</kbd>, <kbd>-noclasspath</kbd>
+options and will load jars from the
+specified <code>ANT_HOME</code>. You should start the latter with the
+most minimal classpath possible, generally just
+the <samp>ant-launcher.jar</samp>.
 </p>
 
-<a name="viaant"/>
-
+<p id="viaant">
 Ant can be started in Ant via the <code>&lt;java&gt;</code> command.
 Here is an example:
-
+</p>
 <pre>
-&lt;java
-        classname="org.apache.tools.ant.launch.Launcher"
-        fork="true"
-        failonerror="true"
-        dir="${sub.builddir}"
-        timeout="4000000"
-        taskname="startAnt"&gt;
+&lt;java classname="org.apache.tools.ant.launch.Launcher"
+      fork="true"
+      failonerror="true"
+      dir="${sub.builddir}"
+      timeout="4000000"
+      taskname="startAnt"&gt;
     &lt;classpath&gt;
         &lt;pathelement location="${ant.home}/lib/ant-launcher.jar"/&gt;
     &lt;/classpath&gt;
@@ -673,8 +685,6 @@
     &lt;arg value="${sub.target}"/&gt;
 &lt;/java&gt;
 </pre>
-<br>
-
 
 </body>
 </html>
diff --git a/manual/runninglist.html b/manual/runninglist.html
index e2b8010..a53d48d 100644
--- a/manual/runninglist.html
+++ b/manual/runninglist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -29,18 +29,16 @@
 
 <h3>Running Apache Ant</h3>
 <ul class="inlinelist">
-<li><a href="running.html#commandline">Command Line</a></li>
-<div style="padding-left:1em">
-  <li><a href="running.html#options">Options</a></li>
-  <li><a href="running.html#libs">Library Directories</a></li>
-  <li><a href="running.html#files">Files</a></li>
-  <li><a href="running.html#envvars">Environment Variables</a></li>
-  <li><a href="running.html#sysprops">Java System Properties</a></li>
-  <li><a href="running.html#cygwin">Cygwin Users</a></li>
-  <li><a href="running.html#os2">OS/2 Users</a></li>
-  <li><a href="running.html#background">Running "in the background"</a></li>
-</div>
-<li><a href="running.html#viajava">Running Ant via Java</a></li>
+  <li><a href="running.html#commandline">Command Line</a></li>
+  <li class="indent"><a href="running.html#options">Options</a></li>
+  <li class="indent"><a href="running.html#libs">Library Directories</a></li>
+  <li class="indent"><a href="running.html#files">Files</a></li>
+  <li class="indent"><a href="running.html#envvars">Environment Variables</a></li>
+  <li class="indent"><a href="running.html#sysprops">Java System Properties</a></li>
+  <li class="indent"><a href="running.html#cygwin">Cygwin Users</a></li>
+  <li class="indent"><a href="running.html#os2">OS/2 Users</a></li>
+  <li class="indent"><a href="running.html#background">Running "in the background"</a></li>
+  <li><a href="running.html#viajava">Running Ant via Java</a></li>
 </ul>
 
 </body>
diff --git a/manual/stylesheets/style.css b/manual/stylesheets/style.css
index cf26c60..83ee4bb 100644
--- a/manual/stylesheets/style.css
+++ b/manual/stylesheets/style.css
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,53 +15,187 @@
  *  limitations under the License.
  *
  */
+body {
+    font-family: "Palatino Linotype", Palatino, Georgia, "Century Schoolbook", serif;
+}
+
 h2 {
   font-size: 200%;
-  background-color: ffffff;
+  background-color: white;
 }
 
 h3 {
   font-size: 130%;
-  color:     #ffffff;
-  background-color: #525D76;
+  color: white;
+  background-color: #525d76;
 }
 
 h4 {
-  color:  #ffffff;
-  background-color: #828DA6;
+  color: white;
+  background-color: #828da6;
 }
 
-td {
-   background-color: eeeeee;
-   color:            000000;
+h5 {
+  font-size: 100%;
+  color: white;
+  background-color: #a6adbe;
+  margin-top: .5rem;
+  margin-bottom: .5rem;
 }
 
-/* first row */
-table tr:first-child td {
-   background-color: cccccc;
-   color:            000000;
+h6 {
+  font-size: 100%;
+  color: white;
+  background-color: #c1c5d1;
+  margin-top: .5rem;
+  margin-bottom: .5rem;
 }
 
-/* or th as first row */
-table th {
-   background-color: cccccc;
-   color:            000000;
+h5 + p, h6 + p {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+
+h3 > a, h4 > a, h5 > a, h6 > a {
+   color: white;
+}
+
+h3 > a:visited, h4 > a:visited, h5 > a:visited, h6 > a:visited,
+h3 > a:hover, h4 > a:hover, h5 > a:hover, h6 > a:hover {
+   color: lightskyblue;
+}
+
+var {
+    font-family: Verdana, Geneva, sans-serif;
+    font-size: 0.8rem;
+}
+
+q {
+    font-family: "Lucida Console", Monaco, monospace;
+    font-size: 0.8rem;
+}
+
+q.no-break {
+    white-space: nowrap;
+    hyphens: none;
+}
+
+code, samp, kbd {
+    white-space: nowrap;
+    hyphens: none;
+    font-size: 1.125rem;
+}
+
+h2 > code, h2 > samp {
+    font-size: 2rem;
+}
+
+h3 > code, h3 > samp {
+    font-size: 1.5rem;
+}
+
+h3 > var {
+    font-size: 1.125rem;
 }
 
 pre {
-   background-color: efefef;
+   background-color: #efefef;
+   margin-right: 4rem;
+   margin-left: 4rem;
+   font-size: 1.125rem;
+}
+
+pre var, code var {
+    font-size: 0.65rem;
 }
 
 /* code snippets in examples and tutorials */
-.code { 
-   background: #EFEFEF; 
-   margin-top: 
+.code {
+   background: #efefef;
+}
+
+/* highlight console input */
+.input, kbd {
+   color: white;
+   background: darkseagreen;
+   overflow: hidden;
+   text-overflow: ellipsis;
 }
 
 /* highlight console output */
-.output { 
-   color: #FFFFFF; 
-   background: #837A67; 
+.output {
+   color: white;
+   background: #837a67;
+   overflow: hidden;
+   text-overflow: ellipsis;
+}
+
+/* a workaround for invisible
+   (white on white) overflows */
+pre.input:hover, pre.output:hover {
+    margin-right: 0;
+    margin-left: 0;
+    overflow: scroll;
+    text-overflow: initial;
+}
+
+td {
+   vertical-align: top;
+   background-color: #eeeeee;
+   color: black;
+}
+
+tr:hover > td {
+    background-color: whitesmoke;
+}
+
+th {
+   background-color: silver;
+   color: black;
+   vertical-align: middle;
+}
+
+td pre {
+    margin: 0 0 0 0;
+    font-size: 1rem;
+}
+
+thead.no-bold th {
+    font-weight: normal;
+    white-space: nowrap;
+}
+
+table.attr {
+    width: 100%;
+}
+
+table.attr td:first-child {
+    font-family: Verdana, Geneva, sans-serif;
+    font-size: 0.8rem;
+    font-style: italic;
+}
+
+table.attr td:last-child {
+    text-align: center;
+}
+
+table.attr td.center, h1.center, p.center {
+    text-align: center;
+}
+
+table.attr td.left {
+    font-family: "Palatino Linotype", Palatino, Georgia, "Century Schoolbook", serif;
+    font-size: 1rem;
+    font-style: normal;
+    text-align: left;
+}
+
+table.attr td.var {
+    text-align: left;
+}
+
+td[rowspan] {
+   vertical-align: middle;
 }
 
 ul.inlinelist {
@@ -70,3 +204,60 @@
    padding: 0;
 }
 
+li.indent {
+    padding-left: 1rem;
+}
+
+div.float {
+    margin-top: 0.5rem;
+    width: 100%;
+    min-height: 1.5rem;
+    line-height: 1.5rem;
+    background-color: silver;
+}
+
+div.float + table {
+    width: 100%;
+    table-layout: fixed;
+}
+
+div.float + table th:first-child {
+    width: 20%;
+    white-space: nowrap;
+}
+
+div.float + table tr:first-child {
+    width: 20%;
+    white-space: nowrap;
+}
+
+span.left {
+    float: left;
+    font-family: Verdana, Geneva, sans-serif;
+    font-weight: bold;
+}
+
+span.right {
+    float: right;
+}
+
+span.left, span.right {
+    vertical-align: middle;
+    background-color: silver;
+}
+
+ol.refs {
+    counter-reset: refs;
+}
+
+ol.refs > li {
+    list-style: none;
+    position: relative;
+}
+
+ol.refs > li:before {
+    content: "[" counter(refs, decimal) "]";
+    counter-increment: refs;
+    position: absolute;
+    left: -2rem;
+}
diff --git a/manual/sysclasspath.html b/manual/sysclasspath.html
index 5efb208..c76ff87 100644
--- a/manual/sysclasspath.html
+++ b/manual/sysclasspath.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,28 +15,27 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>build.sysclasspath</title>
 </head>
 
 <body>
 
-<h2><a name="sysclasspath">build.sysclasspath</a></h2>
-<p>The value of the build.sysclasspath property
+<h2 id="sysclasspath">build.sysclasspath</h2>
+<p>The value of the <code>build.sysclasspath</code> property
 controls how the system classpath, i.e. the classpath in effect when
 Apache Ant is run, affects the behavior of classpaths in Ant.
 The default behavior varies from task to task.</p>
 
 The values and their meanings are:
 
-<table cellspacing="20">
-<tr><th>value</th><th>meaning</th></tr>
+<table>
+<tr><th scope="col">value</th><th scope="col">meaning</th></tr>
 <tr>
-<td align="left" valign="top">only</td>
+<td>only</td>
 <td>Only the system classpath is used and classpaths specified in build files,
 etc are ignored. This situation could be considered as the person running
 the build file knows more about the environment than the person writing the
@@ -44,7 +44,7 @@
 </tr>
 
 <tr>
-<td align="left" valign="top">ignore</td>
+<td>ignore</td>
 <td>
 The system classpath is ignored. This situation is the reverse of the
 above. The person running the build trusts the build file writer to get the
@@ -53,7 +53,7 @@
 </tr>
 
 <tr>
-<td align="left" valign="top">last</td>
+<td>last</td>
 <td>
 The classpath is concatenated to any specified classpaths at the end. This
 is a compromise, where the build file writer has priority.
@@ -61,7 +61,7 @@
 </tr>
 
 <tr>
-<td align="left" valign="top">first</td>
+<td>first</td>
 <td>
 Any specified classpaths are concatenated to the system classpath. This is
 the other form of compromise where the build runner has priority.
@@ -70,9 +70,9 @@
 </table>
 
 <p><em>Since Ant 1.7</em> the value of this property also affects the
-bootclasspath settings--it combines the bootclasspath that has been
-specified for a task with the bootclasspath of the Java VM running
-Ant.  If the property has not been set, it defaults to "ignore" in
+bootclasspath settings&mdash;it combines the bootclasspath that has been
+specified for a task with the bootclasspath of the JVM running
+Ant.  If the property has not been set, it defaults to <q>ignore</q> in
 this case.</p>
 
 </body>
diff --git a/manual/targets.html b/manual/targets.html
index a778c95..4cd0240 100644
--- a/manual/targets.html
+++ b/manual/targets.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,18 +15,17 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-  <meta http-equiv="Content-Language" content="en-us"/>
   <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
   <title>Targets and Extension-Points</title>
 </head>
 
 <body>
-  <h1><a name="targets">Targets</a></h1>
+  <h1 id="targets">Targets</h1>
 
-  <p>A target is a container of tasks that cooperate to reach a
+  <p>A target is a container of tasks and datatypes that cooperate to reach a
     desired state during the build process.</p>
 
   <p>Targets can depend on other targets and Apache Ant ensures that these
@@ -33,27 +33,25 @@
     example you might have a target for compiling and a
     target for creating a distributable. You can only build a
     distributable when you have compiled first, so the distribute
-    target <i>depends on</i> the compile target.</p>
+    target <em>depends on</em> the compile target.</p>
 
-  <p>Ant tries to execute the targets in the <code>depends</code>
+  <p>Ant tries to execute the targets in the <var>depends</var>
     attribute in the order they appear (from left to right). Keep in
     mind that it is possible that a target can get executed earlier
     when an earlier target depends on it:</p>
 
-<blockquote>
-<pre>&lt;target name=&quot;A&quot;/&gt;
+  <pre>&lt;target name=&quot;A&quot;/&gt;
 &lt;target name=&quot;B&quot; depends=&quot;A&quot;/&gt;
 &lt;target name=&quot;C&quot; depends=&quot;B&quot;/&gt;
 &lt;target name=&quot;D&quot; depends=&quot;C,B,A&quot;/&gt;</pre>
-</blockquote>
 
   <p>Suppose we want to execute target D. From its
-    <code>depends</code> attribute, you might think that first target
+    <var>depends</var> attribute, you might think that first target
     C, then B and then A is executed.  Wrong! C depends on B, and B
     depends on A, so first A is executed, then B, then C, and finally
     D.</p>
-    
-  <blockquote><pre><b>Call-Graph:</b>  A --> B --> C --> D</pre></blockquote>
+
+  <pre><b>Call-Graph:</b>  A &rarr; B &rarr; C &rarr; D</pre>
 
   <p>In a chain of dependencies stretching back from a given target
     such as D above, each target gets executed only once, even when
@@ -61,7 +59,7 @@
     will first result in C being called, which in turn will first call
     B, which in turn will first call A. After A, then B, then C have
     executed, execution returns to the dependency list of D, which
-    will <u>not</u> call B and A, since they were already called in
+    will <strong>not</strong> call B and A, since they were already called in
     process of dependency resolution for C and B respectively as
     dependencies of D. Had no such dependencies been discovered in
     processing C and B, B and A would have been executed after C in
@@ -70,9 +68,9 @@
   <p>A target also has the ability to perform its execution if (or
     unless) a property has been set. This allows, for example, better
     control on the building process depending on the state of the
-    system (java version, OS, command-line property defines, etc.).
-    To make a target <i>sense</i> this property, you should add
-    the <code>if</code> (or <code>unless</code>) attribute with the
+    system (Java version, OS, command-line property defines, etc.).
+    To make a target <em>sense</em> this property, you should add
+    the <var>if</var> (or <var>unless</var>) attribute with the
     name of the property that the target should react
     to. <strong>Note:</strong> In the most simple case Ant will only
     check whether the property has been set, the value doesn't matter,
@@ -81,25 +79,24 @@
     <a href="properties.html#if+unless">the properties page</a> for
     more details.  For example:</p>
 
-<blockquote>
   <pre>&lt;target name=&quot;build-module-A&quot; if=&quot;module-A-present&quot;/&gt;</pre>
   <pre>&lt;target name=&quot;build-own-fake-module-A&quot; unless=&quot;module-A-present&quot;/&gt;</pre>
-</blockquote>
 
   <p>In the first example, if the <code>module-A-present</code>
-    property is set (to any value, e.g. <i>false</i>), the target will
+    property is set (to any value, e.g. <q>false</q>), the target will
     be run. In the second example, if
     the <code>module-A-present</code> property is set (again, to any
     value), the target will not be run.</p>
 
-  <p>Only one propertyname can be specified in the if/unless
-    clause. If you want to check multiple conditions, you can use a
-    dependent target for computing the result for the check:</p>
+  <p>Only one property name can be specified in
+    the <var>if</var>/<var>unless</var> attribute. If you want to
+    check multiple conditions, you can use a dependent target for
+    computing the result for the check:</p>
 
-<blockquote><pre>
+<pre>
 &lt;target name="myTarget" depends="myTarget.check" if="myTarget.run"&gt;
     &lt;echo&gt;Files foo.txt and bar.txt are present.&lt;/echo&gt;
-&lt/target&gt;
+&lt;/target&gt;
 
 &lt;target name="myTarget.check"&gt;
     &lt;condition property="myTarget.run"&gt;
@@ -108,162 +105,163 @@
             &lt;available file="bar.txt"/&gt;
         &lt;/and&gt;
     &lt;/condition&gt;
-&lt/target&gt;
-</pre></blockquote>
+&lt;/target&gt;</pre>
 
-  <blockquote><pre><b>Call-Graph:</b>  myTarget.check --> maybe(myTarget)</pre></blockquote>
+  <pre><b>Call-Graph:</b>  myTarget.check &rarr; maybe(myTarget)</pre>
 
-  <p>If no <code>if</code> and no <code>unless</code> attribute is
+  <p>If no <var>if</var> and no <var>unless</var> attribute is
     present, the target will always be executed.</p>
 
-  <p><b>Important:</b> the <code>if</code> and <code>unless</code>
+  <p><strong>Important</strong>: the <var>if</var> and <var>unless</var>
     attributes only enable or disable the target to which they are
     attached. They do not control whether or not targets that a
     conditional target depends upon get executed.  In fact, they do
     not even get evaluated until the target is about to be executed,
     and all its predecessors have already run.
 
-  <p>The optional <code>description</code> attribute can be used to
+  <p>The optional <var>description</var> attribute can be used to
     provide a one-line description of this target, which is printed by
-    the <code>-projecthelp</code> command-line option. Targets without
+    the <kbd>-projecthelp</kbd> command-line option. Targets without
     such a description are deemed internal and will not be listed,
-    unless either the <code>-verbose</code> or <code>-debug</code>
+    unless either the <kbd>-verbose</kbd> or <kbd>-debug</kbd>
     option is used.</p>
 
   <p>It is a good practice to place
     your <a href="Tasks/tstamp.html">tstamp</a> tasks in a
-    so-called <i>initialization</i> target, on which all other targets
+    so-called <em>initialization</em> target, on which all other targets
     depend. Make sure that target is always the first one in the
     depends list of the other targets. In this manual, most
     initialization targets have the name <code>&quot;init&quot;</code>.</p>
-    <blockquote><pre>
-    &lt;project&gt;
-        &lt;target name=&quot;init&quot;&gt;
-            &lt;tstamp/&gt;
-        &lt;/target&gt;
-        &lt;target name=&quot;otherTarget&quot; depends=&quot;init&quot;&gt;
-            ...
-        &lt;/target&gt;
-    &lt;/project&gt;
-    </pre></blockquote>
+    <pre>
+&lt;project&gt;
+    &lt;target name=&quot;init&quot;&gt;
+        &lt;tstamp/&gt;
+    &lt;/target&gt;
+    &lt;target name=&quot;otherTarget&quot; depends=&quot;init&quot;&gt;
+        ...
+    &lt;/target&gt;
+&lt;/project&gt;</pre>
 
   <p>Especially if you only have a few tasks you also could place these
-    tasks directly under the project tag (since Ant 1.6.0):</p>
-    <blockquote><pre>
-    &lt;project&gt;
-        &lt;tstamp/&gt;
-    &lt;/project&gt;
-    </pre></blockquote>
+    tasks directly under the project tag (<em>since Ant 1.6.0</em>):</p>
+  <pre>
+&lt;project&gt;
+    &lt;tstamp/&gt;
+&lt;/project&gt;</pre>
 
-  <p>If the depends attribute and the if/unless attribute are set, the
-    depends attribute is executed first.</p>
+  <p>If the <var>depends</var> attribute and
+  the <var>if</var>/<var>unless</var> attribute are set,
+  the <var>depends</var> attribute is executed first.</p>
 
   <p>A target has the following attributes:</p>
 
-  <table border="1" cellpadding="2" cellspacing="0">
+  <table class="attr">
     <tr>
-      <td valign="top"><b>Attribute</b></td>
-      <td valign="top"><b>Description</b></td>
-      <td align="center" valign="top"><b>Required</b></td>
+      <th scope="col">Attribute</th>
+      <th scope="col">Description</th>
+      <th scope="col">Required</th>
     </tr>
     <tr>
-      <td valign="top">name</td>
-      <td valign="top">the name of the target.</td>
-      <td align="center" valign="top">Yes</td>
+      <td>name</td>
+      <td>the name of the target.</td>
+      <td>Yes</td>
     </tr>
     <tr>
-      <td valign="top">depends</td>
-      <td valign="top">a comma-separated list of names of targets on
+      <td>depends</td>
+      <td>a comma-separated list of names of targets on
         which this target depends.</td>
-      <td align="center" valign="top">No</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">if</td>
-      <td valign="top">the name of the property that must be set in
+      <td>if</td>
+      <td>the name of the property that must be set in
         order for this target to execute,
         or <a href="properties.html#if+unless">something evaluating to
-          true</a>.</td>
-      <td align="center" valign="top">No</td>
+          <q>true</q></a>.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">unless</td>
-      <td valign="top">the name of the property that must not be set
+      <td>unless</td>
+      <td>the name of the property that must not be set
         in order for this target to execute,
         or <a href="properties.html#if+unless">something evaluating to
-        false</a>.</td>
-      <td align="center" valign="top">No</td>
+        <q>false</q></a>.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">description</td>
-      <td valign="top">a short description of this target's function.</td>
-      <td align="center" valign="top">No</td>
+      <td>description</td>
+      <td>a short description of this target's function.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">extensionOf</td>
-      <td valign="top">Adds the current target to the depends list of
+      <td>extensionOf</td>
+      <td>Adds the current target to the depends list of
         the named <a href="#extension-points">extension-point</a>.
-        <em>since Ant 1.8.0.</em></td>
-      <td align="center" valign="top">No</td>
+        <em>since Ant 1.8.0</em>.</td>
+      <td>No</td>
     </tr>
     <tr>
-      <td valign="top">onMissingExtensionPoint</td>
-      <td valign="top">What to do if this target tries to extend a
+      <td>onMissingExtensionPoint</td>
+      <td>What to do if this target tries to extend a
         missing
-        <a href="#extension-points">extension-point</a>. ("fail",
-        "warn", "ignore").
-        <em>since Ant 1.8.2.</em></td>
-      <td align="center" valign="top">No. Not allowed unless
-        <code>extensionOf</code> is present. Defaults to <code>fail</code>. 
+        <a href="#extension-points">extension-point</a>. (<q>fail</q>,
+        <q>warn</q>, <q>ignore</q>).
+        <em>since Ant 1.8.2</em>.</td>
+      <td>No; not allowed unless
+        <var>extensionOf</var> is present, defaults to <q>fail</q>.
       </td>
     </tr>
   </table>
 
   <p>A target name can be any alphanumeric string valid in the
-    encoding of the XML file. The empty string &quot;&quot; is in this
-    set, as is comma &quot;,&quot; and space &quot; &quot;.  Please
-    avoid using these, as they will not be supported in future Ant
-    versions because of all the confusion they cause on command line and IDE. IDE support of
-    unusual target names, or any target name containing spaces, varies
-    with the IDE.</p>
+    encoding of the XML file. The empty string <q></q> is in this set,
+    as is comma <q>,</q> and space <q>&nbsp;</q>. Please avoid using
+    these, as they will not be supported in future Ant versions
+    because of all the confusion they cause on command line and
+    IDE. IDE support of unusual target names, or any target name
+    containing spaces, varies with the IDE.</p>
 
-  <p>Targets beginning with a hyphen such
-    as <code>&quot;-restart&quot;</code> are valid, and can be used to
-    name targets that should not be called directly from the command
-    line. <br>
-    For Ants main class every option starting with hyphen is an
-    option for Ant itself and not a target. For that reason calling these
-    target from command line is not possible. On the other hand IDEs usually
-    don't use Ants main class as entry point and calling them from the IDE
-    is usually possible.</p>
+  <p>Targets beginning with a hyphen such as <q>-restart</q> are
+    valid, and can be used to name targets that should not be called
+    directly from the command line.<br/>
+    For Ant's main class every option starting with hyphen is an
+    option for Ant itself and not a target. For that reason calling
+    these targets from command line is not possible. On the other
+    hand, IDEs usually don't use Ant's main class as entry point and
+    calling them from the IDE is usually possible.</p>
 
-  <h1><a name="extension-points">Extension-Points</a></h1>
+  <h1 id="extension-points">Extension-Points</h1>
 
-  <p><em>since Ant 1.8.0.</em></p>
+  <p><em>Since Ant 1.8.0</em>.</p>
 
-  <p>Extension-Points are similar to targets in that they have a name and
-    a depends list and can be executed from the command line.  Just
-    like targets they represent a state during the build process.</p>
+  <p>Extension-Points are similar to targets in that they have a name
+    and a <var>depends</var> list and can be executed from the command
+    line.  Just like targets they represent a state during the build
+    process.</p>
 
   <p>Unlike targets they don't contain any tasks, their main purpose
     is to collect targets that contribute to the desired state in
-    their depends list.</p>
+    their <var>depends</var> list.</p>
 
-  <p>Targets can add themselves to an extension-points's depends list via
-    their extensionOf attribute.  The targets that add themselves will be
-    added after the targets of the explicit depends-attribute of the
-    extension-point, if multiple targets add themselves, their relative
-    order is not defined.</p>
+  <p>Targets can add themselves to an
+    extension-point's <var>depends</var> list via
+    their <var>extensionOf</var> attribute.  The targets that add
+    themselves will be added after the targets of the
+    explicit <var>depends</var> attribute of the extension-point, if
+    multiple targets add themselves, their relative order is not
+    defined.</p>
 
   <p>The main purpose of an extension-point is to act as an extension
     point for build files designed to
     be <a href="Tasks/import.html">imported</a>.  In the imported
-    file an extension-point defines a state that must be reached and
-    targets from other build files can join the depends list of said
-    extension-point in order to contribute to that state.</p>
+    file, an extension-point defines a state that must be reached and
+    targets from other build files can join the <var>depends</var>
+    list of said extension-point in order to contribute to that
+    state.</p>
 
   <p>For example your imported build file may need to compile code, it
     might look like:</p>
-<blockquote><pre>
+<pre>
 &lt;target name="create-directory-layout"&gt;
    ...
 &lt;/target&gt;
@@ -271,30 +269,26 @@
               depends="create-directory-layout"/&gt;
 &lt;target name="compile" depends="ready-to-compile"&gt;
    ...
-&lt;/target&gt;
-</pre></blockquote>
+&lt;/target&gt;</pre>
 
-  <blockquote><pre><b>Call-Graph:</b>  create-directory-layout --> 'empty slot' --> compile</pre></blockquote>
-
+  <pre><b>Call-Graph:</b>  create-directory-layout &rarr; 'empty slot' &rarr; compile</pre>
 
   <p>And you need to generate some source before compilation, then in
     your main build file you may use something like</p>
-<blockquote><pre>
+<pre>
 &lt;target name="generate-sources"
         extensionOf="ready-to-compile"&gt;
    ...
-&lt;/target&gt;
-</pre></blockquote>
+&lt;/target&gt;</pre>
 
-  <blockquote><pre><b>Call-Graph:</b>  create-directory-layout --> generate-sources  --> compile</pre></blockquote>
+  <pre><b>Call-Graph:</b>  create-directory-layout &rarr; generate-sources  &rarr; compile</pre>
 
-
-  <p>This will ensure that the <em>generate-sources</em> target is
-    executed before the <em>compile</em> target.</p>
+  <p>This will ensure that the <q>generate-sources</q> target is
+    executed before the <q>compile</q> target.</p>
 
   <p>Don't rely on the order of the depends list,
-    if <em>generate-sources</em> depends
-    on <em>create-directory-layout</em> then it must explicitly depend
+    if <q>generate-sources</q> depends
+    on <q>create-directory-layout</q> then it must explicitly depend
     on it via its own depends attribute.</p>
 </body>
 </html>
diff --git a/manual/tasklist.html b/manual/tasklist.html
index 6578e55..553afb3 100644
--- a/manual/tasklist.html
+++ b/manual/tasklist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -34,162 +34,166 @@
 
 <h3>Tasks</h3>
 <ul class="inlinelist">
-<li><a href="Tasks/ant.html">Ant</a></li>
-<li><a href="Tasks/antcall.html">AntCall</a></li>
-<li><a href="Tasks/antlr.html">ANTLR</a></li>
-<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>
-<li><a href="Tasks/basename.html">Basename</a></li>
-<li><a href="Tasks/bindtargets.html">Bindtargets</a></li>
-<li><a href="Tasks/buildnumber.html">BuildNumber</a></li>
-<li><a href="Tasks/unpack.html">BUnzip2</a></li>
-<li><a href="Tasks/pack.html">BZip2</a></li>
-<li><a href="Tasks/cab.html">Cab</a></li>
-<li><a href="Tasks/ccm.html">Continuus/Synergy Tasks</a></li>
-<li><a href="Tasks/changelog.html">CvsChangeLog</a></li>
-<li><a href="Tasks/checksum.html">Checksum</a></li>
-<li><a href="Tasks/chgrp.html">Chgrp</a></li>
-<li><a href="Tasks/chmod.html">Chmod</a></li>
-<li><a href="Tasks/chown.html">Chown</a></li>
-<li><a href="Tasks/clearcase.html">Clearcase Tasks</a></li>
-<li><a href="Tasks/componentdef.html">Componentdef</a></li>
-<li><a href="Tasks/concat.html">Concat</a></li>
-<li><a href="Tasks/condition.html">Condition</a></li>
-<div style="padding-left:1em">
-  <li><a href="Tasks/conditions.html">Supported conditions</a></li>
-</div>
-<li><a href="Tasks/copy.html">Copy</a></li>
-<li><a href="Tasks/copydir.html"><i>Copydir</i></a></li>
-<li><a href="Tasks/copyfile.html"><i>Copyfile</i></a></li>
-<li><a href="Tasks/cvs.html">Cvs</a></li>
-<li><a href="Tasks/cvspass.html">CVSPass</a></li>
-<li><a href="Tasks/cvstagdiff.html">CvsTagDiff</a></li>
-<li><a href="Tasks/cvsversion.html">CvsVersion</a></li>
-<li><a href="Tasks/defaultexcludes.html">Defaultexcludes</a></li>
-<li><a href="Tasks/delete.html">Delete</a></li>
-<li><a href="Tasks/deltree.html"><i>Deltree</i></a></li>
-<li><a href="Tasks/depend.html">Depend</a></li>
-<li><a href="Tasks/dependset.html">Dependset</a></li>
-<li><a href="Tasks/diagnostics.html">Diagnostics</a></li>
-<li><a href="Tasks/dirname.html">Dirname</a></li>
-<li><a href="Tasks/ear.html">Ear</a></li>
-<li><a href="Tasks/echo.html">Echo</a></li>
-<li><a href="Tasks/echoproperties.html">Echoproperties</a></li>
-<li><a href="Tasks/echoxml.html">EchoXML</a></li>
-<li><a href="Tasks/ejb.html">EJB Tasks</a></li>
-<li><a href="Tasks/exec.html">Exec</a></li>
-<li><a href="Tasks/fail.html">Fail</a></li>
-<li><a href="Tasks/filter.html">Filter</a></li>
-<li><a href="Tasks/fixcrlf.html">FixCRLF</a></li>
-<li><a href="Tasks/ftp.html">FTP</a></li>
-<li><a href="Tasks/genkey.html">GenKey</a></li>
-<li><a href="Tasks/get.html">Get</a></li>
-<li><a href="Tasks/unpack.html">GUnzip</a></li>
-<li><a href="Tasks/pack.html">GZip</a></li>
-<li><a href="Tasks/hostinfo.html">Hostinfo</a></li>
-<li><a href="Tasks/image.html">Image</a></li>
-<li><a href="Tasks/import.html">Import</a></li>
-<li><a href="Tasks/include.html">Include</a></li>
-<li><a href="Tasks/input.html">Input</a></li>
-<li><a href="Tasks/jar.html">Jar</a></li>
-<li><a href="Tasks/jarlib-available.html">Jarlib-available</a></li>
-<li><a href="Tasks/jarlib-display.html">Jarlib-display</a></li>
-<li><a href="Tasks/jarlib-manifest.html">Jarlib-manifest</a></li>
-<li><a href="Tasks/jarlib-resolve.html">Jarlib-resolve</a></li>
-<li><a href="Tasks/java.html">Java</a></li>
-<li><a href="Tasks/javac.html">Javac</a></li>
-<li><a href="Tasks/javacc.html">JavaCC</a></li>
-<li><a href="Tasks/javadoc.html">Javadoc/<i>Javadoc2</i></a></li>
-<li><a href="Tasks/javah.html">Javah</a></li>
-<li><a href="Tasks/jdepend.html">JDepend</a></li>
-<li><a href="Tasks/jjdoc.html">JJDoc</a></li>
-<li><a href="Tasks/jjtree.html">JJTree</a></li>
-<li><a href="Tasks/jlink.html"><i>Jlink</i></a></li>
-<li><a href="Tasks/jspc.html">JspC</a></li>
-<li><a href="Tasks/junit.html">JUnit</a></li>
-<li><a href="Tasks/junitreport.html">JUnitReport</a></li>
-<li><a href="Tasks/length.html">Length</a><br/></li>
-<li><a href="Tasks/loadfile.html">LoadFile</a></li>
-<li><a href="Tasks/loadproperties.html">LoadProperties</a></li>
-<li><a href="Tasks/loadresource.html">LoadResource</a></li>
-<li><a href="Tasks/local.html">Local</a></li>
-<li><a href="Tasks/macrodef.html">MacroDef</a></li>
-<li><a href="Tasks/mail.html">Mail</a></li>
-<li><a href="Tasks/makeurl.html">MakeURL</a></li>
-<li><a href="Tasks/manifest.html">Manifest</a></li>
-<li><a href="Tasks/manifestclasspath.html">ManifestClassPath</a></li>
-<li><a href="Tasks/mimemail.html"><i>MimeMail</i></a></li>
-<li><a href="Tasks/mkdir.html">Mkdir</a></li>
-<li><a href="Tasks/move.html">Move</a></li>
-<li><a href="Tasks/native2ascii.html">Native2Ascii</a></li>
-<li><a href="Tasks/netrexxc.html">NetRexxC</a></li>
-<li><a href="Tasks/nice.html">Nice</a></li>
-<li><a href="Tasks/parallel.html">Parallel</a></li>
-<li><a href="Tasks/patch.html">Patch</a></li>
-<li><a href="Tasks/pathconvert.html">PathConvert</a></li>
-<li><a href="Tasks/presetdef.html">PreSetDef</a></li>
-<li><a href="Tasks/projecthelper.html">ProjectHelper</a></li>
-<li><a href="Tasks/property.html">Property</a></li>
-<li><a href="Tasks/propertyfile.html">PropertyFile</a></li>
-<li><a href="Tasks/propertyhelper.html">PropertyHelper</a></li>
-<li><a href="Tasks/pvcstask.html">Pvcs</a></li>
-<li><a href="Tasks/recorder.html">Record</a></li>
-<li><a href="Tasks/rename.html"><i>Rename</i></a></li>
-<li><a href="Tasks/renameextensions.html"><i>RenameExtensions</i></a></li>
-<li><a href="Tasks/replace.html">Replace</a></li>
-<li><a href="Tasks/replaceregexp.html">ReplaceRegExp</a></li>
-<li><a href="Tasks/resourcecount.html">ResourceCount</a></li>
-<li><a href="Tasks/retry.html">Retry</a></li>
-<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/schemavalidate.html">SchemaValidate</a></li>
-<li><a href="Tasks/scp.html">Scp</a></li>
-<li><a href="Tasks/script.html">Script</a></li>
-<li><a href="Tasks/scriptdef.html">Scriptdef</a></li>
-<li><a href="Tasks/sequential.html">Sequential</a></li>
-<li><a href="Tasks/serverdeploy.html">ServerDeploy</a></li>
-<li><a href="Tasks/setproxy.html">Setproxy</a></li>
-<li><a href="Tasks/signjar.html">SignJar</a></li>
-<li><a href="Tasks/sleep.html">Sleep</a></li>
-<li><a href="Tasks/sos.html">SourceOffSite</a></li>
-<li><a href="Tasks/sound.html">Sound</a></li>
-<li><a href="Tasks/splash.html">Splash</a></li>
-<li><a href="Tasks/sql.html">Sql</a></li>
-<li><a href="Tasks/sshexec.html">Sshexec</a></li>
-<li><a href="Tasks/sshsession.html">Sshsession</a></li>
-<li><a href="Tasks/subant.html">Subant</a></li>
-<li><a href="Tasks/symlink.html">Symlink</a></li>
-<li><a href="Tasks/sync.html">Sync</a></li>
-<li><a href="Tasks/tar.html">Tar</a></li>
-<li><a href="Tasks/taskdef.html">Taskdef</a></li>
-<li><a href="Tasks/telnet.html">Telnet</a></li>
-<li><a href="Tasks/tempfile.html">Tempfile</a></li>
-<li><a href="Tasks/touch.html">Touch</a></li>
-<li><a href="Tasks/translate.html">Translate</a></li>
-<li><a href="Tasks/truncate.html">Truncate</a></li>
-<li><a href="Tasks/tstamp.html">TStamp</a></li>
-<li><a href="Tasks/typedef.html">Typedef</a></li>
-<li><a href="Tasks/unzip.html">Unjar</a></li>
-<li><a href="Tasks/unzip.html">Untar</a></li>
-<li><a href="Tasks/unzip.html">Unwar</a></li>
-<li><a href="Tasks/unzip.html">Unzip</a></li>
-<li><a href="Tasks/uptodate.html">Uptodate</a></li>
-<li><a href="Tasks/verifyjar.html">VerifyJar</a></li>
-<li><a href="Tasks/vss.html#tasks">Microsoft Visual SourceSafe Tasks</a></li>
-<li><a href="Tasks/waitfor.html">Waitfor</a></li>
-<li><a href="Tasks/war.html">War</a></li>
-<li><a href="Tasks/whichresource.html">WhichResource</a></li>
-<li><a href="Tasks/wljspc.html">Weblogic JSP Compiler</a></li>
-<li><a href="Tasks/xmlproperty.html">XmlProperty</a></li>
-<li><a href="Tasks/xmlvalidate.html">XmlValidate</a></li>
-<li><a href="Tasks/style.html">XSLT/<i>Style</i></a></li>
-<li><a href="Tasks/zip.html">Zip</a></li>
+  <li><a href="Tasks/ant.html">Ant</a></li>
+  <li><a href="Tasks/antcall.html">AntCall</a></li>
+  <li><a href="Tasks/antlr.html">ANTLR</a></li>
+  <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/<em>ExecOn</em></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>
+  <li><a href="Tasks/basename.html">Basename</a></li>
+  <li><a href="Tasks/bindtargets.html">Bindtargets</a></li>
+  <li><a href="Tasks/buildnumber.html">BuildNumber</a></li>
+  <li><a href="Tasks/unpack.html">BUnzip2</a></li>
+  <li><a href="Tasks/pack.html">BZip2</a></li>
+  <li><a href="Tasks/cab.html">Cab</a></li>
+  <li><a href="Tasks/ccm.html">Continuus/Synergy Tasks</a></li>
+  <li><a href="Tasks/changelog.html">CvsChangeLog</a></li>
+  <li><a href="Tasks/checksum.html">Checksum</a></li>
+  <li><a href="Tasks/chgrp.html">Chgrp</a></li>
+  <li><a href="Tasks/chmod.html">Chmod</a></li>
+  <li><a href="Tasks/chown.html">Chown</a></li>
+  <li><a href="Tasks/clearcase.html">ClearCase Tasks</a></li>
+  <li><a href="Tasks/componentdef.html">Componentdef</a></li>
+  <li><a href="Tasks/concat.html">Concat</a></li>
+  <li><a href="Tasks/condition.html">Condition</a></li>
+  <li class="indent"><a href="Tasks/conditions.html">Supported conditions</a></li>
+  <li><a href="Tasks/copy.html">Copy</a></li>
+  <li><a href="Tasks/copydir.html"><em>Copydir</em></a></li>
+  <li><a href="Tasks/copyfile.html"><em>Copyfile</em></a></li>
+  <li><a href="Tasks/cvs.html">Cvs</a></li>
+  <li><a href="Tasks/cvspass.html">CVSPass</a></li>
+  <li><a href="Tasks/cvstagdiff.html">CvsTagDiff</a></li>
+  <li><a href="Tasks/cvsversion.html">CvsVersion</a></li>
+  <li><a href="Tasks/defaultexcludes.html">Defaultexcludes</a></li>
+  <li><a href="Tasks/delete.html">Delete</a></li>
+  <li><a href="Tasks/deltree.html"><em>Deltree</em></a></li>
+  <li><a href="Tasks/depend.html">Depend</a></li>
+  <li><a href="Tasks/dependset.html">Dependset</a></li>
+  <li><a href="Tasks/diagnostics.html">Diagnostics</a></li>
+  <li><a href="Tasks/dirname.html">Dirname</a></li>
+  <li><a href="Tasks/ear.html">Ear</a></li>
+  <li><a href="Tasks/echo.html">Echo</a></li>
+  <li><a href="Tasks/echoproperties.html">Echoproperties</a></li>
+  <li><a href="Tasks/echoxml.html">EchoXML</a></li>
+  <li><a href="Tasks/ejb.html">EJB Tasks</a></li>
+  <li><a href="Tasks/exec.html">Exec</a></li>
+  <li><a href="Tasks/fail.html">Fail</a></li>
+  <li><a href="Tasks/filter.html">Filter</a></li>
+  <li><a href="Tasks/fixcrlf.html">FixCRLF</a></li>
+  <li><a href="Tasks/ftp.html">FTP</a></li>
+  <li><a href="Tasks/genkey.html">GenKey</a></li>
+  <li><a href="Tasks/get.html">Get</a></li>
+  <li><a href="Tasks/unpack.html">GUnzip</a></li>
+  <li><a href="Tasks/pack.html">GZip</a></li>
+  <li><a href="Tasks/hostinfo.html">Hostinfo</a></li>
+  <li><a href="Tasks/image.html"><em>Image</em></a></li>
+  <li><a href="Tasks/imageio.html">ImageIO</a></li>
+  <li><a href="Tasks/import.html">Import</a></li>
+  <li><a href="Tasks/include.html">Include</a></li>
+  <li><a href="Tasks/input.html">Input</a></li>
+  <li><a href="Tasks/jar.html">Jar</a></li>
+  <li><a href="Tasks/jarlib-available.html">Jarlib-available</a></li>
+  <li><a href="Tasks/jarlib-display.html">Jarlib-display</a></li>
+  <li><a href="Tasks/jarlib-manifest.html">Jarlib-manifest</a></li>
+  <li><a href="Tasks/jarlib-resolve.html">Jarlib-resolve</a></li>
+  <li><a href="Tasks/java.html">Java</a></li>
+  <li><a href="Tasks/javac.html">Javac</a></li>
+  <li><a href="Tasks/javacc.html">JavaCC</a></li>
+  <li><a href="Tasks/javadoc.html">Javadoc/<em>Javadoc2</em></a></li>
+  <li><a href="Tasks/javah.html">Javah</a></li>
+  <li><a href="Tasks/jdepend.html">JDepend</a></li>
+  <li><a href="Tasks/jjdoc.html">JJDoc</a></li>
+  <li><a href="Tasks/jjtree.html">JJTree</a></li>
+  <li><a href="Tasks/jlink.html"><em>Jlink</em></a></li>
+  <li><a href="Tasks/jmod.html">Jmod</a></li>
+  <li><a href="Tasks/jspc.html"><em>JspC</em></a></li>
+  <li><a href="Tasks/junit.html">JUnit</a> (3 &amp; 4)</li>
+  <li><a href="Tasks/junitlauncher.html">JUnitLauncher</a> (JUnit 5)</li>
+  <li><a href="Tasks/junitreport.html">JUnitReport</a></li>
+  <li><a href="Tasks/length.html">Length</a><br/></li>
+  <li><a href="Tasks/link.html">Link</a><br/></li>
+  <li><a href="Tasks/loadfile.html">LoadFile</a></li>
+  <li><a href="Tasks/loadproperties.html">LoadProperties</a></li>
+  <li><a href="Tasks/loadresource.html">LoadResource</a></li>
+  <li><a href="Tasks/local.html">Local</a></li>
+  <li><a href="Tasks/macrodef.html">MacroDef</a></li>
+  <li><a href="Tasks/mail.html">Mail</a></li>
+  <li><a href="Tasks/makeurl.html">MakeURL</a></li>
+  <li><a href="Tasks/manifest.html">Manifest</a></li>
+  <li><a href="Tasks/manifestclasspath.html">ManifestClassPath</a></li>
+  <li><a href="Tasks/mimemail.html"><em>MimeMail</em></a></li>
+  <li><a href="Tasks/mkdir.html">Mkdir</a></li>
+  <li><a href="Tasks/move.html">Move</a></li>
+  <li><a href="Tasks/native2ascii.html">Native2Ascii</a></li>
+  <li><a href="Tasks/netrexxc.html">NetRexxC</a></li>
+  <li><a href="Tasks/nice.html">Nice</a></li>
+  <li><a href="Tasks/parallel.html">Parallel</a></li>
+  <li><a href="Tasks/patch.html">Patch</a></li>
+  <li><a href="Tasks/pathconvert.html">PathConvert</a></li>
+  <li><a href="Tasks/presetdef.html">PreSetDef</a></li>
+  <li><a href="Tasks/projecthelper.html">ProjectHelper</a></li>
+  <li><a href="Tasks/property.html">Property</a></li>
+  <li><a href="Tasks/propertyfile.html">PropertyFile</a></li>
+  <li><a href="Tasks/propertyhelper.html">PropertyHelper</a></li>
+  <li><a href="Tasks/pvcstask.html">Pvcs</a></li>
+  <li><a href="Tasks/recorder.html">Record</a></li>
+  <li><a href="Tasks/rename.html"><em>Rename</em></a></li>
+  <li><a href="Tasks/renameextensions.html"><em>RenameExtensions</em></a></li>
+  <li><a href="Tasks/replace.html">Replace</a></li>
+  <li><a href="Tasks/replaceregexp.html">ReplaceRegExp</a></li>
+  <li><a href="Tasks/resourcecount.html">ResourceCount</a></li>
+  <li><a href="Tasks/retry.html">Retry</a></li>
+  <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/schemavalidate.html">SchemaValidate</a></li>
+  <li><a href="Tasks/scp.html">Scp</a></li>
+  <li><a href="Tasks/script.html">Script</a></li>
+  <li><a href="Tasks/scriptdef.html">Scriptdef</a></li>
+  <li><a href="Tasks/sequential.html">Sequential</a></li>
+  <li><a href="Tasks/serverdeploy.html">ServerDeploy</a></li>
+  <li><a href="Tasks/setpermissions.html">SetPermissions</a></li>
+  <li><a href="Tasks/setproxy.html">SetProxy</a></li>
+  <li><a href="Tasks/signjar.html">SignJar</a></li>
+  <li><a href="Tasks/sleep.html">Sleep</a></li>
+  <li><a href="Tasks/sos.html">SourceOffSite</a></li>
+  <li><a href="Tasks/sound.html">Sound</a></li>
+  <li><a href="Tasks/splash.html">Splash</a></li>
+  <li><a href="Tasks/sql.html">Sql</a></li>
+  <li><a href="Tasks/sshexec.html">Sshexec</a></li>
+  <li><a href="Tasks/sshsession.html">Sshsession</a></li>
+  <li><a href="Tasks/subant.html">Subant</a></li>
+  <li><a href="Tasks/symlink.html">Symlink</a></li>
+  <li><a href="Tasks/sync.html">Sync</a></li>
+  <li><a href="Tasks/tar.html">Tar</a></li>
+  <li><a href="Tasks/taskdef.html">Taskdef</a></li>
+  <li><a href="Tasks/telnet.html">Telnet</a></li>
+  <li><a href="Tasks/tempfile.html">Tempfile</a></li>
+  <li><a href="Tasks/touch.html">Touch</a></li>
+  <li><a href="Tasks/translate.html">Translate</a></li>
+  <li><a href="Tasks/truncate.html">Truncate</a></li>
+  <li><a href="Tasks/tstamp.html">TStamp</a></li>
+  <li><a href="Tasks/typedef.html">Typedef</a></li>
+  <li><a href="Tasks/unzip.html">Unjar</a></li>
+  <li><a href="Tasks/unzip.html">Untar</a></li>
+  <li><a href="Tasks/unzip.html">Unwar</a></li>
+  <li><a href="Tasks/unpack.html">UnXZ</a></li>
+  <li><a href="Tasks/unzip.html">Unzip</a></li>
+  <li><a href="Tasks/uptodate.html">Uptodate</a></li>
+  <li><a href="Tasks/verifyjar.html">VerifyJar</a></li>
+  <li><a href="Tasks/vss.html#tasks">Microsoft Visual SourceSafe Tasks</a></li>
+  <li><a href="Tasks/waitfor.html">Waitfor</a></li>
+  <li><a href="Tasks/war.html">War</a></li>
+  <li><a href="Tasks/whichresource.html">WhichResource</a></li>
+  <li><a href="Tasks/wljspc.html">WebLogic JSP Compiler</a></li>
+  <li><a href="Tasks/xmlproperty.html">XmlProperty</a></li>
+  <li><a href="Tasks/xmlvalidate.html">XmlValidate</a></li>
+  <li><a href="Tasks/pack.html">XZ</a></li>
+  <li><a href="Tasks/style.html">XSLT/<em>Style</em></a></li>
+  <li><a href="Tasks/zip.html">Zip</a></li>
 </ul>
 </body>
 </html>
diff --git a/manual/tasksoverview.html b/manual/tasksoverview.html
index 99aa11b..f8e36c3 100644
--- a/manual/tasksoverview.html
+++ b/manual/tasksoverview.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,416 +15,365 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
-  <meta http-equiv="Content-Language" content="en-us">
   <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Overview of Apache Ant Tasks</title>
   <base target="mainFrame">
 </head>
 
 <body>
-<a name="top"></a>
-<h2>Overview of Apache Ant Tasks</h2>
+<h2 id="top">Overview of Apache Ant Tasks</h2>
 <p>Given the large number of tasks available with Ant, it may be
 difficult to get an overall view of what each task can do.  The following
 tables provide a short description of each task and a link to the complete
 documentation.</p>
 
-<a href="#archive">Archive Tasks</a><br>
-<a href="#audit">Audit/Coverage Tasks</a><br>
-<a href="#compile">Compile Tasks</a><br>
-<a href="#deploy">Deployment Tasks</a><br>
-<a href="#doc">Documentation Tasks</a><br>
-<a href="#ejb">EJB Tasks</a><br>
-<a href="#exec">Execution Tasks</a><br>
-<a href="#file">File Tasks</a><br>
-<a href="#extensions">Java2 Extensions Tasks</a><br>
-<a href="#log">Logging Tasks</a><br>
-<a href="#mail">Mail Tasks</a><br>
-<a href="#misc">Miscellaneous Tasks</a><br>
-<a href="#preproc">Pre-process Tasks</a><br>
-<a href="#prop">Property Tasks</a><br>
-<a href="#remote">Remote Tasks</a><br>
-<a href="#scm">SCM Tasks</a><br>
-<a href="#testing">Testing Tasks</a><br>
+<a href="#archive">Archive Tasks</a><br/>
+<a href="#audit">Audit/Coverage Tasks</a><br/>
+<a href="#compile">Compile Tasks</a><br/>
+<a href="#deploy">Deployment Tasks</a><br/>
+<a href="#doc">Documentation Tasks</a><br/>
+<a href="#ejb">EJB Tasks</a><br/>
+<a href="#exec">Execution Tasks</a><br/>
+<a href="#file">File Tasks</a><br/>
+<a href="#extensions">Java Extensions Tasks</a><br/>
+<a href="#log">Logging Tasks</a><br/>
+<a href="#mail">Mail Tasks</a><br/>
+<a href="#misc">Miscellaneous Tasks</a><br/>
+<a href="#preproc">Pre-process Tasks</a><br/>
+<a href="#prop">Property Tasks</a><br/>
+<a href="#remote">Remote Tasks</a><br/>
+<a href="#scm">SCM Tasks</a><br/>
+<a href="#testing">Testing Tasks</a><br/>
 
+<div class="float" id="archive">
+    <span class="left">Archive Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="archive">Archive Tasks</a>
-</font>
-</th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th nowrap>Description</th>
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/unpack.html">BUnzip2</a></td>
-    <td><p>Expands a file packed using GZip or BZip2.</p></td>
+  <tr>
+    <td><a href="Tasks/unpack.html">GUnzip/BUnzip2/UnXZ</a></td>
+    <td><p>Expands a file packed using GZip, BZip2 or XZ.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/pack.html">BZip2</a></td>
-    <td><p>Packs a file using the GZip or BZip2 algorithm. This task
+  <tr>
+    <td><a href="Tasks/pack.html">GZip/BZip2/XZ</a></td>
+    <td><p>Packs a file using the GZip, BZip2 or XZ algorithm. This task
      does not do any dependency checking; the output file is always
      generated</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/cab.html">Cab</a></td>
-    <td><p>Creates Microsoft CAB archive files. It is invoked
-     similar to the <a href="Tasks/jar.html">Jar</a> or
-     <a href="Tasks/zip.html">Zip</a> tasks. This task will work on
-     Windows using the external <i>cabarc</i> tool (provided by Microsoft),
-     which must be located in your executable path.</p></td>
+  <tr>
+    <td><a href="Tasks/cab.html">Cab</a></td>
+    <td><p>Creates Microsoft CAB archive files. It is invoked similar
+     to the <a href="Tasks/jar.html">Jar</a>
+     or <a href="Tasks/zip.html">Zip</a> tasks. This task will work on
+     Windows using the external <code>cabarc</code> tool (provided by
+     Microsoft), which must be located in your executable
+     path.</p></td>
    </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/ear.html">Ear</a></td>
-    <td><p>An extension of the <a href="Tasks/jar.html">Jar</a> task with
-     special treatment for files that should end up in an
+  <tr>
+    <td><a href="Tasks/ear.html">Ear</a></td>
+    <td><p>An extension of the <a href="Tasks/jar.html">Jar</a> task
+     with special treatment for files that should end up in an
      Enterprise Application archive.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/gunzip.html">GUnzip</a></td>
-    <td><p>Expands a GZip file.</p></td>
-  </tr>
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/gzip.html">GZip</a></td>
-    <td><p>GZips a set of files.</p></td>
-  </tr>
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/jar.html">Jar</a></td>
+  <tr>
+    <td><a href="Tasks/jar.html">Jar</a></td>
     <td><p>Jars a set of files.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/jlink.html">Jlink</a></td>
-    <td><p><i>Deprecated.</i> Use the <code>zipfileset</code>
-     and <code>zipgroupfileset</code> attributes of the
-     <a href="Tasks/jar.html">Jar</a> or
-     <a href="Tasks/zip.html">Zip</a> tasks instead.</p></td>
+  <tr>
+    <td><a href="Tasks/jlink.html">Jlink</a></td>
+    <td><p><em><u>Deprecated</u></em>. Use the <code>zipfileset</code>
+     and <code>zipgroupfileset</code> attributes of
+     the <a href="Tasks/jar.html">Jar</a>
+     or <a href="Tasks/zip.html">Zip</a> tasks instead.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/manifest.html">Manifest</a></td>
+  <tr>
+    <td><a href="Tasks/manifest.html">Manifest</a></td>
     <td><p>Creates a manifest file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/rpm.html">Rpm</a></td>
-    <td><p>Invokes the <i>rpm</i> executable to build a Linux installation
-     file. This task currently only works on Linux or other Unix platforms
-     with RPM support.</p></td>
+  <tr>
+    <td><a href="Tasks/rpm.html">Rpm</a></td>
+    <td><p>Invokes the <kbd>rpm</kbd> executable to build a Linux
+     installation file. This task currently only works on Linux or
+     other Unix platforms with RPM support.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/signjar.html">SignJar</a></td>
-    <td><p>Signs a jar or zip file with the <i>javasign</i>
+  <tr>
+    <td><a href="Tasks/signjar.html">SignJar</a></td>
+    <td><p>Signs a jar or zip file with the <kbd>javasign</kbd>
      command-line tool.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/tar.html">Tar</a></td>
+  <tr>
+    <td><a href="Tasks/tar.html">Tar</a></td>
     <td><p>Creates a tar archive.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/unzip.html">Unjar</a></td>
+  <tr>
+    <td><a href="Tasks/unzip.html">Unjar</a></td>
     <td><p>Unzips a jarfile.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/untar.html">Untar</a></td>
+  <tr>
+    <td><a href="Tasks/unzip.html">Untar</a></td>
     <td><p>Untars a tarfile.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/unzip.html">Unwar</a></td>
+  <tr>
+    <td><a href="Tasks/unzip.html">Unwar</a></td>
     <td><p>Unzips a warfile.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/unzip.html">Unzip</a></td>
+  <tr>
+    <td><a href="Tasks/unzip.html">Unzip</a></td>
     <td><p>Unzips a zipfile.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/war.html">War</a></td>
+  <tr>
+    <td><a href="Tasks/war.html">War</a></td>
     <td><p>An extension of the <a href="Tasks/jar.html">Jar</a> task
-     with special treatment for files that should end up in the
-     <code>WEB-INF/lib</code>, <code>WEB-INF/classes</code>, or
-     <code>WEB-INF</code> directories of the Web Application Archive.</p></td>
+     with special treatment for files that should end up in
+     the <samp>WEB-INF/lib</samp>, <samp>WEB-INF/classes</samp>,
+     or <samp>WEB-INF</samp> directories of the Web Application
+     Archive.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/zip.html">Zip</a></td>
+  <tr>
+    <td><a href="Tasks/zip.html">Zip</a></td>
     <td><p>Creates a zipfile.</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="audit">Audit/Coverage Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="audit">
+    <span class="left">Audit/Coverage Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/jdepend.html">JDepend</a></td>
-    <td><p>Invokes the <a href="http://www.clarkware.com/software/JDepend.html">
-     JDepend</a> parser. This parser &quot;traverses a set of Java source-file
-     directories and generates design-quality metrics for each Java
-     package&quot;.</p></td>
+  <tr>
+    <td><a href="Tasks/jdepend.html">JDepend</a></td>
+    <td><p>Invokes
+     the <a href="https://github.com/clarkware/jdepend"
+     target="_top">JDepend</a> parser. This parser &quot;traverses a
+     set of Java source-file directories and generates design-quality
+     metrics for each Java package&quot;.</p></td>
    </tr>
-
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="compile">Compile Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="compile">
+    <span class="left">Compile Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/depend.html">Depend</a></td>
-    <td><p>Determines which classfiles are out-of-date with respect to their
-     source, removing the classfiles of any other classes that depend on the
-     out-of-date classes, forcing the re-compile of the removed classfiles.
-     Typically used in conjunction with the
+  <tr>
+    <td><a href="Tasks/depend.html">Depend</a></td>
+    <td><p>Determines which class files are out-of-date with respect
+     to their source, removing the class files of any other classes
+     that depend on the out-of-date classes, forcing the re-compile of
+     the removed class files.  Typically used in conjunction with the
      <a href="Tasks/javac.html">Javac</a> task.</p></td>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/javac.html">Javac</a></td>
+  <tr>
+    <td><a href="Tasks/javac.html">Javac</a></td>
     <td><p>Compiles the specified source file(s) within the running
-     (Ant) VM, or in another VM if the <code>fork</code> attribute is
+     (Ant) JVM, or in another JVM if the <var>fork</var> attribute is
      specified.</p></td>
   </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>
+    <td><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 the full JDK installed, or simply to syntax-check
+     the pages without deploying
+     them. The <a href="Tasks/javac.html">Javac</a> task can be used
+     to compile the generated Java source.  (For WebLogic JSP
+     compiler, see the <a href="Tasks/wljspc.html">Wljspc</a>
+     task.)</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
-     the full JDK installed, or simply to syntax-check the pages without
-     deploying them. The <a href="Tasks/javac.html">Javac</a> task
-     can be used to compile the generated Java source.
-     (For Weblogic JSP compiles,
-     see the <a href="Tasks/wljspc.html">Wljspc</a> task.)</p></td>
+  <tr>
+    <td><a href="Tasks/netrexxc.html">NetRexxC</a></td>
+    <td><p>Compiles
+     a <a href="https://www.ibm.com/software/awdtools/netrexx/library.html"
+     target="_top">NetRexx</a> source tree within the running (Ant)
+     JVM.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/netrexxc.html">NetRexxC</a></td>
-    <td><p>Compiles a
-     <a href="http://www2.hursley.ibm.com/netrexx" target="_top">NetRexx</a>
-     source tree within the running (Ant) VM.</p></td>
+  <tr>
+    <td><a href="Tasks/rmic.html">Rmic</a></td>
+    <td><p>Runs the <kbd>rmic</kbd> compiler on the specified file(s).</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/rmic.html">Rmic</a></td>
-    <td><p>Runs the <i>rmic</i> compiler on the specified file(s).</p></td>
-  </tr>
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/wljspc.html">Wljspc</a></td>
-    <td><p>Compiles JSP pages using Weblogic's JSP compiler,
-     <i>weblogic.jspc</i>. (For non-Weblogic JSP compiles, see the
-     <a href="Tasks/jspc.html">JspC</a> task.</p></td>
-  </tr>
-
-</table>
-
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="deploy">Deployment Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
-  </tr>
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/serverdeploy.html">ServerDeploy</a></td>
-    <td><p>Task to run a &quot;hot&quot; deployment tool for vendor-specific
-     J2EE server.
-    </p></td>
+  <tr>
+    <td><a href="Tasks/wljspc.html">Wljspc</a></td>
+    <td><p>Compiles JSP pages using WebLogic JSP
+     compiler, <code>weblogic.jspc</code>. (For non-WebLogic JSP
+     compiler, see the <a href="Tasks/jspc.html">JspC</a>
+     task.</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="doc">Documentation Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="deploy">
+    <span class="left">Deployment Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/javadoc.html">Javadoc/<i>Javadoc2</i></a></td>
-    <td><p>Generates code documentation using the <i>javadoc</i> tool.
-     The Javadoc2 task is deprecated; use the Javadoc task instead.</p></td>
+  <tr>
+    <td><a href="Tasks/serverdeploy.html">ServerDeploy</a></td>
+    <td><p>Runs a &quot;hot&quot; deployment tool for vendor-specific
+     J2EE server.</p></td>
   </tr>
-
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="ejb">EJB Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="doc">
+    <span class="left">Documentation Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/ejb.html">EJB Tasks</a></td>
+  <tr>
+    <td><a href="Tasks/javadoc.html">Javadoc</a></td>
+    <td><p>Generates code documentation using the <kbd>javadoc</kbd>
+     tool. <em>The <code>Javadoc2</code> task is <u>deprecated</u>; use
+     the <code>Javadoc</code> task instead.</em></p></td>
+  </tr>
+</table>
+
+<div class="float" id="ejb">
+    <span class="left">EJB Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
+  </tr>
+
+  <tr>
+    <td><a href="Tasks/ejb.html">EJB Tasks</a></td>
     <td><p>(See the documentation describing the EJB tasks.)</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="exec">Execution Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="exec">
+    <span class="left">Execution Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/ant.html">Ant</a></td>
+  <tr>
+    <td><a href="Tasks/ant.html">Ant</a></td>
     <td><p>Runs Ant on a supplied buildfile, optionally
      passing properties (with possibly new values).
      This task can be used to build sub-projects.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/antcall.html">AntCall</a></td>
+  <tr>
+    <td><a href="Tasks/antcall.html">AntCall</a></td>
     <td><p>Runs another target within the same buildfile, optionally
      passing properties (with possibly new values).</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/apply.html">Apply/<i>ExecOn</i></a></td>
-    <td><p>Executes a system command. When the <code>os</code> attribute is
+  <tr>
+    <td><a href="Tasks/apply.html">Apply/<em>ExecOn</em></a></td>
+    <td><p>Executes a system command. When the <var>os</var> attribute is
      specified, the command is only executed when Ant is run on one
      of the specified operating systems.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/dependset.html">Dependset</a></td>
-    <td><p>This task compares a set of source files with a set of target
+  <tr>
+    <td><a href="Tasks/dependset.html">Dependset</a></td>
+    <td><p>Compares a set of source files with a set of target
      files.  If any of the source files is newer than any of
-     the target files, all the target files are removed. </p></td>
+     the target files, all the target files are removed.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/exec.html">Exec</a></td>
-    <td><p>Executes a system command. When the <code>os</code> attribute
+  <tr>
+    <td><a href="Tasks/exec.html">Exec</a></td>
+    <td><p>Executes a system command. When the <var>os</var> attribute
      is specified, the command is only executed when Ant is run on one of
      the specified operating systems.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/java.html">Java</a></td>
-    <td><p>Executes a Java class within the running (Ant) VM, or in
-     another VM if the <code>fork</code> attribute is specified.</p></td>
+  <tr>
+    <td><a href="Tasks/java.html">Java</a></td>
+    <td><p>Executes a Java class within the running (Ant) JVM, or in
+     another JVM if the <var>fork</var> attribute is specified.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/parallel.html">Parallel</a></td>
+  <tr>
+    <td><a href="Tasks/parallel.html">Parallel</a></td>
     <td><p>A container task that can contain other Ant tasks.
      Each nested task specified within the <code>&lt;parallel&gt;</code>
      tag will be executed in its own thread.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/sequential.html">Sequential</a></td>
+  <tr>
+    <td><a href="Tasks/sequential.html">Sequential</a></td>
     <td><p>A container task that can contain other Ant tasks.
      The nested tasks are simply executed in sequence. Its primary use is
      to support the sequential execution of a subset of tasks within
      the <code>&lt;parallel&gt;</code> tag.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/sleep.html">Sleep</a></td>
-    <td><p> A task for suspending execution for a specified period of time.
+  <tr>
+    <td><a href="Tasks/sleep.html">Sleep</a></td>
+    <td><p>Suspends execution for a specified period of time.
      Useful when a build or deployment process requires an interval between
      tasks.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/subant.html">Subant</a></td>
-    <td><p> Calls a given target for all defined sub-builds. This is an extension of ant for bulk project execution.</p></td>
+  <tr>
+    <td><a href="Tasks/subant.html">Subant</a></td>
+    <td><p>Calls a given target for all defined sub-builds. This is an
+     extension of ant for bulk project execution.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/waitfor.html">Waitfor</a></td>
+  <tr>
+    <td><a href="Tasks/waitfor.html">Waitfor</a></td>
     <td><p>Blocks execution until a set of specified conditions become true.
      This task is intended to be used with the
      <a href="Tasks/parallel.html">Parallel</a> task to synchronize
@@ -431,768 +381,721 @@
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="file">File Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="file">
+    <span class="left">File Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/attrib.html">Attrib</a></td>
+  <tr>
+    <td><a href="Tasks/attrib.html">Attrib</a></td>
     <td><p>Changes the permissions and/or attributes of a file or all
-    files inside the specified directories. Currently, it has effect
-    only under Windows.</p></td>
+     files inside the specified directories. Currently, it has effect
+     only under Windows.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/checksum.html">Checksum</a></td>
+  <tr>
+    <td><a href="Tasks/checksum.html">Checksum</a></td>
     <td><p>Generates a checksum for a file or set of files. This task can
      also be used to perform checksum verifications.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/chgrp.html">Chgrp</a></td>
+  <tr>
+    <td><a href="Tasks/chgrp.html">Chgrp</a></td>
     <td><p>Changes the group ownership of a file or all files inside
-    the specified directories. Currently, it has effect only under
-    Unix.</p></td>
+     the specified directories. Currently, it has effect only under
+     Unix.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/chmod.html">Chmod</a></td>
+  <tr>
+    <td><a href="Tasks/chmod.html">Chmod</a></td>
     <td><p>Changes the permissions of a file or all files inside the
      specified directories. Currently, it has effect only under Unix.
      The permissions are also UNIX style, like the arguments for the
-    <i>chmod</i> command.</p></td>
+     <kbd>chmod</kbd> command.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/chown.html">Chown</a></td>
+  <tr>
+    <td><a href="Tasks/chown.html">Chown</a></td>
     <td><p>Changes the owner of a file or all files inside the
-    specified directories. Currently, it has effect only under
-    Unix.</p></td>
+     specified directories. Currently, it has effect only under
+     Unix.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/concat.html">Concat</a></td>
+  <tr>
+    <td><a href="Tasks/concat.html">Concat</a></td>
     <td><p>Concatenates multiple files into a single one or to Ant's
      logging system.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/copy.html">Copy</a></td>
+  <tr>
+    <td><a href="Tasks/copy.html">Copy</a></td>
     <td><p>Copies a file or Fileset to a new file or directory.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/copydir.html"><i>Copydir</i></a></td>
-    <td><p><i>Deprecated.</i>  Use the
-     <a href="Tasks/copy.html">Copy</a> task instead.</p></td>
+  <tr>
+    <td><a href="Tasks/copydir.html"><em>Copydir</em></a></td>
+    <td><p><em><u>Deprecated</u></em>.  Use
+     the <a href="Tasks/copy.html">Copy</a> task instead.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/copyfile.html"><i>Copyfile</i></a></td>
-    <td><p><i>Deprecated.</i>  Use the
-     <a href="Tasks/copy.html">Copy</a> task instead.</p></td>
+  <tr>
+    <td><a href="Tasks/copyfile.html"><em>Copyfile</em></a></td>
+    <td><p><em><u>Deprecated</u></em>.  Use
+     the <a href="Tasks/copy.html">Copy</a> task instead.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/delete.html">Delete</a></td>
+  <tr>
+    <td><a href="Tasks/delete.html">Delete</a></td>
     <td><p>Deletes either a single file, all files and sub-directories
-     in a specified directory, or a set of files specified by one or more
-     <a href="Types/fileset.html">FileSet</a>s.</p></td>
+     in a specified directory, or a set of files specified by one or
+     more <a href="Types/fileset.html">FileSet</a>s.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/deltree.html"><i>Deltree</i></a></td>
-    <td><p><i>Deprecated.</i>  Use the
-     <a href="Tasks/delete.html">Delete</a> task instead.</p></td>
+  <tr>
+    <td><a href="Tasks/deltree.html"><em>Deltree</em></a></td>
+    <td><p><em><u>Deprecated</u></em>.  Use
+     the <a href="Tasks/delete.html">Delete</a> task instead.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/filter.html">Filter</a></td>
-    <td><p>Sets a token filter for this project, or reads multiple token
-     filters from a specified file and sets these as filters. Token filters
-     are used by all tasks that perform file-copying operations.</p></td>
+  <tr>
+    <td><a href="Tasks/filter.html">Filter</a></td>
+    <td><p>Sets a token filter for this project, or reads multiple
+     token filters from a specified file and sets these as
+     filters. Token filters are used by all tasks that perform
+     file-copying operations.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/fixcrlf.html">FixCRLF</a></td>
-    <td><p>Modifies a file to add or remove tabs, carriage returns, linefeeds,
-     and EOF characters.</p></td>
+  <tr>
+    <td><a href="Tasks/fixcrlf.html">FixCRLF</a></td>
+    <td><p>Modifies a file to add or remove tabs, carriage returns,
+     linefeeds, and EOF characters.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/get.html">Get</a></td>
+  <tr>
+    <td><a href="Tasks/get.html">Get</a></td>
     <td><p>Gets a file from a URL.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/mkdir.html">Mkdir</a></td>
-    <td><p>Creates a directory. Non-existent parent directories are created,
-     when necessary.</p></td>
+  <tr>
+    <td><a href="Tasks/mkdir.html">Mkdir</a></td>
+    <td><p>Creates a directory. Non-existent parent directories are
+     created, when necessary.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/move.html">Move</a></td>
-    <td><p>Moves a file to a new file or directory, or a set(s) of file(s) to
-     a new directory.</p></td>
+  <tr>
+    <td><a href="Tasks/move.html">Move</a></td>
+    <td><p>Moves a file to a new file or directory, or a set(s) of
+     file(s) to a new directory.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/patch.html">Patch</a></td>
-    <td><p>Applies a &quot;diff&quot; file to originals.</p></td>
+  <tr>
+    <td><a href="Tasks/patch.html">Patch</a></td>
+      <td><p>Applies a <q>diff</q> file to originals.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/rename.html"><i>Rename</i></a></td>
-    <td><p><i>Deprecated.</i>  Use the <a href="Tasks/move.html">Move</a>
-    task instead.</p></td>
+  <tr>
+    <td><a href="Tasks/rename.html"><em>Rename</em></a></td>
+    <td><p><em><u>Deprecated</u></em>.  Use
+    the <a href="Tasks/move.html">Move</a> task instead.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/renameextensions.html">
-     <i>RenameExtensions</i></a></td>
-    <td><p><i>Deprecated</i>. Use the <a href="Tasks/move.html">Move</a>
-     task with a <a href="Types/mapper.html#glob-mapper">glob mapper</a>
+  <tr>
+    <td><a href="Tasks/renameextensions.html"><em>RenameExtensions</em></a></td>
+    <td><p><em><u>Deprecated</u></em>. Use
+     the <a href="Tasks/move.html">Move</a> task with
+     a <a href="Types/mapper.html#glob-mapper">glob mapper</a>
      instead.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/replace.html">Replace</a></td>
-    <td><p>Replace is a directory-based task for replacing the occurrence
-     of a given string with another string in selected file.</p></td>
+  <tr>
+    <td><a href="Tasks/replace.html">Replace</a></td>
+    <td><p>Replaces the occurrence of a given string with another
+     string in a file or set of files.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/replaceregexp.html">
-     ReplaceRegExp</a></td>
-    <td><p>Directory-based task for replacing the occurrence of a given
-     regular expression with a substitution pattern in a file or set of
-     files.</p></td>
+  <tr>
+    <td><a href="Tasks/replaceregexp.html">ReplaceRegExp</a></td>
+    <td><p>Replaces the occurrence of a given regular expression with
+     a substitution pattern in a file or set of files.</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>
+    <td><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/tempfile.html">Tempfile</a></td>
-    <td><p>Generates a name for a new temporary file and sets the specified
-     property to that name.</p></td>
+  <tr>
+    <td><a href="Tasks/sync.html">Sync</a></td>
+    <td><p>Synchronizes two directory trees.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/touch.html">Touch</a></td>
-    <td><p>Changes the modification time of a file and possibly creates it at
-     the same time.</p></td>
+  <tr>
+    <td><a href="Tasks/tempfile.html">Tempfile</a></td>
+    <td><p>Generates a name for a new temporary file and sets the
+     specified property to that name.</p></td>
+  </tr>
+
+  <tr>
+    <td><a href="Tasks/touch.html">Touch</a></td>
+    <td><p>Changes the modification time of a file and possibly
+     creates it at the same time.</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="extensions">Java2 Extensions Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="extensions">
+    <span class="left">Java Extensions Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap>
+  <tr>
+    <td>
     <a href="Tasks/jarlib-available.html">Jarlib-available</a></td>
-    <td><p>Check whether an extension is present in a FileSet or an
-      ExtensionSet. If the extension is present, the specified property is
-     set.</p>
+    <td><p>Checks whether an extension is present in a FileSet or an
+      ExtensionSet. If the extension is present, the specified
+      property is set.</p>
     </td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap>
+  <tr>
+    <td>
     <a href="Tasks/jarlib-display.html">Jarlib-display</a></td>
-    <td><p>Display the &quot;Optional Package&quot; and
-      &quot;Package Specification&quot; information contained within the
-      specified jars.</p>
+    <td><p>Displays the <q>Optional Package</q> and <q>Package
+     Specification</q> information contained within the specified
+     jars.</p>
     </td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap>
+  <tr>
+    <td>
     <a href="Tasks/jarlib-manifest.html">Jarlib-manifest</a></td>
-    <td><p>Task to generate a manifest that declares all the dependencies
-      in manifest. The dependencies are determined by looking in the
-      specified path and searching for Extension/&quot;Optional Package&quot;
-      specifications in the manifests of the jars.</p>
+    <td><p>Generates a manifest that declares all the dependencies in
+     manifest. The dependencies are determined by looking in the
+     specified path and searching for <q>Extension</q>/<q>Optional
+     Package</q> specifications in the manifests of the jars.</p>
     </td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap>
+  <tr>
+    <td>
     <a href="Tasks/jarlib-resolve.html">Jarlib-resolve</a></td>
-    <td><p>Try to locate a jar to satisfy an extension, and place the
-      location of the jar into the specified property.</p>
+    <td><p>Tries to locate a jar to satisfy an extension, and places the
+     location of the jar into the specified property.</p>
     </td>
   </tr>
 </table>
 
-<p></p>
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="log">Logging Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="log">
+    <span class="left">Logging Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/recorder.html">Record</a></td>
+  <tr>
+    <td><a href="Tasks/recorder.html">Record</a></td>
     <td><p>Runs a listener that records the logging output of the
-     build-process events to a file. Several recorders can exist
+     build process events to a file. Several recorders can exist
      at the same time. Each recorder is associated with a file.</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="mail">Mail Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="mail">
+    <span class="left">Mail Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/mail.html">Mail</a></td>
-    <td><p>A task to send SMTP email.</p></td>
+  <tr>
+    <td><a href="Tasks/mail.html">Mail</a></td>
+    <td><p>Sends SMTP email.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/mimemail.html">MimeMail</a></td>
-    <td><p><i>Deprecated</i>. Use the <a href="Tasks/mail.html">Mail</a>
-     task instead.</p></td>
+  <tr>
+    <td><a href="Tasks/mimemail.html"><em>MimeMail</em></a></td>
+    <td><p><em><u>Deprecated</u></em>. Use
+     the <a href="Tasks/mail.html">Mail</a> task instead.</p></td>
   </tr>
-
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="misc">Miscellaneous Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="misc">
+    <span class="left">Miscellaneous Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/defaultexcludes.html">Defaultexcludes</a></td>
-    <td><p>Modify the list of default exclude patterns from within
-    your build file.</p></td>
+  <tr>
+    <td><a href="Tasks/defaultexcludes.html">Defaultexcludes</a></td>
+    <td><p>Modifies the list of default exclude patterns from within
+     your build file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/echo.html">Echo</a></td>
+  <tr>
+    <td><a href="Tasks/echo.html">Echo</a></td>
     <td><p>Echoes text to <code>System.out</code> or to a file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/fail.html">Fail</a></td>
-    <td><p>Exits the current build by throwing a BuildException,
-     optionally printing additional information.</p></td>
+  <tr>
+    <td><a href="Tasks/fail.html">Fail</a></td>
+    <td><p>Exits the current build by throwing
+     a <code>BuildException</code>, optionally printing additional
+     information.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/genkey.html">GenKey</a></td>
+  <tr>
+    <td><a href="Tasks/genkey.html">GenKey</a></td>
     <td><p>Generates a key in keystore.</p></td>
   </tr>
-  
-  
-  <tr valign="top">
-    <td nowrap><a href="Tasks/hostinfo.html">HostInfo</a></td>
-    <td><p>Sets properties related to the provided host, or to
-    the host the process is run on.</p></td>
+
+  <tr>
+    <td><a href="Tasks/hostinfo.html">HostInfo</a></td>
+    <td><p>Sets properties related to the provided host, or to the
+     host the process is run on.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/input.html">Input</a></td>
-    <td><p>Allows user interaction during the build process by displaying a
-     message and reading a line of input from the console.</p></td>
+  <tr>
+    <td><a href="Tasks/input.html">Input</a></td>
+    <td><p>Allows user interaction during the build process by
+     displaying a message and reading a line of input from the
+     console.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/script.html">Script</a></td>
-    <td><p>Executes a script in a
-     <a href="http://jakarta.apache.org/bsf/"
-      target="_top">Apache BSF</a>-supported language.</p></td>
+  <tr>
+    <td><a href="Tasks/script.html">Script</a></td>
+    <td><p>Executes a script in
+     a <a href="https://jakarta.apache.org/bsf/" target="_top">Apache
+     BSF</a>-supported language.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/sound.html">Sound</a></td>
-    <td><p>Plays a sound file at the end of the build, according to whether
-     the build failed or succeeded.</p></td>
+  <tr>
+    <td><a href="Tasks/sound.html">Sound</a></td>
+    <td><p>Plays a sound file at the end of the build, according to
+     whether the build failed or succeeded.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/splash.html">Splash</a></td>
+  <tr>
+    <td><a href="Tasks/splash.html">Splash</a></td>
     <td><p>Displays a splash screen.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/sql.html">Sql</a></td>
-    <td><p>Executes a series of SQL statements via JDBC to a database.
-     Statements can either be read in from a text file using the
-     <code>src</code> attribute, or from between the enclosing SQL
+  <tr>
+    <td><a href="Tasks/sql.html">Sql</a></td>
+    <td><p>Executes a series of SQL statements via JDBC to a
+     database. Statements can either be read in from a text file using
+     the <code>src</code> attribute, or from between the enclosing SQL
      tags.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/taskdef.html">Taskdef</a></td>
-    <td><p>Adds a task definition to the current project, such that this
-     new task can be used in the current project.</p></td>
+  <tr>
+    <td><a href="Tasks/taskdef.html">Taskdef</a></td>
+    <td><p>Adds a task definition to the current project, such that
+     this new task can be used in the current project.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/tstamp.html">TStamp</a></td>
-    <td><p>Sets the <code>DSTAMP</code>, <code>TSTAMP</code>, and
-     <code>TODAY</code> properties in the current project, based on
-     the current date and time.</p></td>
+  <tr>
+    <td><a href="Tasks/tstamp.html">TStamp</a></td>
+    <td><p>Sets the <code>DSTAMP</code>, <code>TSTAMP</code>,
+     and <code>TODAY</code> properties in the current project, based
+     on the current date and time.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/typedef.html">Typedef</a></td>
-    <td><p>Adds a data-type definition to the current project, such that this
-     new type can be used in the current project.</p></td>
+  <tr>
+    <td><a href="Tasks/typedef.html">Typedef</a></td>
+    <td><p>Adds a data-type definition to the current project, such
+     that this new type can be used in the current project.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/xmlvalidate.html">XmlValidate</a></td>
-    <td><p>Checks that XML files are valid (or only well-formed). This task
-     uses the XML parser that is currently used by Ant by default, but any SAX1/2
-     parser can be specified, if needed.</p></td>
+  <tr>
+    <td><a href="Tasks/xmlvalidate.html">XmlValidate</a></td>
+    <td><p>Checks that XML files are valid (or only well-formed). This
+     task uses the XML parser that is currently used by Ant by
+     default, but any SAX1/2 parser can be specified, if
+     needed.</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="preproc">Pre-process Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="preproc">
+    <span class="left">Pre-process Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/antlr.html">ANTLR</a></td>
-    <td><p>Invokes the <a HREF="http://www.antlr.org/" target="_top">ANTLR</a>
-     Translator generator on a grammar file.</p></td>
+  <tr>
+    <td><a href="Tasks/antlr.html">ANTLR</a></td>
+    <td><p>Invokes the <a href="https://www.antlr.org/"
+     target="_top">ANTLR</a> Translator generator on a grammar
+     file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/antstructure.html">AntStructure</a></td>
-    <td><p>Generates a DTD for Ant buildfiles that contains information
-     about all tasks currently known to Ant.</p></td>
+  <tr>
+    <td><a href="Tasks/antstructure.html">AntStructure</a></td>
+    <td><p>Generates a DTD for Ant buildfiles that contains
+     information about all tasks currently known to Ant.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/import.html">Import</a></td>
-    <td><p>Import another build file and potentially override targets
-    in it with targets of your own.</p></td>
+  <tr>
+    <td><a href="Tasks/import.html">Import</a></td>
+    <td><p>Imports another build file and potentially overrides
+     targets in it with targets of your own.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/include.html">Include</a></td>
-    <td><p>Include another build file.</p></td>
+  <tr>
+    <td><a href="Tasks/include.html">Include</a></td>
+    <td><p>Includes another build file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/javacc.html">JavaCC</a></td>
-    <td><p>Invokes the
-     <a HREF="http://javacc.dev.java.net/" target="_top">
-     JavaCC</a> compiler-compiler on a grammar file.</p></td>
+  <tr>
+    <td><a href="Tasks/javacc.html">JavaCC</a></td>
+    <td><p>Invokes the <a href="https://javacc.org/"
+     target="_top">JavaCC</a> compiler-compiler on a grammar
+     file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/javah.html">Javah</a></td>
+  <tr>
+    <td><a href="Tasks/javah.html">Javah</a></td>
     <td><p>Generates JNI headers from a Java class.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/jjdoc.html">JJDoc</a></td>
-    <td><p>Invokes the <a href="http://javacc.dev.java.net/">
-     JJDoc</a> documentation generator for the JavaCC compiler-compiler.
-     JJDoc takes a JavaCC parser specification and produces documentation
-     for the BNF grammar.  It can operate in three modes, determined by
-     command line options. This task only invokes JJDoc if the grammar file
-     is newer than the generated BNF grammar documentation.</p></td>
+  <tr>
+    <td><a href="Tasks/jjdoc.html">JJDoc</a></td>
+    <td><p>Invokes the <a href="https://javacc.org/"
+     target="_top">JJDoc</a> documentation generator for the JavaCC
+     compiler-compiler.  JJDoc takes a JavaCC parser specification and
+     produces documentation for the BNF grammar.  It can operate in
+     three modes, determined by command line options. This task only
+     invokes JJDoc if the grammar file is newer than the generated BNF
+     grammar documentation.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/jjtree.html">JJTree</a></td>
-    <td><p>Invokes the <a href="http://javacc.dev.java.net/">
-     JJTree</a> preprocessor for the JavaCC compiler-compiler. It inserts
-     parse-tree building actions at various places in the JavaCC source that
-     it generates. The output of JJTree is run through JavaCC to create the
-     parser. This task only invokes JJTree if the grammar file is newer than
-     the generated JavaCC file.</p></td>
+  <tr>
+    <td><a href="Tasks/jjtree.html">JJTree</a></td>
+    <td><p>Invokes the <a href="https://javacc.org/"
+     target="_top">JJTree</a> preprocessor for the JavaCC
+     compiler-compiler. It inserts parse-tree building actions at
+     various places in the JavaCC source that it generates. The output
+     of JJTree is run through JavaCC to create the parser. This task
+     only invokes JJTree if the grammar file is newer than the
+     generated JavaCC file.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/macrodef.html">Macrodef</a></td>
-    <td><p>Define a new task as a macro built-up upon other tasks.</p></td>
+  <tr>
+    <td><a href="Tasks/macrodef.html">Macrodef</a></td>
+    <td><p>Defines a new task as a macro built-up upon other tasks.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/native2ascii.html">
-     Native2Ascii</a></td>
-    <td><p>Converts files from native encodings to ASCII with escaped Unicode.
-      A common usage is to convert source files maintained in a native
-      operating system encoding to ASCII, prior to compilation.</p></td>
+  <tr>
+    <td><a href="Tasks/native2ascii.html">Native2Ascii</a></td>
+    <td><p>Converts files from native encodings to ASCII with escaped
+     Unicode.  A common usage is to convert source files maintained in
+     a native operating system encoding to ASCII, prior to
+     compilation.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/presetdef.html">Presetdef</a></td>
-    <td><p>Define a new task by instrumenting an existing task with
-    default values for attributes or child elements.</p>
+  <tr>
+    <td><a href="Tasks/presetdef.html">Presetdef</a></td>
+    <td><p>Defines a new task by instrumenting an existing task with
+     default values for attributes or child elements.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/translate.html">Translate</a></td>
+  <tr>
+    <td><a href="Tasks/translate.html">Translate</a></td>
     <td><p>Identifies keys in files, delimited by special tokens, and
      translates them with values read from resource bundles.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/style.html">XSLT</a></td>
+  <tr>
+    <td><a href="Tasks/style.html">XSLT</a></td>
     <td><p>Processes a set of documents via XSLT.</p></td>
   </tr>
-
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="prop">Property Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="prop">
+    <span class="left">Property Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/available.html">Available</a></td>
-    <td><p>Sets a property if a specified file, directory, class in the
-     classpath, or JVM system resource is available at runtime.</p></td>
+  <tr>
+    <td><a href="Tasks/available.html">Available</a></td>
+    <td><p>Sets a property if a specified file, directory, class in
+     the classpath, or JVM system resource is available at
+     run time.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/basename.html">Basename</a></td>
-    <td><p>Sets a property to the last element of a specified path.
+  <tr>
+    <td><a href="Tasks/basename.html">Basename</a></td>
+    <td><p>Sets a property to the last element of a specified path.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/buildnumber.html">BuildNumber</a></td>
-    <td><p>Task that can be used to track build numbers.
+  <tr>
+    <td><a href="Tasks/buildnumber.html">BuildNumber</a></td>
+    <td><p>Helps tracking build numbers.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/condition.html">Condition</a></td>
-    <td><p>Sets a property if a certain condition holds true; this is a
-     generalization of <a href="Tasks/available.html">Available</a> and
-     <a href="Tasks/uptodate.html">Uptodate</a>.</p></td>
+  <tr>
+    <td><a href="Tasks/condition.html">Condition</a></td>
+    <td><p>Sets a property if a certain condition holds true; this is
+     a generalization of <a href="Tasks/available.html">Available</a>
+     and <a href="Tasks/uptodate.html">Uptodate</a>.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/dirname.html">Dirname</a></td>
+  <tr>
+    <td><a href="Tasks/dirname.html">Dirname</a></td>
     <td><p>Sets a property to the value of the specified file up to,
-     but not including, the last path element.
+     but not including, the last path element.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap>
-    <a href="Tasks/echoproperties.html">Echoproperties</a><br>
-
-    </td>
+  <tr>
+    <td><a href="Tasks/echoproperties.html">Echoproperties</a></td>
     <td><p>Lists the current properties.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/loadfile.html">LoadFile</a></td>
+  <tr>
+    <td><a href="Tasks/loadfile.html">LoadFile</a></td>
     <td><p>Loads a file into a property.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/loadproperties.html">LoadProperties</a></td>
-    <td><p>Load a file's contents as Ant properties. This task is
-     equivalent to using <code>&lt;property file=&quot;...&quot;/&gt;</code>
-     except that it supports nested <code>&lt;filterchain&gt;</code> elements,
-     and it cannot be specified outside a target.</p></td>
+  <tr>
+    <td><a href="Tasks/loadproperties.html">LoadProperties</a></td>
+    <td><p>Loads a file's contents as Ant properties. This task is
+     equivalent to using <code>&lt;property
+     file=&quot;...&quot;/&gt;</code> except that it supports
+     nested <code>&lt;filterchain&gt;</code> elements, and it cannot
+     be specified outside a target.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/makeurl.html">MakeURL</a></td>
+  <tr>
+    <td><a href="Tasks/makeurl.html">MakeURL</a></td>
     <td><p>Creates a URL (list) from a file/fileset or path</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/pathconvert.html">PathConvert</a></td>
-    <td><p>Converts a nested path, path reference, filelist reference, or
-     fileset reference to the form usable on a specified platform and/or
-     to a list of items separated by the specified separator and stores
-     the result in the specified property.</p></td>
+  <tr>
+    <td><a href="Tasks/pathconvert.html">PathConvert</a></td>
+    <td><p>Converts a nested path, path reference, filelist reference,
+     or fileset reference to the form usable on a specified platform
+     and/or to a list of items separated by the specified separator
+     and stores the result in the specified property.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/property.html">Property</a></td>
+  <tr>
+    <td><a href="Tasks/property.html">Property</a></td>
     <td><p>Sets a property (by name and value), or set of properties
      (from a file or resource) in the project.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/propertyfile.html">
-     PropertyFile</a></td>
-    <td><p>Creates or modifies property files. Useful when wanting to make
-     unattended modifications to configuration files for application
-     servers and applications. Typically used for things such as
-     automatically generating a build number and saving it to a build
-     properties file, or doing date manipulation.<p></td>
+  <tr>
+    <td><a href="Tasks/propertyfile.html">PropertyFile</a></td>
+    <td><p>Creates or modifies property files. Useful when wanting to
+     make unattended modifications to configuration files for
+     application servers and applications. Typically used for things
+     such as automatically generating a build number and saving it to
+     a build properties file, or doing date manipulation.<p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/uptodate.html">Uptodate</a></td>
-    <td><p>Sets a property if a given target file is newer than a set of
-     source files.</p></td>
+  <tr>
+    <td><a href="Tasks/uptodate.html">Uptodate</a></td>
+    <td><p>Sets a property if a given target file is newer than a set
+     of source files.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/whichresource.html">Whichresource</a></td>
-    <td><p>Find a class or resource.</p></td>
+  <tr>
+    <td><a href="Tasks/whichresource.html">Whichresource</a></td>
+    <td><p>Finds a class or resource.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/xmlproperty.html">XmlProperty</a></td>
+  <tr>
+    <td><a href="Tasks/xmlproperty.html">XmlProperty</a></td>
     <td><p>Loads property values from a well-formed XML file.</p></td>
   </tr>
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="remote">Remote Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="remote">
+    <span class="left">Remote Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/ftp.html">FTP</a></td>
-    <td><p>Implements a basic FTP client that can send, receive,
-     list, and delete files, and create directories.</p></td>
+  <tr>
+    <td><a href="Tasks/ftp.html">FTP</a></td>
+    <td><p>Implements a basic FTP client that can send, receive, list,
+     and delete files, and create directories.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/rexec.html">Rexec</a></td>
-    <td><p>Task to automate a remote rexec session.</p></td>
+  <tr>
+    <td><a href="Tasks/rexec.html">Rexec</a></td>
+    <td><p>Automates a <code>rexec</code> session.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/scp.html">Scp</a></td>
-    <td><p>Copy files to or from a remote server using SSH.</p></td>
+  <tr>
+    <td><a href="Tasks/scp.html">Scp</a></td>
+    <td><p>Copies files to or from a remote server using SSH.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/setproxy.html">setproxy</a></td>
-    <td><p>Sets Java's web proxy properties, so that tasks and code run
- in the same JVM can have through-the-firewall access to remote web sites.</p></td>
+  <tr>
+    <td><a href="Tasks/setproxy.html">setproxy</a></td>
+    <td><p>Sets Java's HTTP proxy properties, so that tasks and code
+     run in the same JVM can have access to remote web sites through a
+     firewall.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/sshexec.html">Sshexec</a></td>
-    <td><p>Execute a command on a remote server using SSH.</p></td>
+  <tr>
+    <td><a href="Tasks/sshexec.html">Sshexec</a></td>
+    <td><p>Executes a command on a remote server using SSH.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/telnet.html">Telnet</a></td>
-    <td><p>Task to automate a remote <i>telnet</i> session. This task uses
-     nested <code>&lt;read&gt;</code> and <code>&lt;write&gt;</code> tags
-     to indicate strings to wait for and specify text to send.</p></td>
+  <tr>
+    <td><a href="Tasks/telnet.html">Telnet</a></td>
+    <td><p>Automates a <code>telnet</code> session. This task uses
+     nested <code>&lt;read&gt;</code> and <code>&lt;write&gt;</code>
+     tags to indicate strings to wait for and specify text to
+     send.</p></td>
   </tr>
-
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="scm">SCM Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
-</table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
+<div class="float" id="scm">
+    <span class="left">SCM Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/cvs.html">Cvs</a></td>
-    <td><p>Handles packages/modules retrieved from a
-     <a href="http://www.nongnu.org/cvs/" target="_top">CVS</a>
+  <tr>
+    <td><a href="Tasks/cvs.html">Cvs</a></td>
+    <td><p>Handles packages/modules retrieved from
+     a <a href="https://www.nongnu.org/cvs/" target="_top">CVS</a>
      repository.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/changelog.html">CvsChangeLog</a></td>
-    <td><p>Generates an XML report of the changes recorded in a
-     <a href="http://www.nongnu.org/cvs/" target="_top">CVS</a>
+  <tr>
+    <td><a href="Tasks/changelog.html">CvsChangeLog</a></td>
+    <td><p>Generates an XML report of the changes recorded in
+     a <a href="https://www.nongnu.org/cvs/" target="_top">CVS</a>
      repository.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/cvspass.html">CVSPass</a></td>
-    <td><p>Adds entries to a .cvspass file. Adding entries to this file
-     has the same affect as a <i>cvs login</i> command.</p></td>
+  <tr>
+    <td><a href="Tasks/cvspass.html">CVSPass</a></td>
+    <td><p>Adds entries to a <samp>.cvspass</samp> file. Adding
+     entries to this file has the same affect as a <kbd>cvs
+     login</kbd> command.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/cvstagdiff.html">CvsTagDiff</a></td>
-    <td><p>Generates an XML-formatted report file of the changes between
-    two tags or dates recorded in a <a href="http://www.nongnu.org/cvs/"
-    target="_top">CVS</a> repository.</p></td>
+  <tr>
+    <td><a href="Tasks/cvstagdiff.html">CvsTagDiff</a></td>
+    <td><p>Generates an XML-formatted report file of the changes
+     between two tags or dates recorded in
+     a <a href="https://www.nongnu.org/cvs/" target="_top">CVS</a>
+     repository.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/clearcase.html">ClearCase</a></td>
-    <td><p>Tasks to perform the ClearCase cleartool <i>checkin</i>, <i>checkout</i>,
-     <i>uncheckout</i>, <i>update</i>, <i>lock</i>, <i>unlock</i>, <i>mklbtype</i>, <i>rmtype</i>, <i>mklabel</i>, <i>mkattr</i>, <i>mkdir</i>, <i>mkelem</i>, and <i>mkbl</i> commands.</p></td>
+  <tr>
+    <td><a href="Tasks/clearcase.html">ClearCase</a></td>
+    <td><p>Tasks to perform the ClearCase <kbd>cleartool checkin</kbd>,
+     <kbd>checkout</kbd>, <kbd>uncheckout</kbd>, <kbd>update</kbd>,
+     <kbd>lock</kbd>, <kbd>unlock</kbd>, <kbd>mklbtype</kbd>, <kbd>rmtype</kbd>,
+     <kbd>mklabel</kbd>, <kbd>mkattr</kbd>, <kbd>mkdir</kbd>, <kbd>mkelem</kbd>,
+     and <kbd>mkbl</kbd> commands.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/ccm.html">Continuus/Synergy</a></td>
-    <td><p>Tasks to perform the Continuus <i>ccmcheckin</i>,
-     <i>ccmcheckout</i>, <i>ccmcheckintask</i>, <i>ccmreconfigure</i>, and
-     <i>ccmcreateTask</i> commands.</p></td>
+  <tr>
+    <td><a href="Tasks/ccm.html">Continuus/Synergy</a></td>
+    <td><p>Tasks to perform the Continuus <kbd>ccm checkin</kbd>,
+     <kbd>checkout</kbd>, <kbd>reconfigure</kbd>, <em>ccmcheckintask</em>,
+     and <em>ccmcreatetask</em> commands.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/vss.html">
-     Microsoft Visual SourceSafe</a></td>
-    <td><p>Tasks to perform the Visual SourceSafe <i>vssget</i>,
-     <i>vsslabel</i>, <i>vsshistory</i>, <i>vsscheckin</i>,
-     <i>vsscheckout</i>, <i>vssadd</i>, <i>vsscp</i>, and <i>vsscreate</i>
-     commands.</p></td>
+  <tr>
+    <td><a href="Tasks/vss.html">Microsoft Visual SourceSafe</a></td>
+    <td><p>Tasks to perform the Visual SourceSafe <kbd>ss get</kbd>,
+     <kbd>label</kbd>, <kbd>history</kbd>, <kbd>checkin</kbd>,
+     <kbd>checkout</kbd>, <kbd>add</kbd>, <kbd>cp</kbd>,
+     and <kbd>create</kbd> commands.</p></td>
   </tr>
 
-
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/pvcstask.html">Pvcs</a></td>
-    <td><p>Allows the user extract the latest edition of the source code
-     from a PVCS repository.</p></td>
+  <tr>
+    <td><a href="Tasks/pvcstask.html">Pvcs</a></td>
+    <td><p>Allows the user extract the latest edition of the source
+     code from a PVCS repository.</p></td>
   </tr>
 
-  <tr valign="top">
-    <td nowrap><a href="Tasks/sos.html">SourceOffSite</a></td>
-    <td><p>Tasks to perform the SourceOffSite <i>sosget</i>, <i>soslabel</i>,
-     <i>soscheckin</i>, and <i>soscheckout</i> commands.</p></td>
+  <tr>
+    <td><a href="Tasks/sos.html">SourceOffSite</a></td>
+    <td><p>Tasks to perform the SourceOffSite <kbd>sos get</kbd>, <kbd>label</kbd>,
+     <kbd>checkin</kbd>, and <kbd>checkout</kbd> commands.</p></td>
   </tr>
-
 </table>
 
-<p></p>
-<table width="100%" border="0" cellpadding="4" cellspacing="0">
-<th align="left">
-<font size="+0" face="arial,helvetica,sanserif">
-<a name="testing">Testing Tasks</a>
-</font></th>
-<font size="-1" face="arial,helvetica,sanserif">
-<th align="right"><a href="#top">[Back to top]</a></th>
-</font>
+<div class="float" id="testing">
+    <span class="left">Testing Tasks</span>
+    <span class="right"><a href="#top" style="text-decoration:none;">&#x1f51d;</a></span>
+</div>
+
+<table>
+  <tr>
+    <th scope="col">Task Name</th>
+    <th scope="col">Description</th>
+  </tr>
+
+  <tr>
+    <td><a href="Tasks/junit.html">Junit</a></td>
+    <td><p>Runs tests from the <a href="https://junit.org"
+     target="_top">Junit</a> testing framework. This task has been
+     tested with JUnit 3.0 and later; it won't work with versions
+     prior to JUnit 3.0.</p></td>
+  </tr>
+
+  <tr>
+    <td><a href="Tasks/junitreport.html">JunitReport</a></td>
+    <td><p>Merges the individual XML files generated by
+     the <a href="Tasks/junit.html">Junit</a> task and applies a
+     stylesheet on the resulting merged document to provide a
+     browsable report of the testcases results.</p></td>
+  </tr>
 </table>
-<table width="100%" border="1" cellpadding="4" cellspacing="0">
-  <tr valign="top">
-    <th nowrap>Task Name</th>
-    <th>Description</th>
-  </tr>
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/junit.html">Junit</a></td>
-    <td><p>Runs tests from the <a href="http://www.junit.org">Junit</a>
-     testing framework. This task has been tested with JUnit 3.0 up to
-     JUnit 3.7; it won't work with versions prior to JUnit 3.0.</p></td>
-  </tr>
-
-  <tr valign="top">
-    <td nowrap><a href="Tasks/junitreport.html">JunitReport</a></td>
-    <td><p>Merges the individual XML files generated by the
-     <a href="Tasks/junit.html">Junit</a> task and applies a
-     stylesheet on the resulting merged document to provide a browsable
-     report of the testcases results.</p></td>
-  </tr>
-
-</table>
-
-
-
 
 </body>
 </html>
diff --git a/manual/toc.html b/manual/toc.html
index 91d9824..3e44694 100644
--- a/manual/toc.html
+++ b/manual/toc.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -48,4 +48,3 @@
 
 </body>
 </html>
-
diff --git a/manual/tutorial-HelloWorldWithAnt.html b/manual/tutorial-HelloWorldWithAnt.html
index babd9b4..e45efbf 100644
--- a/manual/tutorial-HelloWorldWithAnt.html
+++ b/manual/tutorial-HelloWorldWithAnt.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
   <title>Tutorial: Hello World with Apache Ant</title>
   <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
@@ -22,84 +23,70 @@
 <body>
 <h1>Tutorial: Hello World with Apache Ant</h1>
 
-<p>This document provides a step by step tutorial for starting java programming with Apache Ant.
-It does <b>not</b> contain deeper knowledge about Java or Ant. This tutorial has the goal
-to let you see, how to do the easiest steps in Ant.</p>
-
-
+<p>This document provides a step by step tutorial for starting Java programming with Apache Ant. It
+does <strong>not</strong> contain deeper knowledge about Java or Ant. This tutorial has the goal to let you see, how to
+do the easiest steps in Ant.</p>
 
 <h2>Content</h2>
-<p><ul>
+<ul>
 <li><a href="#prepare">Preparing the project</a></li>
-<li><a href="#four-steps">Enhance the build file</a></li>
+<li><a href="#four-steps">Four steps to a running application</a></li>
 <li><a href="#enhance">Enhance the build file</a></li>
 <li><a href="#ext-libs">Using external libraries</a></li>
 <li><a href="#resources">Resources</a></li>
-</ul></p>
+</ul>
 
+<h2 id="prepare">Preparing the project</h2>
+<p>We want to separate the source from the generated files, so our Java source files will be in <samp>src</samp>
+folder. All generated files should be under <samp>build</samp>, and there split into several subdirectories for the
+individual steps: <samp>classes</samp> for our compiled files and <samp>jar</samp> for our own JAR-file.</p>
 
-<a name="prepare"></a>
-<h2>Preparing the project</h2>
-<p>We want to separate the source from the generated files, so our java source files will
-be in <tt>src</tt> folder. All generated files should be under <tt>build</tt>, and there
-splitted into several subdirectories for the individual steps: <tt>classes</tt> for our compiled
-files and <tt>jar</tt> for our own JAR-file.</p>
-<p>We have to create only the <tt>src</tt> directory. (Because I am working on Windows, here is 
-the win-syntax - translate to your shell):</p>
+<p>We have to create only the <samp>src</samp> directory. (Because I am working on Windows, here is the Windows
+syntax&mdash;translate to your shell):</p>
 
-<pre class="code">
-md src
-</pre>
+<pre class="input">md src</pre>
 
-<p>The following simple Java class just prints a fixed message out to STDOUT,
-so just write this code into <tt>src\oata\HelloWorld.java</tt>.</p>
+<p>The following simple Java class just prints a fixed message out to STDOUT, so just write this code
+into <samp>src\oata\HelloWorld.java</samp>.</p>
 
-<pre class="code">
+<pre>
 package oata;
 
 public class HelloWorld {
     public static void main(String[] args) {
         System.out.println("Hello World");
     }
-}
-</pre>
+}</pre>
 
-<p>Now just try to compile and run that:
-<pre class="code">
+<p>Now just try to compile and run that:</p>
+<pre class="input">
 md build\classes
 javac -sourcepath src -d build\classes src\oata\HelloWorld.java
-java -cp build\classes oata.HelloWorld
-</pre>
+java -cp build\classes oata.HelloWorld</pre>
 which will result in
-<pre class="output">
-Hello World
-</pre>
-</p>
+<pre class="output">Hello World</pre>
 
-<p>Creating a jar-file is not very difficult. But creating a <i>startable</i> jar-file needs more steps: create a
+<p>Creating a jar-file is not very difficult. But creating a <em>startable</em> jar-file needs more steps: create a
 manifest-file containing the start class, creating the target directory and archiving the files.</p>
-<pre class="code">
+<pre class="input">
 echo Main-Class: oata.HelloWorld&gt;myManifest
 md build\jar
 jar cfm build\jar\HelloWorld.jar myManifest -C build\classes .
-java -jar build\jar\HelloWorld.jar
-</pre>
+java -jar build\jar\HelloWorld.jar</pre>
 
-<p><b>Note:</b> Do not have blanks around the &gt;-sign in the <tt>echo Main-Class</tt> instruction because it would 
-falsify it!</p>
+<p><strong>Note</strong>: Do not have blanks around the &gt;-sign in the <kbd>echo Main-Class</kbd> instruction because
+it would falsify it!</p>
 
+<h2 id="four-steps">Four steps to a running application</h2>
+<p>After finishing the Java-only step we have to think about our build process. We <em>have</em> to compile our code,
+otherwise we couldn't start the program. Oh&mdash;<q>start</q>&mdash;yes, we could provide a target for
+that. We <em>should</em> package our application.  Now it's only one class&mdash;but if you want to provide a download,
+no one would download several hundreds files ...  (think about a complex Swing GUI&mdash;so let us create a jar file. A
+startable jar file would be nice ... And it's a good practise to have a <q>clean</q> target, which deletes all the
+generated stuff. Many failures could be solved just by a "clean build".</p>
 
-<a name="four-steps"></a>
-<h2>Four steps to a running application</h2>
-<p>After finishing the java-only step we have to think about our build process. We <i>have</i> to compile our code, otherwise we couldn't
-start the program. Oh - "start" - yes, we could provide a target for that. We <i>should</i> package our application.
-Now it's only one class - but if you want to provide a download, no one would download several hundreds files ...
-(think about a complex Swing GUI - so let us create a jar file. A startable jar file would be nice ... And it's a
-good practise to have a "clean" target, which deletes all the generated stuff. Many failures could be solved just
-by a "clean build".</p>
-
-<p>By default Ant uses <tt>build.xml</tt> as the name for a buildfile, so our <tt>.\build.xml</tt> would be:</p>
-<pre class="code">
+<p>By default Ant uses <samp>build.xml</samp> as the name for a buildfile, so our <samp>.\build.xml</samp> would be:</p>
+<pre>
 &lt;project&gt;
 
     &lt;target name="clean"&gt;
@@ -124,28 +111,24 @@
         &lt;java jar="build/jar/HelloWorld.jar" fork="true"/&gt;
     &lt;/target&gt;
 
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
 <p>Now you can compile, package and run the application via</p>
-<pre class="code">
+<pre class="input">
 ant compile
 ant jar
-ant run
-</pre>
+ant run</pre>
 <p>Or shorter with</p>
-<pre class="code">
-ant compile jar run
-</pre>
+<pre class="input">ant compile jar run</pre>
 
-<p>While having a look at the buildfile, we will see some similar steps between Ant and the java-only commands:
+<p>While having a look at the buildfile, we will see some similar steps between Ant and the Java-only commands:</p>
 <table>
 <tr>
-  <th>java-only</th>
-  <th>Ant</th>
+  <th scope="col">Java-only</th>
+  <th scope="col">Ant</th>
 </tr>
 <tr>
-  <td valign="top"><pre class="code">
+  <td><pre class="input">
 md build\classes
 javac
     -sourcepath src
@@ -161,15 +144,14 @@
 
 
 
-java -jar build\jar\HelloWorld.jar
-  </pre></td>
-  <td valign="top"><pre class="code">
+java -jar build\jar\HelloWorld.jar</pre></td>
+  <td><pre>
 &lt;mkdir dir="build/classes"/&gt;
 &lt;javac
     srcdir="src"
     destdir="build/classes"/&gt;
-<i>&lt;!-- automatically detected --&gt;</i>
-<i>&lt;!-- obsolete; done via manifest tag --&gt;</i>
+<em>&lt;!-- automatically detected --&gt;</em>
+<em>&lt;!-- obsolete; done via manifest tag --&gt;</em>
 &lt;mkdir dir="build/jar"/&gt;
 &lt;jar
     destfile="build/jar/HelloWorld.jar"
@@ -179,23 +161,18 @@
         &lt;attribute name="Main-Class" value="oata.HelloWorld"/&gt;
     &lt;/manifest&gt;
 &lt;/jar&gt;
-&lt;java jar="build/jar/HelloWorld.jar" fork="true"/&gt;
-  </pre></td>
-</tr></table>
-</p>
+&lt;java jar="build/jar/HelloWorld.jar" fork="true"/&gt;</pre></td>
+</tr>
+</table>
 
+<h2 id="enhance">Enhance the build file</h2>
+<p>Now that we have a working buildfile, we could do some enhancements: many times you are referencing the same
+directories, main-class and jar-name are hardcoded, and while invoking you have to remember the right order of build
+steps.</p>
+<p>The first and second point would be addressed with <em>properties</em>, the third with a special property&mdash;an
+attribute of the <code>&lt;project&gt;</code> tag and the fourth problem can be solved using dependencies.</p>
 
-
-<a name="enhance"></a>
-<h2>Enhance the build file</h2>
-<p>Now we have a working buildfile we could do some enhancements: many time you are referencing the
-same directories, main-class and jar-name are hard coded, and while invocation you have to remember
-the right order of build steps.</p>
-<p>The first and second point would be addressed with <i>properties</i>, the third with a special property - an attribute
-of the &lt;project&gt;-tag and the fourth problem can be solved using dependencies.</p>
-
-
-<pre class="code">
+<pre>
 &lt;project name="HelloWorld" basedir="." default="main"&gt;
 
     &lt;property name="src.dir"     value="src"/&gt;
@@ -234,11 +211,9 @@
 
     &lt;target name="main" depends="clean,run"/&gt;
 
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-
-<p>Now it's easier, just do a <tt class="code">ant</tt> and you will get</p>
+<p>Now it's easier, just do a <kbd>ant</kbd> and you will get</p>
 <pre class="output">
 Buildfile: build.xml
 
@@ -257,29 +232,27 @@
 
 main:
 
-BUILD SUCCESSFUL
-</pre>
+BUILD SUCCESSFUL</pre>
 
-
-<a name="ext-libs"></a>
-<h2>Using external libraries</h2>
-<p>Somehow told us not to use syso-statements. For log-Statements we should use a Logging-API - customizable on a high
-degree (including switching off during usual life (= not development) execution). We use Log4J for that, because <ul>
-<li>it is not part of the JDK (1.4+) and we want to show how to use external libs</li>
-<li>it can run under JDK 1.2 (as Ant)</li>
+<h2 id="ext-libs">Using external libraries</h2>
+<p>Somebody told us not to use <code>System</code>-statements. For output, we should use a Logging
+API&mdash;customizable to a high degree (including switching off during usual life (= not development) execution). We
+use Log4J for that, because</p>
+<ul>
+<li>it is not part of the JDK and we want to show how to use external libs</li>
 <li>it's highly configurable</li>
 <li>it's from Apache ;-)</li>
-</ul></p>
-<p>We store our external libraries in a new directory <tt>lib</tt>. Log4J can be
-<a href="http://www.apache.org/dist/logging/log4j/1.2.13/logging-log4j-1.2.13.zip">downloaded [1]</a> from Logging's Homepage.
-Create the <tt>lib</tt> directory and extract the log4j-1.2.9.jar into that lib-directory. After that we have to modify
-our java source to use that library and our buildfile so that this library could be accessed during compilation and run.
-</p>
-<p>Working with Log4J is documented inside its manual. Here we use the <i>MyApp</i>-example from the
-<a href="http://logging.apache.org/log4j/docs/manual.html">Short Manual [2]</a>. First we have to modify the java source to
-use the logging framework:</p>
+</ul>
+<p>We store our external libraries in a new directory <samp>lib</samp>. Log4J can
+be <a href="https://archive.apache.org/dist/logging/log4j/1.2.17/log4j-1.2.17.zip" target="_top">downloaded
+[1]</a> from Logging's Homepage.  Create the <samp>lib</samp> directory and extract the <samp>log4j-1.2.17.jar</samp>
+into that directory. After that we have to modify our Java source file to use that library and our buildfile so that
+this library could be accessed during compilation and run.</p>
+<p>Working with Log4J is documented inside its manual. Here we use the <samp>MyApp</samp>-example from
+the <a href="https://logging.apache.org/log4j/1.2/manual.html" target="_top">Short Manual [2]</a>. First we have to
+modify the java source to use the logging framework:</p>
 
-<pre class="code">
+<pre>
 package oata;
 
 <b>import org.apache.log4j.Logger;</b>
@@ -290,19 +263,19 @@
 
     public static void main(String[] args) {
         <b>BasicConfigurator.configure();</b>
-        <font color="blue"><b>logger.info("Hello World");</b></font>          // the old SysO-statement
+        <span style="color:blue"><b>logger.info("Hello World");</b></span>          // the old SysO-statement
     }
-}
-</pre>
+}</pre>
 
 <p>Most of the modifications are "framework overhead" which has to be done once. The blue line is our "old System-out"
 statement.</p>
-<p>Don't try to run <tt>ant</tt> - you will only get lot of compiler errors. Log4J is not inside the classpath so we have
-to do a little work here. But do not change the CLASSPATH environment variable! This is only for this project and maybe
-you would break other environments (this is one of the most famous mistakes when working with Ant). We introduce Log4J
-(or to be more precise: all libraries (jar-files) which are somewhere under <tt>.\lib</tt>) into our buildfile:</p>
+<p>Don't try to run <kbd>ant</kbd>&mdash;you will only get lot of compiler errors. Log4J is not on the classpath so we
+have to do a little work here. But do not change the <code>CLASSPATH</code> environment variable! This is only for this
+project and maybe you would break other environments (this is one of the most famous mistakes when working with Ant). We
+introduce Log4J (or to be more precise: all libraries (jar-files) which are somewhere under <samp>.\lib</samp>) into our
+buildfile:</p>
 
-<pre class="code">
+<pre>
 &lt;project name="HelloWorld" basedir="." default="main"&gt;
     ...
     <b>&lt;property name="lib.dir"     value="lib"/&gt;</b>
@@ -322,59 +295,57 @@
         &lt;java fork="true" <b>classname="${main-class}"</b>&gt;
             <b>&lt;classpath&gt;</b>
                 <b>&lt;path refid="classpath"/&gt;</b>
-                <font color="red"><b>&lt;path location="${jar.dir}/${ant.project.name}.jar"/&gt;</b></font>
+                <span style="color:red"><b>&lt;path location="${jar.dir}/${ant.project.name}.jar"/&gt;</b></span>
             <b>&lt;/classpath&gt;</b>
         &lt;/java&gt;
     &lt;/target&gt;
 
     ...
 
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>In this example we start our application not via its Main-Class manifest-attribute, because we could not provide
-a jarname <i>and</i> a classpath. So add our class in the red line to the already defined path and start as usual. Running
-<tt>ant</tt> would give (after the usual compile stuff):</p>
+<p>In this example we start our application not via its <code>Main-Class</code> manifest-attribute, because we could not
+provide a jar-name <em>and</em> a classpath. So add our class in the red line to the already defined path and start as
+usual. Running <kbd>ant</kbd> would give (after the usual compile stuff):</p>
 
-<pre class="output">
-[java] 0 [main] INFO oata.HelloWorld  - Hello World
-</pre>
+<pre class="output">[java] 0 [main] INFO oata.HelloWorld  - Hello World</pre>
 
-<p>What's that? <ul>
-<li><i>[java]</i> Ant task running at the moment</li>
-<li><i>0</i> <font size="-1">sorry don't know - some Log4J stuff</font></li>
-<li><i>[main]</i> the running thread from our application </li>
-<li><i>INFO</i> log level of that statement</i>
-<li><i>oata.HelloWorld</i> source of that statement</i>
-<li><i>-</i> separator</li>
-<li><i>Hello World</i> the message</li>
+<p>What's that?</p>
+<ul>
+<li><code>[java]</code> Ant task running at the moment</li>
+<li><code>0</code> <small>sorry, don't know&mdash;some Log4J stuff</small></li>
+<li><code>[main]</code> the running thread from our application</li>
+    <li><code>INFO</code> log level of that statement</li>
+    <li><code>oata.HelloWorld</code> source of that statement</li>
+<li><code>-</code> separator</li>
+<li><code>Hello World</code> the message</li>
 </ul>
-For another layout ... have a look inside Log4J's documentation about using other PatternLayout's.</p>
+<p>For another layout ... have a look inside Log4J's documentation about using other PatternLayouts.</p>
 
+<h2 id="config-files">Configuration files</h2>
+<p>Why we have used Log4J? "It's highly configurable"? No&mdash;all is hardcoded! But that is not the fault of
+Log4J&mdash;it's ours. We had coded <code class="code">BasicConfigurator.configure();</code> which implies a simple, but
+hardcoded configuration. More comfortable would be using a property file. In the Java source file, delete
+the <code class="code">BasicConfiguration</code> line from the <code class="code">main()</code> method (and the
+related <code>import</code> statement). Log4J will search then for a configuration as described in its manual. Then
+create a new file <samp>src/log4j.properties</samp>. That's the default name for Log4J's configuration and using that
+name would make life easier&mdash;not only the framework knows what is inside, you too!</p>
 
-<a name="config-files">
-<h2>Configuration files</h2>
-<p>Why we have used Log4J? "It's highly configurable"? No - all is hard coded! But that is not the debt of Log4J - it's
-ours. We had coded <tt>BasicConfigurator.configure();</tt> which implies a simple, but hard coded configuration. More
-comfortable would be using a property file. In the java source delete the BasicConfiguration-line from the main() method
-(and the related import-statement). Log4J will search then for a configuration as described in it's manual. Then create 
-a new file <tt>src/log4j.properties</tt>. That's the default name for Log4J's configuration and using that name would make 
-life easier - not only the framework knows what is inside, you too!</p>
-
-<pre class="code">
+<pre>
 log4j.rootLogger=DEBUG, <b>stdout</b>
 
 log4j.appender.<b>stdout</b>=org.apache.log4j.ConsoleAppender
 
 log4j.appender.<b>stdout</b>.layout=org.apache.log4j.PatternLayout
-log4j.appender.<b>stdout</b>.layout.ConversionPattern=<font color="blue"><b>%m%n</b></font>
+log4j.appender.<b>stdout</b>.layout.ConversionPattern=<span style="color:blue"><b>%m%n</b></span>
 </pre>
 
-<p>This configuration creates an output channel ("Appender") to console named as <tt>stdout</tt> which prints the
-message (%m) followed by a line feed (%n) - same as the earlier System.out.println() :-) Oooh kay - but we haven't
-finished yet. We should deliver the configuration file, too. So we change the buildfile:</p>
+<p>This configuration creates an output channel (<q>Appender</q>) to console named as <code>stdout</code> which prints
+the message (<q>%m</q>) followed by a line feed (<q>%n</q>)&mdash;same as the
+earlier <code class="code">System.out.println()</code> :-) Oooh kay&mdash;but we haven't finished yet. We should deliver
+the configuration file, too. So we change the buildfile:</p>
 
-<pre class="code">
+<pre>
     ...
     &lt;target name="compile"&gt;
         &lt;mkdir dir="${classes.dir}"/&gt;
@@ -383,35 +354,41 @@
             <b>&lt;fileset dir="${src.dir}" excludes="**/*.java"/&gt;</b>
         <b>&lt;/copy&gt;</b>
     &lt;/target&gt;
-    ...
-</pre>
+    ...</pre>
 
-<p>This copies all resources (as long as they haven't the suffix ".java") to the build directory, so we could
+<p>This copies all resources (as long as they haven't the suffix <samp>.java</samp>) to the build directory, so we could
 start the application from that directory and these files will included into the jar.</p>
 
+<h2 id="junit">Testing the class</h2>
+<p>In this step we will introduce the usage of the JUnit [3] test framework in combination with Ant. Because Ant has a
+built-in JUnit 4.13.1 you could start directly using it. Write a test class
+in <samp>src\oata\HelloWorldTest.java</samp>:</p>
 
-<a name="junit">
-<h2>Testing the class</h2>
-<p>In this step we will introduce the usage of the JUnit [3] testframework in combination with Ant. Because Ant
-has a built-in JUnit 3.8.2 you could start directly using it. Write a test class in <tt>src\HelloWorldTest.java</tt>: </p>
+<pre>
+package oata;
 
-<pre class="code">
-public class HelloWorldTest extends junit.framework.TestCase {
+import org.junit.Test;
 
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest {
+
+    @Test
     public void testNothing() {
     }
-    
+
+    @Test
     public void testWillAlwaysFail() {
         fail("An error message");
     }
-    
+
 }</pre>
 
-<p>Because we dont have real business logic to test, this test class is very small: just show how to start. For 
-further information see the JUnit documentation [3] and the manual of <a href="Tasks/junit.html">junit</a> task.
-Now we add a junit instruction to our buildfile:</p>
+<p>Because we don't have real business logic to test, this test class is very small: just showing how to start. For
+further information see the JUnit documentation [3] and the manual of <a href="Tasks/junit.html">junit</a> task.  Now we
+add a <code>junit</code> instruction to our buildfile:</p>
 
-<pre class="code">
+<pre>
     ...
 
     &lt;path <b>id="application"</b> location="${jar.dir}/${ant.project.name}.jar"/&gt;
@@ -424,48 +401,45 @@
             &lt;/classpath&gt;
         &lt;/java&gt;
     &lt;/target&gt;
-    
+
     <b>&lt;target name="junit" depends="jar"&gt;
         &lt;junit printsummary="yes"&gt;
             &lt;classpath&gt;
                 &lt;path refid="classpath"/&gt;
                 &lt;path refid="application"/&gt;
             &lt;/classpath&gt;
-            
+
             &lt;batchtest fork="yes"&gt;
-                &lt;fileset dir="${src.dir}" includes="*Test.java"/&gt;
+                &lt;fileset dir="${src.dir}" includes="**/*Test.java"/&gt;
             &lt;/batchtest&gt;
         &lt;/junit&gt;
     &lt;/target&gt;</b>
 
-    ...
+    ...</pre>
 
-</pre>
+<p>We reuse the path to our own jar file as defined in <q>run</q>-target by giving it an <var>id</var> and making it
+globally available.  The <var>printsummary</var>=<q>yes</q> lets us see more detailed information than just a "FAILED"
+or "PASSED" message.  How much tests failed? Some errors? <var>printsummary</var> lets us know.  The classpath is set up
+to find our classes.  To run tests the <code>batchtest</code> here is used, so you could easily add more test classes in
+the future just by naming them <code>*Test.java</code>.  This is a common naming scheme.</p>
 
-<p>We reuse the path to our own jar file as defined in run-target by
-  giving it an ID and making it globally available.
-The <tt>printsummary=yes</tt> lets us see more detailed information than just a "FAILED" or "PASSED" message.
-How much tests failed? Some errors? Printsummary lets us know. The classpath is set up to find our classes.
-To run tests the <tt>batchtest</tt> here is used, so you could easily add more test classes in the future just
-by naming them <tt>*Test.java</tt>. This is a common naming scheme.</p>
-
-<p>After a <tt class="code">ant junit</tt> you'll get:</p>
+<p>After a <kbd>ant junit</kbd> you'll get:</p>
 
 <pre class="output">
 ...
 junit:
-    [junit] Running HelloWorldTest
-    [junit] Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0,01 sec
-    [junit] Test HelloWorldTest FAILED
+    [junit] Running oata.HelloWorldTest
+    [junit] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0,01 sec
+    [junit] Test oata.HelloWorldTest FAILED
 
 BUILD SUCCESSFUL
-...
-</pre>
+...</pre>
 
-<p>We can also produce a report. Something that you (and other) could read after closing the shell .... 
-There are two steps: 1. let &lt;junit&gt; log the information and 2. convert these to something readable (browsable).<p>
+<p>We can also produce a report. Something that you (and others) could read after closing the shell ...  There are two
+steps: 1. let <code>&lt;junit&gt;</code> log the information and 2. convert these log files to something readable
+(browsable).<p>
 
-<pre class="code">
+<pre>
     ...
     <b>&lt;property name="report.dir"  value="${build.dir}/junitreport"/&gt;</b>
     ...
@@ -476,45 +450,38 @@
                 &lt;path refid="classpath"/&gt;
                 &lt;path refid="application"/&gt;
             &lt;/classpath&gt;
-            
+
             <b>&lt;formatter type="xml"/&gt;</b>
-            
+
             &lt;batchtest fork="yes" <b>todir="${report.dir}"</b>&gt;
-                &lt;fileset dir="${src.dir}" includes="*Test.java"/&gt;
+                &lt;fileset dir="${src.dir}" includes="**/*Test.java"/&gt;
             &lt;/batchtest&gt;
         &lt;/junit&gt;
     &lt;/target&gt;
-    
+
     <b>&lt;target name="junitreport"&gt;
         &lt;junitreport todir="${report.dir}"&gt;
             &lt;fileset dir="${report.dir}" includes="TEST-*.xml"/&gt;
             &lt;report todir="${report.dir}"/&gt;
         &lt;/junitreport&gt;
-    &lt;/target&gt;</b>
-</pre>
+    &lt;/target&gt;</b></pre>
 
-<p>Because we would produce a lot of files and these files would be written to the current directory by default,
-we define a report directory, create it before running the <tt>junit</tt> and redirect the logging to it. The log format
-is XML so <tt>junitreport</tt> could parse it. In a second target <tt>junitreport</tt> should create a browsable 
-HTML-report for all generated xml-log files in the report directory. Now you can open the ${report.dir}\index.html and
-see the result (looks something like JavaDoc).<br>
-Personally I use two different targets for junit and junitreport. Generating the HTML report needs some time and you dont
-need the HTML report just for testing, e.g. if you are fixing an error or a integration server is doing a job.
-</p>
+<p>Because we would produce a lot of files and these files would be written to the current directory by default, we
+define a report directory, create it before running the <q>junit</q> and redirect the logging to it. The log format is
+XML so <q>junitreport</q> could parse it. In a second target <q>junitreport</q> should create a browsable HTML report
+for all generated XML log files in the report directory. Now you can open the <samp>${report.dir}\index.html</samp> and
+see the result (looks something like JavaDoc).<br/>  Personally I use two different targets
+for <code>&lt;junit&gt;</code> and <code>&lt;junitreport&gt;</code>. Generating the HTML report needs some time and you
+don't need the HTML report just for testing, e.g. if you are fixing an error or a integration server is doing a job.</p>
 
-
-
-
-<a name="resources"></a>
-<h2>Resources</h2>
-<pre>
-    [1] <a href="http://www.apache.org/dist/logging/log4j/1.2.13/logging-log4j-1.2.13.zip">http://www.apache.org/dist/logging/log4j/1.2.13/logging-log4j-1.2.13.zip</a>
-    [2] <a href="http://logging.apache.org/log4j/docs/manual.html">http://logging.apache.org/log4j/docs/manual.html</a>
-    [3] <a href="http://www.junit.org/index.htm">http://www.junit.org/index.htm</a>
-</pre>
-
-
-
+<h2 id="resources">Resources</h2>
+<ol class="refs">
+  <li><a href="https://archive.apache.org/dist/logging/log4j/1.2.17/log4j-1.2.17.zip"
+         target="_top">https://archive.apache.org/dist/logging/log4j/1.2.17/log4j-1.2.17.zip</a></li>
+  <li><a href="https://logging.apache.org/log4j/1.2/manual.html"
+         target="_top">https://logging.apache.org/log4j/1.2/manual.html</a></li>
+  <li><a href="https://junit.org/junit4" target="_top">https://junit.org/junit4</a></li>
+</ol>
 
 </body>
 </html>
diff --git a/manual/tutorial-tasks-filesets-properties.html b/manual/tutorial-tasks-filesets-properties.html
index 3a36e7e..b116f12 100644
--- a/manual/tutorial-tasks-filesets-properties.html
+++ b/manual/tutorial-tasks-filesets-properties.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
   <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
   <title>Tutorial: Tasks using Properties, Filesets &amp; Paths</title>
@@ -22,12 +23,12 @@
 <body>
 <h1>Tutorial: Tasks using Properties, Filesets &amp; Paths</h1>
 
-<p>After reading the tutorial about <a href="tutorial-writing-tasks.html">writing
-tasks [1]</a> this tutorial explains how to get and set properties and how to use
-nested filesets and paths. Finally it explains how to contribute tasks to Apache Ant.</p>
+<p>After reading the tutorial about <a href="tutorial-writing-tasks.html">writing tasks [1]</a> this tutorial explains
+how to get and set properties and how to use nested filesets and paths. Finally it explains how to contribute tasks to
+Apache Ant.</p>
 
 <h2>Content</h2>
-<p><ul>
+<ul>
 <li><a href="#goal">The goal</a></li>
 <li><a href="#buildenvironment">Build environment</a></li>
 <li><a href="#propertyaccess">Property access</a></li>
@@ -37,19 +38,17 @@
 <li><a href="#documentation">Documentation</a></li>
 <li><a href="#contribute">Contribute the new task</a></li>
 <li><a href="#resources">Resources</a></li>
-</ul></p>
+</ul>
 
+<h2 id="goal">The goal</h2>
+<p>The goal is to write a task, which searches in a path for a file and saves the location of that file in a
+property.</p>
 
-<h2><a name="goal">The goal</a></h2>
-<p>The goal is to write a task, which searchs in a path for a file and saves the
-location of that file in a property.</p>
-
-
-<h2><a name="buildenvironment">Build environment</a></h2>
-<p>We can use the buildfile from the other tutorial and modify it a little bit.
-That's the advantage of using properties - we can reuse nearly the whole script. :-)</p>
-<pre class="code">
-&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+<h2 id="buildenvironment">Build environment</h2>
+<p>We can use the buildfile from the other tutorial and modify it a little bit.  That's the advantage of using
+properties&mdash;we can reuse nearly the whole script. :-)</p>
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;project name="<b>FindTask</b>" basedir="." default="test"&gt;
     ...
     &lt;target name="use.init" description="Taskdef's the <b>Find</b>-Task" depends="jar"&gt;
@@ -58,31 +57,28 @@
 
     <b>&lt;!-- the other use.* targets are deleted --&gt;</b>
     ...
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>The buildfile is in the archive <a href="tutorial-tasks-filesets-properties.zip">
-tutorial-tasks-filesets-properties.zip [2]</a> in <tt>/build.xml.01-propertyaccess</tt>
-(future version saved as *.02..., final version as build.xml; same for sources).</p>
+<p>The buildfile is in the
+archive <a href="tutorial-tasks-filesets-properties.zip">tutorial-tasks-filesets-properties.zip [2]</a>
+in <samp>/build.xml.01-propertyaccess</samp> (future version saved as *.02..., final version as <samp>build.xml</samp>;
+same for sources).</p>
 
-
-<h2><a name="propertyaccess">Property access</a></h2>
-<p>Our first step is to set a property to a value and print the value of that property.
-So our scenario would be
-<pre class="code">
+<h2 id="propertyaccess">Property access</h2>
+<p>Our first step is to set a property to a value and print the value of that property.  So
+our scenario would be</p>
+<pre>
     &lt;find property="test" value="test-value"/&gt;
-    &lt;find print="test"/&gt;
-</pre>
-ok, can be rewritten with the core tasks
-<pre class="code">
+    &lt;find print="test"/&gt;</pre>
+<p>Ok, it can be rewritten with the core tasks</p>
+<pre>
     &lt;property name="test" value="test-value"/&gt;
-    &lt;echo message="${test}"/&gt;
-</pre>
-but I have to start on known ground :-)</p>
-<p>So what to do? Handling three attributes (property, value, print) and an execute method.
-Because this is only an introduction example I don't do much checking:
+    &lt;echo message="${test}"/&gt;</pre>
+<p>but I have to start on known ground :-)</p>
+<p>So what to do? Handling three attributes (<var>property</var>, <var>value</var>, <var>print</var>) and an execute
+method.  Because this is only an introduction example I don't do much checking:</p>
 
-<pre class="code">
+<pre>
 import org.apache.tools.ant.BuildException;
 
 public class Find extends Task {
@@ -107,47 +103,40 @@
             <b>getProject().setNewProperty(property, value)</b>;
         }
     }
-}
-</pre>
+}</pre>
 
-As said in the other tutorial, the property access is done via Project instance.
-We get this instance via the public <tt>getProject()</tt> method which we inherit from
-<tt>Task</tt> (more precise from ProjectComponent). Reading a property is done via
-<tt>getProperty(<i>propertyname</i>)</tt> (very simple, isn't it?). This property returns
-the value as String or <i>null</i> if not set.<br>
-Setting a property is ... not really difficult, but there is more than one setter. You can
-use the <tt>setProperty()</tt> method which will do the job like expected. But there is
-a golden rule in Ant: <i>properties are immutable</i>. And this method sets the property
-to the specified value - whether it has a value before that or not. So we use another
-way. <tt>setNewProperty()</tt> sets the property only if there is no property with that
-name. Otherwise a message is logged.</p>
+<p>As said in the other tutorial, the property access is done via <code class="code">Project</code> instance.  We get
+this instance via the public <code class="code">getProject()</code> method which we inherit
+from <code class="code">Task</code> (more precisely from <code class="code">ProjectComponent</code>). Reading a property
+is done via <code class="code">getProperty(<i>propertyname</i>)</code> (very simple, isn't it?). This property returns
+the value as <code>String</code> or <code>null</code> if not set.<br/>  Setting a property is ... not really difficult,
+but there is more than one setter. You can use the <code class="code">setProperty()</code> method which will do the job
+as expected. But there is a golden rule in Ant: <em>properties are immutable</em>. And this method sets the property to
+the specified value&mdash;whether it has a value before that or not. So we use another
+way. <code class="code">setNewProperty()</code> sets the property only if there is no property with that name. Otherwise
+a message is logged.</p>
 
-<p><i>(by the way: a short word to ants "namespaces" (don't
-be confused with xml namespaces:
-an <code>&lt;antcall&gt;</code> creates a new space for property names. All properties from the caller
-are passed to the callee, but the callee can set its own properties without notice by the
-caller.)</i></p>
+<p><em>(By the way, a short explanation of Ant's "namespaces"&mdash;not to be confused with XML namespaces:
+an <code>&lt;antcall&gt;</code> creates a new space for property names. All properties from the caller are passed to the
+callee, but the callee can set its own properties without notice by the caller.)</em></p>
 
-<p>There are some other setter, too (but I haven't used them, so I can't say something
-to them, sorry :-)</p>
+<p>There are some other setters, too (but I haven't used them, so I can't say something to them, sorry :-)</p>
 
-<p>After putting our two line example from above into a target names <tt>use.simple</tt>
-we can call that from our testcase:
+<p>After putting our two line example from above into a target names <code>use.simple</code> we can call that from our
+test case:</p>
 
-<pre class="code">
+<pre>
+import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.Before;
-import org.junit.Assert;
 import org.apache.tools.ant.BuildFileRule;
 
-
 public class FindTest {
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
-
     @Before
     public void setUp() {
         configureProject("build.xml");
@@ -155,38 +144,32 @@
 
     @Test
     public void testSimple() {
-        buildRule.executeTarget("useSimgle");
+        buildRule.executeTarget("useSimple");
         <b>Assert.assertEquals("test-value", buildRule.getLog());</b>
     }
-}
-</pre>
+}</pre>
 
-and all works fine.</p>
+<p>and all works fine.</p>
 
-
-
-<h2><a name="filesets">Using filesets</a></h2>
-<p>Ant provides a common way of bundling files: the fileset. Because you are reading
-this tutorial I think you know them and I don't have to spend more explanations about
-their usage in buildfiles. Our goal is to search a file in path. And on this step the
-path is simply a fileset (or more precise: a collection of filesets). So our usage
-would be
-<pre class="code">
+<h2 id="filesets">Using filesets</h2>
+<p>Ant provides a common way of bundling files: the fileset. Because you are reading this tutorial I think you know them
+and I don't have to spend more explanations about their usage in buildfiles. Our goal is to search for a file in
+path. And in this step the path is simply a fileset (or more precise: a collection of filesets). So our usage would
+be</p>
+<pre>
     &lt;find file="ant.jar" location="location.ant-jar"&gt;
         &lt;fileset dir="${ant.home}" includes="**/*.jar"/&gt;
-    &lt;/find&gt;
-</pre>
-</p>
+    &lt;/find&gt;</pre>
 
-<p>What do we need? A task with two attributes (file, location) and nested
-filesets. Because we had attribute handling already explained in the example above and the
-handling of nested elements is described in the other tutorial the code should be very easy:
-<pre class="code">
+<p>What do we need? A task with two attributes (<var>file</var>, <var>location</var>) and nested filesets. Because we
+had attribute handling already explained in the example above and the handling of nested elements is described in the
+other tutorial, the code should be very easy:</p>
+<pre>
 public class Find extends Task {
 
     private String file;
     private String location;
-    private Vector filesets = new Vector();
+    private List&lt;FileSet&gt; filesets = new ArrayList&lt;&gt;();
 
     public void setFile(String file) {
         this.file = file;
@@ -202,66 +185,57 @@
 
     public void execute() {
     }
-}
-</pre>
-Ok - that task wouldn't do very much, but we can use it in the described manner without
-failure. On next step we have to implement the execute method. And before that we will
-implement the appropriate testcases (TDD - test driven development).</p>
+}</pre>
+<p>Ok&mdash;that task wouldn't do very much, but we can use it in the described manner without failure. In the next step
+we have to implement the execute method. And before that we will implement the appropriate test cases (TDD&mdash;test
+driven development).</p>
 
-<p>In the other tutorial we have reused the already written targets of our buildfile.
-Now we will configure most of the testcases via java code (sometimes it's much easier
-to write a target than doing it via java coding). What can be tested?<ul>
-<li>not valid configured task (missing file, missing location, missing fileset)</li>
+<p>In the other tutorial we have reused the already written targets of our buildfile.  Now we will configure most of the
+test cases via Java code (sometimes it's much easier to write a target than doing it via Java coding). What can be
+tested?</p>
+<ul>
+<li>invalid configuration of the task (missing file, missing location, missing fileset)</li>
 <li>don't find a present file</li>
 <li>behaviour if file can't be found</li>
 </ul>
-Maybe you find some more testcases. But this is enough for now.<br>
-For each of these points we create a <tt>testXX</tt> method.</p>
+<p>Maybe you find some more test cases. But this is enough for now.<br/>  For each of these points we create
+a <code class="code">testXX</code> method.</p>
 
-<pre class="code">
+<pre>
 public class FindTest {
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException tried = ExpectedException.none();
+
     ... // constructor, setUp as above
 
     @Test
     public void testMissingFile() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("file not set");
         <b>Find find = new Find();</b>
-        try {
-            <b>find.execute();</b>
-            fail("No 'no-file'-exception thrown.");
-        } catch (Exception e) {
-            // exception expected
-            String expected = "file not set";
-            assertEquals("Wrong exception message.", expected, e.getMessage());
-        }
+        <b>find.execute();</b>
     }
 
     @Test
     public void testMissingLocation() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("location not set");
         Find find = new Find();
         <b>find.setFile("ant.jar");</b>
-        try {
-            find.execute();
-            fail("No 'no-location'-exception thrown.");
-        } catch (Exception e) {
-            ... // similar to testMissingFile()
-        }
+        find.execute();
     }
 
     @Test
     public void testMissingFileset() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("fileset not set");
         Find find = new Find();
         find.setFile("ant.jar");
         find.setLocation("location.ant-jar");
-        try {
-            find.execute();
-            fail("No 'no-fileset'-exception thrown.");
-        } catch (Exception e) {
-            ... // similar to testMissingFile()
-        }
     }
 
     @Test
@@ -278,65 +252,60 @@
         assertNotNull("Property not set.", result);
         assertTrue("Wrong file found.", result.endsWith("ant.jar"));
     }
-}
-</pre>
+}</pre>
 
-<p>If we run this test class all test cases (except <i>testFileNotPresent</i>) fail. Now we
-can implement our task, so that these test cases will pass.</p>
+<p>If we run this test class all test cases (except <code class="code">testFileNotPresent</code>) fail. Now we can
+implement our task, so that these test cases will pass.</p>
 
-<pre class="code">
+<pre>
     protected void validate() {
-        if (file==null) throw new BuildException("file not set");
-        if (location==null) throw new BuildException("location not set");
-        if (filesets.size()&lt;1) throw new BuildException("fileset not set");
+        if (file == null) throw new BuildException("file not set");
+        if (location == null) throw new BuildException("location not set");
+        if (filesets.size() &lt; 1) throw new BuildException("fileset not set");
     }
 
     public void execute() {
         validate();                                                             // 1
         String foundLocation = null;
-        for(Iterator itFSets = filesets.iterator(); itFSets.hasNext(); ) {      // 2
-            FileSet fs = (FileSet)itFSets.next();
+        for (FileSet fs : filesets) {                                           // 2
             DirectoryScanner ds = fs.getDirectoryScanner(getProject());         // 3
-            String[] includedFiles = ds.getIncludedFiles();
-            for(int i=0; i&lt;includedFiles.length; i++) {
-                String filename = includedFiles[i].replace('\\','/');           // 4
-                filename = filename.substring(filename.lastIndexOf("/")+1);
-                if (foundLocation==null &amp;&amp; file.equals(filename)) {
+            for (String includedFile : ds.getIncludedFiles()) {
+                String filename = includedFile.replace('\\','/');               // 4
+                filename = filename.substring(filename.lastIndexOf("/") + 1);
+                if (foundLocation == null &amp;&amp; file.equals(filename)) {
                     File base  = ds.getBasedir();                               // 5
-                    File found = new File(base, includedFiles[i]);
+                    File found = new File(base, includedFile);
                     foundLocation = found.getAbsolutePath();
                 }
             }
         }
-        if (foundLocation!=null)                                                // 6
+        if (foundLocation != null)                                              // 6
             getProject().setNewProperty(location, foundLocation);
-    }
-</pre>
+    }</pre>
 
-<p>On <b>//1</b> we check the prerequisites for our task. Doing that in a <tt>validate</tt>-method
-is a common way, because we separate the prerequisites from the real work. On <b>//2</b> we iterate
-over all nested filesets. If we don't want to handle multiple filesets, the <tt>addFileset()</tt>
-method has to reject the further calls. We can get the result of a fileset via its DirectoryScanner
-like done in <b>//3</b>. After that we create a platform independent String representation of
-the file path (<b>//4</b>, can be done in other ways of course). We have to do the <tt>replace()</tt>,
-because we work with a simple string comparison. Ant itself is platform independent and can
-therefore run on filesystems with slash (/, e.g. Linux) or backslash (\, e.g. Windows) as
-path separator. Therefore we have to unify that. If we found our file we create an absolute
-path representation on <b>//5</b>, so that we can use that information without knowing the basedir.
-(This is very important on use with multiple filesets, because they can have different basedirs
-and the return value of the directory scanner is relative to its basedir.) Finally we store the
-location of the file as property, if we had found one (<b>//6</b>).</p>
+<p>On <strong>//1</strong> we check the prerequisites for our task. Doing that in a <code class="code">validate()</code>
+method is a common way, because we separate the prerequisites from the real work. On <strong>//2</strong> we iterate
+over all nested filesets. If we don't want to handle multiple filesets, the <code class="code">addFileset()</code>
+method has to reject the further calls. We can get the result of a fileset via
+its <code class="code">DirectoryScanner</code> like done in <strong>//3</strong>. After that we create a platform
+independent String representation of the file path (<strong>//4</strong>, can be done in other ways of course). We have
+to do the <code class="code">replace()</code>, because we work with a simple string comparison. Ant itself is platform
+independent and can therefore run on filesystems with slash (<q>/</q>, e.g. Linux) or backslash (<q>\</q>, e.g. Windows)
+as path separator. Therefore we have to unify that. If we find our file, we create an absolute path representation
+on <strong>//5</strong>, so that we can use that information without knowing the <var>basedir</var>.  (This is very
+important on use with multiple filesets, because they can have different <var>basedir</var>s and the return value of the
+directory scanner is relative to its <var>basedir</var>.)  Finally we store the location of the file as property, if we
+had found one (<strong>//6</strong>).</p>
 
-<p>Ok, much more easier in this simple case would be to add the <i>file</i> as additional
-<i>include</i> element to all filesets. But I wanted to show how to handle complex situations
-without being complex :-)</p>
+<p>Ok, much more easier in this simple case would be to add the <var>file</var> as additional <code>include</code>
+element to all filesets. But I wanted to show how to handle complex situations without being complex :-)</p>
 
-<p>The test case uses the ant property <i>ant.home</i> as reference. This property is set by the
-<tt>Launcher</tt> class which starts ant. We can use that property in our buildfiles as a
-<a href="properties.html#built-in-props">build-in property [3]</a>. But if we create a new ant
-environment we have to set that value for our own. And we use the <code>&lt;junit&gt;</code> task in fork-mode.
-Therefore we have do modify our buildfile:
-<pre class="code">
+<p>The test case uses the Ant property <code>ant.home</code> as reference. This property is set by
+the <code class="code">Launcher</code> class which starts ant. We can use that property in our buildfiles as
+a <a href="properties.html#built-in-props">build-in property [3]</a>. But if we create a new Ant environment we have to
+set that value for our own. And we use the <code>&lt;junit&gt;</code> task in <var>fork</var> mode.  Therefore we have
+do modify our buildfile:</p>
+<pre>
     &lt;target name="junit" description="Runs the unit tests" depends="jar"&gt;
         &lt;delete dir="${junit.out.dir.xml}"/&gt;
         &lt;mkdir  dir="${junit.out.dir.xml}"/&gt;
@@ -348,114 +317,109 @@
                 &lt;fileset dir="${src.dir}" includes="**/*Test.java"/&gt;
             &lt;/batchtest&gt;
         &lt;/junit&gt;
-    &lt;/target&gt;
-</pre>
+    &lt;/target&gt;</pre>
 
-
-<h2><a name="path">Using nested paths</a></h2>
-<p>A task providing support for filesets is a very comfortable one. But there is another
-possibility of bundling files: the <code>&lt;path&gt;</code>. Fileset are easy if the files are all under
-a common base directory. But if this is not the case you have a problem. Another disadvantage
-is its speed: if you have only a few files in a huge directory structure, why not use a
-<code>&lt;filelist&gt;</code> instead? <code>&lt;path&gt;</code>s combines these datatypes in that way that a path contains
-other paths, filesets, dirsets and filelists. This is why <a href="http://ant-contrib.sourceforge.net/">
-Ant-Contribs [4]</a> <code>&lt;foreach&gt;</code> task is modified to support paths instead of filesets. So we want that,
-too.</p>
+<h2 id="path">Using nested paths</h2>
+<p>A task providing support for filesets is a very comfortable one. But there is another possibility of bundling files:
+the <code>&lt;path&gt;</code>. Filesets are easy if the files are all under a common base directory. But if this is not
+the case, you have a problem. Another disadvantage is its speed: if you have only a few files in a huge directory
+structure, why not use a <code>&lt;filelist&gt;</code> instead? <code>&lt;path&gt;</code>s combines these datatypes in
+that way that a path contains other paths, filesets, dirsets and filelists. This is
+why <a href="http://ant-contrib.sourceforge.net/" target="_top">Ant-Contrib [4]</a> <code>&lt;foreach&gt;</code> task is
+modified to support paths instead of filesets. So we want that, too.</p>
 
 <p>Changing from fileset to path support is very easy:</p>
-<pre class="code">
-<i><b>Change java code from:</b></i>
-    private Vector filesets = new Vector();
+<em><strong>Change Java code from:</strong></em>
+<pre>
+    private List&lt;FileSet&gt; filesets = new ArrayList&lt;&gt;();
     public void addFileset(FileSet fileset) {
         filesets.add(fileset);
-    }
-<i><b>to:</b></i>
-    private Vector paths = new Vector();                      *1
+    }</pre>
+<em><strong>to:</strong></em>
+<pre>
+    private List&lt;Path&gt; paths = new ArrayList&lt;&gt;();             *1
     public void add<b>Path</b>(<b>Path</b> path) {                          *2
         paths.add(path);
-    }
-<i><b>and build file from:</b></i>
+    }</pre>
+<em><strong>and build file from:</strong></em>
+<pre>
     &lt;find file="ant.jar" location="location.ant-jar"&gt;
         &lt;fileset dir="${ant.home}" includes="**/*.jar"/&gt;
-    &lt;/find&gt;
-<i><b>to:</b></i>
+    &lt;/find&gt;</pre>
+<em><strong>to:</strong></em>
+<pre>
     &lt;find file="ant.jar" location="location.ant-jar"&gt;
         <b>&lt;path&gt;</b>                                                *3
             &lt;fileset dir="${ant.home}" includes="**/*.jar"/&gt;
         &lt;/path&gt;
-    &lt;/find&gt;
-</pre>
-<p>On <b>*1</b> we rename only the vector. It�s just for better reading the source. On <b>*2</b>
-we have to provide the right method: an add<i>Name</i>(<i>Type</i> t). Therefore replace the
-fileset with path here. Finally we have to modify our buildfile on <b>*3</b> because our task
-doesn�t support nested filesets any longer. So we wrap the fileset inside a path.</p>
+    &lt;/find&gt;</pre>
+<p>On <strong>*1</strong> we rename only the list. It's just for better reading the source. On <strong>*2</strong> we
+have to provide the right method: an <code>add<i>Name</i>(<i>Type</i> t)</code>. Therefore replace the fileset with path
+here. Finally we have to modify our buildfile on <strong>*3</strong> because our task doesn't support nested filesets
+any longer. So we wrap the fileset inside a path.</p>
 
-<p>And now we modify the testcase. Oh, not very much to do :-) Renaming the <tt>testMissingFileset()</tt>
-(not really a <i>must-be</i> but better it�s named like the think it does) and update the
-<i>expected</i>-String in that method (now a <tt>path not set</tt> message is expected). The more complex
-test cases base on the buildscript. So the targets <tt>testFileNotPresent</tt> and <tt>testFilePresent</tt> have to be
-modified in the manner described above.</p>
+<p>And now we modify the test case. Oh, not very much to do :-) Renaming
+the <code class="code">testMissingFileset()</code> (not really a <em>must-be</em> but better it's named like the thing
+it does) and update the <var>expected</var>-String in that method (now a <samp>path not set</samp> message is
+expected). The more complex test cases base on the build script. So the targets <var>testFileNotPresent</var>
+and <var>testFilePresent</var> have to be modified in the manner described above.</p>
 
-<p>The test are finished. Now we have to adapt the task implementation. The easiest modification is
-in the <tt>validate()</tt> method where we change le last line to <tt>if (paths.size()&lt;1) throw new
-BuildException("path not set");</tt>. In the <tt>execute()</tt> method we have a little more work.
-... mmmh ... in reality it's lesser work, because the Path class does the whole DirectoryScanner-handling
-and creating-absolute-paths stuff for us. So the execute method is just:</p>
+<p>The test are finished. Now we have to adapt the task implementation. The easiest modification is in
+the <code class="code">validate()</code> method where we change the last line to <code class="code">if
+(paths.size()&lt;1) throw new BuildException("path not set");</code>. In the <code class="code">execute()</code> method
+we have a little more work.  ... mmmh ... in reality it's less work, because the <code class="code">Path</code> class
+does the whole <code class="code">DirectoryScanner</code>-handling and creating-absolute-paths stuff for us. So the
+execute method becomes just:</p>
 
-<pre class="code">
+<pre>
     public void execute() {
         validate();
         String foundLocation = null;
-        for(Iterator itPaths = paths.iterator(); itPaths.hasNext(); ) {
-            Path path = (<b>Path</b>)itPaths.next();                                // 1
-            String[] includedFiles = <b>path.list()</b>;                            // 2
-            for(int i=0; i&lt;includedFiles.length; i++) {
-                String filename = includedFiles[i].replace('\\','/');
-                filename = filename.substring(filename.lastIndexOf("/")+1);
-                if (foundLocation==null &amp;&amp; file.equals(filename)) {
-                    <b>foundLocation = includedFiles[i];</b>                        // 3
+        for (Path path : paths) {                                        // 1
+            for (String includedFile : <b>path.list()</b>) {                    // 2
+                String filename = includedFile.replace('\\','/');
+                filename = filename.substring(filename.lastIndexOf("/") + 1);
+                if (foundLocation == null &amp;&amp; file.equals(filename)) {
+                    <b>foundLocation = includedFile;</b>                        // 3
                 }
             }
         }
-        if (foundLocation!=null)
+        if (foundLocation != null)
             getProject().setNewProperty(location, foundLocation);
     }
 </pre>
 
-<p>Of course we have to do the typecase to Path on <b>//1</b>. On <b>//2</b> and <b>//3</b>
-we see that the Path class does the work for us: no DirectoryScanner (was at 2) and no
-creating of the absolute path (was at 3).</p>
+<p>Of course we have to iterate through paths on <strong>//1</strong>. On <strong>//2</strong> and <strong>//3</strong>
+we see that the Path class does the work for us: no DirectoryScanner (was at 2) and no creating of the absolute path
+(was at 3).</p>
 
+<h2 id="returning-list">Returning a list</h2>
+<p>So far so good. But could a file be on more than one place in the path?&mdash;Of course.<br/>
+And would it be good to get all of them?&mdash;It depends ...<p>
 
-
-<h2><a name="returning-list">Returning a list</a></h2>
-<p>So far so good. But could a file be on more than one place in the path? - Of course.<br>
-And would it be good to get all of them? - It depends on ...<p>
-
-<p>In this section we will extend that task to support returning a list of all files.
-Lists as property values are not supported by Ant natively. So we have to see how other
-tasks use lists. The most famous task using lists is Ant-Contribs <code>&lt;foreach&gt;</code>. All list
-elements are concatenated and separated with a customizable separator (default ',').</p>
+<p>In this section we will extend that task to support returning a list of all files.  Lists as property values are not
+supported by Ant natively. So we have to see how other tasks use lists. The most famous task using lists is
+Ant-Contrib's <code>&lt;foreach&gt;</code>. All list elements are concatenated and separated with a customizable
+separator (default <q>,</q>).</p>
 
 <p>So we do the following:</p>
 
-<pre class="code">
-    &lt;find ... <b>delimiter=""</b>/&gt; ... &lt;/find&gt;
-</pre>
+<pre>&lt;find ... <b>delimiter=""</b>/&gt; ... &lt;/find&gt;</pre>
 
-<p>If the delimiter is set we will return all found files as list with that delimiter.</p>
+<p>if the delimiter is set, we will return all found files as list with that delimiter.</p>
 
-<p>Therefore we have to<ul>
+<p>Therefore we have to</p>
+<ul>
 <li>provide a new attribute</li>
 <li>collect more than the first file</li>
 <li>delete duplicates</li>
 <li>create the list if necessary</li>
 <li>return that list</li>
-</ul></p>
+</ul>
 
-<p>So we add as testcase:</p>
-<pre class="code">
-<b><i>in the buildfile:</i></b>
+<p>So we add as test case:</p>
+<strong><em>in the buildfile:</em></strong>
+<pre>
     &lt;target name="test.init"&gt;
         &lt;mkdir dir="test1/dir11/dir111"/&gt;                             *1
         &lt;mkdir dir="test1/dir11/dir112"/&gt;
@@ -484,27 +448,25 @@
             &lt;fileset dir="test1"/&gt;
             &lt;fileset dir="test2"/&gt;
         &lt;/delete&gt;
-    &lt;/target&gt;
-
-<b><i>in the test class:</i></b>
+    &lt;/target&gt;</pre>
+<strong><em>in the test class:</em></strong>
+<pre>
     public void testMultipleFiles() {
         executeTarget("testMultipleFiles");
         String result = getProject().getProperty("location.test");
         assertNotNull("Property not set.", result);
         assertTrue("Only one file found.", result.indexOf(";") &gt; -1);
-    }
-</pre>
+    }</pre>
 
-<p>Now we need a directory structure where we CAN find files with the same
-name in different directories. Because we can't sure to have one we create
-one on <b>*1</b> and <b>*2</b>. And of course we clean up that on <b>*4</b>. The creation
-can be done inside our test target or in a separate one, which will be better
-for reuse later (<b>*3</b>).
+<p>Now we need a directory structure where we CAN find files with the same name in different directories. Because we
+can't sure to have one we create one on <strong>*1</strong> and <strong>*2</strong>. And of course we clean up that
+on <strong>*4</strong>. The creation can be done inside our test target or in a separate one, which will be better for
+reuse later (<strong>*3</strong>).
 
 <p>The task implementation is modified as followed:</p>
 
-<pre class="code">
-    private Vector foundFiles = new Vector();
+<pre>
+    private List&lt;String&gt; foundFiles = new ArrayList&lt;&gt;();
     ...
     private String delimiter = null;
     ...
@@ -515,99 +477,91 @@
     public void execute() {
         validate();
         // find all files
-        for(Iterator itPaths = paths.iterator(); itPaths.hasNext(); ) {
-            Path path = (Path)itPaths.next();
-            String[] includedFiles = path.list();
-            for(int i=0; i&lt;includedFiles.length; i++) {
-                String filename = includedFiles[i].replace('\\','/');
+        for (Path path : paths) {
+            for (File includedFile : path.list()) {
+                String filename = includedFile.replace('\\','/');
                 filename = filename.substring(filename.lastIndexOf("/")+1);
-                if (file.equals(filename) &amp;&amp; <b>!foundFiles.contains(includedFiles[i]</b>)) {   // 1
-                    foundFiles.add(includedFiles[i]);
+                if (file.equals(filename) &amp;&amp; <b>!foundFiles.contains(includedFile)</b>) {  // 1
+                    foundFiles.add(includedFile);
                 }
             }
         }
 
         // create the return value (list/single)
         String rv = null;
-        if (foundFiles.size() &gt; 0) {                                        // 2
-            if (delimiter==null) {
+        if (!foundFiles.isEmpty()) {                                                // 2
+            if (delimiter == null) {
                 // only the first
-                rv = (String)foundFiles.elementAt(0);
+                rv = foundFiles.get(0);
             } else {
                 // create list
-                StringBuffer list = new StringBuffer();
-                for(Iterator it=foundFiles.iterator(); it.hasNext(); ) {    // 3
+                StringBuilder list = new StringBuilder();
+                for (String file : foundFiles) {                                    // 3
                     list.append(it.next());
-                    if (<b>it.hasNext()</b>) list.append(delimiter);               // 4
-                }
+                    if (<b>list.length() > 0</b>) list.append(delimiter);                  // 4
+                 }
                 rv = list.toString();
             }
         }
 
         // create the property
-        if (rv!=null)
+        if (rv != null)
             getProject().setNewProperty(location, rv);
-    }
-</pre>
+    }</pre>
 
-<p>The algorithm does: finding all files, creating the return value depending on the users
-wish, returning the value as property. On <b>//1</b> we eliminates the duplicates. <b>//2</b>
-ensures that we create the return value only if we have found one file. On <b>//3</b> we
-iterate over all found files and <b>//4</b> ensures that the last entry has no trailing
-delimiter.</p>
+<p>The algorithm does: finding all files, creating the return value depending on the users wish, returning the value as
+property. On <strong>//1</strong> we eliminates the duplicates. <strong>//2</strong> ensures that we create the return
+value only if we have found one file. On <strong>//3</strong> we iterate over all found files and <strong>//4</strong>
+ensures that the last entry has no trailing delimiter.</p>
 
-<p>Ok, first searching for all files and then returning only the first one ... You can
-tune the performance of your own :-)</p>
+<p>Ok, first searching for all files and then returning only the first one ... You can tune the performance of your own
+:-)</p>
 
+<h2 id="documentation">Documentation</h2>
+<p>A task is useless if the only who is able to code the buildfile is the task developer (and he only the next few weeks
+:-). So documentation is also very important. In which form you do that depends on your favourite. But inside Ant there
+is a common format and it has advantages if you use that: all task users know that form, this form is requested if you
+decide to contribute your task. So we will doc our task in that form.</p>
 
-<h2><a name="documentation">Documentation</a></h2>
-<p>A task is useless if the only who is able to code the buildfile is the task developer
-(and he only the next few weeks :-). So documentation is also very important. In which
-form you do that depends on your favourite. But inside Ant there is a common format and
-it has advantages if you use that: all task users know that form, this form is requested if
-you decide to contribute your task. So we will doc our task in that form.</p>
-
-<p>If you have a look at the manual page of the <a href="Tasks/java.html">Java task [5]</a>
-   you will see that it:<ul>
+<p>If you have a look at the manual page of the <a href="Tasks/java.html">Java task [5]</a> you will see that it:</p>
+<ul>
 <li>is plain html</li>
 <li>starts with the name</li>
-<li>has sections: description, parameters, nested elements, (maybe return codes) and (most
-important :-) examples</li>
-<li>parameters are listed in a table with columns for attribute name, its description and whether
-  it's required (if you add a feature after an Ant release, provide a <tt>since Ant xx</tt>
-  statement when it's introduced)</li>
+<li>has sections: description, parameters, nested elements, (maybe return codes) and (most important :-) examples</li>
+<li>parameters are listed in a table with columns for attribute name, its description and whether it's required (if you
+add a feature after an Ant release, provide a <em>since Ant xx</em> statement when it's introduced)</li>
 <li>describe the nested elements (since-statement if necessary)</li>
 <li>provide one or more useful examples; first code, then description.</li>
 </ul>
-As a template we have:
+<p>As a template we have:</p>
 
-<pre class="code">
-&lt;html&gt;
+<pre>
+&lt;!DOCTYPE html&gt;
+&lt;html lang=&quot;en&quot;&gt;
 
 &lt;head&gt;
-&lt;meta http-equiv="Content-Language" content="en-us"&gt;
 &lt;title&gt;<b>Taskname</b> Task&lt;/title&gt;
 &lt;/head&gt;
 
 &lt;body&gt;
 
-&lt;h2&gt;&lt;a name="<b>taskname</b>"&gt;<b>Taskname</b>&lt;/a&gt;&lt;/h2&gt;
+&lt;h2 id=&quot;<b>taskname</b>&quot;&gt;<b>Taskname</b>&lt;/h2&gt;
 &lt;h3&gt;Description&lt;/h3&gt;
-&lt;p&gt; <b>Describe the task.</b>&lt;/p&gt;
+&lt;p&gt;<b>Describe the task.</b>&lt;/p&gt;
 
 &lt;h3&gt;Parameters&lt;/h3&gt;
-&lt;table border="1" cellpadding="2" cellspacing="0"&gt;
+&lt;table class=&quot;attr&quot;&gt;
   &lt;tr&gt;
-    &lt;td valign="top"&gt;&lt;b&gt;Attribute&lt;/b&gt;&lt;/td&gt;
-    &lt;td valign="top"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;
-    &lt;td align="center" valign="top"&gt;&lt;b&gt;Required&lt;/b&gt;&lt;/td&gt;
+    &lt;th scope=&quot;col&quot;&gt;Attribute&lt;/th&gt;
+    &lt;th scope=&quot;col&quot;&gt;Description&lt;/th&gt;
+    &lt;th scope=&quot;col&quot;&gt;Required&lt;/th&gt;
   &lt;/tr&gt;
 
   <b>do this html row for each attribute (including inherited attributes)</b>
   &lt;tr&gt;
-    &lt;td valign="top"&gt;classname&lt;/td&gt;
-    &lt;td valign="top"&gt;the Java class to execute.&lt;/td&gt;
-    &lt;td align="center" valign="top"&gt;Either jar or classname&lt;/td&gt;
+    &lt;td&gt;classname&lt;/td&gt;
+    &lt;td&gt;the Java class to execute.&lt;/td&gt;
+    &lt;td&gt;Either jar or classname&lt;/td&gt;
   &lt;/tr&gt;
 
 &lt;/table&gt;
@@ -626,46 +580,45 @@
 <b>What should that example do?</b>
 
 &lt;/body&gt;
-&lt;/html&gt;
-</pre>
+&lt;/html&gt;</pre>
 
 <p>Here is an example documentation page for our task:</p>
-<pre class="code">
-&lt;html&gt;
+<pre>
+&lt;!DOCTYPE html&gt;
+&lt;html lang=&quot;en&quot;&gt;
 
 &lt;head&gt;
-&lt;meta http-equiv="Content-Language" content="en-us"&gt;
 &lt;title&gt;Find Task&lt;/title&gt;
 &lt;/head&gt;
 
 &lt;body&gt;
 
-&lt;h2&gt;&lt;a name="find"&gt;Find&lt;/a&gt;&lt;/h2&gt;
+&lt;h2 id="find"&gt;Find&lt;/h2&gt;
 &lt;h3&gt;Description&lt;/h3&gt;
-&lt;p&gt;Searchs in a given path for a file and returns the absolute to it as property.
+&lt;p&gt;Searches in a given path for a file and returns the absolute to it as property.
 If delimiter is set this task returns all found locations.&lt;/p&gt;
 
 &lt;h3&gt;Parameters&lt;/h3&gt;
-&lt;table border="1" cellpadding="2" cellspacing="0"&gt;
+&lt;table class=&quot;attr&quot;&gt;
   &lt;tr&gt;
-    &lt;td valign="top"&gt;&lt;b&gt;Attribute&lt;/b&gt;&lt;/td&gt;
-    &lt;td valign="top"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;
-    &lt;td align="center" valign="top"&gt;&lt;b&gt;Required&lt;/b&gt;&lt;/td&gt;
+    &lt;th scope=&quot;col&quot;&gt;Attribute&lt;/th&gt;
+    &lt;th scope=&quot;col&quot;&gt;Description&lt;/th&gt;
+    &lt;th scope=&quot;col&quot;&gt;Required&lt;/th&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td valign="top"&gt;file&lt;/td&gt;
-    &lt;td valign="top"&gt;The name of the file to search.&lt;/td&gt;
-    &lt;td align="center" valign="top"&gt;yes&lt;/td&gt;
+    &lt;td&gt;file&lt;/td&gt;
+    &lt;td&gt;The name of the file to search.&lt;/td&gt;
+    &lt;td&gt;yes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td valign="top"&gt;location&lt;/td&gt;
-    &lt;td valign="top"&gt;The name of the property where to store the location&lt;/td&gt;
-    &lt;td align="center" valign="top"&gt;yes&lt;/td&gt;
+    &lt;td&gt;location&lt;/td&gt;
+    &lt;td&gt;The name of the property where to store the location&lt;/td&gt;
+    &lt;td&gt;yes&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
-    &lt;td valign="top"&gt;delimiter&lt;/td&gt;
-    &lt;td valign="top"&gt;A delimiter to use when returning the list&lt;/td&gt;
-    &lt;td align="center" valign="top"&gt;only if the list is required&lt;/td&gt;
+    &lt;td&gt;delimiter&lt;/td&gt;
+    &lt;td&gt;A delimiter to use when returning the list&lt;/td&gt;
+    &lt;td&gt;only if the list is required&lt;/td&gt;
   &lt;/tr&gt;
 &lt;/table&gt;
 
@@ -676,318 +629,251 @@
 
 &lt;h3&gt;Examples&lt;/h3&gt;
 &lt;pre&gt;
-    &lt;find file="ant.jar" location="loc"&gt;
-        &lt;path&gt;
-            &lt;fileset dir="${ant.home}"/&gt;
-        &lt;path&gt;
-    &lt;/find&gt;
-&lt;/pre&gt;
-Searches in Ants home directory for a file &lt;i&gt;ant.jar&lt;/i&gt; and stores its location in
-property &lt;i&gt;loc&lt;/i&gt; (should be ANT_HOME/bin/ant.jar).
+&lt;find file="ant.jar" location="loc"&gt;
+    &lt;path&gt;
+        &lt;fileset dir="${ant.home}"/&gt;
+    &lt;path&gt;
+&lt;/find&gt;&lt;/pre&gt;
+Searches in Ant's home directory for a file &lt;samp&gt;ant.jar&lt;/samp&gt; and stores its location in
+property &lt;code&gt;loc&lt;/code&gt; (should be &lt;samp&gt;ANT_HOME/bin/ant.jar&lt;/samp&gt;).
 
 &lt;pre&gt;
-    &lt;find file="ant.jar" location="loc" delimiter=";"&gt;
-        &lt;path&gt;
-            &lt;fileset dir="C:/"/&gt;
-        &lt;path&gt;
-    &lt;/find&gt;
-    &lt;echo&gt;ant.jar found in: ${loc}&lt;/echo&gt;
-&lt;/pre&gt;
-Searches in Windows C: drive for all &lt;i&gt;ant.jar&lt;/i&gt; and stores their locations in
-property &lt;i&gt;loc&lt;/i&gt; delimited with &lt;i&gt;';'&lt;/i&gt;. (should need a long time :-)
-After that it prints out the result (e.g. C:/ant-1.5.4/bin/ant.jar;C:/ant-1.6/bin/ant.jar).
+&lt;find file="ant.jar" location="loc" delimiter=";"&gt;
+    &lt;path&gt;
+        &lt;fileset dir="C:/"/&gt;
+    &lt;path&gt;
+&lt;/find&gt;
+&lt;echo&gt;ant.jar found in: ${loc}&lt;/echo&gt;&lt;/pre&gt;
+Searches in Windows C: drive for all &lt;samp&gt;ant.jar&lt;/samp&gt; and stores their locations in
+property &lt;code&gt;loc&lt;/code&gt; delimited with &lt;q&gt;;&lt;/q&gt;. (should need a long time :-)
+After that it prints out the result (e.g. &lt;samp&gt;C:/ant-1.5.4/bin/ant.jar;C:/ant-1.6/bin/ant.jar&lt;/samp&gt;).
 
 &lt;/body&gt;
-&lt;/html&gt;
-</pre>
+&lt;/html&gt;</pre>
 
-
-<h2><a name="contribute">Contribute the new task</a></h2>
-If we decide to contribute our task, we should do some things:<ul>
+<h2 id="contribute">Contribute the new task</h2>
+<p>If we decide to contribute our task, we should do some things:</p>
+<ul>
 <li>is our task welcome? :-) Simply ask on the user list</li>
-<li>is the right package used? </li>
+<li>is the right package used?</li>
 <li>does the code conform to the styleguide?</li>
-<li>do all tests pass? </li>
-<li>does the code compile on JDK 1.2 (and passes all tests there)?</li>
+<li>do all tests pass?</li>
+<li>does the code compile on the minimal and current JDK for the Ant distribution (and passes all tests there)?</li>
 <li>code under Apache license</li>
 <li>create a patch file</li>
 <li>publishing that patch file</li>
 </ul>
-The <a href="http://ant.apache.org/ant_task_guidelines.html">Ant Task Guidelines [6]</a> support additional
-information on that.</p>
+<p>The <a href="https://ant.apache.org/ant_task_guidelines.html" target="_top">Ant Task Guidelines [6]</a> support
+additional information on that.</p>
 
-<p>Now we will check the "Checklist before submitting a new task" described in that guideline.
+<p>Now we will check the "Checklist before submitting a new task" described in that guideline.</p>
 <ul>
-<li>Java file begins with Apache license statement. <b><i>must do that</i></b></li>
-<li>Task does not depend on GPL or LGPL code. <b><i>ok</i></b></li>
-<li>Source code complies with style guidelines <b><i>have to check (checkstyle)</i></b></li>
-<li>Code compiles and runs on Java1.2 <b><i>have to try</i></b></li>
-<li>Member variables are private, and provide public accessor methods
-        if access is actually needed. <b><i>have to check (checkstyle)</i></b></li>
-<li><i>Maybe</i> Task has failonerror attribute to control failure behaviour <b><i>hasn't</i></b></li>
-<li>New test cases written and succeed <b><i>passed on JDK 1.4, have to try on JDK 1.2</i></b></li>
-<li>Documentation page written <b><i>ok</i></b></li>
-<li>Example task declarations in the documentation tested. <b><i>ok (used in tests)</i></b></li>
-<li>Patch files generated using cvs diff -u <b><i>to do</i></b></li>
-<li>patch files include a patch to defaults.properties to register the
-tasks <b><i>to do</i></b></li>
-<li>patch files include a patch to tasklist.html to link to the new task page <b><i>to do</i></b></li>
-<li>Message to dev contains [SUBMIT] and task name in subject <b><i>to do</i></b></li>
-<li>Message body contains a rationale for the task <b><i>to do</i></b></li>
-<li>Message attachments contain the required files -source, documentation,
-test and patches zipped up to escape the HTML filter. <b><i>to do</i></b></li>
+<li>Java file begins with Apache license statement. <strong><em>must do that</em></strong></li>
+<li>Task does not depend on GPL or LGPL code. <strong><em>ok</em></strong></li>
+<li>Source code complies with style guidelines <strong><em>have to check (checkstyle)</em></strong></li>
+<li>Code compiles and runs on minimal support java version <strong><em>have to try</em></strong></li>
+<li>Member variables are private, and provide public accessor methods if access is actually needed. <strong><em>have to
+check (checkstyle)</em></strong></li>
+<li><em>Maybe</em> Task has <var>failonerror</var> attribute to control failure
+behaviour <strong><em>hasn't</em></strong></li>
+<li>New test cases written and succeed <strong><em>passed on newest jdk version, have to try on oldest supported jdk version</em></strong></li>
+<li>Documentation page written <strong><em>ok</em></strong></li>
+<li>Example task declarations in the documentation tested. <strong><em>ok (used in tests)</em></strong></li>
+<li>Message to dev contains [SUBMIT] and task name in subject <strong><em>to do</em></strong></li>
+<li>Message body contains a rationale for the task <strong><em>to do</em></strong></li>
+<li>Message body contains the URL to GitHub pull request. <strong><em>to do</em></strong></li>
 </ul>
 
-
 <h3>Package / Directories</h3>
-<p>This task does not depend on any external library. Therefore we can use this as
-a core task. This task contains only one class. So we can use the standard package
-for core tasks: <tt>org.apache.tools.ant.taskdefs</tt>. Implementations are in the
-directory <tt>src/main</tt>, tests in <tt>src/testcases</tt> and buildfiles for
-tests in <tt>src/etc/testcases</tt>.</p>
+<p>This task does not depend on any external library. Therefore we can use this as a core task. This task contains only
+one class. So we can use the standard package for core
+tasks: <code class="code">org.apache.tools.ant.taskdefs</code>. Implementations are in the
+directory <samp>src/main</samp>, tests in <samp>src/testcases</samp> and buildfiles for tests
+in <samp>src/etc/testcases</samp>.</p>
 
-<p>Now we integrate our work into Ants distribution. So first we do an update of our
-cvs tree. If not done yet, you have to checkout the ant module from Apaches cvs server
-as described in <a href="http://ant.apache.org/cvs.html">Access the Source Tree (AnonCVS)
-[7]</a> (password is <i>anoncvs</i>):<pre class="output">
-cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login                 //1
-cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout ant          //2
-</pre>
-If you have a local copy of Ants sources just do an update
-<pre class="output">
-cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login
-cd ant                                                                       //3
-cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic update                //4
-</pre></p>
+<p>Now we integrate our work into Ant distribution. So first we do an update of our Git tree. If not done yet, you
+should clone the Ant repository on GitHub[7], then create a local clone:</p>
+<pre class="input">git clone https://github.com/<em>your-sig</em>/ant.git</pre>
 
-<p>We use the <i>-d</i> flag on <b>//1</b> to specify the cvs directory. You can
-specify the environment variable CVSROOT with that value and after that you haven�t
-to use that flag any more. On <b>//2</b> we get the whole cvs tree of ant. (Sorry,
-but that uses a lot of time ... 10 up to 30 minutes are not unusual ... but this has
-to be done only once :-). A cvs update doesn't use a modulename but you have to be
-inside the directory. Therefore we go into that on <b>//3</b> and do the update
-on <b>//4</b>.</p>
+<p>Now we will build our Ant distribution and do a test. So we can see if there are any tests failing on our
+machine. (We can ignore these failing tests on later steps; Windows syntax used here&mdash;translate to UNIX if
+needed):</p>
+<pre class="input">
+ANTREPO&gt; build                                                    // 1
+ANTREPO&gt; set ANT_HOME=%CD%\dist                                   // 2
+ANTREPO&gt; ant test -Dtest.haltonfailure=false                      // 3</pre>
 
-<p>Now we will build our Ant distribution and do a test. So we can see if there
-are any tests failing on our machine. (We can ignore these failing tests on later
-steps; windows syntax used here- translate to xNIX if needed):
-<pre class="output">
-ANTHOME&gt; build                                                    // 1
-ANTHOME&gt; set ANT_HOME=%CD%\dist                                   // 2
-ANTHOME&gt; ant test -Dtest.haltonfailure=false                      // 3
-</pre>
+<p>First we have to build our Ant distribution (<strong>//1</strong>). On <strong>//2</strong> we set
+the <code>ANT_HOME</code> environment variable to the directory where the new created distribution is stored
+(<code>%CD%</code> is expanded to the current directory on Windows 2000 and later). On <strong>//3</strong> we let Ant
+do all the tests (which enforced a compile of all tests) without stopping on first failure.</p>
 
-First we have to build our Ant distribution (<b>//1</b>). On <b>//2</b> we set the ANT_HOME
-environment variable to the directory where the new created distribution is stored
-(%CD% is expanded to the current directory on Windows 2000 and XP, on 9x and NT
-write it out). On <b>//3</b> we let Ant do all the tests (which enforced a compile
-of all tests) without stopping on first failure.</p>
-
-<p>Next we apply our work onto Ants sources. Because we haven't modified any, this is
-a relative simple step. <i>(Because I have a local copy of Ant and usually contribute my
-work, I work on the local copy just from the beginning. The advantage: this step isn't
-necessary and saves a lot of work if you modify existing source :-)</i>.
+<p>Next we apply our work onto Ant sources. Because we haven't modified any, this is a relatively simple
+step. <em>(Because I have a local Git clone of Ant and usually contribute my work, I work on the local copy just from
+the beginning. The advantage: this step isn't necessary and saves a lot of work if you modify existing sources :-)</em>.
 
 <ul>
-<li>move the Find.java to ANTHOME/src/main/org/apache/tools/ant/taskdefs/Find.java </li>
-<li>move the FindTest.java to ANTHOME/src/testcases/org/apache/tools/ant/taskdefs/FindTest.java </li>
-<li>move the build.xml to ANTHOME/src/etc/testcases/taskdefs/<b>find.xml</b> (!!! renamed !!!)</li>
-<li>add a <tt>package org.apache.tools.ant.taskdefs;</tt> at the beginning of the two java files </li>
-<li>delete all stuff from find.xml keeping the targets "testFileNotPresent", "testFilePresent",
-    "test.init" and "testMultipleFiles" </li>
-<li>delete the dependency to "use.init" in the find.xml </li>
-<li>in FindTest.java change the line <tt>configureProject("build.xml");</tt> to
-    <tt>configureProject("src/etc/testcases/taskdefs/find.xml");</tt> </li>
-<li>move the find.html to ANTHOME/docs/manual/Tasks/find.html </li>
-<li>add a <tt>&lt;a href="Tasks/find.html"&gt;Find&lt;/a&gt;&lt;br&gt;</tt>
-    in the ANTHOME/docs/manual/tasklist.html </li>
+    <li>move the <samp>Find.java</samp> to <samp>ANTREPO/src/main/org/apache/tools/ant/taskdefs/Find.java</samp></li>
+    <li>move the <samp>FindTest.java</samp> to <samp>ANTREPO/src/testcases/org/apache/tools/ant/taskdefs/FindTest.java</samp></li>
+    <li>move the <samp>build.xml</samp> to <samp>ANTREPO/src/etc/testcases/taskdefs/<strong>find.xml</strong></samp> (!!! renamed !!!)</li>
+    <li>add a <code>package org.apache.tools.ant.taskdefs;</code> at the beginning of the two java files</li>
+    <li>delete all stuff from <samp>find.xml</samp> keeping the
+    targets <q>testFileNotPresent</q>, <q>testFilePresent</q>, <q>test.init</q> and <q>testMultipleFiles</q></li>
+    <li>delete the dependency to <q>use.init</q> in the <samp>find.xml</samp></li>
+    <li>in <samp>FindTest.java</samp> change the line <code>configureProject("build.xml");</code>
+    to <code>configureProject("src/etc/testcases/taskdefs/find.xml");</code></li>
+    <li>move the <samp>find.html</samp> to <samp>ANTREPO/docs/manual/Tasks/find.html</samp></li>
+    <li>add a <code>&lt;a href="Tasks/find.html"&gt;Find&lt;/a&gt;&lt;br&gt;</code> in
+    the <samp>ANTREPO/docs/manual/tasklist.html</samp></li>
 </ul>
 
-Now our modifications are done and we will retest it:
-<pre class="output">
-ANTHOME&gt; build
-ANTHOME&gt; ant run-single-test                                      // 1
+<p>Now our modifications are done and we will retest it:</p>
+<pre class="input">
+ANTREPO&gt; build
+ANTREPO&gt; ant run-single-test                                      // 1
              -Dtestcase=org.apache.tools.ant.taskdefs.FindTest    // 2
-             -Dtest.haltonfailure=false
-</pre>
-Because we only want to test our new class, we use the target for single tests, specify
-the test to use and configure not to halt on the first failure - we want to see all
-failures of our own test (<b>//1 + 2</b>).</p>
+             -Dtest.haltonfailure=false</pre>
+<p>Because we only want to test our new class, we use the target for single tests, specify the test to use and configure
+not to halt on the first failure&mdash;we want to see all failures of our own test (<strong>//1 + 2</strong>).</p>
 
-<p>And ... oh, all tests fail: <i>Ant could not find the task or a class this task relies upon.</i></p>
+<p>And ... oh, all tests fail: <em>Ant could not find the task or a class this task relies upon.</em></p>
 
-<p>Ok: in the earlier steps we told Ant to use the Find class for the <code>&lt;find&gt;</code> task (remember the
-<code>&lt;taskdef&gt;</code> statement in the "use.init" target). But now we want to introduce that task as
-a core task. And nobody wants to taskdef the javac, echo, ... So what to do? The answer is the
-src/main/.../taskdefs/default.properties. Here is the mapping between taskname and implementing
-class done. So we add a <tt>find=org.apache.tools.ant.taskdefs.Find</tt> as the last core
-task (just before the <tt># optional tasks</tt> line). Now a second try:
-<pre class="output">
-ANTHOME&gt; build                                                    // 1
-ANTHOME&gt; ant run-single-test
+<p>Ok: in the earlier steps we told Ant to use the Find class for the <code>&lt;find&gt;</code> task (remember
+the <code>&lt;taskdef&gt;</code> statement in the <q>use.init</q> target). But now we want to introduce that task as a
+core task. And nobody wants to <code>taskdef</code> the <code>javac</code>, <code>echo</code>, ... So what to do? The
+answer is the <samp>src/main/.../taskdefs/default.properties</samp>. Here is the mapping between taskname and
+implementing class done. So we add a <code>find=org.apache.tools.ant.taskdefs.Find</code> as the last core task (just
+before the <code># optional tasks</code> line). Now a second try:</p>
+<pre class="input">
+ANTREPO&gt; build                                                    // 1
+ANTREPO&gt; ant run-single-test
              -Dtestcase=org.apache.tools.ant.taskdefs.FindTest
-             -Dtest.haltonfailure=false
-</pre>
-We have to rebuild (<b>//1</b>) Ant because the test look in the %ANT_HOME%\lib\ant.jar
-(more precise: on the classpath) for the properties file. And we have only modified it in the
-source path. So we have to rebuild that jar. But now all tests pass and we check whether our class
-breaks some other tests.
-<pre class="output">
-ANTHOME&gt; ant test -Dtest.haltonfailure=false
-</pre>
-Because there are a lot of tests this step requires a little bit of time. So use the <i>run-single-test</i>
-during development and do the <i>test</i> only at the end (maybe sometimes during development too).
-We use the <i>-Dtest.haltonfailure=false</i> here because there could be other tests fail and we have
-to look into them.</p>
+             -Dtest.haltonfailure=false</pre>
+<p>We have to rebuild (<strong>//1</strong>) Ant because the test look in the <samp>%ANT_HOME%\lib\ant.jar</samp> (more
+precise: on the classpath) for the properties file. And we have only modified it in the source path. So we have to
+rebuild that jar. But now all tests pass and we check whether our class breaks some other tests.</p>
+<pre class="input">ANTREPO&gt; ant test -Dtest.haltonfailure=false</pre>
+<p>Because there are a lot of tests this step requires a little bit of time. So use the <q>run-single-test</q> during
+development and do the <q>test</q> only at the end (maybe sometimes during development too).  We use
+the <kbd>-Dtest.haltonfailure=false</kbd> here because there could be other tests fail and we have to look into
+them.</p>
 
-<p>This test run should show us two things: our test will run and the number of failing tests
-is the same as directly after the cvs update (without our modifications).</p>
-
-
+<p>This test run should show us two things: our test will run and the number of failing tests is the same as directly
+after <code>git clone</code> (without our modifications).</p>
 
 <h3>Apache license statement</h3>
 <p>Simply copy the license text from one the other source from the Ant source tree.</p>
 
+<h3>Test on the minimal JDK version</h3>
+<p>Ant 1.10 uses Java 8 for development, but Ant 1.9 is actively maintained, too. That means that updates to Ant code 
+present in Ant 1.9 must be able to run on a JDK 5. (It is fine to address only ant 1.10 and above for new teasks.)
+So we have to test that. You can download older JDKs
+from <a href="https://www.oracle.com/technetwork/java/archive-139210.html" target="_top">Oracle [8]</a>.</p>
 
-<h3>Test on JDK 1.2</h3>
-<p>Until version 1.5 Ant must be able to run on a JDK 1.1. With version 1.6 this is not a
-requisite any more. But JDK 1.2 is a must-to-work-with. So we have to test that. You can download older
-JDKs from <a href="http://www.oracle.com/technetwork/java/archive-139210.html">Oracle [8]</a>.</p>
-
-<p>Clean the ANT_HOME variable, delete the <i>build, bootstrap</i> and <i>dist</i> directory
-and point JAVA_HOME to the JDK 1.2 home directory. Then do the <tt>build</tt>, set ANT_HOME
-and run <tt>ant test</tt> (like above).</p>
+<p>Clean the <code>ANT_HOME</code> variable, delete the <samp>build</samp>, <samp>bootstrap</samp> and <samp>dist</samp>
+directories, and point <code>JAVA_HOME</code> to the JDK 5 home directory. Then create the patch with your commit,
+checkout 1.9.x branch in Git, apply your patch and do the <code>build</code>, set <code>ANT_HOME</code> and
+run <kbd>ant test</kbd> (like above).</p>
 
 <p>Our test should pass.</p>
 
-
-
 <h3>Checkstyle</h3>
-<p>There are many things we have to ensure. Indentation with 4 spaces, blanks here and there, ...
-(all described in the <a href="http://ant.apache.org/ant_task_guidelines.html">Ant Task Guidelines [6]</a> which
-includes the <a href="http://www.oracle.com/technetwork/java/codeconvtoc-136057.html">Sun code style
-[9]</a>). Because there are so many things we would be happy to have a tool for do the checks.
-There is one: checkstyle. Checkstyle is available at <a href="http://checkstyle.sourceforge.net/">
-Sourceforge [10]</a> and Ant provides with the <tt>check.xml</tt> a buildfile which will do the job
-for us.</p>
+<p>There are many things we have to ensure. Indentation with 4 spaces, blanks here and there, ...  (all described in
+the <a href="https://ant.apache.org/ant_task_guidelines.html" target="_top">Ant Task Guidelines [6]</a> which includes
+the <a href="https://www.oracle.com/technetwork/java/codeconvtoc-136057.html" target="_top">Sun code style
+[9]</a>). Because there are so many things we would be happy to have a tool for do the checks.  There is one:
+checkstyle. Checkstyle is available at <a href="https://checkstyle.org/" target="_top">Sourceforge [10]</a>
+and Ant provides with the <samp>check.xml</samp> a buildfile which will do the job for us.</p>
 
-<p>Download it and put the checkstyle-*-all.jar into your %USERPROFILE%\.ant\lib directory.
-All jar's stored there are available to Ant so you haven't to add it to you %ANT_HOME%\lib
-directory (this feature was added with Ant 1.6).</p>
+<p>Download it and put the <samp>checkstyle-*-all.jar</samp> into your <samp>%USERPROFILE%\.ant\lib</samp> directory.
+All jar's stored there are available to Ant so you haven't to add it to you <samp>%ANT_HOME%\lib</samp> directory (this
+feature is available <em>since Ant 1.6</em>).</p>
 
-<p>So we will run the tests with
-<pre class="output">
-ANTHOME&gt; ant -f check.xml checkstyle htmlreport
-</pre>
-I prefer the HTML report because there are lots of messages and we can navigate faster.
-Open the ANTHOME/build/reports/checkstyle/html/index.html and navigate to the Find.java. Now we
-see that there are some errors: missing whitespaces, unused imports, missing javadocs. So we have
-to do that.</p>
+<p>So we will run the tests with</p>
+<pre class="input">ANTREPO&gt; ant -f check.xml checkstyle htmlreport</pre>
+<p>I prefer the HTML report because there are lots of messages and we can navigate faster.  Open
+the <samp>ANTREPO/build/reports/checkstyle/html/index.html</samp> and navigate to the <samp>Find.java</samp>. Now we see
+that there are some errors: missing whitespaces, unused imports, missing javadocs. So we have to do that.</p>
 
-<p>Hint: start at the <b>buttom</b> of the file so the line numbers in the report will keep
-up to date and you will find the next error place much more easier without redoing the checkstyle.</p>
+<p>Hint: start at the <strong>bottom</strong> of the file so the line numbers in the report will keep up to date and you
+will find the next error place much more easier without redoing the checkstyle.</p>
 
-<p>After cleaning up the code according to the messages we delete the reports directory and
-do a second checkstyle run. Now our task isn't listed. That's fine :-)</p>
-
-
-
-<!--
-  Couldnt create the diff that way for myself, but that should be documented.
-  But on the other hand this tutorial should not be forgotten any longer so I
-  comment that out.  JHM
-<h3>Creating the diff</h3>
-<p>Creating a diff for Ant is very easy: just start <tt>ant -f patch.xml</tt> and all is done
-automatically. This step requires a cvs executable in your path and internet access (more precise:
-cvs access). As a result we get a file <i> TODO </i>.</p>
--->
-
+<p>After cleaning up the code according to the messages we delete the reports directory and do a second checkstyle
+run. Now our task isn't listed. That's fine :-)</p>
 
 <h3>Publish the task</h3>
-<p>Finally we publish that archive. As described in the <a href="http://ant.apache.org/ant_task_guidelines.html">
-Ant Task Guidelines [7]</a> we can post it on the developer mailinglist or we create a BugZilla
-entry. For both we need some information:</p>
+<p>Finally we publish that archive. As described in the <a href="https://ant.apache.org/ant_task_guidelines.html"
+target="_top">Ant Task Guidelines [7]</a> we can announce it on the developer mailing list, create a BugZilla entry and
+open a GitHub pull request. For both we need some information:</p>
 
-<table border="1">
+<table>
 <tr>
-  <th>subject</th>
-  <td><i>short description</i></td>
+  <th scope="row">subject</th>
+  <td><em>short description</em></td>
   <td>Task for finding files in a path</td>
 </tr>
 <tr>
-  <th>body</th>
-  <td><i>more details about the path</i></td>
-  <td>This new task looks inside a nested <code>&lt;path/&gt;</code> for occurrences of a file and stores
-      all locations as a property. See the included manual for details.</td>
+  <th scope="row">body</th>
+  <td><em>more details about the path</em></td>
+  <td>This new task looks inside a nested <code>&lt;path/&gt;</code> for occurrences of a file and stores all locations
+      as a property. See the included manual for details.</td>
 </tr>
 <tr>
-  <th>attachments</th>
-  <td><i>all files needed to apply the path</i></td>
-  <td>Archive containing a patch with the new and modified resources</td>
+  <th scope="row">pull request reference</th>
+  <td><em>GitHub pull request URL</em></td>
+  <td>https://github.com/apache/ant/pull/0</td>
 </tr>
 </table>
 
-<p>Sending an email with these information is very easy and I think I haven't to show that.
-The other way - BugZilla - is slightly more difficult. But it has the advantage that entries
-will not be forgotten (once per week a report is generated). So I will show this way.</p>
+<p>Sending an email with this information is very easy and I think I haven't to describe that.  BugZilla is slightly
+more difficult.  But the advantage is that entries will not be forgotten (a report is generated once every weekend).  So
+I will describe the process.</p>
 
-<p>You must have a BugZilla account for that. So open the <a href="http://issues.apache.org/bugzilla/">
-BugZilla Main Page [11]</a> and follow the link
-<a href="http://issues.apache.org/bugzilla/createaccount.cgi">Open a new Bugzilla account [12]</a>
+<p>First, you must have a BugZilla account. So open the <a href="https://issues.apache.org/bugzilla/"
+target="_top">BugZilla Main Page [11]</a> and follow the
+link <a href="https://issues.apache.org/bugzilla/createaccount.cgi" target="_top">Open a new Bugzilla account [12]</a>
 and the steps described there if you haven't one.</p>
 
 <ol>
-<li>From the BugZilla main page choose <a href="http://issues.apache.org/bugzilla/enter_bug.cgi">Enter
-    a new bug report [13]</a></li>
-<li>Choose "Ant" as product </li>
-<li>Version is the last "Alpha (nightly)" (at this time 1.7)</li>
+<li>From the BugZilla main page choose <a href="https://issues.apache.org/bugzilla/enter_bug.cgi" target="_top">Enter a
+    new bug report [13]</a></li>
+<li>Choose "Ant" as product</li>
+<li>Version is the last "Alpha (nightly)" (at this time 1.10)</li>
 <li>Component is "Core tasks"</li>
 <li>Platform and Severity are ok with "Other" and "Normal"</li>
 <li>Initial State is ok with "New"</li>
 <li>Same with the empty "Assigned to"</li>
-<li>It is not required to add yourself as CC, because you are the reporter and therefore will be
-    informed on changes</li>
-<li>URL: no url required</li>
-<li>Summary: add the <i>subject</i> from the table</li>
-<li>Description: add the <i>body</i> from the table</li>
-<li>Then press "Commit"</li>
-<li>After redirecting to the new created bug entry click "Create a New Attachment"</li>
-<li>Enter the path to your local path file into "File" or choose it via the "File"'s
-    button.</li>
-<li>Enter a short description into "Description", so that you could guess, what the
-    path file includes. Here we could add "Initial Patch".</li>
-<li>The "Content Type" is "auto-detect". You could use the "patch" type, if you only
-    provide a single path file, but we want do upload more that one, included in our
-    patch.zip.</li>
+<li>It is not required to add yourself as CC, because you are the reporter and therefore will be informed on
+    changes</li>
+<li>URL: GitHub pull request URL</li>
+<li>Summary: add the <var>subject</var> from the table</li>
+<li>Description: add the <var>body</var> from the table</li>
 <li>Then press "Commit"</li>
 </ol>
-Now the new task is uploaded into the bug database.
 
+<p>Now the new task is registered in the bug database.</p>
 
-<h2><a name="resources">Resources</a></h2>
-&nbsp;&nbsp;[1] <a href="tutorial-writing-tasks.html">tutorial-writing-tasks.html</a><br>
-&nbsp;&nbsp;[2] <a href="tutorial-tasks-filesets-properties.zip">tutorial-tasks-filesets-properties.zip</a><br>
-&nbsp;&nbsp;[3] <a href="properties.html#built-in-props">properties.html#built-in-props</a><br>
-&nbsp;&nbsp;[4] <a href="http://ant-contrib.sourceforge.net/">http://ant-contrib.sourceforge.net/</a><br>
-&nbsp;&nbsp;[5] <a href="Tasks/java.html">Tasks/java.html</a><br>
-&nbsp;&nbsp;[6] <a href="http://ant.apache.org/ant_task_guidelines.html">http://ant.apache.org/ant_task_guidelines.html</a><br>
-&nbsp;&nbsp;[7] <a href="http://ant.apache.org/cvs.html">http://ant.apache.org/cvs.html</a><br>
-&nbsp;&nbsp;[8] <a href="http://www.oracle.com/technetwork/java/archive-139210.html">http://www.oracle.com/technetwork/java/archive-139210.html</a><br>
-&nbsp;&nbsp;[9] <a href="http://www.oracle.com/technetwork/java/codeconvtoc-136057.html">http://www.oracle.com/technetwork/java/codeconvtoc-136057.html</a><br>
-&nbsp;&nbsp;[10] <a href="http://checkstyle.sourceforge.net/">http://checkstyle.sourceforge.net/</a><br>
-&nbsp;&nbsp;[11] <a href="http://issues.apache.org/bugzilla/">http://issues.apache.org/bugzilla/</a><br>
-&nbsp;&nbsp;[12] <a href="http://issues.apache.org/bugzilla/createaccount.cgi">http://issues.apache.org/bugzilla/createaccount.cgi</a><br>
-&nbsp;&nbsp;[13] <a href="http://issues.apache.org/bugzilla/enter_bug.cgi">http://issues.apache.org/bugzilla/enter_bug.cgi</a><br>
-
-
-<!--
-  TODO:
-  - how to create a path (path.xml / command line)
--->
-
-
-
-
+<h2 id="resources">Resources</h2>
+<ol class="refs">
+    <li><a href="tutorial-writing-tasks.html">tutorial-writing-tasks.html</a></li>
+    <li><a href="tutorial-tasks-filesets-properties.zip">tutorial-tasks-filesets-properties.zip</a></li>
+    <li><a href="properties.html#built-in-props">properties.html#built-in-props</a></li>
+    <li><a href="http://ant-contrib.sourceforge.net/" target="_top">http://ant-contrib.sourceforge.net/</a></li>
+    <li><a href="Tasks/java.html">Tasks/java.html</a></li>
+    <li><a href="https://ant.apache.org/ant_task_guidelines.html"
+           target="_top">https://ant.apache.org/ant_task_guidelines.html</a></li>
+    <li><a href="https://github.com/apache/ant" target="_top">https://github.com/apache/ant</a></li>
+    <li><a href="https://www.oracle.com/technetwork/java/archive-139210.html"
+           target="_top">https://www.oracle.com/technetwork/java/archive-139210.html</a></li>
+    <li><a href="https://www.oracle.com/technetwork/java/codeconvtoc-136057.html"
+           target="_top">https://www.oracle.com/technetwork/java/codeconvtoc-136057.html</a></li>
+    <li><a href="https://checkstyle.org/" target="_top">https://checkstyle.org/</a></li>
+    <li><a href="https://issues.apache.org/bugzilla/" target="_top">https://issues.apache.org/bugzilla/</a></li>
+    <li><a href="https://issues.apache.org/bugzilla/createaccount.cgi"
+           target="_top">https://issues.apache.org/bugzilla/createaccount.cgi</a></li>
+    <li><a href="https://issues.apache.org/bugzilla/enter_bug.cgi"
+           target="_top">https://issues.apache.org/bugzilla/enter_bug.cgi</a></li>
+</ol>
 
 </body>
 </html>
diff --git a/manual/tutorial-writing-tasks.html b/manual/tutorial-writing-tasks.html
index c3b8a6a..960e41d 100644
--- a/manual/tutorial-writing-tasks.html
+++ b/manual/tutorial-writing-tasks.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,10 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 <head>
   <title>Tutorial: Writing Tasks</title>
-  <link rel="stylesheet" type="text/css" href="stylesheets/style.css" />
+  <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 </head>
 <body>
 <h1>Tutorial: Writing Tasks</h1>
@@ -41,22 +42,20 @@
 <li><a href="#resources">Resources</a></li>
 </ul>
 
-<a name="buildenvironment"></a>
-<h2>Set up the build environment</h2>
-<p>Apache Ant builds itself, we are using Ant too (why we would write
-a task if not? :-) therefore we should use Ant for our build.</p>
-<p>We choose a directory as root directory. All things will be done
-here if I say nothing different. I will reference this directory
-as <i>root-directory</i> of our project. In this root-directory we
-create a text file names <i>build.xml</i>. What should Ant do for us?</p>
+<h2 id="buildenvironment">Set up the build environment</h2>
+<p>Apache Ant builds itself, we are using Ant too (why we would write a task if not? :-) therefore we should use Ant for
+our build.</p>
+<p>We choose a directory as root directory. All things will be done here if I say nothing different. I will reference
+this directory as <em>root-directory</em> of our project. In this root-directory we create a text file
+names <samp>build.xml</samp>. What should Ant do for us?</p>
 <ul>
 <li>compiles my stuff</li>
 <li>make the jar, so that I can deploy it</li>
 <li>clean up everything</li>
 </ul>
 So the buildfile contains three targets.
-<pre class="code">
-&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;project name="MyTask" basedir="." default="jar"&gt;
 
     &lt;target name="clean" description="Delete all generated files"&gt;
@@ -72,16 +71,15 @@
         &lt;jar destfile="MyTask.jar" basedir="classes"/&gt;
     &lt;/target&gt;
 
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-This buildfile uses often the same value (src, classes, MyTask.jar), so we should rewrite that
-using <code>&lt;property&gt;</code>s. On second there are some handicaps: <code>&lt;javac&gt;</code> requires that the destination
-directory exists; a call of "clean" with a non existing classes directory will fail; "jar" requires
-the execution of some steps before. So the refactored code is:
+This buildfile uses often the same value (<samp>src</samp>, <samp>classes</samp>, <samp>MyTask.jar</samp>), so we should
+rewrite that using <code>&lt;property&gt;</code>s. On second there are some handicaps: <code>&lt;javac&gt;</code>
+requires that the destination directory exists; a call of <q>clean</q> with a non existing classes directory will
+fail; <q>jar</q> requires the execution of some steps before. So the refactored code is:
 
-<pre class="code">
-&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;project name="MyTask" basedir="." default="jar"&gt;
 
     <b>&lt;property name="src.dir" value="src"/&gt;</b>
@@ -101,38 +99,29 @@
         &lt;jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/&gt;
     &lt;/target&gt;
 
-&lt;/project&gt;
-</pre>
-<i>ant.project.name</i> is one of the
-<a href="http://ant.apache.org/manual/properties.html#built-in-props" target="_blank">
-build-in properties [1]</a> of Ant.
+&lt;/project&gt;</pre>
+<p><code>ant.project.name</code> is one of the <a href="properties.html#built-in-props" target="_top">build-in
+properties [1]</a> of Ant.</p>
 
+<h2 id="write1">Write the Task</h2>
 
-<a name="write1"></a>
-<h2>Write the Task</h2>
-
-Now we write the simplest Task - a HelloWorld-Task (what else?). Create a text file
-<i>HelloWorld.java</i> in the src-directory with:
-<pre class="code">
+<p>Now we write the simplest Task&mdash;a HelloWorld Task (what else?). Create a text file <samp>HelloWorld.java</samp>
+in the src-directory with:</p>
+<pre>
 public class HelloWorld {
     public void execute() {
         System.out.println("Hello World");
     }
-}
-</pre>
-and we can compile and jar it with <tt>ant</tt> (default target is "jar" and via
-its <i>depends</i>-clause the "compile" is executed before).
+}</pre>
+<p>and we can compile and jar it with <kbd>ant</kbd> (default target is <q>jar</q> and via its <var>depends</var>
+attribute the <q>compile</q> is executed before).</p>
 
-
-
-<a name="use1"></a>
-<h2>Use the Task</h2>
-<p>But after creating the jar we want to use our new Task. Therefore we need a
-new target "use". Before we can use our new task we have to declare it with
-<a href="http://ant.apache.org/manual/Tasks/taskdef.html" target="_blank">
-<code>&lt;taskdef&gt;</code> [2]</a>. And for easier process we change the default clause:</p>
-<pre class="code">
-&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+<h2 id="use1">Use the Task</h2>
+<p>But after creating the jar we want to use our new Task. Therefore we need a new target <q>use</q>. Before we can use
+our new task we have to declare it with <a href="Tasks/taskdef.html" target="_top"><code>&lt;taskdef&gt;</code>
+[2]</a>.  And for easier process we change the <var>default</var> attribute:</p>
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;project name="MyTask" basedir="." default="<b>use</b>"&gt;
 
     ...
@@ -142,13 +131,12 @@
         &lt;helloworld/&gt;
     &lt;/target&gt;</b>
 
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>Important is the <i>classpath</i>-attribute. Ant searches in its /lib directory for
-tasks and our task isn't there. So we have to provide the right location. </p>
+<p>Important is the <var>classpath</var> attribute. Ant searches in its <samp>/lib</samp> directory for tasks and our
+task isn't there. So we have to provide the right location.</p>
 
-<p>Now we can type in <tt>ant</tt> and all should work ...</p>
+<p>Now we can type in <kbd>ant</kbd> and all should work ...</p>
 <pre class="output">
 Buildfile: build.xml
 
@@ -163,23 +151,18 @@
 [helloworld] Hello World
 
 BUILD SUCCESSFUL
-Total time: 3 seconds
-</pre>
+Total time: 3 seconds</pre>
 
+<h2 id="TaskAdapter">Integration with TaskAdapter</h2>
+<p>Our class has nothing to do with Ant. It extends no superclass and implements no interface. How does Ant know to
+integrate? Via name convention: our class provides a method with signature <code class="code">public void
+execute()</code>. This class is wrapped by Ant's <code class="code">org.apache.tools.ant.TaskAdapter</code> which is a
+task and uses reflection for setting a reference to the project and calling the <code class="code">execute()</code>
+method.</p>
 
-
-<a name="TaskAdapter"></a>
-<h2>Integration with TaskAdapter</h2>
-<p>Our class has nothing to do with Ant. It extends no superclass and implements
-no interface. How does Ant know to integrate? Via name convention: our class provides
-a method with signature <tt>public void execute()</tt>. This class is wrapped by Ant's
-<tt>org.apache.tools.ant.TaskAdapter</tt> which is a task and uses reflection for
-setting a reference to the project and calling the <i>execute()</i> method.</p>
-
-<p><i>Setting a reference to the project</i>? Could be interesting. The Project class
-gives us some nice abilities: access to Ant's logging facilities getting and setting
-properties and much more. So we try to use that class:</p>
-<pre class="code">
+<p><em>Setting a reference to the project</em>? Could be interesting. The Project class gives us some nice abilities:
+access to Ant's logging facilities getting and setting properties and much more. So we try to use that class:</p>
+<pre>
 import org.apache.tools.ant.Project;
 
 public class HelloWorld {
@@ -194,24 +177,19 @@
         String message = project.getProperty("ant.project.name");
         project.log("Here is project '" + message + "'.", Project.MSG_INFO);
     }
-}
-</pre>
-and the execution with <tt>ant</tt> will show us the expected
+}</pre>
+<p>and the execution with <kbd>ant</kbd> will show us the expected</p>
 <pre class="output">
 use:
-Here is project 'MyTask'.
-</pre>
+Here is project 'MyTask'.</pre>
 
+<h2 id="derivingFromTask">Deriving from Ant's Task</h2>
+<p>Ok, that works ... But usually you will extend <code class="code">org.apache.tools.ant.Task</code>.  That class is
+integrated in Ant, gets the project reference, provides documentation fields, provides easier access to the logging
+facility and (very useful) gives you the exact location where <em>in the buildfile</em> this task instance is used.</p>
 
-<a name="derivingFromTask"></a>
-<h2>Deriving from Ant's Task</h2>
-<p>Ok, that works ... But usually you will extend <tt>org.apache.tools.ant.Task</tt>.
-That class is integrated in Ant, get's the project-reference, provides documentation
-fields, provides easier access to the logging facility and (very useful) gives you
-the exact location where <i>in the buildfile</i> this task instance is used.</p>
-
-<p>Oki-doki - let's us use some of these:</p>
-<pre class="code">
+<p>Oki-doki&mdash;let's us use some of these:</p>
+<pre>
 import org.apache.tools.ant.Task;
 
 public class HelloWorld extends Task {
@@ -225,35 +203,33 @@
         // where this task is used?
         log("I am used in: " +  getLocation() );
     }
-}
-</pre>
+}</pre>
 <p>which gives us when running</p>
 <pre class="output">
 use:
 [helloworld] Here is project 'MyTask'.
-[helloworld] I am used in: C:\tmp\anttests\MyFirstTask\build.xml:23:
-</pre>
+[helloworld] I am used in: C:\tmp\anttests\MyFirstTask\build.xml:23:</pre>
 
-<a name="accessTaskProject"></a>
-<h2>Accessing the Task's Project</h2>
-<p>The parent project of your custom task may be accessed through method <code>getProject()</code>.  However, do not call this from the custom task constructor, as the return value will be null.  Later, when node attributes or text are set, or method <code>execute()</code> is called, the Project object is available.</p>
+<h2 id="accessTaskProject">Accessing the Task's Project</h2>
+<p>The parent project of your custom task may be accessed through method <code class="code">getProject()</code>.
+However, do not call this from the custom task constructor, as the return value will be null.  Later, when node
+attributes or text are set, or method <code class="code">execute()</code> is called, the Project object is
+available.</p>
 <p>Here are two useful methods from class Project:</p>
 <ul>
-  <li><code>String getProperty(String propertyName)</code></li>
-  <li>
-    <code>String replaceProperties(String value)</code>
-  </li>
+  <li><code class="code">String getProperty(String propertyName)</code></li>
+  <li><code class="code">String replaceProperties(String value)</code></li>
 </ul>
 
-<p>The method <code>replaceProperties()</code> is discussed further in section <a href="#NestedText">Nested Text</a>.</p>
+<p>The method <code class="code">replaceProperties()</code> is discussed further in section <a href="#NestedText">Nested
+Text</a>.</p>
 
-<a name="attributes"></a>
-<h2>Attributes</h2>
-<p>Now we want to specify the text of our message (it seems that we are
-rewriting the <code>&lt;echo/&gt;</code> task :-). First we well do that with an attribute.
-It is very easy - for each attribute provide a <tt>public void set<code>&lt;attributename&gt;</code>(<code>&lt;type&gt;</code>
-newValue)</tt> method and Ant will do the rest via reflection.</p>
-<pre class="code">
+<h2 id="attributes">Attributes</h2>
+<p>Now we want to specify the text of our message (it seems that we are rewriting the <code>&lt;echo/&gt;</code> task
+:-). First we well do that with an attribute.  It is very easy&mdash;for each attribute provide
+a <code class="code">public void set<i>Attributename</i>(<i>Type</i> newValue)</code> method and Ant will do the rest
+via reflection.</p>
+<pre>
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.BuildException;
 
@@ -265,51 +241,48 @@
     }
 
     public void execute() {
-        if (message==null) {
+        if (message == null) {
             throw new BuildException("No message set.");
         }
         log(message);
     }
 
-}
-</pre>
-<p>Oh, what's that in execute()? Throw a <i>BuildException</i>? Yes, that's the usual
-way to show Ant that something important is missed and complete build should fail. The
-string provided there is written as build-failes-message. Here it's necessary because
-the log() method can't handle a <i>null</i> value as parameter and throws a NullPointerException.
-(Of course you can initialize the <i>message</i> with a default string.)</p>
+}</pre>
+<p>Oh, what's that in <code class="code">execute()</code>? Throw a <code>BuildException</code>? Yes, that's the usual
+way to show Ant that something important is missed and complete build should fail. The string provided there is written
+as build-fails-message. Here it's necessary because the <code class="code">log()</code> method can't handle
+a <code>null</code> value as parameter and throws a <code>NullPointerException</code>.  (Of course you can initialize
+the <var>message</var> with a default string.)</p>
 
 <p>After that we have to modify our buildfile:</p>
-<pre class="code">
+<pre>
     &lt;target name="use" description="Use the Task" depends="jar"&gt;
         &lt;taskdef name="helloworld"
                  classname="HelloWorld"
                  classpath="${ant.project.name}.jar"/&gt;
         &lt;helloworld <b>message="Hello World"</b>/&gt;
-    &lt;/target&gt;
-</pre>
+    &lt;/target&gt;</pre>
 <p>That's all.</p>
 
-<p>Some background for working with attributes: Ant supports any of these datatypes as
-arguments of the set-method:</p><ul>
-<li>elementary data type like <i>int</i>, <i>long</i>, ...</li>
-<li>its wrapper classes like <i>java.lang.Integer</i>, <i>java.lang.Long</i>, ...</li>
-<li><i>java.lang.String</i></li>
-<li>some more classes (e.g. <i>java.io.File</i>; see
-    <a href="develop.html#set-magic">Manual
-    'Writing Your Own Task' [3]</a>)</li>
+<p>Some background for working with attributes: Ant supports any of these datatypes as arguments of the set-method:</p>
+<ul>
+<li>primitive data types like <code class="code">int</code>, <code class="code">long</code>, ...</li>
+<li>their wrapper classes like <code class="code">java.lang.Integer</code>, <code class="code">java.lang.Long</code>,
+...</li>
+<li><code class="code">java.lang.String</code></li>
+<li>some other classes (e.g. <code class="code">java.io.File</code>; see <a href="develop.html#set-magic">Manual
+'Writing Your Own Task' [3]</a>)</li>
 <li>Any Java Object parsed from Ant 1.8's <a href="Tasks/propertyhelper.html">Property
 Helper</a></li>
 </ul>
-Before calling the set-method all properties are resolved. So a <tt>&lt;helloworld message="${msg}"/&gt;</tt>
-would not set the message string to "${msg}" if there is a property "msg" with a set value.
+<p>Before calling the set-method all properties are resolved. So a <code>&lt;helloworld message="${msg}"/&gt;</code>
+would not set the message string to <q>${msg}</q> if there is a property <code>msg</code> with a set value.</p>
 
-
-<a name="NestedText"></a>
-<h2>Nested Text</h2>
-<p>Maybe you have used the <code>&lt;echo&gt;</code> task in a way like <tt>&lt;echo&gt;Hello World&lt;/echo&gt;</tt>.
-For that you have to provide a <tt>public void addText(String text)</tt> method.</p>
-<pre class="code">
+<h2 id="NestedText">Nested Text</h2>
+<p>Maybe you have used the <code>&lt;echo&gt;</code> task in a way like <code>&lt;echo&gt;Hello
+World&lt;/echo&gt;</code>.  For that you have to provide a <code class="code">public void addText(String text)</code>
+method.</p>
+<pre>
 ...
 public class HelloWorld extends Task {
     private String message;
@@ -318,46 +291,42 @@
         message = text;
     }
     ...
-}
-</pre>
-<p>But here properties are <b>not</b> resolved! For resolving properties we have to use
-Project's <tt>replaceProperties(String propname) : String</tt> method which takes the
-property name as argument and returns its value (or ${propname} if not set).</p>
-<p>Thus, to replace properties in the nested node text, our method <code>addText()</code> can be written as:</p>
-<pre class="code">
+}</pre>
+<p>But here properties are <strong>not</strong> resolved! For resolving properties we have to use
+Project's <code class="code">replaceProperties(String propname)</code> method which takes the property name as argument
+and returns its value (or <code>${propname}</code> if not set).</p>
+<p>Thus, to replace properties in the nested node text, our method <code class="code">addText()</code> can be written
+as:</p>
+<pre>
     public void addText(String text) {
         message = getProject().replaceProperties(text);
-    }
-</pre>
+    }</pre>
 
-
-<a name="NestedElements"></a>
-<h2>Nested Elements</h2>
+<h2 id="NestedElements">Nested Elements</h2>
 <p>There are several ways for inserting the ability of handling nested elements. See
-the <a href="http://ant.apache.org/manual/develop.html#nested-elements">Manual [4]</a> for other.
-We use the first way of the three described ways. There are several steps for that:</p><ol>
-<li>We create a class for collecting all the info the nested element should contain.
-  This class is created by the same rules for attributes and nested elements
-  as for the task (<code>set&lt;attributename&gt;</code>() methods). </li>
+the <a href="develop.html#nested-elements">Manual [4]</a> for other.  We use the first way of the three described
+ways. There are several steps for that:</p>
+<ol>
+<li>We create a class for collecting all the info the nested element should contain.  This class is created by the same
+rules for attributes and nested elements as for the task (<code class="code">set<i>Attributename</i>()</code>
+methods).</li>
 <li>The task holds multiple instances of this class in a list.</li>
-<li>A factory method instantiates an object, saves the reference in the list
-  and returns it to Ant Core.</li>
-<li>The execute() method iterates over the list and evaluates its values.</li>
+<li>A factory method instantiates an object, saves the reference in the list and returns it to Ant Core.</li>
+<li>The <code class="code">execute()</code> method iterates over the list and evaluates its values.</li>
 </ol>
-<pre class="code">
-import java.util.Vector;
-import java.util.Iterator;
+<pre>
+import java.util.ArrayList;
+import java.util.List;
 ...
     public void execute() {
-        if (message!=null) log(message);
-        for (Iterator it=messages.iterator(); it.hasNext(); ) {      <b>// 4</b>
-            Message msg = (Message)it.next();
+        if (message != null) log(message);
+        for (Message msg : messages) {      <b>// 4</b>
             log(msg.getMsg());
         }
     }
 
 
-    Vector messages = new Vector();                                  <b>// 2</b>
+    List&lt;Message&gt; messages = new ArrayList&lt;&gt;();                      <b>// 2</b>
 
     public Message createMessage() {                                 <b>// 3</b>
         Message msg = new Message();
@@ -372,26 +341,22 @@
         public void setMsg(String msg) { this.msg = msg; }
         public String getMsg() { return msg; }
     }
-...
-</pre>
-<p>Then we can use the new nested element. But where is xml-name for that defined?
-The mapping XML-name : classname is defined in the factory method:
-<tt>public <i>classname</i> create<i>XML-name</i>()</tt>. Therefore we write in
-the buildfile</p>
-<pre class="code">
+...</pre>
+<p>Then we can use the new nested element. But where is XML-name for that defined?  The mapping XML-name &rarr;
+classname is defined in the factory method: <code class="code">public <i>classname</i>
+create<i>XML-name</i>()</code>. Therefore we write in the buildfile</p>
+<pre>
         &lt;helloworld&gt;
             &lt;message msg="Nested Element 1"/&gt;
             &lt;message msg="Nested Element 2"/&gt;
-        &lt;/helloworld&gt;
-</pre>
-<p>Note that if you choose to use methods 2 or 3, the class that represents the nested
-element must be declared as <code>static</code></p>
+        &lt;/helloworld&gt;</pre>
+<p>Note that if you choose to use methods 2 or 3, the class that represents the nested element must be declared
+as <code>static</code></p>
 
-<a name="complex"></a>
-<h2>Our task in a little more complex version</h2>
+<h2 id="complex">Our task in a little more complex version</h2>
 <p>For recapitulation now a little refactored buildfile:</p>
-<pre class="code">
-&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;project name="MyTask" basedir="." default="use"&gt;
 
     &lt;property name="src.dir" value="src"/&gt;
@@ -457,18 +422,15 @@
 
     &lt;target name="use"
             description="Try all (w/out use.fail)"
-            depends="use.without,use.message,use.nestedText,use.nestedElement"
-    /&gt;
+            depends="use.without,use.message,use.nestedText,use.nestedElement"/&gt;
 
-&lt;/project&gt;
-</pre>
-
-And the code of the task:
-<pre class="code">
+&lt;/project&gt;</pre>
+<p>And the code of the task:</p>
+<pre>
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.BuildException;
-import java.util.Vector;
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * The task of the tutorial.
@@ -502,18 +464,17 @@
         if (fail) throw new BuildException("Fail requested.");
 
         // handle attribute 'message' and nested text
-        if (message!=null) log(message);
+        if (message != null) log(message);
 
         // handle nested elements
-        for (Iterator it=messages.iterator(); it.hasNext(); ) {
-            Message msg = (Message)it.next();
+        for (Message msg : messages) {
             log(msg.getMsg());
         }
     }
 
 
     /** Store nested 'message's. */
-    Vector messages = new Vector();
+    List&lt;Message&gt; messages = new ArrayList&lt;&gt;();
 
     /** Factory method for creating nested 'message's. */
     public Message createMessage() {
@@ -533,10 +494,8 @@
         public String getMsg() { return msg; }
     }
 
-}
-</pre>
-
-And it works:
+}</pre>
+<p>And it works:</p>
 <pre class="output">
 C:\tmp\anttests\MyFirstTask&gt;ant
 Buildfile: build.xml
@@ -585,36 +544,26 @@
 C:\tmp\anttests\MyFirstTask\build.xml:36: Fail requested.
 
 Total time: 1 second
-C:\tmp\anttests\MyFirstTask&gt;
-</pre>
-Next step: test ...
+C:\tmp\anttests\MyFirstTask&gt;</pre>
+<p>Next step: test ...</p>
 
+<h2 id="TestingTasks">Test the Task</h2>
+<p>We have written a test already: the <q>use.*</q> targets in the buildfile. But it's difficult to test that
+automatically. Commonly (and in Ant) JUnit is used for that. For testing tasks Ant provides a JUnit
+Rule <code class="code">org.apache.tools.ant.BuildFileRule</code>.  This class provides some for testing tasks useful
+methods: initialize Ant, load a buildfile, execute targets, capture debug and run logs ...</p>
 
-
-<a name="TestingTasks"></a>
-<h2>Test the Task</h2>
-<p>We have written a test already: the use.* tasks in the buildfile. But its
-difficult to test that automatically. Common (and in Ant) used is JUnit for
-that. For testing tasks Ant provides a JUnit Rule <tt>org.apache.tools.ant.BuildFileRule</tt>.
-This class provides some for testing tasks useful methods:
-initialize Ant, load a buildfile, execute targets, capturing debug and run logs ...</p>
-
-<p>In Ant it is usual that the testcase has the same name as the task with a prepending
-<i>Test</i>, therefore we will create a file <i>HelloWorldTest.java</i>. Because we
-have a very small project we can put this file into <i>src</i> directory (Ant's own
-testclasses are in /src/testcases/...). Because we have already written our tests
-for "hand-test" we can use that for automatic tests, too. But there is one little
-problem we have to solve: all test supporting classes are not part of the binary
-distribution of Ant. So you can build the special jar file from source distro with
-target "test-jar" or you can download a nightly build from
-<a href="http://gump.covalent.net/jars/latest/ant/ant-testutil.jar">
-http://gump.covalent.net/jars/latest/ant/ant-testutil.jar [5]</a>.</p>
+<p>In Ant it is usual that the testcase has the same name as the task with a prepended <code>Test</code>, therefore we
+will create a file <samp>HelloWorldTest.java</samp>. Because we have a very small project we can put this file
+into <samp>src</samp> directory (Ant's own testclasses are in <samp>/src/testcases/...</samp>). Because we have already
+written our tests for "hand-test" we can use that for automatic tests, too. All test supporting classes are a part of
+the binary distribution of Ant <em>since Ant 1.7.0</em> in form of <samp>ant-testutil.jar</samp>. You can also build the
+jar file from source distro with target "test-jar".
 
 <p>For executing the test and creating a report we need the optional tasks <code>&lt;junit&gt;</code>
 and <code>&lt;junitreport&gt;</code>. So we add to the buildfile:</p>
-<pre class="code">
-...
-<font color="#9F9F9F">&lt;project name="MyTask" basedir="." </font>default="test"<font color="#9F9F9F">&gt;</font>
+<pre>
+<span style="color:gray">&lt;project name="MyTask" basedir="." </span>default="test"<span style="color:gray">&gt;</span>
 ...
     &lt;property name="ant.test.lib" value="ant-testutil.jar"/&gt;
     &lt;property name="report.dir"   value="report"/&gt;
@@ -639,10 +588,10 @@
         &lt;/delete&gt;
     &lt;/target&gt;
 
-    <font color="#9F9F9F">&lt;target name="compile" description="Compiles the Task"&gt;
+    <span style="color:gray">&lt;target name="compile" description="Compiles Vector the Task"&gt;
         &lt;mkdir dir="${classes.dir}"/&gt;
-        &lt;javac srcdir="${src.dir}" destdir="${classes.dir}" </font>classpath="${ant.test.lib}"<font color="#9F9F9F">/&gt;
-    &lt;/target&gt;</font>
+        &lt;javac srcdir="${src.dir}" destdir="${classes.dir}" </span>classpath="${ant.test.lib}"<span style="color:gray">/&gt;
+    &lt;/target&gt;</span>
 ...
     &lt;target name="junit" description="Runs the unit tests" depends="jar"&gt;
         &lt;delete dir="${junit.out.dir.xml}"/&gt;
@@ -668,17 +617,16 @@
 
     &lt;target name="test"
             depends="junit,junitreport"
-            description="Runs unit tests and creates a report"
-    /&gt;
+            description="Runs unit tests and creates a report"/&gt;
 ...
-</pre>
+<span style="color:gray">&lt;/project&gt;</span></pre>
 
-<p>Back to the <i>src/HelloWorldTest.java</i>. We create a class with a public
-<i>BuildFileRule</i> field annotated with JUnit's <i>@Rule</i> annotation. As per
-conventional JUnit4 tests, this class should have no constructors, or a default no-args
-constructor, setup methods should be annotated with <i>@Before</i>, tear down methods
-annotated with <i>@After</i> and any test method annotated with <i>@Test</i>.
-<pre class="code">
+<p>Back to the <samp>src/HelloWorldTest.java</samp>. We create a class with a
+public <code class="code">BuildFileRule</code> field annotated with JUnit's <code class="code">@Rule</code>
+annotation. As per conventional JUnit4 tests, this class should have no constructors, nor a default no-args constructor,
+setup methods should be annotated with <code class="code">@Before</code>, tear down methods annotated
+with <code class="code">@After</code> and any test method annotated with <code class="code">@Test</code>.
+<pre>
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Assert;
 import org.junit.Test;
@@ -736,11 +684,9 @@
         AntAssert.assertContains("Nested Element 1", buildRule.getLog());
         AntAssert.assertContains("Nested Element 2", buildRule.getLog());
     }
-}
-</pre>
+}</pre>
 
-<p>When starting <tt>ant</tt> we'll get a short message to STDOUT and
-a nice HTML-report.</p>
+<p>When starting <kbd>ant</kbd> we'll get a short message to STDOUT and a nice HTML report.</p>
 <pre class="output">
 C:\tmp\anttests\MyFirstTask&gt;ant
 Buildfile: build.xml
@@ -768,30 +714,29 @@
 
 BUILD SUCCESSFUL
 Total time: 7 seconds
-C:\tmp\anttests\MyFirstTask&gt;
-</pre>
+C:\tmp\anttests\MyFirstTask&gt;</pre>
 
+<h2 id="Debugging">Debugging</h2>
 
-<a name="Debugging"></a>
-<h2>Debugging</h2>
-
-<p>Try running Ant with the flag <code>-verbose</code>.  For more information, try flag <code>-debug</code>.</p>
-<p>For deeper issues, you may need to run the custom task code in a Java debugger.  First, get the source for Ant and build it with debugging information.</p>
-<p>Since Ant is a large project, it can be a little tricky to set the right breakpoints.  Here are two important breakpoints for version 1.8:</p>
+<p>Try running Ant with the flag <kbd>-verbose</kbd>.  For more information, try flag <kbd>-debug</kbd>.</p>
+<p>For deeper issues, you may need to run the custom task code in a Java debugger.  First, get the source for Ant and
+build it with debugging information.</p>
+<p>Since Ant is a large project, it can be a little tricky to set the right breakpoints.  Here are two important
+breakpoints for version 1.8:</p>
 <ul>
-  <li>Initial <code>main()</code> function: <code>com.apache.tools.ant.launch.Launcher.main()</code></li>
-  <li>Task entry point: <code>com.apache.tools.ant.UnknownElement.execute()</code></li>
+  <li>Initial <code class="code">main()</code>
+  function: <code class="code">com.apache.tools.ant.launch.Launcher.main()</code></li>
+  <li>Task entry point: <code class="code">com.apache.tools.ant.UnknownElement.execute()</code></li>
 </ul>
 
-<p>If you need to debug when a task attribute or the text is set, begin by debugging into method <code>execute()</code> of your custom task.  Then set breakpoints in other methods.  This will ensure the class byte-code has been loaded by the Java VM.</p>
+<p>If you need to debug when a task attribute or the text is set, begin by debugging into
+method <code class="code">execute()</code> of your custom task.  Then set breakpoints in other methods.  This will
+ensure the class bytecode has been loaded by JVM.</p>
 
-
-
-<a name="resources"></a>
-<h2>Resources</h2>
-<p>This tutorial and its resources are available via
-<a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22570">BugZilla [6]</a>.
-The ZIP provided there contains</p><ul>
+<h2 id="resources">Resources</h2>
+<p>This tutorial and its resources are available via <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=22570"
+target="_top">BugZilla [5]</a>.  The ZIP provided there contains</p>
+<ul>
 <li>this initial version of this tutorial</li>
 <li>the buildfile (last version)</li>
 <li>the source of the task (last version)</li>
@@ -801,19 +746,19 @@
 <li>generated jar</li>
 <li>generated reports</li>
 </ul>
-<p>The last sources and the buildfile are also available
-<a href="tutorial-writing-tasks-src.zip">here [7]</a> inside the manual.
-</p>
+<p>The last sources and the buildfile are also available <a href="tutorial-writing-tasks-src.zip">here [6]</a> inside
+the manual.</p>
 
-<p>Used Links:<br />
-&nbsp;&nbsp;[1] <a href="http://ant.apache.org/manual/properties.html#built-in-props">http://ant.apache.org/manual/properties.html#built-in-props</a><br />
-&nbsp;&nbsp;[2] <a href="http://ant.apache.org/manual/Tasks/taskdef.html">http://ant.apache.org/manual/Tasks/taskdef.html</a><br />
-&nbsp;&nbsp;[3] <a href="http://ant.apache.org/manual/develop.html#set-magic">http://ant.apache.org/manual/develop.html#set-magic</a><br />
-&nbsp;&nbsp;[4] <a href="http://ant.apache.org/manual/develop.html#nested-elements">http://ant.apache.org/manual/develop.html#nested-elements</a><br />
-&nbsp;&nbsp;[5] <a href="http://gump.covalent.net/jars/latest/ant/ant-testutil.jar">http://gump.covalent.net/jars/latest/ant/ant-testutil.jar</a><br />
-&nbsp;&nbsp;[6] <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22570">http://issues.apache.org/bugzilla/show_bug.cgi?id=22570</a><br />
-&nbsp;&nbsp;[7] <a href="tutorial-writing-tasks-src.zip">tutorial-writing-tasks-src.zip</a><br />
-</p>
+<p>Used Links:</p>
+<ol class="refs">
+<li><a href="properties.html#built-in-props">https://ant.apache.org/manual/properties.html#built-in-props</a></li>
+<li><a href="Tasks/taskdef.html">https://ant.apache.org/manual/Tasks/taskdef.html</a></li>
+<li><a href="develop.html#set-magic">https://ant.apache.org/manual/develop.html#set-magic</a></li>
+<li><a href="develop.html#nested-elements">https://ant.apache.org/manual/develop.html#nested-elements</a></li>
+<li><a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=22570"
+       target="_top">https://issues.apache.org/bugzilla/show_bug.cgi?id=22570</a></li>
+<li><a href="tutorial-writing-tasks-src.zip">tutorial-writing-tasks-src.zip</a></li>
+</ol>
 
 </body>
 </html>
diff --git a/manual/tutorials.html b/manual/tutorials.html
index 5720473..cbfdaff 100644
--- a/manual/tutorials.html
+++ b/manual/tutorials.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Tutorials</title>
 <base target="mainFrame"/>
@@ -30,16 +30,14 @@
 <h3>Tutorials</h3>
 
 <p><a href="tutorial-HelloWorldWithAnt.html">Hello World with Apache Ant</a><br/>
-A step by step tutorial for starting java programming with Ant.</p>
+A step by step tutorial for starting Java programming with Ant.</p>
 
 <p><a href="tutorial-writing-tasks.html">Writing Tasks</a><br/>
 A step by step tutorial for writing tasks.</p>
 
 <p><a href="tutorial-tasks-filesets-properties.html">Tasks using Properties, Filesets &amp; Paths</a><br/>
-How to get and set properties and how to use nested filesets and paths 
+How to get and set properties and how to use nested filesets and paths
 while writing tasks. Finally it explains how to contribute tasks to Ant.</p>
 
-
-
 </body>
 </html>
diff --git a/manual/using.html b/manual/using.html
index 5a3c06c..7203e51 100644
--- a/manual/using.html
+++ b/manual/using.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,156 +15,125 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
 <title>Writing a Simple Buildfile</title>
 </head>
 
 <body>
 <h1>Using Apache Ant</h1>
-<h2><a name="buildfile">Writing a Simple Buildfile</a></h2>
-<p>Apache Ant's buildfiles are written in XML. Each buildfile contains one project
-and at least one (default) target. Targets contain task elements.
-Each task element of the buildfile can have an <code>id</code> attribute and
-can later be referred to by the value supplied to this. The value has
-to be unique. (For additional information, see the
-<a href="#tasks"> Tasks</a> section below.)</p>
-<h3><a name="projects">Projects</a></h3>
-<p>A <i>project</i> has three attributes:</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h2 id="buildfile">Writing a Simple Buildfile</h2>
+<p>Apache Ant's buildfiles are written in XML. Each buildfile contains one project and at least one (default)
+target. Targets contain task elements.  Each task element of the buildfile can have an <var>id</var> attribute and can
+later be referred to by the value supplied to this. The value has to be unique. (For additional information, see
+the <a href="#tasks">Tasks</a> section below.)</p>
+
+<h3 id="projects">Projects</h3>
+<p>A <em>project</em> has three attributes:</p>
+<table class="attr">
   <tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
   </tr>
   <tr>
-    <td valign="top">name</td>
-    <td valign="top">the name of the project.</td>
-    <td align="center" valign="top">No</td>
+    <td>name</td>
+    <td>the name of the project.</td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">default</td>
-    <td valign="top">the default target to use when no target is supplied.</td>
-    <td align="center" valign="top">No; however, <b>since Ant 1.6.0</b>,
-        every project includes an implicit target that contains any and
-        all top-level tasks and/or types. This target will always be
-        executed as part of the project's initialization, even when Ant is
-        run with the <a href="running.html#options">-projecthelp</a> option.
+    <td>default</td>
+    <td>the default target to use when no target is supplied.</td>
+    <td>No; however, <em>since Ant 1.6.0</em>, every project includes an implicit target that contains any and all
+      top-level tasks and/or types. This target will always be executed as part of the project's initialization, even
+      when Ant is run with the <a href="running.html#options"><kbd>-projecthelp</kbd></a> option.
     </td>
   </tr>
   <tr>
-    <td valign="top">basedir</td>
-    <td valign="top">the base directory from which all path calculations are
-      done. This attribute might be overridden by setting
-      the &quot;basedir&quot;
-      property beforehand. When this is done, it must be omitted in the
-      project tag. If neither the attribute nor the property have
-      been set, the parent directory of the buildfile will be used.<br/>
-      A relative path is resolved relative to the directory containing
-      the build file.
+    <td>basedir</td>
+    <td>the base directory from which all path calculations are done. A relative path is resolved relative to the
+      directory containing the buildfile.
     </td>
-    <td align="center" valign="top">No</td>
+    <td>No; defaults to the parent directory of the buildfile, unless overridden by the project's <var>basedir</var> or
+      the <code>basedir</code> property</td>
   </tr>
 </table>
-<p>Optionally, a description for the project can be provided as a
-top-level <code>&lt;description&gt;</code> element (see the <a
-href="Types/description.html">description</a> type).</p>
+<p>Optionally, a description for the project can be provided as a top-level <code>&lt;description&gt;</code> element
+(see the <a href="Types/description.html">description</a> type).</p>
 
-<p>Each project defines one or more <i>targets</i>.
-A target is a set of <i>tasks</i> you want
-to be executed. When starting Ant, you can select which target(s) you
-want to have executed. When no target is given,
-the project's default is used.</p>
+<p>Each project defines one or more <em>targets</em>.  A target is a set of <em>tasks</em> you want to be executed. When
+starting Ant, you can select which target(s) you want to have executed. When no target is given, the
+project's <var>default</var> is used.</p>
 
-<h3><a name="targets">Targets</a></h3>
-<p>A target can depend on other targets. You might have a target for compiling,
-for example, and a target for creating a distributable. You can only build a
-distributable when you have compiled first, so the distribute target
-<i>depends on</i> the compile target. Ant resolves these dependencies.</p>
-<p>It should be noted, however, that Ant's <code>depends</code> attribute
-only specifies the <i>order</i> in which targets should be executed - it
-does not affect whether the target that specifies the dependency(s) gets
-executed if the dependent target(s) did not (need to) run.
-</p>
+<h3 id="targets">Targets</h3>
+<p>A target can depend on other targets. You might have a target for compiling, for example, and a target for creating a
+distributable. You can only build a distributable when you have compiled first, so the <q>distribute</q>
+target <em>depends on</em> the <q>compile</q> target. Ant resolves these dependencies.</p>
+<p>It should be noted, however, that Ant's <var>depends</var> attribute only specifies the <em>order</em> in which
+targets should be executed&mdash;it does not affect whether the target that specifies the dependency(s) gets executed if
+the dependent target(s) did not (need to) run.</p>
 
-<p>More information can be found in the
-  dedicated <a href="targets.html">manual page</a>.</p>
+<p>More information can be found in the dedicated <a href="targets.html">manual page</a>.</p>
 
-<h3><a name="tasks">Tasks</a></h3>
+<h3 id="tasks">Tasks</h3>
 <p>A task is a piece of code that can be executed.</p>
-<p>A task can have multiple attributes (or arguments, if you prefer). The value
-of an attribute might contain references to a property. These references will be
-resolved before the task is executed.</p>
+<p>A task can have multiple attributes (or arguments, if you prefer). The value of an attribute might contain references
+to a property. These references will be resolved before the task is executed.</p>
 <p>Tasks have a common structure:</p>
-<blockquote>
-  <pre>&lt;<i>name</i> <i>attribute1</i>=&quot;<i>value1</i>&quot; <i>attribute2</i>=&quot;<i>value2</i>&quot; ... /&gt;</pre>
-</blockquote>
-<p>where <i>name</i> is the name of the task,
-<i>attributeN</i> is the attribute name, and
-<i>valueN</i> is the value for this attribute.</p>
-<p>There is a set of <a href="tasklist.html" target="navFrame">built-in tasks</a>, but it is also very
-easy to <a href="develop.html#writingowntask">write your own</a>.</p>
-<p>All tasks share a task name attribute. The value of
-this attribute will be used in the logging messages generated by
-Ant.</p>
-Tasks can be assigned an <code>id</code> attribute:
-<blockquote>
-<pre>&lt;<i>taskname</i> id="<i>taskID</i>" ... /&gt;</pre>
-</blockquote>
-where <i>taskname</i> is the name of the task, and <i>taskID</i> is
-a unique identifier for this task.
-You can refer to the
-corresponding task object in scripts or other tasks via this name.
-For example, in scripts you could do:
-<blockquote>
+
+<pre>&lt;<i>name</i> <var>attribute1</var>=&quot;<i>value1</i>&quot; <var>attribute2</var>=&quot;<i>value2</i>&quot; ... /&gt;</pre>
+
+<p>where <code><i>name</i></code> is the name of the task, <var>attributeN</var> is the attribute name,
+and <code><i>valueN</i></code> is the value for this attribute.</p>
+<p>There is a set of <a href="tasklist.html" target="navFrame">built-in tasks</a>, but it is also very easy
+to <a href="develop.html#writingowntask">write your own</a>.</p>
+<p>All tasks can have a <var>name</var> attribute. The value of this attribute will be used in the logging messages
+generated by Ant.</p>
+<p>Tasks can be assigned an <var>id</var> attribute:</p>
+
+<pre>&lt;<i>taskname</i> <var>id</var>="<i>taskID</i>" ... /&gt;</pre>
+
+<p>where <code><i>taskname</i></code> is the name of the task, and <code><i>taskID</i></code> is a unique identifier for
+this task.  You can refer to the corresponding task object in scripts or other tasks via this name.  For example, in
+scripts you could do:</p>
+
 <pre>
 &lt;script ... &gt;
   task1.setFoo("bar");
-&lt;/script&gt;
-</pre>
-</blockquote>
-to set the <code>foo</code> attribute of this particular task instance.
-In another task (written in Java), you can access the instance via
-<code>project.getReference("task1")</code>.
-<p>
-Note<sup>1</sup>: If &quot;task1&quot; has not been run yet, then
-it has not been configured (ie., no attributes have been set), and if it is
-going to be configured later, anything you've done to the instance may
-be overwritten.
-</p>
-<p>
-Note<sup>2</sup>: Future versions of Ant will most likely <i>not</i>
-be backward-compatible with this behaviour, since there will likely be no
-task instances at all, only proxies.
-</p>
+&lt;/script&gt;</pre>
+<p>to set the <code>foo</code> attribute of this particular task instance.  In another task (written in Java), you can
+access the instance via <code class="code">project.getReference("task1")</code>.</p>
+<p>Note 1: If <q>task1</q> has not been run yet, then it has not been configured (ie., no attributes have been set), and
+if it is going to be configured later, anything you've done to the instance may be overwritten.</p>
+<p>Note 2: Future versions of Ant will most likely <em>not</em> be backward-compatible with this behaviour, since there
+will likely be no task instances at all, only proxies.</p>
 
-<h3><a name="properties">Properties</a></h3>
+<h3 id="properties">Properties</h3>
 
 <p>Properties are an important way to customize a build process or
   to just provide shortcuts for strings that are used repeatedly
-  inside a build file.</p>
+  inside a buildfile.</p>
 
-<p>In its most simple form properties are defined in the build file
+<p>In its most simple form properties are defined in the buildfile
   (for example by the <a href="Tasks/property.html">property</a>
   task) or might be set outside Ant.  A property has a name and a
   value; the name is case-sensitive. Properties may be used in the
   value of task attributes or in the nested text of tasks that support
   them.  This is done by placing the property name between
-  &quot;<code>${</code>&quot; and &quot;<code>}</code>&quot; in the
-  attribute value. For example, if there is a &quot;builddir&quot;
-  property with the value &quot;build&quot;, then this could be used
-  in an attribute like this: <code>${builddir}/classes</code>.  This
-  is resolved at run-time as <code>build/classes</code>.</p>
+  <q>${</q> and <q>}</q> in the
+  attribute value. For example, if there is a <code>builddir</code>
+  property with the value <q>build</q>, then this could be used
+  in an attribute like this: <samp>${builddir}/classes</samp>.  This
+  is resolved at run-time as <samp>build/classes</samp>.</p>
 
-<p>With Ant 1.8.0 property expansion has become much more powerful
+<p><em>Since Ant 1.8.0</em>, property expansion has become much more powerful
   than simple key value pairs, more details can be
   found <a href="properties.html">in the concepts section</a> of this
   manual.</p>
 
-<h3><a name="example">Example Buildfile</a></h3>
+<h3 id="example">Example Buildfile</h3>
 <pre>
 &lt;project name=&quot;MyProject&quot; default=&quot;dist&quot; basedir=&quot;.&quot;&gt;
   &lt;description&gt;
@@ -183,7 +153,7 @@
 
   &lt;target name=&quot;compile&quot; depends=&quot;init&quot;
         description=&quot;compile the source&quot;&gt;
-    &lt;!-- Compile the java code from ${src} into ${build} --&gt;
+    &lt;!-- Compile the Java code from ${src} into ${build} --&gt;
     &lt;javac srcdir=&quot;${src}&quot; destdir=&quot;${build}&quot;/&gt;
   &lt;/target&gt;
 
@@ -202,268 +172,199 @@
     &lt;delete dir=&quot;${build}&quot;/&gt;
     &lt;delete dir=&quot;${dist}&quot;/&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre>
+&lt;/project&gt;</pre>
 
-<p>Notice that we are declaring properties outside any target.  As of
-Ant 1.6 all tasks can be declared outside targets (earlier version
-only allowed <tt>&lt;property&gt;</tt>,<tt>&lt;typedef&gt;</tt> and
-<tt>&lt;taskdef&gt;</tt>).  When you do this they are evaluated before
-any targets are executed.  Some tasks will generate build failures if
-they are used outside of targets as they may cause infinite loops
-otherwise (<code>&lt;antcall&gt;</code> for example).</p>
+<p>Notice that we are declaring properties outside any target. <em>Since Ant 1.6</em>, all tasks can be declared outside
+targets (earlier version only allowed <code>&lt;property&gt;</code>, <code>&lt;typedef&gt;</code>
+and <code>&lt;taskdef&gt;</code>).  When you do this they are evaluated before any targets are executed.  Some tasks
+will generate build failures if they are used outside of targets as they may cause infinite loops otherwise
+(<code>&lt;antcall&gt;</code> for example).</p>
 
-<p>
-We have given some targets descriptions; this causes the <tt>projecthelp</tt>
-invocation option to list them as public targets with the descriptions; the
-other target is internal and not listed.
-<p>
-Finally, for this target to work the source in the <tt>src</tt> subdirectory
-should be stored in a directory tree which matches the package names. Check the
-<tt>&lt;javac&gt;</tt> task for details.
+<p>We have given some targets descriptions; this causes the <kbd>-projecthelp</kbd> invocation option to list them as
+public targets with the descriptions; the other target is internal and not listed.</p>
+<p>Finally, for this target to work the source in the <samp>src</samp> subdirectory should be stored in a directory tree
+which matches the package names. Check the <code>&lt;javac&gt;</code> task for details.</p>
 
-<h3><a name="filters">Token Filters</a></h3>
-<p>A project can have a set of tokens that might be automatically expanded if
-found when a file is copied, when the filtering-copy behavior is selected in the
-tasks that support this. These might be set in the buildfile
-by the <a href="Tasks/filter.html">filter</a> task.</p>
-<p>Since this can potentially be a very harmful behavior,
-the tokens in the files <b>must</b>
-be of the form <code>@</code><i>token</i><code>@</code>, where
-<i>token</i> is the token name that is set
-in the <code>&lt;filter&gt;</code> task. This token syntax matches the syntax of other build systems
-that perform such filtering and remains sufficiently orthogonal to most
-programming and scripting languages, as well as with documentation systems.</p>
-<p>Note: If a token with the format <code>@</code><i>token</i><code>@</code>
-is found in a file, but no
-filter is associated with that token, no changes take place;
-therefore, no escaping
-method is available - but as long as you choose appropriate names for your
-tokens, this should not cause problems.</p>
-<p><b>Warning:</b> If you copy binary files with filtering turned on, you can corrupt the
-files. This feature should be used with text files <em>only</em>.</p>
+<h3 id="filters">Token Filters</h3>
+<p>A project can have a set of tokens that might be automatically expanded if found when a file is copied, when the
+filtering-copy behavior is selected in the tasks that support this. These might be set in the buildfile by
+the <a href="Tasks/filter.html">filter</a> task.</p>
+<p>Since this can potentially be a very harmful behavior, the tokens in the files <strong>must</strong> be of the
+form <code>@<var>token</var>@</code>, where <var>token</var> is the token name that is set in
+the <code>&lt;filter&gt;</code> task. This token syntax matches the syntax of other build systems that perform such
+filtering and remains sufficiently orthogonal to most programming and scripting languages, as well as with documentation
+systems.</p>
+<p><strong>Note</strong>: If a token with the format <code>@<var>token</var>@</code> is found in a file, but no filter
+is associated with that token, no changes take place; therefore, no escaping method is available&mdash;but as long as
+you choose appropriate names for your tokens, this should not cause problems.</p>
+<p><strong>Warning</strong>: If you copy binary files with filtering turned on, you can corrupt the files. This feature
+should be used with text files <em>only</em>.</p>
 
-<h3><a name="path">Path-like Structures</a></h3>
-<p>You can specify <code>PATH</code>- and <code>CLASSPATH</code>-type
-references using both
-&quot;<code>:</code>&quot; and &quot;<code>;</code>&quot; as separator
-characters. Ant will
-convert the separator to the correct character of the current operating
-system.</p>
-<p>Wherever path-like values need to be specified, a nested element can
-be used. This takes the general form of:</p>
+<h3 id="path">Path-like Structures</h3>
+<p>You can specify <code>PATH</code>- and <code>CLASSPATH</code>-type references using both <q>:</q> and <q>;</q> as
+separator characters. Ant will convert the separator to the correct character of the current operating system.</p>
+<p>Wherever path-like values need to be specified, a nested element can be used. This takes the general form of:</p>
 <pre>
-    &lt;classpath&gt;
-      &lt;pathelement path=&quot;${classpath}&quot;/&gt;
-      &lt;pathelement location=&quot;lib/helper.jar&quot;/&gt;
-    &lt;/classpath&gt;
-</pre>
-<p>The <code>location</code> attribute specifies a single file or
-directory relative to the project's base directory (or an absolute
-filename), while the <code>path</code> attribute accepts colon-
-or semicolon-separated lists of locations. The <code>path</code>
-attribute is intended to be used with predefined paths - in any other
-case, multiple elements with <code>location</code> attributes should be
-preferred.</p>
-<p><em>Since Ant 1.8.2</em> the location attribute can also contain a
-  wildcard in its last path component (i.e. it can end in a
-  &quot;*&quot;) in order to support wildcard CLASSPATHs introduced
-  with Java6.  Ant will not expand or evaluate the wildcards and the
-  resulting path may not work as anything else but a CLASSPATH - or
-  even as a CLASSPATH for a Java VM prior to Java6.</p>
+&lt;classpath&gt;
+  &lt;pathelement path=&quot;${classpath}&quot;/&gt;
+  &lt;pathelement location=&quot;lib/helper.jar&quot;/&gt;
+&lt;/classpath&gt;</pre>
+<p>The <var>location</var> attribute specifies a single file or directory relative to the project's base directory (or
+an absolute filename), while the <var>path</var> attribute accepts colon- or semicolon-separated lists of
+locations. The <var>path</var> attribute is intended to be used with predefined paths&mdash;in any other case, multiple
+elements with <var>location</var> attributes should be preferred.</p>
+<p><em>Since Ant 1.8.2</em> the <var>location</var> attribute can also contain a wildcard in its last path component
+(i.e. it can end in a <q>*</q>) in order to support wildcard <code>CLASSPATH</code>s introduced with Java 6.  Ant will
+not expand or evaluate the wildcards and the resulting path may not work as anything else but
+a <code>CLASSPATH</code>&mdash;or even as a <code>CLASSPATH</code> for JVM prior to Java 6.</p>
 <p>As a shortcut, the <code>&lt;classpath&gt;</code> tag
-supports <code>path</code> and
-<code>location</code> attributes of its own, so:</p>
+supports <var>path</var> and
+<var>location</var> attributes of its own, so:</p>
 <pre>
-    &lt;classpath&gt;
-      &lt;pathelement path=&quot;${classpath}&quot;/&gt;
-    &lt;/classpath&gt;
+&lt;classpath&gt;
+  &lt;pathelement path=&quot;${classpath}&quot;/&gt;
+&lt;/classpath&gt;
 </pre>
 <p>can be abbreviated to:</p>
+<pre>&lt;classpath path=&quot;${classpath}&quot;/&gt;</pre>
+<p>In addition, one or more <a href="Types/resources.html#collection">resource collections</a> can be specified as
+nested elements (these must consist of <a href="Types/resources.html#file">file</a>-type resources only).  Additionally,
+it should be noted that although resource collections are processed in the order encountered, certain resource
+collection types such as <a href="Types/fileset.html">fileset</a>, <a href="Types/dirset.html">dirset</a>
+and <a href="Types/resources.html#files">files</a> are undefined in terms of order.</p>
 <pre>
-    &lt;classpath path=&quot;${classpath}&quot;/&gt;
-</pre>
-<p>In addition, one or more
-<a href="Types/resources.html#collection">Resource Collection</a>s
-can be specified as nested elements (these must consist of
-<a href="Types/resources.html#file">file</a>-type resources only).
-Additionally, it should be noted that although resource collections are
-processed in the order encountered, certain resource collection types
-such as <a href="Types/fileset.html">fileset</a>,
-<a href="Types/dirset.html">dirset</a> and
-<a href="Types/resources.html#files">files</a>
-are undefined in terms of order.</p>
-<pre>
-    &lt;classpath&gt;
-      &lt;pathelement path=&quot;${classpath}&quot;/&gt;
-      &lt;fileset dir=&quot;lib&quot;&gt;
-        &lt;include name=&quot;**/*.jar&quot;/&gt;
-      &lt;/fileset&gt;
-      &lt;pathelement location=&quot;classes&quot;/&gt;
-      &lt;dirset dir=&quot;${build.dir}&quot;&gt;
-        &lt;include name=&quot;apps/**/classes&quot;/&gt;
-        &lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
-      &lt;/dirset&gt;
-      &lt;filelist refid=&quot;third-party_jars&quot;/&gt;
-    &lt;/classpath&gt;
-</pre>
-<p>This builds a path that holds the value of <code>${classpath}</code>,
-followed by all jar files in the <code>lib</code> directory,
-the <code>classes</code> directory, all directories named
-<code>classes</code> under the <code>apps</code> subdirectory of
-<code>${build.dir}</code>, except those
-that have the text <code>Test</code> in their name, and
-the files specified in the referenced FileList.</p>
-<p>If you want to use the same path-like structure for several tasks,
-you can define them with a <code>&lt;path&gt;</code> element at the
-same level as <i>target</i>s, and reference them via their
-<i>id</i> attribute--see <a href="#references">References</a> for an
+&lt;classpath&gt;
+  &lt;pathelement path=&quot;${classpath}&quot;/&gt;
+  &lt;fileset dir=&quot;lib&quot;&gt;
+    &lt;include name=&quot;**/*.jar&quot;/&gt;
+  &lt;/fileset&gt;
+  &lt;pathelement location=&quot;classes&quot;/&gt;
+  &lt;dirset dir=&quot;${build.dir}&quot;&gt;
+    &lt;include name=&quot;apps/**/classes&quot;/&gt;
+    &lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;
+  &lt;/dirset&gt;
+  &lt;filelist refid=&quot;third-party_jars&quot;/&gt;
+&lt;/classpath&gt;</pre>
+<p>This builds a path that holds the value of <samp>${classpath}</samp>, followed by all jar files in
+the <samp>lib</samp> directory, the <samp>classes</samp> directory, all directories named <samp>classes</samp> under
+the <samp>apps</samp> subdirectory of <samp>${build.dir}</samp>, except those that have the text <code>Test</code> in
+their name, and the files specified in the referenced FileList.</p>
+<p>If you want to use the same path-like structure for several tasks, you can define them with
+a <code>&lt;path&gt;</code> element at the same level as <code>&lt;target&gt;</code>s, and reference them via their
+<var>id</var> attribute&mdash;see <a href="#references">References</a> for an
 example.</p>
 
-<p>By default a path like structure will re-evaluate all nested
-  resource collections whenever it is used, which may lead to
-  unnecessary re-scanning of the filesystem.  Since Ant 1.8.0 path has
-  an optional <i>cache</i> attribute, if it is set to true, the path
-  instance will only scan its nested resource collections once and
-  assume it doesn't change during the build anymore (the default
-  for <i>cache</i> still is <i>false</i>).  Even if you are using the
-  path only in a single task it may improve overall performance to set
-  <i>cache</i> to <i>true</i> if you are using complex nested
-  constructs.</p>
+<p>By default a path-like structure will re-evaluate all nested resource collections whenever it is used, which may lead
+to unnecessary re-scanning of the filesystem.  <em>Since Ant 1.8.0</em>, path has an optional <var>cache</var>
+attribute, if it is set to <q>true</q>, the path instance will only scan its nested resource collections once and assume
+it doesn't change during the build anymore (the default for <var>cache</var> still is <q>false</q>).  Even if you are
+using the path only in a single task it may improve overall performance to set <var>cache</var> to <q>true</q> if you
+are using complex nested constructs.</p>
 
-<p>A path-like structure can include a reference to another path-like
-structure (a path being itself a resource collection)
-via nested <code>&lt;path&gt;</code> elements:</p>
+<p>A path-like structure can include a reference to another path-like structure (a path being itself a resource
+collection) via nested <code>&lt;path&gt;</code> elements:</p>
 <pre>
-    &lt;path id=&quot;base.path&quot;&gt;
-      &lt;pathelement path=&quot;${classpath}&quot;/&gt;
-      &lt;fileset dir=&quot;lib&quot;&gt;
-        &lt;include name=&quot;**/*.jar&quot;/&gt;
-      &lt;/fileset&gt;
-      &lt;pathelement location=&quot;classes&quot;/&gt;
-    &lt;/path&gt;
+&lt;path id=&quot;base.path&quot;&gt;
+  &lt;pathelement path=&quot;${classpath}&quot;/&gt;
+  &lt;fileset dir=&quot;lib&quot;&gt;
+    &lt;include name=&quot;**/*.jar&quot;/&gt;
+  &lt;/fileset&gt;
+  &lt;pathelement location=&quot;classes&quot;/&gt;
+&lt;/path&gt;
 
-    &lt;path id=&quot;tests.path&quot; cache=&quot;true&quot;&gt;
-      &lt;path refid=&quot;base.path&quot;/&gt;
-      &lt;pathelement location=&quot;testclasses&quot;/&gt;
-    &lt;/path&gt;
-</pre>
- The shortcuts previously mentioned for <code>&lt;classpath&gt;</code> are also valid for <code>&lt;path&gt;</code>.For example:
+&lt;path id=&quot;tests.path&quot; cache=&quot;true&quot;&gt;
+  &lt;path refid=&quot;base.path&quot;/&gt;
+  &lt;pathelement location=&quot;testclasses&quot;/&gt;
+&lt;/path&gt;</pre>
+<p>The shortcuts previously mentioned for <code>&lt;classpath&gt;</code> are also valid
+for <code>&lt;path&gt;</code>. For example:</p>
 <pre>
-    &lt;path id=&quot;base.path&quot;&gt;
-      &lt;pathelement path=&quot;${classpath}&quot;/&gt;
-    &lt;/path&gt;
-</pre>
-can be written as:
+&lt;path id=&quot;base.path&quot;&gt;
+  &lt;pathelement path=&quot;${classpath}&quot;/&gt;
+&lt;/path&gt;</pre>
+<p>can be written as:</p>
+<pre>&lt;path id=&quot;base.path&quot; path=&quot;${classpath}&quot;/&gt;</pre>
+<h4 id="pathshortcut">Path Shortcut</h4>
+<p><em>Since Ant 1.6</em>, there is a shortcut for converting paths to OS specific strings in properties. One can use
+the expression <samp>${toString:<em>pathreference</em>}</samp> to convert a path element reference to a string that can
+be used for a path argument. For example:</p>
 <pre>
-    &lt;path id=&quot;base.path&quot; path=&quot;${classpath}&quot;/&gt;
-</pre>
+&lt;path id="lib.path.ref"&gt;
+  &lt;fileset dir="lib" includes="*.jar"/&gt;
+&lt;/path&gt;
+&lt;javac srcdir="src" destdir="classes"&gt;
+  &lt;compilerarg arg="-Xbootclasspath/p:${toString:lib.path.ref}"/&gt;
+&lt;/javac&gt;</pre>
 
-  <h4><a name="pathshortcut">Path Shortcut</a></h4>
-  <p>
-    In Ant 1.6 a shortcut for converting paths to OS specific strings
-    in properties has been added. One can use the expression 
-    ${toString:<em>pathreference</em>} to convert a path element
-    reference to a string that can be used for a path argument.
-    For example:
-  </p>
-<pre>
-  &lt;path id="lib.path.ref"&gt;
-    &lt;fileset dir="lib" includes="*.jar"/&gt;
-  &lt;/path&gt;
-  &lt;javac srcdir="src" destdir="classes"&gt;
-    &lt;compilerarg arg="-Xbootclasspath/p:${toString:lib.path.ref}"/&gt;
-  &lt;/javac&gt;
-</pre>
-
-
-<h3><a name="arg">Command-line Arguments</a></h3>
-<p>Several tasks take arguments that will be passed to another
-process on the command line. To make it easier to specify arguments
-that contain space characters, nested <code>arg</code> elements can be used.</p>
-<table border="1" cellpadding="2" cellspacing="0">
+<h3 id="arg">Command-line Arguments</h3>
+<p>Several tasks take arguments that will be passed to another process on the command line. To make it easier to specify
+arguments that contain space characters, nested <code>arg</code> elements can be used.</p>
+<table class="attr">
 <tr>
-  <td width="12%" valign="top"><b>Attribute</b></td>
-  <td width="78%" valign="top"><b>Description</b></td>
-  <td width="10%" valign="top"><b>Required</b></td>
+  <th scope="col">Attribute</th>
+  <th scope="col">Description</th>
+  <th scope="col">Required</th>
 </tr>
   <tr>
-    <td valign="top">value</td>
-    <td valign="top">a single command-line argument; can contain space
-      characters.</td>
-    <td align="center" rowspan="5">Exactly one of these.</td>
+    <td>value</td>
+    <td>a single command-line argument; can contain space characters.</td>
+    <td rowspan="5">Exactly one of these.</td>
   </tr>
   <tr>
-    <td valign="top">file</td>
-    <td valign="top">The name of a file as a single command-line
-      argument; will be replaced with the absolute filename of the file.</td>
+    <td>file</td>
+    <td class="left">The name of a file as a single command-line argument; will be replaced with the absolute filename
+      of the file.</td>
   </tr>
   <tr>
-    <td valign="top">path</td>
-    <td valign="top">A string that will be treated as a path-like
-      string as a single command-line argument; you can use <code>;</code>
-      or <code>:</code> as
-      path separators and Ant will convert it to the platform's local
-      conventions.</td>
+    <td>path</td>
+    <td class="left">A string that will be treated as a path-like string as a single command-line argument; you can
+      use <q>;</q> or <q>:</q> as path separators and Ant will convert it to the platform's local conventions.</td>
   </tr>
   <tr>
-    <td valign="top">pathref</td>
-    <td valign="top"><a href="#references">Reference</a> to a path
-      defined elsewhere.  Ant will convert it to the platform's local
-      conventions.</td>
+    <td>pathref</td>
+    <td class="left"><a href="#references">Reference</a> to a path defined elsewhere.  Ant will convert it to the
+      platform's local conventions.</td>
   </tr>
   <tr>
-    <td valign="top">line</td>
-    <td valign="top">a space-delimited list of command-line arguments.</td>
+    <td>line</td>
+    <td class="left">a space-delimited list of command-line arguments.</td>
   </tr>
   <tr>
-    <td valign="top">prefix</td>
-    <td valign="top">A fixed string to be placed in front of the
-      argument. In the case of a line broken into parts, it will be
-      placed in front of every part. <em>Since Ant 1.8.</em></td>
-    <td valign="top" align="center">No</td>
+    <td>prefix</td>
+    <td>A fixed string to be placed in front of the argument. In the case of a line broken into parts, it will be placed
+      in front of every part. <em>Since Ant 1.8.</em></td>
+    <td>No</td>
   </tr>
   <tr>
-    <td valign="top">suffix</td>
-    <td valign="top">A fixed string to be placed immediately after the
-      argument. In the case of a line broken into parts, it will be
+    <td>suffix</td>
+    <td>A fixed string to be placed immediately after the argument. In the case of a line broken into parts, it will be
       placed after every part. <em>Since Ant 1.8.</em></td>
-    <td valign="top" align="center">No</td>
+    <td>No</td>
   </tr>
 </table>
 
-<p>It is highly recommended to avoid the <code>line</code> version
-when possible.  Ant will try to split the command line in a way
-similar to what a (Unix) shell would do, but may create something that
-is very different from what you expect under some circumstances.</p>
+<p>It is highly recommended to avoid the <var>line</var> version when possible.  Ant will try to split the command line
+in a way similar to what a (Unix) shell would do, but may create something that is very different from what you expect
+under some circumstances.</p>
 
 <h4>Examples</h4>
-<blockquote><pre>
-  &lt;arg value=&quot;-l -a&quot;/&gt;
-</pre></blockquote>
-<p>is a single command-line argument containing a space character,
-<i>not</i> separate commands "-l" and "-a".</p>
-<blockquote><pre>
-  &lt;arg line=&quot;-l -a&quot;/&gt;
-</pre></blockquote>
-<p>This is a command line with two separate arguments, "-l" and "-a".</p>
-<blockquote><pre>
-  &lt;arg path=&quot;/dir;/dir2:\dir3&quot;/&gt;
-</pre></blockquote>
-<p>is a single command-line argument with the value
-<code>\dir;\dir2;\dir3</code> on DOS-based systems and
-<code>/dir:/dir2:/dir3</code> on Unix-like systems.</p>
+<pre>&lt;arg value=&quot;-l -a&quot;/&gt;</pre>
+<p>is a single command-line argument containing a space character, <em>not</em> separate options <q>-l</q>
+and <q>-a</q>.</p>
+<pre>&lt;arg line=&quot;-l -a&quot;/&gt;</pre>
+<p>This is a command line with two separate options, <q>-l</q> and <q>-a</q>.</p>
+<pre>&lt;arg path=&quot;/dir;/dir2:\dir3&quot;/&gt;</pre>
+<p>is a single command-line argument with the value <code>\dir;\dir2;\dir3</code> on DOS-based systems
+and <code>/dir:/dir2:/dir3</code> on Unix(-like) systems.</p>
 
-<h3><a name="references">References</a></h3>
+<h3 id="references">References</h3>
 
-<p>Any project element can be assigned an identifier using its
-<code>id</code> attribute. In most cases the element can subsequently
-be referenced by specifying the <code>refid</code> attribute on an
-element of the same type.  This can be useful if you are going to
-replicate the same snippet of XML over and over again--using a
-<code>&lt;classpath&gt;</code> structure more than once, for example.</p>
+<p>Any project element can be assigned an identifier using its <var>id</var> attribute. In most cases the element can
+subsequently be referenced by specifying the <var>refid</var> attribute on an element of the same type.  This can be
+useful if you are going to replicate the same snippet of XML over and over again&mdash;using
+a <code>&lt;classpath&gt;</code> structure more than once, for example.</p>
 <p>The following example:</p>
-<blockquote><pre>
+<pre>
 &lt;project ... &gt;
   &lt;target ... &gt;
     &lt;rmic ...&gt;
@@ -484,10 +385,9 @@
       &lt;/classpath&gt;
     &lt;/javac&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre></blockquote>
+&lt;/project&gt;</pre>
 <p>could be rewritten as:</p>
-<blockquote><pre>
+<pre>
 &lt;project ... &gt;
   &lt;path id=&quot;project.class.path&quot;&gt;
     &lt;pathelement location=&quot;lib/&quot;/&gt;
@@ -506,72 +406,58 @@
       &lt;classpath refid=&quot;project.class.path&quot;/&gt;
     &lt;/javac&gt;
   &lt;/target&gt;
-&lt;/project&gt;
-</pre></blockquote>
-<p>All tasks that use nested elements for 
-<a href="Types/patternset.html">PatternSet</a>s, 
-<a href="Types/fileset.html">FileSet</a>s, 
-<a href="Types/zipfileset.html">ZipFileSet</a>s or 
-<a href="#path">path-like structures</a> accept references to these structures 
-as shown in the examples. Using <code>refid</code> on a task will ordinarily 
-have the same effect (referencing a task already declared), but the user 
-should be aware that the interpretation of this attribute is dependent on the 
-implementation of the element upon which it is specified. Some tasks (the 
-<a href="Tasks/property.html">property</a> task is a handy example) 
-deliberately assign a different meaning to <code>refid</code>.</p>
+&lt;/project&gt;</pre>
+<p>All tasks that use nested elements
+for <a href="Types/patternset.html">PatternSet</a>s, <a href="Types/fileset.html">FileSet</a>s, <a href="Types/zipfileset.html">ZipFileSet</a>s
+or <a href="#path">path-like structures</a> accept references to these structures as shown in the
+examples. Using <var>refid</var> on a task will ordinarily have the same effect (referencing a task already declared),
+but the user should be aware that the interpretation of this attribute is dependent on the implementation of the element
+upon which it is specified. Some tasks (the <a href="Tasks/property.html">property</a> task is a handy example)
+deliberately assign a different meaning to <var>refid</var>.</p>
 
-
-<h3><a name="external-tasks">Use of external tasks</a></h3> 
-Ant supports a plugin mechanism for using third party tasks. For using them you 
-have to do two steps: 
+<h3 id="external-tasks">Use of external tasks</h3>
+<p>Ant supports a plugin mechanism for using third party tasks. For using them you have to do two steps:</p>
 <ol>
-  <li>place their implementation somewhere where Ant can find them</li>
+  <li>place their implementation somewhere where Ant can find them.</li>
   <li>declare them.</li>
-</ol> 
-Don't add anything to the CLASSPATH environment variable - this is often the  
-reason for very obscure errors. Use Ant's own <a href="install.html#optionalTasks">mechanisms</a> 
-for adding libraries: 
+</ol>
+<p>Don't add anything to the <code>CLASSPATH</code> environment variable&mdash;this is often the reason for very obscure
+errors. Use Ant's own <a href="install.html#optionalTasks">mechanisms</a> for adding libraries:</p>
 <ul>
-  <li>via command line argument <code>-lib</code></li>
+  <li>via command line argument <kbd>-lib</kbd></li>
   <li>adding to <code>${user.home}/.ant/lib</code></li>
   <li>adding to <code>${ant.home}/lib</code></li>
 </ul>
-For the declaration there are several ways:
+<p>For the declaration there are several ways:</p>
 <ul>
-  <li>declare a single task per using instruction using  
-      <code>&lt;<a href="Tasks/taskdef.html">taskdef</a> name=&quot;taskname&quot; 
-      classname=&quot;ImplementationClass&quot;/&gt;</code>
-      <br>
-      <code>&lt;taskdef name=&quot;for&quot; classname=&quot;net.sf.antcontrib.logic.For&quot; /&gt; 
-      &lt;for ... /&gt;</code>
+  <li>declare a single task per using instruction using
+    <code>&lt;<a href="Tasks/taskdef.html">taskdef</a> name=&quot;taskname&quot;
+      classname=&quot;ImplementationClass&quot;/&gt;</code><br/>
+    <code class="code">&lt;taskdef name=&quot;for&quot; classname=&quot;net.sf.antcontrib.logic.For&quot;/&gt; &lt;for
+      ... /&gt;</code>
   </li>
-  <li>declare a bundle of tasks using a properties-file holding these 
-      taskname-ImplementationClass-pairs and <code>&lt;taskdef&gt;</code>
-      <br>
-      <code>&lt;taskdef resource=&quot;net/sf/antcontrib/antcontrib.properties&quot; /&gt; 
-      &lt;for ... /&gt;</code>
+  <li>declare a bundle of tasks using a <samp>properties</samp> file holding these taskname&ndash;ImplementationClass
+    pairs and <code>&lt;taskdef&gt;</code><br/>
+    <code class="code">&lt;taskdef resource=&quot;net/sf/antcontrib/antcontrib.properties&quot;/&gt; &lt;for
+    ... /&gt;</code>
   </li>
-  <li>declare a bundle of tasks using a <a href="Types/antlib.html">xml-file</a> holding these  
-      taskname-ImplementationClass-pairs and <code>&lt;taskdef&gt;</code>
-      <br>
-      <code>&lt;taskdef resource=&quot;net/sf/antcontrib/antlib.xml&quot; /&gt; 
-      &lt;for ... /&gt;</code>
+  <li>declare a bundle of tasks using an <a href="Types/antlib.html">xml file</a> holding these
+    taskname-ImplementationClass-pairs and <code>&lt;taskdef&gt;</code><br/>
+    <code class="code">&lt;taskdef resource=&quot;net/sf/antcontrib/antlib.xml&quot;/&gt; &lt;for ... /&gt;</code>
   </li>
-  <li>declare a bundle of tasks using a xml-file named antlib.xml, XML-namespace and 
-      <a href="Types/antlib.html#antlibnamespace"><code>antlib:</code> protocol handler</a> 
-      <br>
-      <code>&lt;project xmlns:ac=&quot;antlib:net.sf.antcontrib&quot;/&gt; 
-      &lt;ac:for ... /&gt;</code>
+  <li>declare a bundle of tasks using an xml file named <samp>antlib.xml</samp>, XML namespace
+    and <a href="Types/antlib.html#antlibnamespace"><code>antlib:</code> protocol handler</a><br/>
+    <code class="code">&lt;project xmlns:ac=&quot;antlib:net.sf.antcontrib&quot;/&gt; &lt;ac:for ... /&gt;</code>
   </li>
 </ul>
 
 If you need a special function, you should
 <ol>
   <li>have a look at this manual, because Ant provides lot of tasks</li>
-  <li>have a look at the external task page <a href="http://ant.apache.org/external.html">online</a></li>
+  <li>have a look at the external task page <a href="https://ant.apache.org/external.html" target="_top">online</a></li>
   <li>have a look at the external task <a href="https://cwiki.apache.org/confluence/display/ANT/AntExternalTaskdefs" target="_top">wiki
     page</a></li>
-  <li>ask on the <a href="http://ant.apache.org/mail.html#User%20List">Ant user</a> list</li>
+  <li>ask on the <a href="https://ant.apache.org/mail.html#User%20List" target="_top">Ant user</a> list</li>
   <li><a href="tutorial-writing-tasks.html">implement</a> (and share) your own</li>
 </ol>
 
diff --git a/manual/usinglist.html b/manual/usinglist.html
index 9169d6f..cb70c2b 100644
--- a/manual/usinglist.html
+++ b/manual/usinglist.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,10 +15,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<html>
+<html lang="en">
 
 <head>
-<meta http-equiv="Content-Language" content="en-us"/>
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css"/>
 <title>Apache Ant User Manual</title>
 <base target="mainFrame"/>
@@ -29,22 +29,19 @@
 
 <h3>Using Apache Ant</h3>
 <ul class="inlinelist">
-<li><a href="using.html#buildfile">Writing a Simple Buildfile</a></li>
-<div style="padding-left:1em">
-  <li><a href="using.html#projects">Projects</a></li>
-  <li><a href="targets.html#targets">Targets</a></li>
-  <li><a href="using.html#tasks">Tasks</a></li>
-  <li><a href="using.html#properties">Properties</a></li>
-  <li><a href="properties.html#built-in-props">Built-in Properties</a></li>
-  <li><a href="properties.html#propertyHelper">Property Helpers</a></li>
-  <li><a href="using.html#example">Example Buildfile</a></li>
-  <li><a href="using.html#filters">Token Filters</a></li>
-  <li><a href="using.html#path">Path-like Structures</a></li>
-  <li><a href="using.html#arg">Command-line Arguments</a></li>
-  <li><a href="using.html#references">References</a></li>
-  <li><a href="using.html#external-tasks">Use of external tasks</a></li>
-</div>
+  <li><a href="using.html#buildfile">Writing a Simple Buildfile</a></li>
+  <li class="indent"><a href="using.html#projects">Projects</a></li>
+  <li class="indent"><a href="targets.html#targets">Targets</a></li>
+  <li class="indent"><a href="using.html#tasks">Tasks</a></li>
+  <li class="indent"><a href="using.html#properties">Properties</a></li>
+  <li class="indent"><a href="properties.html#built-in-props">Built-in Properties</a></li>
+  <li class="indent"><a href="properties.html#propertyHelper">Property Helpers</a></li>
+  <li class="indent"><a href="using.html#example">Example Buildfile</a></li>
+  <li class="indent"><a href="using.html#filters">Token Filters</a></li>
+  <li class="indent"><a href="using.html#path">Path-like Structures</a></li>
+  <li class="indent"><a href="using.html#arg">Command-line Arguments</a></li>
+  <li class="indent"><a href="using.html#references">References</a></li>
+  <li class="indent"><a href="using.html#external-tasks">Use of external tasks</a></li>
 </ul>
 </body>
 </html>
-
diff --git a/patch.xml b/patch.xml
index 910b123..7adbe04 100644
--- a/patch.xml
+++ b/patch.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
diff --git a/release.sh b/release.sh
index d1043d5..cdaec06 100755
--- a/release.sh
+++ b/release.sh
@@ -6,7 +6,7 @@
 # (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
+#     https://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,
diff --git a/release/build-osx-pkg.py b/release/build-osx-pkg.py
deleted file mode 100755
index 4144a03..0000000
--- a/release/build-osx-pkg.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#!/usr/bin/env python
-
-# 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.
-
-# Builds a Mac OS X .pkg from a binary ZIP archive of Apache Ant.
-
-import collections
-import contextlib
-import os
-
-ApacheAntURL = collections.namedtuple(
-    'ApacheAntURL',
-    ('url', 'url_scheme', 'version', 'directory_name'))
-
-@contextlib.contextmanager
-def make_temp_directory():
-    '''Creates a temporary directory which is recursively deleted when out of scope.'''
-    import shutil
-    import tempfile
-    temp_dir = tempfile.mkdtemp()
-    yield temp_dir
-    shutil.rmtree(temp_dir)
-
-@contextlib.contextmanager
-def self_closing_url(url):
-    '''Opens a URL and returns a self-closing file-like object.'''
-    import urllib2
-    url_fp = urllib2.urlopen(url)
-    yield url_fp
-    url_fp.close()
-
-def apache_ant_url(url_string):
-    '''Parses a URL string into an ApacheAntURL object.'''
-    import argparse, collections, os.path, urlparse
-    parse_result = urlparse.urlparse(url_string)
-    filename = os.path.split(parse_result.path)[1]
-    if not (filename.startswith('apache-ant-') and filename.endswith('-bin.zip')):
-        raise argparse.ArgumentTypeError(
-            'Expected [%s] to end with apache-ant-X.Y.Z-bin.zip' % (url_string))
-    extracted_directory = filename.replace('-bin.zip', '')
-    extracted_version = extracted_directory.replace('apache-ant-', '')
-    return ApacheAntURL(
-        url=url_string,
-        url_scheme=parse_result.scheme,
-        version=extracted_version,
-        directory_name=extracted_directory)
-
-def fetch_url(url, local_output_file):
-    '''Downloads the contents of 'url' and writes them the opened file 'output_file'.'''
-    import shutil
-    import urllib2
-    CHUNK_SIZE = 16 * 1024
-    print 'Fetching {url}...'.format(url=url)
-    with self_closing_url(url) as url_input_file:
-        while True:
-            chunk = url_input_file.read(CHUNK_SIZE)
-            if not chunk:
-                break
-            local_output_file.write(chunk)
-        local_output_file.seek(0)
-
-def fetch_apache_ant_url(apache_ant_url, temp_dir):
-    '''If the ApacheAntURL object is remote, fetches and returns the local file object.
-    Otherwise, opens and returns a file object.'''
-    import tempfile
-    if apache_ant_url.url_scheme == '' or apache_ant_url.url_scheme == 'file':
-        return open(apache_ant_url.url, 'rb')
-    else:
-        fp = tempfile.TemporaryFile(dir=temp_dir)
-        fetch_url(apache_ant_url.url, fp)
-        return fp
-
-def uncompress_contents(temp_dir, archive_file, directory_name, path_prefix):
-    '''Uncompresses the contents of 'archive_file' to 'temp_dir'.
-
-    Strips the prefix 'directory_name' and prepends 'path_prefix' to each entry
-    of the zip file.
-    '''
-    import shutil, zipfile
-    output_path = os.path.join(temp_dir, 'pkg')
-    os.mkdir(output_path)
-    z = zipfile.ZipFile(archive_file)
-    print 'Extracting archive to {output_path}...'.format(
-        output_path=output_path)
-    for entry in z.infolist():
-        # We can't just extract directly, since we want to map:
-        #
-        # apache-ant-X.Y.Z/bin/foo
-        #
-        # to
-        #
-        # usr/local/ant/bin/foo
-        #
-        # So, we strip out the apache-ant-X.Y.Z prefix, then instead of
-        # using ZipFile.extract(), we use ZipFile.open() to get a read fd to
-        # the source file, then os.fdopen() with the appropriate permissions
-        # to geta write fd to the modified destination path.
-        expected_prefix = directory_name + '/'
-        if not entry.filename.startswith(expected_prefix):
-            raise Exeption('Unexpected entry in zip file: [{filename}]'.format(
-                    filename=entry.filename))
-        entry_path = entry.filename.replace(expected_prefix, '', 1)
-
-        # Using os.path.join is annoying here (we'd have to explode output_path
-        # and entry_path).
-        entry_output_path = output_path + path_prefix + '/' + entry_path
-
-        # Zip file paths are normalized with '/' at the end for directories.
-        if entry_output_path.endswith('/'):
-            print 'Creating directory {path}'.format(path=entry_output_path)
-            os.makedirs(entry_output_path)
-        else:
-            # Yes, this is really how you extract permissions from a ZipInfo entry.
-            perms = (entry.external_attr >> 16L) & 0777
-            print 'Extracting {entry_filename} to {path} with mode 0{mode:o}'.format(
-                entry_filename=entry.filename, path=entry_output_path, mode=perms)
-            with z.open(entry) as source:
-                with os.fdopen(
-                    os.open(entry_output_path, os.O_WRONLY | os.O_CREAT, perms), 'w') \
-                    as destination:
-                    shutil.copyfileobj(source, destination)
-    return output_path
-
-def write_paths_d_entry(paths_d_directory, filename):
-    os.makedirs(paths_d_directory)
-    output_file = os.path.join(paths_d_directory, filename)
-    with open(output_file, 'w') as f:
-        print >>f, '/usr/local/ant/bin'
-
-def make_pkg(pkg_dir, pkg_identifier, pkg_version, output_pkg_path):
-    import subprocess
-    print 'Building package at {output_pkg_path}...'.format(
-        output_pkg_path=output_pkg_path)
-    subprocess.call(
-        ['pkgbuild',
-         '--root', pkg_dir,
-         '--identifier', pkg_identifier,
-         '--version', pkg_version,
-         output_pkg_path])
-
-def main():
-    import argparse
-    parser = argparse.ArgumentParser(description='Builds a Mac OS X .pkg of ant.')
-    parser.add_argument(
-        'apache_ant_url',
-        metavar='file-or-url',
-        help='Source file or URL from which to uncompress apache-ant-X.Y.Z-bin.zip',
-        type=apache_ant_url)
-    parser.add_argument(
-        '--output-dir',
-        default='.',
-        help='Directory to which .pkg will be written. Defaults to current directory.')
-    args = parser.parse_args()
-    with make_temp_directory() as temp_dir:
-        archive_file = fetch_apache_ant_url(args.apache_ant_url, temp_dir)
-        pkg_dir = uncompress_contents(
-            temp_dir, archive_file, args.apache_ant_url.directory_name, '/usr/local/ant')
-        etc_paths_d_dir = os.path.join(pkg_dir, 'etc', 'paths.d')
-        write_paths_d_entry(etc_paths_d_dir, 'org.apache.ant')
-        pkg_identifier = 'org.apache.ant'
-        output_pkg_path = os.path.join(
-            args.output_dir, args.apache_ant_url.directory_name + '.pkg')
-        make_pkg(pkg_dir, pkg_identifier, args.apache_ant_url.version, output_pkg_path)
-
-if __name__ == '__main__':
-    main()
diff --git a/release/ivy.xml b/release/ivy.xml
index ebb2a13..ccd677d 100644
--- a/release/ivy.xml
+++ b/release/ivy.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -19,7 +19,7 @@
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
   <info organisation="org/apache"
-        module="ant" revision="1.9.17"/>
+        module="ant" revision="1.10.13"/>
   <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"/>
@@ -91,6 +91,12 @@
     <artifact name="ant-commons-net" type="jar.asc" ext="jar.asc"/>
     <artifact name="ant-commons-net" type="source" ext="jar" e:classifier="sources"/>
     <artifact name="ant-commons-net" type="source.asc" ext="jar.asc" e:classifier="sources"/>
+    <artifact name="ant-imageio" type="pom" ext="pom"/>
+    <artifact name="ant-imageio" type="pom.asc" ext="pom.asc"/>
+    <artifact name="ant-imageio" type="jar" ext="jar"/>
+    <artifact name="ant-imageio" type="jar.asc" ext="jar.asc"/>
+    <artifact name="ant-imageio" type="source" ext="jar" e:classifier="sources"/>
+    <artifact name="ant-imageio" type="source.asc" ext="jar.asc" e:classifier="sources"/>
     <artifact name="ant-jai" type="pom" ext="pom"/>
     <artifact name="ant-jai" type="pom.asc" ext="pom.asc"/>
     <artifact name="ant-jai" type="jar" ext="jar"/>
@@ -103,6 +109,12 @@
     <artifact name="ant-javamail" type="jar.asc" ext="jar.asc"/>
     <artifact name="ant-javamail" type="source" ext="jar" e:classifier="sources"/>
     <artifact name="ant-javamail" type="source.asc" ext="jar.asc" e:classifier="sources"/>
+    <artifact name="ant-jakartamail" type="pom" ext="pom"/>
+    <artifact name="ant-jakartamail" type="pom.asc" ext="pom.asc"/>
+    <artifact name="ant-jakartamail" type="jar" ext="jar"/>
+    <artifact name="ant-jakartamail" type="jar.asc" ext="jar.asc"/>
+    <artifact name="ant-jakartamail" type="source" ext="jar" e:classifier="sources"/>
+    <artifact name="ant-jakartamail" type="source.asc" ext="jar.asc" e:classifier="sources"/>
     <artifact name="ant-jdepend" type="pom" ext="pom"/>
     <artifact name="ant-jdepend" type="pom.asc" ext="pom.asc"/>
     <artifact name="ant-jdepend" type="jar" ext="jar"/>
@@ -133,6 +145,12 @@
     <artifact name="ant-junit4" type="jar.asc" ext="jar.asc"/>
     <artifact name="ant-junit4" type="source" ext="jar" e:classifier="sources"/>
     <artifact name="ant-junit4" type="source.asc" ext="jar.asc" e:classifier="sources"/>
+    <artifact name="ant-junitlauncher" type="pom" ext="pom"/>
+    <artifact name="ant-junitlauncher" type="pom.asc" ext="pom.asc"/>
+    <artifact name="ant-junitlauncher" type="jar" ext="jar"/>
+    <artifact name="ant-junitlauncher" type="jar.asc" ext="jar.asc"/>
+    <artifact name="ant-junitlauncher" type="source" ext="jar" e:classifier="sources"/>
+    <artifact name="ant-junitlauncher" type="source.asc" ext="jar.asc" e:classifier="sources"/>
     <artifact name="ant-launcher" type="pom" ext="pom"/>
     <artifact name="ant-launcher" type="pom.asc" ext="pom.asc"/>
     <artifact name="ant-launcher" type="jar" ext="jar"/>
@@ -157,6 +175,12 @@
     <artifact name="ant-testutil" type="jar.asc" ext="jar.asc"/>
     <artifact name="ant-testutil" type="source" ext="jar" e:classifier="sources"/>
     <artifact name="ant-testutil" type="source.asc" ext="jar.asc" e:classifier="sources"/>
+    <artifact name="ant-xz" type="pom" ext="pom"/>
+    <artifact name="ant-xz" type="pom.asc" ext="pom.asc"/>
+    <artifact name="ant-xz" type="jar" ext="jar"/>
+    <artifact name="ant-xz" type="jar.asc" ext="jar.asc"/>
+    <artifact name="ant-xz" type="source" ext="jar" e:classifier="sources"/>
+    <artifact name="ant-xz" type="source.asc" ext="jar.asc" e:classifier="sources"/>
   </publications>
-  <dependencies/> 
+  <dependencies/>
 </ivy-module>
diff --git a/release/ivysettings.xml b/release/ivysettings.xml
index d40c461..24520c7 100644
--- a/release/ivysettings.xml
+++ b/release/ivysettings.xml
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/release/signit.xml b/release/signit.xml
index 8ac20cf..5fc224f 100644
--- a/release/signit.xml
+++ b/release/signit.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
diff --git a/release/upload.xml b/release/upload.xml
index 5631cfd..cd058dc 100644
--- a/release/upload.xml
+++ b/release/upload.xml
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index c644c82..1c7fa89 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 name: ant
-version: "1.9.17alpha"
+version: "1.10.13alpha"
 summary: Apache Ant
 description: |
   Apache Ant™ is a Java library and command-line tool whose mission is
@@ -27,7 +27,7 @@
   pilot any type of process which can be described in terms of targets
   and tasks.
 
-  Ant is written in Java and thus requires Java 5 or a later runtime
+  Ant is written in Java and thus requires Java 8 or a later runtime
   environment to be installed. If you want to build a Java project you
   will need a Java Development Kit rather than just a Java Runtime
   Environment.
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644
index 0000000..e5a814e
--- /dev/null
+++ b/sonar-project.properties
@@ -0,0 +1,10 @@
+sonar.projectKey=ant-master
+sonar.organization=apache
+sonar.projectName=Apache Ant
+sonar.sources=src/main
+sonar.tests=src/tests/junit
+sonar.projectVersion=1.10.0-SNAPSHOT
+sonar.java.source=8
+sonar.java.binaries=build/classes
+sonar.java.test.binaries=build/testcases
+sonar.java.libraries=lib/optional/*.jar
diff --git a/sonarqube.xml b/sonarqube.xml
new file mode 100644
index 0000000..7d97169
--- /dev/null
+++ b/sonarqube.xml
@@ -0,0 +1,33 @@
+<project default="sonar" basedir=".">
+
+  <!-- gets overridden by the jenkins job -->
+  <property name="sonar.host.url" value="http://localhost:9000" />
+  <property name="sonar.login" value="xxx" />
+
+  <!-- source SonarQube project properties -->
+  <property file="sonar-project.properties"/>
+
+  <property name="downloads" location="build/downloads"/>
+  <property name="sonarqube-ant-task-jar" location="${downloads}/sonarqube-ant-task.jar"/>
+  <property name="sonarqube-ant-task-url"
+            value="https://binaries.sonarsource.com/Distribution/sonarqube-ant-task/sonarqube-ant-task-2.6.0.1426.jar"/>
+
+  <target name="download">
+    <mkdir dir="${downloads}"/>
+    <get dest="${sonarqube-ant-task-jar}" src="${sonarqube-ant-task-url}"/>
+  </target>
+
+  <target name="build-classes">
+    <ant antfile="launch-build.xml">
+      <property name="args" value="-Djenkins=t"/>
+    </ant>
+  </target>
+
+  <target name="sonar" depends="build-classes,download">
+    <taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
+        <classpath path="${sonarqube-ant-task-jar}" />
+    </taskdef>
+
+    <sonar:sonar xmlns:sonar="antlib:org.sonar.ant"/>
+  </target>
+</project>
diff --git a/src/etc/ant-bin.wxs b/src/etc/ant-bin.wxs
index 74ed74f..587aaba 100644
--- a/src/etc/ant-bin.wxs
+++ b/src/etc/ant-bin.wxs
@@ -6,7 +6,7 @@
    (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
+       https://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,
@@ -436,16 +436,18 @@
           <File DiskId="1" Id="file594" Name="JUNIT-_3.XSL" LongName="junit-frames-xalan1.xsl" Vital="yes" src="$(var.dist.dir)/etc\junit-frames-xalan1.xsl" />
           <File DiskId="1" Id="file595" Name="JUNIT-_1.XSL" LongName="junit-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\junit-frames.xsl" />
           <File DiskId="1" Id="file596" Name="JUNIT-_2.XSL" LongName="junit-noframes.xsl" Vital="yes" src="$(var.dist.dir)/etc\junit-noframes.xsl" />
-          <File DiskId="1" Id="file597" Name="log.xsl" Vital="yes" src="$(var.dist.dir)/etc\log.xsl" />
-          <File DiskId="1" Id="file598" Name="MAUDIT_1.XSL" LongName="maudit-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\maudit-frames.xsl" />
-          <File DiskId="1" Id="file599" Name="MMETRI_1.XSL" LongName="mmetrics-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\mmetrics-frames.xsl" />
-          <File DiskId="1" Id="file600" Name="tagdiff.xsl" Vital="yes" src="$(var.dist.dir)/etc\tagdiff.xsl" />
+          <File DiskId="1" Id="file597" Name="JUNIT-_4.XSL" LongName="junit-frames-saxon.xsl" Vital="yes" src="$(var.dist.dir)/etc\junit-frames-saxon.xsl" />
+          <File DiskId="1" Id="file598" Name="JUNIT-_5.XSL" LongName="junit-noframes-saxon.xsl" Vital="yes" src="$(var.dist.dir)/etc\junit-noframes-saxon.xsl" />
+          <File DiskId="1" Id="file599" Name="log.xsl" Vital="yes" src="$(var.dist.dir)/etc\log.xsl" />
+          <File DiskId="1" Id="file600" Name="MAUDIT_1.XSL" LongName="maudit-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\maudit-frames.xsl" />
+          <File DiskId="1" Id="file601" Name="MMETRI_1.XSL" LongName="mmetrics-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\mmetrics-frames.xsl" />
+          <File DiskId="1" Id="file602" Name="tagdiff.xsl" Vital="yes" src="$(var.dist.dir)/etc\tagdiff.xsl" />
         </Component>
         <Directory Id="directory98" Name="CHECKS_1" LongName="checkstyle">
           <Component Id="component95" DiskId="1" Guid="2AEB59C7-5CEF-401c-9AB9-911B995F00FC">
-            <File DiskId="1" Id="file601" Name="CHECKS_1.XSL" LongName="checkstyle-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\checkstyle\checkstyle-frames.xsl" />
-            <File DiskId="1" Id="file602" Name="CHECKS_3.XSL" LongName="checkstyle-text.xsl" Vital="yes" src="$(var.dist.dir)/etc\checkstyle\checkstyle-text.xsl" />
-            <File DiskId="1" Id="file603" Name="CHECKS_2.XSL" LongName="checkstyle-xdoc.xsl" Vital="yes" src="$(var.dist.dir)/etc\checkstyle\checkstyle-xdoc.xsl" />
+            <File DiskId="1" Id="file603" Name="CHECKS_1.XSL" LongName="checkstyle-frames.xsl" Vital="yes" src="$(var.dist.dir)/etc\checkstyle\checkstyle-frames.xsl" />
+            <File DiskId="1" Id="file604" Name="CHECKS_3.XSL" LongName="checkstyle-text.xsl" Vital="yes" src="$(var.dist.dir)/etc\checkstyle\checkstyle-text.xsl" />
+            <File DiskId="1" Id="file605" Name="CHECKS_2.XSL" LongName="checkstyle-xdoc.xsl" Vital="yes" src="$(var.dist.dir)/etc\checkstyle\checkstyle-xdoc.xsl" />
           </Component>
         </Directory>
       </Directory>
diff --git a/src/etc/ant-msi.wxs b/src/etc/ant-msi.wxs
index 34b59eb..04e9fe9 100644
--- a/src/etc/ant-msi.wxs
+++ b/src/etc/ant-msi.wxs
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/ant-update.xsl b/src/etc/ant-update.xsl
index c81a39f..ec3a61f 100644
--- a/src/etc/ant-update.xsl
+++ b/src/etc/ant-update.xsl
@@ -9,7 +9,7 @@
    (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
+       https://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,
diff --git a/src/etc/changelog.xsl b/src/etc/changelog.xsl
index c6aef8f..6a5904f 100644
--- a/src/etc/changelog.xsl
+++ b/src/etc/changelog.xsl
@@ -12,7 +12,7 @@
    (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
+       https://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,
@@ -76,7 +76,7 @@
         <h1>
           <a name="top"><xsl:value-of select="$title"/></a>
         </h1>
-        <p style="text-align: right">Designed for use with <a href="http://ant.apache.org/">Apache Ant</a>.</p>
+        <p style="text-align: right">Designed for use with <a href="https://ant.apache.org/">Apache Ant</a>.</p>
         <hr/>
         <table border="0" width="100%" cellspacing="1">
           
diff --git a/src/etc/checkstyle/RequiredHeader.txt b/src/etc/checkstyle/RequiredHeader.txt
index 6a5bb9a..7074baf 100644
--- a/src/etc/checkstyle/RequiredHeader.txt
+++ b/src/etc/checkstyle/RequiredHeader.txt
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/checkstyle/checkstyle-config b/src/etc/checkstyle/checkstyle-config
index 508a882..f0b46c5 100644
--- a/src/etc/checkstyle/checkstyle-config
+++ b/src/etc/checkstyle/checkstyle-config
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+<!DOCTYPE module PUBLIC
+    "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
+    "https://checkstyle.org/dtds/configuration_1_3.dtd">
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -8,7 +10,7 @@
    (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
+       https://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,
@@ -18,18 +20,15 @@
 -->
 
 <module name="Checker">
-
   <!-- required licence file -->
   <module name="Header">
-      <property name="headerFile" value="${config.dir}/RequiredHeader.txt"/>
-      <property name="ignoreLines" value="2"/>
+    <property name="headerFile" value="${checkstyle.src.dir}/RequiredHeader.txt"/>
+    <property name="ignoreLines" value="2"/>
   </module>
-  
+
   <!-- size limits -->
   <module name="FileLength"/>
-
   <module name="FileTabCharacter"/>
-  
 
   <module name="TreeWalker">
     <!-- Javadoc requirements -->
@@ -93,7 +92,7 @@
     <module name="RightCurly"/>
 
     <!-- Checks for common coding problems -->
-    <!--<module name="AvoidInlineConditionals"/> -->
+    <!-- <module name="AvoidInlineConditionals"/> -->
     <module name="EmptyStatement"/>
     <module name="EqualsHashCode"/>
     <module name="IllegalInstantiation">
@@ -102,11 +101,11 @@
     <!-- <module name="InnerAssignment"/> -->
     <!-- <module name="MagicNumber"/> -->
     <module name="MissingSwitchDefault"/>
-    <!-- Allow redundant throw declarations for doc purposes 
+    <!-- Allow redundant throw declarations for doc purposes
     <module name="RedundantThrows">
       <property name="allowUnchecked" value="true"/>
     </module>
-         -->
+    -->
     <module name="SimplifyBooleanExpression"/>
     <module name="SimplifyBooleanReturn"/>
 
@@ -129,7 +128,7 @@
     <!-- \s matches whitespace character, $ matches end of line. -->
     <property name="format" value="\s+$"/>
   </module>
-  
+
   <!-- <module name="au.com.redhillconsulting.simian.SimianCheck"/> -->
   <module name="SuppressionCommentFilter">
     <property name="offCommentFormat" value="CheckStyle\:([\w\|]+) *OFF"/>
diff --git a/src/etc/checkstyle/checkstyle-frames-sortby-check.xsl b/src/etc/checkstyle/checkstyle-frames-sortby-check.xsl
index 060f878..e7a19b2 100644
--- a/src/etc/checkstyle/checkstyle-frames-sortby-check.xsl
+++ b/src/etc/checkstyle/checkstyle-frames-sortby-check.xsl
@@ -12,7 +12,7 @@
    (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
+       https://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,
@@ -64,8 +64,8 @@
             <body onload="javascript:openFirst();">
                 <h1>CheckStyle Audit</h1>
                 <p>Designed for use with
-                  <a href='http://checkstyle.sourceforge.net/'>CheckStyle</a> and
-                  <a href='http://ant.apache.org/'>Ant</a>.
+                  <a href='https://checkstyle.org/'>CheckStyle</a> and
+                  <a href='https://ant.apache.org/'>Ant</a>.
                 </p>
                 <xsl:apply-templates select="." mode="navigation"/>
                 <xsl:apply-templates select="." mode="data"/>
diff --git a/src/etc/checkstyle/checkstyle-frames.xsl b/src/etc/checkstyle/checkstyle-frames.xsl
index c79c0b7..c0351e2 100644
--- a/src/etc/checkstyle/checkstyle-frames.xsl
+++ b/src/etc/checkstyle/checkstyle-frames.xsl
@@ -12,7 +12,7 @@
    (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
+       https://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,
@@ -78,8 +78,8 @@
             </tr>
             <tr>
                 <td class="text-align:right">Designed for use with
-                  <a href='http://checkstyle.sourceforge.net/'>CheckStyle</a> and
-                  <a href='http://ant.apache.org/'>Ant</a>.</td>
+                  <a href='https://checkstyle.org/'>CheckStyle</a> and
+                  <a href='https://ant.apache.org/'>Ant</a>.</td>
             </tr>
         </table>
         <hr size="1"/>
@@ -296,4 +296,4 @@
             <xsl:if test="position() mod 2 = 0">evenrow</xsl:if>
         </xsl:attribute>
     </xsl:template>
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>
diff --git a/src/etc/checkstyle/checkstyle-text.xsl b/src/etc/checkstyle/checkstyle-text.xsl
index 7359e41..65943a3 100644
--- a/src/etc/checkstyle/checkstyle-text.xsl
+++ b/src/etc/checkstyle/checkstyle-text.xsl
@@ -9,7 +9,7 @@
    (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
+       https://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,
diff --git a/src/etc/checkstyle/checkstyle-xdoc.xsl b/src/etc/checkstyle/checkstyle-xdoc.xsl
index 5fc6eab..5f7b367 100644
--- a/src/etc/checkstyle/checkstyle-xdoc.xsl
+++ b/src/etc/checkstyle/checkstyle-xdoc.xsl
@@ -12,7 +12,7 @@
    (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
+       https://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,
diff --git a/src/etc/common2master.xsl b/src/etc/common2master.xsl
index da1527e..2466d2e 100644
--- a/src/etc/common2master.xsl
+++ b/src/etc/common2master.xsl
@@ -17,7 +17,7 @@
    (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
+       https://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,
diff --git a/src/etc/copyrightcheck.sh b/src/etc/copyrightcheck.sh
index 51c5e99..9cab2c8 100755
--- a/src/etc/copyrightcheck.sh
+++ b/src/etc/copyrightcheck.sh
@@ -7,7 +7,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/coverage-frames.xsl b/src/etc/coverage-frames.xsl
index 9603597..c2379de 100644
--- a/src/etc/coverage-frames.xsl
+++ b/src/etc/coverage-frames.xsl
@@ -13,7 +13,7 @@
    (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
+       https://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,
@@ -392,14 +392,14 @@
   <table border="0" cellpadding="0" cellspacing="0" width="100%">
   <tr>
     <td class="bannercell" rowspan="2">
-      <a href="http://jakarta.apache.org/">
-      <img src="http://jakarta.apache.org/images/jakarta-logo.gif" alt="http://jakarta.apache.org" align="left" border="0"/>
+      <a href="https://ant.apache.org/">
+      <img src="https://ant.apache.org/images/group-logo.gif" alt="https://ant.apache.org" align="left" border="0"/>
       </a>
     </td>
         <td style="text-align:right"><h2>Source Code Coverage</h2></td>
         </tr>
         <tr>
-        <td style="text-align:right">Designed for use with <a href='http://www.sitraka.com/jprobe'>Sitraka JProbe</a> and <a href='http://jakarta.apache.org'>Ant</a>.</td>
+        <td style="text-align:right">Designed for use with Sitraka JProbe and <a href='https://ant.apache.org'>Ant</a>.</td>
         </tr>
   </table>
     <hr size="1"/>
diff --git a/src/etc/jdepend-frames.xsl b/src/etc/jdepend-frames.xsl
index 8028734..d35444b 100644
--- a/src/etc/jdepend-frames.xsl
+++ b/src/etc/jdepend-frames.xsl
@@ -12,7 +12,7 @@
    (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
+       https://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,
@@ -360,7 +360,7 @@
   [explanations]
    </td></tr></table>
 
-  <p>The following explanations are for quick reference and are lifted directly from the original <a href="http://www.clarkware.com/software/JDepend.html">JDepend documentation</a>.</p>
+  <p>The following explanations are for quick reference and are lifted directly from the original <a href="https://github.com/clarkware/jdepend">JDepend documentation</a>.</p>
 
   <h3><a name="EXnumber">Number of Classes</a></h3>
     <p>The number of concrete and abstract classes (and interfaces) in the package is an indicator of the extensibility of the package.</p>
@@ -476,7 +476,7 @@
   <table width="100%">
   <tr>
     <td align="left"></td>
-      <td align="right">Designed for use with <a href="http://www.clarkware.com/software/JDepend.html">JDepend</a> and <a href="http://jakarta.apache.org">Ant</a>.</td>
+      <td align="right">Designed for use with <a href="https://github.com/clarkware/jdepend">JDepend</a> and <a href="https://ant.apache.org">Ant</a>.</td>
   </tr>
   </table>
   <hr size="1"/>
diff --git a/src/etc/jdepend.xsl b/src/etc/jdepend.xsl
index b3a3778..68aaa2f 100644
--- a/src/etc/jdepend.xsl
+++ b/src/etc/jdepend.xsl
@@ -9,7 +9,7 @@
    (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
+       https://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,
@@ -89,7 +89,7 @@
     </ul-->
     
     <h1><a name="top">JDepend Analysis</a></h1>
-    <p align="right">Designed for use with <a href="http://www.clarkware.com/software/JDepend.html">JDepend</a> and <a href="https://ant.apache.org">Ant</a>.</p>
+    <p align="right">Designed for use with <a href="https://github.com/clarkware/jdepend">JDepend</a> and <a href="https://ant.apache.org">Ant</a>.</p>
     <hr size="2" />
     
     <table width="100%"><tr><td>
@@ -250,7 +250,7 @@
     [<a href="#NVexplanations">explanations</a>]
     </td></tr></table>
     
-    <p>The following explanations are for quick reference and are lifted directly from the original <a href="http://www.clarkware.com/software/JDepend.html">JDepend documentation</a>.</p>
+    <p>The following explanations are for quick reference and are lifted directly from the original <a href="https://github.com/clarkware/jdepend">JDepend documentation</a>.</p>
     
     <h3><a name="EXnumber">Number of Classes</a></h3>
         <p>The number of concrete and abstract classes (and interfaces) in the package is an indicator of the extensibility of the package.</p>
diff --git a/src/etc/junit-frames-saxon.xsl b/src/etc/junit-frames-saxon.xsl
new file mode 100644
index 0000000..1b2084e
--- /dev/null
+++ b/src/etc/junit-frames-saxon.xsl
@@ -0,0 +1,1022 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    exclude-result-prefixes="xs"
+    version="2.0">
+    <xsl:character-map name="no-control-characters">
+        <xsl:output-character character="&#127;" string="&amp;#127;"/>
+        <xsl:output-character character="&#128;" string="&amp;#128;"/>
+        <xsl:output-character character="&#129;" string="&amp;#129;"/>
+        <xsl:output-character character="&#130;" string="&amp;#130;"/>
+        <xsl:output-character character="&#131;" string="&amp;#131;"/>
+        <xsl:output-character character="&#132;" string="&amp;#132;"/>
+        <xsl:output-character character="&#133;" string="&amp;#133;"/>
+        <xsl:output-character character="&#134;" string="&amp;#134;"/>
+        <xsl:output-character character="&#135;" string="&amp;#135;"/>
+        <xsl:output-character character="&#136;" string="&amp;#136;"/>
+        <xsl:output-character character="&#137;" string="&amp;#137;"/>
+        <xsl:output-character character="&#138;" string="&amp;#138;"/>
+        <xsl:output-character character="&#139;" string="&amp;#139;"/>
+        <xsl:output-character character="&#140;" string="&amp;#140;"/>
+        <xsl:output-character character="&#141;" string="&amp;#141;"/>
+        <xsl:output-character character="&#142;" string="&amp;#142;"/>
+        <xsl:output-character character="&#143;" string="&amp;#143;"/>
+        <xsl:output-character character="&#144;" string="&amp;#144;"/>
+        <xsl:output-character character="&#145;" string="&amp;#145;"/>
+        <xsl:output-character character="&#146;" string="&amp;#146;"/>
+        <xsl:output-character character="&#147;" string="&amp;#147;"/>
+        <xsl:output-character character="&#148;" string="&amp;#148;"/>
+        <xsl:output-character character="&#149;" string="&amp;#149;"/>
+        <xsl:output-character character="&#150;" string="&amp;#150;"/>
+        <xsl:output-character character="&#151;" string="&amp;#151;"/>
+        <xsl:output-character character="&#152;" string="&amp;#152;"/>
+        <xsl:output-character character="&#153;" string="&amp;#153;"/>
+        <xsl:output-character character="&#154;" string="&amp;#154;"/>
+        <xsl:output-character character="&#155;" string="&amp;#155;"/>
+        <xsl:output-character character="&#156;" string="&amp;#156;"/>
+        <xsl:output-character character="&#157;" string="&amp;#157;"/>
+        <xsl:output-character character="&#158;" string="&amp;#158;"/>
+        <xsl:output-character character="&#159;" string="&amp;#159;"/>
+    </xsl:character-map>
+    <xsl:output method="html" indent="yes" encoding="UTF-8" use-character-maps="no-control-characters"/>
+    <xsl:decimal-format decimal-separator="." grouping-separator=","/>
+    <!--
+       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
+
+           https://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.
+     -->
+
+    <!--
+
+     Sample stylesheet to be used with Ant JUnitReport output.
+
+     It creates a set of HTML files a la javadoc where you can browse easily
+     through all packages and classes.
+
+    -->
+    <xsl:param name="output.dir" select="'.'"/>
+    <xsl:param name="TITLE">Unit Test Results.</xsl:param>
+
+
+    <xsl:template match="testsuites">
+        <!-- create the index.html -->
+        <xsl:result-document href="file:///{$output.dir}/index.html">
+            <xsl:call-template name="index.html"/>
+        </xsl:result-document>
+
+        <!-- create the stylesheet.css -->
+        <xsl:result-document href="file:///{$output.dir}/stylesheet.css">
+            <xsl:call-template name="stylesheet.css"/>
+        </xsl:result-document>
+
+        <!-- create the overview-packages.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/overview-summary.html">
+            <xsl:apply-templates select="." mode="overview.packages"/>
+        </xsl:result-document>
+
+        <!-- create the all-packages.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/overview-frame.html">
+            <xsl:apply-templates select="." mode="all.packages"/>
+        </xsl:result-document>
+
+        <!-- create the all-classes.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/allclasses-frame.html">
+            <xsl:apply-templates select="." mode="all.classes"/>
+        </xsl:result-document>
+
+        <!-- create the all-tests.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/all-tests.html">
+            <xsl:apply-templates select="." mode="all.tests"/>
+        </xsl:result-document>
+
+        <!-- create the alltests-fails.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/alltests-fails.html">
+            <xsl:apply-templates select="." mode="all.tests">
+                <xsl:with-param name="type" select="'fails'"/>
+            </xsl:apply-templates>
+        </xsl:result-document>
+
+        <!-- create the alltests-errors.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/alltests-errors.html">
+            <xsl:apply-templates select="." mode="all.tests">
+                <xsl:with-param name="type" select="'errors'"/>
+            </xsl:apply-templates>
+        </xsl:result-document>
+
+        <!-- create the alltests-skipped.html at the root -->
+        <xsl:result-document href="file:///{$output.dir}/alltests-skipped.html">
+            <xsl:apply-templates select="." mode="all.tests">
+                <xsl:with-param name="type" select="'skipped'"/>
+            </xsl:apply-templates>
+        </xsl:result-document>
+
+        <!-- process all packages -->
+        <xsl:for-each select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+            <xsl:call-template name="package">
+                <xsl:with-param name="name" select="@package"/>
+            </xsl:call-template>
+        </xsl:for-each>
+    </xsl:template>
+
+
+    <xsl:template name="package">
+        <xsl:param name="name"/>
+        <xsl:variable name="package.dir">
+            <xsl:if test="not($name = '')"><xsl:value-of select="translate($name,'.','/')"/></xsl:if>
+            <xsl:if test="$name = ''">.</xsl:if>
+        </xsl:variable>
+        <!--Processing package <xsl:value-of select="@name"/> in <xsl:value-of select="$output.dir"/> -->
+        <!-- create a classes-list.html in the package directory -->
+        <xsl:result-document href="file:///{$output.dir}/{$package.dir}/package-frame.html">
+            <xsl:call-template name="classes.list">
+                <xsl:with-param name="name" select="$name"/>
+            </xsl:call-template>
+        </xsl:result-document>
+
+        <!-- create a package-summary.html in the package directory -->
+        <xsl:result-document href="file:///{$output.dir}/{$package.dir}/package-summary.html">
+            <xsl:call-template name="package.summary">
+                <xsl:with-param name="name" select="$name"/>
+            </xsl:call-template>
+        </xsl:result-document>
+
+        <!-- for each class, creates a @name.html -->
+        <!-- @bug there will be a problem with inner classes having the same name, it will be overwritten -->
+        <xsl:for-each select="/testsuites/testsuite[@package = $name]">
+            <xsl:result-document href="file:///{$output.dir}/{$package.dir}/{@id}_{@name}.html">
+                <xsl:apply-templates select="." mode="class.details"/>
+            </xsl:result-document>
+            <xsl:if test="string-length(./system-out)!=0">
+                <xsl:result-document href="file:///{$output.dir}/{$package.dir}/{@id}_{@name}-out.html">
+                    <html>
+                        <head>
+                            <title>Standard Output from <xsl:value-of select="@name"/></title>
+                        </head>
+                        <body>
+                            <pre><xsl:value-of select="./system-out"/></pre>
+                        </body>
+                    </html>
+                </xsl:result-document>
+            </xsl:if>
+            <xsl:if test="string-length(./system-err)!=0">
+                <xsl:result-document href="file:///{$output.dir}/{$package.dir}/{@id}_{@name}-err.html">
+                    <html>
+                        <head>
+                            <title>Standard Error from <xsl:value-of select="@name"/></title>
+                        </head>
+                        <body>
+                            <pre><xsl:value-of select="./system-err"/></pre>
+                        </body>
+                    </html>
+                </xsl:result-document>
+            </xsl:if>
+            <xsl:if test="@failures != 0">
+                <xsl:result-document href="file:///{$output.dir}/{$package.dir}/{@id}_{@name}-fails.html">
+                    <xsl:apply-templates select="." mode="class.details">
+                        <xsl:with-param name="type" select="'fails'"/>
+                    </xsl:apply-templates>
+                </xsl:result-document>
+            </xsl:if>
+            <xsl:if test="@errors != 0">
+                <xsl:result-document href="file:///{$output.dir}/{$package.dir}/{@id}_{@name}-errors.html">
+                    <xsl:apply-templates select="." mode="class.details">
+                        <xsl:with-param name="type" select="'errors'"/>
+                    </xsl:apply-templates>
+                </xsl:result-document>
+            </xsl:if>
+            <xsl:if test="@skipped != 0">
+                <xsl:result-document href="file:///{$output.dir}/{$package.dir}/{@id}_{@name}-skipped.html">
+                    <xsl:apply-templates select="." mode="class.details">
+                        <xsl:with-param name="type" select="'skipped'"/>
+                    </xsl:apply-templates>
+                </xsl:result-document>
+            </xsl:if>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="index.html">
+        <html>
+            <head>
+                <title><xsl:value-of select="$TITLE"/></title>
+            </head>
+            <frameset cols="20%,80%">
+                <frameset rows="30%,70%">
+                    <frame src="overview-frame.html" name="packageListFrame"/>
+                    <frame src="allclasses-frame.html" name="classListFrame"/>
+                </frameset>
+                <frame src="overview-summary.html" name="classFrame"/>
+                <noframes>
+                    <h2>Frame Alert</h2>
+                    <p>
+                        This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+                    </p>
+                </noframes>
+            </frameset>
+        </html>
+    </xsl:template>
+
+    <!-- this is the stylesheet css to use for nearly everything -->
+    <xsl:template name="stylesheet.css">
+        body {
+        font:normal 68% verdana,arial,helvetica;
+        color:#000000;
+        }
+        table tr td, table tr th {
+        font-size: 68%;
+        }
+        table.details tr th{
+        font-weight: bold;
+        text-align:left;
+        background:#a6caf0;
+        }
+        table.details tr td{
+        background:#eeeee0;
+        }
+
+        p {
+        line-height:1.5em;
+        margin-top:0.5em; margin-bottom:1.0em;
+        }
+        h1 {
+        margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
+        }
+        h2 {
+        margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
+        }
+        h3 {
+        margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
+        }
+        h4 {
+        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+        }
+        h5 {
+        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+        }
+        h6 {
+        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+        }
+        .Error {
+        font-weight:bold; color:red;
+        }
+        .Failure {
+        font-weight:bold; color:purple;
+        }
+        .Properties {
+        text-align:right;
+        }
+    </xsl:template>
+
+    <!-- Create list of all/failed/errored/skipped tests -->
+    <xsl:template match="testsuites" mode="all.tests">
+        <xsl:param name="type" select="'all'"/>
+        <html>
+            <xsl:variable name="title">
+                <xsl:choose>
+                    <xsl:when test="$type = 'fails'">
+                        <xsl:text>All Failures</xsl:text>
+                    </xsl:when>
+                    <xsl:when test="$type = 'errors'">
+                        <xsl:text>All Errors</xsl:text>
+                    </xsl:when>
+                    <xsl:when test="$type = 'skipped'">
+                        <xsl:text>All Skipped</xsl:text>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:text>All Tests</xsl:text>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </xsl:variable>
+            <head>
+                <title>Unit Test Results: <xsl:value-of select="$title"/></title>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name"/>
+                </xsl:call-template>
+            </head>
+            <body>
+                <xsl:attribute name="onload">open('allclasses-frame.html','classListFrame')</xsl:attribute>
+                <xsl:call-template name="pageHeader"/>
+                <h2><xsl:value-of select="$title"/></h2>
+
+                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <xsl:call-template name="testcase.test.header">
+                        <xsl:with-param name="show.class" select="'yes'"/>
+                    </xsl:call-template>
+                    <!--
+                            test can even not be started at all (failure to load the class)
+                    so report the error directly
+                    -->
+                    <xsl:if test="./error">
+                        <tr class="Error">
+                            <td colspan="4">
+                                <xsl:apply-templates select="./error"/>
+                            </td>
+                        </tr>
+                    </xsl:if>
+                    <xsl:choose>
+                        <xsl:when test="$type = 'fails'">
+                            <xsl:apply-templates select=".//testcase[failure]" mode="print.test">
+                                <xsl:with-param name="show.class" select="'yes'"/>
+                            </xsl:apply-templates>
+                        </xsl:when>
+                        <xsl:when test="$type = 'errors'">
+                            <xsl:apply-templates select=".//testsuite[error]" mode="alltests.error.row"/>
+                            <xsl:apply-templates select=".//testcase[error]" mode="print.test">
+                                <xsl:with-param name="show.class" select="'yes'"/>
+                            </xsl:apply-templates>
+                        </xsl:when>
+                        <xsl:when test="$type = 'skipped'">
+                            <xsl:apply-templates select=".//testcase[skipped]" mode="print.test">
+                                <xsl:with-param name="show.class" select="'yes'"/>
+                            </xsl:apply-templates>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:apply-templates select=".//testsuite[error]" mode="alltests.error.row"/>
+                            <xsl:apply-templates select=".//testcase" mode="print.test">
+                                <xsl:with-param name="show.class" select="'yes'"/>
+                            </xsl:apply-templates>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </table>
+            </body>
+        </html>
+    </xsl:template>
+
+
+    <!-- ======================================================================
+        This page is created for every testsuite class.
+        It prints a summary of the testsuite and detailed information about
+        testcase methods.
+         ====================================================================== -->
+    <xsl:template match="testsuite" mode="class.details">
+        <xsl:param name="type" select="'all'"/>
+        <xsl:variable name="package.name" select="@package"/>
+        <xsl:variable name="class.name"><xsl:if test="not($package.name = '')"><xsl:value-of select="$package.name"/>.</xsl:if><xsl:value-of select="@name"/></xsl:variable>
+        <html>
+            <head>
+                <title>Unit Test Results: <xsl:value-of select="$class.name"/></title>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name" select="$package.name"/>
+                </xsl:call-template>
+                <script type="text/javascript" language="JavaScript">
+                    var TestCases = new Array();
+                    var cur;
+                    <xsl:apply-templates select="properties"/>
+                </script>
+                <script type="text/javascript" language="JavaScript"><![CDATA[
+        function displayProperties (name) {
+          var win = window.open('','JUnitSystemProperties','scrollbars=1,resizable=1');
+          var doc = win.document;
+          doc.open();
+          doc.write("<html><head><title>Properties of " + name + "</title>");
+          doc.write("<style type=\"text/css\">");
+          doc.write("body {font:normal 68% verdana,arial,helvetica; color:#000000; }");
+          doc.write("table tr td, table tr th { font-size: 68%; }");
+          doc.write("table.properties { border-collapse:collapse; border-left:solid 1 #cccccc; border-top:solid 1 #cccccc; padding:5px; }");
+          doc.write("table.properties th { text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#eeeeee; }");
+          doc.write("table.properties td { font:normal; text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#fffffff; }");
+          doc.write("h3 { margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica }");
+          doc.write("</style>");
+          doc.write("</head><body>");
+          doc.write("<h3>Properties of " + name + "</h3>");
+          doc.write("<div align=\"right\"><a href=\"javascript:window.close();\">Close</a></div>");
+          doc.write("<table class='properties'>");
+          doc.write("<tr><th>Name</th><th>Value</th></tr>");
+          for (prop in TestCases[name]) {
+            doc.write("<tr><th>" + prop + "</th><td>" + TestCases[name][prop] + "</td></tr>");
+          }
+          doc.write("</table>");
+          doc.write("</body></html>");
+          doc.close();
+          win.focus();
+        }
+      ]]>
+                </script>
+            </head>
+            <body>
+                <xsl:call-template name="pageHeader"/>
+                <h3>Class <xsl:value-of select="$class.name"/></h3>
+
+
+                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <xsl:call-template name="testsuite.test.header"/>
+                    <xsl:apply-templates select="." mode="print.test"/>
+                </table>
+
+                <xsl:choose>
+                    <xsl:when test="$type = 'fails'">
+                        <h2>Failures</h2>
+                    </xsl:when>
+                    <xsl:when test="$type = 'errors'">
+                        <h2>Errors</h2>
+                    </xsl:when>
+                    <xsl:when test="$type = 'skipped'">
+                        <h2>Skipped</h2>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <h2>Tests</h2>
+                    </xsl:otherwise>
+                </xsl:choose>
+                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <xsl:call-template name="testcase.test.header"/>
+                    <!--
+                            test can even not be started at all (failure to load the class)
+                    so report the error directly
+                    -->
+                    <xsl:if test="./error">
+                        <tr class="Error">
+                            <td colspan="4"><xsl:apply-templates select="./error"/></td>
+                        </tr>
+                    </xsl:if>
+                    <xsl:choose>
+                        <xsl:when test="$type = 'fails'">
+                            <xsl:apply-templates select="./testcase[failure]" mode="print.test"/>
+                        </xsl:when>
+                        <xsl:when test="$type = 'errors'">
+                            <xsl:apply-templates select="./testcase[error]" mode="print.test"/>
+                        </xsl:when>
+                        <xsl:when test="$type = 'skipped'">
+                            <xsl:apply-templates select="./testcase[skipped]" mode="print.test"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:apply-templates select="./testcase" mode="print.test"/>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </table>
+                <div class="Properties">
+                    <a>
+                        <xsl:attribute name="href">javascript:displayProperties('<xsl:value-of select="@package"/>.<xsl:value-of select="@name"/>');</xsl:attribute>
+                        Properties &#187;
+                    </a>
+                </div>
+                <xsl:if test="string-length(./system-out)!=0">
+                    <div class="Properties">
+                        <a>
+                            <xsl:attribute name="href">./<xsl:value-of select="@id"/>_<xsl:value-of select="@name"/>-out.html</xsl:attribute>
+                            System.out &#187;
+                        </a>
+                    </div>
+                </xsl:if>
+                <xsl:if test="string-length(./system-err)!=0">
+                    <div class="Properties">
+                        <a>
+                            <xsl:attribute name="href">./<xsl:value-of select="@id"/>_<xsl:value-of select="@name"/>-err.html</xsl:attribute>
+                            System.err &#187;
+                        </a>
+                    </div>
+                </xsl:if>
+            </body>
+        </html>
+    </xsl:template>
+
+    <!--
+     Write properties into a JavaScript data structure.
+     This is based on the original idea by Erik Hatcher (ehatcher@apache.org)
+     -->
+    <xsl:template match="properties">
+        cur = TestCases['<xsl:value-of select="../@package"/>.<xsl:value-of select="../@name"/>'] = new Array();
+        <xsl:for-each select="property">
+            <xsl:sort select="@name"/>
+            cur['<xsl:value-of select="@name"/>'] = '<xsl:call-template name="JS-escape"><xsl:with-param name="string" select="@value"/></xsl:call-template>';
+        </xsl:for-each>
+    </xsl:template>
+
+
+    <!-- ======================================================================
+        This page is created for every package.
+        It prints the name of all classes that belongs to this package.
+        @param name the package name to print classes.
+         ====================================================================== -->
+    <!-- list of classes in a package -->
+    <xsl:template name="classes.list">
+        <xsl:param name="name"/>
+        <html>
+            <head>
+                <title>Unit Test Classes: <xsl:value-of select="$name"/></title>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name" select="$name"/>
+                </xsl:call-template>
+            </head>
+            <body>
+                <table width="100%">
+                    <tr>
+                        <td nowrap="nowrap">
+                            <h2><a href="package-summary.html" target="classFrame">
+                                <xsl:value-of select="$name"/>
+                                <xsl:if test="$name = ''">&lt;none&gt;</xsl:if>
+                            </a></h2>
+                        </td>
+                    </tr>
+                </table>
+
+                <h2>Classes</h2>
+                <table width="100%">
+                    <xsl:for-each select="/testsuites/testsuite[./@package = $name]">
+                        <xsl:sort select="@name"/>
+                        <tr>
+                            <td nowrap="nowrap">
+                                <a href="{@id}_{@name}.html" target="classFrame"><xsl:value-of select="@name"/></a>
+                            </td>
+                        </tr>
+                    </xsl:for-each>
+                </table>
+            </body>
+        </html>
+    </xsl:template>
+
+
+    <!--
+        Creates an all-classes.html file that contains a link to all package-summary.html
+        on each class.
+    -->
+    <xsl:template match="testsuites" mode="all.classes">
+        <html>
+            <head>
+                <title>All Unit Test Classes</title>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name"/>
+                </xsl:call-template>
+            </head>
+            <body>
+                <h2>Classes</h2>
+                <table width="100%">
+                    <xsl:apply-templates select="testsuite" mode="all.classes">
+                        <xsl:sort select="@name"/>
+                    </xsl:apply-templates>
+                </table>
+            </body>
+        </html>
+    </xsl:template>
+
+    <xsl:template match="testsuite" mode="all.classes">
+        <xsl:variable name="package.name" select="@package"/>
+        <tr>
+            <td nowrap="nowrap">
+                <a target="classFrame">
+                    <xsl:attribute name="href">
+                        <xsl:if test="not($package.name='')">
+                            <xsl:value-of select="translate($package.name,'.','/')"/><xsl:text>/</xsl:text>
+                        </xsl:if><xsl:value-of select="@id"/>_<xsl:value-of select="@name"/><xsl:text>.html</xsl:text>
+                    </xsl:attribute>
+                    <xsl:value-of select="@name"/>
+                </a>
+            </td>
+        </tr>
+    </xsl:template>
+
+
+    <!--
+        Creates an html file that contains a link to all package-summary.html files on
+        each package existing on testsuites.
+        @bug there will be a problem here, I don't know yet how to handle unnamed package :(
+    -->
+    <xsl:template match="testsuites" mode="all.packages">
+        <html>
+            <head>
+                <title>All Unit Test Packages</title>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name"/>
+                </xsl:call-template>
+            </head>
+            <body>
+                <h2><a href="overview-summary.html" target="classFrame">Home</a></h2>
+                <h2>Packages</h2>
+                <table width="100%">
+                    <xsl:apply-templates select="testsuite[not(./@package = preceding-sibling::testsuite/@package)]" mode="all.packages">
+                        <xsl:sort select="@package"/>
+                    </xsl:apply-templates>
+                </table>
+            </body>
+        </html>
+    </xsl:template>
+
+    <xsl:template match="testsuite" mode="all.packages">
+        <tr>
+            <td nowrap="nowrap">
+                <a href="./{translate(@package,'.','/')}/package-summary.html" target="classFrame">
+                    <xsl:value-of select="@package"/>
+                    <xsl:if test="@package = ''">&lt;none&gt;</xsl:if>
+                </a>
+            </td>
+        </tr>
+    </xsl:template>
+
+
+    <xsl:template match="testsuites" mode="overview.packages">
+        <html>
+            <head>
+                <title>Unit Test Results: Summary</title>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name"/>
+                </xsl:call-template>
+            </head>
+            <body>
+                <xsl:attribute name="onload">open('allclasses-frame.html','classListFrame')</xsl:attribute>
+                <xsl:call-template name="pageHeader"/>
+                <h2>Summary</h2>
+                <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
+                <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
+                <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
+                <xsl:variable name="skippedCount" select="sum(testsuite/@skipped)" />
+                <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
+                <xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
+                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <tr valign="top">
+                        <th>Tests</th>
+                        <th>Failures</th>
+                        <th>Errors</th>
+                        <th>Skipped</th>
+                        <th>Success rate</th>
+                        <th>Time</th>
+                    </tr>
+                    <tr valign="top">
+                        <xsl:attribute name="class">
+                            <xsl:choose>
+                                <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
+                                <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
+                                <xsl:otherwise>Pass</xsl:otherwise>
+                            </xsl:choose>
+                        </xsl:attribute>
+                        <td><a title="Display all tests" href="all-tests.html"><xsl:value-of select="$testCount"/></a></td>
+                        <td><a title="Display all failures" href="alltests-fails.html"><xsl:value-of select="$failureCount"/></a></td>
+                        <td><a title="Display all errors" href="alltests-errors.html"><xsl:value-of select="$errorCount"/></a></td>
+                        <td><a title="Display all skipped test" href="alltests-skipped.html"><xsl:value-of select="$skippedCount" /></a></td>
+                        <td>
+                            <xsl:call-template name="display-percent">
+                                <xsl:with-param name="value" select="$successRate"/>
+                            </xsl:call-template>
+                        </td>
+                        <td>
+                            <xsl:call-template name="display-time">
+                                <xsl:with-param name="value" select="$timeCount"/>
+                            </xsl:call-template>
+                        </td>
+                    </tr>
+                </table>
+                <table border="0" width="95%">
+                    <tr>
+                        <td style="text-align: justify;">
+                            Note: <em>failures</em> are anticipated and checked for with assertions while <em>errors</em> are unanticipated.
+                        </td>
+                    </tr>
+                </table>
+
+                <h2>Packages</h2>
+                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <xsl:call-template name="testsuite.test.header"/>
+                    <xsl:for-each select="testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+                        <xsl:sort select="@package" order="ascending"/>
+                        <!-- get the node set containing all testsuites that have the same package -->
+                        <xsl:variable name="insamepackage" select="/testsuites/testsuite[./@package = current()/@package]"/>
+                        <tr valign="top">
+                            <!-- display a failure if there is any failure/error in the package -->
+                            <xsl:attribute name="class">
+                                <xsl:choose>
+                                    <xsl:when test="sum($insamepackage/@errors) &gt; 0">Error</xsl:when>
+                                    <xsl:when test="sum($insamepackage/@failures) &gt; 0">Failure</xsl:when>
+                                    <xsl:otherwise>Pass</xsl:otherwise>
+                                </xsl:choose>
+                            </xsl:attribute>
+                            <td><a href="./{translate(@package,'.','/')}/package-summary.html">
+                                <xsl:value-of select="@package"/>
+                                <xsl:if test="@package = ''">&lt;none&gt;</xsl:if>
+                            </a></td>
+                            <td><xsl:value-of select="sum($insamepackage/@tests)"/></td>
+                            <td><xsl:value-of select="sum($insamepackage/@errors)"/></td>
+                            <td><xsl:value-of select="sum($insamepackage/@failures)"/></td>
+                            <td><xsl:value-of select="sum($insamepackage/@skipped)" /></td>
+                            <td>
+                                <xsl:call-template name="display-time">
+                                    <xsl:with-param name="value" select="sum($insamepackage/@time)"/>
+                                </xsl:call-template>
+                            </td>
+                            <td><xsl:value-of select="$insamepackage/@timestamp"/></td>
+                            <td><xsl:value-of select="$insamepackage/@hostname"/></td>
+                        </tr>
+                    </xsl:for-each>
+                </table>
+            </body>
+        </html>
+    </xsl:template>
+
+
+    <xsl:template name="package.summary">
+        <xsl:param name="name"/>
+        <html>
+            <head>
+                <xsl:call-template name="create.stylesheet.link">
+                    <xsl:with-param name="package.name" select="$name"/>
+                </xsl:call-template>
+            </head>
+            <body>
+                <xsl:attribute name="onload">open('package-frame.html','classListFrame')</xsl:attribute>
+                <xsl:call-template name="pageHeader"/>
+                <h3>Package <xsl:value-of select="$name"/></h3>
+
+                <!--table border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <xsl:call-template name="class.metrics.header"/>
+                    <xsl:apply-templates select="." mode="print.metrics"/>
+                </table-->
+
+                <xsl:variable name="insamepackage" select="/testsuites/testsuite[./@package = $name]"/>
+                <xsl:if test="count($insamepackage) &gt; 0">
+                    <h2>Classes</h2>
+                    <p>
+                        <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                            <xsl:call-template name="testsuite.test.header"/>
+                            <xsl:apply-templates select="$insamepackage" mode="print.test">
+                                <xsl:sort select="@name"/>
+                            </xsl:apply-templates>
+                        </table>
+                    </p>
+                </xsl:if>
+            </body>
+        </html>
+    </xsl:template>
+
+
+    <!--
+        transform string like a.b.c to ../../../
+        @param path the path to transform into a descending directory path
+    -->
+    <xsl:template name="path">
+        <xsl:param name="path"/>
+        <xsl:if test="contains($path,'.')">
+            <xsl:text>../</xsl:text>
+            <xsl:call-template name="path">
+                <xsl:with-param name="path"><xsl:value-of select="substring-after($path,'.')"/></xsl:with-param>
+            </xsl:call-template>
+        </xsl:if>
+        <xsl:if test="not(contains($path,'.')) and not($path = '')">
+            <xsl:text>../</xsl:text>
+        </xsl:if>
+    </xsl:template>
+
+
+    <!-- create the link to the stylesheet based on the package name -->
+    <xsl:template name="create.stylesheet.link">
+        <xsl:param name="package.name"/>
+        <link rel="stylesheet" type="text/css" title="Style"><xsl:attribute name="href"><xsl:if test="not($package.name = 'unnamed package')"><xsl:call-template name="path"><xsl:with-param name="path" select="$package.name"/></xsl:call-template></xsl:if>stylesheet.css</xsl:attribute></link>
+    </xsl:template>
+
+
+    <!-- Page HEADER -->
+    <xsl:template name="pageHeader">
+        <h1><xsl:value-of select="$TITLE"/></h1>
+        <table width="100%">
+            <tr>
+                <td align="left"></td>
+                <td align="right">Designed for use with <a href="https://www.junit.org/">JUnit</a> and <a href="https://ant.apache.org/">Ant</a>.</td>
+            </tr>
+        </table>
+        <hr size="1"/>
+    </xsl:template>
+
+    <!-- class header -->
+    <xsl:template name="testsuite.test.header">
+        <tr valign="top">
+            <th width="80%">Name</th>
+            <th>Tests</th>
+            <th>Errors</th>
+            <th>Failures</th>
+            <th>Skipped</th>
+            <th nowrap="nowrap">Time(s)</th>
+            <th nowrap="nowrap">Time Stamp</th>
+            <th>Host</th>
+        </tr>
+    </xsl:template>
+
+    <!-- method header -->
+    <xsl:template name="testcase.test.header">
+        <xsl:param name="show.class" select="''"/>
+        <tr valign="top">
+            <xsl:if test="boolean($show.class)">
+                <th>Class</th>
+            </xsl:if>
+            <th>Name</th>
+            <th>Status</th>
+            <th width="80%">Type</th>
+            <th nowrap="nowrap">Time(s)</th>
+        </tr>
+    </xsl:template>
+
+
+    <!-- class information -->
+    <xsl:template match="testsuite" mode="print.test">
+        <tr valign="top">
+            <xsl:attribute name="class">
+                <xsl:choose>
+                    <xsl:when test="@errors[.&gt; 0]">Error</xsl:when>
+                    <xsl:when test="@failures[.&gt; 0]">Failure</xsl:when>
+                    <xsl:otherwise>Pass</xsl:otherwise>
+                </xsl:choose>
+            </xsl:attribute>
+            <td><a title="Display all tests" href="{@id}_{@name}.html"><xsl:value-of select="@name"/></a></td>
+            <td><a title="Display all tests" href="{@id}_{@name}.html"><xsl:apply-templates select="@tests"/></a></td>
+            <td>
+                <xsl:choose>
+                    <xsl:when test="@errors != 0">
+                        <a title="Display only errors" href="{@id}_{@name}-errors.html"><xsl:apply-templates select="@errors"/></a>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:apply-templates select="@errors"/>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </td>
+            <td>
+                <xsl:choose>
+                    <xsl:when test="@failures != 0">
+                        <a title="Display only failures" href="{@id}_{@name}-fails.html"><xsl:apply-templates select="@failures"/></a>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:apply-templates select="@failures"/>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </td>
+            <td>
+                <xsl:choose>
+                    <xsl:when test="@skipped != 0">
+                        <a title="Display only skipped tests" href="{@id}_{@name}-skipped.html"><xsl:apply-templates select="@skipped"/></a>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:apply-templates select="@skipped"/>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </td>
+            <td><xsl:call-template name="display-time">
+                <xsl:with-param name="value" select="@time"/>
+            </xsl:call-template>
+            </td>
+            <td><xsl:apply-templates select="@timestamp"/></td>
+            <td><xsl:apply-templates select="@hostname"/></td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template match="testcase" mode="print.test">
+        <xsl:param name="show.class" select="''"/>
+        <tr valign="top">
+            <xsl:attribute name="class">
+                <xsl:choose>
+                    <xsl:when test="error">Error</xsl:when>
+                    <xsl:when test="failure">Failure</xsl:when>
+                    <xsl:otherwise>TableRowColor</xsl:otherwise>
+                </xsl:choose>
+            </xsl:attribute>
+            <xsl:variable name="class.href">
+                <xsl:value-of select="concat(translate(../@package,'.','/'), '/', ../@id, '_', ../@name, '.html')"/>
+            </xsl:variable>
+            <xsl:if test="boolean($show.class)">
+                <td><a href="{$class.href}"><xsl:value-of select="../@name"/></a></td>
+            </xsl:if>
+            <td>
+                <a name="{@name}"/>
+                <xsl:choose>
+                    <xsl:when test="boolean($show.class)">
+                        <a href="{concat($class.href, '#', @name)}"><xsl:value-of select="@name"/></a>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:value-of select="@name"/>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </td>
+            <xsl:choose>
+                <xsl:when test="failure">
+                    <td>Failure</td>
+                    <td><xsl:apply-templates select="failure"/></td>
+                </xsl:when>
+                <xsl:when test="error">
+                    <td>Error</td>
+                    <td><xsl:apply-templates select="error"/></td>
+                </xsl:when>
+                <xsl:when test="skipped">
+                    <td>Skipped</td>
+                    <td><xsl:apply-templates select="skipped"/></td>
+                </xsl:when>
+                <xsl:otherwise>
+                    <td>Success</td>
+                    <td></td>
+                </xsl:otherwise>
+            </xsl:choose>
+            <td>
+                <xsl:call-template name="display-time">
+                    <xsl:with-param name="value" select="@time"/>
+                </xsl:call-template>
+            </td>
+        </tr>
+    </xsl:template>
+
+
+    <!-- Note : the below template skipped, error and failure are the same style
+                so just call the same style store in the toolkit template -->
+    <xsl:template match="failure">
+        <xsl:call-template name="display-failures"/>
+    </xsl:template>
+
+    <xsl:template match="error">
+        <xsl:call-template name="display-failures"/>
+    </xsl:template>
+
+    <xsl:template match="skipped">
+        <xsl:call-template name="display-failures"/>
+    </xsl:template>
+
+    <!-- Style for the error and failure in the testcase template -->
+    <xsl:template name="display-failures">
+        <xsl:choose>
+            <xsl:when test="not(@message)">N/A</xsl:when>
+            <xsl:otherwise>
+                <xsl:value-of select="@message"/>
+            </xsl:otherwise>
+        </xsl:choose>
+        <!-- display the stacktrace -->
+        <br/><br/>
+        <code>
+            <xsl:call-template name="br-replace">
+                <xsl:with-param name="word" select="."/>
+            </xsl:call-template>
+        </code>
+        <!-- the latter is better but might be problematic for non-21" monitors... -->
+        <!--pre><xsl:value-of select="."/></pre-->
+    </xsl:template>
+
+    <xsl:template name="JS-escape">
+        <xsl:param name="string"/>
+        <xsl:variable name="tmp1" select="replace($string,'\\','\\\\')"/>
+        <xsl:variable name="tmp2" select="replace($tmp1,&quot;'&quot;,&quot;\\&apos;&quot;)"/>
+        <xsl:variable name="tmp3" select="replace($tmp2,&quot;&#10;&quot;,'\\n')"/>
+        <xsl:variable name="tmp4" select="replace($tmp3,&quot;&#13;&quot;,'\\r')"/>
+        <xsl:value-of select="$tmp4"/>
+    </xsl:template>
+
+
+    <!--
+        template that will convert a carriage return into a br tag
+        @param word the text from which to convert CR to BR tag
+    -->
+    <xsl:template name="br-replace">
+        <xsl:param name="word"/>
+        <xsl:param name="splitlimit">32</xsl:param>
+        <xsl:variable name="secondhalfstartindex" select="(string-length($word)+(string-length($word) mod 2)) div 2"/>
+        <xsl:variable name="secondhalfword" select="substring($word, $secondhalfstartindex)"/>
+        <!-- When word is very big, a recursive replace is very heap/stack expensive, so subdivide on line break after middle of string -->
+        <xsl:choose>
+            <xsl:when test="(string-length($word) > $splitlimit) and (contains($secondhalfword, '&#xa;'))">
+                <xsl:variable name="secondhalfend" select="substring-after($secondhalfword, '&#xa;')"/>
+                <xsl:variable name="firsthalflen" select="string-length($word) - string-length($secondhalfword)"/>
+                <xsl:variable name="firsthalfword" select="substring($word, 1, $firsthalflen)"/>
+                <xsl:variable name="firsthalfend" select="substring-before($secondhalfword, '&#xa;')"/>
+                <xsl:call-template name="br-replace">
+                    <xsl:with-param name="word" select="concat($firsthalfword,$firsthalfend)"/>
+                </xsl:call-template>
+                <br/>
+                <xsl:call-template name="br-replace">
+                    <xsl:with-param name="word" select="$secondhalfend"/>
+                </xsl:call-template>
+            </xsl:when>
+            <xsl:when test="contains($word, '&#xa;')">
+                <xsl:value-of select="substring-before($word, '&#xa;')"/>
+                <br/>
+                <xsl:call-template name="br-replace">
+                    <xsl:with-param name="word" select="substring-after($word, '&#xa;')"/>
+                </xsl:call-template>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:value-of select="$word"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="display-time">
+        <xsl:param name="value"/>
+        <xsl:value-of select="format-number($value,'0.000')"/>
+    </xsl:template>
+
+    <xsl:template name="display-percent">
+        <xsl:param name="value"/>
+        <xsl:value-of select="format-number($value,'0.00%')"/>
+    </xsl:template>
+
+    <xsl:template match="testsuite" mode="alltests.error.row">
+      <xsl:variable name="package.dir">
+        <xsl:if test="not(@package = '')"><xsl:value-of select="translate(@package,'.','/')"/><xsl:text>/</xsl:text></xsl:if>
+      </xsl:variable>
+      <xsl:variable name="class.href">
+        <xsl:value-of select="concat($package.dir, @id, '_', @name, '.html')"/>
+      </xsl:variable>
+      <tr class="Error">
+        <td><a href="{$class.href}"><xsl:value-of select="@name"/></a></td>
+        <td colspan="3"><xsl:apply-templates select="./error"/></td>
+      </tr>
+    </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/etc/junit-frames-xalan1.xsl b/src/etc/junit-frames-xalan1.xsl
index fbc28e1..bc41a7c 100644
--- a/src/etc/junit-frames-xalan1.xsl
+++ b/src/etc/junit-frames-xalan1.xsl
@@ -3,6 +3,7 @@
     xmlns:lxslt="http://xml.apache.org/xslt"
     xmlns:redirect="org.apache.xalan.lib.Redirect"
     xmlns:string="xalan://java.lang.String"
+    xmlns:stringutils="xalan://org.apache.tools.ant.util.StringUtils"
     extension-element-prefixes="redirect">
 <xsl:output method="html" indent="yes" encoding="UTF-8"/>
 <xsl:decimal-format decimal-separator="." grouping-separator=","/>
@@ -14,7 +15,7 @@
    (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
+       https://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,
@@ -443,7 +444,7 @@
         <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
         <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
         <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
-        <xsl:variable name="skippedCount" select="sum(testsuite/@skipped)"/>
+        <xsl:variable name="skipCount" select="sum(testsuite/@skipped)"/>
         <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
         <xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
         <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
@@ -592,7 +593,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href="http://www.junit.org/">JUnit</a> and <a href="http://ant.apache.org/">Ant</a>.</td>
+        <td align="right">Designed for use with <a href="https://www.junit.org/">JUnit</a> and <a href="https://ant.apache.org/">Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/etc/junit-frames.xsl b/src/etc/junit-frames.xsl
index 49fc667..732e040 100644
--- a/src/etc/junit-frames.xsl
+++ b/src/etc/junit-frames.xsl
@@ -14,7 +14,7 @@
    (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
+       https://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,
@@ -742,7 +742,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href="http://www.junit.org/">JUnit</a> and <a href="http://ant.apache.org/">Ant</a>.</td>
+        <td align="right">Designed for use with <a href="https://www.junit.org/">JUnit</a> and <a href="https://ant.apache.org/">Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/etc/junit-noframes-saxon.xsl b/src/etc/junit-noframes-saxon.xsl
new file mode 100644
index 0000000..ce7efb8
--- /dev/null
+++ b/src/etc/junit-noframes-saxon.xsl
@@ -0,0 +1,549 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    exclude-result-prefixes="xs"
+    version="2.0">
+    <xsl:character-map name="no-control-characters">
+        <xsl:output-character character="&#127;" string="&amp;#127;"/>
+        <xsl:output-character character="&#128;" string="&amp;#128;"/>
+        <xsl:output-character character="&#129;" string="&amp;#129;"/>
+        <xsl:output-character character="&#130;" string="&amp;#130;"/>
+        <xsl:output-character character="&#131;" string="&amp;#131;"/>
+        <xsl:output-character character="&#132;" string="&amp;#132;"/>
+        <xsl:output-character character="&#133;" string="&amp;#133;"/>
+        <xsl:output-character character="&#134;" string="&amp;#134;"/>
+        <xsl:output-character character="&#135;" string="&amp;#135;"/>
+        <xsl:output-character character="&#136;" string="&amp;#136;"/>
+        <xsl:output-character character="&#137;" string="&amp;#137;"/>
+        <xsl:output-character character="&#138;" string="&amp;#138;"/>
+        <xsl:output-character character="&#139;" string="&amp;#139;"/>
+        <xsl:output-character character="&#140;" string="&amp;#140;"/>
+        <xsl:output-character character="&#141;" string="&amp;#141;"/>
+        <xsl:output-character character="&#142;" string="&amp;#142;"/>
+        <xsl:output-character character="&#143;" string="&amp;#143;"/>
+        <xsl:output-character character="&#144;" string="&amp;#144;"/>
+        <xsl:output-character character="&#145;" string="&amp;#145;"/>
+        <xsl:output-character character="&#146;" string="&amp;#146;"/>
+        <xsl:output-character character="&#147;" string="&amp;#147;"/>
+        <xsl:output-character character="&#148;" string="&amp;#148;"/>
+        <xsl:output-character character="&#149;" string="&amp;#149;"/>
+        <xsl:output-character character="&#150;" string="&amp;#150;"/>
+        <xsl:output-character character="&#151;" string="&amp;#151;"/>
+        <xsl:output-character character="&#152;" string="&amp;#152;"/>
+        <xsl:output-character character="&#153;" string="&amp;#153;"/>
+        <xsl:output-character character="&#154;" string="&amp;#154;"/>
+        <xsl:output-character character="&#155;" string="&amp;#155;"/>
+        <xsl:output-character character="&#156;" string="&amp;#156;"/>
+        <xsl:output-character character="&#157;" string="&amp;#157;"/>
+        <xsl:output-character character="&#158;" string="&amp;#158;"/>
+        <xsl:output-character character="&#159;" string="&amp;#159;"/>
+    </xsl:character-map>
+<xsl:output method="html" indent="yes" encoding="UTF-8" use-character-maps="no-control-characters"
+  doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
+<xsl:decimal-format decimal-separator="." grouping-separator="," />
+<!--
+   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
+
+       https://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.
+ -->
+
+<xsl:param name="TITLE">Unit Test Results.</xsl:param>
+
+<!--
+
+ Sample stylesheet to be used with Ant JUnitReport output.
+
+ It creates a non-framed report that can be useful to send via
+ e-mail or such.
+
+-->
+<xsl:template match="testsuites">
+    <html>
+        <head>
+            <title><xsl:value-of select="$TITLE"/></title>
+    <style type="text/css">
+      body {
+        font:normal 68% verdana,arial,helvetica;
+        color:#000000;
+      }
+      table tr td, table tr th {
+          font-size: 68%;
+      }
+      table.details tr th{
+        font-weight: bold;
+        text-align:left;
+        background:#a6caf0;
+      }
+      table.details tr td{
+        background:#eeeee0;
+      }
+
+      p {
+        line-height:1.5em;
+        margin-top:0.5em; margin-bottom:1.0em;
+      }
+      h1 {
+        margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
+      }
+      h2 {
+        margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
+      }
+      h3 {
+        margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
+      }
+      h4 {
+        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+      }
+      h5 {
+        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+      }
+      h6 {
+        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+      }
+      .Error {
+        font-weight:bold; color:red;
+      }
+      .Failure {
+        font-weight:bold; color:purple;
+      }
+      .Properties {
+        text-align:right;
+      }
+      </style>
+      <script type="text/javascript" language="JavaScript">
+        var TestCases = new Array();
+        var cur;
+        <xsl:for-each select="./testsuite">
+            <xsl:apply-templates select="properties"/>
+        </xsl:for-each>
+
+       </script>
+       <script type="text/javascript" language="JavaScript"><![CDATA[
+        function displayProperties (name) {
+          var win = window.open('','JUnitSystemProperties','scrollbars=1,resizable=1');
+          var doc = win.document;
+          doc.open();
+          doc.write("<html><head><title>Properties of " + name + "</title>");
+          doc.write("<style>")
+          doc.write("body {font:normal 68% verdana,arial,helvetica; color:#000000; }");
+          doc.write("table tr td, table tr th { font-size: 68%; }");
+          doc.write("table.properties { border-collapse:collapse; border-left:solid 1 #cccccc; border-top:solid 1 #cccccc; padding:5px; }");
+          doc.write("table.properties th { text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#eeeeee; }");
+          doc.write("table.properties td { font:normal; text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#fffffff; }");
+          doc.write("h3 { margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica }");
+          doc.write("</style>");
+          doc.write("</head><body>");
+          doc.write("<h3>Properties of " + name + "</h3>");
+          doc.write("<div align=\"right\"><a href=\"javascript:window.close();\">Close</a></div>");
+          doc.write("<table class='properties'>");
+          doc.write("<tr><th>Name</th><th>Value</th></tr>");
+          for (prop in TestCases[name]) {
+            doc.write("<tr><th>" + prop + "</th><td>" + TestCases[name][prop] + "</td></tr>");
+          }
+          doc.write("</table>");
+          doc.write("</body></html>");
+          doc.close();
+          win.focus();
+        }
+      ]]>
+      </script>
+        </head>
+        <body>
+            <a name="top"></a>
+            <xsl:call-template name="pageHeader"/>
+
+            <!-- Summary part -->
+            <xsl:call-template name="summary"/>
+            <hr size="1" width="95%" align="left"/>
+
+            <!-- Package List part -->
+            <xsl:call-template name="packagelist"/>
+            <hr size="1" width="95%" align="left"/>
+
+            <!-- For each package create its part -->
+            <xsl:call-template name="packages"/>
+            <hr size="1" width="95%" align="left"/>
+
+            <!-- For each class create the  part -->
+            <xsl:call-template name="classes"/>
+
+        </body>
+    </html>
+</xsl:template>
+
+
+
+    <!-- ================================================================== -->
+    <!-- Write a list of all packages with an hyperlink to the anchor of    -->
+    <!-- of the package name.                                               -->
+    <!-- ================================================================== -->
+    <xsl:template name="packagelist">
+        <h2>Packages</h2>
+        Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.
+        <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+            <xsl:call-template name="testsuite.test.header"/>
+            <!-- list all packages recursively -->
+            <xsl:for-each select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+                <xsl:sort select="@package"/>
+                <xsl:variable name="testsuites-in-package" select="/testsuites/testsuite[./@package = current()/@package]"/>
+                <xsl:variable name="testCount" select="sum($testsuites-in-package/@tests)"/>
+                <xsl:variable name="errorCount" select="sum($testsuites-in-package/@errors)"/>
+                <xsl:variable name="failureCount" select="sum($testsuites-in-package/@failures)"/>
+                <xsl:variable name="skippedCount" select="sum($testsuites-in-package/@skipped)" />
+                <xsl:variable name="timeCount" select="sum($testsuites-in-package/@time)"/>
+
+                <!-- write a summary for the package -->
+                <tr valign="top">
+                    <!-- set a nice color depending if there is an error/failure -->
+                    <xsl:attribute name="class">
+                        <xsl:choose>
+                            <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
+                            <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
+                        </xsl:choose>
+                    </xsl:attribute>
+                    <td><a href="#{@package}"><xsl:value-of select="@package"/></a></td>
+                    <td><xsl:value-of select="$testCount"/></td>
+                    <td><xsl:value-of select="$errorCount"/></td>
+                    <td><xsl:value-of select="$failureCount"/></td>
+                    <td><xsl:value-of select="$skippedCount" /></td>
+                    <td>
+                    <xsl:call-template name="display-time">
+                        <xsl:with-param name="value" select="$timeCount"/>
+                    </xsl:call-template>
+                    </td>
+                    <td><xsl:value-of select="$testsuites-in-package/@timestamp"/></td>
+                    <td><xsl:value-of select="$testsuites-in-package/@hostname"/></td>
+                </tr>
+            </xsl:for-each>
+        </table>
+    </xsl:template>
+
+
+    <!-- ================================================================== -->
+    <!-- Write a package level report                                       -->
+    <!-- It creates a table with values from the document:                  -->
+    <!-- Name | Tests | Errors | Failures | Time                            -->
+    <!-- ================================================================== -->
+    <xsl:template name="packages">
+        <!-- create an anchor to this package name -->
+        <xsl:for-each select="/testsuites/testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+            <xsl:sort select="@package"/>
+                <a name="{@package}"></a>
+                <h3>Package <xsl:value-of select="@package"/></h3>
+
+                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+                    <xsl:call-template name="testsuite.test.header"/>
+
+                    <!-- match the testsuites of this package -->
+                    <xsl:apply-templates select="/testsuites/testsuite[./@package = current()/@package]" mode="print.test"/>
+                </table>
+                <a href="#top">Back to top</a>
+                <p/>
+                <p/>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="classes">
+        <xsl:for-each select="testsuite">
+            <xsl:sort select="@name"/>
+            <!-- create an anchor to this class name -->
+            <a name="{@name}"></a>
+            <h3>TestCase <xsl:value-of select="@name"/></h3>
+
+            <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+              <xsl:call-template name="testcase.test.header"/>
+              <!--
+              test can even not be started at all (failure to load the class)
+              so report the error directly
+              -->
+                <xsl:if test="./error">
+                    <tr class="Error">
+                        <td colspan="4"><xsl:apply-templates select="./error"/></td>
+                    </tr>
+                </xsl:if>
+                <xsl:apply-templates select="./testcase" mode="print.test"/>
+            </table>
+            <div class="Properties">
+                <a>
+                    <xsl:attribute name="href">javascript:displayProperties('<xsl:value-of select="@package"/>.<xsl:value-of select="@name"/>');</xsl:attribute>
+                    Properties &#187;
+                </a>
+            </div>
+            <p/>
+
+            <a href="#top">Back to top</a>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="summary">
+        <h2>Summary</h2>
+        <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
+        <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
+        <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
+        <xsl:variable name="skippedCount" select="sum(testsuite/@skipped)" />
+        <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
+        <xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
+        <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+        <tr valign="top">
+            <th>Tests</th>
+            <th>Failures</th>
+            <th>Errors</th>
+            <th>Skipped</th>
+            <th>Success rate</th>
+            <th>Time</th>
+        </tr>
+        <tr valign="top">
+            <xsl:attribute name="class">
+                <xsl:choose>
+                    <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
+                    <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
+                </xsl:choose>
+            </xsl:attribute>
+            <td><xsl:value-of select="$testCount"/></td>
+            <td><xsl:value-of select="$failureCount"/></td>
+            <td><xsl:value-of select="$errorCount"/></td>
+            <td><xsl:value-of select="$skippedCount" /></td>
+            <td>
+                <xsl:call-template name="display-percent">
+                    <xsl:with-param name="value" select="$successRate"/>
+                </xsl:call-template>
+            </td>
+            <td>
+                <xsl:call-template name="display-time">
+                    <xsl:with-param name="value" select="$timeCount"/>
+                </xsl:call-template>
+            </td>
+
+        </tr>
+        </table>
+        <table border="0" width="95%">
+        <tr>
+        <td style="text-align: justify;">
+        Note: <i>failures</i> are anticipated and checked for with assertions while <i>errors</i> are unanticipated.
+        </td>
+        </tr>
+        </table>
+    </xsl:template>
+
+  <!--
+   Write properties into a JavaScript data structure.
+   This is based on the original idea by Erik Hatcher (ehatcher@apache.org)
+   -->
+  <xsl:template match="properties">
+    cur = TestCases['<xsl:value-of select="../@package"/>.<xsl:value-of select="../@name"/>'] = new Array();
+    <xsl:for-each select="property">
+    <xsl:sort select="@name"/>
+        cur['<xsl:value-of select="@name"/>'] = '<xsl:call-template name="JS-escape"><xsl:with-param name="string" select="@value"/></xsl:call-template>';
+    </xsl:for-each>
+  </xsl:template>
+
+<!-- Page HEADER -->
+<xsl:template name="pageHeader">
+    <h1><xsl:value-of select="$TITLE"/></h1>
+    <table width="100%">
+    <tr>
+        <td align="left"></td>
+        <td align="right">Designed for use with <a href='https://www.junit.org'>JUnit</a> and <a href='https://ant.apache.org/ant'>Ant</a>.</td>
+    </tr>
+    </table>
+    <hr size="1"/>
+</xsl:template>
+
+<xsl:template match="testsuite" mode="header">
+    <tr valign="top">
+        <th width="80%">Name</th>
+        <th>Tests</th>
+        <th>Errors</th>
+        <th>Failures</th>
+        <th>Skipped</th>
+        <th nowrap="nowrap">Time(s)</th>
+    </tr>
+</xsl:template>
+
+<!-- class header -->
+<xsl:template name="testsuite.test.header">
+    <tr valign="top">
+        <th width="80%">Name</th>
+        <th>Tests</th>
+        <th>Errors</th>
+        <th>Failures</th>
+        <th>Skipped</th>
+        <th nowrap="nowrap">Time(s)</th>
+        <th nowrap="nowrap">Time Stamp</th>
+        <th>Host</th>
+    </tr>
+</xsl:template>
+
+<!-- method header -->
+<xsl:template name="testcase.test.header">
+    <tr valign="top">
+        <th>Name</th>
+        <th>Status</th>
+        <th width="80%">Type</th>
+        <th nowrap="nowrap">Time(s)</th>
+    </tr>
+</xsl:template>
+
+
+<!-- class information -->
+<xsl:template match="testsuite" mode="print.test">
+    <tr valign="top">
+        <!-- set a nice color depending if there is an error/failure -->
+        <xsl:attribute name="class">
+            <xsl:choose>
+                <xsl:when test="@failures[.&gt; 0]">Failure</xsl:when>
+                <xsl:when test="@errors[.&gt; 0]">Error</xsl:when>
+            </xsl:choose>
+        </xsl:attribute>
+
+        <!-- print testsuite information -->
+        <td><a href="#{@name}"><xsl:value-of select="@name"/></a></td>
+        <td><xsl:value-of select="@tests"/></td>
+        <td><xsl:value-of select="@errors"/></td>
+        <td><xsl:value-of select="@failures"/></td>
+        <td><xsl:value-of select="@skipped" /></td>
+        <td>
+            <xsl:call-template name="display-time">
+                <xsl:with-param name="value" select="@time"/>
+            </xsl:call-template>
+        </td>
+        <td><xsl:apply-templates select="@timestamp"/></td>
+        <td><xsl:apply-templates select="@hostname"/></td>
+    </tr>
+</xsl:template>
+
+<xsl:template match="testcase" mode="print.test">
+    <tr valign="top">
+        <xsl:attribute name="class">
+            <xsl:choose>
+                <xsl:when test="failure | error">Error</xsl:when>
+            </xsl:choose>
+        </xsl:attribute>
+        <td><xsl:value-of select="@name"/></td>
+        <xsl:choose>
+            <xsl:when test="failure">
+                <td>Failure</td>
+                <td><xsl:apply-templates select="failure"/></td>
+            </xsl:when>
+            <xsl:when test="error">
+                <td>Error</td>
+                <td><xsl:apply-templates select="error"/></td>
+            </xsl:when>
+            <xsl:when test="skipped">
+            	<td>Skipped</td>
+            	<td><xsl:apply-templates select="skipped"/></td>
+            </xsl:when>
+            <xsl:otherwise>
+                <td>Success</td>
+                <td></td>
+            </xsl:otherwise>
+        </xsl:choose>
+        <td>
+            <xsl:call-template name="display-time">
+                <xsl:with-param name="value" select="@time"/>
+            </xsl:call-template>
+        </td>
+    </tr>
+</xsl:template>
+
+
+<xsl:template match="failure">
+    <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<xsl:template match="error">
+    <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<xsl:template match="skipped">
+    <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<!-- Style for the error, failure and skipped in the testcase template -->
+<xsl:template name="display-failures">
+    <xsl:choose>
+        <xsl:when test="not(@message)">N/A</xsl:when>
+        <xsl:otherwise>
+            <xsl:value-of select="@message"/>
+        </xsl:otherwise>
+    </xsl:choose>
+    <!-- display the stacktrace -->
+    <code>
+        <br/><br/>
+        <xsl:call-template name="br-replace">
+            <xsl:with-param name="word" select="."/>
+        </xsl:call-template>
+    </code>
+    <!-- the later is better but might be problematic for non-21" monitors... -->
+    <!--pre><xsl:value-of select="."/></pre-->
+</xsl:template>
+
+<xsl:template name="JS-escape">
+    <xsl:param name="string"/>
+    <xsl:variable name="tmp1" select="replace($string,'\\','\\\\')"/>
+    <xsl:variable name="tmp2" select="replace($tmp1,&quot;'&quot;,&quot;\\&apos;&quot;)"/>
+    <xsl:variable name="tmp3" select="replace($tmp2,&quot;&#10;&quot;,'\\n')"/>
+    <xsl:variable name="tmp4" select="replace($tmp3,&quot;&#13;&quot;,'\\r')"/>
+    <xsl:value-of select="$tmp4"/>
+</xsl:template>
+
+
+<!--
+    template that will convert a carriage return into a br tag
+    @param word the text from which to convert CR to BR tag
+-->
+<xsl:template name="br-replace">
+    <xsl:param name="word"/>
+    <xsl:param name="splitlimit">32</xsl:param>
+    <xsl:variable name="secondhalfstartindex" select="(string-length($word)+(string-length($word) mod 2)) div 2"/>
+    <xsl:variable name="secondhalfword" select="substring($word, $secondhalfstartindex)"/>
+    <!-- When word is very big, a recursive replace is very heap/stack expensive, so subdivide on line break after middle of string -->
+    <xsl:choose>
+      <xsl:when test="(string-length($word) > $splitlimit) and (contains($secondhalfword, '&#xa;'))">
+        <xsl:variable name="secondhalfend" select="substring-after($secondhalfword, '&#xa;')"/>
+        <xsl:variable name="firsthalflen" select="string-length($word) - string-length($secondhalfword)"/>
+        <xsl:variable name="firsthalfword" select="substring($word, 1, $firsthalflen)"/>
+        <xsl:variable name="firsthalfend" select="substring-before($secondhalfword, '&#xa;')"/>
+        <xsl:call-template name="br-replace">
+          <xsl:with-param name="word" select="concat($firsthalfword,$firsthalfend)"/>
+        </xsl:call-template>
+        <br/>
+        <xsl:call-template name="br-replace">
+          <xsl:with-param name="word" select="$secondhalfend"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:when test="contains($word, '&#xa;')">
+        <xsl:value-of select="substring-before($word, '&#xa;')"/>
+        <br/>
+        <xsl:call-template name="br-replace">
+          <xsl:with-param name="word" select="substring-after($word, '&#xa;')"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$word"/>
+      </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+<xsl:template name="display-time">
+    <xsl:param name="value"/>
+    <xsl:value-of select="format-number($value,'0.000')"/>
+</xsl:template>
+
+<xsl:template name="display-percent">
+    <xsl:param name="value"/>
+    <xsl:value-of select="format-number($value,'0.00%')"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/etc/junit-noframes.xsl b/src/etc/junit-noframes.xsl
index fa3ac3e..0d03eb3 100644
--- a/src/etc/junit-noframes.xsl
+++ b/src/etc/junit-noframes.xsl
@@ -13,7 +13,7 @@
    (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
+       https://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,
@@ -318,7 +318,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href='http://www.junit.org'>JUnit</a> and <a href='http://ant.apache.org/ant'>Ant</a>.</td>
+        <td align="right">Designed for use with <a href='https://www.junit.org'>JUnit</a> and <a href='https://ant.apache.org/ant'>Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/etc/log.xsl b/src/etc/log.xsl
index 5040993..9fe60fb 100644
--- a/src/etc/log.xsl
+++ b/src/etc/log.xsl
@@ -9,7 +9,7 @@
    (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
+       https://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,
@@ -109,12 +109,12 @@
     <table border="0" cellpadding="0" cellspacing="0" width="100%">
     <tr>
       <td valign="top" class="bannercell">
-        <a href="http://jakarta.apache.org/">
-        <img src="http://jakarta.apache.org/images/jakarta-logo.gif" alt="http://jakarta.apache.org" align="left" border="0"/>
+        <a href="https://ant.apache.org/">
+        <img src="https://ant.apache.org/images/group-logo.gif" alt="https://ant.apache.org" align="left" border="0"/>
         </a>
       </td>
       <td style="text-align:right;vertical-align:bottom">
-        <a href="http://ant.apache.org/">Apache Ant</a>
+        <a href="https://ant.apache.org/">Apache Ant</a>
       </td>
     </tr>
     </table>
diff --git a/src/etc/manifest b/src/etc/manifest
deleted file mode 100644
index 758bc0f..0000000
--- a/src/etc/manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-Manifest-Version: 1.0
-Main-Class: org.apache.tools.ant.Main
-
-
diff --git a/src/etc/maudit-frames.xsl b/src/etc/maudit-frames.xsl
index c81f8dc..aa36b38 100644
--- a/src/etc/maudit-frames.xsl
+++ b/src/etc/maudit-frames.xsl
@@ -13,7 +13,7 @@
    (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
+       https://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,
@@ -343,11 +343,11 @@
         <td style="text-align: justify;">
         Note: Rules checked have originated from style guidelines suggested by the language designers,
         experience from the Java development community and insite experience. Violations are generally
-        reported with a reference to the <a href="http://java.sun.com/docs/books/jls/second_edition/html/jTOC.doc.html">Java Language Specifications</a> (JLS x.x.x)
+        reported with a reference to the <a href="https://docs.oracle.com/javase/specs/">Java Language Specifications</a> (JLS x.x.x)
         and Metamata Audit rules (x.x).
         Please consult these documents for additional information about violations.
         <p/>
-        Rules checked also enforce adherence to <a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html">Sun Java coding guidelines</a> in use at Jakarta.
+        Rules checked also enforce adherence to <a href="https://www.oracle.com/technetwork/java/codeconvtoc-136057.html">Sun Java coding guidelines</a> in use at Jakarta.
         <p/>
         One should note that these violations do not necessary underline errors but should be used
         as an indication for <i>possible</i> errors. As always, use your best judgment and review
@@ -438,14 +438,14 @@
   <table border="0" cellpadding="0" cellspacing="0" width="100%">
   <tr>
     <td class="bannercell" rowspan="2">
-      <a href="http://jakarta.apache.org/">
-      <img src="http://jakarta.apache.org/images/jakarta-logo.gif" alt="http://jakarta.apache.org" align="left" border="0"/>
+      <a href="https://ant.apache.org/">
+      <img src="https://ant.apache.org/images/group-logo.gif" alt="https://ant.apache.org" align="left" border="0"/>
       </a>
     </td>
         <td style="text-align:right"><h2>Source Code Audit</h2></td>
         </tr>
         <tr>
-        <td style="text-align:right">Designed for use with <a href='http://www.webgain.com/products/quality_analyzer/'>Webgain QA/Metamata Audit</a> and <a href='http://jakarta.apache.org'>Ant</a>.</td>
+        <td style="text-align:right">Designed for use with Webgain QA/Metamata Audit and <a href='https://ant.apache.org'>Ant</a>.</td>
         </tr>
   </table>
     <hr size="1"/>
diff --git a/src/etc/mmetrics-frames.xsl b/src/etc/mmetrics-frames.xsl
index 2b0f6b8..02616bd 100644
--- a/src/etc/mmetrics-frames.xsl
+++ b/src/etc/mmetrics-frames.xsl
@@ -15,7 +15,7 @@
    (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
+       https://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,
@@ -782,14 +782,14 @@
   <table border="0" cellpadding="0" cellspacing="0" width="100%">
   <tr>
     <td class="bannercell" rowspan="2">
-      <a href="http://jakarta.apache.org/">
-      <img src="http://jakarta.apache.org/images/jakarta-logo.gif" alt="http://jakarta.apache.org" align="left" border="0"/>
+      <a href="https://ant.apache.org/">
+      <img src="https://ant.apache.org/images/group-logo.gif" alt="https://ant.apache.org" align="left" border="0"/>
       </a>
     </td>
     <td style="text-align:right"><h2>Source Code Metrics</h2></td>
     </tr>
     <tr>
-    <td style="text-align:right">Designed for use with <a href='http://www.webgain.com/products/quality_analyzer/'>Webgain QA/Metamata Metrics</a> and <a href='http://jakarta.apache.org'>Ant</a>.</td>
+    <td style="text-align:right">Designed for use with Webgain QA/Metamata Metrics and <a href='https://ant.apache.org'>Ant</a>.</td>
     </tr>
   </table>
   <hr size="1"/>
diff --git a/src/etc/performance/build.xml b/src/etc/performance/build.xml
index c3e3ed9..f5f20f9 100644
--- a/src/etc/performance/build.xml
+++ b/src/etc/performance/build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/performance/dirscanner.xml b/src/etc/performance/dirscanner.xml
index 5628a46..4573831 100644
--- a/src/etc/performance/dirscanner.xml
+++ b/src/etc/performance/dirscanner.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -67,7 +67,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/poms/README.txt b/src/etc/poms/README.txt
index 26fc1b5..d282a6b 100644
--- a/src/etc/poms/README.txt
+++ b/src/etc/poms/README.txt
@@ -46,4 +46,4 @@
 REFERENCES :
 
 about skipping tests :
-http://maven.apache.org/plugins/maven-surefire-plugin/examples/skipping-test.html
+https://maven.apache.org/plugins/maven-surefire-plugin/examples/skipping-test.html
diff --git a/src/etc/poms/ant-antlr/pom.xml b/src/etc/poms/ant-antlr/pom.xml
index 87e3c8c..5698168 100644
--- a/src/etc/poms/ant-antlr/pom.xml
+++ b/src/etc/poms/ant-antlr/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,22 +18,22 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-antlr</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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,15 +41,14 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <optional>true</optional>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <!-- add a dependency with antlr 2.7.2 consistent with libraries.properties antlr 2.7.6 is also available on ibiblio-->
       <groupId>antlr</groupId>
       <artifactId>antlr</artifactId>
-      <version>2.7.2</version>
+      <version>2.7.7</version>
       <optional>true</optional>
       <scope>runtime</scope>
     </dependency>
@@ -63,11 +62,52 @@
           <includes>
             <include>org/apache/tools/ant/taskdefs/optional/ANTLR*</include>
           </includes>
+          <testIncludes>
+            <include>org/apache/tools/ant/taskdefs/optional/ANTLR*</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
         </configuration>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-apache-bcel/pom.xml b/src/etc/poms/ant-apache-bcel/pom.xml
index 554643e..f271feb 100644
--- a/src/etc/poms/ant-apache-bcel/pom.xml
+++ b/src/etc/poms/ant-apache-bcel/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,34 +18,34 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-bcel</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant + BCEL</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>bcel</groupId>
+      <groupId>org.apache.bcel</groupId>
       <artifactId>bcel</artifactId>
-      <version>5.1</version>
+      <version>6.5.0</version>
       <scope>compile</scope>
     </dependency>
   </dependencies>
@@ -59,11 +59,52 @@
             <include>org/apache/tools/ant/filters/util/JavaClassHelper*</include>
             <include>org/apache/tools/ant/util/depend/bcel/*</include>
           </includes>
+          <testIncludes>
+            <exclude>org/apache/tools/ant/types/optional/depend/ClassFileSet*</exclude>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
         </configuration>
       </plugin>
     </plugins>
+      <resources>
+          <resource>
+              <directory>../../../..</directory>
+              <targetPath>META-INF</targetPath>
+              <includes>
+                  <include>LICENSE</include>
+                  <include>NOTICE</include>
+              </includes>
+          </resource>
+      </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-apache-bsf/pom.xml b/src/etc/poms/ant-apache-bsf/pom.xml
index 399a41a..24add86 100644
--- a/src/etc/poms/ant-apache-bsf/pom.xml
+++ b/src/etc/poms/ant-apache-bsf/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,28 +18,28 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-bsf</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant + BSF</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -56,15 +56,36 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <includes>
-            <include>org/apache/tools/ant/taskdefs/optional/Script*</include>
-            <include>org/apache/tools/ant/taskdefs/optional/script/**</include>
-            <include>org/apache/tools/ant/types/optional/*Script*</include>
-            <include>org/apache/tools/ant/util/Script*</include>
-            <include>org/apache/tools/ant/util/optional/Script*</include>
+            <include>org/apache/tools/ant/util/ScriptRunner.java</include>
+            <include>org/apache/tools/ant/util/optional/ScriptRunner.java</include>
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-apache-log4j/pom.xml b/src/etc/poms/ant-apache-log4j/pom.xml
index 33262ee..2b9b783 100644
--- a/src/etc/poms/ant-apache-log4j/pom.xml
+++ b/src/etc/poms/ant-apache-log4j/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,27 +18,27 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-log4j</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant + Log4J</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -59,7 +59,31 @@
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-apache-oro/pom.xml b/src/etc/poms/ant-apache-oro/pom.xml
index fb37437..1126d81 100644
--- a/src/etc/poms/ant-apache-oro/pom.xml
+++ b/src/etc/poms/ant-apache-oro/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,28 +18,28 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-oro</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant + Apache Oro</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -48,12 +48,6 @@
       <version>2.0.8</version>
       <scope>compile</scope>
     </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.12</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -70,7 +64,31 @@
           </testIncludes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-apache-regexp/pom.xml b/src/etc/poms/ant-apache-regexp/pom.xml
index ed45f6c..1595857 100644
--- a/src/etc/poms/ant-apache-regexp/pom.xml
+++ b/src/etc/poms/ant-apache-regexp/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,27 +18,27 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-regexp</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant + Apache Regexp</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -57,11 +57,38 @@
           <includes>
             <include>org/apache/tools/ant/util/regexp/JakartaRegexp*</include>
           </includes>
+          <testIncludes>
+            <include>org/apache/tools/ant/util/regexp/JakartaRegexp*</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
         </configuration>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-apache-resolver/pom.xml b/src/etc/poms/ant-apache-resolver/pom.xml
index abc6dd3..c3ecb04 100644
--- a/src/etc/poms/ant-apache-resolver/pom.xml
+++ b/src/etc/poms/ant-apache-resolver/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,27 +18,27 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-resolver</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant + Apache Resolver</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -55,11 +55,35 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <includes>
-            <include>org/apache/tools/ant/types/resolver/**</include>
+            <include>org/apache/tools/ant/types/resolver/*.java</include>
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-apache-xalan2/pom.xml b/src/etc/poms/ant-apache-xalan2/pom.xml
index 1dc0e44..5f4ba16 100644
--- a/src/etc/poms/ant-apache-xalan2/pom.xml
+++ b/src/etc/poms/ant-apache-xalan2/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,28 +18,28 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-xalan2</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -52,41 +52,76 @@
   <build>
     <plugins>
       <plugin>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>create-timestamp-file</id>
-            <phase>generate-resources</phase>
-            <goals>
-              <goal>run</goal>
-            </goals>
-            <configuration>
-              <tasks>
-                <mkdir dir="${project.build.outputDirectory}"/>
-                <copy todir="${project.build.outputDirectory}/org/apache/tools/ant/taskdefs/optional/junit/xsl">
-                  <fileset dir="${project.build.sourceDirectory}/../etc">
-                    <include name="junit-frames.xsl"/>
-                    <include name="junit-noframes.xsl"/>
-                  </fileset>
-                </copy>              
-              </tasks>
-            </configuration>
-          </execution>
-
-        </executions>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <includes>
             <include>org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport*</include>
           </includes>
+          <testIncludes>
+            <include>org/apache/tools/ant/taskdefs/optional/TraXLiaison*</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>3.1.0</version>
+        <configuration>
+          <encoding>ISO-8859-1</encoding>
         </configuration>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
+    <testResources>
+      <testResource>
+        <directory>../../../../src/etc/testcases</directory>
+        <includes>
+          <include>taskdefs/optional/xalan*</include>
+          <include>taskdefs/optional/xsltliaison*</include>
+        </includes>
+        <filtering>true</filtering>
+      </testResource>
+    </testResources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-commons-logging/pom.xml b/src/etc/poms/ant-commons-logging/pom.xml
index a83eadd..fcafc97 100644
--- a/src/etc/poms/ant-commons-logging/pom.xml
+++ b/src/etc/poms/ant-commons-logging/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,28 +18,28 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-commons-logging</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -60,7 +60,31 @@
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-commons-net/pom.xml b/src/etc/poms/ant-commons-net/pom.xml
index caefda5..938562a 100644
--- a/src/etc/poms/ant-commons-net/pom.xml
+++ b/src/etc/poms/ant-commons-net/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,34 +18,34 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-commons-net</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
       <groupId>commons-net</groupId>
       <artifactId>commons-net</artifactId>
-      <version>2.2</version>
+      <version>3.8.0</version>
       <scope>compile</scope>
     </dependency>
   </dependencies>
@@ -65,9 +65,43 @@
           </testIncludes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <!-- tests assume an FTP server listening on localhost -->
+          <skipTests>true</skipTests>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-imageio/pom.xml b/src/etc/poms/ant-imageio/pom.xml
new file mode 100644
index 0000000..3db3577
--- /dev/null
+++ b/src/etc/poms/ant-imageio/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://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.
+-->
+<!--
+  This POM has been created manually by the Ant Development Team.
+  Please contact us if you are not satisfied with the data contained in this POM.
+  URL : https://ant.apache.org
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.ant</groupId>
+    <artifactId>ant-parent</artifactId>
+    <relativePath>../pom.xml</relativePath>
+    <version>1.10.13-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <url>https://ant.apache.org/</url>
+  <groupId>org.apache.ant</groupId>
+  <artifactId>ant-imageio</artifactId>
+  <version>1.10.13-SNAPSHOT</version>
+  <name>Apache Ant + ImageIO</name>
+  <description>imageio task and corresponding types.</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant</artifactId>
+      <version>1.10.13-SNAPSHOT</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>org/apache/tools/ant/taskdefs/optional/image/ImageIOTask.java</include>
+            <include>org/apache/tools/ant/types/optional/imageio/*</include>
+          </includes>
+          <testIncludes>
+            <include>org/apache/tools/ant/taskdefs/optional/image/ImageIOTest.java</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
+       </configuration>
+      </plugin>
+    </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
+    <sourceDirectory>../../../../src/main</sourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
+    <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
+    <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
+    <directory>../../../../target/${project.artifactId}</directory>
+  </build>
+</project>
diff --git a/src/etc/poms/ant-jai/pom.xml b/src/etc/poms/ant-jai/pom.xml
index f2d8220..c7373fd 100644
--- a/src/etc/poms/ant-jai/pom.xml
+++ b/src/etc/poms/ant-jai/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,22 +18,22 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jai</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -57,11 +57,11 @@
   </dependencies>
   <!-- Central has javax.media:jai-core:1.1.3 but only com.sun.media:jai-codec:1.1.2_01 -->
   <repositories>
-      <repository>
-          <id>jboss</id>
-          <name>JBoss</name>
-          <url>https://repository.jboss.org/nexus/content/groups/public/</url>
-      </repository>
+    <repository>
+      <id>jboss</id>
+      <name>JBoss</name>
+      <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+    </repository>
   </repositories>
   <build>
     <plugins>
@@ -70,14 +70,55 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <includes>
-            <include>org/apache/tools/ant/taskdefs/optional/image/*</include>
+            <include>org/apache/tools/ant/taskdefs/optional/image/Image.java</include>
             <include>org/apache/tools/ant/types/optional/image/*</include>
           </includes>
+          <testIncludes>
+            <include>org/apache/tools/ant/taskdefs/optional/image/ImageTest.java</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
         </configuration>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-jakartamail/pom.xml b/src/etc/poms/ant-jakartamail/pom.xml
new file mode 100644
index 0000000..cb55f9c
--- /dev/null
+++ b/src/etc/poms/ant-jakartamail/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://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.
+-->
+<!--
+  This POM has been created manually by the Ant Development Team.
+  Please contact us if you are not satisfied with the data contained in this POM.
+  URL : https://ant.apache.org
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.ant</groupId>
+    <artifactId>ant-parent</artifactId>
+    <relativePath>../pom.xml</relativePath>
+    <version>1.10.13-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <url>https://ant.apache.org/</url>
+  <groupId>org.apache.ant</groupId>
+  <artifactId>ant-jakartamail</artifactId>
+  <version>1.10.13-SNAPSHOT</version>
+  <name>Apache Ant + JakartaMail</name>
+  <description>implementation of the mail task based on Jakarta EE mail.
+    Required to send emails to SMTP servers using user/password combinations
+  or to send mail over SSL</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant</artifactId>
+      <version>1.10.13-SNAPSHOT</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <!-- This brings in the necessary dependencies.
+      See https://eclipse-ee4j.github.io/mail/ -->
+      <groupId>com.sun.mail</groupId>
+      <artifactId>jakarta.mail</artifactId>
+      <version>2.0.1</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>org/apache/tools/ant/taskdefs/email/JakartaMimeMailer*</include>
+          </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+    </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
+    <sourceDirectory>../../../../src/main</sourceDirectory>
+    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
+    <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
+    <directory>../../../../target/${project.artifactId}</directory>
+  </build>
+</project>
diff --git a/src/etc/poms/ant-javamail/pom.xml b/src/etc/poms/ant-javamail/pom.xml
index 9765ca5..05b2dec 100644
--- a/src/etc/poms/ant-javamail/pom.xml
+++ b/src/etc/poms/ant-javamail/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,21 +18,21 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-javamail</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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,18 +41,18 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
       <!-- This brings in the necessary dependencies.
-      See https://javaee.github.io/javamail/#Download_JavaMail_Release -->
+      See https://eclipse-ee4j.github.io/mail/ -->
       <groupId>com.sun.mail</groupId>
       <artifactId>javax.mail</artifactId>
-      <version>1.5.6</version>
+      <version>1.6.2</version>
       <scope>compile</scope>
     </dependency>
-  </dependencies> 
+  </dependencies>
   <build>
     <plugins>
       <plugin>
@@ -64,7 +64,31 @@
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-jdepend/pom.xml b/src/etc/poms/ant-jdepend/pom.xml
index aeb76de..fbe9a05 100644
--- a/src/etc/poms/ant-jdepend/pom.xml
+++ b/src/etc/poms/ant-jdepend/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,22 +18,22 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jdepend</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -58,13 +58,59 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <includes>
-            <include>org/apache/tools/ant/taskdefs/optional/jdepend/*</include>
+            <include>org/apache/tools/ant/taskdefs/optional/jdepend/</include>
           </includes>
+          <testIncludes>
+            <include>org/apache/tools/ant/taskdefs/optional/jdepend/</include>
+            <include>org/apache/tools/ant/util/facade/</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>build.tests.value</name>
+              <value>${project.basedir}/../../../../target/${project.artifactId}/testcases</value>
+            </property>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
         </configuration>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-jmf/pom.xml b/src/etc/poms/ant-jmf/pom.xml
index 3c28756..30fdded 100644
--- a/src/etc/poms/ant-jmf/pom.xml
+++ b/src/etc/poms/ant-jmf/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,29 +18,29 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jmf</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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>
+    download the dependency from https://java.sun.com/products/java-media/jmf/</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
   </dependencies>
@@ -55,7 +55,31 @@
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-jsch/pom.xml b/src/etc/poms/ant-jsch/pom.xml
index ffd671e..887d2d9 100644
--- a/src/etc/poms/ant-jsch/pom.xml
+++ b/src/etc/poms/ant-jsch/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,21 +18,21 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jsch</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -64,9 +64,47 @@
           </testIncludes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>scp.tmp</name>
+              <value>${java.io.tmpdir}</value>
+            </property>
+          </systemProperties>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-junit/pom.xml b/src/etc/poms/ant-junit/pom.xml
index 82b3aa6..a39d6f3 100644
--- a/src/etc/poms/ant-junit/pom.xml
+++ b/src/etc/poms/ant-junit/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,28 +18,28 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-junit</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
@@ -48,6 +48,18 @@
       <version>4.13.1</version>
       <scope>compile</scope>
     </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.12.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>xalan</groupId>
+      <artifactId>xalan</artifactId>
+      <version>2.7.2</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -55,24 +67,24 @@
         <artifactId>maven-antrun-plugin</artifactId>
         <executions>
           <execution>
-            <id>create-timestamp-file</id>
-            <phase>generate-resources</phase>
+            <id>copy-junit-xsl</id>
+            <phase>process-classes</phase>
             <goals>
               <goal>run</goal>
             </goals>
             <configuration>
-              <tasks>
-                <mkdir dir="${project.build.outputDirectory}"/>
+              <target>
                 <copy todir="${project.build.outputDirectory}/org/apache/tools/ant/taskdefs/optional/junit/xsl">
-                  <fileset dir="${project.build.sourceDirectory}/../etc">
+                  <fileset dir="${project.build.scriptSourceDirectory}">
                     <include name="junit-frames.xsl"/>
                     <include name="junit-noframes.xsl"/>
+                    <include name="junit-frames-saxon.xsl"/>
+                    <include name="junit-noframes-saxon.xsl"/>
                   </fileset>
                 </copy>              
-              </tasks>
+              </target>
             </configuration>
           </execution>
-
         </executions>
       </plugin>
       <plugin>
@@ -82,18 +94,95 @@
           <includes>
             <include>org/apache/tools/ant/taskdefs/optional/junit/*</include>
           </includes>
-          <excludes>
-              <exclude>org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter*</exclude>
-              <exclude>org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache*</exclude>
-          </excludes>
           <testIncludes>
             <include>org/apache/tools/ant/taskdefs/optional/junit/</include>
+            <include>org/example/junit/</include>
+            <include>org/example/tasks/*.java</include>
+            <include>org/example/types/</include>
           </testIncludes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <!-- Cannot exclude JUnit 4-specific classes from compilation because tests depend on them -->
+          <excludes>
+            <exclude>org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache*</exclude>
+          </excludes>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
+          <systemProperties>
+            <property>
+              <name>build.tests.value</name>
+              <value>${project.basedir}/../../../../target/${project.artifactId}/testcases</value>
+            </property>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
+          </systemProperties>
+          <excludes>
+            <exclude>org/example/junit/*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/junit/*$*</exclude>
+            <!-- test fails as classloaders are different when run via Maven -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/junit/JUnitClassLoaderTest*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
+    <testResources>
+      <testResource>
+        <directory>../../../../src/etc/testcases</directory>
+        <includes>
+         <include>taskdefs/optional/junit/**</include>
+          <include>taskdefs/optional/junit.xml</include>
+          <include>taskdefs/optional/junitreport.xml</include>
+         <include>buildfiletest-base.xml</include>
+        </includes>
+      </testResource>
+      <testResource>
+        <directory>../../../../src</directory>
+        <includes>
+          <include>tests/junit/org/apache/tools/ant/taskdefs/optional/junit/*Test.java</include>
+        </includes>
+      </testResource>
+      <testResource>
+        <directory>../../../../src/tests/junit</directory>
+        <includes>
+          <include>org/example/tasks/*.xml</include>
+        </includes>
+      </testResource>
+    </testResources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
-    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
+    <scriptSourceDirectory>../../../../src/etc</scriptSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
diff --git a/src/etc/poms/ant-junit4/pom.xml b/src/etc/poms/ant-junit4/pom.xml
index 164668a..00269e0 100644
--- a/src/etc/poms/ant-junit4/pom.xml
+++ b/src/etc/poms/ant-junit4/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,28 +18,28 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
     <parent>
         <groupId>org.apache.ant</groupId>
         <artifactId>ant-parent</artifactId>
         <relativePath>../pom.xml</relativePath>
-        <version>1.9.17-SNAPSHOT</version>
+        <version>1.10.13-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <url>http://ant.apache.org/</url>
+    <url>https://ant.apache.org/</url>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-junit4</artifactId>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-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.17-SNAPSHOT</version>
+            <version>1.10.13-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
@@ -61,7 +61,34 @@
                     </includes>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>**/*Ignored*</exclude>
+                    </excludes>
+                    <archive>
+                        <index>true</index>
+                        <manifest>
+                            <addExtensions>true</addExtensions>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
         </plugins>
+        <resources>
+            <resource>
+                <directory>../../../..</directory>
+                <targetPath>META-INF</targetPath>
+                <includes>
+                    <include>LICENSE</include>
+                    <include>NOTICE</include>
+                </includes>
+            </resource>
+        </resources>
         <sourceDirectory>../../../../src/main</sourceDirectory>
         <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
         <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-junitlauncher/pom.xml b/src/etc/poms/ant-junitlauncher/pom.xml
new file mode 100644
index 0000000..b17f7e0
--- /dev/null
+++ b/src/etc/poms/ant-junitlauncher/pom.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://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.
+-->
+<!--
+  This POM has been created manually by the Ant Development Team.
+  Please contact us if you are not satisfied with the data contained in this POM.
+  URL : https://ant.apache.org
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.apache.ant</groupId>
+        <artifactId>ant-parent</artifactId>
+        <relativePath>../pom.xml</relativePath>
+        <version>1.10.13-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <url>https://ant.apache.org/</url>
+    <groupId>org.apache.ant</groupId>
+    <artifactId>ant-junitlauncher</artifactId>
+    <version>1.10.13-SNAPSHOT</version>
+    <name>Apache Ant + JUnit 5</name>
+    <description>contains JUnit 5.x support</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.10.13-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <version>1.8.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>5.8.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.vintage</groupId>
+            <artifactId>junit-vintage-engine</artifactId>
+            <version>5.8.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <includes>
+                        <include>org/apache/tools/ant/taskdefs/optional/junitlauncher/</include>
+                    </includes>
+                    <testIncludes>
+                        <include>org/apache/tools/ant/taskdefs/optional/junitlauncher/</include>
+                        <include>org/example/junitlauncher/</include>
+                    </testIncludes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <index>true</index>
+                        <manifest>
+                            <addExtensions>true</addExtensions>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <basedir>../../../..</basedir>
+                    <workingDirectory>../../../..</workingDirectory>
+                    <systemProperties>
+                        <property>
+                            <name>build.tests.value</name>
+                            <value>${project.basedir}/../../../../target/${project.artifactId}/testcases</value>
+                        </property>
+                        <property>
+                            <name>ant.test.basedir.ignore</name>
+                            <value>true</value>
+                        </property>
+                    </systemProperties>
+                    <excludes>
+                        <exclude>org/example/junitlauncher/**</exclude>
+                        <!-- test fails as classloaders are different when run via Maven -->
+                        <exclude>org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest*</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>../../../..</directory>
+                <targetPath>META-INF</targetPath>
+                <includes>
+                    <include>LICENSE</include>
+                    <include>NOTICE</include>
+                </includes>
+            </resource>
+        </resources>
+        <testResources>
+            <testResource>
+                <directory>../../../../src/etc/testcases</directory>
+                <includes>
+                    <include>taskdefs/optional/junitlauncher.xml</include>
+                    <include>buildfiletest-base.xml</include>
+                </includes>
+            </testResource>
+        </testResources>
+        <sourceDirectory>../../../../src/main</sourceDirectory>
+        <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
+        <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
+        <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
+        <directory>../../../../target/${project.artifactId}</directory>
+    </build>
+</project>
diff --git a/src/etc/poms/ant-launcher/pom.xml b/src/etc/poms/ant-launcher/pom.xml
index ceef1da..cbfbbf6 100644
--- a/src/etc/poms/ant-launcher/pom.xml
+++ b/src/etc/poms/ant-launcher/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,22 +18,22 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-launcher</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant Launcher</name>
   <build>
     <plugins>
@@ -44,14 +44,39 @@
           <includes>
             <include>org/apache/tools/ant/launch/*.java</include>
           </includes>
-
+          <testIncludes>
+            <include>org/apache/tools/ant/launch/*.java</include>
+          </testIncludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <mainClass>org.apache.tools.ant.launch.Launcher</mainClass>
+            </manifest>
+          </archive>
         </configuration>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
+    <!-- tests depend on Ant (Os) -->
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
-    <outputDirectory>../../../../target/ant-launcher/classes</outputDirectory>
-    <testOutputDirectory>../../../../target/ant-launcher/testcases</testOutputDirectory>
-    <directory>../../../../target/ant-launcher</directory>
+    <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
+    <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
+    <directory>../../../../target/${project.artifactId}</directory>
   </build>
 </project>
diff --git a/src/etc/poms/ant-netrexx/pom.xml b/src/etc/poms/ant-netrexx/pom.xml
index 8728a0a..1a92434 100644
--- a/src/etc/poms/ant-netrexx/pom.xml
+++ b/src/etc/poms/ant-netrexx/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,29 +18,29 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-netrexx</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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>
+    dependency can be downloaded from https://www.ibm.com/software/awdtools/netrexx/download.html</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <!-- Processed too early, before maven-antrun-plugin gets a chance to work:
@@ -70,17 +70,30 @@
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-antrun-plugin</artifactId>
-        <version>1.4</version>
         <executions>
           <execution>
             <phase>validate</phase>
             <configuration>
-              <tasks>
+              <target>
                 <ant dir="${basedir}/../../../.." antfile="fetch.xml" target="netrexx">
                   <property name="dest" value="optional"/>
                 </ant>
-              </tasks>
+              </target>
             </configuration>
             <goals>
               <goal>run</goal>
@@ -89,6 +102,16 @@
         </executions>
       </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
diff --git a/src/etc/poms/ant-swing/pom.xml b/src/etc/poms/ant-swing/pom.xml
index 2bf04ab..99d1391 100644
--- a/src/etc/poms/ant-swing/pom.xml
+++ b/src/etc/poms/ant-swing/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,29 +18,29 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-swing</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
   </dependencies>
@@ -55,12 +55,35 @@
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
   </build>
-  
 </project>
diff --git a/src/etc/poms/ant-testutil/pom.xml b/src/etc/poms/ant-testutil/pom.xml
index 5483b4e..181ced1 100644
--- a/src/etc/poms/ant-testutil/pom.xml
+++ b/src/etc/poms/ant-testutil/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,29 +18,29 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>  
+  <url>https://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-testutil</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-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.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
      <dependency>
@@ -57,7 +57,10 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <includes>
-            <include>org/apache/tools/ant/BuildFileTest*</include>
+            <include>org/apache/tools/ant/AntAssert*</include>
+            <include>org/apache/tools/ant/BuildFile*</include>
+            <include>org/apache/tools/ant/FileUtilities*</include>
+            <include>org/apache/tools/ant/MagicTestNames*</include>
             <include>org/apache/tools/ant/util/regexp/RegexpMatcherTest*</include>
             <include>org/apache/tools/ant/util/regexp/RegexpTest*</include>
             <include>org/apache/tools/ant/taskdefs/optional/AbstractXSLTLiaisonTest*</include>
@@ -65,10 +68,33 @@
           </includes>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
     <sourceDirectory>../../../../src/tests/junit</sourceDirectory>
     <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
     <directory>../../../../target/${project.artifactId}</directory>
   </build>
-  
 </project>
diff --git a/src/etc/poms/ant-xz/pom.xml b/src/etc/poms/ant-xz/pom.xml
new file mode 100644
index 0000000..a97961d
--- /dev/null
+++ b/src/etc/poms/ant-xz/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://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.
+-->
+<!--
+  This POM has been created manually by the Ant Development Team.
+  Please contact us if you are not satisfied with the data contained in this POM.
+  URL : https://ant.apache.org
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.ant</groupId>
+    <artifactId>ant-parent</artifactId>
+    <relativePath>../pom.xml</relativePath>
+    <version>1.10.13-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <url>https://ant.apache.org/</url>
+  <groupId>org.apache.ant</groupId>
+  <artifactId>ant-xz</artifactId>
+  <version>1.10.13-SNAPSHOT</version>
+  <name>Apache Ant + XZ for Java</name>
+  <description>contains the xz compression support</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant</artifactId>
+      <version>1.10.13-SNAPSHOT</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.tukaani</groupId>
+      <artifactId>xz</artifactId>
+      <version>1.8</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>org/apache/tools/ant/taskdefs/optional/xz/*</include>
+            <include>org/apache/tools/ant/types/optional/xz/*</include>
+          </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+    </plugins>
+    <resources>
+      <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+    </resources>
+    <sourceDirectory>../../../../src/main</sourceDirectory>
+    <testSourceDirectory>../../../../src/testcases</testSourceDirectory>
+    <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
+    <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
+    <directory>../../../../target/${project.artifactId}</directory>
+  </build>
+</project>
diff --git a/src/etc/poms/ant/pom.xml b/src/etc/poms/ant/pom.xml
index 970fba3..8ce508b 100644
--- a/src/etc/poms/ant/pom.xml
+++ b/src/etc/poms/ant/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,37 +18,34 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.17-SNAPSHOT</version>
+    <version>1.10.13-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <name>Apache Ant Core</name>
+  <properties>
+    <modules.exclude>org/apache/tools/ant/taskdefs/modules/</modules.exclude>
+  </properties>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant-launcher</artifactId>
-      <version>1.9.17-SNAPSHOT</version>
+      <version>1.10.13-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.12</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant-antunit</artifactId>
       <version>1.4.1</version>
@@ -64,6 +61,24 @@
         </exclusion>
       </exclusions>
     </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.12.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.mail</groupId>
+      <artifactId>javax.mail</artifactId>
+      <version>1.6.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.beanshell</groupId>
+      <artifactId>bsh</artifactId>
+      <version>2.0b5</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <filters>
@@ -71,11 +86,6 @@
     </filters>
     <plugins>
       <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <configuration> </configuration>
-      </plugin>
-      <plugin>
         <artifactId>maven-antrun-plugin</artifactId>
         <executions>
           <execution>
@@ -85,13 +95,46 @@
               <goal>run</goal>
             </goals>
             <configuration>
-              <tasks>
+              <target>
                 <tstamp/>
                 <mkdir dir="${project.build.directory}"/>
                 <touch file="${project.build.directory}/.build.timestamp.properties"/>
                 <echo file="${project.build.directory}/.build.timestamp.properties" append="false"
                   message="TODAY=${TODAY}"/>
-              </tasks>
+              </target>
+            </configuration>
+          </execution>
+          <execution>
+            <id>create-antlib-test-jar</id>
+            <phase>process-test-classes</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <target>
+                <jar jarfile="${project.build.testOutputDirectory}/org/apache/tools/ant/taskdefs/test2-antlib.jar">
+                  <manifest>
+                    <attribute name="Extension-name"
+                               value="org.apache.tools.ant"/>
+                    <attribute name="Specification-Title"
+                               value="Apache Ant"/>
+                    <attribute name="Specification-Version"
+                               value="${project.version}"/>
+                    <attribute name="Specification-Vendor"
+                               value="Apache Software Foundation"/>
+                    <attribute name="Implementation-Title"
+                               value="org.apache.tools.ant"/>
+                    <attribute name="Implementation-Version"
+                               value="${project.version}"/>
+                    <attribute name="Implementation-Vendor"
+                               value="Apache Software Foundation"/>
+                  </manifest>
+                  <zipfileset dir="${project.build.scriptSourceDirectory}/testcases" fullpath="taskdefs/test.antlib.xml">
+                    <include name="taskdefs/test2.antlib.xml"/>
+                  </zipfileset>
+                </jar>
+                <echoproperties prefix="maven."/>
+              </target>
             </configuration>
           </execution>
           <execution>
@@ -101,9 +144,9 @@
               <goal>run</goal>
             </goals>
             <configuration>
-              <tasks>
+              <target>
                 <delete file="${project.build.directory}/.build.timestamp.properties"/>
-              </tasks>
+              </target>
             </configuration>
           </execution>
         </executions>
@@ -114,71 +157,143 @@
         <configuration>
           <excludes>
             <exclude>org/apache/tools/ant/filters/util/JavaClassHelper*</exclude>
-            <exclude>org/apache/tools/ant/types/resolver/**</exclude>
-            <exclude>org/apache/tools/ant/listener/Log4jListener*</exclude>
+            <exclude>org/apache/tools/ant/launch/</exclude>
             <exclude>org/apache/tools/ant/listener/CommonsLoggingListener*</exclude>
-            <exclude>org/apache/tools/ant/util/regexp/JakartaRegexp*</exclude>
-            <exclude>org/apache/tools/ant/util/regexp/JakartaOro*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/email/MimeMailer*</exclude>
-            <exclude>org/apache/tools/ant/launch/**</exclude>
+            <exclude>org/apache/tools/ant/listener/Log4jListener*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/email/*MimeMailer*</exclude>
+            <exclude>${modules.exclude}</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/NetRexxC*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/image/</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/jdepend/</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/junit/</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/junitlauncher/</exclude>
             <exclude>org/apache/tools/ant/taskdefs/optional/net/FTP*</exclude>
             <exclude>org/apache/tools/ant/taskdefs/optional/net/RExec*</exclude>
             <exclude>org/apache/tools/ant/taskdefs/optional/net/TelnetTask*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/junit/*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/ssh/*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/image/*</exclude>
-            <exclude>org/apache/tools/ant/types/optional/image/*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/Script*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/script/**</exclude>
-            <exclude>org/apache/tools/ant/types/optional/*Script*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/sound/</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/splash/</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/ssh/</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/xz/</exclude>
+            <exclude>org/apache/tools/ant/types/optional/image/</exclude>
+            <exclude>org/apache/tools/ant/types/optional/imageio/</exclude>
+            <exclude>org/apache/tools/ant/types/optional/xz/</exclude>
+            <exclude>org/apache/tools/ant/types/resolver/</exclude>
+            <exclude>org/apache/tools/ant/util/depend/bcel/</exclude>
             <exclude>org/apache/tools/ant/util/ScriptRunner.java</exclude>
             <exclude>org/apache/tools/ant/util/optional/ScriptRunner.java</exclude>
-            <exclude>org/apache/tools/ant/filters/util/JavaClassHelper*</exclude>
-            <exclude>org/apache/tools/ant/util/depend/bcel/*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/NetRexxC*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/jdepend/*</exclude>
+            <exclude>org/apache/tools/ant/util/regexp/JakartaOro*</exclude>
+            <exclude>org/apache/tools/ant/util/regexp/JakartaRegexp*</exclude>
           </excludes>
           <testExcludes>
-            <exclude>org/apache/tools/ant/filters/util/JavaClassHelper*</exclude>
-            <exclude>org/apache/tools/ant/types/resolver/**</exclude>
-            <exclude>org/apache/tools/ant/util/Script*</exclude>
-            <exclude>org/apache/tools/ant/listener/Log4jListener*</exclude>
+            <!-- launcher -->
+            <exclude>org/apache/tools/ant/launch/</exclude>
+            <!-- commons-logging -->
             <exclude>org/apache/tools/ant/listener/CommonsLoggingListener*</exclude>
-            <exclude>org/apache/tools/ant/util/regexp/JakartaRegexp*</exclude>
-            <exclude>org/apache/tools/ant/util/regexp/JakartaOro*</exclude>
-            <exclude>org/apache/tools/ant/util/regexp/Jdk14Regexp*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/email/MimeMailer*</exclude>
-            <exclude>org/apache/tools/ant/launch/**</exclude>
+            <!-- log4j -->
+            <exclude>org/apache/tools/ant/listener/Log4jListener*</exclude>
+            <!-- obsolete -->
+            <exclude>org/apache/tools/ant/taskdefs/AbstractCvs*</exclude>
+            <!-- ERROR: "default value" when javac cannot cross-compile to Java 5 -->
+            <exclude>org/apache/tools/ant/taskdefs/Javac*</exclude>
+            <!-- see XsltTest -->
             <exclude>org/apache/tools/ant/taskdefs/StyleTest*</exclude>
+            <!-- ERROR: Unexpected recipients -->
+            <exclude>org/apache/tools/ant/taskdefs/email/EmailTask*</exclude>
+            <!-- Java9+ -->
+            <exclude>${modules.exclude}</exclude>
+            <!-- antlr -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/ANTLR*</exclude>
+            <!-- obsolete -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/Jspc*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/optional/Pvcs*</exclude>
+            <!-- xalan: workaround for different resource encoding -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/TraXLiaison*</exclude>
+            <!-- ERROR: UnknownHostException: chemical (XML parser-dependent) -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/XmlValidateCatalog*</exclude>
+            <!-- image/imageio -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/image/</exclude>
+            <!-- jdepend -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/jdepend/</exclude>
+            <!-- junit -->
             <exclude>org/apache/tools/ant/taskdefs/optional/junit/</exclude>
+            <!-- junitlauncher -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/junitlauncher/</exclude>
+            <!-- net -->
             <exclude>org/apache/tools/ant/taskdefs/optional/net/FTP*</exclude>
-            <exclude>org/apache/tools/ant/taskdefs/optional/ssh/*</exclude>
+            <!-- swing -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/splash/</exclude>
+            <!-- jsch -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/ssh/</exclude>
+            <!-- dependent on junit -->
+            <exclude>org/apache/tools/ant/types/Assertions*</exclude>
+            <!-- bcel -->
+            <exclude>org/apache/tools/ant/types/optional/depend/ClassFileSet*</exclude>
+            <!-- ERROR: defaults.properties are in both compile and test file tree -->
+            <exclude>org/apache/tools/ant/util/ClasspathUtils*</exclude>
+            <exclude>org/apache/tools/ant/util/LoaderUtils*</exclude>
+            <!-- oro -->
+            <exclude>org/apache/tools/ant/util/regexp/JakartaOro*</exclude>
+            <!-- regexp -->
+            <exclude>org/apache/tools/ant/util/regexp/JakartaRegexp*</exclude>
+            <!-- dependent on IncludeTest.class: checks presence -->
+            <exclude>org/apache/tools/ant/AntClassLoaderDelegation*</exclude>
+            <!-- ERROR:  More pseudo attributes are expected (encoding="UTF-8");
+             failure mode is XML parser-dependent (see to do for failures in IDE) -->
+            <exclude>org/apache/tools/ant/Include*</exclude>
+            <!-- dependent on JUnit 5 -->
+            <exclude>org/example/junitlauncher/</exclude>
+            <!-- requires Graal.js and forking tests per class -->
+            <exclude>org/apache/tools/ant/taskdefs/optional/script/graal/</exclude>
+            <!-- requires structure of a binary distribution of Ant in ANT_HOME -->
+            <exclude>org/apache/tools/ant/types/CommandlineJavaTest*</exclude>
+            <exclude>org/apache/tools/ant/types/selectors/ModifiedSelectorTest*</exclude>
+            <exclude>org/apache/tools/ant/taskdefs/AvailableTest*</exclude>
           </testExcludes>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <index>true</index>
+            <manifest>
+              <mainClass>org.apache.tools.ant.Main</mainClass>
+              <addExtensions>true</addExtensions>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <basedir>../../../..</basedir>
+          <workingDirectory>../../../..</workingDirectory>
           <systemProperties>
             <property>
               <name>ant.home</name>
               <value>${env.ANT_HOME}</value>
             </property>
             <property>
-              <name>build.tests</name>
-              <value>../../../../target/ant/testcases</value>
+              <name>build.classes.value</name>
+              <value>${project.basedir}/../../../../target/${project.artifactId}/classes</value>
             </property>
             <property>
               <name>build.tests.value</name>
-              <value>../../../../target/ant/testcases</value>
+              <value>${project.basedir}/../../../../target/${project.artifactId}/testcases</value>
             </property>
             <property>
               <name>offline</name>
               <value>true</value>
             </property>
+            <property>
+              <name>ant.test.basedir.ignore</name>
+              <value>true</value>
+            </property>
           </systemProperties>
         </configuration>
       </plugin>
@@ -189,12 +304,21 @@
     </plugins>
     <resources>
       <resource>
+        <directory>../../../..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE</include>
+          <include>NOTICE</include>
+        </includes>
+      </resource>
+      <resource>
         <directory>../../../../src/main</directory>
         <filtering>true</filtering>
         <includes>
-          <include>org/apache/tools/ant/taskdefs/default.properties</include>
-          <include>org/apache/tools/ant/types/default.properties</include>
-          <include>org/apache/tools/ant/taskdefs/default.properties</include>
+          <include>org/apache/tools/ant/listener/defaults.properties</include>
+          <include>org/apache/tools/ant/taskdefs/defaults.properties</include>
+          <include>org/apache/tools/ant/types/defaults.properties</include>
+          <include>org/apache/tools/ant/antlib.xml</include>
           <include>org/apache/tools/ant/types/conditions/antlib.xml</include>
           <include>org/apache/tools/ant/defaultManifest.mf</include>
           <include>org/apache/tools/ant/version.txt</include>
@@ -205,10 +329,11 @@
         <filtering>true</filtering>
         <includes>
           <include>**/antlib.xml</include>
+          <include>**/javadoc-frame-injections-fix.txt</include>
         </includes>
       </resource>
       <resource>
-        <directory>../../../../docs</directory>
+        <directory>../../../../manual</directory>
         <filtering>false</filtering>
         <includes>
           <include>images/ant_logo_large.gif</include>
@@ -230,8 +355,21 @@
     </testResources>
     <sourceDirectory>../../../../src/main</sourceDirectory>
     <testSourceDirectory>../../../../src/tests/junit</testSourceDirectory>
-    <outputDirectory>../../../../target/ant/classes</outputDirectory>
-    <testOutputDirectory>../../../../target/ant/testcases</testOutputDirectory>
-    <directory>../../../../target/ant</directory>
+    <scriptSourceDirectory>../../../../src/etc</scriptSourceDirectory>
+    <!-- directory name is hardcoded in AntTest -->
+    <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory>
+    <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory>
+    <directory>../../../../target/${project.artifactId}</directory>
   </build>
+  <profiles>
+    <profile>
+      <id>java9+</id>
+      <activation>
+        <jdk>[9,)</jdk>
+      </activation>
+      <properties>
+        <modules.exclude>not/here</modules.exclude>
+      </properties>
+    </profile>
+  </profiles>
 </project>
diff --git a/src/etc/poms/pom.xml b/src/etc/poms/pom.xml
index 9ce09f4..893ceee 100644
--- a/src/etc/poms/pom.xml
+++ b/src/etc/poms/pom.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -18,47 +18,47 @@
 <!--
   This POM has been created manually by the Ant Development Team.
   Please contact us if you are not satisfied with the data contained in this POM.
-  URL : http://ant.apache.org
+  URL : https://ant.apache.org
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-parent</artifactId>
-  <version>1.9.17-SNAPSHOT</version>
+  <version>1.10.13-SNAPSHOT</version>
   <packaging>pom</packaging>
   <description>master POM</description>
   <licenses>
     <license>
       <name>The Apache Software License, Version 2.0</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
       <distribution>repo</distribution>
     </license>
   </licenses>
   <name>Apache Ant</name>
-  <url>http://ant.apache.org/</url>
+  <url>https://ant.apache.org/</url>
   <inceptionYear>2000</inceptionYear>
   <organization>
     <name>The Apache Software Foundation</name>
-    <url>http://www.apache.org/</url>
+    <url>https://www.apache.org/</url>
   </organization>
   <distributionManagement>
     <!-- Null out inherited apache distribution repo by default -->
     <repository>
       <id>dummy</id>
       <name>Dummy to avoid accidental deploys</name>
-      <url>http://nowhere.net/</url>
+      <url>https://nowhere.net/</url>
     </repository>
   </distributionManagement>
   <scm>
-    <connection>scm:git:https://git-wip-us.apache.org/repos/asf/ant.git</connection>
-    <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/ant.git</developerConnection>
-    <url>https://git-wip-us.apache.org/repos/asf/ant.git</url>
+    <connection>scm:git:https://gitbox.apache.org/repos/asf/ant.git</connection>
+    <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/ant.git</developerConnection>
+    <url>https://gitbox.apache.org/repos/asf/ant.git</url>
   </scm>
   <ciManagement>
-    <system>hudson</system>
-    <url>https://builds.apache.org/job/Ant_BuildFromPOMs/</url>
+    <system>jenkins</system>
+    <url>https://builds.apache.org/job/Ant-Build-from-POMs/</url>
   </ciManagement>
   <mailingLists>
     <mailingList>
@@ -66,19 +66,19 @@
       <subscribe>dev-subscribe@ant.apache.org</subscribe>
       <unsubscribe>dev-unsubscribe@ant.apache.org</unsubscribe>
       <post>dev@ant.apache.org</post>
-      <archive>http://mail-archives.apache.org/mod_mbox/ant-dev</archive>
+      <archive>https://mail-archives.apache.org/mod_mbox/ant-dev</archive>
     </mailingList>
     <mailingList>
       <name>Ant Users List</name>
       <subscribe>user-subscribe@ant.apache.org</subscribe>
       <unsubscribe>user-unsubscribe@ant.apache.org</unsubscribe>
       <post>user@ant.apache.org</post>
-      <archive>http://mail-archives.apache.org/mod_mbox/ant-user</archive>
+      <archive>https://mail-archives.apache.org/mod_mbox/ant-user</archive>
     </mailingList>
   </mailingLists>
   <issueManagement>
     <system>bugzilla</system>
-    <url>http://issues.apache.org/bugzilla/</url>
+    <url>https://issues.apache.org/bugzilla/</url>
   </issueManagement>
   <modules>
     <module>ant</module>
@@ -92,23 +92,33 @@
     <module>ant-apache-xalan2</module>
     <module>ant-commons-logging</module>
     <module>ant-commons-net</module>
+    <module>ant-imageio</module>
     <module>ant-jai</module>
     <module>ant-javamail</module>
+    <module>ant-jakartamail</module>
     <module>ant-jdepend</module>
     <module>ant-jmf</module>
     <module>ant-jsch</module>
     <module>ant-junit</module>
     <module>ant-junit4</module>
+    <module>ant-junitlauncher</module>
     <module>ant-launcher</module>
     <module>ant-netrexx</module>
     <module>ant-swing</module>
     <module>ant-testutil</module>
+    <module>ant-xz</module>
   </modules>
   <dependencies>
      <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>3.8.2</version>
+      <version>4.13.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-library</artifactId>
+      <version>1.3</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
@@ -122,26 +132,31 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
-          <version>2.3.2</version>
+          <version>3.8.0</version>
           <configuration>
-            <source>1.5</source>
-            <target>1.5</target>
+            <source>1.8</source>
+            <target>1.8</target>
           </configuration>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>2.4</version>
+          <version>3.1.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
-          <version>2.12</version>
+          <version>2.22.1</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-report-plugin</artifactId>
-          <version>2.12</version>
+          <version>2.22.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-antrun-plugin</artifactId>
+          <version>1.8</version>
         </plugin>
       </plugins>
     </pluginManagement>
@@ -149,4 +164,21 @@
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
+  <profiles>
+    <profile>
+      <id>javac-8</id>
+      <activation>
+        <jdk>1.8</jdk>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>com.sun</groupId>
+          <artifactId>tools</artifactId>
+          <version>1.8.0</version>
+          <scope>system</scope>
+          <systemPath>${java.home}/../lib/tools.jar</systemPath>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
 </project>
diff --git a/src/etc/printFailingTests.xsl b/src/etc/printFailingTests.xsl
index 7d32340..1dfb333 100644
--- a/src/etc/printFailingTests.xsl
+++ b/src/etc/printFailingTests.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/tagdiff.xsl b/src/etc/tagdiff.xsl
index 5d430a7..42c9569 100644
--- a/src/etc/tagdiff.xsl
+++ b/src/etc/tagdiff.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -65,7 +65,7 @@
           </h1>
           Tagdiff between <xsl:value-of select="@startTag"/> <xsl:value-of select="@startDate"/> and
 			<xsl:value-of select="@endTag"/> <xsl:value-of select="@endDate"/>
-          <p align="right">Designed for use with <a href="http://ant.apache.org/">Ant</a>.</p>
+          <p align="right">Designed for use with <a href="https://ant.apache.org/">Ant</a>.</p>
           <hr size="2"/>
 	<a name="TOP"/>
 	<table width="100%">
diff --git a/src/etc/testcases/buildfiletest-base.xml b/src/etc/testcases/buildfiletest-base.xml
index fc1e8b0..1dca0e5 100644
--- a/src/etc/testcases/buildfiletest-base.xml
+++ b/src/etc/testcases/buildfiletest-base.xml
@@ -1,3 +1,20 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
 <project name="buildfiletest-base">
   <property name="buildfiletest.tmpdir" location="${java.io.tmpdir}"/>
   <property name="input" location="${buildfiletest.tmpdir}/testinput_${ant.processid}_${ant.threadname}"/>
diff --git a/src/etc/testcases/core/antclassloader.xml b/src/etc/testcases/core/antclassloader.xml
index cafc823..ad651e3 100644
--- a/src/etc/testcases/core/antclassloader.xml
+++ b/src/etc/testcases/core/antclassloader.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -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"/>
@@ -77,4 +73,52 @@
     <target name="createNonJar">
       <touch file="${tmp.dir}/foo.jar"/>
     </target>
+
+    <target name="testMRJar" description="tests AntClassLoader support for multi-release jars.
+                            see https://bz.apache.org/bugzilla/show_bug.cgi?id=62952">
+        <mkdir dir="${tmp.dir}/mrjar/org/example"/>
+        <mkdir dir="${tmp.dir}/mrjar-9/org/example"/>
+        <!-- default version of the class -->
+        <echo file="${tmp.dir}/mrjar/org/example/MRJarTest.java"><![CDATA[
+                package org.example;
+                public class MRJarTest {
+                    public static void main(String[] args) {
+                        System.out.println("mrjar test result = default");
+                    }
+                }
+            ]]>
+        </echo>
+        <!-- Java runtime version 9 of the class -->
+        <echo file="${tmp.dir}/mrjar-9/org/example/MRJarTest.java"><![CDATA[
+                package org.example;
+                public class MRJarTest {
+                    public static void main(String[] args) {
+                        System.out.println("mrjar test result = 9");
+                    }
+                }
+            ]]>
+        </echo>
+        <!-- compile these classes -->
+        <javac srcdir="${tmp.dir}/mrjar" destdir="${tmp.dir}/mrjar"/>
+        <javac srcdir="${tmp.dir}/mrjar-9" destdir="${tmp.dir}/mrjar-9"/>
+
+        <!-- create multi-release jar file -->
+        <jar destfile="${tmp.dir}/mrjar.jar">
+            <manifest>
+                <attribute name="Multi-Release" value="true"/>
+            </manifest>
+            <!-- default classes -->
+            <fileset dir="${tmp.dir}/mrjar" includes="**/*.class"/>
+            <!-- Java 9 specific classes -->
+            <zipfileset prefix="META-INF/versions/9/" dir="${tmp.dir}/mrjar-9" includes="**/*.class"/>
+        </jar>
+
+        <!-- now run the class present in the multi-release jar -->
+        <java classname="org.example.MRJarTest" failonerror="true">
+            <classpath>
+                <pathelement location="${tmp.dir}/mrjar.jar"/>
+            </classpath>
+        </java>
+
+    </target>
 </project>
diff --git a/src/etc/testcases/core/case.xml b/src/etc/testcases/core/case.xml
index ea4ac1d..eecb321 100644
--- a/src/etc/testcases/core/case.xml
+++ b/src/etc/testcases/core/case.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/containersrc/test/SpecialSeq.java b/src/etc/testcases/core/containersrc/test/SpecialSeq.java
index f3f0176..52254fb 100644
--- a/src/etc/testcases/core/containersrc/test/SpecialSeq.java
+++ b/src/etc/testcases/core/containersrc/test/SpecialSeq.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,12 +23,11 @@
 import org.apache.tools.ant.types.FileSet;
 import org.apache.tools.ant.taskdefs.Echo;
 
-import java.util.Enumeration;
 import java.util.Vector;
 
 public class SpecialSeq extends Task implements TaskContainer {
     /** Optional Vector holding the nested tasks */
-    private Vector nestedTasks = new Vector();
+    private Vector<Task> nestedTasks = new Vector<>();
 
     private FileSet fileset;
 
@@ -50,10 +49,7 @@
         if (fileset == null || fileset.getDir(getProject()) == null) {
             throw new BuildException("Fileset was not configured");
         }
-        for (Enumeration e = nestedTasks.elements(); e.hasMoreElements();) {
-            Task nestedTask = (Task) e.nextElement();
-            nestedTask.perform();
-        }
+        nestedTasks.forEach(Task::perform);
         nestedEcho.reconfigure();
         nestedEcho.perform();
     }
diff --git a/src/etc/testcases/core/directoryscanner.xml b/src/etc/testcases/core/directoryscanner.xml
index 7e8683a..e11af08 100644
--- a/src/etc/testcases/core/directoryscanner.xml
+++ b/src/etc/testcases/core/directoryscanner.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/dispatch/dispatch.xml b/src/etc/testcases/core/dispatch/dispatch.xml
index d529644..0d73ad2 100644
--- a/src/etc/testcases/core/dispatch/dispatch.xml
+++ b/src/etc/testcases/core/dispatch/dispatch.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -19,14 +19,12 @@
 <project name="dispatch-test" default="disp">
 
   <path id="testclasses">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="disp">
-    <taskdef name="disptask"
-             classname="org.apache.tools.ant.taskdefs.PickOneTask">
-      <classpath refid="testclasses" />
+    <taskdef name="disptask" classname="org.apache.tools.ant.PickOneTask">
+      <classpath refid="testclasses"/>
     </taskdef>
     <disptask action="list"/>
   </target>
diff --git a/src/etc/testcases/core/duplicate-target-imported.xml b/src/etc/testcases/core/duplicate-target-imported.xml
index fc945f7..32a84d6 100644
--- a/src/etc/testcases/core/duplicate-target-imported.xml
+++ b/src/etc/testcases/core/duplicate-target-imported.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/duplicate-target.xml b/src/etc/testcases/core/duplicate-target.xml
index 0a29526..c968510 100644
--- a/src/etc/testcases/core/duplicate-target.xml
+++ b/src/etc/testcases/core/duplicate-target.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/duplicate-target2.xml b/src/etc/testcases/core/duplicate-target2.xml
index 6d96bca..55c29a8 100644
--- a/src/etc/testcases/core/duplicate-target2.xml
+++ b/src/etc/testcases/core/duplicate-target2.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/executor.xml b/src/etc/testcases/core/executor.xml
index 080c8dc..05b8233 100644
--- a/src/etc/testcases/core/executor.xml
+++ b/src/etc/testcases/core/executor.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/extended-taskdef.xml b/src/etc/testcases/core/extended-taskdef.xml
index 58ca979..899c8d0 100644
--- a/src/etc/testcases/core/extended-taskdef.xml
+++ b/src/etc/testcases/core/extended-taskdef.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/immutable.xml b/src/etc/testcases/core/immutable.xml
index 26fda08..f0a584f 100644
--- a/src/etc/testcases/core/immutable.xml
+++ b/src/etc/testcases/core/immutable.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/basic/include.inc b/src/etc/testcases/core/include/basic/include.inc
index 960792d..e35a4d6 100644
--- a/src/etc/testcases/core/include/basic/include.inc
+++ b/src/etc/testcases/core/include/basic/include.inc
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/basic/include.xml b/src/etc/testcases/core/include/basic/include.xml
index 2c131b1..49f13eb 100644
--- a/src/etc/testcases/core/include/basic/include.xml
+++ b/src/etc/testcases/core/include/basic/include.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/basic/relative.xml b/src/etc/testcases/core/include/basic/relative.xml
index 697c841..3f6898c 100644
--- a/src/etc/testcases/core/include/basic/relative.xml
+++ b/src/etc/testcases/core/include/basic/relative.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git "a/src/etc/testcases/core/include/frag\043ment/include.inc" "b/src/etc/testcases/core/include/frag\043ment/include.inc"
index 960792d..e35a4d6 100644
--- "a/src/etc/testcases/core/include/frag\043ment/include.inc"
+++ "b/src/etc/testcases/core/include/frag\043ment/include.inc"
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git "a/src/etc/testcases/core/include/frag\043ment/include.xml" "b/src/etc/testcases/core/include/frag\043ment/include.xml"
index 400a15c..6a6a131 100644
--- "a/src/etc/testcases/core/include/frag\043ment/include.xml"
+++ "b/src/etc/testcases/core/include/frag\043ment/include.xml"
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git "a/src/etc/testcases/core/include/frag\043ment/relative.xml" "b/src/etc/testcases/core/include/frag\043ment/relative.xml"
index 05bbc9e..bf26f4e 100644
--- "a/src/etc/testcases/core/include/frag\043ment/relative.xml"
+++ "b/src/etc/testcases/core/include/frag\043ment/relative.xml"
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git "a/src/etc/testcases/core/include/frag\043ment/simple.xml" "b/src/etc/testcases/core/include/frag\043ment/simple.xml"
index d337234..64f746d 100644
--- "a/src/etc/testcases/core/include/frag\043ment/simple.xml"
+++ "b/src/etc/testcases/core/include/frag\043ment/simple.xml"
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/included_file_parse_error/build.xml b/src/etc/testcases/core/include/included_file_parse_error/build.xml
index d75747c..5c270ab 100644
--- a/src/etc/testcases/core/include/included_file_parse_error/build.xml
+++ b/src/etc/testcases/core/include/included_file_parse_error/build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/included_file_parse_error/included_file.xml b/src/etc/testcases/core/include/included_file_parse_error/included_file.xml
index 5fbd3f5..1e4327e 100644
--- a/src/etc/testcases/core/include/included_file_parse_error/included_file.xml
+++ b/src/etc/testcases/core/include/included_file_parse_error/included_file.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/included_file_task_error/build.xml b/src/etc/testcases/core/include/included_file_task_error/build.xml
index d75747c..5c270ab 100644
--- a/src/etc/testcases/core/include/included_file_task_error/build.xml
+++ b/src/etc/testcases/core/include/included_file_task_error/build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/included_file_task_error/included_file.xml b/src/etc/testcases/core/include/included_file_task_error/included_file.xml
index d40d397..3ac05c2 100644
--- a/src/etc/testcases/core/include/included_file_task_error/included_file.xml
+++ b/src/etc/testcases/core/include/included_file_task_error/included_file.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/including_file_parse_error/build.xml b/src/etc/testcases/core/include/including_file_parse_error/build.xml
index 7de5264..7670f3c 100644
--- a/src/etc/testcases/core/include/including_file_parse_error/build.xml
+++ b/src/etc/testcases/core/include/including_file_parse_error/build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/including_file_parse_error/included_file.xml b/src/etc/testcases/core/include/including_file_parse_error/included_file.xml
index c607bbc..8dcc12e 100644
--- a/src/etc/testcases/core/include/including_file_parse_error/included_file.xml
+++ b/src/etc/testcases/core/include/including_file_parse_error/included_file.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/including_file_task_error/build.xml b/src/etc/testcases/core/include/including_file_task_error/build.xml
index 687b8cf..c668447 100644
--- a/src/etc/testcases/core/include/including_file_task_error/build.xml
+++ b/src/etc/testcases/core/include/including_file_task_error/build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/including_file_task_error/included_file.xml b/src/etc/testcases/core/include/including_file_task_error/included_file.xml
index c607bbc..8dcc12e 100644
--- a/src/etc/testcases/core/include/including_file_task_error/included_file.xml
+++ b/src/etc/testcases/core/include/including_file_task_error/included_file.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/with space/include.inc b/src/etc/testcases/core/include/with space/include.inc
index d8fd638..0f41885 100644
--- a/src/etc/testcases/core/include/with space/include.inc
+++ b/src/etc/testcases/core/include/with space/include.inc
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/with space/include.xml b/src/etc/testcases/core/include/with space/include.xml
index 4b693cd..94d3e51 100644
--- a/src/etc/testcases/core/include/with space/include.xml
+++ b/src/etc/testcases/core/include/with space/include.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/with space/relative.xml b/src/etc/testcases/core/include/with space/relative.xml
index 81f502a..5376067 100644
--- a/src/etc/testcases/core/include/with space/relative.xml
+++ b/src/etc/testcases/core/include/with space/relative.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/include/with space/simple.xml b/src/etc/testcases/core/include/with space/simple.xml
index 4092ce7..b2b37e0 100644
--- a/src/etc/testcases/core/include/with space/simple.xml
+++ b/src/etc/testcases/core/include/with space/simple.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/loaderref/loaderref.xml b/src/etc/testcases/core/loaderref/loaderref.xml
index 8397497..9b5f93f 100644
--- a/src/etc/testcases/core/loaderref/loaderref.xml
+++ b/src/etc/testcases/core/loaderref/loaderref.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/loaderref/src/Task1.java b/src/etc/testcases/core/loaderref/src/Task1.java
index cb374bd..c5bd93b 100644
--- a/src/etc/testcases/core/loaderref/src/Task1.java
+++ b/src/etc/testcases/core/loaderref/src/Task1.java
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/location.xml b/src/etc/testcases/core/location.xml
index 7e8f639..20f4afd 100644
--- a/src/etc/testcases/core/location.xml
+++ b/src/etc/testcases/core/location.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -36,12 +36,9 @@
   </target>
 
   <target name="define">
-    <property name="testclasses"
-      location="../../../../build/testcases" />
     <taskdef name="echoloc"
-      classname="org.apache.tools.ant.LocationTest$EchoLocation">
+             classname="org.apache.tools.ant.LocationTest$EchoLocation">
       <classpath>
-        <pathelement location="${testclasses}" />
         <pathelement path="${java.class.path}"/>
       </classpath>
     </taskdef>
@@ -70,5 +67,4 @@
     <echo id="echo4">Hello</echo>
     <echoloc3/>
   </target>
-
-</project>
\ No newline at end of file
+</project>
diff --git a/src/etc/testcases/core/taskcontainer.xml b/src/etc/testcases/core/taskcontainer.xml
index 4a21373..5f0209c 100644
--- a/src/etc/testcases/core/taskcontainer.xml
+++ b/src/etc/testcases/core/taskcontainer.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/topleveltasks/notarget.xml b/src/etc/testcases/core/topleveltasks/notarget.xml
index 2543751..b0a16ad 100644
--- a/src/etc/testcases/core/topleveltasks/notarget.xml
+++ b/src/etc/testcases/core/topleveltasks/notarget.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/topleveltasks/targetlevelant.xml b/src/etc/testcases/core/topleveltasks/targetlevelant.xml
index 9b1bb1d..e4c32b9 100644
--- a/src/etc/testcases/core/topleveltasks/targetlevelant.xml
+++ b/src/etc/testcases/core/topleveltasks/targetlevelant.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/topleveltasks/toplevelant.xml b/src/etc/testcases/core/topleveltasks/toplevelant.xml
index 968ad6c..12ead1e 100644
--- a/src/etc/testcases/core/topleveltasks/toplevelant.xml
+++ b/src/etc/testcases/core/topleveltasks/toplevelant.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/core/unknownelement.xml b/src/etc/testcases/core/unknownelement.xml
index b6d8939..6526023 100644
--- a/src/etc/testcases/core/unknownelement.xml
+++ b/src/etc/testcases/core/unknownelement.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -21,7 +21,6 @@
              classname="org.apache.tools.ant.UnknownElementTest$Parent"
              loaderref="unknown.id">
       <classpath>
-        <pathelement location="../../../../build/testcases"/>
         <pathelement path="${java.class.path}"/>
       </classpath>
     </taskdef>
@@ -33,6 +32,7 @@
       <child/>
     </parent>
   </target>
+
   <target name="echo">
     <echo message="Hello, world!"/>
   </target>
diff --git a/src/etc/testcases/filters/build.xml b/src/etc/testcases/filters/build.xml
index b70b778..371af3a 100644
--- a/src/etc/testcases/filters/build.xml
+++ b/src/etc/testcases/filters/build.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -16,12 +16,13 @@
    limitations under the License.
 -->
 <project default="tearDown" basedir=".">
+
   <import file="../buildfiletest-base.xml"/>
+
   <target name="setUp">
     <mkdir dir="${output}" />
   </target>
 
-
   <target name="testLineContains" depends="setUp">
     <copy todir="${output}">
       <fileset dir="input">
@@ -79,8 +80,8 @@
   </target>
 
   <target name="testReplaceTokens" depends="setUp">
-    <copy todir="${output}">
-      <fileset dir="input" includes="replacetokens.test" />
+    <copy  tofile="${output}/replaceTokens.test">
+      <fileset dir="input" includes="replacetokens.test"/>
       <filterchain>
         <replacetokens>
           <token key="foo" value=""/>
@@ -90,19 +91,19 @@
   </target>
 
   <target name="testReplaceTokensPropertyFile" depends="setUp">
-    <copy tofile="${output}/replacetokensPropertyFile.test">
-      <fileset dir="input" includes="replacetokens.test" />
+    <copy tofile="${output}/replaceTokensPropertyFile.test">
+      <fileset dir="input" includes="replacetokens.test"/>
       <filterchain>
       	<filterreader classname="org.apache.tools.ant.filters.ReplaceTokens">
           <param type="propertiesfile" value="${basedir}/input/sample.properties"/>
-    	  </filterreader>
+        </filterreader>
       </filterchain>
     </copy>
   </target>
 
   <target name="testReplaceTokensDoubleEncoded" depends="setUp">
-    <copy todir="${output}">
-      <fileset dir="input" includes="replacetokens.double.test" />
+    <copy tofile="${output}/replaceTokensDoubleEncoded.test">
+      <fileset dir="input" includes="replacetokens.double.test"/>
       <filterchain>
         <replacetokens>
           <token key="foo" value=""/>
@@ -112,8 +113,8 @@
   </target>
 
   <target name="testReplaceTokensDoubleEncodedToSimple" depends="setUp">
-    <copy todir="${output}">
-      <fileset dir="input" includes="replacetokens.double.test" />
+    <copy tofile="${output}/replaceTokensDoubleEncodedToSimple.test">
+      <fileset dir="input" includes="replacetokens.double.test"/>
       <filterchain>
         <replacetokens begintoken="@@" endtoken="@@">
           <token key="foo" value=""/>
@@ -123,8 +124,8 @@
   </target>
 
   <target name="testReplaceTokensMustacheStyle" depends="setUp">
-    <copy todir="${output}">
-      <fileset dir="input" includes="replacetokens.mustache.test" />
+    <copy tofile="${output}/replaceTokensMustacheStyle.test">
+      <fileset dir="input" includes="replacetokens.mustache.test"/>
       <filterchain>
         <replacetokens begintoken="{{" endtoken="}}">
           <token key="foo" value=""/>
@@ -144,4 +145,31 @@
     <fail unless="filterchain.files.are.same">File was modified</fail>
   </target>
 
+  <target name="testMatchAny" depends="setUp">
+    <copy todir="${output}">
+      <fileset dir="input">
+        <include name="linecontains.test"/>
+      </fileset>
+      <filterchain>
+        <linecontains matchAny="true">
+          <contains value="beta"/>
+          <contains value="alpha"/>
+        </linecontains>
+      </filterchain>
+    </copy>
+  </target>
+
+  <target name="testMatchAnyNegate" depends="setUp">
+    <copy todir="${output}">
+      <fileset dir="input">
+        <include name="linecontains.test"/>
+      </fileset>
+      <filterchain>
+        <linecontains matchAny="true" negate="true">
+          <contains value="beta"/>
+          <contains value="alpha"/>
+        </linecontains>
+      </filterchain>
+    </copy>
+  </target>
 </project>
diff --git a/src/etc/testcases/filters/concat.xml b/src/etc/testcases/filters/concat.xml
index 262dd16..3877f46 100644
--- a/src/etc/testcases/filters/concat.xml
+++ b/src/etc/testcases/filters/concat.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/filters/dynamicfilter.xml b/src/etc/testcases/filters/dynamicfilter.xml
index cb52d21..bd9620f 100644
--- a/src/etc/testcases/filters/dynamicfilter.xml
+++ b/src/etc/testcases/filters/dynamicfilter.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -20,17 +20,15 @@
   <import file="../buildfiletest-base.xml"/>
 
   <target name="setUp">
-    <mkdir dir="${output}" />
+    <mkdir dir="${output}"/>
   </target>
 
   <target name="dynamicfilter">
     <path id="test-classes">
-      <pathelement location="../../../../build/testcases" />
-      <pathelement path="${java.class.path}" />
+      <pathelement path="${java.class.path}"/>
     </path>
-    <typedef 
-      name="customfilter" 
-      classname="org.apache.tools.ant.filters.DynamicFilterTest$CustomFilter">
+    <typedef name="customfilter"
+             classname="org.apache.tools.ant.filters.DynamicFilterTest$CustomFilter">
       <classpath refid="test-classes"/>
     </typedef>
     
diff --git a/src/etc/testcases/filters/expected/linecontains-matchany-negate.test b/src/etc/testcases/filters/expected/linecontains-matchany-negate.test
new file mode 100644
index 0000000..9dacab9
--- /dev/null
+++ b/src/etc/testcases/filters/expected/linecontains-matchany-negate.test
@@ -0,0 +1,2 @@
+This is line 4 with gamma.
+This is line 6 with delta.
diff --git a/src/etc/testcases/filters/expected/linecontains-matchany.test b/src/etc/testcases/filters/expected/linecontains-matchany.test
new file mode 100644
index 0000000..0a472b2
--- /dev/null
+++ b/src/etc/testcases/filters/expected/linecontains-matchany.test
@@ -0,0 +1,5 @@
+This is line 1 with alpha.
+This is line 2 with beta.
+This is line 3 with beta.
+This is line 5 with beta.
+This is line 7 with beta.
diff --git a/src/etc/testcases/filters/head-tail.xml b/src/etc/testcases/filters/head-tail.xml
index e0ffed7..5bb3492 100644
--- a/src/etc/testcases/filters/head-tail.xml
+++ b/src/etc/testcases/filters/head-tail.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -23,7 +23,6 @@
     <mkdir dir="${output}" />
   </target>
 
-
   <!-- Testcases for HeadFilter -->
 
   <target name="testHead" depends="setUp">
@@ -135,7 +134,7 @@
   <!-- Testcases for combined scenarios -->
 
   <target name="testHeadTail" depends="setUp">
-    <copy file="input/head-tail.test" tofile="${output}/head-tail.headtail.test">
+    <copy file="input/head-tail.test" tofile="${output}/head-tail.headTail.test">
       <filterchain>
         <headfilter lines="4"/>
         <tailfilter lines="2"/>
diff --git a/src/etc/testcases/filters/input/sample.properties b/src/etc/testcases/filters/input/sample.properties
index 572e79d..3d316f6 100644
--- a/src/etc/testcases/filters/input/sample.properties
+++ b/src/etc/testcases/filters/input/sample.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/filters/tokenfilter.xml b/src/etc/testcases/filters/tokenfilter.xml
index b1b5aef..cc4b234 100644
--- a/src/etc/testcases/filters/tokenfilter.xml
+++ b/src/etc/testcases/filters/tokenfilter.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -20,7 +20,7 @@
   <import file="../buildfiletest-base.xml"/>
 
   <target name="setUp">
-    <mkdir dir="${output}" />
+    <mkdir dir="${output}"/>
   </target>
 
   <target name="tokenfilter">
@@ -314,14 +314,11 @@
 
   <target name="customtokenfilter">
     <path id="test-classes">
-      <pathelement location="../../../../build/testcases" />
-      <pathelement path="${java.class.path}" />
+      <pathelement path="${java.class.path}"/>
     </path>
 
-
-    <typedef 
-      name="capitalize" 
-      classname="org.apache.tools.ant.filters.TokenFilterTest$Capitalize">
+    <typedef name="capitalize"
+             classname="org.apache.tools.ant.filters.TokenFilterTest$Capitalize">
       <classpath refid="test-classes"/>
     </typedef>
     
diff --git a/src/etc/testcases/taskdefs/abstractcvstask.xml b/src/etc/testcases/taskdefs/abstractcvstask.xml
index 5de8b5e..c63fc02 100644
--- a/src/etc/testcases/taskdefs/abstractcvstask.xml
+++ b/src/etc/testcases/taskdefs/abstractcvstask.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/ant.topleveltest.xml b/src/etc/testcases/taskdefs/ant.topleveltest.xml
index 65bc729..c43d3f3 100644
--- a/src/etc/testcases/taskdefs/ant.topleveltest.xml
+++ b/src/etc/testcases/taskdefs/ant.topleveltest.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/ant.xml b/src/etc/testcases/taskdefs/ant.xml
index 33ef1da..c659e3c 100644
--- a/src/etc/testcases/taskdefs/ant.xml
+++ b/src/etc/testcases/taskdefs/ant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/ant/ant.xml b/src/etc/testcases/taskdefs/ant/ant.xml
index 52c9a70..486d6e2 100644
--- a/src/etc/testcases/taskdefs/ant/ant.xml
+++ b/src/etc/testcases/taskdefs/ant/ant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/ant/references.xml b/src/etc/testcases/taskdefs/ant/references.xml
index 0f3a693..d91e660 100644
--- a/src/etc/testcases/taskdefs/ant/references.xml
+++ b/src/etc/testcases/taskdefs/ant/references.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/antlib.current-test.xml b/src/etc/testcases/taskdefs/antlib.current-test.xml
index 0ad44db..c16bee6 100644
--- a/src/etc/testcases/taskdefs/antlib.current-test.xml
+++ b/src/etc/testcases/taskdefs/antlib.current-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/antlib.xml b/src/etc/testcases/taskdefs/antlib.xml
index d1c4061..da46d93 100644
--- a/src/etc/testcases/taskdefs/antlib.xml
+++ b/src/etc/testcases/taskdefs/antlib.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -17,11 +17,8 @@
 -->
 <project name="test">
 
-  <property name="testcases.dir" location="../../../../build/testcases"/>
-
   <path id="testclasses">
-    <pathelement location="${testcases.dir}" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="antlib.file">
@@ -32,14 +29,14 @@
 
   <target name="antlib.resource">
     <typedef resource="taskdefs/test.antlib.xml">
-        <classpath>
-            <!-- To load the task classes: -->
-            <path refid="testclasses"/>
-            <!-- For test.antlib.xml: -->
-            <pathelement location=".."/>
-            <!-- For test2.antlib.xml: -->
-            <pathelement location="${testcases.dir}/org/apache/tools/ant/taskdefs/test2-antlib.jar"/>
-        </classpath>
+      <classpath>
+        <!-- To load the task classes: -->
+        <path refid="testclasses"/>
+        <!-- For test.antlib.xml: -->
+        <pathelement location=".."/>
+        <!-- For test2.antlib.xml: -->
+        <pathelement location="${build.tests.value}/org/apache/tools/ant/taskdefs/test2-antlib.jar"/>
+      </classpath>
     </typedef>
     <mytask/>
     <echo>-and-then-</echo>
@@ -59,7 +56,7 @@
 
   <target name="antlib_uri_auto" xmlns:ex="antlib:org.example.tasks">
     <ex:simple>
-      <echo message="inside simple" />
+      <echo message="inside simple"/>
     </ex:simple>
   </target>
 
@@ -69,4 +66,4 @@
     </ex:simple>
   </target>
   
-</project>
\ No newline at end of file
+</project>
diff --git a/src/etc/testcases/taskdefs/antstructure.xml b/src/etc/testcases/taskdefs/antstructure.xml
index 516a973..71b1c1a 100644
--- a/src/etc/testcases/taskdefs/antstructure.xml
+++ b/src/etc/testcases/taskdefs/antstructure.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/available.xml b/src/etc/testcases/taskdefs/available.xml
index 324c054..78b1981 100644
--- a/src/etc/testcases/taskdefs/available.xml
+++ b/src/etc/testcases/taskdefs/available.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/bar.properties b/src/etc/testcases/taskdefs/bar.properties
index c64b91e..2899fe4 100644
--- a/src/etc/testcases/taskdefs/bar.properties
+++ b/src/etc/testcases/taskdefs/bar.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/basename.xml b/src/etc/testcases/taskdefs/basename.xml
index c5fd2ab..627b2ff 100644
--- a/src/etc/testcases/taskdefs/basename.xml
+++ b/src/etc/testcases/taskdefs/basename.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/bunzip2.xml b/src/etc/testcases/taskdefs/bunzip2.xml
index 8ae1758..11e15f5 100644
--- a/src/etc/testcases/taskdefs/bunzip2.xml
+++ b/src/etc/testcases/taskdefs/bunzip2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/bzip2.xml b/src/etc/testcases/taskdefs/bzip2.xml
index e133dae..8ddf8eb 100644
--- a/src/etc/testcases/taskdefs/bzip2.xml
+++ b/src/etc/testcases/taskdefs/bzip2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/calltarget.xml b/src/etc/testcases/taskdefs/calltarget.xml
index 4c3af92..7927ec9 100644
--- a/src/etc/testcases/taskdefs/calltarget.xml
+++ b/src/etc/testcases/taskdefs/calltarget.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/checksum.xml b/src/etc/testcases/taskdefs/checksum.xml
index e82fb69..1013d56 100644
--- a/src/etc/testcases/taskdefs/checksum.xml
+++ b/src/etc/testcases/taskdefs/checksum.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/classloader.xml b/src/etc/testcases/taskdefs/classloader.xml
index 02e47ab..3689a90 100644
--- a/src/etc/testcases/taskdefs/classloader.xml
+++ b/src/etc/testcases/taskdefs/classloader.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/concat.xml b/src/etc/testcases/taskdefs/concat.xml
index 235b152..8879f4f 100644
--- a/src/etc/testcases/taskdefs/concat.xml
+++ b/src/etc/testcases/taskdefs/concat.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/condition.xml b/src/etc/testcases/taskdefs/condition.xml
index 81660ae..ab56884 100644
--- a/src/etc/testcases/taskdefs/condition.xml
+++ b/src/etc/testcases/taskdefs/condition.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/antversion.xml b/src/etc/testcases/taskdefs/conditions/antversion.xml
index c97da9f..75d1017 100644
--- a/src/etc/testcases/taskdefs/conditions/antversion.xml
+++ b/src/etc/testcases/taskdefs/conditions/antversion.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -32,11 +32,10 @@
                 <fail>
                         <condition>
                                 <not>
-                                        <antversion exactly="1.9.17" />
+                                        <antversion exactly="1.10.13" />
                                 </not>
                         </condition>
-                        Should be exactly 1.9.17
-
+                        Should be exactly 1.10.13
                 </fail>
         </target>
 
@@ -45,10 +44,10 @@
                 <fail>
                         <condition>
                                 <not>
-                                        <antversion atleast="1.9.17" />
+                                        <antversion atleast="1.9.8" />
                                 </not>
                         </condition>
-                Should be at least 1.9.17
+                Should be at least 1.9.8
                 </fail>
         </target>
 
@@ -57,10 +56,10 @@
                 <fail>
                         <condition>
                                 <not>
-                                        <antversion exactly="1.9.17" />
+                                        <antversion exactly="1.9.8" />
                                 </not>
                         </condition>
-                  Should be exactly 1.9.17
+                  Should be exactly 1.9.8
                 </fail>
         </target>
 </project>
diff --git a/src/etc/testcases/taskdefs/conditions/http.xml b/src/etc/testcases/taskdefs/conditions/http.xml
index 76e87cb..76ae9fa 100644
--- a/src/etc/testcases/taskdefs/conditions/http.xml
+++ b/src/etc/testcases/taskdefs/conditions/http.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -23,34 +23,34 @@
 
   <target name="basic-no-method">
       <condition property="basic-no-method">
-          <http url="http://ant.apache.org/"/>
+          <http url="https://ant.apache.org/"/>
       </condition>
       <condition property="basic-no-method-bad-url">
-          <http url="http://ant.apache.org/this-page-does-not-exist"/>
+          <http url="https://ant.apache.org/this-page-does-not-exist"/>
       </condition>
   </target>
 
   <target name="test-head-request">
       <condition property="test-head-request">
-          <http url="http://ant.apache.org/" requestMethod="HEAD"/>
+          <http url="https://ant.apache.org/" requestMethod="HEAD"/>
       </condition>
       <condition property="test-head-request-bad-url">
-          <http url="http://ant.apache.org/this-page-does-not-exist" requestMethod="HEAD"/>
+          <http url="https://ant.apache.org/this-page-does-not-exist" requestMethod="HEAD"/>
       </condition>
   </target>
 
   <target name="test-get-request">
       <condition property="test-get-request">
-          <http url="http://ant.apache.org/" requestMethod="GET"/>
+          <http url="https://ant.apache.org/" requestMethod="GET"/>
       </condition>
       <condition property="test-get-request-bad-url">
-          <http url="http://ant.apache.org/this-page-does-not-exist" requestMethod="GET"/>
+          <http url="https://ant.apache.org/this-page-does-not-exist" requestMethod="GET"/>
       </condition>
   </target>
 
   <target name="bad-request-method">
       <condition property="bad-request-method">
-          <http url="http://ant.apache.org" requestMethod="UNKNOWN"/>
+          <http url="https://ant.apache.org" requestMethod="UNKNOWN"/>
       </condition>
   </target>
 
diff --git a/src/etc/testcases/taskdefs/conditions/isfailure.xml b/src/etc/testcases/taskdefs/conditions/isfailure.xml
index b5d1a6a..005139c 100644
--- a/src/etc/testcases/taskdefs/conditions/isfailure.xml
+++ b/src/etc/testcases/taskdefs/conditions/isfailure.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/isfileselected.xml b/src/etc/testcases/taskdefs/conditions/isfileselected.xml
index 0626eed..79c88b5 100644
--- a/src/etc/testcases/taskdefs/conditions/isfileselected.xml
+++ b/src/etc/testcases/taskdefs/conditions/isfileselected.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/isreachable.xml b/src/etc/testcases/taskdefs/conditions/isreachable.xml
index 3f74aef..4369db6 100644
--- a/src/etc/testcases/taskdefs/conditions/isreachable.xml
+++ b/src/etc/testcases/taskdefs/conditions/isreachable.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/isreference.xml b/src/etc/testcases/taskdefs/conditions/isreference.xml
index d1f86db..94217c1 100644
--- a/src/etc/testcases/taskdefs/conditions/isreference.xml
+++ b/src/etc/testcases/taskdefs/conditions/isreference.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/issigned.xml b/src/etc/testcases/taskdefs/conditions/issigned.xml
index 7cbf328..1554aec 100644
--- a/src/etc/testcases/taskdefs/conditions/issigned.xml
+++ b/src/etc/testcases/taskdefs/conditions/issigned.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/parsersupports.xml b/src/etc/testcases/taskdefs/conditions/parsersupports.xml
index c80fd35..feadcf3 100644
--- a/src/etc/testcases/taskdefs/conditions/parsersupports.xml
+++ b/src/etc/testcases/taskdefs/conditions/parsersupports.xml
@@ -8,7 +8,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/typefound.xml b/src/etc/testcases/taskdefs/conditions/typefound.xml
index 054ca67..080c939 100644
--- a/src/etc/testcases/taskdefs/conditions/typefound.xml
+++ b/src/etc/testcases/taskdefs/conditions/typefound.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/conditions/xor.xml b/src/etc/testcases/taskdefs/conditions/xor.xml
index 895dccd..8227949 100644
--- a/src/etc/testcases/taskdefs/conditions/xor.xml
+++ b/src/etc/testcases/taskdefs/conditions/xor.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/copy.xml b/src/etc/testcases/taskdefs/copy.xml
index 2601556..8780980 100644
--- a/src/etc/testcases/taskdefs/copy.xml
+++ b/src/etc/testcases/taskdefs/copy.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/copydir.xml b/src/etc/testcases/taskdefs/copydir.xml
index 8a8abd3..8cf0873 100644
--- a/src/etc/testcases/taskdefs/copydir.xml
+++ b/src/etc/testcases/taskdefs/copydir.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/copyfile.xml b/src/etc/testcases/taskdefs/copyfile.xml
index 0f8c9ab..406e0f0 100644
--- a/src/etc/testcases/taskdefs/copyfile.xml
+++ b/src/etc/testcases/taskdefs/copyfile.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/cvspass.xml b/src/etc/testcases/taskdefs/cvspass.xml
index bbca110..6adecc1 100644
--- a/src/etc/testcases/taskdefs/cvspass.xml
+++ b/src/etc/testcases/taskdefs/cvspass.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/defaultexcludes.xml b/src/etc/testcases/taskdefs/defaultexcludes.xml
index 4629250..65bf37f 100644
--- a/src/etc/testcases/taskdefs/defaultexcludes.xml
+++ b/src/etc/testcases/taskdefs/defaultexcludes.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/delete.xml b/src/etc/testcases/taskdefs/delete.xml
index d74c8ba..ee4c7fa 100644
--- a/src/etc/testcases/taskdefs/delete.xml
+++ b/src/etc/testcases/taskdefs/delete.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -20,7 +20,6 @@
 
   <import file="../buildfiletest-base.xml"/>
 
-
   <property name="dir" location="${output}" />
   <basename property="dirname" file="${output}"/>
 
diff --git a/src/etc/testcases/taskdefs/deltree.xml b/src/etc/testcases/taskdefs/deltree.xml
index c69d51f..f353343 100644
--- a/src/etc/testcases/taskdefs/deltree.xml
+++ b/src/etc/testcases/taskdefs/deltree.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/dirname.xml b/src/etc/testcases/taskdefs/dirname.xml
index 1027db1..dafae92 100644
--- a/src/etc/testcases/taskdefs/dirname.xml
+++ b/src/etc/testcases/taskdefs/dirname.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/dynamictask.xml b/src/etc/testcases/taskdefs/dynamictask.xml
index 307181f..50e33f6 100644
--- a/src/etc/testcases/taskdefs/dynamictask.xml
+++ b/src/etc/testcases/taskdefs/dynamictask.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -19,14 +19,13 @@
 <project name="dynamic-test" default="simple">
 
   <path id="testclasses">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="simple">
     <taskdef name="dyna"
              classname="org.apache.tools.ant.taskdefs.DynamicTask">
-      <classpath refid="testclasses" />
+      <classpath refid="testclasses"/>
     </taskdef>
     <dyna prop1="1" prop2="2">
       <sub prop3="3"/>
diff --git a/src/etc/testcases/taskdefs/echoxml.xml b/src/etc/testcases/taskdefs/echoxml.xml
index ec53abb..9ee819a 100644
--- a/src/etc/testcases/taskdefs/echoxml.xml
+++ b/src/etc/testcases/taskdefs/echoxml.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/email/mail.xml b/src/etc/testcases/taskdefs/email/mail.xml
index 5144b7a..12c315b 100644
--- a/src/etc/testcases/taskdefs/email/mail.xml
+++ b/src/etc/testcases/taskdefs/email/mail.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/exec/blabla.sh b/src/etc/testcases/taskdefs/exec/blabla.sh
index c996d6a..76a4189 100644
--- a/src/etc/testcases/taskdefs/exec/blabla.sh
+++ b/src/etc/testcases/taskdefs/exec/blabla.sh
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/exec/exec-with-redirector.xml b/src/etc/testcases/taskdefs/exec/exec-with-redirector.xml
index 27b680d..8fbcc8c 100644
--- a/src/etc/testcases/taskdefs/exec/exec-with-redirector.xml
+++ b/src/etc/testcases/taskdefs/exec/exec-with-redirector.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/exec/exec.xml b/src/etc/testcases/taskdefs/exec/exec.xml
index 20e5656..998cb06 100644
--- a/src/etc/testcases/taskdefs/exec/exec.xml
+++ b/src/etc/testcases/taskdefs/exec/exec.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/exec/parrot.sh b/src/etc/testcases/taskdefs/exec/parrot.sh
index c064c38..c2c087b 100755
--- a/src/etc/testcases/taskdefs/exec/parrot.sh
+++ b/src/etc/testcases/taskdefs/exec/parrot.sh
@@ -6,7 +6,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/exec/spawn.sh b/src/etc/testcases/taskdefs/exec/spawn.sh
index a639ce5..09556f8 100755
--- a/src/etc/testcases/taskdefs/exec/spawn.sh
+++ b/src/etc/testcases/taskdefs/exec/spawn.sh
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/expected/asf-logo.gif.xz b/src/etc/testcases/taskdefs/expected/asf-logo.gif.xz
new file mode 100644
index 0000000..139eea4
--- /dev/null
+++ b/src/etc/testcases/taskdefs/expected/asf-logo.gif.xz
Binary files differ
diff --git a/src/etc/testcases/taskdefs/fail.xml b/src/etc/testcases/taskdefs/fail.xml
index 0a6561e..b5eaba4 100644
--- a/src/etc/testcases/taskdefs/fail.xml
+++ b/src/etc/testcases/taskdefs/fail.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/filter.xml b/src/etc/testcases/taskdefs/filter.xml
index 303efa7..0e109be 100644
--- a/src/etc/testcases/taskdefs/filter.xml
+++ b/src/etc/testcases/taskdefs/filter.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/filterdefs.properties b/src/etc/testcases/taskdefs/filterdefs.properties
index f099df3..046ad79 100644
--- a/src/etc/testcases/taskdefs/filterdefs.properties
+++ b/src/etc/testcases/taskdefs/filterdefs.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/fixcrlf/build.xml b/src/etc/testcases/taskdefs/fixcrlf/build.xml
index e2fecac..c2d9dc1 100644
--- a/src/etc/testcases/taskdefs/fixcrlf/build.xml
+++ b/src/etc/testcases/taskdefs/fixcrlf/build.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/foo.properties b/src/etc/testcases/taskdefs/foo.properties
index e4a8152..4e20549 100644
--- a/src/etc/testcases/taskdefs/foo.properties
+++ b/src/etc/testcases/taskdefs/foo.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/get.xml b/src/etc/testcases/taskdefs/get.xml
index b74e92a..a10a414 100644
--- a/src/etc/testcases/taskdefs/get.xml
+++ b/src/etc/testcases/taskdefs/get.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -35,11 +35,11 @@
   </target>
 
   <target name="test5">
-    <get src="http://www.apache.org/" dest=""/>
+    <get src="https://www.apache.org/" dest=""/>
   </target>
 
   <target name="test6">
-    <get src="http://www.apache.org/" dest="get.tmp" userAgent="Apache Ant/test"/>
+    <get src="https://www.apache.org/" dest="get.tmp" userAgent="Apache Ant/test"/>
 
     <fileset id="t6" file="get.tmp" />
     <pathconvert property="t6" refid="t6" setonempty="false" />
@@ -80,7 +80,7 @@
 
     <touch file="get.tmp" datetime="${dt}" pattern="${pat}" />
 
-    <get src="http://www.w3.org/MarkUp" dest="get.tmp"
+    <get src="https://www.w3.org/MarkUp" dest="get.tmp"
          usetimestamp="true" verbose="true" />
 
     <fileset id="ts" file="get.tmp">
@@ -98,6 +98,34 @@
     </fail>
   </target>
 
+  <target name="testTwoHeadersAreAddedOK">
+    <get src="https://www.apache.org/" dest="get.tmp">
+      <header name="header1" value="header1Value"/>
+      <header name="header2" value="header2Value"/>
+    </get>
+  </target>
+
+  <target name="testEmptyHeadersAreNeverAdded">
+    <get src="https://www.apache.org/" dest="get.tmp">
+      <header name="" value="headerValue"/>
+      <header name="header2" value=""/>
+    </get>
+  </target>
+
+  <target name="testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded">
+    <get src="https://www.apache.org/" dest="get.tmp">
+      <header name="header1" value="headerValue1"/>
+      <header name="header1" value="headerValue2"/>
+      <header name="header1" value="headerValue3"/>
+    </get>
+  </target>
+
+  <target name="testHeaderSpaceTrimmed">
+    <get src="https://www.apache.org/" dest="get.tmp">
+      <header name="  header1     " value="  headerValue1  "/>
+    </get>
+  </target>
+
   <target name="cleanup">
     <delete>
       <fileset dir="${basedir}" includes="get.tmp" />
diff --git a/src/etc/testcases/taskdefs/gunzip.xml b/src/etc/testcases/taskdefs/gunzip.xml
index ea75d54..2b9402a 100644
--- a/src/etc/testcases/taskdefs/gunzip.xml
+++ b/src/etc/testcases/taskdefs/gunzip.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/gzip.xml b/src/etc/testcases/taskdefs/gzip.xml
index f1c4262..c7046cd 100644
--- a/src/etc/testcases/taskdefs/gzip.xml
+++ b/src/etc/testcases/taskdefs/gzip.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/a.xml b/src/etc/testcases/taskdefs/import/a.xml
index cf4e7a5..35e2805 100644
--- a/src/etc/testcases/taskdefs/import/a.xml
+++ b/src/etc/testcases/taskdefs/import/a.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/b.xml b/src/etc/testcases/taskdefs/import/b.xml
index f95cf01..f3f943d 100644
--- a/src/etc/testcases/taskdefs/import/b.xml
+++ b/src/etc/testcases/taskdefs/import/b.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/bad.xml b/src/etc/testcases/taskdefs/import/bad.xml
index a3a0647..f02f370 100644
--- a/src/etc/testcases/taskdefs/import/bad.xml
+++ b/src/etc/testcases/taskdefs/import/bad.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/c.xml b/src/etc/testcases/taskdefs/import/c.xml
index d92fbc7..2595054 100644
--- a/src/etc/testcases/taskdefs/import/c.xml
+++ b/src/etc/testcases/taskdefs/import/c.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/import.xml b/src/etc/testcases/taskdefs/import/import.xml
index f84d8e3..2070c67 100644
--- a/src/etc/testcases/taskdefs/import/import.xml
+++ b/src/etc/testcases/taskdefs/import/import.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/import_bad_import.xml b/src/etc/testcases/taskdefs/import/import_bad_import.xml
index 8ff5367..82f5f56 100644
--- a/src/etc/testcases/taskdefs/import/import_bad_import.xml
+++ b/src/etc/testcases/taskdefs/import/import_bad_import.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/import_same_target.xml b/src/etc/testcases/taskdefs/import/import_same_target.xml
index f2b1933..50923ac 100644
--- a/src/etc/testcases/taskdefs/import/import_same_target.xml
+++ b/src/etc/testcases/taskdefs/import/import_same_target.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/imported.xml b/src/etc/testcases/taskdefs/import/imported.xml
index 19dfdb0..dcbb9aa 100644
--- a/src/etc/testcases/taskdefs/import/imported.xml
+++ b/src/etc/testcases/taskdefs/import/imported.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/importtargetfirst.xml b/src/etc/testcases/taskdefs/import/importtargetfirst.xml
index 835191b..5689ba9 100644
--- a/src/etc/testcases/taskdefs/import/importtargetfirst.xml
+++ b/src/etc/testcases/taskdefs/import/importtargetfirst.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/recursive-selfimport.xml b/src/etc/testcases/taskdefs/import/recursive-selfimport.xml
index d5ae3b2..6cd8b91 100644
--- a/src/etc/testcases/taskdefs/import/recursive-selfimport.xml
+++ b/src/etc/testcases/taskdefs/import/recursive-selfimport.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/import/same_target.xml b/src/etc/testcases/taskdefs/import/same_target.xml
index 1a14fe5..264b7dc 100644
--- a/src/etc/testcases/taskdefs/import/same_target.xml
+++ b/src/etc/testcases/taskdefs/import/same_target.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/subdir/importinsequential-inner.xml b/src/etc/testcases/taskdefs/import/subdir/importinsequential-inner.xml
index cc2a681..c462b8b 100644
--- a/src/etc/testcases/taskdefs/import/subdir/importinsequential-inner.xml
+++ b/src/etc/testcases/taskdefs/import/subdir/importinsequential-inner.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/subdir/importinsequential.xml b/src/etc/testcases/taskdefs/import/subdir/importinsequential.xml
index fdd68b0..853334c 100644
--- a/src/etc/testcases/taskdefs/import/subdir/importinsequential.xml
+++ b/src/etc/testcases/taskdefs/import/subdir/importinsequential.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/subdir/importintarget-inner.xml b/src/etc/testcases/taskdefs/import/subdir/importintarget-inner.xml
index cd5086e..24c1b28 100644
--- a/src/etc/testcases/taskdefs/import/subdir/importintarget-inner.xml
+++ b/src/etc/testcases/taskdefs/import/subdir/importintarget-inner.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/subdir/importintarget.xml b/src/etc/testcases/taskdefs/import/subdir/importintarget.xml
index 2dfa370..50847cd 100644
--- a/src/etc/testcases/taskdefs/import/subdir/importintarget.xml
+++ b/src/etc/testcases/taskdefs/import/subdir/importintarget.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/subdir/serial.xml b/src/etc/testcases/taskdefs/import/subdir/serial.xml
index 360f9d1..99c6372 100644
--- a/src/etc/testcases/taskdefs/import/subdir/serial.xml
+++ b/src/etc/testcases/taskdefs/import/subdir/serial.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/symlinks/d1/p1.xml b/src/etc/testcases/taskdefs/import/symlinks/d1/p1.xml
index d1b792c..5cca2f5 100644
--- a/src/etc/testcases/taskdefs/import/symlinks/d1/p1.xml
+++ b/src/etc/testcases/taskdefs/import/symlinks/d1/p1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/symlinks/d2/p2.xml b/src/etc/testcases/taskdefs/import/symlinks/d2/p2.xml
index 51948c9..7908355 100644
--- a/src/etc/testcases/taskdefs/import/symlinks/d2/p2.xml
+++ b/src/etc/testcases/taskdefs/import/symlinks/d2/p2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/symlinks/d3a/p3.xml b/src/etc/testcases/taskdefs/import/symlinks/d3a/p3.xml
index 3185845..3f08ba0 100644
--- a/src/etc/testcases/taskdefs/import/symlinks/d3a/p3.xml
+++ b/src/etc/testcases/taskdefs/import/symlinks/d3a/p3.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/targetfirst.xml b/src/etc/testcases/taskdefs/import/targetfirst.xml
index 06c1fbe..d5a545c 100644
--- a/src/etc/testcases/taskdefs/import/targetfirst.xml
+++ b/src/etc/testcases/taskdefs/import/targetfirst.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/unnamed1.xml b/src/etc/testcases/taskdefs/import/unnamed1.xml
index 6fc7fde..d923719 100644
--- a/src/etc/testcases/taskdefs/import/unnamed1.xml
+++ b/src/etc/testcases/taskdefs/import/unnamed1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/unnamed2.xml b/src/etc/testcases/taskdefs/import/unnamed2.xml
index c0fd7c6..400cc71 100644
--- a/src/etc/testcases/taskdefs/import/unnamed2.xml
+++ b/src/etc/testcases/taskdefs/import/unnamed2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/import/unnamedImport.xml b/src/etc/testcases/taskdefs/import/unnamedImport.xml
index 13b3a85..9e1845f 100644
--- a/src/etc/testcases/taskdefs/import/unnamedImport.xml
+++ b/src/etc/testcases/taskdefs/import/unnamedImport.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/initializeclass.xml b/src/etc/testcases/taskdefs/initializeclass.xml
index 6e07991..24bd370 100644
--- a/src/etc/testcases/taskdefs/initializeclass.xml
+++ b/src/etc/testcases/taskdefs/initializeclass.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -22,10 +22,9 @@
   <target name="forked">
     <java fork="true" output="forkedout" failonerror="true"
           className="org.apache.tools.ant.taskdefs.dir1.B">
-
       <classpath>
-        <pathelement path="../../../../build/testcases"/>
-        <pathelement location="${java.home}/lib/classes.zip" />
+        <pathelement path="${build.tests.value}"/>
+        <pathelement location="${java.home}/lib/classes.zip"/>
       </classpath>
     </java>
   </target>
@@ -33,8 +32,8 @@
   <target name="unforked">
     <java className="org.apache.tools.ant.taskdefs.dir1.B">
       <classpath>
-        <pathelement path="../../../../build/testcases"/>
-        <pathelement location="${java.home}/lib/classes.zip" />
+        <pathelement path="${build.tests.value}"/>
+        <pathelement location="${java.home}/lib/classes.zip"/>
       </classpath>
     </java>
   </target>
diff --git a/src/etc/testcases/taskdefs/input.properties b/src/etc/testcases/taskdefs/input.properties
index c0025a3..5e93a6e 100644
--- a/src/etc/testcases/taskdefs/input.properties
+++ b/src/etc/testcases/taskdefs/input.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/input.xml b/src/etc/testcases/taskdefs/input.xml
index d204b79..cf41985 100644
--- a/src/etc/testcases/taskdefs/input.xml
+++ b/src/etc/testcases/taskdefs/input.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/jar.xml b/src/etc/testcases/taskdefs/jar.xml
index 78d1abc..0aaeeef 100644
--- a/src/etc/testcases/taskdefs/jar.xml
+++ b/src/etc/testcases/taskdefs/jar.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -121,7 +121,7 @@
          destfile="${tmp.jar}"
          basedir="."
          includes="j*.xml"
-         excludes="java.xml"
+         excludes="java.xml,jmod.xml"
          update="true"
     />
   </target>
@@ -131,7 +131,7 @@
          destfile="${tmp.jar}"
          basedir="."
          includes="j*.xml"
-         excludes="java.xml"
+         excludes="java.xml,jmod.xml"
     />
   </target>
 
@@ -144,14 +144,14 @@
           depends="makezip">
     <jar destfile="${tmp.jar}"
          update="true">
-      <zipfileset src="${tmp.zip}" excludes="java.xml"/>
+      <zipfileset src="${tmp.zip}" excludes="java.xml,jmod.xml"/>
     </jar>
   </target>
 
   <target name="testNoRecreateZipfilesetExcludesWithoutUpdate"
           depends="makezip">
     <jar destfile="${tmp.jar}">
-      <zipfileset src="${tmp.zip}" excludes="java.xml"/>
+      <zipfileset src="${tmp.zip}" excludes="java.xml,jmod.xml"/>
     </jar>
   </target>
 
@@ -248,7 +248,22 @@
       </indexjars>
     </jar>
   </target>
-    
+
+  <target name="testIndexJarsPlusJarMarkerWithMapping">
+    <mkdir dir="${tmp.dir}/a/b/c"/>
+    <jar destfile="${tmp.jar}" basedir="${tmp.dir}"/>
+    <delete dir="${tmp.dir}/a" quiet="true"/>
+    <mkdir dir="${tmp.dir}/d/e/f"/>
+    <jar destfile="${tmp.jar}2" basedir="${tmp.dir}" index="true">
+      <indexjars>
+        <fileset file="${tmp.jar}"/>
+      </indexjars>
+      <indexjarsmapper>
+        <globmapper from="${output}/*" to="foo/*" handledirsep="true"/>
+      </indexjarsmapper>
+    </jar>
+  </target>
+
   <target name="testNoVersionInfoNoStrict">
     <mkdir dir="${tmp.dir}"/>
     <jar destfile="${tmp.jar}" basedir="${tmp.dir}"/>
@@ -269,7 +284,7 @@
     <jar destfile="${tmp.jar}" basedir="${tmp.dir}" strict="warn"/>
   </target>  
     
-  <!-- see http://java.sun.com/j2se/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersioning -->  
+  <!-- see https://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html -->  
   <target name="testHasVersionInfo">
     <mkdir dir="${tmp.dir}"/>
     <jar destfile="${tmp.jar}" basedir="${tmp.dir}" strict="fail">
diff --git a/src/etc/testcases/taskdefs/java.xml b/src/etc/testcases/taskdefs/java.xml
index a3d3778..19f6aae 100644
--- a/src/etc/testcases/taskdefs/java.xml
+++ b/src/etc/testcases/taskdefs/java.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -424,4 +424,66 @@
 
     <target name="foo" />
 
+    <target name="simpleSourceFile"
+            description="Tests that the single source file programs, introduced in Java 11, works as expected">
+        <mkdir dir="${output}/javasource"/>
+        <echo file="${output}/javasource/A.java">
+            import java.nio.file.Files;
+            import java.nio.file.Paths;
+            import java.io.BufferedWriter;
+            public class A {
+                public static void main(String[] args) throws Exception {
+                    final String outFile = args[0];
+                    try(BufferedWriter bw = Files.newBufferedWriter(Paths.get(outFile));) {
+                        bw.write("Hello world!");
+                    }
+                }
+            }
+        </echo>
+        <java sourcefile="${output}/javasource/A.java" fork="true" failonerror="true" logerror="true">
+            <arg value="${output}/javasource/simpleSourceFileOutput.txt"/>
+        </java>
+        <loadfile property="simpleSourceFile.prog.output" srcfile="${output}/javasource/simpleSourceFileOutput.txt"/>
+        <condition property="simpleSourceFile.execution.success">
+            <equals arg1="${simpleSourceFile.prog.output}" arg2="Hello world!"/>
+        </condition>
+        <fail unless="simpleSourceFile.execution.success">Java source-file execution did not yield the expected
+            result</fail>
+    </target>
+
+
+    <target name="generateDummyJavaSource">
+        <mkdir dir="${output}/javasource"/>
+        <echo file="${output}/javasource/ThrowsException.java">
+            public class ThrowsException {
+                public static void main(String[] args) throws Exception {
+                    throw new RuntimeException("Wasn't expected to be run");
+                }
+            }
+        </echo>
+    </target>
+
+    <target name="sourceFileRequiresFork" depends="generateDummyJavaSource">
+        <java sourcefile="${output}/javasource/ThrowsException.java" failonerror="true" logerror="true"/>
+        <fail>Execution of java task, for sourcefile, was expected to fail since fork wasn't set</fail>
+    </target>
+
+    <target name="sourceFileCantUseClassname" depends="generateDummyJavaSource">
+        <java classname="foo.bar" sourcefile="${output}/javasource/ThrowsException.java"
+              fork="true" failonerror="true" logerror="true"/>
+        <fail>Execution of java task, for sourcefile, was expected to fail since classname attribute was set</fail>
+    </target>
+
+    <target name="sourceFileCantUseJar" depends="generateDummyJavaSource">
+        <java jar="irrelevant.jar" sourcefile="${output}/javasource/ThrowsException.java"
+              fork="true" failonerror="true" logerror="true"/>
+        <fail>Execution of java task, for sourcefile, was expected to fail since jar attribute was set</fail>
+    </target>
+
+    <target name="sourceFileCantUseModule" depends="generateDummyJavaSource">
+        <java module="irrelevant" sourcefile="${output}/javasource/ThrowsException.java"
+              fork="true" failonerror="true" logerror="true"/>
+        <fail>Execution of java task, for sourcefile, was expected to fail since module attribute was set</fail>
+    </target>
+
 </project>
diff --git a/src/etc/testcases/taskdefs/javadoc/java/ClassToJavadoc.java b/src/etc/testcases/taskdefs/javadoc/java/ClassToJavadoc.java
index bd8cab6..423934e 100644
--- a/src/etc/testcases/taskdefs/javadoc/java/ClassToJavadoc.java
+++ b/src/etc/testcases/taskdefs/javadoc/java/ClassToJavadoc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,15 +25,19 @@
     /**
      * @param anArgument A String that is ignored
      */
-    public void methodToJavadoc(String anArgument) { }
+    public void methodToJavadoc(String anArgument) {}
 
     /**
      * @see java.lang.Object#toString()
      */
-    public String toString() { return this.getClass().getName(); }
+    public String toString() {
+        return this.getClass().getName();
+    }
 
     /**
      * @return An arbitrary string.
      */
-    public String anotherString() {return "An arbitrary string.";}
+    public String anotherString() {
+        return "An arbitrary string.";
+    }
 }
diff --git a/src/etc/testcases/taskdefs/javadoc/javadoc.xml b/src/etc/testcases/taskdefs/javadoc/javadoc.xml
index 2a05ec0..4893cb6 100644
--- a/src/etc/testcases/taskdefs/javadoc/javadoc.xml
+++ b/src/etc/testcases/taskdefs/javadoc/javadoc.xml
@@ -7,7 +7,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/testcases/taskdefs/jmod.xml b/src/etc/testcases/taskdefs/jmod.xml
new file mode 100644
index 0000000..38ab346
--- /dev/null
+++ b/src/etc/testcases/taskdefs/jmod.xml
@@ -0,0 +1,1417 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project name="jmodtest" default="nil" >
+  <import file="../buildfiletest-base.xml"/>
+
+  <target name="nil"/>
+
+  <target name="-dirs">
+    <mkdir dir="${input}"/>
+    <mkdir dir="${output}"/>
+    <property name="jmod" value="${output}/test.jmod"/>
+    <property name="version" value="1.0.1-+99"/>
+  </target>
+
+  <target name="setUp" depends="-dirs">
+  </target>
+
+  <!-- Creates simple modular jar, with only Java SE dependencies. -->
+  <target name="-hello" depends="-dirs">
+
+    <property name="hello.root" value="${input}/hello"/>
+
+    <property name="hello.src" value="${hello.root}/src"/>
+    <property name="hello.classes" value="${hello.root}/classes"/>
+    <property name="hello.jar.dir" value="${hello.root}/jars"/>
+    <property name="hello.jar" value="${hello.jar.dir}/hello.jar"/>
+
+    <property name="hello.pkg"     value=             "org.apache.tools.ant.test.hello"/>
+    <property name="hello.pkg.dir" value="${hello.src}/org/apache/tools/ant/test/hello"/>
+
+    <property name="hello.main-class" value="${hello.pkg}.HelloWorld"/>
+
+    <mkdir dir="${hello.pkg.dir}"/>
+    <echo file="${hello.pkg.dir}/HelloWorld.java">
+package ${hello.pkg};
+
+import java.util.logging.Logger;
+
+public class HelloWorld {
+    public void run() {
+        Logger logger = Logger.getLogger(HelloWorld.class.getName());
+        logger.info("HELLO WORLD");
+    }
+
+    public static void main(String[] args) {
+        new HelloWorld().run();
+    }
+}
+    </echo>
+    <echo file="${hello.src}/module-info.java">
+module ${hello.pkg} {
+    exports ${hello.pkg};
+    requires java.logging;
+}
+    </echo>
+
+    <mkdir dir="${hello.classes}"/>
+    <javac srcdir="${hello.src}" destdir="${hello.classes}" includeAntRuntime="false"/>
+
+    <mkdir dir="${hello.jar.dir}"/>
+    <jar destfile="${hello.jar}" basedir="${hello.classes}"/>
+  </target>
+
+  <!-- Creates modular jar with dependency on hello module. -->
+  <target name="-smile" depends="-dirs,-hello">
+    <property name="smile.root" value="${input}/smile"/>
+
+    <property name="smile.src" value="${smile.root}/src"/>
+    <property name="smile.classes" value="${smile.root}/classes"/>
+    <property name="smile.jar.dir" value="${smile.root}/jars"/>
+    <property name="smile.jar" value="${smile.jar.dir}/smile.jar"/>
+
+    <property name="smile.pkg"     value=             "org.apache.tools.ant.test.smile"/>
+    <property name="smile.pkg.dir" value="${smile.src}/org/apache/tools/ant/test/smile"/>
+
+    <property name="smile.main-class" value="${smile.pkg}.Smile"/>
+
+    <mkdir dir="${smile.pkg.dir}"/>
+    <echo file="${smile.pkg.dir}/Smile.java">
+package ${smile.pkg};
+
+import java.util.logging.Logger;
+import ${hello.pkg}.HelloWorld;
+
+public class Smile {
+    public void run() {
+        Logger logger = Logger.getLogger(Smile.class.getName());
+        logger.info("\u263a\u263b\u263a\u263b");
+    }
+
+    public static void main(String[] args) {
+        new Smile().run();
+        new HelloWorld().run();
+    }
+}
+    </echo>
+    <echo file="${smile.src}/module-info.java">
+module ${smile.pkg} {
+    exports ${smile.pkg};
+    requires java.logging;
+    requires ${hello.pkg};
+}
+    </echo>
+
+    <mkdir dir="${smile.classes}"/>
+    <javac srcdir="${smile.src}" destdir="${smile.classes}"
+           includeAntRuntime="false"
+           modulepath="${hello.jar}"/>
+
+    <mkdir dir="${smile.jar.dir}"/>
+    <jar destfile="${smile.jar}" basedir="${smile.classes}"/>
+  </target>
+
+  <!-- Creates additional modular jar, with only Java SE dependencies. -->
+  <target name="-foobar" depends="-smile">
+
+    <property name="foobar.root" value="${input}/foobar"/>
+
+    <property name="foobar.src" value="${foobar.root}/src"/>
+    <property name="foobar.classes" value="${foobar.root}/classes"/>
+    <property name="foobar.jar.dir" value="${foobar.root}/jars"/>
+    <property name="foobar.jar" value="${foobar.jar.dir}/foobar.jar"/>
+
+    <property name="foobar.pkg"     value=             "org.apache.tools.ant.test.foobar"/>
+    <property name="foobar.pkg.dir" value="${foobar.src}/org/apache/tools/ant/test/foobar"/>
+
+    <property name="foobar.main-class" value="${foobar.pkg}.FooBar"/>
+
+    <mkdir dir="${foobar.pkg.dir}"/>
+    <echo file="${foobar.pkg.dir}/FooBar.java">
+package ${foobar.pkg};
+
+import ${hello.main-class};
+import ${smile.main-class};
+
+public class FooBar {
+    public void run() {
+        new HelloWorld().run();
+        new Smile().run();
+    }
+
+    public static void main(String[] args) {
+        new FooBar().run();
+    }
+}
+    </echo>
+    <echo file="${foobar.src}/module-info.java">
+module ${foobar.pkg} {
+    exports ${foobar.pkg};
+    requires java.logging;
+    requires ${hello.pkg};
+    requires ${smile.pkg};
+}
+    </echo>
+
+    <mkdir dir="${foobar.classes}"/>
+    <javac srcdir="${foobar.src}" destdir="${foobar.classes}"
+           includeAntRuntime="false" modulepath="${hello.jar};${smile.jar}"/>
+
+    <mkdir dir="${foobar.jar.dir}"/>
+    <jar destfile="${foobar.jar}" basedir="${foobar.classes}"/>
+  </target>
+
+  <target name="destAndClasspathNoJmod" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}"/>
+  </target>
+
+  <target name="destAndClasspathOlderThanJmod" depends="-hello">
+    <property name="dateformat" value="yyyy-MM-dd HH:mm:ss.SSS"/>
+    <tstamp>
+      <format property="future" pattern="${dateformat}" offset="1" unit="hour"/>
+    </tstamp>
+    <touch file="${jmod}" datetime="${future}" pattern="${dateformat}"/>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"/>
+  </target>
+
+  <target name="noDestFile">
+    <jmod classpath="."/>
+  </target>
+
+  <target name="noClasspath">
+    <jmod destfile="${jmod}"/>
+  </target>
+
+  <target name="emptyClasspath">
+    <jmod destfile="${jmod}" classpath=""/>
+  </target>
+
+  <target name="nonexistentClasspath">
+    <jmod destfile="${jmod}" classpath="dummy:dummy2"/>
+  </target>
+
+  <target name="classpathref" depends="-hello">
+    <path id="classpathref.testpath">
+      <pathelement location="${hello.jar}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpathref="classpathref.testpath"/>
+  </target>
+
+  <target name="classpath-nested" depends="-hello">
+    <jmod destfile="${jmod}">
+      <classpath>
+        <pathelement location="${hello.jar}"/>
+      </classpath>
+    </jmod>
+  </target>
+
+  <target name="classpath-both" depends="-smile">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <classpath>
+        <pathelement location="${smile.classes}"/>
+      </classpath>
+    </jmod>
+  </target>
+
+  <!-- modulepath targets -->
+
+  <target name="modulepath" depends="-smile">
+    <jmod destfile="${jmod}" classpath="${smile.jar}"
+        modulepath="${hello.jar.dir}"/>
+  </target>
+
+  <target name="modulepathref" depends="-smile">
+    <path id="modulepathref.testpath">
+      <pathelement location="${hello.jar.dir}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${smile.jar}"
+          modulepathref="modulepathref.testpath"/>
+  </target>
+
+  <target name="modulepath-nested" depends="-smile">
+    <jmod destfile="${jmod}" classpath="${smile.jar}">
+      <modulepath>
+        <pathelement location="${hello.jar.dir}"/>
+      </modulepath>
+    </jmod>
+  </target>
+
+  <target name="modulepath-both" depends="-smile,-foobar">
+    <jmod destfile="${jmod}" classpath="${foobar.jar}"
+          modulepath="${hello.jar.dir}">
+      <modulepath>
+        <pathelement location="${smile.jar.dir}"/>
+      </modulepath>
+    </jmod>
+  </target>
+
+  <target name="modulepathnondir" depends="-smile">
+    <jmod destfile="${jmod}" classpath="${smile.jar}"
+          modulepath="${hello.jar}"/>
+  </target>
+
+  <!-- commandpath targets -->
+
+  <target name="commandpath" depends="-hello">
+    <property name="commands" value="${output}/commands"/>
+    <mkdir dir="${commands}"/>
+
+    <property name="command1" value="${commands}/command1"/>
+
+    <echo file="${command1}">
+#!/bin/bash
+`dirname "$0"`/java -m ${hello.pkg}/${hello.pkg}.HelloWorld
+    </echo>
+    <setpermissions mode="777" nonPosixMode="tryDosOrPass">
+      <file file="${command1}"/>
+    </setpermissions>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          commandpath="${commands}"/>
+  </target>
+
+  <target name="commandpathref" depends="-hello">
+    <property name="commands" value="${output}/commands"/>
+    <mkdir dir="${commands}"/>
+
+    <property name="command2" value="${commands}/command2"/>
+
+    <echo file="${command2}">
+#!/bin/bash
+`dirname "$0"`/java -m ${hello.pkg}/${hello.pkg}.HelloWorld
+    </echo>
+    <setpermissions mode="777" nonPosixMode="tryDosOrPass">
+      <file file="${command2}"/>
+    </setpermissions>
+
+    <path id="commandpathref.testpath">
+      <pathelement location="${commands}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          commandpathref="commandpathref.testpath"/>
+  </target>
+
+  <target name="commandpath-nested" depends="-hello">
+    <property name="commands" value="${output}/commands"/>
+    <mkdir dir="${commands}"/>
+
+    <property name="command3" value="${commands}/command3"/>
+
+    <echo file="${command3}">
+#!/bin/bash
+`dirname "$0"`/java -m ${hello.pkg}/${hello.pkg}.HelloWorld
+    </echo>
+    <setpermissions mode="777" nonPosixMode="tryDosOrPass">
+      <file file="${command3}"/>
+    </setpermissions>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <commandpath>
+        <pathelement location="${commands}"/>
+      </commandpath>
+    </jmod>
+  </target>
+
+  <target name="commandpath-both" depends="-hello">
+    <property name="commands1" value="${output}/commands1"/>
+    <property name="commands2" value="${output}/commands2"/>
+    <mkdir dir="${commands1}"/>
+    <mkdir dir="${commands2}"/>
+
+    <property name="command4" value="${commands1}/command4"/>
+    <echo file="${command4}">
+#!/bin/bash
+`dirname "$0"`/java -m ${hello.pkg}/${hello.pkg}.HelloWorld
+    </echo>
+    <setpermissions mode="777" nonPosixMode="tryDosOrPass">
+      <file file="${command4}"/>
+    </setpermissions>
+
+    <property name="command5" value="${commands2}/command5"/>
+    <echo file="${command5}">
+#!/bin/bash
+`dirname "$0"`/java -m ${hello.pkg}/${hello.pkg}.HelloWorld
+    </echo>
+    <setpermissions mode="777" nonPosixMode="tryDosOrPass">
+      <file file="${command5}"/>
+    </setpermissions>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          commandpath="${commands1}">
+      <commandpath>
+        <pathelement location="${commands2}"/>
+      </commandpath>
+    </jmod>
+  </target>
+
+  <!-- headerpath targets -->
+
+  <target name="headerpath" depends="-hello">
+    <property name="headers" value="${output}/headers"/>
+    <mkdir dir="${headers}"/>
+
+    <property name="header1" value="${headers}/header1.h"/>
+
+    <echo file="${header1}">
+typedef int index_t;
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          headerpath="${headers}"/>
+  </target>
+
+  <target name="headerpathref" depends="-hello">
+    <property name="headers" value="${output}/headers"/>
+    <mkdir dir="${headers}"/>
+
+    <property name="header2" value="${headers}/header2.h"/>
+
+    <echo file="${header2}">
+typedef char * string_t;
+    </echo>
+
+    <path id="headerpathref.testpath">
+      <pathelement location="${headers}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          headerpathref="headerpathref.testpath"/>
+  </target>
+
+  <target name="headerpath-nested" depends="-hello">
+    <property name="headers" value="${output}/headers"/>
+    <mkdir dir="${headers}"/>
+
+    <property name="header3" value="${headers}/header3.h"/>
+
+    <echo file="${header3}">
+typedef char * string_t;
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <headerpath>
+        <pathelement location="${headers}"/>
+      </headerpath>
+    </jmod>
+  </target>
+
+  <target name="headerpath-both" depends="-hello">
+    <property name="headers4" value="${output}/headers4"/>
+    <property name="headers5" value="${output}/headers5"/>
+    <mkdir dir="${headers4}"/>
+    <mkdir dir="${headers5}"/>
+
+    <property name="header4" value="${headers4}/header4.h"/>
+    <property name="header5" value="${headers5}/header5.h"/>
+
+    <echo file="${header4}">
+typedef int index_t;
+    </echo>
+    <echo file="${header5}">
+typedef char * string_t;
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" headerpath="${headers4}">
+      <headerpath>
+        <pathelement location="${headers5}"/>
+      </headerpath>
+    </jmod>
+  </target>
+
+  <!-- configpath targets -->
+
+  <target name="configpath" depends="-hello">
+    <property name="config" value="${output}/config"/>
+    <mkdir dir="${config}"/>
+
+    <property name="config1" value="${config}/config1.properties"/>
+
+    <echo file="${config1}">
+timeout=3600
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" configpath="${config}"/>
+  </target>
+
+  <target name="configpathref" depends="-hello">
+    <property name="config" value="${output}/config"/>
+    <mkdir dir="${config}"/>
+
+    <property name="config2" value="${config}/config2.properties"/>
+
+    <echo file="${config2}">
+timeout=7200
+    </echo>
+
+    <path id="configpathref.testpath">
+      <pathelement location="${config}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          configpathref="configpathref.testpath"/>
+  </target>
+
+  <target name="configpath-nested" depends="-hello">
+    <property name="config" value="${output}/config"/>
+    <mkdir dir="${config}"/>
+
+    <property name="config3" value="${config}/config3.properties"/>
+
+    <echo file="${config3}">
+timeout=7200
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <configpath>
+        <pathelement location="${config}"/>
+      </configpath>
+    </jmod>
+  </target>
+
+  <target name="configpath-both" depends="-hello">
+    <property name="config4" value="${output}/config4"/>
+    <property name="config5" value="${output}/config5"/>
+    <mkdir dir="${config4}"/>
+    <mkdir dir="${config5}"/>
+
+    <property name="configfile4" value="${config4}/config4.properties"/>
+    <property name="configfile5" value="${config5}/config5.properties"/>
+
+    <echo file="${configfile4}">
+timeout=3600
+    </echo>
+    <echo file="${configfile5}">
+timeout=7200
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" configpath="${config4}">
+      <configpath>
+        <pathelement location="${config5}"/>
+      </configpath>
+    </jmod>
+  </target>
+
+  <!-- legalpath targets -->
+
+  <target name="legalpath" depends="-hello">
+    <property name="legal" value="${output}/legal"/>
+    <mkdir dir="${legal}"/>
+
+    <property name="legal1" value="${legal}/legal1.txt"/>
+
+    <echo file="${legal1}">
+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
+
+    https://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.
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" legalpath="${legal}"/>
+  </target>
+
+  <target name="legalpathref" depends="-hello">
+    <property name="legal" value="${output}/legal"/>
+    <mkdir dir="${legal}"/>
+
+    <property name="legal2" value="${legal}/legal2.txt"/>
+
+    <echo file="${legal2}">
+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
+
+    https://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.
+    </echo>
+
+    <path id="legalpathref.testpath">
+      <pathelement location="${legal}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          legalpathref="legalpathref.testpath"/>
+  </target>
+
+  <target name="legalpath-nested" depends="-hello">
+    <property name="legal" value="${output}/legal"/>
+    <mkdir dir="${legal}"/>
+
+    <property name="legal3" value="${legal}/legal3.txt"/>
+
+    <echo file="${legal3}">
+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
+
+    https://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.
+    </echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <legalpath>
+        <pathelement location="${legal}"/>
+      </legalpath>
+    </jmod>
+  </target>
+
+  <target name="legalpath-both" depends="-hello">
+    <property name="legal4" value="${output}/legal4"/>
+    <property name="legal5" value="${output}/legal5"/>
+    <mkdir dir="${legal4}"/>
+    <mkdir dir="${legal5}"/>
+
+    <property name="legalfile4" value="${legal4}/legal4.txt"/>
+    <property name="legalfile5" value="${legal5}/legal5.txt"/>
+
+    <echo file="${legalfile4}">
+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
+
+    https://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.
+    </echo>
+    <copy file="${legalfile4}" tofile="${legalfile5}"/>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" legalpath="${legal4}">
+      <legalpath>
+        <pathelement location="${legal5}"/>
+      </legalpath>
+    </jmod>
+  </target>
+
+  <!-- manpath targets -->
+
+  <target name="manpath" depends="-hello">
+    <property name="manpages" value="${output}/manpages"/>
+    <mkdir dir="${manpages}"/>
+
+    <property name="man1" value="${manpages}/man1.1"/>
+
+    <echo file="${man1}"><!--
+--><![CDATA[.TH "CHFN" "1" "05/17/2017" "shadow\-utils 4\&.4" "User Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+chfn \- change real user name and information
+.SH "SYNOPSIS"
+.HP \w'\fBchfn\fR\ 'u
+\fBchfn\fR [\fIoptions\fR] [\fILOGIN\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBchfn\fR
+command changes user fullname, office room number, office phone number, and home phone number information for a user\*(Aqs account\&. This information is typically printed by
+\fBfinger\fR(1)
+and similar programs\&. A normal user may only change the fields for her own account, subject to the restrictions in
+/etc/login\&.defs\&. (The default configuration is to prevent users from changing their fullname\&.) The superuser may change any field for any account\&. Additionally, only the superuser may use the
+\fB\-o\fR
+option to change the undefined portions of the GECOS field\&.
+.PP
+These fields must not contain any colons\&. Except for the
+\fIother\fR
+field, they should not contain any comma or equal sign\&. It is also recommended to avoid non\-US\-ASCII characters, but this is only enforced for the phone numbers\&. The
+\fIother\fR
+field is used to store accounting information used by other applications\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBchfn\fR
+command are:
+.PP
+\fB\-f\fR, \fB\-\-full\-name\fR\ \&\fIFULL_NAME\fR
+.RS 4
+Change the user\*(Aqs full name\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-home\-phone\fR\ \&\fIHOME_PHONE\fR
+.RS 4
+Change the user\*(Aqs home phone number\&.
+.RE
+.PP
+\fB\-o\fR, \fB\-\-other\fR\ \&\fIOTHER\fR
+.RS 4
+Change the user\*(Aqs other GECOS information\&. This field is used to store accounting information used by other applications, and can be changed only by a superuser\&.
+.RE
+.PP
+\fB\-r\fR, \fB\-\-room\fR\ \&\fIROOM_NUMBER\fR
+.RS 4
+Change the user\*(Aqs room number\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-u\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-w\fR, \fB\-\-work\-phone\fR\ \&\fIWORK_PHONE\fR
+.RS 4
+Change the user\*(Aqs office phone number\&.
+.RE
+.PP
+If none of the options are selected,
+\fBchfn\fR
+operates in an interactive fashion, prompting the user with the current values for all of the fields\&. Enter the new value to change the field, or leave the line blank to use the current value\&. The current value is displayed between a pair of
+\fB[ ]\fR
+marks\&. Without options,
+\fBchfn\fR
+prompts for the current user account\&.
+.SH "CONFIGURATION"
+.PP
+The following configuration variables in
+/etc/login\&.defs
+change the behavior of this tool:
+.PP
+\fBCHFN_RESTRICT\fR (string)
+.RS 4
+This parameter specifies which values in the
+\fIgecos\fR
+field of the
+/etc/passwd
+file may be changed by regular users using the
+\fBchfn\fR
+program\&. It can be any combination of letters
+\fIf\fR,
+\fIr\fR,
+\fIw\fR,
+\fIh\fR, for Full name, Room number, Work phone, and Home phone, respectively\&. For backward compatibility,
+\fIyes\fR
+is equivalent to
+\fIrwh\fR
+and
+\fIno\fR
+is equivalent to
+\fIfrwh\fR\&. If not specified, only the superuser can make any changes\&. The most restrictive setting is better achieved by not installing
+\fBchfn\fR
+SUID\&.
+.RE
+.SH "FILES"
+.PP
+/etc/login\&.defs
+.RS 4
+Shadow password suite configuration\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBchsh\fR(1),
+\fBlogin.defs\fR(5),
+\fBpasswd\fR(5)\&.
+]]><!--
+    --></echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" manpath="${manpages}"/>
+  </target>
+
+  <target name="manpathref" depends="-hello">
+    <property name="manpages" value="${output}/manpages"/>
+    <mkdir dir="${manpages}"/>
+
+    <property name="man2" value="${manpages}/man2.1"/>
+
+    <echo file="${man2}"><!--
+--><![CDATA[.TH "VIPW" "8" "05/17/2017" "shadow\-utils 4\&.4" "System Management Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+vipw, vigr \- edit the password, group, shadow\-password or shadow\-group file
+.SH "SYNOPSIS"
+.HP \w'\fBvipw\fR\ 'u
+\fBvipw\fR [\fIoptions\fR]
+.HP \w'\fBvigr\fR\ 'u
+\fBvigr\fR [\fIoptions\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBvipw\fR
+and
+\fBvigr\fR
+commands edits the files
+/etc/passwd
+and
+/etc/group, respectively\&. With the
+\fB\-s\fR
+flag, they will edit the shadow versions of those files,
+/etc/shadow
+and
+/etc/gshadow, respectively\&. The programs will set the appropriate locks to prevent file corruption\&. When looking for an editor, the programs will first try the environment variable
+\fB$VISUAL\fR, then the environment variable
+\fB$EDITOR\fR, and finally the default editor,
+\fBvi\fR(1)\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBvipw\fR
+and
+\fBvigr\fR
+commands are:
+.PP
+\fB\-g\fR, \fB\-\-group\fR
+.RS 4
+Edit group database\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-p\fR, \fB\-\-passwd\fR
+.RS 4
+Edit passwd database\&.
+.RE
+.PP
+\fB\-q\fR, \fB\-\-quiet\fR
+.RS 4
+Quiet mode\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-s\fR, \fB\-\-shadow\fR
+.RS 4
+Edit shadow or gshadow database\&.
+.RE
+.SH "ENVIRONMENT"
+.PP
+\fBVISUAL\fR
+.RS 4
+Editor to be used\&.
+.RE
+.PP
+\fBEDITOR\fR
+.RS 4
+Editor to be used if
+\fBVISUAL\fR
+is not set\&.
+.RE
+.SH "FILES"
+.PP
+/etc/group
+.RS 4
+Group account information\&.
+.RE
+.PP
+/etc/gshadow
+.RS 4
+Secure group account information\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.PP
+/etc/shadow
+.RS 4
+Secure user account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBvi\fR(1),
+\fBgroup\fR(5),
+\fBgshadow\fR(5)
+,
+\fBpasswd\fR(5), ,
+\fBshadow\fR(5)\&.
+]]><!--
+    --></echo>
+
+    <path id="manpathref.testpath">
+      <pathelement location="${manpages}"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          manpathref="manpathref.testpath"/>
+  </target>
+
+  <target name="manpath-nested" depends="-hello">
+    <property name="manpages" value="${output}/manpages"/>
+    <mkdir dir="${manpages}"/>
+
+    <property name="man3" value="${manpages}/man3.1"/>
+
+    <echo file="${man3}"><!--
+--><![CDATA[.TH "VIPW" "8" "05/17/2017" "shadow\-utils 4\&.4" "System Management Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+vipw, vigr \- edit the password, group, shadow\-password or shadow\-group file
+.SH "SYNOPSIS"
+.HP \w'\fBvipw\fR\ 'u
+\fBvipw\fR [\fIoptions\fR]
+.HP \w'\fBvigr\fR\ 'u
+\fBvigr\fR [\fIoptions\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBvipw\fR
+and
+\fBvigr\fR
+commands edits the files
+/etc/passwd
+and
+/etc/group, respectively\&. With the
+\fB\-s\fR
+flag, they will edit the shadow versions of those files,
+/etc/shadow
+and
+/etc/gshadow, respectively\&. The programs will set the appropriate locks to prevent file corruption\&. When looking for an editor, the programs will first try the environment variable
+\fB$VISUAL\fR, then the environment variable
+\fB$EDITOR\fR, and finally the default editor,
+\fBvi\fR(1)\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBvipw\fR
+and
+\fBvigr\fR
+commands are:
+.PP
+\fB\-g\fR, \fB\-\-group\fR
+.RS 4
+Edit group database\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-p\fR, \fB\-\-passwd\fR
+.RS 4
+Edit passwd database\&.
+.RE
+.PP
+\fB\-q\fR, \fB\-\-quiet\fR
+.RS 4
+Quiet mode\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-s\fR, \fB\-\-shadow\fR
+.RS 4
+Edit shadow or gshadow database\&.
+.RE
+.SH "ENVIRONMENT"
+.PP
+\fBVISUAL\fR
+.RS 4
+Editor to be used\&.
+.RE
+.PP
+\fBEDITOR\fR
+.RS 4
+Editor to be used if
+\fBVISUAL\fR
+is not set\&.
+.RE
+.SH "FILES"
+.PP
+/etc/group
+.RS 4
+Group account information\&.
+.RE
+.PP
+/etc/gshadow
+.RS 4
+Secure group account information\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.PP
+/etc/shadow
+.RS 4
+Secure user account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBvi\fR(1),
+\fBgroup\fR(5),
+\fBgshadow\fR(5)
+,
+\fBpasswd\fR(5), ,
+\fBshadow\fR(5)\&.
+]]><!--
+    --></echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <manpath>
+        <pathelement location="${manpages}"/>
+      </manpath>
+    </jmod>
+  </target>
+
+  <target name="manpath-both" depends="-hello">
+    <property name="manpages4" value="${output}/manpages4"/>
+    <property name="manpages5" value="${output}/manpages5"/>
+    <mkdir dir="${manpages4}"/>
+    <mkdir dir="${manpages5}"/>
+
+    <property name="man4" value="${manpages4}/man4.1"/>
+    <property name="man5" value="${manpages5}/man5.1"/>
+
+    <echo file="${man4}"><!--
+--><![CDATA[.TH "CHFN" "1" "05/17/2017" "shadow\-utils 4\&.4" "User Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+chfn \- change real user name and information
+.SH "SYNOPSIS"
+.HP \w'\fBchfn\fR\ 'u
+\fBchfn\fR [\fIoptions\fR] [\fILOGIN\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBchfn\fR
+command changes user fullname, office room number, office phone number, and home phone number information for a user\*(Aqs account\&. This information is typically printed by
+\fBfinger\fR(1)
+and similar programs\&. A normal user may only change the fields for her own account, subject to the restrictions in
+/etc/login\&.defs\&. (The default configuration is to prevent users from changing their fullname\&.) The superuser may change any field for any account\&. Additionally, only the superuser may use the
+\fB\-o\fR
+option to change the undefined portions of the GECOS field\&.
+.PP
+These fields must not contain any colons\&. Except for the
+\fIother\fR
+field, they should not contain any comma or equal sign\&. It is also recommended to avoid non\-US\-ASCII characters, but this is only enforced for the phone numbers\&. The
+\fIother\fR
+field is used to store accounting information used by other applications\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBchfn\fR
+command are:
+.PP
+\fB\-f\fR, \fB\-\-full\-name\fR\ \&\fIFULL_NAME\fR
+.RS 4
+Change the user\*(Aqs full name\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-home\-phone\fR\ \&\fIHOME_PHONE\fR
+.RS 4
+Change the user\*(Aqs home phone number\&.
+.RE
+.PP
+\fB\-o\fR, \fB\-\-other\fR\ \&\fIOTHER\fR
+.RS 4
+Change the user\*(Aqs other GECOS information\&. This field is used to store accounting information used by other applications, and can be changed only by a superuser\&.
+.RE
+.PP
+\fB\-r\fR, \fB\-\-room\fR\ \&\fIROOM_NUMBER\fR
+.RS 4
+Change the user\*(Aqs room number\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-u\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-w\fR, \fB\-\-work\-phone\fR\ \&\fIWORK_PHONE\fR
+.RS 4
+Change the user\*(Aqs office phone number\&.
+.RE
+.PP
+If none of the options are selected,
+\fBchfn\fR
+operates in an interactive fashion, prompting the user with the current values for all of the fields\&. Enter the new value to change the field, or leave the line blank to use the current value\&. The current value is displayed between a pair of
+\fB[ ]\fR
+marks\&. Without options,
+\fBchfn\fR
+prompts for the current user account\&.
+.SH "CONFIGURATION"
+.PP
+The following configuration variables in
+/etc/login\&.defs
+change the behavior of this tool:
+.PP
+\fBCHFN_RESTRICT\fR (string)
+.RS 4
+This parameter specifies which values in the
+\fIgecos\fR
+field of the
+/etc/passwd
+file may be changed by regular users using the
+\fBchfn\fR
+program\&. It can be any combination of letters
+\fIf\fR,
+\fIr\fR,
+\fIw\fR,
+\fIh\fR, for Full name, Room number, Work phone, and Home phone, respectively\&. For backward compatibility,
+\fIyes\fR
+is equivalent to
+\fIrwh\fR
+and
+\fIno\fR
+is equivalent to
+\fIfrwh\fR\&. If not specified, only the superuser can make any changes\&. The most restrictive setting is better achieved by not installing
+\fBchfn\fR
+SUID\&.
+.RE
+.SH "FILES"
+.PP
+/etc/login\&.defs
+.RS 4
+Shadow password suite configuration\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBchsh\fR(1),
+\fBlogin.defs\fR(5),
+\fBpasswd\fR(5)\&.
+]]><!--
+    --></echo>
+    <echo file="${man5}"><!--
+--><![CDATA[.TH "VIPW" "8" "05/17/2017" "shadow\-utils 4\&.4" "System Management Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+vipw, vigr \- edit the password, group, shadow\-password or shadow\-group file
+.SH "SYNOPSIS"
+.HP \w'\fBvipw\fR\ 'u
+\fBvipw\fR [\fIoptions\fR]
+.HP \w'\fBvigr\fR\ 'u
+\fBvigr\fR [\fIoptions\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBvipw\fR
+and
+\fBvigr\fR
+commands edits the files
+/etc/passwd
+and
+/etc/group, respectively\&. With the
+\fB\-s\fR
+flag, they will edit the shadow versions of those files,
+/etc/shadow
+and
+/etc/gshadow, respectively\&. The programs will set the appropriate locks to prevent file corruption\&. When looking for an editor, the programs will first try the environment variable
+\fB$VISUAL\fR, then the environment variable
+\fB$EDITOR\fR, and finally the default editor,
+\fBvi\fR(1)\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBvipw\fR
+and
+\fBvigr\fR
+commands are:
+.PP
+\fB\-g\fR, \fB\-\-group\fR
+.RS 4
+Edit group database\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-p\fR, \fB\-\-passwd\fR
+.RS 4
+Edit passwd database\&.
+.RE
+.PP
+\fB\-q\fR, \fB\-\-quiet\fR
+.RS 4
+Quiet mode\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-s\fR, \fB\-\-shadow\fR
+.RS 4
+Edit shadow or gshadow database\&.
+.RE
+.SH "ENVIRONMENT"
+.PP
+\fBVISUAL\fR
+.RS 4
+Editor to be used\&.
+.RE
+.PP
+\fBEDITOR\fR
+.RS 4
+Editor to be used if
+\fBVISUAL\fR
+is not set\&.
+.RE
+.SH "FILES"
+.PP
+/etc/group
+.RS 4
+Group account information\&.
+.RE
+.PP
+/etc/gshadow
+.RS 4
+Secure group account information\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.PP
+/etc/shadow
+.RS 4
+Secure user account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBvi\fR(1),
+\fBgroup\fR(5),
+\fBgshadow\fR(5)
+,
+\fBpasswd\fR(5), ,
+\fBshadow\fR(5)\&.
+]]><!--
+    --></echo>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}" manpath="${manpages4}">
+      <manpath>
+        <pathelement location="${manpages5}"/>
+      </manpath>
+    </jmod>
+  </target>
+
+  <!-- nativelibpath targets -->
+
+  <target name="nativelibpath" depends="-hello">
+    <property name="nativelib" location="${java.home}/lib;${java.home}/bin"/>
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          nativelibpath="${nativelib}"/>
+  </target>
+
+  <target name="nativelibpathref" depends="-hello">
+
+    <path id="nativelibpathref.testpath">
+      <pathelement location="${java.home}/lib"/>
+      <pathelement location="${java.home}/bin"/>
+    </path>
+
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          nativelibpathref="nativelibpathref.testpath"/>
+  </target>
+
+  <target name="nativelibpath-nested" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <nativelibpath>
+        <pathelement location="${java.home}/lib"/>
+        <pathelement location="${java.home}/bin"/>
+      </nativelibpath>
+    </jmod>
+  </target>
+
+  <target name="nativelibpath-both" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          nativelibpath="${java.home}/lib;${java.home}/bin">
+      <nativelibpath>
+        <dirset dir="${java.home}">
+          <include name="lib/server"/>
+          <include name="bin/server"/>
+        </dirset>
+      </nativelibpath>
+    </jmod>
+  </target>
+
+  <!-- non-path targets -->
+
+  <target name="version" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}" version="${version}"/>
+  </target>
+
+  <target name="version-nested" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <version number="1.0.1" build="99"/>
+    </jmod>
+  </target>
+
+  <target name="version-nested-number" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <version number="1.0.1"/>
+    </jmod>
+  </target>
+
+  <target name="version-nested-no-number" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <version build="99"/>
+    </jmod>
+  </target>
+
+  <target name="version-nested-invalid-number" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <version number="1-0-1" build="99"/>
+    </jmod>
+  </target>
+
+  <target name="version-nested-invalid-prerelease" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}">
+      <version number="1.0.1" build="99" prerelease="unit+testing"/>
+    </jmod>
+  </target>
+
+  <target name="version-both" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}" version="${version}">
+      <version number="1.0.1" build="99"/>
+    </jmod>
+  </target>
+
+  <target name="mainclass" depends="-hello">
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          mainclass="${hello.main-class}"/>
+  </target>
+
+  <target name="platform" depends="-smile">
+    <property name="target-platform" value="windows-amd64"/>
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          platform="${target-platform}"/>
+  </target>
+
+  <target name="hashing" depends="-smile">
+    <jmod destfile="${jmod}" classpath="${hello.jar}"
+          modulepath="${smile.jar.dir}"
+          hashModulesPattern=".*smile.*"/>
+  </target>
+</project>
diff --git a/src/etc/testcases/taskdefs/link.xml b/src/etc/testcases/taskdefs/link.xml
new file mode 100644
index 0000000..cc479d5
--- /dev/null
+++ b/src/etc/testcases/taskdefs/link.xml
@@ -0,0 +1,1260 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project name="linktest" default="nil" xmlns:unless="ant:unless">
+  <import file="../buildfiletest-base.xml"/>
+
+  <target name="nil"/>
+
+  <target name="-dirs">
+    <mkdir dir="${input}"/>
+
+    <property name="jmods" value="${output}/jmods"/>
+    <mkdir dir="${jmods}"/>
+
+    <property name="manpages" value="${output}/manpages"/>
+    <mkdir dir="${manpages}"/>
+
+    <property name="image" value="${output}/image"/>
+
+    <!--
+      Before Java 10, JDK's jmods directory must be explicitly included
+      in module paths.
+     -->
+    <condition property="jdkmods" value=""
+               else="${java.home}/jmods${path.separator}">
+      <hasmethod classname="java.util.List" method="copyOf"/>
+    </condition>
+  </target>
+
+  <target name="setUp" depends="-dirs">
+  </target>
+
+  <!-- Creates simple modular jar, with only Java SE dependencies. -->
+  <target name="-hello" depends="-dirs">
+
+    <property name="hello.root" value="${input}/hello"/>
+
+    <property name="hello.src" value="${hello.root}/src"/>
+    <property name="hello.classes" value="${hello.root}/classes"/>
+    <property name="hello.jar.dir" value="${hello.root}/jars"/>
+    <property name="hello.jar" value="${hello.jar.dir}/hello.jar"/>
+    <property name="hello.legal" value="${hello.root}/legal"/>
+
+    <property name="hello.mod"      value="org.apache.tools.ant.test.hello"/>
+    <property name="hello.pkg"      value="org.apache.tools.ant.test.hello"/>
+    <property name="hello.pkg.path" value="org/apache/tools/ant/test/hello"/>
+    <property name="hello.pkg.dir" value="${hello.src}/${hello.pkg.path}"/>
+
+    <property name="hello.main-class" value="${hello.pkg}.HelloWorld"/>
+
+    <mkdir dir="${hello.pkg.dir}"/>
+    <echo file="${hello.pkg.dir}/HelloWorld.java">
+package ${hello.pkg};
+
+import java.util.logging.Logger;
+
+public class HelloWorld {
+    public void run(String[] resources) {
+        Logger logger = Logger.getLogger(HelloWorld.class.getName());
+        logger.info("HELLO WORLD");
+
+        for (String resource : resources) {
+            Object url = HelloWorld.class.getResource(resource);
+            logger.info(resource + " " + (url != null ? "present" : "absent"));
+        }
+    }
+
+    public static void main(String[] args) {
+        new HelloWorld().run(args);
+    }
+}
+    </echo>
+    <echo file="${hello.src}/module-info.java">
+module ${hello.mod} {
+    exports ${hello.pkg};
+    requires java.logging;
+}
+    </echo>
+
+    <mkdir dir="${hello.classes}"/>
+    <javac srcdir="${hello.src}" destdir="${hello.classes}"
+           includeAntRuntime="false" debug="true"/>
+    <echo file="${hello.classes}/${hello.pkg.path}/resource1.txt"
+          message="First HelloWorld resource."/>
+    <echo file="${hello.classes}/${hello.pkg.path}/resource2.txt"
+          message="Second HelloWorld resource."/>
+
+    <mkdir dir="${hello.jar.dir}"/>
+    <jar destfile="${hello.jar}" basedir="${hello.classes}"/>
+  </target>
+
+  <!-- Creates modular jar with dependency on hello module. -->
+  <target name="-smile" depends="-dirs,-hello">
+    <property name="smile.root" value="${input}/smile"/>
+
+    <property name="smile.src" value="${smile.root}/src"/>
+    <property name="smile.classes" value="${smile.root}/classes"/>
+    <property name="smile.jar.dir" value="${smile.root}/jars"/>
+    <property name="smile.jar" value="${smile.jar.dir}/smile.jar"/>
+    <property name="smile.legal" value="${smile.root}/legal"/>
+
+    <property name="smile.mod"      value="org.apache.tools.ant.test.smile"/>
+    <property name="smile.pkg"      value="org.apache.tools.ant.test.smile"/>
+    <property name="smile.pkg.path" value="org/apache/tools/ant/test/smile"/>
+    <property name="smile.pkg.dir" value="${smile.src}/${smile.pkg.path}"/>
+
+    <property name="smile.main-class" value="${smile.pkg}.Smile"/>
+
+    <mkdir dir="${smile.pkg.dir}"/>
+    <echo file="${smile.pkg.dir}/Smile.java">
+package ${smile.pkg};
+
+import java.util.logging.Logger;
+import ${hello.pkg}.HelloWorld;
+
+public class Smile {
+    public void run(String[] resources) {
+        Logger logger = Logger.getLogger(Smile.class.getName());
+        logger.info("\u263a\u263b\u263a\u263b");
+
+        for (String resource : resources) {
+            Object url = HelloWorld.class.getResource(resource);
+            logger.info(resource + " " + (url != null ? "present" : "absent"));
+        }
+    }
+
+    public static void main(String[] args) {
+        new Smile().run(args);
+        new HelloWorld().run(args);
+    }
+}
+    </echo>
+    <echo file="${smile.src}/module-info.java">
+module ${smile.mod} {
+    exports ${smile.pkg};
+    requires java.logging;
+    requires ${hello.mod};
+}
+    </echo>
+
+    <mkdir dir="${smile.classes}"/>
+    <javac srcdir="${smile.src}" destdir="${smile.classes}"
+           includeAntRuntime="false" debug="true"
+           modulepath="${hello.jar}"/>
+    <echo file="${smile.classes}/${smile.pkg.path}/resource1.txt"
+          message="First Smile resource."/>
+    <echo file="${smile.classes}/${smile.pkg.path}/resource2.txt"
+          message="Second Smile resource."/>
+
+    <mkdir dir="${smile.jar.dir}"/>
+    <jar destfile="${smile.jar}" basedir="${smile.classes}"/>
+  </target>
+
+  <target name="-manpages" depends="-dirs">
+
+    <property name="man1" value="${manpages}/man1.1"/>
+    <property name="man2" value="${manpages}/man2.1"/>
+
+    <echo file="${man1}"><!--
+--><![CDATA[.TH "CHFN" "1" "05/17/2017" "shadow\-utils 4\&.4" "User Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+chfn \- change real user name and information
+.SH "SYNOPSIS"
+.HP \w'\fBchfn\fR\ 'u
+\fBchfn\fR [\fIoptions\fR] [\fILOGIN\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBchfn\fR
+command changes user fullname, office room number, office phone number, and home phone number information for a user\*(Aqs account\&. This information is typically printed by
+\fBfinger\fR(1)
+and similar programs\&. A normal user may only change the fields for her own account, subject to the restrictions in
+/etc/login\&.defs\&. (The default configuration is to prevent users from changing their fullname\&.) The superuser may change any field for any account\&. Additionally, only the superuser may use the
+\fB\-o\fR
+option to change the undefined portions of the GECOS field\&.
+.PP
+These fields must not contain any colons\&. Except for the
+\fIother\fR
+field, they should not contain any comma or equal sign\&. It is also recommended to avoid non\-US\-ASCII characters, but this is only enforced for the phone numbers\&. The
+\fIother\fR
+field is used to store accounting information used by other applications\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBchfn\fR
+command are:
+.PP
+\fB\-f\fR, \fB\-\-full\-name\fR\ \&\fIFULL_NAME\fR
+.RS 4
+Change the user\*(Aqs full name\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-home\-phone\fR\ \&\fIHOME_PHONE\fR
+.RS 4
+Change the user\*(Aqs home phone number\&.
+.RE
+.PP
+\fB\-o\fR, \fB\-\-other\fR\ \&\fIOTHER\fR
+.RS 4
+Change the user\*(Aqs other GECOS information\&. This field is used to store accounting information used by other applications, and can be changed only by a superuser\&.
+.RE
+.PP
+\fB\-r\fR, \fB\-\-room\fR\ \&\fIROOM_NUMBER\fR
+.RS 4
+Change the user\*(Aqs room number\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-u\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-w\fR, \fB\-\-work\-phone\fR\ \&\fIWORK_PHONE\fR
+.RS 4
+Change the user\*(Aqs office phone number\&.
+.RE
+.PP
+If none of the options are selected,
+\fBchfn\fR
+operates in an interactive fashion, prompting the user with the current values for all of the fields\&. Enter the new value to change the field, or leave the line blank to use the current value\&. The current value is displayed between a pair of
+\fB[ ]\fR
+marks\&. Without options,
+\fBchfn\fR
+prompts for the current user account\&.
+.SH "CONFIGURATION"
+.PP
+The following configuration variables in
+/etc/login\&.defs
+change the behavior of this tool:
+.PP
+\fBCHFN_RESTRICT\fR (string)
+.RS 4
+This parameter specifies which values in the
+\fIgecos\fR
+field of the
+/etc/passwd
+file may be changed by regular users using the
+\fBchfn\fR
+program\&. It can be any combination of letters
+\fIf\fR,
+\fIr\fR,
+\fIw\fR,
+\fIh\fR, for Full name, Room number, Work phone, and Home phone, respectively\&. For backward compatibility,
+\fIyes\fR
+is equivalent to
+\fIrwh\fR
+and
+\fIno\fR
+is equivalent to
+\fIfrwh\fR\&. If not specified, only the superuser can make any changes\&. The most restrictive setting is better achieved by not installing
+\fBchfn\fR
+SUID\&.
+.RE
+.SH "FILES"
+.PP
+/etc/login\&.defs
+.RS 4
+Shadow password suite configuration\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBchsh\fR(1),
+\fBlogin.defs\fR(5),
+\fBpasswd\fR(5)\&.
+]]><!--
+    --></echo>
+
+    <echo file="${man2}"><!--
+--><![CDATA[.TH "VIPW" "8" "05/17/2017" "shadow\-utils 4\&.4" "System Management Commands"
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+vipw, vigr \- edit the password, group, shadow\-password or shadow\-group file
+.SH "SYNOPSIS"
+.HP \w'\fBvipw\fR\ 'u
+\fBvipw\fR [\fIoptions\fR]
+.HP \w'\fBvigr\fR\ 'u
+\fBvigr\fR [\fIoptions\fR]
+.SH "DESCRIPTION"
+.PP
+The
+\fBvipw\fR
+and
+\fBvigr\fR
+commands edits the files
+/etc/passwd
+and
+/etc/group, respectively\&. With the
+\fB\-s\fR
+flag, they will edit the shadow versions of those files,
+/etc/shadow
+and
+/etc/gshadow, respectively\&. The programs will set the appropriate locks to prevent file corruption\&. When looking for an editor, the programs will first try the environment variable
+\fB$VISUAL\fR, then the environment variable
+\fB$EDITOR\fR, and finally the default editor,
+\fBvi\fR(1)\&.
+.SH "OPTIONS"
+.PP
+The options which apply to the
+\fBvipw\fR
+and
+\fBvigr\fR
+commands are:
+.PP
+\fB\-g\fR, \fB\-\-group\fR
+.RS 4
+Edit group database\&.
+.RE
+.PP
+\fB\-h\fR, \fB\-\-help\fR
+.RS 4
+Display help message and exit\&.
+.RE
+.PP
+\fB\-p\fR, \fB\-\-passwd\fR
+.RS 4
+Edit passwd database\&.
+.RE
+.PP
+\fB\-q\fR, \fB\-\-quiet\fR
+.RS 4
+Quiet mode\&.
+.RE
+.PP
+\fB\-R\fR, \fB\-\-root\fR\ \&\fICHROOT_DIR\fR
+.RS 4
+Apply changes in the
+\fICHROOT_DIR\fR
+directory and use the configuration files from the
+\fICHROOT_DIR\fR
+directory\&.
+.RE
+.PP
+\fB\-s\fR, \fB\-\-shadow\fR
+.RS 4
+Edit shadow or gshadow database\&.
+.RE
+.SH "ENVIRONMENT"
+.PP
+\fBVISUAL\fR
+.RS 4
+Editor to be used\&.
+.RE
+.PP
+\fBEDITOR\fR
+.RS 4
+Editor to be used if
+\fBVISUAL\fR
+is not set\&.
+.RE
+.SH "FILES"
+.PP
+/etc/group
+.RS 4
+Group account information\&.
+.RE
+.PP
+/etc/gshadow
+.RS 4
+Secure group account information\&.
+.RE
+.PP
+/etc/passwd
+.RS 4
+User account information\&.
+.RE
+.PP
+/etc/shadow
+.RS 4
+Secure user account information\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBvi\fR(1),
+\fBgroup\fR(5),
+\fBgshadow\fR(5)
+,
+\fBpasswd\fR(5), ,
+\fBshadow\fR(5)\&.
+]]><!--
+    --></echo>
+  </target>
+
+  <target name="-legal" depends="-smile">
+    <property name="sharedlicense.name" value="USELESSLICENSE"/>
+    <property name="sharedlicense.text"
+              value="This license grants no particular rights."/>
+
+    <mkdir dir="${hello.legal}"/>
+    <mkdir dir="${smile.legal}"/>
+
+    <echo file="${hello.legal}/${sharedlicense.name}"
+          message="${sharedlicense.text}"/>
+    <echo file="${smile.legal}/${sharedlicense.name}"
+          message="${sharedlicense.text}"/>
+
+    <property name="uniquelicense.name" value="UNIQUELICENSE"/>
+    <echo file="${hello.legal}/${uniquelicense.name}"
+          message="License for ${hello.mod}."/>
+    <echo file="${smile.legal}/${uniquelicense.name}"
+          message="License for ${smile.mod}."/>
+  </target>
+
+  <target name="-jmods" depends="-smile,-legal">
+    <property name="hello.jmod" value="${jmods}/hello.jmod"/>
+    <property name="smile.jmod" value="${jmods}/smile.jmod"/>
+
+    <jmod destfile="${hello.jmod}"
+          classpath="${hello.jar}"
+          legalpath="${hello.legal}"
+          manpath="${manpages}"/>
+
+    <jmod destfile="${smile.jmod}"
+          classpath="${smile.jar}"
+          legalpath="${smile.legal}"
+          manpath="${manpages}"
+          modulepath="${hello.jar.dir}"/>
+  </target>
+
+  <target name="modulepath" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+  </target>
+
+  <target name="imageNewerThanJmods" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+
+    <chmod perm="a+w">
+      <fileset dir="${image}"/>
+    </chmod>
+
+    <property name="dateformat" value="yyyy-MM-dd HH:mm:ss.SSS"/>
+    <tstamp>
+      <format property="future" pattern="${dateformat}" offset="1" unit="hour"/>
+    </tstamp>
+    <touch datetime="${future}" pattern="${dateformat}">
+      <fileset dir="${image}"/>
+    </touch>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+  </target>
+
+  <target name="nomodulepath" depends="-jmods">
+    <link destdir="${image}"
+          modules="${hello.mod},${smile.mod}"/>
+  </target>
+
+  <target name="nomodules" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"/>
+  </target>
+
+  <target name="modulepathref" depends="-jmods">
+    <path id="modules">
+      <pathelement location="${jdkmods}" unless:blank="${jdkmods}"/>
+      <pathelement location="${jmods}"/>
+    </path>
+    <link destdir="${image}" modulepathref="modules"
+          modules="${hello.mod},${smile.mod}"/>
+  </target>
+
+  <target name="modulepath-nested" depends="-jmods">
+    <link destdir="${image}" modules="${hello.mod},${smile.mod}">
+      <modulepath>
+        <pathelement location="${jdkmods}" unless:blank="${jdkmods}"/>
+        <pathelement location="${jmods}"/>
+      </modulepath>
+    </link>
+  </target>
+
+  <target name="modulepath-both" depends="-jmods">
+    <property name="mod1" value="${output}/mod1"/>
+    <property name="mod2" value="${output}/mod2"/>
+
+    <mkdir dir="${mod1}"/>
+    <mkdir dir="${mod2}"/>
+
+    <copy file="${hello.jmod}" todir="${mod1}"/>
+    <copy file="${smile.jmod}" todir="${mod2}"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${mod1}"
+          modules="${hello.mod},${smile.mod}">
+      <modulepath>
+        <pathelement location="${mod2}"/>
+      </modulepath>
+    </link>
+  </target>
+
+  <target name="modules-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}">
+      <module name="${hello.mod}"/>
+      <module name="${smile.mod}"/>
+    </link>
+  </target>
+
+  <target name="modules-nested-missing-name" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}">
+      <module/>
+      <module name="${smile.mod}"/>
+    </link>
+  </target>
+
+  <target name="modules-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}" modules="${hello.mod}">
+      <module name="${smile.mod}"/>
+      <!--
+        Adding this launcher guarantees an error occurs unless
+        both modules are found.
+      -->
+      <launcher name="Smile" module="${smile.mod}" mainclass="${smile.main-class}"/>
+    </link>
+  </target>
+
+  <target name="observable" depends="-jmods">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${hello.mod},${smile.mod}"
+          observableModules="java.base"/>
+  </target>
+
+  <target name="observable-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${hello.mod},${smile.mod}">
+        <observableModule name="java.base"/>
+    </link>
+  </target>
+
+  <target name="observable-nested-missing-name" depends="-jmods">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${hello.mod},${smile.mod}">
+        <observableModule/>
+    </link>
+  </target>
+
+  <target name="observable-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${hello.mod},${smile.mod}"
+          observableModules="java.base">
+        <observableModule name="java.logging"/>
+    </link>
+  </target>
+
+  <target name="launchers" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          launchers="Hello=${hello.mod}/${hello.main-class},Smile=${smile.mod}/${smile.main-class}"/>
+  </target>
+
+  <target name="launchers-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <launcher name="Hello" module="${hello.mod}" mainClass="${hello.main-class}"/>
+      <launcher name="Smile" module="${smile.mod}" mainClass="${smile.main-class}"/>
+    </link>
+  </target>
+
+  <target name="launchers-nested-missing-name" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <launcher              module="${hello.mod}" mainClass="${hello.main-class}"/>
+      <launcher name="Smile" module="${smile.mod}" mainClass="${smile.main-class}"/>
+    </link>
+  </target>
+
+  <target name="launchers-nested-missing-module" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <launcher name="Hello"                       mainClass="${hello.main-class}"/>
+      <launcher name="Smile" module="${smile.mod}" mainClass="${smile.main-class}"/>
+    </link>
+  </target>
+
+  <target name="launchers-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          launchers="Hello=${hello.mod}/${hello.main-class}">
+      <launcher name="Smile" module="${smile.mod}" mainClass="${smile.main-class}"/>
+    </link>
+  </target>
+
+  <target name="-localefinder" depends="-dirs">
+
+    <property name="localefinder.root" value="${input}/localefinder"/>
+
+    <property name="localefinder.src" value="${localefinder.root}/src"/>
+    <property name="localefinder.classes" value="${localefinder.root}/classes"/>
+    <property name="localefinder.jar.dir" value="${localefinder.root}/jars"/>
+    <property name="localefinder.jar" value="${localefinder.jar.dir}/localefinder.jar"/>
+
+    <property name="localefinder.mod"      value="org.apache.tools.ant.test.localefinder"/>
+    <property name="localefinder.pkg"      value="org.apache.tools.ant.test.localefinder"/>
+    <property name="localefinder.pkg.path" value="org/apache/tools/ant/test/localefinder"/>
+    <property name="localefinder.pkg.dir" value="${localefinder.src}/${localefinder.pkg.path}"/>
+
+    <property name="localefinder.main-class" value="${localefinder.pkg}.LocaleFinder"/>
+
+    <mkdir dir="${localefinder.pkg.dir}"/>
+    <echo file="${localefinder.pkg.dir}/LocaleFinder.java"><![CDATA[
+package ${localefinder.pkg};
+
+import java.util.Locale;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+
+public class LocaleFinder {
+    public static void main(String[] languagesToFind) {
+        Set<String> languages = new HashSet<>();
+        for (Locale locale : Locale.getAvailableLocales()) {
+            languages.add(locale.getLanguage());
+        }
+
+        boolean matched = languages.containsAll(Arrays.asList(languagesToFind));
+        System.exit(matched ? 0 : 1);
+    }
+}]]>
+    </echo>
+    <echo file="${localefinder.src}/module-info.java">
+module ${localefinder.mod} {
+    exports ${localefinder.pkg};
+    requires jdk.localedata;
+}
+    </echo>
+
+    <mkdir dir="${localefinder.classes}"/>
+    <javac srcdir="${localefinder.src}"
+           destdir="${localefinder.classes}"
+           includeAntRuntime="false"
+           debug="true"/>
+
+    <mkdir dir="${localefinder.jar.dir}"/>
+    <jar destfile="${localefinder.jar}" basedir="${localefinder.classes}"/>
+
+    <property name="localefinder.jmod" value="${jmods}/localefinder.jmod"/>
+    <jmod destfile="${localefinder.jmod}" classpath="${localefinder.jar}"/>
+  </target>
+
+  <target name="locales" depends="-localefinder">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${localefinder.mod},jdk.localedata"
+          locales="zh,in"/>
+  </target>
+
+  <target name="locales-nested" depends="-localefinder">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${localefinder.mod},jdk.localedata">
+      <locale name="zh"/>
+      <locale name="in"/>
+    </link>
+  </target>
+
+  <target name="locales-nested-missing-name" depends="-localefinder">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${localefinder.mod},jdk.localedata">
+      <locale/>
+      <locale name="in"/>
+    </link>
+  </target>
+
+  <target name="locales-both" depends="-localefinder">
+    <link destdir="${image}" modulepath="${jmods};${java.home}/jmods"
+          modules="${localefinder.mod},jdk.localedata"
+          locales="zh">
+      <locale name="in"/>
+    </link>
+  </target>
+
+  <target name="ordering" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          resourceOrder="**/resource1.txt"/>
+  </target>
+
+  <target name="ordering-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <resourceOrder pattern="**/resource1.txt"/>
+    </link>
+  </target>
+
+  <target name="ordering-nested-file" depends="-jmods">
+    <tempfile property="listfile" destdir="${output}" suffix=".lst"/>
+    <echo file="${listfile}" message="**/resource1.txt"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <resourceOrder listfile="${listfile}"/>
+    </link>
+  </target>
+
+  <target name="ordering-nested-no-attr" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <resourceOrder/>
+    </link>
+  </target>
+
+  <target name="ordering-nested-both" depends="-jmods">
+    <tempfile property="listfile" destdir="${output}" suffix=".lst"/>
+    <echo file="${listfile}" message="**/resource1.txt"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <resourceOrder pattern="**/resource1.txt" listfile="${listfile}"/>
+    </link>
+  </target>
+
+  <target name="ordering-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          resourceOrder="**/resource1.txt">
+      <resourceOrder pattern="**/resource2.txt"/>
+    </link>
+  </target>
+
+  <target name="excluderesources" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          excludeResources="**/resource1.txt"/>
+  </target>
+
+  <target name="excluderesources-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeResources pattern="**/resource1.txt"/>
+    </link>
+  </target>
+
+  <target name="excluderesources-nested-file" depends="-jmods">
+    <tempfile property="listfile" destdir="${output}" suffix=".lst"/>
+    <echo file="${listfile}" message="**/resource1.txt"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeResources listfile="${listfile}"/>
+    </link>
+  </target>
+
+  <target name="excluderesources-nested-no-attr" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeResources/>
+    </link>
+  </target>
+
+  <target name="excluderesources-nested-both" depends="-jmods">
+    <tempfile property="listfile" destdir="${output}" suffix=".lst"/>
+    <echo file="${listfile}" message="**/resource1.txt"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeResources pattern="**/resource1.txt" listfile="${listfile}"/>
+    </link>
+  </target>
+
+  <target name="excluderesources-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          excludeResources="**/resource1.txt">
+      <excludeResources pattern="**/resource2.txt"/>
+    </link>
+  </target>
+
+  <target name="excludefiles" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          excludeFiles="**/file1.txt"/>
+  </target>
+
+  <target name="excludefiles-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeFiles pattern="**/file1.txt"/>
+    </link>
+  </target>
+
+  <target name="excludefiles-nested-file" depends="-jmods">
+    <tempfile property="listfile" destdir="${output}" suffix=".lst"/>
+    <echo file="${listfile}" message="**/file1.txt"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeFiles listfile="${listfile}"/>
+    </link>
+  </target>
+
+  <target name="excludefiles-nested-no-attr" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeFiles/>
+    </link>
+  </target>
+
+  <target name="excludefiles-nested-both" depends="-jmods">
+    <tempfile property="listfile" destdir="${output}" suffix=".lst"/>
+    <echo file="${listfile}" message="**/file1.txt"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <excludeFiles pattern="**/file1.txt" listfile="${listfile}"/>
+    </link>
+  </target>
+
+  <target name="excludefiles-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          excludeFiles="**/file1.txt">
+      <excludeFiles pattern="**/file2.txt"/>
+    </link>
+  </target>
+
+  <target name="includeheaders" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          includeHeaders="false"/>
+  </target>
+
+  <target name="includemanpages" depends="-manpages,-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          includeManPages="false"/>
+  </target>
+
+  <target name="includenativecommands" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          includeNativeCommands="false"/>
+  </target>
+
+  <target name="compression" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+
+    <property name="compressed-image" value="${output}/image2"/>
+    <link destdir="${compressed-image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          compress="zip"/>
+  </target>
+
+  <target name="compression-nested" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+
+    <property name="compressed-image" value="${output}/image2"/>
+    <link destdir="${compressed-image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <compress level="zip"/>
+    </link>
+  </target>
+
+  <target name="compression-nested-no-attr" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <compress/>
+    </link>
+  </target>
+
+  <target name="compression-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+
+    <property name="compressed-image" value="${output}/image2"/>
+    <link destdir="${compressed-image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          compress="zip">
+      <compress level="zip"/>
+    </link>
+  </target>
+
+  <target name="endian" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}" endianness="little"/>
+  </target>
+
+  <target name="vm" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}" vmType="server"/>
+  </target>
+
+  <target name="releaseinfo-file" depends="-jmods">
+    <property name="props" value="${output}/app.properties"/>
+    <echo file="${props}" message="test=true" encoding="ISO-8859-1"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo file="${props}"/>
+    </link>
+  </target>
+
+  <target name="releaseinfo-delete" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add key="test" value="true"/>
+      </releaseinfo>
+      <releaseinfo delete="test"/>
+    </link>
+  </target>
+
+  <target name="releaseinfo-nested-delete" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add key="test" value="true"/>
+      </releaseinfo>
+      <releaseinfo>
+        <delete key="test"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-nested-delete-no-key" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <delete/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-nested-delete-both" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add key="test" value="true"/>
+        <add key="foo" value="bar"/>
+      </releaseinfo>
+      <releaseinfo delete="test">
+        <delete key="foo"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-file" depends="-jmods">
+    <property name="props" value="${output}/app.properties"/>
+    <echo file="${props}" message="test=s&#xed;" encoding="ISO-8859-1"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add file="${props}"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-file-charset" depends="-jmods">
+    <property name="props" value="${output}/app.properties"/>
+    <echo file="${props}" message="test=s&#xed;" encoding="UTF-8"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add file="${props}" charset="UTF-8"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-key" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add key="test" value="true"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-no-value" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add key="test"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-no-key" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add value="true"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-file-and-key" depends="-jmods">
+    <property name="props" value="${output}/app.properties"/>
+    <echo file="${props}" message="test=s&#xed;" encoding="UTF-8"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add file="${props}" key="test"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="releaseinfo-add-file-and-value" depends="-jmods">
+    <property name="props" value="${output}/app.properties"/>
+    <echo file="${props}" message="test=s&#xed;" encoding="UTF-8"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}">
+      <releaseinfo>
+        <add file="${props}" value="true"/>
+      </releaseinfo>
+    </link>
+  </target>
+
+  <target name="-thrower" depends="-dirs">
+
+    <property name="thrower.root" value="${input}/thrower"/>
+
+    <property name="thrower.src" value="${thrower.root}/src"/>
+    <property name="thrower.classes" value="${thrower.root}/classes"/>
+    <property name="thrower.jar.dir" value="${thrower.root}/jars"/>
+    <property name="thrower.jar" value="${thrower.jar.dir}/thrower.jar"/>
+
+    <property name="thrower.mod"      value="org.apache.tools.ant.test.thrower"/>
+    <property name="thrower.pkg"      value="org.apache.tools.ant.test.thrower"/>
+    <property name="thrower.pkg.path" value="org/apache/tools/ant/test/thrower"/>
+    <property name="thrower.pkg.dir" value="${thrower.src}/${thrower.pkg.path}"/>
+
+    <property name="thrower.main-class" value="${thrower.pkg}.Thrower"/>
+
+    <mkdir dir="${thrower.pkg.dir}"/>
+    <echo file="${thrower.pkg.dir}/Thrower.java">
+package ${thrower.pkg};
+
+public class Thrower {
+    public static void main(String[] args) {
+        throw new RuntimeException("Deliberate exception.");
+    }
+}
+    </echo>
+    <echo file="${thrower.src}/module-info.java">
+module ${thrower.mod} {
+    exports ${thrower.pkg};
+}
+    </echo>
+
+    <mkdir dir="${thrower.classes}"/>
+    <javac srcdir="${thrower.src}" destdir="${thrower.classes}"
+           includeAntRuntime="false" debug="true"/>
+
+    <mkdir dir="${thrower.jar.dir}"/>
+    <jar destfile="${thrower.jar}" basedir="${thrower.classes}"/>
+  </target>
+
+  <target name="debug" depends="-thrower">
+    <property name="thrower.jmod" value="${jmods}/thrower.jmod"/>
+    <jmod destfile="${thrower.jmod}" classpath="${thrower.jar}"/>
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${thrower.mod}" debug="false"/>
+  </target>
+
+  <target name="dedup" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"/>
+  </target>
+
+  <target name="dedup-identical" depends="-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          checkDuplicateLegal="true"/>
+  </target>
+
+  <target name="-sign" depends="-smile,-legal">
+    <property name="keystore.file" value="${output}/keystore"/>
+    <property name="keystore.alias" value="test"/>
+    <property name="keystore.password" value="swordfish"/>
+
+    <condition property="execsuffix" value=".exe" else="">
+      <os family="windows"/>
+    </condition>
+    <exec executable="${java.home}/bin/keytool${execsuffix}" failonerror="true">
+      <arg value="-genkeypair"/>
+      <arg value="-keystore"/>
+      <arg file="${keystore.file}"/>
+      <arg value="-storepass"/>
+      <arg value="${keystore.password}"/>
+      <arg value="-keypass"/>
+      <arg value="${keystore.password}"/>
+      <arg value="-alias"/>
+      <arg value="${keystore.alias}"/>
+      <arg value="-dname"/>
+      <arg value="CN=Ant Unit Test, OU=Ant, O=Apache Software Foundation, L=Unknown, ST=Unknown, C=US"/>
+    </exec>
+
+    <signjar jar="${hello.jar}"
+             keystore="${keystore.file}"
+             alias="${keystore.alias}"
+             storepass="${keystore.password}"/>
+  </target>
+
+  <target name="ignoresigning" depends="-sign,-jmods">
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${hello.mod},${smile.mod}"
+          ignoreSigning="true"/>
+  </target>
+
+  <target name="bindservices" depends="-dirs">
+    <property name="inc.root" value="${input}/inc"/>
+
+    <property name="inc.src" value="${inc.root}/src"/>
+    <property name="inc.classes" value="${inc.root}/classes"/>
+    <property name="inc.jar.dir" value="${inc.root}/jars"/>
+    <property name="inc.jar" value="${inc.jar.dir}/inc.jar"/>
+
+    <property name="inc.mod"      value="org.apache.tools.ant.test.inc"/>
+    <property name="inc.pkg"      value="org.apache.tools.ant.test.inc"/>
+    <property name="inc.pkg.path" value="org/apache/tools/ant/test/inc"/>
+    <property name="inc.pkg.dir" value="${inc.src}/${inc.pkg.path}"/>
+
+    <property name="inc.main-class" value="${inc.pkg}.Incrementer"/>
+
+    <mkdir dir="${inc.pkg.dir}"/>
+    <echo file="${inc.pkg.dir}/IncrementProvider.java">
+package ${inc.pkg};
+
+public interface IncrementProvider {
+    int getIncrement();
+}
+    </echo>
+    <echo file="${inc.pkg.dir}/Incrementer.java">
+package ${inc.pkg};
+
+import java.util.ServiceLoader;
+
+public class Incrementer {
+    public static void main(String[] args) {
+        for (IncrementProvider provider : ServiceLoader.load(IncrementProvider.class)) {
+            int n = 0;
+            for (int i = 0; i &lt; 5; i++) {
+                n += provider.getIncrement();
+                System.out.println(n);
+            }
+        }
+    }
+}
+    </echo>
+    <echo file="${inc.src}/module-info.java">
+module ${inc.mod} {
+    exports ${inc.pkg};
+    uses ${inc.pkg}.IncrementProvider;
+}
+    </echo>
+
+    <mkdir dir="${inc.classes}"/>
+    <javac srcdir="${inc.src}" destdir="${inc.classes}"
+           includeAntRuntime="false" debug="true"/>
+
+    <mkdir dir="${inc.jar.dir}"/>
+    <jar destfile="${inc.jar}" basedir="${inc.classes}"/>
+
+    <property name="provider.root" value="${input}/provider"/>
+    <property name="provider.src" value="${provider.root}/src"/>
+    <property name="provider.classes" value="${provider.root}/classes"/>
+    <property name="provider.jar.dir" value="${provider.root}/jars"/>
+    <property name="provider.jar" value="${provider.jar.dir}/provider.jar"/>
+
+    <property name="provider.mod"      value="org.apache.tools.ant.test.provider"/>
+    <property name="provider.pkg"      value="org.apache.tools.ant.test.provider"/>
+    <property name="provider.pkg.path" value="org/apache/tools/ant/test/provider"/>
+    <property name="provider.pkg.dir" value="${provider.src}/${provider.pkg.path}"/>
+
+    <mkdir dir="${provider.pkg.dir}"/>
+    <echo file="${provider.pkg.dir}/ByTwoProvider.java">
+package ${provider.pkg};
+
+import ${inc.pkg}.IncrementProvider;
+
+public class ByTwoProvider
+implements IncrementProvider {
+    @Override
+    public int getIncrement() {
+        return 2;
+    }
+}
+    </echo>
+    <echo file="${provider.src}/module-info.java">
+module ${provider.mod} {
+    exports ${provider.pkg};
+    requires transitive ${inc.mod};
+    provides ${inc.pkg}.IncrementProvider with ${provider.pkg}.ByTwoProvider;
+}
+    </echo>
+
+    <mkdir dir="${provider.classes}"/>
+    <javac srcdir="${provider.src}" destdir="${provider.classes}"
+           includeAntRuntime="false" debug="true"
+           modulepath="${inc.classes}"/>
+
+    <mkdir dir="${provider.jar.dir}"/>
+    <jar destfile="${provider.jar}" basedir="${provider.classes}"/>
+
+    <property name="inc.jmod" value="${jmods}/inc.jmod"/>
+    <property name="provider.jmod" value="${jmods}/provider.jmod"/>
+
+    <jmod destfile="${inc.jmod}"
+          classpath="${inc.jar}"/>
+
+    <jmod destfile="${provider.jmod}"
+          classpath="${provider.jar}"
+          modulepath="${inc.jar.dir}"/>
+
+    <property name="image2" value="${output}/image2"/>
+
+    <link destdir="${image}" modulepath="${jdkmods}${jmods}"
+          modules="${inc.mod}"
+          bindServices="false"/>
+
+    <link destdir="${image2}" modulepath="${jdkmods}${jmods}"
+          modules="${inc.mod}"
+          bindServices="true"/>
+  </target>
+</project>
diff --git a/src/etc/testcases/taskdefs/loadfile.xml b/src/etc/testcases/taskdefs/loadfile.xml
index 66c9ce4..4e97d9d 100644
--- a/src/etc/testcases/taskdefs/loadfile.xml
+++ b/src/etc/testcases/taskdefs/loadfile.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/macrodef.xml b/src/etc/testcases/taskdefs/macrodef.xml
index f7a356f..cc5395e 100644
--- a/src/etc/testcases/taskdefs/macrodef.xml
+++ b/src/etc/testcases/taskdefs/macrodef.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/makeurl.xml b/src/etc/testcases/taskdefs/makeurl.xml
index dafd00a..76f743a 100644
--- a/src/etc/testcases/taskdefs/makeurl.xml
+++ b/src/etc/testcases/taskdefs/makeurl.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/manifest.xml b/src/etc/testcases/taskdefs/manifest.xml
index aecaf96..104aa1e 100644
--- a/src/etc/testcases/taskdefs/manifest.xml
+++ b/src/etc/testcases/taskdefs/manifest.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/manifestclasspath.xml b/src/etc/testcases/taskdefs/manifestclasspath.xml
index f8a4795..f9c356f 100644
--- a/src/etc/testcases/taskdefs/manifestclasspath.xml
+++ b/src/etc/testcases/taskdefs/manifestclasspath.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/manifestclasspath/Alpha.java b/src/etc/testcases/taskdefs/manifestclasspath/Alpha.java
index 9f00a93..cc389fb 100644
--- a/src/etc/testcases/taskdefs/manifestclasspath/Alpha.java
+++ b/src/etc/testcases/taskdefs/manifestclasspath/Alpha.java
@@ -6,7 +6,7 @@
  * (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
+ *     https://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,
diff --git a/src/etc/testcases/taskdefs/manifestclasspath/Beta.java b/src/etc/testcases/taskdefs/manifestclasspath/Beta.java
index 7ffeffe..dc7fc47 100644
--- a/src/etc/testcases/taskdefs/manifestclasspath/Beta.java
+++ b/src/etc/testcases/taskdefs/manifestclasspath/Beta.java
@@ -6,7 +6,7 @@
  * (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
+ *     https://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,
diff --git a/src/etc/testcases/taskdefs/mkdir.xml b/src/etc/testcases/taskdefs/mkdir.xml
index 1ecc274..3dd30e7 100644
--- a/src/etc/testcases/taskdefs/mkdir.xml
+++ b/src/etc/testcases/taskdefs/mkdir.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/move.xml b/src/etc/testcases/taskdefs/move.xml
index 8b4a6c8..e094755 100644
--- a/src/etc/testcases/taskdefs/move.xml
+++ b/src/etc/testcases/taskdefs/move.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/multimap.xml b/src/etc/testcases/taskdefs/multimap.xml
index ce4b121..edcfe48 100644
--- a/src/etc/testcases/taskdefs/multimap.xml
+++ b/src/etc/testcases/taskdefs/multimap.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -20,8 +20,7 @@
   <import file="../buildfiletest-base.xml"/>
 
   <path id="testclasses">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <mapper id="testmapper"
@@ -188,5 +187,4 @@
     <fail unless="movewithempty.outcome">movewithempty failed</fail>
   </target>
 
-
 </project>
diff --git a/src/etc/testcases/taskdefs/nice.xml b/src/etc/testcases/taskdefs/nice.xml
index e67ee19..e805f5a 100644
--- a/src/etc/testcases/taskdefs/nice.xml
+++ b/src/etc/testcases/taskdefs/nice.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.txt b/src/etc/testcases/taskdefs/optional/TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.txt
diff --git a/src/etc/testcases/taskdefs/optional/antlr/antlr.g b/src/etc/testcases/taskdefs/optional/antlr/antlr.g
index 9f72493..912acaf 100644
--- a/src/etc/testcases/taskdefs/optional/antlr/antlr.g
+++ b/src/etc/testcases/taskdefs/optional/antlr/antlr.g
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/antlr/antlr.xml b/src/etc/testcases/taskdefs/optional/antlr/antlr.xml
index c136d06..de4abc2 100644
--- a/src/etc/testcases/taskdefs/optional/antlr/antlr.xml
+++ b/src/etc/testcases/taskdefs/optional/antlr/antlr.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/antlr/extended.calc.g b/src/etc/testcases/taskdefs/optional/antlr/extended.calc.g
index 00c1993..2eec008 100644
--- a/src/etc/testcases/taskdefs/optional/antlr/extended.calc.g
+++ b/src/etc/testcases/taskdefs/optional/antlr/extended.calc.g
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/depend.xml b/src/etc/testcases/taskdefs/optional/depend/depend.xml
index 8465bb0..04e42a2 100644
--- a/src/etc/testcases/taskdefs/optional/depend/depend.xml
+++ b/src/etc/testcases/taskdefs/optional/depend/depend.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -33,6 +33,11 @@
   <property name="src3.dir" value="src3"/>
   <property name="src4.dir" value="src4"/>
   <property name="src5.dir" value="src5"/>
+  <property name="src6.dir" value="src6"/>
+
+  <condition property="atleast.java9">
+    <javaversion atleast="9"/>
+  </condition>
 
   <target name="help">
     <echo>This buildfile is used as part of Ant's test suite.</echo>
@@ -193,4 +198,10 @@
     <depend srcdir="${tempsrc.dir}" destdir="${classes.dir}" closure="yes"/>
     <fileset id="result" dir="${classes.dir}"/>
   </target>
+
+  <target name="testmoduleinfo" if="${atleast.java9}">
+    <mkdir dir="${output}/java9"/>
+    <javac srcdir="${src6.dir}" destdir="${output}/java9" source="9" target="9"/>
+    <depend srcdir="${src6.dir}" destdir="${output}/java9"/>
+  </target>
 </project>
diff --git a/src/etc/testcases/taskdefs/optional/depend/src1/A.java b/src/etc/testcases/taskdefs/optional/depend/src1/A.java
index dc6df23..bb8e9ef 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src1/A.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src1/A.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src1/B.java b/src/etc/testcases/taskdefs/optional/depend/src1/B.java
index 4be51f7..34dc336 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src1/B.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src1/B.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src1/C.java b/src/etc/testcases/taskdefs/optional/depend/src1/C.java
index d2bfca9..1c2ab9c 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src1/C.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src1/C.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src1/D.java b/src/etc/testcases/taskdefs/optional/depend/src1/D.java
index 127de57..84b8573 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src1/D.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src1/D.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src1/E.java b/src/etc/testcases/taskdefs/optional/depend/src1/E.java
index 0efd613..8fb6d69 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src1/E.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src1/E.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src2/A.java b/src/etc/testcases/taskdefs/optional/depend/src2/A.java
index 02b35be..c940173 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src2/A.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src2/A.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src2/B.java b/src/etc/testcases/taskdefs/optional/depend/src2/B.java
index bc7b7d2..fe9d234 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src2/B.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src2/B.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src3/A.java b/src/etc/testcases/taskdefs/optional/depend/src3/A.java
index 1d973b1..440c6b3 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src3/A.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src3/A.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src3/B.java b/src/etc/testcases/taskdefs/optional/depend/src3/B.java
index bc7b7d2..fe9d234 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src3/B.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src3/B.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src4/test/ContainsOnlyInner.java b/src/etc/testcases/taskdefs/optional/depend/src4/test/ContainsOnlyInner.java
index 9694ddd..6096a2b 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src4/test/ContainsOnlyInner.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src4/test/ContainsOnlyInner.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src4/test/MethodParam.java b/src/etc/testcases/taskdefs/optional/depend/src4/test/MethodParam.java
index 276f016..cda341b 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src4/test/MethodParam.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src4/test/MethodParam.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src4/test/Outer.java b/src/etc/testcases/taskdefs/optional/depend/src4/test/Outer.java
index 0b70900..34893c6 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src4/test/Outer.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src4/test/Outer.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src5/A.java b/src/etc/testcases/taskdefs/optional/depend/src5/A.java
index 19521a1..6dad434 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src5/A.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src5/A.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src5/B.java b/src/etc/testcases/taskdefs/optional/depend/src5/B.java
index bc7b7d2..fe9d234 100644
--- a/src/etc/testcases/taskdefs/optional/depend/src5/B.java
+++ b/src/etc/testcases/taskdefs/optional/depend/src5/B.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/etc/testcases/taskdefs/optional/depend/src6/module-info.java b/src/etc/testcases/taskdefs/optional/depend/src6/module-info.java
new file mode 100644
index 0000000..d7b254f
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/depend/src6/module-info.java
@@ -0,0 +1,4 @@
+module dummy {
+    requires java.base;
+    exports org.dummy;
+}
\ No newline at end of file
diff --git a/src/etc/testcases/taskdefs/optional/depend/src6/org.dummy/Foo.java b/src/etc/testcases/taskdefs/optional/depend/src6/org.dummy/Foo.java
new file mode 100644
index 0000000..0eb8c66
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/depend/src6/org.dummy/Foo.java
@@ -0,0 +1,24 @@
+/*
+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
+
+    https://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.dummy;
+
+public class Foo {
+    public static void main(final String[] args) {
+        System.out.println("foo");
+    }
+}
\ No newline at end of file
diff --git a/src/etc/testcases/taskdefs/optional/echoproperties.properties b/src/etc/testcases/taskdefs/optional/echoproperties.properties
index 4c970e7..0e27365 100644
--- a/src/etc/testcases/taskdefs/optional/echoproperties.properties
+++ b/src/etc/testcases/taskdefs/optional/echoproperties.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/optional/echoproperties.xml b/src/etc/testcases/taskdefs/optional/echoproperties.xml
index 7b1b8bb..661df13 100644
--- a/src/etc/testcases/taskdefs/optional/echoproperties.xml
+++ b/src/etc/testcases/taskdefs/optional/echoproperties.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -123,6 +123,16 @@
     <echoproperties regex=".*ant.*"/>
   </target>
 
+  <target name="testEchoLocalPropertyset">
+    <local name="loc"/>
+    <property name="loc" value="foo"/>
+    <echoproperties>
+      <propertyset>
+        <propertyref name="loc"/>
+      </propertyset>
+    </echoproperties>
+  </target>
+
   <target name="cleanup">
     <delete file="test.properties" failonerror="no" />
     <delete file="test-prefix.properties" failonerror="no" />
diff --git a/src/etc/testcases/taskdefs/optional/i18n/translate/input/resources_ger_DE.properties b/src/etc/testcases/taskdefs/optional/i18n/translate/input/resources_ger_DE.properties
index 7efe9b0..92578dd 100644
--- a/src/etc/testcases/taskdefs/optional/i18n/translate/input/resources_ger_DE.properties
+++ b/src/etc/testcases/taskdefs/optional/i18n/translate/input/resources_ger_DE.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/optional/i18n/translate/translate.xml b/src/etc/testcases/taskdefs/optional/i18n/translate/translate.xml
index e6debd5..d2c807a 100644
--- a/src/etc/testcases/taskdefs/optional/i18n/translate/translate.xml
+++ b/src/etc/testcases/taskdefs/optional/i18n/translate/translate.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/image/image.xml b/src/etc/testcases/taskdefs/optional/image/image.xml
index 2fefa04..d94a69d 100644
--- a/src/etc/testcases/taskdefs/optional/image/image.xml
+++ b/src/etc/testcases/taskdefs/optional/image/image.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -23,47 +23,48 @@
   <target name="setUp">
     <mkdir dir="${output}"/>
     <property name="src.dir" location="${basedir}/src"/>
+    <available classname="com.sun.image.codec.jpeg.JPEGCodec" property="jpeg.codec.available"/>
   </target>
 
   <target name="main" depends="testSimpleScale">
   </target>
 
   <!-- this should produce a single file in the dest dir -->
-  <target name="testSimpleScale" depends="setUp">
+  <target name="testSimpleScale" depends="setUp" if="jpeg.codec.available">
     <image includes="*.jpg" srcdir="${src.dir}" destdir="${output}" overwrite="no" failonerror="no">
       <scale width="300" proportions="width"/>
     </image>
   </target>
 
   <!-- this should put some text in the log -->
-  <target name="testEchoToLog" depends="setUp">
+  <target name="testEchoToLog" depends="setUp" if="jpeg.codec.available">
     <image includes="*.jpg" srcdir="${src.dir}" destdir="${output}" overwrite="no" failonerror="no">
       <scale width="300" proportions="width"/>
     </image>
   </target>
 
   <!-- this should produce a single file in the dest dir -->
-  <target name="testFailOnError" depends="setUp">
+  <target name="testFailOnError" depends="setUp" if="jpeg.codec.available">
     <image includes="*.jpg" srcdir="${src.dir}" destdir="${output}" overwrite="no" failonerror="yes">
       <scale width="300" proportions="width"/>
     </image>
   </target>
 
   <!-- this should produce a single file in the dest dir, overwriting any existing file -->
-  <target name="testOverwriteTrue" depends="setUp">
+  <target name="testOverwriteTrue" depends="setUp" if="jpeg.codec.available">
     <image includes="*.jpg" srcdir="${src.dir}" destdir="${output}" overwrite="true" failonerror="no">
       <scale width="300" proportions="width"/>
     </image>
   </target>
 
   <!-- this should not overwrite the existing file -->
-  <target name="testOverwriteFalse" depends="setUp">
+  <target name="testOverwriteFalse" depends="setUp" if="jpeg.codec.available">
     <image includes="*.jpg" srcdir="${src.dir}" destdir="${output}" overwrite="false" failonerror="no">
       <scale width="300" proportions="width"/>
     </image>
   </target>
 
-  <target name="testSimpleScaleWithMapper" depends="setUp">
+  <target name="testSimpleScaleWithMapper" depends="setUp" if="jpeg.codec.available">
     <image includes="*.jpg" srcdir="${src.dir}"
            destdir="${output}" overwrite="no" failonerror="no">
       <scale width="300" proportions="width"/>
diff --git a/src/etc/testcases/taskdefs/optional/image/imageio.xml b/src/etc/testcases/taskdefs/optional/image/imageio.xml
new file mode 100644
index 0000000..5d42dfd
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/image/imageio.xml
@@ -0,0 +1,97 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<project name="image-test" default="main" basedir=".">
+
+  <import file="../../../buildfiletest-base.xml"/>
+
+  <target name="setUp">
+    <mkdir dir="${output}"/>
+    <property name="src.dir" location="${basedir}/src"/>
+  </target>
+
+  <target name="main" depends="testSimpleScale"/>
+
+  <!-- this should produce a single file in the dest dir -->
+  <target name="testSimpleScale" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="no" failonerror="no">
+      <scale width="300" proportions="width"/>
+    </imageio>
+  </target>
+
+  <!-- this should put some text in the log -->
+  <target name="testEchoToLog" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="no" failonerror="no">
+      <scale width="300" proportions="width"/>
+    </imageio>
+  </target>
+
+  <!-- this should produce a single file in the dest dir -->
+  <target name="testFailOnError" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="no" failonerror="yes">
+      <scale width="300" proportions="width"/>
+    </imageio>
+  </target>
+
+  <!-- this should produce a single file in the dest dir, overwriting any existing file -->
+  <target name="testOverwriteTrue" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="yes" failonerror="no">
+      <scale width="300" proportions="width"/>
+    </imageio>
+  </target>
+
+  <!-- this should produce a single file in the dest dir, overwriting any existing file -->
+  <target name="testDrawOverwriteTrue" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="yes" failonerror="no">
+      <scale width="300" proportions="width"/>
+      <draw xloc="10" yloc="10">
+        <rectangle height="50" width="50" strokewidth="2"/>
+        <text string="Test"/>
+      </draw>
+    </imageio>
+  </target>
+
+  <!-- this should not overwrite the existing file -->
+  <target name="testOverwriteFalse" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="no" failonerror="no">
+      <scale width="300" proportions="width"/>
+    </imageio>
+  </target>
+
+  <!-- this tests a special case of rotation -->
+  <target name="testFlip" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="no" failonerror="no">
+      <rotate angle="-180"/>
+    </imageio>
+  </target>
+
+  <target name="testSimpleScaleWithMapper" depends="setUp">
+    <imageio includes="*.jpg" srcdir="${src.dir}" destdir="${output}"
+             overwrite="no" failonerror="no">
+      <scale width="300" proportions="width"/>
+      <globmapper from="*" to="scaled-*"/>
+    </imageio>
+  </target>
+</project>
diff --git a/src/etc/testcases/taskdefs/optional/javah/build.xml b/src/etc/testcases/taskdefs/optional/javah/build.xml
index ea70b9e..ec15063 100644
--- a/src/etc/testcases/taskdefs/optional/javah/build.xml
+++ b/src/etc/testcases/taskdefs/optional/javah/build.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java b/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java
index 59d03f7..60ad9a3 100644
--- a/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java
+++ b/src/etc/testcases/taskdefs/optional/javah/input/org/example/Foo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jdepend/jdepend.xml b/src/etc/testcases/taskdefs/optional/jdepend/jdepend.xml
index 8418226..54bde44 100644
--- a/src/etc/testcases/taskdefs/optional/jdepend/jdepend.xml
+++ b/src/etc/testcases/taskdefs/optional/jdepend/jdepend.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -16,19 +16,17 @@
   limitations under the License.
 -->
 <project>
-  <property name="testclasses" location="../../../../../../build/testcases"/>
-  
   <path id="all-test-classes.id">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement location="${build.tests.value}"/>
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <path id="example-classes.id">
-    <pathelement location="${testclasses}/org/apache/tools/ant/util/facade" />
+    <pathelement location="${build.tests.value}/org/apache/tools/ant/util/facade"/>
   </path>
 
   <path id="test-classes.id">
-    <pathelement location="${testclasses}" />
+    <pathelement location="${build.tests.value}"/>
   </path>
 
   <target name="simple">
@@ -66,5 +64,4 @@
       <classespath refid="example-classes.id"/>
     </jdepend>
   </target>
-
-</project>
\ No newline at end of file
+</project>
diff --git a/src/etc/testcases/taskdefs/optional/jsp/1nvalid-classname.jsp b/src/etc/testcases/taskdefs/optional/jsp/1nvalid-classname.jsp
index f5b42e2..3cdf8b8 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/1nvalid-classname.jsp
+++ b/src/etc/testcases/taskdefs/optional/jsp/1nvalid-classname.jsp
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jsp/WEB-INF/web.xml b/src/etc/testcases/taskdefs/optional/jsp/WEB-INF/web.xml
index 2ef199d..0b86b21 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/WEB-INF/web.xml
+++ b/src/etc/testcases/taskdefs/optional/jsp/WEB-INF/web.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jsp/default.jsp b/src/etc/testcases/taskdefs/optional/jsp/default.jsp
index c7296b2..457c67a 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/default.jsp
+++ b/src/etc/testcases/taskdefs/optional/jsp/default.jsp
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jsp/missing_tld.jsp b/src/etc/testcases/taskdefs/optional/jsp/missing_tld.jsp
index b837fb1..18606a9 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/missing_tld.jsp
+++ b/src/etc/testcases/taskdefs/optional/jsp/missing_tld.jsp
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jsp/simple.jsp b/src/etc/testcases/taskdefs/optional/jsp/simple.jsp
index c7296b2..457c67a 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/simple.jsp
+++ b/src/etc/testcases/taskdefs/optional/jsp/simple.jsp
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jsp/uriroot.jsp b/src/etc/testcases/taskdefs/optional/jsp/uriroot.jsp
index c7296b2..457c67a 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/uriroot.jsp
+++ b/src/etc/testcases/taskdefs/optional/jsp/uriroot.jsp
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jsp/xml.jsp b/src/etc/testcases/taskdefs/optional/jsp/xml.jsp
index 7bb9e49..59145f6 100644
--- a/src/etc/testcases/taskdefs/optional/jsp/xml.jsp
+++ b/src/etc/testcases/taskdefs/optional/jsp/xml.jsp
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/jspc.xml b/src/etc/testcases/taskdefs/optional/jspc.xml
index f120790..48b761f 100644
--- a/src/etc/testcases/taskdefs/optional/jspc.xml
+++ b/src/etc/testcases/taskdefs/optional/jspc.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junit.xml b/src/etc/testcases/taskdefs/optional/junit.xml
index 34d8cb2..c4e57d6 100644
--- a/src/etc/testcases/taskdefs/optional/junit.xml
+++ b/src/etc/testcases/taskdefs/optional/junit.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -20,85 +20,85 @@
   <import file="../../buildfiletest-base.xml"/>
 
   <target name="setUp">
-    <mkdir dir="${output}" />
+    <mkdir dir="${output}"/>
   </target>
 
-  <property name="showoutput" value="false" />
+  <property name="showoutput" value="false"/>
+
   <path id="test">
-    <pathelement path="${java.class.path}" />
-    <pathelement location="../../../../../build/testcases" />
+    <pathelement path="${java.class.path}"/>
+    <pathelement location="${build.tests.value}"/>
   </path>
 
   <target name="testForkedOutput">
     <junit fork="yes" haltonerror="true" haltonfailure="true" 
            showoutput="${showoutput}">
-      <test name="org.example.junit.Output" />
-      <classpath refid="test" />
+      <test name="org.example.junit.Output"/>
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="testNonForkedOutput">
     <junit fork="false" haltonerror="true" haltonfailure="true"
            showoutput="${showoutput}">
-      <test name="org.example.junit.Output" />
-      <classpath refid="test" />
+      <test name="org.example.junit.Output"/>
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="testForkedThreadedOutput">
     <junit fork="yes" haltonerror="true" haltonfailure="true"
            showoutput="${showoutput}">
-      <test name="org.example.junit.ThreadedOutput" />
-      <classpath refid="test" />
+      <test name="org.example.junit.ThreadedOutput"/>
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="testNonForkedThreadedOutput">
     <junit fork="false" haltonerror="true" haltonfailure="true"
            showoutput="${showoutput}">
-      <test name="org.example.junit.ThreadedOutput" />
-      <classpath refid="test" />
+      <test name="org.example.junit.ThreadedOutput"/>
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="outputTests" 
-          depends="testForkedOutput,testNonForkedOutput,testForkedThreadedOutput,testNonForkedThreadedOutput" />
+          depends="testForkedOutput,testNonForkedOutput,testForkedThreadedOutput,testNonForkedThreadedOutput"/>
 
   <target name="crash">
     <junit fork="true" errorproperty="crashed">
       <test name="org.apache.tools.ant.taskdefs.optional.junit.VmCrash"/>
-      <classpath refid="test" />
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="nocrash">
     <junit fork="true" errorproperty="crashed">
       <test name="org.apache.tools.ant.taskdefs.optional.junit.NoVmCrash"/>
-      <classpath refid="test" />
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="timeout">
     <junit fork="true" errorproperty="timeout" timeout="1000">
       <test name="org.apache.tools.ant.taskdefs.optional.junit.Sleeper"/>
-      <classpath refid="test" />
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="notimeout">
     <junit fork="true" errorproperty="timeout" timeout="15000">
       <test name="org.apache.tools.ant.taskdefs.optional.junit.Sleeper"/>
-      <classpath refid="test" />
+      <classpath refid="test"/>
     </junit>
   </target>
 
   <target name="capture" depends="setUp">
     <property name="fork" value="false"/>
     <junit fork="${fork}">
-      <test
-        name="org.apache.tools.ant.taskdefs.optional.junit.Printer"
-        todir="${output}"
-        outfile="testlog"/>
+      <test name="org.apache.tools.ant.taskdefs.optional.junit.Printer"
+            todir="${output}"
+            outfile="testlog"/>
       <formatter type="plain"/>
       <classpath refid="test"/>
     </junit>
@@ -120,8 +120,7 @@
       <classpath refid="test"/>
       <batchtest todir="${output}">
         <fileset dir="../../../../tests/junit">
-          <include
-            name="org/apache/tools/ant/taskdefs/optional/junit/*Test.java"/>
+          <include name="org/apache/tools/ant/taskdefs/optional/junit/*Test.java"/>
           <!-- tests remove out-dir on tearDown -->
           <exclude name="**/JUnitTestListenerTest.java"/>
           <exclude name="**/JUnitTaskTest.java"/>
@@ -139,8 +138,7 @@
       <classpath refid="test"/>
       <batchtest todir="${output}">
         <fileset dir="../../../../tests/junit">
-          <include
-            name="org/apache/tools/ant/taskdefs/optional/junit/*Test.java"/>
+          <include name="org/apache/tools/ant/taskdefs/optional/junit/*Test.java"/>
           <!-- tests remove out-dir on tearDown -->
           <exclude name="**/JUnitTestListenerTest.java"/>
           <exclude name="**/JUnitTaskTest.java"/>
@@ -154,12 +152,11 @@
     <mkdir dir="${output}"/>
     <junit fork="true" forkmode="once">
       <formatter extension="foo"
-        classname="org.apache.tools.ant.taskdefs.optional.junit.TestFormatter"/>
+                 classname="org.apache.tools.ant.taskdefs.optional.junit.TestFormatter"/>
       <classpath refid="test"/>
       <batchtest todir="${output}">
         <fileset dir="../../../../tests/junit">
-          <include
-            name="org/apache/tools/ant/taskdefs/optional/junit/*Test.java"/>
+          <include name="org/apache/tools/ant/taskdefs/optional/junit/*Test.java"/>
           <!-- tests remove out-dir on tearDown -->
           <exclude name="**/JUnitTestListenerTest.java"/>
           <exclude name="**/JUnitTaskTest.java"/>
@@ -244,8 +241,7 @@
     <ant target="failureRecorder.internal"
          antfile="junit.xml" 
          inheritAll="false"
-         inheritRefs="false" 
-    />
+         inheritRefs="false"/>
   </target>
   
   <target name="failureRecorder.fixing">
@@ -281,47 +277,46 @@
   <target name="testSkippableTests">
     <mkdir dir="${output}"/>
     <junit>
-            <formatter type="xml"/>
-            <classpath refid="test"/>
-            <batchtest todir="${output}">
-                <fileset dir="../../../../tests/junit">
-                    <include name="org/example/junit/JUnit4Skippable.java"/>
-                    <!-- tests remove out-dir on tearDown -->
-                </fileset>
-            </batchtest>
+      <formatter type="xml"/>
+      <classpath refid="test"/>
+      <batchtest todir="${output}">
+        <fileset dir="../../../../tests/junit">
+          <include name="org/example/junit/JUnit4Skippable.java"/>
+          <!-- tests remove out-dir on tearDown -->
+        </fileset>
+      </batchtest>
     </junit>
   </target>
 
-
   <!-- Skipping classes that are not tests -->
   <target name="testNonTests">
     <mkdir dir="${output}"/>
-        <junit>
-            <formatter type="xml"/>
-            <classpath refid="test"/>
-            <batchtest todir="${output}" skipNonTests="true">
-                <fileset dir="../../../../tests/junit">
-                    <include name="org/example/junit/*Missed.java"/>
-                    <!-- tests remove out-dir on tearDown -->
-                </fileset>
-            </batchtest>
+    <junit>
+      <formatter type="xml"/>
+      <classpath refid="test"/>
+      <batchtest todir="${output}" skipNonTests="true">
+        <fileset dir="../../../../tests/junit">
+          <include name="org/example/junit/*Missed.java"/>
+          <!-- tests remove out-dir on tearDown -->
+        </fileset>
+      </batchtest>
     </junit>
   </target>
 
-    <!-- Not skipping classes that are not tests -->
-    <target name="testNonTestsRun">
-        <mkdir dir="${output}"/>
-        <junit>
-            <formatter type="xml"/>
-            <classpath refid="test"/>
-            <batchtest todir="${output}" skipNonTests="false">
-                <fileset dir="../../../../tests/junit">
-                    <include name="org/example/junit/*Missed.java"/>
-                    <!-- tests remove out-dir on tearDown -->
-                </fileset>
-            </batchtest>
-        </junit>
-    </target>
+  <!-- Not skipping classes that are not tests -->
+  <target name="testNonTestsRun">
+    <mkdir dir="${output}"/>
+    <junit>
+      <formatter type="xml"/>
+      <classpath refid="test"/>
+      <batchtest todir="${output}" skipNonTests="false">
+        <fileset dir="../../../../tests/junit">
+          <include name="org/example/junit/*Missed.java"/>
+          <!-- tests remove out-dir on tearDown -->
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
 
   <target name="testTestMethods" >
     <property name="tmp.dir" value="${output}"/>
@@ -339,36 +334,31 @@
       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}">
-
     </javac>
     <junit fork="false" printsummary="true" haltonerror="true">
       <classpath>
-        <pathelement location="${tmp.dir}" />
-        <path refid="test" />
+        <pathelement location="${tmp.dir}"/>
+        <path refid="test"/>
       </classpath>
-      <test name="T1" methods="testOK" />
-      <test name="T2" methods="ok" />
+      <test name="T1" methods="testOK"/>
+      <test name="T2" methods="ok"/>
     </junit>
   </target>
 
   <target name="testCheckForkedPath">
-    <property name="includeantruntime" value="yes" />
+    <property name="includeantruntime" value="yes"/>
     <!-- duplicate the Ant classes into a jar -->
-    <jar destfile="${output}/ant.jar" basedir="${antclasses}" />
+    <jar destfile="${output}/ant.jar" basedir="${antclasses}"/>
     <junit fork="yes" haltonerror="true" haltonfailure="true"
-             showoutput="${showoutput}" includeantruntime="${includeantruntime}">
-      <test name="org.example.junit.Output" />
+           showoutput="${showoutput}" includeantruntime="${includeantruntime}">
+      <test name="org.example.junit.Output"/>
       <classpath>
-        <pathelement location="../../../../../build/testcases" />
-        <pathelement location="${junitjar}" />
-        <pathelement location="${output}/ant.jar" />
+        <pathelement location="${build.tests.value}"/>
+        <pathelement location="${junitjar}"/>
+        <pathelement location="${output}/ant.jar"/>
       </classpath>
     </junit>
   </target>
diff --git a/src/etc/testcases/taskdefs/optional/junit/cdataoutput.xml b/src/etc/testcases/taskdefs/optional/junit/cdataoutput.xml
index ab5409b..a99401d 100644
--- a/src/etc/testcases/taskdefs/optional/junit/cdataoutput.xml
+++ b/src/etc/testcases/taskdefs/optional/junit/cdataoutput.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junit/matches.xml b/src/etc/testcases/taskdefs/optional/junit/matches.xml
index 2451cf8..7418561 100644
--- a/src/etc/testcases/taskdefs/optional/junit/matches.xml
+++ b/src/etc/testcases/taskdefs/optional/junit/matches.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junit/teardownlistener.xml b/src/etc/testcases/taskdefs/optional/junit/teardownlistener.xml
index abb6a41..83fe0e4 100644
--- a/src/etc/testcases/taskdefs/optional/junit/teardownlistener.xml
+++ b/src/etc/testcases/taskdefs/optional/junit/teardownlistener.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -18,15 +18,15 @@
 <project>
 
   <path id="test">
-    <pathelement path="${java.class.path}" />
-    <pathelement location="../../../../../../build/testcases" />
+    <pathelement path="${java.class.path}"/>
+    <pathelement location="${build.tests.value}"/>
   </path>
 
   <target name="testNoTeardown">
     <junit haltonerror="false" errorproperty="error" fork="true" timeout="1000">
       <formatter type="plain" usefile="false"/>
       <batchtest>
-        <fileset dir="../../../../../../build/testcases">
+        <fileset dir="${build.tests.value}">
           <include name="org/example/junit/Timeout*"/>
         </fileset>
       </batchtest>
@@ -40,11 +40,12 @@
       <formatter classname="org.apache.tools.ant.taskdefs.optional.junit.TearDownOnVmCrash"
                  usefile="false"/>
       <batchtest>
-        <fileset dir="../../../../../../build/testcases">
+        <fileset dir="${build.tests.value}">
           <include name="org/example/junit/Timeout*"/>
         </fileset>
       </batchtest>
       <classpath refid="test"/>
     </junit>
   </target>
+
 </project>
diff --git a/src/etc/testcases/taskdefs/optional/junitlauncher.xml b/src/etc/testcases/taskdefs/optional/junitlauncher.xml
new file mode 100644
index 0000000..87b00ad
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/junitlauncher.xml
@@ -0,0 +1,375 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<project name="junitlauncher-test" basedir=".">
+
+    <property name="output.dir" location="${java.io.tmpdir}"/>
+    <property name="build.classes.dir" value="${build.tests.value}"/>
+    <target name="init">
+        <mkdir dir="${output.dir}"/>
+    </target>
+
+    <path id="junit.platform.classpath">
+        <fileset dir="../../../../../lib/optional" includes="junit-platform*.jar"/>
+    </path>
+
+    <path id="junit.engine.vintage.classpath">
+        <fileset dir="../../../../../lib/optional" includes="junit-vintage-engine*.jar"/>
+        <fileset dir="../../../../../lib/optional" includes="junit-*.jar"/>
+        <fileset dir="../../../../../lib/optional" includes="hamcrest*.jar"/>
+        <fileset dir="../../../../../lib/optional" includes="opentest4j*.jar"/>
+    </path>
+
+    <path id="junit.engine.jupiter.classpath">
+        <fileset dir="../../../../../lib/optional">
+            <include name="junit-jupiter*.jar"/>
+            <include name="opentest4j*.jar"/>
+        </fileset>
+    </path>
+
+    <path id="test.classpath">
+        <pathelement location="${build.classes.dir}"/>
+        <path refid="junit.engine.vintage.classpath"/>
+        <path refid="junit.engine.jupiter.classpath"/>
+    </path>
+
+    <target name="test-failure-stops-build" depends="init">
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      outputDir="${output.dir}"
+                      resultFile="${test-failure-stops-build.tracker}"
+                      if="test-failure-stops-build.tracker"/>
+
+            <!-- A specific test meant to fail -->
+            <test name="org.example.junitlauncher.vintage.AlwaysFailingJUnit4Test" haltOnFailure="true"/>
+            <!-- classpath to be used for the tests -->
+            <classpath refid="test.classpath"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-failure-continues-build" depends="init">
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      outputDir="${output.dir}"
+                      resultFile="${test-failure-continues-build.tracker}"
+                      if="test-failure-continues-build.tracker"/>
+
+            <!-- A specific test meant to fail -->
+            <test name="org.example.junitlauncher.vintage.AlwaysFailingJUnit4Test"/>
+            <classpath refid="test.classpath"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-success" depends="init">
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      outputDir="${output.dir}"
+                      resultFile="${test-success.tracker}"
+                      if="test-success.tracker"/>
+            <!-- A specific test meant to pass -->
+            <test name="org.example.junitlauncher.vintage.JUnit4SampleTest"/>
+            <classpath refid="test.classpath"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-one-specific-method" depends="init">
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      outputDir="${output.dir}"
+                      resultFile="${test-one-specific-method.tracker}"
+                      if="test-one-specific-method.tracker"/>
+
+            <test name="org.example.junitlauncher.vintage.JUnit4SampleTest" methods="testBar" haltonfailure="true"/>
+            <classpath refid="test.classpath"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-multiple-specific-methods" depends="init">
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      outputDir="${output.dir}"
+                      resultFile="${test-multiple-specific-methods.tracker}"
+                      if="test-multiple-specific-methods.tracker"/>
+
+            <test name="org.example.junitlauncher.vintage.JUnit4SampleTest" methods=" testFoo, testFooBar "
+                  haltonfailure="true"/>
+            <classpath refid="test.classpath"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-multiple-individual" depends="init">
+        <junitlauncher>
+            <test name="org.example.junitlauncher.vintage.AlwaysFailingJUnit4Test">
+                <listener classname="org.example.junitlauncher.Tracker"
+                          outputDir="${output.dir}"
+                          resultFile="${test-multiple-individual-1.tracker}"
+                          if="test-multiple-individual-1.tracker"/>
+            </test>
+            <test name="org.example.junitlauncher.vintage.JUnit4SampleTest">
+                <listener classname="org.example.junitlauncher.Tracker"
+                          outputDir="${output.dir}"
+                          resultFile="${test-multiple-individual-2.tracker}"
+                          if="test-multiple-individual-2.tracker"/>
+            </test>
+            <classpath refid="test.classpath"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-batch" depends="init">
+        <property name="junitlauncher.test.tracker.append.file" value="${output.dir}/${test-batch.tracker}"/>
+        <junitlauncher>
+            <classpath refid="test.classpath"/>
+            <testclasses outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker"
+                          if="test-batch.tracker"/>
+
+                <fileset dir="${build.classes.dir}">
+                    <include name="org/example/**/junitlauncher/**/"/>
+                    <exclude name="org/example/**/junitlauncher/**/ForkedTest.class"/>
+                </fileset>
+                <listener type="legacy-brief" sendSysOut="true"/>
+                <listener type="legacy-xml" sendSysErr="true" sendSysOut="true"/>
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+    <target name="test-basic-fork" depends="init">
+        <junitlauncher>
+            <classpath refid="test.classpath"/>
+            <test name="org.example.junitlauncher.vintage.ForkedTest" outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker"
+                          outputDir="${output.dir}"
+                          resultFile="${test-basic-fork.tracker}"
+                          if="test-basic-fork.tracker"/>
+
+                <fork dir="${basedir}">
+                    <sysproperty key="junitlauncher.test.sysprop.one" value="forked"/>
+                </fork>
+
+                <listener type="legacy-xml" sendSysErr="true" sendSysOut="true" useLegacyReportingName="false"/>
+            </test>
+        </junitlauncher>
+    </target>
+
+    <target name="test-junit-platform-lib-excluded" depends="init">
+        <junitlauncher>
+            <classpath refid="junit.engine.jupiter.classpath"/>
+            <classpath>
+                <pathelement location="${build.classes.dir}"/>
+            </classpath>
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
+                <!-- expect the test to not be launched due to CNFE on JUnit platform classes -->
+                <fork dir="${basedir}" includeJUnitPlatformLibraries="false"/>
+            </test>
+        </junitlauncher>
+    </target>
+
+    <target name="test-junit-ant-runtime-lib-excluded" depends="init">
+        <junitlauncher>
+            <classpath refid="junit.engine.jupiter.classpath"/>
+            <classpath>
+                <pathelement location="${build.classes.dir}"/>
+            </classpath>
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
+                <!-- expect the test to not be launched due to CNFE on Ant runtime classes -->
+                <fork dir="${basedir}" includeAntRuntimeLibraries="false"/>
+            </test>
+        </junitlauncher>
+    </target>
+
+    <target name="test-junit-platform-lib-custom-location" depends="init">
+        <junitlauncher>
+            <classpath refid="junit.engine.jupiter.classpath"/>
+            <classpath>
+                <pathelement location="${build.classes.dir}"/>
+            </classpath>
+            <!-- we set includeJUnitPlatformLibraries=false on the fork element
+            and then explicitly specify a location of the JUnit platform libraries -->
+            <classpath refid="junit.platform.classpath"/>
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker"
+                          outputDir="${output.dir}"
+                          resultFile="${test-junit-platform-lib-custom-location.tracker}"
+                          if="test-junit-platform-lib-custom-location.tracker"/>
+                <fork dir="${basedir}" includeJUnitPlatformLibraries="false"/>
+            </test>
+        </junitlauncher>
+    </target>
+
+    <target name="test-ant-runtime-lib-custom-location" depends="init">
+        <!-- duplicate the Ant classes into a jar -->
+        <jar destfile="${output.dir}/ant-runtime-duplicated.jar" basedir="${ant.runtime.classes.original.path}"/>
+
+        <property name="junitlauncher.test.tracker.append.file" value="${output.dir}/${test-ant-runtime-lib-custom-location.tracker}"/>
+        <junitlauncher>
+            <classpath>
+                <path refid="junit.engine.jupiter.classpath"/>
+                <path refid="junit.engine.vintage.classpath"/>
+                <pathelement location="${build.classes.dir}"/>
+                <!-- our duplicated Ant runtime classes jar, since we
+                exclude the original Ant runtime classes on the fork element
+                by setting includeAntRuntimeLibraries=false -->
+                <pathelement location="${output.dir}/ant-runtime-duplicated.jar"/>
+            </classpath>
+            <testclasses outputdir="${output.dir}">
+                <fileset dir="${build.classes.dir}">
+                    <include name="org/example/**/junitlauncher/**/"/>
+                </fileset>
+                <listener classname="org.example.junitlauncher.Tracker"
+                          if="test-ant-runtime-lib-custom-location.tracker"/>
+                <fork dir="${basedir}" includeAntRuntimeLibraries="false">
+                    <sysproperty key="junitlauncher.test.sysprop.one" value="forked"/>
+                </fork>
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+
+    <target name="test-ant-and-junit-platform-lib-custom-location" depends="init">
+        <!-- duplicate the Ant classes into a jar -->
+        <jar destfile="${output.dir}/ant-runtime-duplicated.jar" basedir="${ant.runtime.classes.original.path}"/>
+
+        <junitlauncher>
+            <classpath>
+                <path refid="junit.engine.vintage.classpath"/>
+                <pathelement location="${build.classes.dir}"/>
+                <!-- our duplicated Ant runtime classes jar, since we
+                exclude the original Ant runtime classes on the fork element
+                by setting includeAntRuntimeLibraries=false -->
+                <pathelement location="${output.dir}/ant-runtime-duplicated.jar"/>
+                <!-- we set includeJUnitPlatformLibraries=false on the fork element
+                    and then explicitly specify a location of the JUnit platform libraries -->
+                <path refid="junit.platform.classpath"/>
+            </classpath>
+            <testclasses outputdir="${output.dir}">
+                <fileset dir="${build.classes.dir}">
+                    <include name="org/example/**/junitlauncher/**/JUnit4SampleTest.class"/>
+                </fileset>
+                <listener classname="org.example.junitlauncher.Tracker"
+                          outputDir="${output.dir}"
+                          resultFile="${test-ant-and-junit-platform-lib-custom-location.tracker}"
+                          if="test-ant-and-junit-platform-lib-custom-location.tracker"/>
+                <fork dir="${basedir}" includeAntRuntimeLibraries="false" includeJUnitPlatformLibraries="false"/>
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+	<target name="test-method-with-include-tag" depends="init">
+        <!-- junitlauncher  includeTags="fast, superfast" excludeTags="slow"-->
+        <junitlauncher includeTags="   fast   , superfast" excludeTags="   slow">
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker" outputDir="${output.dir}"
+                          resultFile="${test-method-with-include-tag.tracker}" if="test-method-with-include-tag.tracker" />
+            </test>
+        </junitlauncher>
+    </target>
+
+    <target name="test-method-with-exclude-tag" depends="init">
+        <junitlauncher excludeTags="slow">
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker" outputDir="${output.dir}"
+                          resultFile="${test-method-with-exclude-tag.tracker}" if="test-method-with-exclude-tag.tracker" />
+            </test>
+        </junitlauncher>
+    </target>
+
+    <target name="test-method-with-tag-2-classes" depends="init">
+        <junitlauncher includeTags="fast">
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker" outputDir="${output.dir}"
+                          resultFile="${test-method-with-tag-2-classes1.tracker}" if="test-method-with-tag-2-classes1.tracker" />
+            </test>
+            <test name="org.example.junitlauncher.jupiter.JupiterTagSampleTest" outputdir="${output.dir}">
+                <listener classname="org.example.junitlauncher.Tracker" outputDir="${output.dir}"
+                          resultFile="${test-method-with-tag-2-classes2.tracker}" if="test-method-with-tag-2-classes2.tracker" />
+            </test>
+        </junitlauncher>
+    </target>
+	
+    <target name="test-beforeall-failure-stops-build" depends="init">
+        <property name="junitlauncher.test.tracker.append.file" value="${output.dir}/${test-beforeall-failure-stops-build.tracker}"/>
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      if="test-beforeall-failure-stops-build.tracker"/>
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll" haltOnFailure="true"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-beforeall-failure-continues-build" depends="init">
+        <property name="junitlauncher.test.tracker.append.file" value="${output.dir}/${test-beforeall-failure-continues-build.tracker}"/>
+        <junitlauncher>
+            <listener classname="org.example.junitlauncher.Tracker"
+                      if="test-beforeall-failure-continues-build.tracker"/>
+            <test name="org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll"/>
+        </junitlauncher>
+    </target>
+
+    <target name="test-method-with-tag-fileset" depends="init">
+        <property name="junitlauncher.test.tracker.append.file" value="${output.dir}/${test-method-with-tag-fileset.tracker}"/>
+        <junitlauncher includeTags="fast">
+            <testclasses outputdir="${output.dir}">
+                <fileset dir="${build.classes.dir}">
+                    <include name="org/example/junitlauncher/jupiter/*" />
+                </fileset>
+                <listener classname="org.example.junitlauncher.Tracker" outputDir="${output.dir}"
+                          if="test-method-with-tag-fileset.tracker" />
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+    <target name="test-method-with-tag-fileset-fork" depends="init">
+        <property name="junitlauncher.test.tracker.append.file" value="${output.dir}/${test-method-with-tag-fileset-fork.tracker}" />
+        <junitlauncher includeTags="fast">
+            <classpath refid="junit.engine.jupiter.classpath" />
+                    <classpath>
+                        <pathelement location="${build.classes.dir}" />
+                    </classpath>
+                    <classpath refid="junit.platform.classpath" />
+            <testclasses outputdir="${output.dir}">
+                <fileset dir="${build.classes.dir}">
+                    <include name="org/example/junitlauncher/jupiter/*" />
+                </fileset>
+                <fork dir="${basedir}" includeJUnitPlatformLibraries="false">
+                </fork>
+                <listener classname="org.example.junitlauncher.Tracker" outputDir="${output.dir}"
+                          if="test-method-with-tag-fileset-fork.tracker" />
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+    <target name="bz-63958">
+        <junitlauncher>
+            <classpath refid="test.classpath"/>
+            <testclasses>
+                <listener classname="org.example.junitlauncher.Tracker"
+                          outputDir="${output.dir}"
+                          resultFile="${bz-63958.tracker}"
+                          if="bz-63958.tracker"/>
+                <fileset dir="${build.classes.dir}">
+                    <include name="**/ForkedTest.class"/>
+                </fileset>
+                <fork>
+                    <sysproperty key="junitlauncher.test.sysprop.one" value="forked"/>
+                </fork>
+            </testclasses>
+            <listener type="legacy-plain" sendSysOut="true" />
+            <listener type="legacy-brief" sendSysOut="true" useLegacyReportingName="true"/>
+        </junitlauncher>
+    </target>
+</project>
+
diff --git a/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-frames.xsl b/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-frames.xsl
index 3c0d85a..135ac83 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-frames.xsl
+++ b/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-frames.xsl
@@ -15,7 +15,7 @@
    (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
+       https://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,
@@ -696,7 +696,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href="http://www.junit.org/">JUnit</a> and <a href="http://ant.apache.org/">Ant</a>.</td>
+        <td align="right">Designed for use with <a href="https://www.junit.org/">JUnit</a> and <a href="https://ant.apache.org/">Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-import.xsl b/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-import.xsl
index ecba47b..ccfccb8 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-import.xsl
+++ b/src/etc/testcases/taskdefs/optional/junitreport-with-include/junit-import.xsl
@@ -12,7 +12,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport.xml b/src/etc/testcases/taskdefs/optional/junitreport.xml
index 6080662..87f0f17 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport.xml
+++ b/src/etc/testcases/taskdefs/optional/junitreport.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport/INCOMPLETE-sampleproject.incomplete.xml b/src/etc/testcases/taskdefs/optional/junitreport/INCOMPLETE-sampleproject.incomplete.xml
index 56af014..108ea72 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport/INCOMPLETE-sampleproject.incomplete.xml
+++ b/src/etc/testcases/taskdefs/optional/junitreport/INCOMPLETE-sampleproject.incomplete.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport/NAMESPACE-sampleproject.namespace.xml b/src/etc/testcases/taskdefs/optional/junitreport/NAMESPACE-sampleproject.namespace.xml
index 41e7dbf..9c76ae0 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport/NAMESPACE-sampleproject.namespace.xml
+++ b/src/etc/testcases/taskdefs/optional/junitreport/NAMESPACE-sampleproject.namespace.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.coins.CoinTest.xml b/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.coins.CoinTest.xml
index 6bc99f2..cb31159 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.coins.CoinTest.xml
+++ b/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.coins.CoinTest.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.util.UniqueStringTest.xml b/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.util.UniqueStringTest.xml
index f4016c2..09408ef 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.util.UniqueStringTest.xml
+++ b/src/etc/testcases/taskdefs/optional/junitreport/TEST-sampleproject.util.UniqueStringTest.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport/WRONGELEMENT-sampleproject.wrongelement.xml b/src/etc/testcases/taskdefs/optional/junitreport/WRONGELEMENT-sampleproject.wrongelement.xml
index 9cb5a14..926efc4 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport/WRONGELEMENT-sampleproject.wrongelement.xml
+++ b/src/etc/testcases/taskdefs/optional/junitreport/WRONGELEMENT-sampleproject.wrongelement.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl b/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl
index ca313af..55dd776 100644
--- a/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl
+++ b/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl
@@ -14,7 +14,7 @@
    (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
+       https://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,
@@ -696,7 +696,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href="http://www.junit.org/">JUnit</a> and <a href="http://ant.apache.org/">Ant</a>.</td>
+        <td align="right">Designed for use with <a href="https://www.junit.org/">JUnit</a> and <a href="https://ant.apache.org/">Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/etc/testcases/taskdefs/optional/native2ascii/build.xml b/src/etc/testcases/taskdefs/optional/native2ascii/build.xml
index 27b4031..48f8b00 100644
--- a/src/etc/testcases/taskdefs/optional/native2ascii/build.xml
+++ b/src/etc/testcases/taskdefs/optional/native2ascii/build.xml
@@ -8,7 +8,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/net/ftp.xml b/src/etc/testcases/taskdefs/optional/net/ftp.xml
index aaf4b8e..5c92643 100644
--- a/src/etc/testcases/taskdefs/optional/net/ftp.xml
+++ b/src/etc/testcases/taskdefs/optional/net/ftp.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/propertyfile.xml b/src/etc/testcases/taskdefs/optional/propertyfile.xml
index 20a1727..1ee71b6 100644
--- a/src/etc/testcases/taskdefs/optional/propertyfile.xml
+++ b/src/etc/testcases/taskdefs/optional/propertyfile.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/pvcs.xml b/src/etc/testcases/taskdefs/optional/pvcs.xml
index 99bfcff..5539207 100644
--- a/src/etc/testcases/taskdefs/optional/pvcs.xml
+++ b/src/etc/testcases/taskdefs/optional/pvcs.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -37,7 +37,7 @@
   </target>
 
   <target name="test5" description="Get the latest from PVCS">
-    <pvcs pvcsbin="/home/cvs/pvcsant/src/etc/testcases/taskdefs" 
+    <pvcs pvcsbin="/home/cvs/pvcsant/src/etc/testcases/taskdefs"
 			 repository="//ct4serv2/pvcs/monitor"/>
   </target>
 
diff --git a/src/etc/testcases/taskdefs/optional/replaceregexp.properties b/src/etc/testcases/taskdefs/optional/replaceregexp.properties
index d7f057e..3c8d147 100644
--- a/src/etc/testcases/taskdefs/optional/replaceregexp.properties
+++ b/src/etc/testcases/taskdefs/optional/replaceregexp.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/optional/replaceregexp.xml b/src/etc/testcases/taskdefs/optional/replaceregexp.xml
index 58fdc59..902d283 100644
--- a/src/etc/testcases/taskdefs/optional/replaceregexp.xml
+++ b/src/etc/testcases/taskdefs/optional/replaceregexp.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -18,11 +18,9 @@
 <project name="test" default="def" basedir=".">
   <import file="../../buildfiletest-base.xml"/>
 
-  <property name="root" location="../../../../.."/>
-
   <target name="setUp">
-    <mkdir dir="${output}" />
-    <copy file="replaceregexp.properties" tofile="${output}/test.properties" />
+    <mkdir dir="${output}"/>
+    <copy file="replaceregexp.properties" tofile="${output}/test.properties"/>
   </target>
 
   <target name="def">
@@ -30,39 +28,39 @@
   </target>
 
   <target name="setUp-nl">
-    <mkdir dir="${output}" />
-    <copy file="replaceregexp2.properties" tofile="${output}/test.properties" />
+    <mkdir dir="${output}"/>
+    <copy file="replaceregexp2.properties" tofile="${output}/test.properties"/>
   </target>
 
   <target name="testReplace" depends="setUp">
     <replaceregexp file="${output}/test.properties" byline="true">
-      <regexp pattern="Old(.*)=(.*)" />
-      <substitution expression="NewProp=\1\2" />
+      <regexp pattern="Old(.*)=(.*)"/>
+      <substitution expression="NewProp=\1\2"/>
     </replaceregexp>
   </target>
   <!-- use in conjunction with testDirectoryDateDoesNotChange to make sure something will happen -->
   <target name="touchDirectory">
-    <copy file="replaceregexp.properties" tofile="${output}/test.properties" />
+    <copy file="replaceregexp.properties" tofile="${output}/test.properties"/>
 
   </target>
   <target name="testDirectoryDateDoesNotChange">
     <replaceregexp file="${output}/test.properties" byline="true">
-      <regexp pattern="foo" />
+      <regexp pattern="foo"/>
         <substitution expression="bar"/>
       </replaceregexp>
   </target>
 
   <target name="testDontAddNewline1" depends="setUp-nl">
     <replaceregexp file="${output}/test.properties" byline="false">
-      <regexp pattern="Old(.*)=(.*)" />
-      <substitution expression="NewProp=\1\2" />
+      <regexp pattern="Old(.*)=(.*)"/>
+      <substitution expression="NewProp=\1\2"/>
     </replaceregexp>
   </target>
 
   <target name="testDontAddNewline2" depends="setUp-nl">
     <replaceregexp file="${output}/test.properties" byline="true">
-      <regexp pattern="Old(.*)=(.*)" />
-      <substitution expression="NewProp=\1\2" />
+      <regexp pattern="Old(.*)=(.*)"/>
+      <substitution expression="NewProp=\1\2"/>
     </replaceregexp>
   </target>
 
diff --git a/src/etc/testcases/taskdefs/optional/replaceregexp2.properties b/src/etc/testcases/taskdefs/optional/replaceregexp2.properties
index ada7727..48922ab 100644
--- a/src/etc/testcases/taskdefs/optional/replaceregexp2.properties
+++ b/src/etc/testcases/taskdefs/optional/replaceregexp2.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/optional/replaceregexp2.result.properties b/src/etc/testcases/taskdefs/optional/replaceregexp2.result.properties
index 6393cd7..5ab6bc5 100644
--- a/src/etc/testcases/taskdefs/optional/replaceregexp2.result.properties
+++ b/src/etc/testcases/taskdefs/optional/replaceregexp2.result.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/optional/schemavalidate.xml b/src/etc/testcases/taskdefs/optional/schemavalidate.xml
index f43201e..152f2f8 100644
--- a/src/etc/testcases/taskdefs/optional/schemavalidate.xml
+++ b/src/etc/testcases/taskdefs/optional/schemavalidate.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/script.xml b/src/etc/testcases/taskdefs/optional/script.xml
index 841f70d..0cc08b2 100644
--- a/src/etc/testcases/taskdefs/optional/script.xml
+++ b/src/etc/testcases/taskdefs/optional/script.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -17,22 +17,22 @@
 -->
 <project name="testproject" default="def" basedir=".">
 
+  <import file="../../buildfiletest-base.xml"/>
+
   <target name="def">
     <fail>This build-file is intended to be run from the test cases</fail>
   </target>
 
   <target name="setup1">
-
-    <script language="javascript"> <![CDATA[
-
+    <script language="javascript">
+      <![CDATA[
       for (i=1; i<=10; i++) {
         echo = testproject.createTask("echo");
         setup1.addTask(echo);
         echo.setMessage(i*i);
       }
-
-    ]]> </script>
-
+      ]]>
+    </script>
   </target>
 
   <target name="example1" depends="setup1"/>
@@ -43,4 +43,22 @@
     ]]></script>
   </target>
 
+  <target name="useSrcAndEncoding">
+    <mkdir dir="${output}"/>
+    <property name="useSrcAndEncoding.encoding" value="UTF-8"/>
+    <property name="useSrcAndEncoding.reader.encoding" value="${useSrcAndEncoding.encoding}"
+              description="Set a different encoding to raise a failure (ex. ISO-8859-1)"/>
+    <property name="useSrcAndEncoding.file" location="${output}/script.useSrcAndEncoding.js"/>
+    <property name="useSrcAndEncoding.expectedProp" value="eacute [&#233;]"/>
+
+    <echo file="${useSrcAndEncoding.file}" encoding="${useSrcAndEncoding.encoding}"
+          message="project.setNewProperty('useSrcAndEncoding.prop', '${useSrcAndEncoding.expectedProp}');"/>
+
+    <script language="javascript" src="${useSrcAndEncoding.file}" encoding="${useSrcAndEncoding.reader.encoding}"/>
+    <condition property="useSrcAndEncoding.testOK" >
+      <equals arg1="${useSrcAndEncoding.expectedProp}" arg2="${useSrcAndEncoding.prop}"/>
+    </condition>
+    <fail message="expected &lt;${useSrcAndEncoding.expectedProp}&gt; but was &lt;${useSrcAndEncoding.prop}&gt;" unless="useSrcAndEncoding.testOK"/>
+  </target>
+
 </project>
\ No newline at end of file
diff --git a/src/etc/testcases/taskdefs/optional/script/graal.xml b/src/etc/testcases/taskdefs/optional/script/graal.xml
new file mode 100644
index 0000000..42a69c5
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/script/graal.xml
@@ -0,0 +1,28 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project name="squares">
+  <target name="run-squares-test">
+    <script language="javascript" manager="javax"> <![CDATA[
+      for (i = 1; i <= 10; i++) {
+        echo = squares.createTask("echo");
+        echo.setMessage(i*i);
+        echo.perform();
+      }
+    ]]> </script>
+  </target>
+</project>
diff --git a/src/etc/testcases/taskdefs/optional/script/heavy-script.js b/src/etc/testcases/taskdefs/optional/script/heavy-script.js
new file mode 100644
index 0000000..9f57639
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/script/heavy-script.js
@@ -0,0 +1,85 @@
+/*
+ *  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
+ *
+ *      https://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.
+ *
+ */
+
+var functions = [
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },function (value) { return value; },
+];
+
+var v = 'a';
+for (var i in functions) {
+  v = functions[i](v);
+}
+
+var echo = project.createTask("echo");
+echo.setMessage("heavy-script done");
+echo.perform();
diff --git a/src/etc/testcases/taskdefs/optional/script/scriptdef.xml b/src/etc/testcases/taskdefs/optional/script/scriptdef.xml
index 0d051ea..37829c5 100644
--- a/src/etc/testcases/taskdefs/optional/script/scriptdef.xml
+++ b/src/etc/testcases/taskdefs/optional/script/scriptdef.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -17,6 +17,8 @@
 -->
 <project name="testproject" default="def" basedir=".">
 
+  <import file="../../../buildfiletest-base.xml"/>
+
   <target name="def">
     <fail>This build-file is intended to be run from the test cases</fail>
   </target>
@@ -26,11 +28,9 @@
       <attribute name="attr1"/>
       <element name="fileset" type="fileset"/>
       <![CDATA[
-        
         project.log("Attribute attr1 = " + attributes.get("attr1"));
         project.log("Fileset basedir = "
           + elements.get("fileset").get(0).getDir(project));
-        
       ]]>
     </scriptdef>
     
@@ -61,11 +61,9 @@
       <attribute name="attr1"/>
       <element name="fileset" classname="org.apache.tools.ant.types.FileSet"/>
       <![CDATA[
-        
         project.log("Attribute attr1 = " + attributes.get("attr1"));
         project.log("Fileset basedir = "
           + elements.get("fileset").get(0).getDir(project));
-        
       ]]>
     </scriptdef>
     
@@ -93,11 +91,9 @@
       <attribute name="attr1"/>
       <element name="fileset" classname="org.apache.tools.ant.types.FileSet"/>
       <![CDATA[
-        
         java.lang.System.out.println("Attribute attr1 = " + attributes.get("attr1"));
         java.lang.System.out.println("Fileset basedir = "
           + elements.get("fileset").get(0).getDir(project));
-        
       ]]>
     </scriptdef>
     
@@ -131,7 +127,6 @@
     <scriptdef name="scripttest" language="javascript">
       <attribute name="attr1"/>
       <![CDATA[
-        
         project.log("Attribute value = " + attributes.get("attr1"));
       ]]>
     </scriptdef>
@@ -141,5 +136,81 @@
     </scripttest>
   </target>
 
+  <target name="useBeanshell">
+    <script language="beanshell"><![CDATA[
+       self.log("I'm here", org.apache.tools.ant.Project.MSG_INFO);
+    ]]></script>
+  </target>
+
+  <target name="useSrcAndEncoding">
+    <mkdir dir="${output}"/>
+    <property name="useSrcAndEncoding.encoding" value="UTF-8"/>
+    <property name="useSrcAndEncoding.reader.encoding" value="${useSrcAndEncoding.encoding}"
+              description="Set a different encoding to raise a failure (ex. ISO-8859-1)"/>
+    <property name="useSrcAndEncoding.file" location="${output}/script.useSrcAndEncoding.js"/>
+    <property name="useSrcAndEncoding.expectedProp" value="eacute [&#233;]"/>
+
+    <echo file="${useSrcAndEncoding.file}" encoding="${useSrcAndEncoding.encoding}"
+          message="project.setNewProperty('useSrcAndEncoding.prop', '${useSrcAndEncoding.expectedProp}');"/>
+
+    <scriptdef name="useSrcAndEncoding" language="javascript" src="${useSrcAndEncoding.file}" encoding="${useSrcAndEncoding.reader.encoding}"/>
+    <useSrcAndEncoding/>
+
+    <condition property="useSrcAndEncoding.testOK" >
+      <equals arg1="${useSrcAndEncoding.expectedProp}" arg2="${useSrcAndEncoding.prop}"/>
+    </condition>
+    <fail message="expected &lt;${useSrcAndEncoding.expectedProp}&gt; but was &lt;${useSrcAndEncoding.prop}&gt;" unless="useSrcAndEncoding.testOK"/>
+  </target>
+
+  <target name="useCompiled">
+    <!-- Test with 'javax' manager, 'bsf' manager already compiles the script. -->
+    <scriptdef manager="javax" name="heavyscript" language="javascript" src="heavy-script.js" encoding="UTF-8" compiled="true"/>
+
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+    <heavyscript/>
+  </target>
+
+  <target name="useNotCompiled">
+    <scriptdef manager="javax" name="heavyscriptNotCompiled" language="javascript" src="heavy-script.js" encoding="UTF-8" compiled="false"/>
+
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+    <heavyscriptNotCompiled/>
+  </target>
 
 </project>
diff --git a/src/etc/testcases/taskdefs/optional/script_reference.xml b/src/etc/testcases/taskdefs/optional/script_reference.xml
index 82ccb1f..0b75486 100644
--- a/src/etc/testcases/taskdefs/optional/script_reference.xml
+++ b/src/etc/testcases/taskdefs/optional/script_reference.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/sos/sos.xml b/src/etc/testcases/taskdefs/optional/sos/sos.xml
index 982b47c..7d54dc6 100644
--- a/src/etc/testcases/taskdefs/optional/sos/sos.xml
+++ b/src/etc/testcases/taskdefs/optional/sos/sos.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/splash-test.xml b/src/etc/testcases/taskdefs/optional/splash-test.xml
index 5b5bbe2..7c3f154 100644
--- a/src/etc/testcases/taskdefs/optional/splash-test.xml
+++ b/src/etc/testcases/taskdefs/optional/splash-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/unix/symlink.xml b/src/etc/testcases/taskdefs/optional/unix/symlink.xml
index f039a62..99c0bbb 100644
--- a/src/etc/testcases/taskdefs/optional/unix/symlink.xml
+++ b/src/etc/testcases/taskdefs/optional/unix/symlink.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -302,7 +302,7 @@
 
     <sleep seconds="${delay}"/>  <!-- make sure OS has time to do the execs -->
 
-    <symlink action="recreate">
+    <symlink action="recreate" overwrite="true">
       <fileset dir="${output}/symtest1" includes="**/recorded.links"/>
     </symlink>
 
@@ -350,5 +350,17 @@
       <delete file="${output}/file2"/>
   </target>
 
+  <target name="test-overwrite-link" depends="setUp">
+    <mkdir dir="${output}/test-overwrite"/>
+    <mkdir dir="${output}/test-overwrite/dir1"/>
+    <property name="test.overwrite.link.target.dir" location="${output}/test-overwrite/dir1"/>
+    <!-- Create a symlink to the dir, this should work fine -->
+    <symlink link="${output}/test-overwrite/symlinked1" resource="${test.overwrite.link.target.dir}"/>
+    <!-- Create a symlink at the previously created symlink path with overwrite = false.
+      This *shouldn't* create a new link (within the target resource). See https://bz.apache.org/bugzilla/show_bug.cgi?id=58683 -->
+    <symlink link="${output}/test-overwrite/symlinked1" resource="${test.overwrite.link.target.dir}"/>
+
+
+  </target>
 
 </project>
diff --git a/src/etc/testcases/taskdefs/optional/vss/vss.xml b/src/etc/testcases/taskdefs/optional/vss/vss.xml
index 7c6c0d3..bd07d2a 100644
--- a/src/etc/testcases/taskdefs/optional/vss/vss.xml
+++ b/src/etc/testcases/taskdefs/optional/vss/vss.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xalan-redirect-in.xsl b/src/etc/testcases/taskdefs/optional/xalan-redirect-in.xsl
index b9d0794..ef0be5f 100644
--- a/src/etc/testcases/taskdefs/optional/xalan-redirect-in.xsl
+++ b/src/etc/testcases/taskdefs/optional/xalan-redirect-in.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/about.xml b/src/etc/testcases/taskdefs/optional/xml/about.xml
index f6a9dab..762d6a4 100644
--- a/src/etc/testcases/taskdefs/optional/xml/about.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/about.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/apache.xsl b/src/etc/testcases/taskdefs/optional/xml/apache.xsl
index 120addf..872508a 100644
--- a/src/etc/testcases/taskdefs/optional/xml/apache.xsl
+++ b/src/etc/testcases/taskdefs/optional/xml/apache.xsl
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/books.xml b/src/etc/testcases/taskdefs/optional/xml/books.xml
index 17923d7..9bac394 100644
--- a/src/etc/testcases/taskdefs/optional/xml/books.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/books.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/doc-in-ns.xsd b/src/etc/testcases/taskdefs/optional/xml/doc-in-ns.xsd
index b34147c..72a91b1 100644
--- a/src/etc/testcases/taskdefs/optional/xml/doc-in-ns.xsd
+++ b/src/etc/testcases/taskdefs/optional/xml/doc-in-ns.xsd
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/doc.dtd b/src/etc/testcases/taskdefs/optional/xml/doc.dtd
index 51629d5..faeb2b6 100644
--- a/src/etc/testcases/taskdefs/optional/xml/doc.dtd
+++ b/src/etc/testcases/taskdefs/optional/xml/doc.dtd
@@ -6,7 +6,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/doc.xsd b/src/etc/testcases/taskdefs/optional/xml/doc.xsd
index eeedbca..3f55747 100644
--- a/src/etc/testcases/taskdefs/optional/xml/doc.xsd
+++ b/src/etc/testcases/taskdefs/optional/xml/doc.xsd
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/doc.xsl b/src/etc/testcases/taskdefs/optional/xml/doc.xsl
index 3d9c2a4..b09dea2 100644
--- a/src/etc/testcases/taskdefs/optional/xml/doc.xsl
+++ b/src/etc/testcases/taskdefs/optional/xml/doc.xsl
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/docwithentity.xml b/src/etc/testcases/taskdefs/optional/xml/docwithentity.xml
index 6435c32..3d186b3 100644
--- a/src/etc/testcases/taskdefs/optional/xml/docwithentity.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/docwithentity.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema-invalid.xml b/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema-invalid.xml
index ec58085..bcebe6e 100644
--- a/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema-invalid.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema-invalid.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema.xml b/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema.xml
index 7ae559d..3cb8094 100644
--- a/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/endpiece-noSchema.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/endpiece-ns-no-location.xml b/src/etc/testcases/taskdefs/optional/xml/endpiece-ns-no-location.xml
index 3fe93c7..73adc76 100644
--- a/src/etc/testcases/taskdefs/optional/xml/endpiece-ns-no-location.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/endpiece-ns-no-location.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/endpiece.xml b/src/etc/testcases/taskdefs/optional/xml/endpiece.xml
index 3fe93c7..73adc76 100644
--- a/src/etc/testcases/taskdefs/optional/xml/endpiece.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/endpiece.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/endpiece2.xml b/src/etc/testcases/taskdefs/optional/xml/endpiece2.xml
index eec49f6..626969a 100644
--- a/src/etc/testcases/taskdefs/optional/xml/endpiece2.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/endpiece2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/entity.xml b/src/etc/testcases/taskdefs/optional/xml/entity.xml
index a9340e5..60135ed 100644
--- a/src/etc/testcases/taskdefs/optional/xml/entity.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/entity.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/iso-2022-jp.xml b/src/etc/testcases/taskdefs/optional/xml/iso-2022-jp.xml
index b325e6d..2cdd6bf 100644
--- a/src/etc/testcases/taskdefs/optional/xml/iso-2022-jp.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/iso-2022-jp.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/stylesheet_include.xsl b/src/etc/testcases/taskdefs/optional/xml/stylesheet_include.xsl
index 9c1ffad..0ac3b0f 100644
--- a/src/etc/testcases/taskdefs/optional/xml/stylesheet_include.xsl
+++ b/src/etc/testcases/taskdefs/optional/xml/stylesheet_include.xsl
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/stylesheet_with_include.xsl b/src/etc/testcases/taskdefs/optional/xml/stylesheet_with_include.xsl
index b1feaca..daf234c 100644
--- a/src/etc/testcases/taskdefs/optional/xml/stylesheet_with_include.xsl
+++ b/src/etc/testcases/taskdefs/optional/xml/stylesheet_with_include.xsl
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/test.xml b/src/etc/testcases/taskdefs/optional/xml/test.xml
index 7f2abe0..0d35b1c 100644
--- a/src/etc/testcases/taskdefs/optional/xml/test.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/test.xsl b/src/etc/testcases/taskdefs/optional/xml/test.xsl
index 8d28eb3..9e34f80 100644
--- a/src/etc/testcases/taskdefs/optional/xml/test.xsl
+++ b/src/etc/testcases/taskdefs/optional/xml/test.xsl
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/utf-8.xml b/src/etc/testcases/taskdefs/optional/xml/utf-8.xml
index db442a3..6e60f0d 100644
--- a/src/etc/testcases/taskdefs/optional/xml/utf-8.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/utf-8.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xml/validate.xml b/src/etc/testcases/taskdefs/optional/xml/validate.xml
index cade722..2a046d6 100644
--- a/src/etc/testcases/taskdefs/optional/xml/validate.xml
+++ b/src/etc/testcases/taskdefs/optional/xml/validate.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xmlvalidate.xml b/src/etc/testcases/taskdefs/optional/xmlvalidate.xml
index cd7cc45..b3df835 100644
--- a/src/etc/testcases/taskdefs/optional/xmlvalidate.xml
+++ b/src/etc/testcases/taskdefs/optional/xmlvalidate.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xslt.xml b/src/etc/testcases/taskdefs/optional/xslt.xml
index d872ea8..89be7fd 100644
--- a/src/etc/testcases/taskdefs/optional/xslt.xml
+++ b/src/etc/testcases/taskdefs/optional/xslt.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xml b/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xml
index 80d9336..f3c4b61 100644
--- a/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xml
+++ b/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xsl b/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xsl
index f19bf82..0e90347 100644
--- a/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xsl
+++ b/src/etc/testcases/taskdefs/optional/xsltliaison-encoding-in.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xsltliaison-in.xml b/src/etc/testcases/taskdefs/optional/xsltliaison-in.xml
index a4b0247..e64cfd1 100644
--- a/src/etc/testcases/taskdefs/optional/xsltliaison-in.xml
+++ b/src/etc/testcases/taskdefs/optional/xsltliaison-in.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xsltliaison-in.xsl b/src/etc/testcases/taskdefs/optional/xsltliaison-in.xsl
index 852d38a..b8c11d8 100644
--- a/src/etc/testcases/taskdefs/optional/xsltliaison-in.xsl
+++ b/src/etc/testcases/taskdefs/optional/xsltliaison-in.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xsltliaison-include.xml b/src/etc/testcases/taskdefs/optional/xsltliaison-include.xml
index aebef33..99d08b0 100644
--- a/src/etc/testcases/taskdefs/optional/xsltliaison-include.xml
+++ b/src/etc/testcases/taskdefs/optional/xsltliaison-include.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/optional/xsltliaison-include.xsl b/src/etc/testcases/taskdefs/optional/xsltliaison-include.xsl
index 986f1b3..953c56c 100644
--- a/src/etc/testcases/taskdefs/optional/xsltliaison-include.xsl
+++ b/src/etc/testcases/taskdefs/optional/xsltliaison-include.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/parallel.xml b/src/etc/testcases/taskdefs/parallel.xml
index 9a3434c..31565bd 100644
--- a/src/etc/testcases/taskdefs/parallel.xml
+++ b/src/etc/testcases/taskdefs/parallel.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/pathconvert.xml b/src/etc/testcases/taskdefs/pathconvert.xml
deleted file mode 100644
index 5a1cdf7..0000000
--- a/src/etc/testcases/taskdefs/pathconvert.xml
+++ /dev/null
@@ -1,60 +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 name="pathconvert">
-
-    <import file="../buildfiletest-base.xml"/>
-
-    <path id="testpath">
-        <pathelement path="${ant.file}" />
-    </path>
-
-    <target name="testmap">
-        <pathconvert property="result" dirsep="#">
-            <path refid="testpath" />
-            <map from="${basedir}" to="test" />
-        </pathconvert>
-    </target>
-
-    <target name="testmapper">
-        <pathconvert property="result" dirsep="#">
-            <path refid="testpath" />
-            <mapper type="glob" from="${basedir}*" to="test*" />
-        </pathconvert>
-    </target>
-
-    <target name="testnotargetos">
-        <pathconvert property="result" refid="testpath" />
-    </target>
-
-    <target name="test-nonmatching-mapper" description="test for bug fix bz-62076">
-        <mkdir dir="${output}/mapper-source-dir"/>
-        <!-- create 2 files, one of which will be matched/included by the globmapper
-        later in this target -->
-        <touch file="${output}/mapper-source-dir/file1.txt"/>
-        <touch file="${output}/mapper-source-dir/file2.log"/>
-
-        <pathconvert property="pc">
-            <mappedresources>
-                <fileset dir="${output}/mapper-source-dir"/>
-                <!-- we intentionally exclude one of the files -->
-                <globmapper from="*.log" to="*.txt"/>
-            </mappedresources>
-        </pathconvert>
-    </target>
-
-</project>
diff --git a/src/etc/testcases/taskdefs/presetdef.xml b/src/etc/testcases/taskdefs/presetdef.xml
index 695747e..b247660 100644
--- a/src/etc/testcases/taskdefs/presetdef.xml
+++ b/src/etc/testcases/taskdefs/presetdef.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -17,8 +17,7 @@
 -->
 <project>
   <path id="test-classes">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
   
   <target name="simple">
@@ -119,7 +118,7 @@
 
   <target name="correct_taskname_badattr">
     <presetdef name="mytask">
-       <javac srcdir="whatever"/>
+      <javac srcdir="whatever"/>
     </presetdef>
 
     <javac srcdir="whatever" badattr="whatever"/>
@@ -127,7 +126,7 @@
 
   <target name="correct_taskname_badel">
     <presetdef name="mytask">
-       <javac srcdir="whatever"/>
+      <javac srcdir="whatever"/>
     </presetdef>
 
     <javac srcdir="whatever">
@@ -135,13 +134,12 @@
     </javac>
   </target>
 
-    <target name="presetdef-with-nested-element-twice">
-        <copy todir=".">
-            <fileset dir="." includes="nonexistent"/>
-        </copy>
-        <presetdef name="copy">
-            <copy verbose="true"/>
-        </presetdef>
-    </target>
-
+  <target name="presetdef-with-nested-element-twice">
+    <copy todir=".">
+      <fileset dir="." includes="nonexistent"/>
+    </copy>
+    <presetdef name="copy">
+      <copy verbose="true"/>
+    </presetdef>
+  </target>
 </project>
diff --git a/src/etc/testcases/taskdefs/property.xml b/src/etc/testcases/taskdefs/property.xml
index 2e0c835..47db2ab 100644
--- a/src/etc/testcases/taskdefs/property.xml
+++ b/src/etc/testcases/taskdefs/property.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/property1.properties b/src/etc/testcases/taskdefs/property1.properties
index ef3ebd3..1c68a9d 100644
--- a/src/etc/testcases/taskdefs/property1.properties
+++ b/src/etc/testcases/taskdefs/property1.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/property2.properties b/src/etc/testcases/taskdefs/property2.properties
index 8125312..ac5b976 100644
--- a/src/etc/testcases/taskdefs/property2.properties
+++ b/src/etc/testcases/taskdefs/property2.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/property3.properties b/src/etc/testcases/taskdefs/property3.properties
index ac21612..4807a46 100644
--- a/src/etc/testcases/taskdefs/property3.properties
+++ b/src/etc/testcases/taskdefs/property3.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/property4.properties b/src/etc/testcases/taskdefs/property4.properties
index 6552710..fee520d 100644
--- a/src/etc/testcases/taskdefs/property4.properties
+++ b/src/etc/testcases/taskdefs/property4.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/property5.properties b/src/etc/testcases/taskdefs/property5.properties
index e1ebcd3..5f5e93d 100644
--- a/src/etc/testcases/taskdefs/property5.properties
+++ b/src/etc/testcases/taskdefs/property5.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/recorder.xml b/src/etc/testcases/taskdefs/recorder.xml
index 1c07311..c005aab 100644
--- a/src/etc/testcases/taskdefs/recorder.xml
+++ b/src/etc/testcases/taskdefs/recorder.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/recorder2.xml b/src/etc/testcases/taskdefs/recorder2.xml
index e093cf5..2262d39 100644
--- a/src/etc/testcases/taskdefs/recorder2.xml
+++ b/src/etc/testcases/taskdefs/recorder2.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/rename.xml b/src/etc/testcases/taskdefs/rename.xml
index a23a81e..b07ce71 100644
--- a/src/etc/testcases/taskdefs/rename.xml
+++ b/src/etc/testcases/taskdefs/rename.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/replace.xml b/src/etc/testcases/taskdefs/replace.xml
index a4039e5..bb11994 100644
--- a/src/etc/testcases/taskdefs/replace.xml
+++ b/src/etc/testcases/taskdefs/replace.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/rmic/rmic.xml b/src/etc/testcases/taskdefs/rmic/rmic.xml
index fe9973e..04b3f4d 100644
--- a/src/etc/testcases/taskdefs/rmic/rmic.xml
+++ b/src/etc/testcases/taskdefs/rmic/rmic.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -217,12 +217,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>
     <condition property="java15+">
       <javaversion atleast="15"/>
     </condition>
@@ -443,23 +437,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/taskdefs/rmic/src/AntTimestamp.java b/src/etc/testcases/taskdefs/rmic/src/AntTimestamp.java
index 579d2ed..5d25b3e 100644
--- a/src/etc/testcases/taskdefs/rmic/src/AntTimestamp.java
+++ b/src/etc/testcases/taskdefs/rmic/src/AntTimestamp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -14,29 +14,25 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-import java.rmi.Remote;
 import java.rmi.RemoteException;
 import java.util.Calendar;
 
-import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.DateUtils;
 
-
 /**
  * This class imports a dependency on the Ant runtime classes,
  * so tests that classpath setup include them
  */
 public class AntTimestamp implements RemoteTimestamp {
 
-
     /**
      * return the phase of the moon.
      * Note the completely different semantics of the other implementation,
      * which goes to show why signature is an inadequate way of verifying
      * how well an interface is implemented.
      *
-     * @return
-     * @throws RemoteException
+     * @return the phase of the moon
+     * @throws RemoteException hopefully never
      */
     public long when() throws RemoteException {
         Calendar cal = Calendar.getInstance();
diff --git a/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java
index 5c9afc8..018126d 100644
--- a/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java
+++ b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java
index f361452..3a8de93 100644
--- a/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java
+++ b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-import java.rmi.Remote;
 import java.rmi.RemoteException;
 
 /**
diff --git a/src/etc/testcases/taskdefs/signjar.xml b/src/etc/testcases/taskdefs/signjar.xml
index 38a1359..7d0ab25 100644
--- a/src/etc/testcases/taskdefs/signjar.xml
+++ b/src/etc/testcases/taskdefs/signjar.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -20,42 +20,38 @@
   <import file="../buildfiletest-base.xml"/>
 
   <target name="setUp">
-    <mkdir dir="${output}" />
-    <property name="subdir" location="${output}/subdir" />
-    <property name="classes.dir" value="../../../build/classes"/>
-    <property name="test.jar" location="${output}/signtest.jar" />
-    <property name="subdirtest.jar" location="${subdir}/signtest.jar" />
-
+    <mkdir dir="${output}"/>
+    <property name="subdir" location="${output}/subdir"/>
+    <property name="test.jar" location="${output}/signtest.jar"/>
+    <property name="subdirtest.jar" location="${subdir}/signtest.jar"/>
   </target>
 
 
   <macrodef name="assertSigned">
-    <attribute name="jar" default="${test.jar}" />
+    <attribute name="jar" default="${test.jar}"/>
     <sequential>
-      <fail message="not signed: @{jar}" >
+      <fail message="not signed: @{jar}">
         <condition>
-          <not><issigned file="@{jar}" /></not>
+          <not><issigned file="@{jar}"/></not>
         </condition>
       </fail>
     </sequential>
   </macrodef>
 
   <presetdef name="sign-base">
-    <signjar alias="testonly" keystore="testkeystore"
-           storepass="apacheant"/>
+    <signjar alias="testonly" keystore="testkeystore" storepass="apacheant"/>
   </presetdef>
 
   <presetdef name="verify-base">
-    <verifyjar keystore="testkeystore"
-           storepass="apacheant"/>
+    <verifyjar keystore="testkeystore" storepass="apacheant"/>
   </presetdef>
 
   <presetdef name="sign">
-    <sign-base jar="${test.jar}" />
+    <sign-base jar="${test.jar}"/>
   </presetdef>
 
   <target name="jar" depends="setUp">
-    <jar jarfile="${test.jar}" basedir="${classes.dir}" includes="**/Task.class"/>
+    <jar jarfile="${test.jar}" basedir="${build.classes.value}" includes="**/Task.class"/>
   </target>
 
   <target name="help">
@@ -63,7 +59,7 @@
   </target>
 
   <target name="basic" depends="jar">
-    <sign />
+    <sign/>
     <assertSigned/>
   </target>
 
@@ -84,14 +80,12 @@
   </target>
 
   <target name="urlKeystoreHTTP" depends="jar">
-    <sign
-      keystore="http://ant.apache.org/webtest/testkeystore"
-      />
+    <sign keystore="https://ant.apache.org/webtest/testkeystore"/>
     <assertSigned/>
   </target>
 
   <target name="testTsaLocalhost" depends="jar">
-    <sign tsaurl="http://localhost:0/" />
+    <sign tsaurl="http://localhost:0/"/>
   </target>
 
 </project>
diff --git a/src/etc/testcases/taskdefs/skinconfig.dtd b/src/etc/testcases/taskdefs/skinconfig.dtd
index ba1b4de..4d3e636 100644
--- a/src/etc/testcases/taskdefs/skinconfig.dtd
+++ b/src/etc/testcases/taskdefs/skinconfig.dtd
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/sleep.xml b/src/etc/testcases/taskdefs/sleep.xml
index e161322..6278918 100644
--- a/src/etc/testcases/taskdefs/sleep.xml
+++ b/src/etc/testcases/taskdefs/sleep.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/style/build.xml b/src/etc/testcases/taskdefs/style/build.xml
index c91d10f..42ad93d 100644
--- a/src/etc/testcases/taskdefs/style/build.xml
+++ b/src/etc/testcases/taskdefs/style/build.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/style/data.xml b/src/etc/testcases/taskdefs/style/data.xml
index 21e2397..405ae7e 100644
--- a/src/etc/testcases/taskdefs/style/data.xml
+++ b/src/etc/testcases/taskdefs/style/data.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/style/printFilename.xsl b/src/etc/testcases/taskdefs/style/printFilename.xsl
index eb2cbc7..680eac5 100644
--- a/src/etc/testcases/taskdefs/style/printFilename.xsl
+++ b/src/etc/testcases/taskdefs/style/printFilename.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/style/printParams.xsl b/src/etc/testcases/taskdefs/style/printParams.xsl
index 110e49c..2eaa0e6 100644
--- a/src/etc/testcases/taskdefs/style/printParams.xsl
+++ b/src/etc/testcases/taskdefs/style/printParams.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/style/testNewerStylesheet.xsl b/src/etc/testcases/taskdefs/style/testNewerStylesheet.xsl
index dff8120..c0475f5 100644
--- a/src/etc/testcases/taskdefs/style/testNewerStylesheet.xsl
+++ b/src/etc/testcases/taskdefs/style/testNewerStylesheet.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/taskdefs/subant.xml b/src/etc/testcases/taskdefs/subant.xml
index 7db547a..5f504c3 100644
--- a/src/etc/testcases/taskdefs/subant.xml
+++ b/src/etc/testcases/taskdefs/subant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/subant/genericsubant.xml b/src/etc/testcases/taskdefs/subant/genericsubant.xml
index c5bfbe2..2abe9bd 100644
--- a/src/etc/testcases/taskdefs/subant/genericsubant.xml
+++ b/src/etc/testcases/taskdefs/subant/genericsubant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml b/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml
index ecc6288..3209091 100644
--- a/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml
+++ b/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml b/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml
index 5ee875f..fe75e8f 100644
--- a/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml
+++ b/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/sync.xml b/src/etc/testcases/taskdefs/sync.xml
index d2eb126..445ba83 100644
--- a/src/etc/testcases/taskdefs/sync.xml
+++ b/src/etc/testcases/taskdefs/sync.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -138,4 +138,23 @@
     </sync>
   </target>
 
+  <target name="casesensitivity-test" depends="setUp" description="Tests the bug fix for bz-62890">
+    <mkdir dir="${src}/casecheck"/>
+    <mkdir dir="${dest}/casecheck"/>
+    <!-- lower case file in source dir -->
+    <touch file="${src}/casecheck/a.txt"/>
+    <!-- upper case file in dest dir -->
+    <touch file="${dest}/casecheck/A.txt"/>
+    <!-- some random file in source dir -->
+    <touch file="${src}/casecheck/foo.txt"/>
+    <!-- some random file in dest dir -->
+    <touch file="${dest}/casecheck/bar.txt"/>
+
+    <sync todir="${dest}/casecheck"
+          includeEmptyDirs="true"
+          overwrite="false">
+      <fileset dir="${src}/casecheck"/>
+    </sync>
+  </target>
+
 </project>
\ No newline at end of file
diff --git a/src/etc/testcases/taskdefs/tar.xml b/src/etc/testcases/taskdefs/tar.xml
index e76b7ad..08ac2f7 100644
--- a/src/etc/testcases/taskdefs/tar.xml
+++ b/src/etc/testcases/taskdefs/tar.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -172,6 +172,12 @@
     <untar src="${output}/test11.tar.bz2" dest="${output}/untar" compression="bzip2"/>
   </target>
 
+  <target name="testTarFilesetWithReference">
+    <fileset id="xml.fileset" dir="." includes="*.xml"/>
+    <tar destfile="${output}/testtar.tar">
+      <tarfileset prefix="pre" refid="xml.fileset"/>
+    </tar>
+  </target>
 
   <target name="feather">
     <tar destfile="${output}/asf-logo.gif.tar"
diff --git a/src/etc/testcases/taskdefs/taskdef.xml b/src/etc/testcases/taskdefs/taskdef.xml
index 4b0658e..f17b0be 100644
--- a/src/etc/testcases/taskdefs/taskdef.xml
+++ b/src/etc/testcases/taskdefs/taskdef.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -19,13 +19,11 @@
 <project name="xxx-test" basedir="." default="test1">
 
   <path id="testclasses">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
-  <taskdef name="global"
-           classname="org.example.tasks.TaskdefTestContainerTask">
-    <classpath refid="testclasses" />
+  <taskdef name="global" classname="org.example.tasks.TaskdefTestContainerTask">
+    <classpath refid="testclasses"/>
   </taskdef>
 
   <target name="test1">
@@ -45,41 +43,39 @@
   </target>
 
   <target name="test5">
-    <taskdef name="test" classname="org.apache.tools.ant.Project" />
+    <taskdef name="test" classname="org.apache.tools.ant.Project"/>
   </target>
 
   <target name="test5a">
-    <taskdef name="test" classname="org.apache.tools.ant.taskdefs.Copy" />
+    <taskdef name="test" classname="org.apache.tools.ant.taskdefs.Copy"/>
   </target>
 
   <target name="test6">
-    <taskdef name="test6"
-             classname="org.example.tasks.TaskdefTestSimpleTask">
-      <classpath refid="testclasses" />
+    <taskdef name="test6" classname="org.example.tasks.TaskdefTestSimpleTask">
+      <classpath refid="testclasses"/>
     </taskdef>
     <test6>
-      <echo message="worked" />
+      <echo message="worked"/>
     </test6>
   </target>
 
   <target name="test7">
-    <taskdef name="test7"
-             classname="org.example.tasks.TaskdefTestContainerTask">
-      <classpath refid="testclasses" />
+    <taskdef name="test7" classname="org.example.tasks.TaskdefTestContainerTask">
+      <classpath refid="testclasses"/>
     </taskdef>
     <test7>
-      <echo message="worked" />
+      <echo message="worked"/>
     </test7>
   </target>
 
   <target name="testGlobal">
     <global>
-      <echo message="worked" />
+      <echo message="worked"/>
     </global>
   </target>
 
   <target name="testOverride">
-    <taskdef name="copy" classname="org.apache.tools.ant.taskdefs.Echo" />
+    <taskdef name="copy" classname="org.apache.tools.ant.taskdefs.Echo"/>
     <copy>In target</copy>
     <sequential>
       <copy>In TaskContainer</copy>
diff --git a/src/etc/testcases/taskdefs/template.xml b/src/etc/testcases/taskdefs/template.xml
index 9f351c7..2a0a372 100644
--- a/src/etc/testcases/taskdefs/template.xml
+++ b/src/etc/testcases/taskdefs/template.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/test.antlib.xml b/src/etc/testcases/taskdefs/test.antlib.xml
index 37ff7f8..21d205c 100644
--- a/src/etc/testcases/taskdefs/test.antlib.xml
+++ b/src/etc/testcases/taskdefs/test.antlib.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/test2.antlib.xml b/src/etc/testcases/taskdefs/test2.antlib.xml
index 9a2509e..ed2e829 100644
--- a/src/etc/testcases/taskdefs/test2.antlib.xml
+++ b/src/etc/testcases/taskdefs/test2.antlib.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/toplevelant.xml b/src/etc/testcases/taskdefs/toplevelant.xml
index e6b466a..12889bb 100644
--- a/src/etc/testcases/taskdefs/toplevelant.xml
+++ b/src/etc/testcases/taskdefs/toplevelant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/toplevelantcall.xml b/src/etc/testcases/taskdefs/toplevelantcall.xml
index 2ccabe7..fdbe77b 100644
--- a/src/etc/testcases/taskdefs/toplevelantcall.xml
+++ b/src/etc/testcases/taskdefs/toplevelantcall.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/toplevelsubant.xml b/src/etc/testcases/taskdefs/toplevelsubant.xml
index b7a3a35..efde71a 100644
--- a/src/etc/testcases/taskdefs/toplevelsubant.xml
+++ b/src/etc/testcases/taskdefs/toplevelsubant.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/touch.xml b/src/etc/testcases/taskdefs/touch.xml
index 3b426d9..750311d 100644
--- a/src/etc/testcases/taskdefs/touch.xml
+++ b/src/etc/testcases/taskdefs/touch.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -45,8 +45,8 @@
     <!-- this one is about 21 years after the epoch -->
     <!-- less than 20 years after the epoch, test does not pass on my Win2K/FAT -->
     <!-- Antoine February 8, 2004 -->
-    <!-- see http://developer.java.sun.com/developer/bugParade/bugs/4177432.html -->
-    <!-- and http://developer.java.sun.com/developer/bugParade/bugs/4697792.html -->
+    <!-- see https://bugs.openjdk.java.net/browse/JDK-4177432 -->
+    <!-- and https://bugs.openjdk.java.net/browse/JDK-4697792 -->
     <!-- not sure why -->
     <touch file="touchtest" millis="662256000000" />
   </target>
diff --git a/src/etc/testcases/taskdefs/typeadapter.xml b/src/etc/testcases/taskdefs/typeadapter.xml
index c2aa70e..b3816f6 100644
--- a/src/etc/testcases/taskdefs/typeadapter.xml
+++ b/src/etc/testcases/taskdefs/typeadapter.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -17,10 +17,8 @@
 -->
 
 <project name="test" basedir="." default="invalid">
-  <property name="testcases.dir" location="../../../../build/testcases"/>
   <path id="testclasses">
-    <pathelement location="${testcases.dir}" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="taskadapter">
@@ -74,6 +72,5 @@
       onerror="ignore"/>
   </target>
 
-
 </project>
 
diff --git a/src/etc/testcases/taskdefs/typedef.xml b/src/etc/testcases/taskdefs/typedef.xml
index 1c7922b..4325f43 100644
--- a/src/etc/testcases/taskdefs/typedef.xml
+++ b/src/etc/testcases/taskdefs/typedef.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -23,16 +23,16 @@
   </target>
 
   <target name="empty">
-    <typedef />
+    <typedef/>
   </target>
 
   <target name="noClassname">
-    <typedef name="dummy" />
+    <typedef name="dummy"/>
   </target>
 
   <target name="noName">
     <typedef classname="org.example.types.TypedefTestType">
-      <classpath refid="testclasses" />
+      <classpath refid="testclasses"/>
     </typedef>
   </target>
 
@@ -41,25 +41,24 @@
   </target>
 
   <path id="testclasses">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <typedef name="global"
            classname="org.example.types.TypedefTestType">
-    <classpath refid="testclasses" />
+    <classpath refid="testclasses"/>
   </typedef>
 
   <target name="testGlobal">
-    <global id="global" />
+    <global id="global"/>
   </target>
 
   <target name="testLocal">
     <typedef name="localtype"
              classname="org.example.types.TypedefTestType">
-      <classpath refid="testclasses" />
+      <classpath refid="testclasses"/>
     </typedef>
-    <localtype id="local" />
+    <localtype id="local"/>
   </target>
 
   <target name="double-notpresent">
@@ -79,6 +78,7 @@
   </target>
   
   <target name="noresourcenotfail">
-  	<typedef resource="somenotpresentfile.properties" />
+  	<typedef resource="somenotpresentfile.properties"/>
   </target>
+
 </project>
diff --git a/src/etc/testcases/taskdefs/untar.xml b/src/etc/testcases/taskdefs/untar.xml
index 04d44b3..a443e12 100644
--- a/src/etc/testcases/taskdefs/untar.xml
+++ b/src/etc/testcases/taskdefs/untar.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/unzip.xml b/src/etc/testcases/taskdefs/unzip.xml
index ee96ee1..633fc7c 100644
--- a/src/etc/testcases/taskdefs/unzip.xml
+++ b/src/etc/testcases/taskdefs/unzip.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/uptodate.xml b/src/etc/testcases/taskdefs/uptodate.xml
index 04bb370..05221ca 100644
--- a/src/etc/testcases/taskdefs/uptodate.xml
+++ b/src/etc/testcases/taskdefs/uptodate.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/war.xml b/src/etc/testcases/taskdefs/war.xml
index b000ecf..ec46764 100644
--- a/src/etc/testcases/taskdefs/war.xml
+++ b/src/etc/testcases/taskdefs/war.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/whichresource.xml b/src/etc/testcases/taskdefs/whichresource.xml
index 352e9c0..6737759 100644
--- a/src/etc/testcases/taskdefs/whichresource.xml
+++ b/src/etc/testcases/taskdefs/whichresource.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlns.xml b/src/etc/testcases/taskdefs/xmlns.xml
index e699166..0be07cc 100644
--- a/src/etc/testcases/taskdefs/xmlns.xml
+++ b/src/etc/testcases/taskdefs/xmlns.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -18,18 +18,15 @@
 <project name="test" xmlns:other="this is the other uri"
          other:attr="this should be ignored by ant">
 
-  <property name="testcases.dir" location="../../../../build/testcases"/>
-
   <path id="testclasses">
-    <pathelement location="${testcases.dir}" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="xmlns" xmlns:test="this.is.another.test.uri">
     <typedef classname="org.apache.tools.ant.taskdefs.XmlnsTest$MyTask"
              classpathref="testclasses"
              name="mytask"
-             uri="this.is.another.test.uri" />
+             uri="this.is.another.test.uri"/>
     <test:mytask/>
   </target>
 
@@ -46,22 +43,20 @@
   <target name="xmlns.file" xmlns:test="this.is.a.test.uri">
     <typedef file="test.antlib.xml"
              classpathref="testclasses"
-             uri="this.is.a.test.uri" />
+             uri="this.is.a.test.uri"/>
     <test:mytask/>
   </target>
 
   <target name="core">
     <typedef file="test.antlib.xml"
              classpathref="testclasses"
-             uri="antlib:org.apache.tools.ant" />
+             uri="antlib:org.apache.tools.ant"/>
     <mytask/>
   </target>
 
   <target name="excluded">
     <typedef file="test.antlib.xml"
              classpathref="testclasses"
-             uri="ant:notallowed" />
+             uri="ant:notallowed"/>
   </target>
-
-
-</project>
\ No newline at end of file
+</project>
diff --git a/src/etc/testcases/taskdefs/xmlproperty.xml b/src/etc/testcases/taskdefs/xmlproperty.xml
index a19eb6c..0195229 100644
--- a/src/etc/testcases/taskdefs/xmlproperty.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-input1.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-input1.properties
index d60cbab..dc19f5c 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-input1.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-input1.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-original.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-original.properties
index ce05e18..d127783 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-original.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-original.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-override.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-override.properties
index 33f8611..ac16a43 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-override.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-collapse-override.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-nocollapse-original.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-nocollapse-original.properties
index 47e0c2d..2b3daf4 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-nocollapse-original.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-nocollapse-original.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-include.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-include.properties
index d60cbab..dc19f5c 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-include.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-include.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-input1.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-input1.properties
index 46b807b..5b139e6 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-input1.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-input1.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-override.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-override.properties
index 33f8611..ac16a43 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-override.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/keeproot-semantic-override.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-input1.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-input1.properties
index 7cfd29e..f3a2b56 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-input1.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-input1.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-original.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-original.properties
index 5842c38..099e9b2 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-original.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-collapse-original.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-multi.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-multi.properties
index 9ef90ef..d31702d 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-multi.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-multi.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-original.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-original.properties
index 550f213..421ee76 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-original.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-nocollapse-original.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-include-input1.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-include-input1.properties
index 7cfd29e..f3a2b56 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-include-input1.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-include-input1.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-input1.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-input1.properties
index 5dfcfb5..67acd60 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-input1.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-input1.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-locations.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-locations.properties
index f945d7c..9abc46f 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-locations.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-locations.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-paths.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-paths.properties
index 1bf51de..ba0f920 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-paths.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-paths.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-references.properties b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-references.properties
index e55913a..5d52a49 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-references.properties
+++ b/src/etc/testcases/taskdefs/xmlproperty/goldfiles/nokeeproot-semantic-references.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/input1.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/input1.xml
index 28328c5..eeab58f 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/input1.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/input1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/locations.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/locations.xml
index d5cace8..e114fc7 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/locations.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/locations.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/multi.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/multi.xml
index 66904d6..663f0db 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/multi.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/multi.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/original.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/original.xml
index ef2603c..a535b65 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/original.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/original.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/override.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/override.xml
index c7da9c4..d3ca467 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/override.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/override.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/paths.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/paths.xml
index 83422d9..36ff19b 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/paths.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/paths.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty/inputs/references.xml b/src/etc/testcases/taskdefs/xmlproperty/inputs/references.xml
index 7e88b7b..21e2d98 100644
--- a/src/etc/testcases/taskdefs/xmlproperty/inputs/references.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty/inputs/references.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty_data.dtd b/src/etc/testcases/taskdefs/xmlproperty_data.dtd
index 5d75d6e..41f7265 100644
--- a/src/etc/testcases/taskdefs/xmlproperty_data.dtd
+++ b/src/etc/testcases/taskdefs/xmlproperty_data.dtd
@@ -6,7 +6,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty_data.xml b/src/etc/testcases/taskdefs/xmlproperty_data.xml
index 5f92221..67a721b 100644
--- a/src/etc/testcases/taskdefs/xmlproperty_data.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty_data.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty_needscat.xml b/src/etc/testcases/taskdefs/xmlproperty_needscat.xml
index 942a183..775d9f2 100644
--- a/src/etc/testcases/taskdefs/xmlproperty_needscat.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty_needscat.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/xmlproperty_withdtd.xml b/src/etc/testcases/taskdefs/xmlproperty_withdtd.xml
index 1e96cdb..4af97b6 100644
--- a/src/etc/testcases/taskdefs/xmlproperty_withdtd.xml
+++ b/src/etc/testcases/taskdefs/xmlproperty_withdtd.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/taskdefs/zip.xml b/src/etc/testcases/taskdefs/zip.xml
index 61a54a3..1c03eb8 100644
--- a/src/etc/testcases/taskdefs/zip.xml
+++ b/src/etc/testcases/taskdefs/zip.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/addtype.xml b/src/etc/testcases/types/addtype.xml
index cc8ff24..cd49678 100644
--- a/src/etc/testcases/types/addtype.xml
+++ b/src/etc/testcases/types/addtype.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -57,38 +57,37 @@
   <target name="init">
     <property name="nested.package" value="org.apache.tools.ant.types."/>
     <path id="test-classes">
-      <pathelement location="../../../../build/testcases" />
-      <pathelement path="${java.class.path}" />
+      <pathelement path="${java.class.path}"/>
     </path>
     <typedef loaderref="nested.loader" classpathref="test-classes"
-             name = "nested.a"
+             name="nested.a"
              classname="${nested.package}AddTypeTest$AImpl"/>
     <typedef loaderref="nested.loader"
-             name = "nested.b"
+             name="nested.b"
              classname="${nested.package}AddTypeTest$BImpl"/>
     <typedef loaderref="nested.loader"
-             name = "nested.c"
+             name="nested.c"
              classname="${nested.package}AddTypeTest$CImpl"/>
     <typedef loaderref="nested.loader"
-             name = "nested.ab"
+             name="nested.ab"
              classname="${nested.package}AddTypeTest$ABImpl"/>
     <taskdef loaderref="nested.loader"
-             name = "nested.container" 
+             name="nested.container"
              classname="${nested.package}AddTypeTest$NestedContainer"/>
     <taskdef loaderref="nested.loader"
-             name = "nested.condition.task" 
+             name="nested.condition.task"
              classname="${nested.package}AddTypeTest$MyCondition"/>
     <typedef loaderref="nested.loader"
-             name = "nested.condition.type" 
+             name="nested.condition.type"
              classname="${nested.package}AddTypeTest$MyCondition"/>
     <typedef loaderref="nested.loader"
-             name = "myaddconfigured" 
+             name="myaddconfigured"
              classname="${nested.package}AddTypeTest$MyAddConfigured"/>
     <typedef loaderref="nested.loader"
-             name = "myaddconfiguredvalue" 
+             name="myaddconfiguredvalue"
              classname="${nested.package}AddTypeTest$MyAddConfiguredValue"/>
     <typedef loaderref="nested.loader"
-             name = "myvalue" 
+             name="myvalue"
              classname="${nested.package}AddTypeTest$MyValue"/>
   </target>
 
@@ -160,4 +159,5 @@
       <prefix:eq arg1="a" arg2="b"/>
     </condition>
   </target>
+
 </project>
diff --git a/src/etc/testcases/types/assertions.xml b/src/etc/testcases/types/assertions.xml
index dee7ce7..8b1e6bc 100644
--- a/src/etc/testcases/types/assertions.xml
+++ b/src/etc/testcases/types/assertions.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/etc/testcases/types/assertions/AssertionMain.java b/src/etc/testcases/types/assertions/AssertionMain.java
index bc8853b..ef2b277 100644
--- a/src/etc/testcases/types/assertions/AssertionMain.java
+++ b/src/etc/testcases/types/assertions/AssertionMain.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/testcases/types/assertions/AssertionTest.java b/src/etc/testcases/types/assertions/AssertionTest.java
index d717203..99b41c3 100644
--- a/src/etc/testcases/types/assertions/AssertionTest.java
+++ b/src/etc/testcases/types/assertions/AssertionTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/etc/testcases/types/description1.xml b/src/etc/testcases/types/description1.xml
index 86a2a16..b56aa1e 100644
--- a/src/etc/testcases/types/description1.xml
+++ b/src/etc/testcases/types/description1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/description2.xml b/src/etc/testcases/types/description2.xml
index 945bc20..86b770c 100644
--- a/src/etc/testcases/types/description2.xml
+++ b/src/etc/testcases/types/description2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/description3.xml b/src/etc/testcases/types/description3.xml
index af5dda1..30c6d9e 100644
--- a/src/etc/testcases/types/description3.xml
+++ b/src/etc/testcases/types/description3.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/description4.xml b/src/etc/testcases/types/description4.xml
index 22df9c2..6caf064 100644
--- a/src/etc/testcases/types/description4.xml
+++ b/src/etc/testcases/types/description4.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/filelist.xml b/src/etc/testcases/types/filelist.xml
index f854ddb..781b578 100644
--- a/src/etc/testcases/types/filelist.xml
+++ b/src/etc/testcases/types/filelist.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/fileset.xml b/src/etc/testcases/types/fileset.xml
index c0f6949..e6dc985 100644
--- a/src/etc/testcases/types/fileset.xml
+++ b/src/etc/testcases/types/fileset.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/filterset.xml b/src/etc/testcases/types/filterset.xml
index bf291e7..f6b6997 100644
--- a/src/etc/testcases/types/filterset.xml
+++ b/src/etc/testcases/types/filterset.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/flexinteger.xml b/src/etc/testcases/types/flexinteger.xml
index aa10aa0..d5e2e98 100644
--- a/src/etc/testcases/types/flexinteger.xml
+++ b/src/etc/testcases/types/flexinteger.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -18,15 +18,13 @@
 <project name="test" default="test" basedir=".">
 
   <path id="testclasses">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="test">
     <taskdef name="flexint"
              classname="org.apache.tools.ant.types.FlexIntegerTest"
-             classpathref="testclasses"
-    />
+             classpathref="testclasses"/>
             
     <flexint propname="flexint.value1" value="0xA"/>
     <flexint propname="flexint.value2" value="010"/>
diff --git a/src/etc/testcases/types/mapper.xml b/src/etc/testcases/types/mapper.xml
index a96f10c..37f40a0 100644
--- a/src/etc/testcases/types/mapper.xml
+++ b/src/etc/testcases/types/mapper.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/mappers/define.mapperresult.xml b/src/etc/testcases/types/mappers/define.mapperresult.xml
index d9152a1..0c28bfa 100644
--- a/src/etc/testcases/types/mappers/define.mapperresult.xml
+++ b/src/etc/testcases/types/mappers/define.mapperresult.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -17,7 +17,7 @@
 -->
 <project>
   <typedef name="mapperresult"
-           classpath="../../../../../build/testcases"
+           classpath="${build.tests.value}"
            classname="org.apache.tools.ant.types.mappers.MapperResult"/>
 
   <!-- this is what you get with no result -->           
diff --git a/src/etc/testcases/types/mappers/globmapper.xml b/src/etc/testcases/types/mappers/globmapper.xml
index 1666d81..8d79799 100644
--- a/src/etc/testcases/types/mappers/globmapper.xml
+++ b/src/etc/testcases/types/mappers/globmapper.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/mappers/regexpmapper.xml b/src/etc/testcases/types/mappers/regexpmapper.xml
index a85c49c..08f0ded 100644
--- a/src/etc/testcases/types/mappers/regexpmapper.xml
+++ b/src/etc/testcases/types/mappers/regexpmapper.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/mappers/scriptmapper.xml b/src/etc/testcases/types/mappers/scriptmapper.xml
index d3e7a8d..05bd032 100644
--- a/src/etc/testcases/types/mappers/scriptmapper.xml
+++ b/src/etc/testcases/types/mappers/scriptmapper.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/poly.xml b/src/etc/testcases/types/poly.xml
index cabf9ec..b72049c 100644
--- a/src/etc/testcases/types/poly.xml
+++ b/src/etc/testcases/types/poly.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -20,19 +20,18 @@
   <property name="c" value="org.apache.tools.ant.types.PolyTest"/>
   
   <path id="test-c">
-    <pathelement location="../../../../build/testcases" />
-    <pathelement path="${java.class.path}" />
+    <pathelement path="${java.class.path}"/>
   </path>
 
   <target name="init">
-    <typedef loaderref="poly"   classpathref="test-c"
-             name = "myfileset" classname="${c}$MyFileSet"/>
+    <typedef loaderref="poly" classpathref="test-c"
+             name="myfileset" classname="${c}$MyFileSet"/>
 
     <typedef loaderref="poly" classpathref="test-c"
-             name = "mypath"  classname="${c}$MyPath"/>
+             name="mypath"    classname="${c}$MyPath"/>
 
     <typedef loaderref="poly" classpathref="test-c"
-             name = "mytask"  classname="${c}$MyTask"/>
+             name="mytask"    classname="${c}$MyTask"/>
   </target>
 
   <target name="fileset" depends="init">
diff --git a/src/etc/testcases/types/quote1.xml b/src/etc/testcases/types/quote1.xml
index 8e77122..449ef86 100644
--- a/src/etc/testcases/types/quote1.xml
+++ b/src/etc/testcases/types/quote1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/quote2.xml b/src/etc/testcases/types/quote2.xml
index ef9a3c3..197c976 100644
--- a/src/etc/testcases/types/quote2.xml
+++ b/src/etc/testcases/types/quote2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/redirector.xml b/src/etc/testcases/types/redirector.xml
index 4784e9f..e70a055 100644
--- a/src/etc/testcases/types/redirector.xml
+++ b/src/etc/testcases/types/redirector.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/etc/testcases/types/resources/javaresource.xml b/src/etc/testcases/types/resources/javaresource.xml
index 8326762..f4b6062 100644
--- a/src/etc/testcases/types/resources/javaresource.xml
+++ b/src/etc/testcases/types/resources/javaresource.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/resources/resourcelist.xml b/src/etc/testcases/types/resources/resourcelist.xml
index f1ac6df..6628352 100644
--- a/src/etc/testcases/types/resources/resourcelist.xml
+++ b/src/etc/testcases/types/resources/resourcelist.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/resources/tarentry.xml b/src/etc/testcases/types/resources/tarentry.xml
index c0fa379..6d52cca 100644
--- a/src/etc/testcases/types/resources/tarentry.xml
+++ b/src/etc/testcases/types/resources/tarentry.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/selectors.xml b/src/etc/testcases/types/selectors.xml
index 5a80d04..2ca6c79 100644
--- a/src/etc/testcases/types/selectors.xml
+++ b/src/etc/testcases/types/selectors.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/selectors/scriptselector.xml b/src/etc/testcases/types/selectors/scriptselector.xml
index 80afe30..23f3362 100644
--- a/src/etc/testcases/types/selectors/scriptselector.xml
+++ b/src/etc/testcases/types/selectors/scriptselector.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/selectors/signedselector.xml b/src/etc/testcases/types/selectors/signedselector.xml
index 60fe940..6f177fc 100644
--- a/src/etc/testcases/types/selectors/signedselector.xml
+++ b/src/etc/testcases/types/selectors/signedselector.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/xmlcatalog.xml b/src/etc/testcases/types/xmlcatalog.xml
index 63269f7..d97c140 100644
--- a/src/etc/testcases/types/xmlcatalog.xml
+++ b/src/etc/testcases/types/xmlcatalog.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/xmlcatalog.xsl b/src/etc/testcases/types/xmlcatalog.xsl
index a2c839c..16096e3 100644
--- a/src/etc/testcases/types/xmlcatalog.xsl
+++ b/src/etc/testcases/types/xmlcatalog.xsl
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/xmlcatalog1.xml b/src/etc/testcases/types/xmlcatalog1.xml
index d4b5461..2404eff 100644
--- a/src/etc/testcases/types/xmlcatalog1.xml
+++ b/src/etc/testcases/types/xmlcatalog1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/xmlcatalog2.xml b/src/etc/testcases/types/xmlcatalog2.xml
index 9d2bed0..e57a9c1 100644
--- a/src/etc/testcases/types/xmlcatalog2.xml
+++ b/src/etc/testcases/types/xmlcatalog2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/types/xmlfragment.xml b/src/etc/testcases/types/xmlfragment.xml
index 75214d6..5dcf7f1 100644
--- a/src/etc/testcases/types/xmlfragment.xml
+++ b/src/etc/testcases/types/xmlfragment.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/etc/testcases/util/simple.properties b/src/etc/testcases/util/simple.properties
index 550908c..5c8eb9c 100644
--- a/src/etc/testcases/util/simple.properties
+++ b/src/etc/testcases/util/simple.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/etc/testcases/util/unusual.properties b/src/etc/testcases/util/unusual.properties
index 3b63de6..e7d505d 100644
--- a/src/etc/testcases/util/unusual.properties
+++ b/src/etc/testcases/util/unusual.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/main/org/apache/tools/ant/AntClassLoader.java b/src/main/org/apache/tools/ant/AntClassLoader.java
index 7f37fbc..9560f98 100644
--- a/src/main/org/apache/tools/ant/AntClassLoader.java
+++ b/src/main/org/apache/tools/ant/AntClassLoader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,12 +20,12 @@
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Constructor;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.file.Files;
 import java.security.CodeSource;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
@@ -35,6 +35,7 @@
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.StringTokenizer;
 import java.util.Vector;
 import java.util.jar.Attributes;
@@ -42,13 +43,16 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipFile;
 
 import org.apache.tools.ant.launch.Locator;
 import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
 import org.apache.tools.ant.util.LoaderUtils;
+import org.apache.tools.ant.util.ReflectUtil;
 import org.apache.tools.ant.util.StringUtils;
 import org.apache.tools.ant.util.VectorSet;
 import org.apache.tools.zip.ZipLong;
@@ -74,6 +78,31 @@
 
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
+    private static final boolean IS_ATLEAST_JAVA9 = JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9);
+    // constructs needed to create (via reflection) a java.util.jar.JarFile instance when Java runtime version is >= 9
+    private static final Class[] MR_JARFILE_CTOR_ARGS;
+    private static final Object MR_JARFILE_CTOR_RUNTIME_VERSION_VAL;
+
+    static {
+        registerAsParallelCapable();
+        if (IS_ATLEAST_JAVA9) {
+            Class[] ctorArgs = null;
+            Object runtimeVersionVal = null;
+            try {
+                final Class<?> runtimeVersionClass = Class.forName("java.lang.Runtime$Version");
+                ctorArgs = new Class[] {File.class, boolean.class, int.class, runtimeVersionClass};
+                runtimeVersionVal = Runtime.class.getDeclaredMethod("version").invoke(null);
+            } catch (Exception e) {
+                // ignore - we consider this as multi-release jar unsupported
+            }
+            MR_JARFILE_CTOR_ARGS = ctorArgs;
+            MR_JARFILE_CTOR_RUNTIME_VERSION_VAL = runtimeVersionVal;
+        } else {
+            MR_JARFILE_CTOR_ARGS = null;
+            MR_JARFILE_CTOR_RUNTIME_VERSION_VAL = null;
+        }
+    }
+
     /**
      * An enumeration of all resources of a given name found within the
      * classpath of this class loader. This enumeration is used by the
@@ -174,7 +203,7 @@
      * The components of the classpath that the classloader searches
      * for classes.
      */
-    private final Vector<File> pathComponents  = new VectorSet<File>();
+    private final Vector<File> pathComponents  = new VectorSet<>();
 
     /**
      * The project to which this class loader belongs.
@@ -192,14 +221,14 @@
      * loader regardless of whether the parent class loader is being searched
      * first or not.
      */
-    private final Vector<String> systemPackages = new Vector<String>();
+    private final Vector<String> systemPackages = new Vector<>();
 
     /**
      * These are the package roots that are to be loaded by this class loader
      * regardless of whether the parent class loader is being searched first
      * or not.
      */
-    private final Vector<String> loaderPackages = new Vector<String>();
+    private final Vector<String> loaderPackages = new Vector<>();
 
     /**
      * Whether or not this classloader will ignore the base
@@ -217,11 +246,11 @@
     /**
      * A hashtable of zip files opened by the classloader (File to JarFile).
      */
-    private Hashtable<File, JarFile> jarFiles = new Hashtable<File, JarFile>();
+    private Hashtable<File, JarFile> jarFiles = new Hashtable<>();
 
     /** Static map of jar file/time to manifest class-path entries */
     private static Map<String, String> pathMap =
-        Collections.synchronizedMap(new HashMap<String, String>());
+        Collections.synchronizedMap(new HashMap<>());
 
     /**
      * The context loader saved when setting the thread's current
@@ -289,8 +318,8 @@
      *                    classloader should be consulted  before trying to
      *                    load the a class through this loader.
      */
-    public AntClassLoader(
-                          final ClassLoader parent, final Project project, final Path classpath, final boolean parentFirst) {
+    public AntClassLoader(final ClassLoader parent, final Project project,
+        final Path classpath, final boolean parentFirst) {
         this(project, classpath);
         if (parent != null) {
             setParent(parent);
@@ -311,7 +340,8 @@
      *                    classloader should be consulted before trying to
      *                    load the a class through this loader.
      */
-    public AntClassLoader(final Project project, final Path classpath, final boolean parentFirst) {
+    public AntClassLoader(final Project project, final Path classpath,
+        final boolean parentFirst) {
         this(null, project, classpath, parentFirst);
     }
 
@@ -418,7 +448,7 @@
         if (LoaderUtils.isContextLoaderAvailable()) {
             savedContextLoader = LoaderUtils.getContextClassLoader();
             ClassLoader loader = this;
-            if (project != null && "only".equals(project.getProperty("build.sysclasspath"))) {
+            if (project != null && "only".equals(project.getProperty(MagicNames.BUILD_SYSCLASSPATH))) {
                 loader = this.getClass().getClassLoader();
             }
             LoaderUtils.setContextClassLoader(loader);
@@ -493,19 +523,13 @@
                 + pathComponent.lastModified() + "-" + pathComponent.length();
         String classpath = pathMap.get(absPathPlusTimeAndLength);
         if (classpath == null) {
-            JarFile jarFile = null;
-            try {
-                jarFile = new JarFile(pathComponent);
+            try (JarFile jarFile = newJarFile(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 = "";
@@ -513,7 +537,7 @@
             pathMap.put(absPathPlusTimeAndLength, classpath);
         }
 
-        if (!"".equals(classpath)) {
+        if (!classpath.isEmpty()) {
             final URL baseURL = FILE_UTILS.getFileURL(pathComponent);
             final StringTokenizer st = new StringTokenizer(classpath);
             while (st.hasMoreTokens()) {
@@ -542,15 +566,11 @@
      */
     public String getClasspath() {
         final StringBuilder sb = new StringBuilder();
-        boolean firstPass = true;
-        final Enumeration<File> componentEnum = pathComponents.elements();
-        while (componentEnum.hasMoreElements()) {
-            if (!firstPass) {
-                sb.append(System.getProperty("path.separator"));
-            } else {
-                firstPass = false;
+        for (final File component : pathComponents) {
+            if (sb.length() > 0) {
+                sb.append(File.pathSeparator);
             }
-            sb.append(componentEnum.nextElement().getAbsolutePath());
+            sb.append(component.getAbsolutePath());
         }
         return sb.toString();
     }
@@ -747,14 +767,8 @@
     private InputStream loadResource(final String name) {
         // we need to search the components of the path to see if we can
         // find the class we want.
-        InputStream stream = null;
-
-        final Enumeration<File> e = pathComponents.elements();
-        while (e.hasMoreElements() && stream == null) {
-            final File pathComponent = e.nextElement();
-            stream = getResourceStream(pathComponent, name);
-        }
-        return stream;
+        return pathComponents.stream().map(path -> getResourceStream(path, name))
+                .filter(Objects::nonNull).findFirst().orElse(null);
     }
 
     /**
@@ -789,12 +803,12 @@
             if (jarFile == null && file.isDirectory()) {
                 final File resource = new File(file, resourceName);
                 if (resource.exists()) {
-                    return new FileInputStream(resource);
+                    return Files.newInputStream(resource.toPath());
                 }
             } else {
                 if (jarFile == null) {
                     if (file.exists()) {
-                        jarFile = new JarFile(file);
+                        jarFile = newJarFile(file);
                         jarFiles.put(file, jarFile);
                     } else {
                         return null;
@@ -836,27 +850,12 @@
 
         // TODO - shouldn't this always return false in isolated mode?
 
-        boolean useParentFirst = parentFirst;
-
-        for (final Enumeration<String> e = systemPackages.elements(); e.hasMoreElements();) {
-            final String packageName = e.nextElement();
-            if (resourceName.startsWith(packageName)) {
-                useParentFirst = true;
-                break;
-            }
-        }
-        for (final Enumeration<String> e = loaderPackages.elements(); e.hasMoreElements();) {
-            final String packageName = e.nextElement();
-            if (resourceName.startsWith(packageName)) {
-                useParentFirst = false;
-                break;
-            }
-        }
-        return useParentFirst;
+        return loaderPackages.stream().noneMatch(resourceName::startsWith)
+                && (systemPackages.stream().anyMatch(resourceName::startsWith) || parentFirst);
     }
 
     /**
-     * Used for isolated resource seaching.
+     * Used for isolated resource searching.
      * @return the root classloader of AntClassLoader.
      */
     private ClassLoader getRootLoader() {
@@ -890,16 +889,7 @@
         if (url != null) {
             log("Resource " + name + " loaded from parent loader", Project.MSG_DEBUG);
         } else {
-            // try and load from this loader if the parent either didn't find
-            // it or wasn't consulted.
-            final Enumeration<File> e = pathComponents.elements();
-            while (e.hasMoreElements() && url == null) {
-                final File pathComponent = e.nextElement();
-                url = getResourceURL(pathComponent, name);
-                if (url != null) {
-                    log("Resource " + name + " loaded from ant loader", Project.MSG_DEBUG);
-                }
-            }
+            url = getUrl(name);
         }
         if (url == null && !isParentFirst(name)) {
             // this loader was first but it didn't find it - try the parent
@@ -919,13 +909,33 @@
     }
 
     /**
+     * Finds a matching file by iterating through path components.
+     *
+     * @param name File to find
+     * @return A <code>URL</code> object for reading the resource, or <code>null</code> if the
+     *     resource could not be found
+     */
+    private URL getUrl(String name) {
+        URL url = null;
+
+        // try and load from this loader if the parent either didn't find
+        // it or wasn't consulted.
+        for (final File pathComponent : pathComponents) {
+            url = getResourceURL(pathComponent, name);
+            if (url != null) {
+                log("Resource " + name + " loaded from ant loader", Project.MSG_DEBUG);
+                break;
+            }
+        }
+
+        return url;
+    }
+
+    /**
      * Finds all the resources with the given name. A resource is some
      * data (images, audio, text, etc) that can be accessed by class
      * code in a way that is independent of the location of the code.
      *
-     * <p>Would override getResources if that wasn't final in Java
-     * 1.4.</p>
-     *
      * @param name name of the resource
      * @return possible URLs as enumeration
      * @throws IOException if something goes wrong
@@ -938,6 +948,18 @@
     }
 
     /**
+     * Finds the resource with the given name.
+     *
+     * @param name The resource name
+     * @return A <code>URL</code> object for reading the resource, or <code>null</code> if the
+     *     resource could not be found
+     */
+    @Override
+    protected URL findResource(final String name) {
+        return getUrl(name);
+    }
+
+    /**
      * Returns an enumeration of URLs representing all the resources with the
      * given name by searching the class loader's classpath.
      *
@@ -957,38 +979,38 @@
      *
      * @param name The resource name to search for.
      *             Must not be <code>null</code>.
-     * @param parentHasBeenSearched whether ClassLoader.this.parent
-     * has been searched - will be true if the method is (indirectly)
-     * called from ClassLoader.getResources
+     * @param skipParent whether to skip searching the parent first - will be false if the method is
+     *     invoked from {@link #getResources(String)} or {@link #getNamedResources(String)} and true
+     *     if the method is invoked from {@link #findResources(String)}.
      * @return an enumeration of URLs for the resources
      * @exception IOException if I/O errors occurs (can't happen)
      */
     protected Enumeration<URL> findResources(final String name,
-                                             final boolean parentHasBeenSearched)
+                                             final boolean skipParent)
         throws IOException {
         final Enumeration<URL> mine = new ResourceEnumeration(name);
         Enumeration<URL> base;
-        if (parent != null && (!parentHasBeenSearched || parent != getParent())) {
+        if (parent != null && !skipParent) {
             // Delegate to the parent:
             base = parent.getResources(name);
-            // Note: could cause overlaps in case
-            // ClassLoader.this.parent has matches and
-            // parentHasBeenSearched is true
         } else {
-            // ClassLoader.this.parent is already delegated to for example from
-            // ClassLoader.getResources, no need:
-            base = new CollectionUtils.EmptyEnumeration<URL>();
+            base = Collections.emptyEnumeration();
         }
         if (isParentFirst(name)) {
             // Normal case.
-            return CollectionUtils.append(base, mine);
+            return append(base, mine);
         }
         if (ignoreBase) {
-            return getRootLoader() == null ? mine : CollectionUtils.append(mine, getRootLoader()
-                    .getResources(name));
+            return getRootLoader() == null ? mine
+                    : append(mine, getRootLoader().getResources(name));
         }
         // parent last:
-        return CollectionUtils.append(mine, base);
+        return append(mine, base);
+    }
+
+    private static Enumeration<URL> append(Enumeration<URL> one, Enumeration<URL> two) {
+        return Stream.concat(Collections.list(one).stream(), Collections.list(two).stream())
+                .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::enumeration));
     }
 
     /**
@@ -1025,7 +1047,7 @@
                             log(msg, Project.MSG_WARN);
                             return null;
                         }
-                        jarFile = new JarFile(file);
+                        jarFile = newJarFile(file);
                         jarFiles.put(file, jarFile);
                     } else {
                         return null;
@@ -1362,12 +1384,8 @@
         // we need to search the components of the path to see if
         // we can find the class we want.
         final String classFilename = getClassFilename(name);
-        final Enumeration<File> e = pathComponents.elements();
-        while (e.hasMoreElements()) {
-            final File pathComponent = e.nextElement();
-            InputStream stream = null;
-            try {
-                stream = getResourceStream(pathComponent, classFilename);
+        for (final File pathComponent : pathComponents) {
+            try (InputStream stream = getResourceStream(pathComponent, classFilename)) {
                 if (stream != null) {
                     log("Loaded from " + pathComponent + " "
                         + classFilename, Project.MSG_DEBUG);
@@ -1379,8 +1397,6 @@
                 // ioe.printStackTrace();
                 log("Exception reading component " + pathComponent + " (reason: "
                     + ioe.getMessage() + ")", Project.MSG_VERBOSE);
-            } finally {
-                FileUtils.close(stream);
             }
         }
         throw new ClassNotFoundException(name);
@@ -1410,15 +1426,10 @@
      * files are closed.
      */
     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
-            }
+        for (final JarFile jarFile : jarFiles.values()) {
+            FileUtils.close(jarFile);
         }
-        jarFiles = new Hashtable<File, JarFile>();
+        jarFiles = new Hashtable<>();
         if (project != null) {
             project.removeBuildListener(this);
         }
@@ -1531,12 +1542,7 @@
      * here
      */
     public void addJavaLibraries() {
-        final Vector<String> packages = JavaEnvUtils.getJrePackages();
-        final Enumeration<String> e = packages.elements();
-        while (e.hasMoreElements()) {
-            final String packageName = e.nextElement();
-            addSystemPackageRoot(packageName);
-        }
+        JavaEnvUtils.getJrePackages().forEach(this::addSystemPackageRoot);
     }
 
     /**
@@ -1592,8 +1598,7 @@
     }
 
     private static boolean readFully(final File f, final byte[] b) throws IOException {
-        final FileInputStream fis = new FileInputStream(f);
-        try {
+        try (InputStream fis = Files.newInputStream(f.toPath())) {
             final int len = b.length;
             int count = 0, x = 0;
             while (count != len) {
@@ -1604,9 +1609,22 @@
                 count += x;
             }
             return count == len;
-        } finally {
-            fis.close();
         }
     }
 
+    /**
+     *
+     * @param file The file representing the jar
+     * @return Returns a {@link JarFile} instance, which is constructed based upon the Java runtime version.
+     *         Depending on the Java runtime version, the returned instance may or may not be {@code multi-release}
+     *         aware (a feature introduced in Java 9)
+     * @throws IOException
+     */
+    private static JarFile newJarFile(final File file) throws IOException {
+        if (!IS_ATLEAST_JAVA9 || MR_JARFILE_CTOR_ARGS == null || MR_JARFILE_CTOR_RUNTIME_VERSION_VAL == null) {
+            return new JarFile(file);
+        }
+        return ReflectUtil.newInstance(JarFile.class, MR_JARFILE_CTOR_ARGS,
+                new Object[] {file, true, ZipFile.OPEN_READ, MR_JARFILE_CTOR_RUNTIME_VERSION_VAL});
+    }
 }
diff --git a/src/main/org/apache/tools/ant/AntTypeDefinition.java b/src/main/org/apache/tools/ant/AntTypeDefinition.java
index c7b223c..c645a94 100644
--- a/src/main/org/apache/tools/ant/AntTypeDefinition.java
+++ b/src/main/org/apache/tools/ant/AntTypeDefinition.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -307,11 +307,11 @@
         // DataType can have a "no arg" constructor or take a single
         // Project argument.
         try {
-            ctor = newclass.getConstructor(new Class[0]);
+            ctor = newclass.getConstructor();
             noArg = true;
         } catch (NoSuchMethodException nse) {
             //can throw the same exception, if there is no this(Project) ctor.
-            ctor = newclass.getConstructor(new Class[] {Project.class});
+            ctor = newclass.getConstructor(Project.class);
             noArg = false;
         }
         //now we instantiate
@@ -373,6 +373,6 @@
     }
 
     private String extractClassname(Class<?> c) {
-        return (c == null) ? "<null>" : c.getClass().getName();
+        return (c == null) ? "<null>" : c.getName();
     }
 }
diff --git a/src/main/org/apache/tools/ant/ArgumentProcessor.java b/src/main/org/apache/tools/ant/ArgumentProcessor.java
index 7a547fd..ec08f00 100644
--- a/src/main/org/apache/tools/ant/ArgumentProcessor.java
+++ b/src/main/org/apache/tools/ant/ArgumentProcessor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/ArgumentProcessorRegistry.java b/src/main/org/apache/tools/ant/ArgumentProcessorRegistry.java
index ed3331f..2a36399 100644
--- a/src/main/org/apache/tools/ant/ArgumentProcessorRegistry.java
+++ b/src/main/org/apache/tools/ant/ArgumentProcessorRegistry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,11 +23,11 @@
 import java.io.InputStreamReader;
 import java.net.URL;
 import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.List;
 
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.LoaderUtils;
 
 /**
@@ -55,7 +55,7 @@
 
     private static ArgumentProcessorRegistry instance = new ArgumentProcessorRegistry();
 
-    private List<ArgumentProcessor> processors = new ArrayList<ArgumentProcessor>();
+    private List<ArgumentProcessor> processors = new ArrayList<>();
 
     public static ArgumentProcessorRegistry getInstance() {
         return instance;
@@ -73,9 +73,7 @@
         try {
             ClassLoader classLoader = LoaderUtils.getContextClassLoader();
             if (classLoader != null) {
-                Enumeration<URL> resources = classLoader.getResources(SERVICE_ID);
-                while (resources.hasMoreElements()) {
-                    URL resource = resources.nextElement();
+                for (URL resource : Collections.list(classLoader.getResources(SERVICE_ID))) {
                     URLConnection conn = resource.openConnection();
                     conn.setUseCaches(false);
                     ArgumentProcessor processor = getProcessorByService(conn.getInputStream());
@@ -127,7 +125,7 @@
             processor = processorClass.getConstructor().newInstance();
         } catch (Exception e) {
             throw new BuildException("The argument processor class"
-                    + processorClass.getClass().getName()
+                    + processorClass.getName()
                     + " could not be instantiated with a default constructor",
                     e);
         }
@@ -147,20 +145,11 @@
 
     private ArgumentProcessor getProcessorByService(InputStream is)
             throws IOException {
-        InputStreamReader isr = null;
-        try {
-            try {
-                isr = new InputStreamReader(is, "UTF-8");
-            } catch (java.io.UnsupportedEncodingException e) {
-                isr = new InputStreamReader(is);
-            }
-            BufferedReader rd = new BufferedReader(isr);
+        try (BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
             String processorClassName = rd.readLine();
-            if (processorClassName != null && !"".equals(processorClassName)) {
+            if (processorClassName != null && !processorClassName.isEmpty()) {
                 return getProcessor(processorClassName);
             }
-        } finally {
-            FileUtils.close(isr);
         }
         return null;
     }
diff --git a/src/main/org/apache/tools/ant/BuildEvent.java b/src/main/org/apache/tools/ant/BuildEvent.java
index 623ad1e..d4d71f8 100644
--- a/src/main/org/apache/tools/ant/BuildEvent.java
+++ b/src/main/org/apache/tools/ant/BuildEvent.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/BuildException.java b/src/main/org/apache/tools/ant/BuildException.java
index a4ed05f..9104fad 100644
--- a/src/main/org/apache/tools/ant/BuildException.java
+++ b/src/main/org/apache/tools/ant/BuildException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,6 +24,19 @@
 
     private static final long serialVersionUID = -5419014565354664240L;
 
+    /**
+     * Get a {@link BuildException} for the specified {@link Throwable}.
+     * @param t
+     * @return {@link BuildException}
+     * @since Ant 1.10.13
+     */
+    public static BuildException of(Throwable t) {
+        if (t instanceof BuildException) {
+            return (BuildException) t;
+        }
+        return new BuildException(t);
+    }
+
     /** Location in the build file where the exception occurred */
     private Location location = Location.UNKNOWN_LOCATION;
 
@@ -38,13 +51,26 @@
      * Constructs an exception with the given descriptive message.
      *
      * @param message A description of or information about the exception.
-     *            Should not be <code>null</code>.
+     *            Should not be {@code null}.
      */
     public BuildException(String message) {
         super(message);
     }
 
     /**
+     * Constructs an exception with the given format pattern and arguments.
+     *
+     * @param pattern A description of or information about the exception.
+     *            Should not be {@code null}.
+     * @param formatArguments ditto
+     * @see String#format(String, Object...)
+     * @since Ant 1.10.2
+     */
+    public BuildException(String pattern, Object... formatArguments) {
+        super(String.format(pattern, formatArguments));
+    }
+
+    /**
      * Constructs an exception with the given message and exception as
      * a root cause.
      *
@@ -61,15 +87,15 @@
      * Constructs an exception with the given message and exception as
      * a root cause and a location in a file.
      *
-     * @param msg A description of or information about the exception.
-     *            Should not be <code>null</code> unless a cause is specified.
+     * @param message A description of or information about the exception.
+     *                Should not be <code>null</code> unless a cause is specified.
      * @param cause The exception that might have caused this one.
      *              May be <code>null</code>.
      * @param location The location in the project file where the error
      *                 occurred. Must not be <code>null</code>.
      */
-    public BuildException(String msg, Throwable cause, Location location) {
-        this(msg, cause);
+    public BuildException(String message, Throwable cause, Location location) {
+        this(message, cause);
         this.location = location;
     }
 
diff --git a/src/main/org/apache/tools/ant/BuildListener.java b/src/main/org/apache/tools/ant/BuildListener.java
index ed6731c..37c850e 100644
--- a/src/main/org/apache/tools/ant/BuildListener.java
+++ b/src/main/org/apache/tools/ant/BuildListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/BuildLogger.java b/src/main/org/apache/tools/ant/BuildLogger.java
index 249d8f5..08123aa 100644
--- a/src/main/org/apache/tools/ant/BuildLogger.java
+++ b/src/main/org/apache/tools/ant/BuildLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/ComponentHelper.java b/src/main/org/apache/tools/ant/ComponentHelper.java
index 6672fda..0011c19 100644
--- a/src/main/org/apache/tools/ant/ComponentHelper.java
+++ b/src/main/org/apache/tools/ant/ComponentHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,6 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -35,12 +34,12 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.Stack;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.launch.Launcher;
 import org.apache.tools.ant.taskdefs.Definer;
 import org.apache.tools.ant.taskdefs.Property;
 import org.apache.tools.ant.taskdefs.Typedef;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Component creation and configuration.
@@ -60,31 +59,31 @@
  */
 public class ComponentHelper  {
     /** Map of component name to lists of restricted definitions */
-    private Map<String, List<AntTypeDefinition>> restrictedDefinitions = new HashMap<String, List<AntTypeDefinition>>();
+    private final Map<String, List<AntTypeDefinition>> restrictedDefinitions = new HashMap<>();
 
     /** Map from component name to anttypedefinition */
-    private final Hashtable<String, AntTypeDefinition> antTypeTable = new Hashtable<String, AntTypeDefinition>();
+    private final Hashtable<String, AntTypeDefinition> antTypeTable = new Hashtable<>();
 
     /** Map of tasks generated from antTypeTable */
-    private final Hashtable<String, Class<?>> taskClassDefinitions = new Hashtable<String, Class<?>>();
+    private final Hashtable<String, Class<?>> taskClassDefinitions = new Hashtable<>();
 
     /** flag to rebuild taskClassDefinitions */
     private boolean rebuildTaskClassDefinitions = true;
 
     /** Map of types generated from antTypeTable */
-    private final Hashtable<String, Class<?>> typeClassDefinitions = new Hashtable<String, Class<?>>();
+    private final Hashtable<String, Class<?>> typeClassDefinitions = new Hashtable<>();
 
     /** flag to rebuild typeClassDefinitions */
     private boolean rebuildTypeClassDefinitions = true;
 
     /** Set of namespaces that have been checked for antlibs */
-    private final HashSet<String> checkedNamespaces = new HashSet<String>();
+    private final HashSet<String> checkedNamespaces = new HashSet<>();
 
     /**
      * Stack of antlib contexts used to resolve definitions while
      *   processing antlib
      */
-    private Stack<String> antLibStack = new Stack<String>();
+    private Stack<String> antLibStack = new Stack<>();
 
     /** current antlib uri */
     private String antLibCurrentUri = null;
@@ -190,7 +189,6 @@
      */
     public void setProject(Project project) {
         this.project = project;
-//        antTypeTable = new Hashtable<String, AntTypeDefinition>(project);
     }
 
     /**
@@ -206,13 +204,13 @@
      * @return A deep copy of the restrictedDefinition
      */
     private Map<String, List<AntTypeDefinition>> getRestrictedDefinition() {
-        final Map<String, List<AntTypeDefinition>> result = new HashMap<String, List<AntTypeDefinition>>();
+        final Map<String, List<AntTypeDefinition>> result = new HashMap<>();
         synchronized (restrictedDefinitions) {
             for (Map.Entry<String, List<AntTypeDefinition>> entry : restrictedDefinitions.entrySet()) {
                 List<AntTypeDefinition> entryVal = entry.getValue();
                 synchronized (entryVal) {
                     //copy the entryVal
-                    entryVal = new ArrayList<AntTypeDefinition> (entryVal);
+                    entryVal = new ArrayList<>(entryVal);
                 }
                 result.put(entry.getKey(), entryVal);
             }
@@ -230,7 +228,8 @@
     public void initSubProject(ComponentHelper helper) {
         // add the types of the parent project
         @SuppressWarnings("unchecked")
-        final Hashtable<String, AntTypeDefinition> typeTable = (Hashtable<String, AntTypeDefinition>) helper.antTypeTable.clone();
+        final Hashtable<String, AntTypeDefinition> typeTable
+                = (Hashtable<String, AntTypeDefinition>) helper.antTypeTable.clone();
         synchronized (antTypeTable) {
             for (AntTypeDefinition def : typeTable.values()) {
                 antTypeTable.put(def.getName(), def);
@@ -241,7 +240,8 @@
         synchronized (this) {
             checkedNamespaces.addAll(inheritedCheckedNamespace);
         }
-        Map<String, List<AntTypeDefinition>> inheritedRestrictedDef = helper.getRestrictedDefinition();
+        Map<String, List<AntTypeDefinition>> inheritedRestrictedDef
+                = helper.getRestrictedDefinition();
         synchronized (restrictedDefinitions) {
             restrictedDefinitions.putAll(inheritedRestrictedDef);
         }
@@ -400,15 +400,11 @@
             synchronized (antTypeTable) {
                 if (rebuildTaskClassDefinitions) {
                     taskClassDefinitions.clear();
-                    for (Map.Entry<String, AntTypeDefinition> e : antTypeTable.entrySet()) {
-                        final Class<?> clazz = e.getValue().getExposedClass(project);
-                        if (clazz == null) {
-                            continue;
-                        }
-                        if (Task.class.isAssignableFrom(clazz)) {
-                            taskClassDefinitions.put(e.getKey(), e.getValue().getTypeClass(project));
-                        }
-                    }
+                    antTypeTable.entrySet().stream()
+                            .filter(e -> e.getValue().getExposedClass(project) != null
+                                    && Task.class.isAssignableFrom(e.getValue().getExposedClass(project)))
+                            .forEach(e -> taskClassDefinitions.put(e.getKey(),
+                                    e.getValue().getTypeClass(project)));
                     rebuildTaskClassDefinitions = false;
                 }
             }
@@ -428,15 +424,11 @@
             synchronized (antTypeTable) {
                 if (rebuildTypeClassDefinitions) {
                     typeClassDefinitions.clear();
-                    for (Map.Entry<String, AntTypeDefinition> e : antTypeTable.entrySet()) {
-                        final Class<?> clazz = e.getValue().getExposedClass(project);
-                        if (clazz == null) {
-                            continue;
-                        }
-                        if (!Task.class.isAssignableFrom(clazz)) {
-                            typeClassDefinitions.put(e.getKey(), e.getValue().getTypeClass(project));
-                        }
-                    }
+                    antTypeTable.entrySet().stream()
+                            .filter(e -> e.getValue().getExposedClass(project) != null
+                                    && !Task.class.isAssignableFrom(e.getValue().getExposedClass(project)))
+                            .forEach(e -> typeClassDefinitions.put(e.getKey(),
+                                    e.getValue().getTypeClass(project)));
                     rebuildTypeClassDefinitions = false;
                 }
             }
@@ -684,11 +676,7 @@
         String name = def.getName();
         List<AntTypeDefinition> list = null;
         synchronized (restrictedDefinitions) {
-            list = restrictedDefinitions.get(name);
-            if (list == null) {
-                list = new ArrayList<AntTypeDefinition>();
-                restrictedDefinitions.put(name, list);
-            }
+            list = restrictedDefinitions.computeIfAbsent(name, k -> new ArrayList<>());
         }
         // Check if the classname is already present and remove it
         // if it is
@@ -751,7 +739,7 @@
      */
     public void exitAntLib() {
         antLibStack.pop();
-        antLibCurrentUri = (antLibStack.size() == 0) ? null : (String) antLibStack.peek();
+        antLibCurrentUri = (antLibStack.isEmpty()) ? null : antLibStack.peek();
     }
 
     /**
@@ -760,13 +748,10 @@
     private void initTasks() {
         ClassLoader classLoader = getClassLoader(null);
         Properties props = getDefaultDefinitions(false);
-        Enumeration<?> e = props.propertyNames();
-        while (e.hasMoreElements()) {
-            String name = (String) e.nextElement();
-            String className = props.getProperty(name);
+        for (String name : props.stringPropertyNames()) {
             AntTypeDefinition def = new AntTypeDefinition();
             def.setName(name);
-            def.setClassName(className);
+            def.setClassName(props.getProperty(name));
             def.setClassLoader(classLoader);
             def.setAdaptToClass(Task.class);
             def.setAdapterClass(TaskAdapter.class);
@@ -799,9 +784,7 @@
             String resource = type ? MagicNames.TYPEDEFS_PROPERTIES_RESOURCE
                     : MagicNames.TASKDEF_PROPERTIES_RESOURCE;
             String errorString = type ? ERROR_NO_TYPE_LIST_LOAD : ERROR_NO_TASK_LIST_LOAD;
-            InputStream in = null;
-            try {
-                in = ComponentHelper.class.getResourceAsStream(resource);
+            try (InputStream in = ComponentHelper.class.getResourceAsStream(resource)) {
                 if (in == null) {
                     throw new BuildException(errorString);
                 }
@@ -810,8 +793,6 @@
                 defaultDefinitions[idx] = p;
             } catch (IOException e) {
                 throw new BuildException(errorString, e);
-            } finally {
-                FileUtils.close(in);
             }
         }
         return defaultDefinitions[idx];
@@ -823,13 +804,10 @@
     private void initTypes() {
         ClassLoader classLoader = getClassLoader(null);
         Properties props = getDefaultDefinitions(true);
-        Enumeration<?> e = props.propertyNames();
-        while (e.hasMoreElements()) {
-            String name = (String) e.nextElement();
-            String className = props.getProperty(name);
+        for (String name : props.stringPropertyNames()) {
             AntTypeDefinition def = new AntTypeDefinition();
             def.setName(name);
-            def.setClassName(className);
+            def.setClassName(props.getProperty(name));
             def.setClassLoader(classLoader);
             antTypeTable.put(name, def);
         }
@@ -843,10 +821,10 @@
      */
     private synchronized void checkNamespace(String componentName) {
         String uri = ProjectHelper.extractUriFromComponentName(componentName);
-        if ("".equals(uri)) {
+        if (uri.isEmpty()) {
             uri = ProjectHelper.ANT_CORE_URI;
         }
-        if (!uri.startsWith(ProjectHelper.ANTLIB_URI)) {
+        if (!uri.startsWith(MagicNames.ANTLIB_PREFIX)) {
             return; // namespace that does not contain antlib
         }
         if (checkedNamespaces.contains(uri)) {
@@ -854,7 +832,7 @@
         }
         checkedNamespaces.add(uri);
 
-        if (antTypeTable.size() == 0) {
+        if (antTypeTable.isEmpty()) {
             // Project instance doesn't know the tasks and types
             // defined in defaults.properties, likely created by the
             // user - without those definitions it cannot parse antlib
@@ -903,7 +881,7 @@
             probablyIDE = true;
             antHomeLib = "ANT_HOME" + File.separatorChar + "lib";
         }
-        StringBuffer dirListingText = new StringBuffer();
+        StringBuilder dirListingText = new StringBuilder();
         final String tab = "        -";
         dirListingText.append(tab);
         dirListingText.append(antHomeLib);
@@ -929,9 +907,9 @@
         } else {
             //we are defined, so it is an instantiation problem
             final String classname = def.getClassName();
-            antTask = classname.startsWith("org.apache.tools.ant.");
-            boolean optional = classname.startsWith("org.apache.tools.ant.taskdefs.optional");
-            optional |= classname.startsWith("org.apache.tools.ant.types.optional");
+            antTask = classname.startsWith(MagicNames.ANT_CORE_PACKAGE + ".");
+            boolean optional = classname.startsWith(MagicNames.ANT_CORE_PACKAGE + ".types.optional")
+                    || classname.startsWith(MagicNames.ANT_CORE_PACKAGE + ".taskdefs.optional");
 
             //start with instantiating the class.
             Class<?> clazz = null;
@@ -1025,16 +1003,9 @@
         out.println("Action: Check that any custom tasks/types have been declared.");
         out.println("Action: Check that any <presetdef>/<macrodef>"
                 + " declarations have taken place.");
-        if (uri.length() > 0) {
+        if (!uri.isEmpty()) {
             final List<AntTypeDefinition> matches = findTypeMatches(uri);
-            if (matches.size() > 0) {
-                out.println();
-                out.println("The definitions in the namespace " + uri + " are:");
-                for (AntTypeDefinition def : matches) {
-                    String local = ProjectHelper.extractNameFromComponentName(def.getName());
-                    out.println("    " + local);
-                }
-            } else {
+            if (matches.isEmpty()) {
                 out.println("No types or tasks have been defined in this namespace yet");
                 if (isAntlib) {
                     out.println();
@@ -1042,6 +1013,13 @@
                     out.println("Action: Check that the implementing library exists in one of:");
                     out.println(dirListing);
                 }
+            } else {
+                out.println();
+                out.println("The definitions in the namespace " + uri + " are:");
+                for (AntTypeDefinition def : matches) {
+                    String local = ProjectHelper.extractNameFromComponentName(def.getName());
+                    out.println("    " + local);
+                }
             }
         }
     }
@@ -1089,14 +1067,9 @@
      * @return the (possibly empty) list of definitions
      */
     private List<AntTypeDefinition> findTypeMatches(String prefix) {
-        final List<AntTypeDefinition> result = new ArrayList<AntTypeDefinition>();
         synchronized (antTypeTable) {
-            for (AntTypeDefinition def : antTypeTable.values()) {
-                if (def.getName().startsWith(prefix)) {
-                    result.add(def);
-                }
-            }
+            return antTypeTable.values().stream().filter(def -> def.getName().startsWith(prefix))
+                    .collect(Collectors.toList());
         }
-        return result;
     }
 }
diff --git a/src/main/org/apache/tools/ant/DefaultDefinitions.java b/src/main/org/apache/tools/ant/DefaultDefinitions.java
index 062018d..d558e43 100644
--- a/src/main/org/apache/tools/ant/DefaultDefinitions.java
+++ b/src/main/org/apache/tools/ant/DefaultDefinitions.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,6 @@
 public final class DefaultDefinitions {
     private static final String IF_NAMESPACE = "ant:if";
     private static final String UNLESS_NAMESPACE = "ant:unless";
-    private static final String OATA = "org.apache.tools.ant.";
 
     private final ComponentHelper componentHelper;
 
@@ -52,21 +51,20 @@
     private void attributeNamespaceDef(String ns) {
         AntTypeDefinition def = new AntTypeDefinition();
         def.setName(ProjectHelper.nsToComponentName(ns));
-        def.setClassName(OATA + "attribute.AttributeNamespace");
+        def.setClassName(MagicNames.ANT_CORE_PACKAGE + ".attribute.AttributeNamespace");
         def.setClassLoader(getClass().getClassLoader());
         def.setRestrict(true);
         componentHelper.addDataTypeDefinition(def);
     }
 
     private void ifUnlessDef(String name, String base) {
-        String classname =  OATA + "attribute." + base;
+        String classname = MagicNames.ANT_CORE_PACKAGE + ".attribute." + base;
         componentDef(IF_NAMESPACE, name, classname);
         componentDef(UNLESS_NAMESPACE, name, classname + "$Unless");
     }
 
     private void componentDef(String ns, String name, String classname) {
         AntTypeDefinition def = new AntTypeDefinition();
-        String n = ProjectHelper.genComponentName(ns, name);
         def.setName(ProjectHelper.genComponentName(ns, name));
         def.setClassName(classname);
         def.setClassLoader(getClass().getClassLoader());
diff --git a/src/main/org/apache/tools/ant/DefaultLogger.java b/src/main/org/apache/tools/ant/DefaultLogger.java
index e683b05..af503ea 100644
--- a/src/main/org/apache/tools/ant/DefaultLogger.java
+++ b/src/main/org/apache/tools/ant/DefaultLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,9 +24,10 @@
 import java.io.StringReader;
 import java.text.DateFormat;
 import java.util.Date;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.util.DateUtils;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.StringUtils;
 
 /**
@@ -57,6 +58,7 @@
 
     // CheckStyle:ConstantNameCheck OFF - bc
     /** Line separator */
+    @Deprecated
     protected static final String lSep = StringUtils.LINE_SEP;
     // CheckStyle:ConstantNameCheck ON
 
@@ -139,7 +141,7 @@
             String msg1 = error.toString();
             String msg2 = cause.toString();
             if (msg1.endsWith(msg2)) {
-                m.append(msg1.substring(0, msg1.length() - msg2.length()));
+                m.append(msg1, 0, msg1.length() - msg2.length());
                 error = cause;
             } else {
                 break;
@@ -148,7 +150,7 @@
         if (verbose || !(error instanceof BuildException)) {
             m.append(StringUtils.getStackTrace(error));
         } else {
-            m.append(error).append(lSep);
+            m.append(String.format("%s%n", error));
         }
     }
 
@@ -164,17 +166,13 @@
         Throwable error = event.getException();
         StringBuffer message = new StringBuffer();
         if (error == null) {
-            message.append(StringUtils.LINE_SEP);
-            message.append(getBuildSuccessfulMessage());
+            message.append(String.format("%n%s", getBuildSuccessfulMessage()));
         } else {
-            message.append(StringUtils.LINE_SEP);
-            message.append(getBuildFailedMessage());
-            message.append(StringUtils.LINE_SEP);
+            message.append(String.format("%n%s%n", getBuildFailedMessage()));
             throwableMessage(message, error, Project.MSG_VERBOSE <= msgOutputLevel);
         }
-        message.append(StringUtils.LINE_SEP);
-        message.append("Total time: ");
-        message.append(formatTime(System.currentTimeMillis() - startTime));
+        message.append(String.format("%nTotal time: %s",
+                formatTime(System.currentTimeMillis() - startTime)));
 
         String msg = message.toString();
         if (error == null) {
@@ -212,7 +210,7 @@
       */
     public void targetStarted(BuildEvent event) {
         if (Project.MSG_INFO <= msgOutputLevel
-                && !event.getTarget().getName().equals("")) {
+                && !event.getTarget().getName().isEmpty()) {
             String msg = String.format("%n%s:", event.getTarget().getName());
             printMessage(msg, out, event.getPriority());
             log(msg);
@@ -256,48 +254,26 @@
         // Filter out messages based on priority
         if (priority <= msgOutputLevel) {
 
-            StringBuffer message = new StringBuffer();
-            if (event.getTask() != null && !emacsMode) {
+            StringBuilder message = new StringBuilder();
+            if (event.getTask() == null || emacsMode) {
+                // emacs mode or there is no task
+                message.append(event.getMessage());
+            } else {
                 // Print out the name of the task if we're in one
                 String name = event.getTask().getTaskName();
                 String label = "[" + name + "] ";
                 int size = LEFT_COLUMN_SIZE - label.length();
-                StringBuffer tmp = new StringBuffer();
-                for (int i = 0; i < size; i++) {
-                    tmp.append(" ");
-                }
-                tmp.append(label);
-                label = tmp.toString();
+                final String prefix = size > 0 ? Stream.generate(() -> " ")
+                    .limit(size).collect(Collectors.joining()) + label : label;
 
-                BufferedReader r = null;
-                try {
-                    r = new BufferedReader(
-                            new StringReader(event.getMessage()));
-                    String line = r.readLine();
-                    boolean first = true;
-                    do {
-                        if (first) {
-                            if (line == null) {
-                                message.append(label);
-                                break;
-                            }
-                        } else {
-                            message.append(StringUtils.LINE_SEP);
-                        }
-                        first = false;
-                        message.append(label).append(line);
-                        line = r.readLine();
-                    } while (line != null);
+                try (BufferedReader r =
+                    new BufferedReader(new StringReader(event.getMessage()))) {
+                    message.append(r.lines()
+                        .collect(Collectors.joining(System.lineSeparator() + prefix, prefix, "")));
                 } catch (IOException e) {
                     // shouldn't be possible
                     message.append(label).append(event.getMessage());
-                } finally {
-                    FileUtils.close(r);
                 }
-
-            } else {
-                //emacs mode or there is no task
-                message.append(event.getMessage());
             }
             Throwable ex = event.getException();
             if (Project.MSG_DEBUG <= msgOutputLevel && ex != null) {
@@ -361,8 +337,7 @@
     protected String getTimestamp() {
         Date date = new Date(System.currentTimeMillis());
         DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
-        String finishTime = formatter.format(date);
-        return finishTime;
+        return formatter.format(date);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/DemuxInputStream.java b/src/main/org/apache/tools/ant/DemuxInputStream.java
index ea263ca..a978c7f 100644
--- a/src/main/org/apache/tools/ant/DemuxInputStream.java
+++ b/src/main/org/apache/tools/ant/DemuxInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,7 @@
 
 /**
  *
- * Passes input requests to the project object for demuxing into
+ * Passes input requests to the project object for demultiplexing into
  * individual tasks and threads.
  *
  * @since Ant 1.6
@@ -46,10 +46,11 @@
     }
 
     /**
-     * Read a byte from the project's demuxed input.
+     * Read a byte from the project's demultiplexed input.
      * @return the next byte
      * @throws IOException on error
      */
+    @Override
     public int read() throws IOException {
         byte[] buffer = new byte[1];
         if (project.demuxInput(buffer, 0, 1) == -1) {
@@ -60,13 +61,14 @@
 
 
     /**
-     * Read bytes from the project's demuxed input.
+     * Read bytes from the project's demultiplexed input.
      * @param buffer an array of bytes to read into
      * @param offset the offset in the array of bytes
      * @param length the number of bytes in the array
      * @return the number of bytes read
      * @throws IOException on error
      */
+    @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
         return project.demuxInput(buffer, offset, length);
     }
diff --git a/src/main/org/apache/tools/ant/DemuxOutputStream.java b/src/main/org/apache/tools/ant/DemuxOutputStream.java
index 9645ca7..648ed35 100644
--- a/src/main/org/apache/tools/ant/DemuxOutputStream.java
+++ b/src/main/org/apache/tools/ant/DemuxOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -64,7 +64,7 @@
     private static final int LF = 0x0a;
 
     /** Mapping from thread to buffer (Thread to BufferInfo). */
-    private WeakHashMap<Thread, BufferInfo> buffers = new WeakHashMap<Thread, BufferInfo>();
+    private WeakHashMap<Thread, BufferInfo> buffers = new WeakHashMap<>();
 
     /**
      * The project to send output to.
@@ -98,14 +98,12 @@
      */
     private BufferInfo getBufferInfo() {
         Thread current = Thread.currentThread();
-        BufferInfo bufferInfo = (BufferInfo) buffers.get(current);
-        if (bufferInfo == null) {
-            bufferInfo = new BufferInfo();
+        return buffers.computeIfAbsent(current, x -> {
+            BufferInfo bufferInfo = new BufferInfo();
             bufferInfo.buffer = new ByteArrayOutputStream(INITIAL_SIZE);
             bufferInfo.crSeen = false;
-            buffers.put(current, bufferInfo);
-        }
-        return bufferInfo;
+            return bufferInfo;
+        });
     }
 
     /**
@@ -113,7 +111,7 @@
      */
     private void resetBufferInfo() {
         Thread current = Thread.currentThread();
-        BufferInfo bufferInfo = (BufferInfo) buffers.get(current);
+        BufferInfo bufferInfo = buffers.get(current);
         FileUtils.close(bufferInfo.buffer);
         bufferInfo.buffer = new ByteArrayOutputStream();
         bufferInfo.crSeen = false;
@@ -134,6 +132,7 @@
      * @param cc data to log (byte).
      * @exception IOException if the data cannot be written to the stream
      */
+    @Override
     public void write(int cc) throws IOException {
         final byte c = (byte) cc;
 
@@ -192,6 +191,7 @@
      *
      * @see #flush
      */
+    @Override
     public void close() throws IOException {
         flush();
         removeBuffer();
@@ -203,6 +203,7 @@
      *
      * @exception IOException if there is a problem flushing the stream.
      */
+    @Override
     public void flush() throws IOException {
         BufferInfo bufferInfo = getBufferInfo();
         if (bufferInfo.buffer.size() > 0) {
@@ -219,6 +220,7 @@
      *
      * @throws IOException if the data cannot be written into the stream.
      */
+    @Override
     public void write(byte[] b, int off, int len) throws IOException {
         // find the line breaks and pass other chars through in blocks
         int offset = off;
diff --git a/src/main/org/apache/tools/ant/Diagnostics.java b/src/main/org/apache/tools/ant/Diagnostics.java
index 424a0d2..9333a57 100644
--- a/src/main/org/apache/tools/ant/Diagnostics.java
+++ b/src/main/org/apache/tools/ant/Diagnostics.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,17 +18,15 @@
 package org.apache.tools.ant;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.Calendar;
-import java.util.Enumeration;
 import java.util.Properties;
 import java.util.TimeZone;
 
@@ -42,6 +40,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;
 
 /**
@@ -53,9 +52,6 @@
  */
 public final class Diagnostics {
 
-    /** the version number for java 1.5 returned from JavaEnvUtils */
-    private static final int JAVA_1_5_NUMBER = 15;
-
     /**
      * value for which a difference between clock and temp file time triggers
      * a warning.
@@ -88,7 +84,7 @@
     /**
      * Doesn't do anything.
      * @deprecated Obsolete since Ant 1.8.2
-     * @return <tt>true</tt>
+     * @return <code>true</code>
      */
     @Deprecated
     public static boolean isOptionalAvailable() {
@@ -107,15 +103,14 @@
      * return the list of jar files existing in ANT_HOME/lib
      * and that must have been picked up by Ant script.
      * @return the list of jar files existing in ant.home/lib or
-     * <tt>null</tt> if an error occurs.
+     * <code>null</code> if an error occurs.
      */
     public static File[] listLibraries() {
         String home = System.getProperty(MagicNames.ANT_HOME);
         if (home == null) {
             return null;
         }
-        File libDir = new File(home, "lib");
-        return listJarFiles(libDir);
+        return listJarFiles(new File(home, "lib"));
 
     }
 
@@ -125,13 +120,7 @@
      * @return array of files (or null for no such directory)
      */
     private static File[] listJarFiles(File libDir) {
-        FilenameFilter filter = new FilenameFilter() {
-            public boolean accept(File dir, String name) {
-                return name.endsWith(".jar");
-            }
-        };
-        File[] files  = libDir.listFiles(filter);
-        return files;
+        return libDir.listFiles((dir, name) -> name.endsWith(".jar"));
     }
 
     /**
@@ -174,8 +163,7 @@
             return "Could not create an XML Parser";
         }
         // check to what is in the classname
-        String saxParserName = saxParser.getClass().getName();
-        return saxParserName;
+        return saxParser.getClass().getName();
     }
 
     /**
@@ -188,8 +176,7 @@
             return "Could not create an XSLT Processor";
         }
         // check to what is in the classname
-        String processorName = transformer.getClass().getName();
-        return processorName;
+        return transformer.getClass().getName();
     }
 
     /**
@@ -221,17 +208,15 @@
      */
     private static Transformer getXSLTProcessor() {
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
-        if (transformerFactory == null) {
-            return null;
+        if (transformerFactory != null) {
+            try {
+                return transformerFactory.newTransformer();
+            } catch (Exception e) {
+                // ignore
+                ignoreThrowable(e);
+            }
         }
-        Transformer transformer = null;
-        try {
-            transformer = transformerFactory.newTransformer();
-        } catch (Exception e) {
-            // ignore
-            ignoreThrowable(e);
-        }
-        return transformer;
+        return null;
     }
 
     /**
@@ -371,12 +356,8 @@
             out.println("Access to System.getProperties() blocked " + "by a security manager");
             return;
         }
-        for (Enumeration<?> keys = sysprops.propertyNames();
-            keys.hasMoreElements();) {
-            String key = (String) keys.nextElement();
-            String value = getProperty(key);
-            out.println(key + " : " + value);
-        }
+        sysprops.stringPropertyNames().stream()
+                .map(key -> key + " : " + getProperty(key)).forEach(out::println);
     }
 
     /**
@@ -463,11 +444,11 @@
         try {
             Class<?> which = Class.forName("org.apache.env.Which");
             Method method = which.getMethod(
-                "main", new Class[] {String[].class});
+                "main", String[].class);
             method.invoke(null, new Object[]{new String[]{}});
         } catch (ClassNotFoundException e) {
             out.println("Not available.");
-            out.println("Download it at http://xml.apache.org/commons/");
+            out.println("Download it at https://xml.apache.org/commons/");
         } catch (InvocationTargetException e) {
             error = e.getTargetException() == null ? e : e.getTargetException();
         } catch (Throwable e) {
@@ -486,7 +467,7 @@
      * because Ant requires multiple libraries to compile and one of them
      * was missing when compiling Ant.
      * @param out the stream to print the tasks report to
-     * <tt>null</tt> for a missing stream (ie mapping).
+     * <code>null</code> for a missing stream (ie mapping).
      */
     private static void doReportTasksAvailability(PrintStream out) {
         InputStream is = Main.class.getResourceAsStream(
@@ -497,8 +478,7 @@
             Properties props = new Properties();
             try {
                 props.load(is);
-                for (Enumeration<?> keys = props.keys(); keys.hasMoreElements();) {
-                    String key = (String) keys.nextElement();
+                for (String key : props.stringPropertyNames()) {
                     String classname = props.getProperty(key);
                     try {
                         Class.forName(classname);
@@ -580,12 +560,12 @@
         //create the file
         long now = System.currentTimeMillis();
         File tempFile = null;
-        FileOutputStream fileout = null;
-        FileInputStream filein = null;
+        OutputStream fileout = null;
+        InputStream filein = null;
         try {
             tempFile = File.createTempFile("diag", "txt", tempDirectory);
             //do some writing to it
-            fileout = new FileOutputStream(tempFile);
+            fileout = Files.newOutputStream(tempFile.toPath());
             byte[] buffer = new byte[KILOBYTE];
             for (int i = 0; i < TEST_FILE_SIZE; i++) {
                 fileout.write(buffer);
@@ -595,7 +575,7 @@
 
             // read to make sure the file has been written completely
             Thread.sleep(1000);
-            filein = new FileInputStream(tempFile);
+            filein = Files.newInputStream(tempFile.toPath());
             int total = 0;
             int read = 0;
             while ((read = filein.read(buffer, 0, KILOBYTE)) > 0) {
@@ -696,25 +676,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/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java
index a0e7837..b7f6479 100644
--- a/src/main/org/apache/tools/ant/DirectoryScanner.java
+++ b/src/main/org/apache/tools/ant/DirectoryScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,15 +20,22 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.apache.tools.ant.types.Resource;
@@ -39,9 +46,7 @@
 import org.apache.tools.ant.types.selectors.SelectorUtils;
 import org.apache.tools.ant.types.selectors.TokenizedPath;
 import org.apache.tools.ant.types.selectors.TokenizedPattern;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.SymbolicLinkUtils;
 import org.apache.tools.ant.util.VectorSet;
 
 /**
@@ -224,16 +229,12 @@
     /** Helper. */
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-    /** Helper. */
-    private static final SymbolicLinkUtils SYMLINK_UTILS =
-        SymbolicLinkUtils.getSymbolicLinkUtils();
-
     /**
      * Patterns which should be excluded by default.
      *
      * @see #addDefaultExcludes()
      */
-    private static final Set<String> defaultExcludes = new HashSet<String>();
+    private static final Set<String> defaultExcludes = new HashSet<>();
     static {
         resetDefaultExcludes();
     }
@@ -326,7 +327,7 @@
      *
      * @since Ant 1.6
      */
-    private final Set<String> scannedDirs = new HashSet<String>();
+    private final Set<String> scannedDirs = new HashSet<>();
 
     /**
      * Map of all include patterns that are full file names and don't
@@ -343,7 +344,7 @@
      *
      * @since Ant 1.8.0
      */
-    private final Map<String, TokenizedPath> includeNonPatterns = new HashMap<String, TokenizedPath>();
+    private final Map<String, TokenizedPath> includeNonPatterns = new HashMap<>();
 
     /**
      * Map of all exclude patterns that are full file names and don't
@@ -360,7 +361,7 @@
      *
      * @since Ant 1.8.0
      */
-    private final Map<String, TokenizedPath> excludeNonPatterns = new HashMap<String, TokenizedPath>();
+    private final Map<String, TokenizedPath> excludeNonPatterns = new HashMap<>();
 
     /**
      * Array of all include patterns that contain wildcards.
@@ -439,13 +440,7 @@
      *
      * @since Ant 1.8.0
      */
-    private final Set<String> notFollowedSymlinks = new HashSet<String>();
-
-    /**
-     * Sole constructor.
-     */
-    public DirectoryScanner() {
-    }
+    private final Set<String> notFollowedSymlinks = new HashSet<>();
 
     /**
      * Test whether or not a given path matches the start of a given
@@ -575,8 +570,7 @@
      */
     public static String[] getDefaultExcludes() {
         synchronized (defaultExcludes) {
-            return defaultExcludes.toArray(new String[defaultExcludes
-                                                                 .size()]);
+            return defaultExcludes.toArray(new String[0]);
         }
     }
 
@@ -621,9 +615,7 @@
     public static void resetDefaultExcludes() {
         synchronized (defaultExcludes) {
             defaultExcludes.clear();
-            for (int i = 0; i < DEFAULTEXCLUDES.length; i++) {
-                defaultExcludes.add(DEFAULTEXCLUDES[i]);
-            }
+            Collections.addAll(defaultExcludes, DEFAULTEXCLUDES);
         }
     }
 
@@ -635,8 +627,9 @@
      *
      * @param basedir The base directory to scan.
      */
+    @Override
     public void setBasedir(final String basedir) {
-        setBasedir(basedir == null ? (File) null
+        setBasedir(basedir == null ? null
             : new File(basedir.replace('/', File.separatorChar).replace(
             '\\', File.separatorChar)));
     }
@@ -647,6 +640,7 @@
      *
      * @param basedir The base directory for scanning.
      */
+    @Override
     public synchronized void setBasedir(final File basedir) {
         this.basedir = basedir;
     }
@@ -657,6 +651,7 @@
      *
      * @return the base directory to be scanned.
      */
+    @Override
     public synchronized File getBasedir() {
         return basedir;
     }
@@ -678,6 +673,7 @@
      * @param isCaseSensitive whether or not the file system should be
      *                        regarded as a case sensitive one.
      */
+    @Override
     public synchronized void setCaseSensitive(final boolean isCaseSensitive) {
         this.isCaseSensitive = isCaseSensitive;
     }
@@ -737,14 +733,13 @@
      *                 list is given, all elements must be
      *                 non-<code>null</code>.
      */
+    @Override
     public synchronized void setIncludes(final String[] includes) {
         if (includes == null) {
             this.includes = null;
         } else {
-            this.includes = new String[includes.length];
-            for (int i = 0; i < includes.length; i++) {
-                this.includes[i] = normalizePattern(includes[i]);
-            }
+            this.includes = Stream.of(includes)
+                .map(DirectoryScanner::normalizePattern).toArray(String[]::new);
         }
     }
 
@@ -760,14 +755,13 @@
      *                 should be excluded. If a non-<code>null</code> list is
      *                 given, all elements must be non-<code>null</code>.
      */
+    @Override
     public synchronized void setExcludes(final String[] excludes) {
         if (excludes == null) {
             this.excludes = null;
         } else {
-            this.excludes = new String[excludes.length];
-            for (int i = 0; i < excludes.length; i++) {
-                this.excludes[i] = normalizePattern(excludes[i]);
-            }
+            this.excludes = Stream.of(excludes).map(DirectoryScanner::normalizePattern)
+                    .toArray(String[]::new);
         }
     }
 
@@ -786,17 +780,12 @@
      */
     public synchronized void addExcludes(final String[] excludes) {
         if (excludes != null && excludes.length > 0) {
-            if (this.excludes != null && this.excludes.length > 0) {
-                final String[] tmp = new String[excludes.length
-                                          + this.excludes.length];
-                System.arraycopy(this.excludes, 0, tmp, 0,
-                                 this.excludes.length);
-                for (int i = 0; i < excludes.length; i++) {
-                    tmp[this.excludes.length + i] = normalizePattern(excludes[i]);
-                }
-                this.excludes = tmp;
-            } else {
+            if (this.excludes == null || this.excludes.length == 0) {
                 setExcludes(excludes);
+            } else {
+                this.excludes = Stream.concat(Stream.of(this.excludes),
+                        Stream.of(excludes).map(DirectoryScanner::normalizePattern))
+                        .toArray(String[]::new);
             }
         }
     }
@@ -824,6 +813,7 @@
      *
      * @param selectors specifies the selectors to be invoked on a scan.
      */
+    @Override
     public synchronized void setSelectors(final FileSelector[] selectors) {
         this.selectors = selectors;
     }
@@ -849,6 +839,7 @@
      * @exception IllegalStateException if the base directory was set
      *            incorrectly (i.e. if it doesn't exist or isn't a directory).
      */
+    @Override
     public void scan() throws IllegalStateException {
         synchronized (scanLock) {
             if (scanning) {
@@ -872,13 +863,13 @@
                 clearResults();
 
                 // set in/excludes to reasonable defaults if needed:
-                final boolean nullIncludes = (includes == null);
+                final boolean nullIncludes = includes == null;
                 includes = nullIncludes ? new String[] {SelectorUtils.DEEP_TREE_MATCH} : includes;
-                final boolean nullExcludes = (excludes == null);
+                final boolean nullExcludes = excludes == null;
                 excludes = nullExcludes ? new String[0] : excludes;
 
                 if (basedir != null && !followSymlinks
-                    && SYMLINK_UTILS.isSymbolicLink(basedir)) {
+                    && Files.isSymbolicLink(basedir.toPath())) {
                     notFollowedSymlinks.add(basedir.getAbsolutePath());
                     basedir = null;
                 }
@@ -901,22 +892,19 @@
                     } else if (!basedir.isDirectory()) {
                         illegal = new IllegalStateException("basedir "
                                                             + basedir
-                                                            + " is not a"
-                                                            + " directory.");
+                                                            + " is not a directory.");
                     }
                     if (illegal != null) {
                         throw illegal;
                     }
                 }
                 if (isIncluded(TokenizedPath.EMPTY_PATH)) {
-                    if (!isExcluded(TokenizedPath.EMPTY_PATH)) {
-                        if (isSelected("", basedir)) {
-                            dirsIncluded.addElement("");
-                        } else {
-                            dirsDeselected.addElement("");
-                        }
-                    } else {
+                    if (isExcluded(TokenizedPath.EMPTY_PATH)) {
                         dirsExcluded.addElement("");
+                    } else if (isSelected("", basedir)) {
+                        dirsIncluded.addElement("");
+                    } else {
+                        dirsDeselected.addElement("");
                     }
                 } else {
                     dirsNotIncluded.addElement("");
@@ -926,8 +914,6 @@
                 includes = nullIncludes ? null : includes;
                 excludes = nullExcludes ? null : excludes;
             }
-        } catch (final IOException ex) {
-            throw new BuildException(ex);
         } finally {
             basedir = savedBase;
             synchronized (scanLock) {
@@ -944,17 +930,18 @@
      */
     private void checkIncludePatterns() {
         ensureNonPatternSetsReady();
-        final Map<TokenizedPath, String> newroots = new HashMap<TokenizedPath, String>();
+        final Map<TokenizedPath, String> newroots = new HashMap<>();
 
         // put in the newroots map the include patterns without
         // wildcard tokens
-        for (int i = 0; i < includePatterns.length; i++) {
-            final String pattern = includePatterns[i].toString();
+        for (TokenizedPattern includePattern : includePatterns) {
+            final String pattern = includePattern.toString();
             if (!shouldSkipPattern(pattern)) {
-                newroots.put(includePatterns[i].rtrimWildcardTokens(), pattern);
+                newroots.put(includePattern.rtrimWildcardTokens(), pattern);
             }
         }
-        for (final Map.Entry<String, TokenizedPath> entry : includeNonPatterns.entrySet()) {
+        for (final Map.Entry<String, TokenizedPath> entry : includeNonPatterns
+            .entrySet()) {
             final String pattern = entry.getKey();
             if (!shouldSkipPattern(pattern)) {
                 newroots.put(entry.getValue(), pattern);
@@ -1027,8 +1014,7 @@
                         continue;
                     }
                     if (myfile.isDirectory()) {
-                        if (isIncluded(currentPath)
-                            && currentelement.length() > 0) {
+                        if (isIncluded(currentPath) && !currentelement.isEmpty()) {
                             accountForIncludedDir(currentPath, myfile, true);
                         }  else {
                             scandir(myfile, currentPath, true);
@@ -1056,31 +1042,25 @@
     private boolean shouldSkipPattern(final String pattern) {
         if (FileUtils.isAbsolutePath(pattern)) {
             //skip abs. paths not under basedir, if set:
-            if (basedir != null
-                && !SelectorUtils.matchPatternStart(pattern,
-                                                    basedir.getAbsolutePath(),
-                                                    isCaseSensitive())) {
-                return true;
-            }
-        } else if (basedir == null) {
-            //skip non-abs. paths if basedir == null:
-            return true;
+            return !(basedir == null || SelectorUtils.matchPatternStart(pattern,
+                    basedir.getAbsolutePath(), isCaseSensitive()));
         }
-        return false;
+
+        return basedir == null;
     }
 
     /**
      * Clear the result caches for a scan.
      */
     protected synchronized void clearResults() {
-        filesIncluded    = new VectorSet<String>();
-        filesNotIncluded = new VectorSet<String>();
-        filesExcluded    = new VectorSet<String>();
-        filesDeselected  = new VectorSet<String>();
-        dirsIncluded     = new VectorSet<String>();
-        dirsNotIncluded  = new VectorSet<String>();
-        dirsExcluded     = new VectorSet<String>();
-        dirsDeselected   = new VectorSet<String>();
+        filesIncluded    = new VectorSet<>();
+        filesNotIncluded = new VectorSet<>();
+        filesExcluded    = new VectorSet<>();
+        filesDeselected  = new VectorSet<>();
+        dirsIncluded     = new VectorSet<>();
+        dirsNotIncluded  = new VectorSet<>();
+        dirsExcluded     = new VectorSet<>();
+        dirsDeselected   = new VectorSet<>();
         everythingIncluded = (basedir != null);
         scannedDirs.clear();
         notFollowedSymlinks.clear();
@@ -1144,14 +1124,18 @@
     }
 
     private void processSlowScan(final String[] arr) {
-        for (int i = 0; i < arr.length; i++) {
-            final TokenizedPath path  = new TokenizedPath(arr[i]);
-            if (!couldHoldIncluded(path) || contentsExcluded(path)) {
-                scandir(new File(basedir, arr[i]), path, false);
+        for (String element : arr) {
+            final TokenizedPath path  = new TokenizedPath(element);
+            if (!scanDuringFastScan(path)) {
+                scandir(new File(basedir, element), path, false);
             }
         }
     }
 
+    private boolean scanDuringFastScan(TokenizedPath path) {
+        return couldHoldIncluded(path) && !contentsExcluded(path);
+    }
+
     /**
      * Scan the given directory for files and directories. Found files and
      * directories are placed in their respective collections, based on the
@@ -1205,19 +1189,19 @@
             if (!dir.exists()) {
                 throw new BuildException(dir + DOES_NOT_EXIST_POSTFIX);
             } else if (!dir.isDirectory()) {
-                throw new BuildException(dir + " is not a directory.");
+                throw new BuildException("%s is not a directory.", dir);
             } else {
-                throw new BuildException("IO error scanning directory '"
-                                         + dir.getAbsolutePath() + "'");
+                throw new BuildException("IO error scanning directory '%s'",
+                    dir.getAbsolutePath());
             }
         }
-        scandir(dir, path, fast, newfiles, new LinkedList<String>());
+        scandir(dir, path, fast, newfiles, new LinkedList<>());
     }
 
     private void scandir(final File dir, final TokenizedPath path, final boolean fast,
-                         String[] newFiles, final LinkedList<String> directoryNamesFollowed) {
+                         String[] newFiles, final Deque<String> directoryNamesFollowed) {
         String vpath = path.toString();
-        if (vpath.length() > 0 && !vpath.endsWith(File.separator)) {
+        if (!vpath.isEmpty() && !vpath.endsWith(File.separator)) {
             vpath += File.separator;
         }
 
@@ -1226,30 +1210,28 @@
             return;
         }
         if (!followSymlinks) {
-            final ArrayList<String> noLinks = new ArrayList<String>();
+            final ArrayList<String> noLinks = new ArrayList<>();
             for (final String newFile : newFiles) {
-                try {
-                    if (SYMLINK_UTILS.isSymbolicLink(dir, newFile)) {
-                        final String name = vpath + newFile;
-                        final File file = new File(dir, newFile);
-                        if (file.isDirectory()) {
-                            dirsExcluded.addElement(name);
-                        } else if (file.isFile()) {
-                            filesExcluded.addElement(name);
-                        }
-                        accountForNotFollowedSymlink(name, file);
-                    } else {
-                        noLinks.add(newFile);
+                final Path filePath;
+                if (dir == null) {
+                    filePath = Paths.get(newFile);
+                } else {
+                    filePath = Paths.get(dir.toPath().toString(), newFile);
+                }
+                if (Files.isSymbolicLink(filePath)) {
+                    final String name = vpath + newFile;
+                    final File file = new File(dir, newFile);
+                    if (file.isDirectory()) {
+                        dirsExcluded.addElement(name);
+                    } else if (file.isFile()) {
+                        filesExcluded.addElement(name);
                     }
-                } catch (final IOException ioe) {
-                    final String msg = "IOException caught while checking "
-                        + "for links, couldn't get canonical path!";
-                    // will be caught and redirected to Ant's logging system
-                    System.err.println(msg);
+                    accountForNotFollowedSymlink(name, file);
+                } else {
                     noLinks.add(newFile);
                 }
             }
-            newFiles = (noLinks.toArray(new String[noLinks.size()]));
+            newFiles = noLinks.toArray(new String[0]);
         } else {
             directoryNamesFollowed.addFirst(dir.getName());
         }
@@ -1258,7 +1240,18 @@
             final String name = vpath + newFile;
             final TokenizedPath newPath = new TokenizedPath(path, newFile);
             final File file = new File(dir, newFile);
-            final String[] children = file.list();
+            final String[] children;
+
+            // don't invoke file.list() if we know we never use the children
+            if (fast // slow scan scans everything anyway
+                && file.isDirectory() // otherwise we need list() to know whether this is a directory
+                && !scanDuringFastScan(newPath) // otherwise we'd invoke scandir
+                ) {
+                children = new String[0];
+            } else {
+                children = file.list();
+            }
+
             if (children == null || (children.length == 0 && file.isFile())) {
                 if (isIncluded(newPath)) {
                     accountForIncludedFile(newPath, file);
@@ -1285,7 +1278,7 @@
                 } else {
                     everythingIncluded = false;
                     dirsNotIncluded.addElement(name);
-                    if (fast && couldHoldIncluded(newPath) && !contentsExcluded(newPath)) {
+                    if (fast && scanDuringFastScan(newPath)) {
                         scandir(file, newPath, fast, children, directoryNamesFollowed);
                     }
                 }
@@ -1320,7 +1313,7 @@
     private void accountForIncludedDir(final TokenizedPath name, final File file,
                                        final boolean fast) {
         processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
-        if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) {
+        if (fast && scanDuringFastScan(name)) {
             scandir(file, name, fast);
         }
     }
@@ -1328,9 +1321,9 @@
     private void accountForIncludedDir(final TokenizedPath name,
                                        final File file, final boolean fast,
                                        final String[] children,
-                                       final LinkedList<String> directoryNamesFollowed) {
+                                       final Deque<String> directoryNamesFollowed) {
         processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
-        if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) {
+        if (fast && scanDuringFastScan(name)) {
             scandir(file, name, fast, children, directoryNamesFollowed);
         }
     }
@@ -1341,19 +1334,18 @@
 
     private void accountForNotFollowedSymlink(final TokenizedPath name, final File file) {
         if (!isExcluded(name) && (isIncluded(name)
-                || (file.isDirectory() && couldHoldIncluded(name) && !contentsExcluded(name)))) {
+                || (file.isDirectory() && scanDuringFastScan(name)))) {
             notFollowedSymlinks.add(file.getAbsolutePath());
         }
     }
 
     private void processIncluded(final TokenizedPath path,
-                                 final File file, final Vector<String> inc, final Vector<String> exc,
-                                 final Vector<String> des) {
+                                 final File file, final List<String> inc, final List<String> exc,
+                                 final List<String> des) {
         final String name = path.toString();
         if (inc.contains(name) || exc.contains(name) || des.contains(name)) {
             return;
         }
-
         boolean included = false;
         if (isExcluded(path)) {
             exc.add(name);
@@ -1389,17 +1381,12 @@
     private boolean isIncluded(final TokenizedPath path) {
         ensureNonPatternSetsReady();
 
-        if (isCaseSensitive()
-            ? includeNonPatterns.containsKey(path.toString())
-            : includeNonPatterns.containsKey(path.toString().toUpperCase())) {
-            return true;
+        String toMatch = path.toString();
+        if (!isCaseSensitive()) {
+            toMatch = toMatch.toUpperCase();
         }
-        for (int i = 0; i < includePatterns.length; i++) {
-            if (includePatterns[i].matchPath(path, isCaseSensitive())) {
-                return true;
-            }
-        }
-        return false;
+        return includeNonPatterns.containsKey(toMatch)
+            || Stream.of(includePatterns).anyMatch(p -> p.matchPath(path, isCaseSensitive()));
     }
 
     /**
@@ -1423,19 +1410,9 @@
      *         least one include pattern, or <code>false</code> otherwise.
      */
     private boolean couldHoldIncluded(final TokenizedPath tokenizedName) {
-        for (int i = 0; i < includePatterns.length; i++) {
-            if (couldHoldIncluded(tokenizedName, includePatterns[i])) {
-                return true;
-            }
-        }
-        for (final Iterator<TokenizedPath> iter = includeNonPatterns.values().iterator();
-             iter.hasNext();) {
-            if (couldHoldIncluded(tokenizedName,
-                                  iter.next().toPattern())) {
-                return true;
-            }
-        }
-        return false;
+        return Stream.concat(Stream.of(includePatterns),
+                includeNonPatterns.values().stream().map(TokenizedPath::toPattern))
+                .anyMatch(pat -> couldHoldIncluded(tokenizedName, pat));
     }
 
     /**
@@ -1484,12 +1461,8 @@
      */
     private boolean isMorePowerfulThanExcludes(final String name) {
         final String soughtexclude = name + File.separatorChar + SelectorUtils.DEEP_TREE_MATCH;
-        for (int counter = 0; counter < excludePatterns.length; counter++) {
-            if (excludePatterns[counter].toString().equals(soughtexclude))  {
-                return false;
-            }
-        }
-        return true;
+        return Stream.of(excludePatterns).map(Object::toString)
+            .noneMatch(Predicate.isEqual(soughtexclude));
     }
 
     /**
@@ -1498,14 +1471,10 @@
      * @return whether all the specified directory's contents are excluded.
      */
     /* package */ boolean contentsExcluded(final TokenizedPath path) {
-        for (int i = 0; i < excludePatterns.length; i++) {
-            if (excludePatterns[i].endsWith(SelectorUtils.DEEP_TREE_MATCH)
-                && excludePatterns[i].withoutLastToken()
-                   .matchPath(path, isCaseSensitive())) {
-                return true;
-            }
-        }
-        return false;
+        return Stream.of(excludePatterns)
+            .filter(p -> p.endsWith(SelectorUtils.DEEP_TREE_MATCH))
+            .map(TokenizedPattern::withoutLastToken)
+            .anyMatch(wlt -> wlt.matchPath(path, isCaseSensitive()));
     }
 
     /**
@@ -1531,17 +1500,12 @@
     private boolean isExcluded(final TokenizedPath name) {
         ensureNonPatternSetsReady();
 
-        if (isCaseSensitive()
-            ? excludeNonPatterns.containsKey(name.toString())
-            : excludeNonPatterns.containsKey(name.toString().toUpperCase())) {
-            return true;
+        String toMatch = name.toString();
+        if (!isCaseSensitive()) {
+            toMatch = toMatch.toUpperCase();
         }
-        for (int i = 0; i < excludePatterns.length; i++) {
-            if (excludePatterns[i].matchPath(name, isCaseSensitive())) {
-                return true;
-            }
-        }
-        return false;
+        return excludeNonPatterns.containsKey(toMatch)
+            || Stream.of(excludePatterns).anyMatch(p -> p.matchPath(name, isCaseSensitive()));
     }
 
     /**
@@ -1553,14 +1517,8 @@
      *         should not be selected, <code>true</code> otherwise.
      */
     protected boolean isSelected(final String name, final File file) {
-        if (selectors != null) {
-            for (int i = 0; i < selectors.length; i++) {
-                if (!selectors[i].isSelected(basedir, name, file)) {
-                    return false;
-                }
-            }
-        }
-        return true;
+        return selectors == null
+                || Stream.of(selectors).allMatch(sel -> sel.isSelected(basedir, name, file));
     }
 
     /**
@@ -1571,14 +1529,14 @@
      * @return the names of the files which matched at least one of the
      *         include patterns and none of the exclude patterns.
      */
+    @Override
     public String[] getIncludedFiles() {
         String[] files;
         synchronized (this) {
             if (filesIncluded == null) {
                 throw new IllegalStateException("Must call scan() first");
             }
-            files = new String[filesIncluded.size()];
-            filesIncluded.copyInto(files);
+            files = filesIncluded.toArray(new String[0]);
         }
         Arrays.sort(files);
         return files;
@@ -1606,11 +1564,10 @@
      *
      * @see #slowScan
      */
+    @Override
     public synchronized String[] getNotIncludedFiles() {
         slowScan();
-        final String[] files = new String[filesNotIncluded.size()];
-        filesNotIncluded.copyInto(files);
-        return files;
+        return filesNotIncluded.toArray(new String[0]);
     }
 
     /**
@@ -1624,11 +1581,10 @@
      *
      * @see #slowScan
      */
+    @Override
     public synchronized String[] getExcludedFiles() {
         slowScan();
-        final String[] files = new String[filesExcluded.size()];
-        filesExcluded.copyInto(files);
-        return files;
+        return filesExcluded.toArray(new String[0]);
     }
 
     /**
@@ -1642,11 +1598,10 @@
      *
      * @see #slowScan
      */
+    @Override
     public synchronized String[] getDeselectedFiles() {
         slowScan();
-        final String[] files = new String[filesDeselected.size()];
-        filesDeselected.copyInto(files);
-        return files;
+        return filesDeselected.toArray(new String[0]);
     }
 
     /**
@@ -1657,14 +1612,14 @@
      * @return the names of the directories which matched at least one of the
      * include patterns and none of the exclude patterns.
      */
+    @Override
     public String[] getIncludedDirectories() {
         String[] directories;
         synchronized (this) {
             if (dirsIncluded == null) {
                 throw new IllegalStateException("Must call scan() first");
             }
-            directories = new String[dirsIncluded.size()];
-            dirsIncluded.copyInto(directories);
+            directories = dirsIncluded.toArray(new String[0]);
         }
         Arrays.sort(directories);
         return directories;
@@ -1692,11 +1647,10 @@
      *
      * @see #slowScan
      */
+    @Override
     public synchronized String[] getNotIncludedDirectories() {
         slowScan();
-        final String[] directories = new String[dirsNotIncluded.size()];
-        dirsNotIncluded.copyInto(directories);
-        return directories;
+        return dirsNotIncluded.toArray(new String[0]);
     }
 
     /**
@@ -1710,11 +1664,10 @@
      *
      * @see #slowScan
      */
+    @Override
     public synchronized String[] getExcludedDirectories() {
         slowScan();
-        final String[] directories = new String[dirsExcluded.size()];
-        dirsExcluded.copyInto(directories);
-        return directories;
+        return dirsExcluded.toArray(new String[0]);
     }
 
     /**
@@ -1728,11 +1681,10 @@
      *
      * @see #slowScan
      */
+    @Override
     public synchronized String[] getDeselectedDirectories() {
         slowScan();
-        final String[] directories = new String[dirsDeselected.size()];
-        dirsDeselected.copyInto(directories);
-        return directories;
+        return dirsDeselected.toArray(new String[0]);
     }
 
     /**
@@ -1747,7 +1699,7 @@
     public synchronized String[] getNotFollowedSymlinks() {
         String[] links;
         synchronized (this) {
-            links = notFollowedSymlinks.toArray(new String[notFollowedSymlinks.size()]);
+            links = notFollowedSymlinks.toArray(new String[0]);
         }
         Arrays.sort(links);
         return links;
@@ -1756,20 +1708,14 @@
     /**
      * Add default exclusions to the current exclusions set.
      */
+    @Override
     public synchronized void addDefaultExcludes() {
-        final int excludesLength = excludes == null ? 0 : excludes.length;
-        String[] newExcludes;
-        final String[] defaultExcludesTemp = getDefaultExcludes();
-        newExcludes = new String[excludesLength + defaultExcludesTemp.length];
-        if (excludesLength > 0) {
-            System.arraycopy(excludes, 0, newExcludes, 0, excludesLength);
+        Stream<String> s = Stream.of(getDefaultExcludes()).map(p -> p.replace('/',
+                File.separatorChar).replace('\\', File.separatorChar));
+        if (excludes != null) {
+            s = Stream.concat(Stream.of(excludes), s);
         }
-        for (int i = 0; i < defaultExcludesTemp.length; i++) {
-            newExcludes[i + excludesLength] =
-                defaultExcludesTemp[i].replace('/', File.separatorChar)
-                .replace('\\', File.separatorChar);
-        }
-        excludes = newExcludes;
+        excludes = s.toArray(String[]::new);
     }
 
     /**
@@ -1779,6 +1725,7 @@
      * @return the resource with the given name.
      * @since Ant 1.5.2
      */
+    @Override
     public synchronized Resource getResource(final String name) {
         return new FileResource(basedir, name);
     }
@@ -1841,16 +1788,16 @@
      */
     private TokenizedPattern[] fillNonPatternSet(final Map<String, TokenizedPath> map,
                                                  final String[] patterns) {
-        final ArrayList<TokenizedPattern> al = new ArrayList<TokenizedPattern>(patterns.length);
-        for (int i = 0; i < patterns.length; i++) {
-            if (!SelectorUtils.hasWildcards(patterns[i])) {
-                final String s = isCaseSensitive() ? patterns[i] : patterns[i].toUpperCase();
-                map.put(s, new TokenizedPath(s));
+        final List<TokenizedPattern> al = new ArrayList<>(patterns.length);
+        for (String pattern : patterns) {
+            if (SelectorUtils.hasWildcards(pattern)) {
+                al.add(new TokenizedPattern(pattern));
             } else {
-                al.add(new TokenizedPattern(patterns[i]));
+                final String s = isCaseSensitive() ? pattern : pattern.toUpperCase();
+                map.put(s, new TokenizedPath(s));
             }
         }
-        return al.toArray(new TokenizedPattern[al.size()]);
+        return al.toArray(new TokenizedPattern[0]);
     }
 
     /**
@@ -1865,35 +1812,40 @@
      * @since Ant 1.8.0
      */
     private boolean causesIllegalSymlinkLoop(final String dirName, final File parent,
-                                             final LinkedList<String> directoryNamesFollowed) {
+                                             final Deque<String> directoryNamesFollowed) {
         try {
+            final Path dirPath;
+            if (parent == null) {
+                dirPath = Paths.get(dirName);
+            } else {
+                dirPath = Paths.get(parent.toPath().toString(), dirName);
+            }
             if (directoryNamesFollowed.size() >= maxLevelsOfSymlinks
-                && CollectionUtils.frequency(directoryNamesFollowed, dirName) >= maxLevelsOfSymlinks
-                && SYMLINK_UTILS.isSymbolicLink(parent, dirName)) {
+                && Collections.frequency(directoryNamesFollowed, dirName) >= maxLevelsOfSymlinks
+                && Files.isSymbolicLink(dirPath)) {
 
-                final ArrayList<String> files = new ArrayList<String>();
+                final List<String> files = new ArrayList<>();
                 File f = FILE_UTILS.resolveFile(parent, dirName);
                 final String target = f.getCanonicalPath();
                 files.add(target);
 
-                String relPath = "";
+                StringBuilder relPath = new StringBuilder();
                 for (final String dir : directoryNamesFollowed) {
-                    relPath += "../";
+                    relPath.append("../");
                     if (dirName.equals(dir)) {
                         f = FILE_UTILS.resolveFile(parent, relPath + dir);
                         files.add(f.getCanonicalPath());
                         if (files.size() > maxLevelsOfSymlinks
-                            && CollectionUtils.frequency(files, target) > maxLevelsOfSymlinks) {
+                            && Collections.frequency(files, target) > maxLevelsOfSymlinks) {
                             return true;
                         }
                     }
                 }
-
             }
             return false;
         } catch (final IOException ex) {
-            throw new BuildException("Caught error while checking for"
-                                     + " symbolic links", ex);
+            throw new BuildException(
+                "Caught error while checking for symbolic links", ex);
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/DynamicAttribute.java b/src/main/org/apache/tools/ant/DynamicAttribute.java
index 445c33e..79ee178 100644
--- a/src/main/org/apache/tools/ant/DynamicAttribute.java
+++ b/src/main/org/apache/tools/ant/DynamicAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/DynamicAttributeNS.java b/src/main/org/apache/tools/ant/DynamicAttributeNS.java
index 7d6e84e..e2f655f 100644
--- a/src/main/org/apache/tools/ant/DynamicAttributeNS.java
+++ b/src/main/org/apache/tools/ant/DynamicAttributeNS.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/DynamicConfigurator.java b/src/main/org/apache/tools/ant/DynamicConfigurator.java
index e48062b..0494c0b 100644
--- a/src/main/org/apache/tools/ant/DynamicConfigurator.java
+++ b/src/main/org/apache/tools/ant/DynamicConfigurator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,4 +26,3 @@
 public interface DynamicConfigurator
     extends DynamicAttribute, DynamicElement {
 }
-
diff --git a/src/main/org/apache/tools/ant/DynamicConfiguratorNS.java b/src/main/org/apache/tools/ant/DynamicConfiguratorNS.java
index 40b3d65..f635d28 100644
--- a/src/main/org/apache/tools/ant/DynamicConfiguratorNS.java
+++ b/src/main/org/apache/tools/ant/DynamicConfiguratorNS.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/DynamicElement.java b/src/main/org/apache/tools/ant/DynamicElement.java
index b9caf0c..e288a5f 100644
--- a/src/main/org/apache/tools/ant/DynamicElement.java
+++ b/src/main/org/apache/tools/ant/DynamicElement.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/DynamicElementNS.java b/src/main/org/apache/tools/ant/DynamicElementNS.java
index 57bfa53..bd131aa 100644
--- a/src/main/org/apache/tools/ant/DynamicElementNS.java
+++ b/src/main/org/apache/tools/ant/DynamicElementNS.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/DynamicObjectAttribute.java b/src/main/org/apache/tools/ant/DynamicObjectAttribute.java
index 9a9aca9..fe73314 100644
--- a/src/main/org/apache/tools/ant/DynamicObjectAttribute.java
+++ b/src/main/org/apache/tools/ant/DynamicObjectAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/Evaluable.java b/src/main/org/apache/tools/ant/Evaluable.java
index 47f09c7..3688f58 100644
--- a/src/main/org/apache/tools/ant/Evaluable.java
+++ b/src/main/org/apache/tools/ant/Evaluable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,13 +17,19 @@
  */
 package org.apache.tools.ant;
 
+import java.util.function.Supplier;
+
 /**
  * Kind of task attribute that can be evaluated before being assigned
+ * @param <T> as {@link Supplier}
  *
  * @see RuntimeConfigurable
  */
-public interface Evaluable {
+public interface Evaluable<T> extends Supplier<T> {
 
-    Object eval();
+    T eval();
 
+    default T get() {
+        return eval();
+    }
 }
diff --git a/src/main/org/apache/tools/ant/Executor.java b/src/main/org/apache/tools/ant/Executor.java
index 9aff148..b2cdfa6 100644
--- a/src/main/org/apache/tools/ant/Executor.java
+++ b/src/main/org/apache/tools/ant/Executor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/ExitException.java b/src/main/org/apache/tools/ant/ExitException.java
index 11e1bc8..9c2513f 100644
--- a/src/main/org/apache/tools/ant/ExitException.java
+++ b/src/main/org/apache/tools/ant/ExitException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/ExitStatusException.java b/src/main/org/apache/tools/ant/ExitStatusException.java
index 1eb5127..ef2ee7a 100644
--- a/src/main/org/apache/tools/ant/ExitStatusException.java
+++ b/src/main/org/apache/tools/ant/ExitStatusException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/ExtensionPoint.java b/src/main/org/apache/tools/ant/ExtensionPoint.java
index 32c8c55..773a182 100644
--- a/src/main/org/apache/tools/ant/ExtensionPoint.java
+++ b/src/main/org/apache/tools/ant/ExtensionPoint.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/FileScanner.java b/src/main/org/apache/tools/ant/FileScanner.java
index a7cb9de..0afd919 100644
--- a/src/main/org/apache/tools/ant/FileScanner.java
+++ b/src/main/org/apache/tools/ant/FileScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/IntrospectionHelper.java b/src/main/org/apache/tools/ant/IntrospectionHelper.java
index af7f312..b61a6de 100644
--- a/src/main/org/apache/tools/ant/IntrospectionHelper.java
+++ b/src/main/org/apache/tools/ant/IntrospectionHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,8 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -29,6 +31,11 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
+import java.util.function.Supplier;
 
 import org.apache.tools.ant.taskdefs.PreSetDef;
 import org.apache.tools.ant.types.EnumeratedAttribute;
@@ -64,7 +71,7 @@
     /**
      * Helper instances we've already created (Class.getName() to IntrospectionHelper).
      */
-    private static final Map<String, IntrospectionHelper> HELPERS = new Hashtable<String, IntrospectionHelper>();
+    private static final Map<String, IntrospectionHelper> HELPERS = new Hashtable<>();
 
     /**
      * Map from primitive types to wrapper classes for use in
@@ -72,7 +79,7 @@
      * and boolean are in here even though they get special treatment
      * - this way we only need to test for the wrapper class.
      */
-    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_MAP = new HashMap<Class<?>, Class<?>>(8);
+    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_MAP = new HashMap<>(8);
 
     // Set up PRIMITIVE_TYPE_MAP
     static {
@@ -81,7 +88,7 @@
         final Class<?>[] wrappers = {Boolean.class, Byte.class, Character.class, Short.class,
                             Integer.class, Long.class, Float.class, Double.class};
         for (int i = 0; i < primitives.length; i++) {
-            PRIMITIVE_TYPE_MAP.put (primitives[i], wrappers[i]);
+            PRIMITIVE_TYPE_MAP.put(primitives[i], wrappers[i]);
         }
     }
 
@@ -92,30 +99,30 @@
      * Map from attribute names to attribute types
      * (String to Class).
      */
-    private final Hashtable<String, Class<?>> attributeTypes = new Hashtable<String, Class<?>>();
+    private final Map<String, Class<?>> attributeTypes = new Hashtable<>();
 
     /**
      * Map from attribute names to attribute setter methods
      * (String to AttributeSetter).
      */
-    private final Hashtable<String, AttributeSetter> attributeSetters = new Hashtable<String, AttributeSetter>();
+    private final Map<String, AttributeSetter> attributeSetters = new Hashtable<>();
 
     /**
      * Map from attribute names to nested types
      * (String to Class).
      */
-    private final Hashtable<String, Class<?>> nestedTypes = new Hashtable<String, Class<?>>();
+    private final Map<String, Class<?>> nestedTypes = new Hashtable<>();
 
     /**
      * Map from attribute names to methods to create nested types
      * (String to NestedCreator).
      */
-    private final Hashtable<String, NestedCreator> nestedCreators = new Hashtable<String, NestedCreator>();
+    private final Map<String, NestedCreator> nestedCreators = new Hashtable<>();
 
     /**
      * Vector of methods matching add[Configured](Class) pattern.
      */
-    private final List<Method> addTypeMethods = new ArrayList<Method>();
+    private final List<Method> addTypeMethods = new ArrayList<>();
 
     /**
      * The method to invoke to add PCDATA.
@@ -307,13 +314,8 @@
      * @return true if the given set method is to be hidden.
      */
     private boolean isHiddenSetMethod(final String name, final Class<?> type) {
-        if ("setLocation".equals(name) && Location.class.equals(type)) {
-            return true;
-        }
-        if ("setTaskType".equals(name) && String.class.equals(type)) {
-            return true;
-        }
-        return false;
+        return "setLocation".equals(name) && Location.class.equals(type)
+                || "setTaskType".equals(name) && String.class.equals(type);
     }
 
     /**
@@ -325,7 +327,7 @@
      *
      * @return a helper for the specified class
      */
-    public static synchronized IntrospectionHelper getHelper(final Class<?> c) {
+    public static IntrospectionHelper getHelper(final Class<?> c) {
         return getHelper(null, c);
     }
 
@@ -342,19 +344,31 @@
      *
      * @return a helper for the specified class
      */
-    public static synchronized IntrospectionHelper getHelper(final Project p, final Class<?> c) {
-        IntrospectionHelper ih = HELPERS.get(c.getName());
-        // If a helper cannot be found, or if the helper is for another
-        // classloader, create a new IH
-        if (ih == null || ih.bean != c) {
-            ih = new IntrospectionHelper(c);
-            if (p != null) {
-                // #30162: do *not* cache this if there is no project, as we
-                // cannot guarantee that the cache will be cleared.
-                HELPERS.put(c.getName(), ih);
-            }
+    public static IntrospectionHelper getHelper(final Project p, final Class<?> c) {
+        if (p == null) {
+            // #30162: do *not* use cache if there is no project, as we
+            // cannot guarantee that the cache will be cleared.
+            return new IntrospectionHelper(c);
         }
-        return ih;
+        IntrospectionHelper ih = HELPERS.get(c.getName());
+        if (ih != null && ih.bean == c) {
+            return ih;
+        }
+        // If a helper cannot be found, or if the helper is for another
+        // classloader, create a new IH and cache it
+        // Note: This new instance of IntrospectionHelper is intentionally
+        // created without holding a lock, to prevent potential deadlocks.
+        // See bz-65424 for details
+        ih = new IntrospectionHelper(c);
+        synchronized (HELPERS) {
+            IntrospectionHelper cached = HELPERS.get(c.getName());
+            if (cached != null && cached.bean == c) {
+                return cached;
+            }
+            // cache the recently created one
+            HELPERS.put(c.getName(), ih);
+            return ih;
+        }
     }
 
     /**
@@ -385,7 +399,7 @@
                 final String uriPlusPrefix = ProjectHelper.extractUriFromComponentName(attributeName);
                 final String uri = ProjectHelper.extractUriFromComponentName(uriPlusPrefix);
                 final String localName = ProjectHelper.extractNameFromComponentName(attributeName);
-                final String qName = "".equals(uri) ? localName : uri + ":" + localName;
+                final String qName = uri.isEmpty() ? localName : uri + ":" + localName;
                 dc.setDynamicAttribute(uri, localName, qName, value.toString());
                 return;
             }
@@ -399,7 +413,7 @@
                 dc.setDynamicAttribute(attributeName.toLowerCase(Locale.ENGLISH), value.toString());
                 return;
             }
-            if (attributeName.indexOf(':') >= 0) {
+            if (attributeName.contains(":")) {
                 return; // Ignore attribute from unknown uri's
             }
             final String msg = getElementName(p, element)
@@ -463,7 +477,7 @@
         if (addText == null) {
             text = text.trim();
             // Element doesn't handle text content
-            if (text.length() == 0) {
+            if (text.isEmpty()) {
                 // Only whitespace - ignore
                 return;
             }
@@ -472,7 +486,7 @@
                     + " doesn't support nested text data (\"" + condenseText(text) + "\").");
         }
         try {
-            addText.invoke(element, new Object[] {text});
+            addText.invoke(element, text);
         } catch (final IllegalAccessException ie) {
             // impossible as getMethods should only return public methods
             throw new BuildException(ie);
@@ -535,21 +549,17 @@
             parentUri = "";
         }
         NestedCreator nc = null;
-        if (uri.equals(parentUri) || uri.length() == 0) {
+        if (uri.equals(parentUri) || uri.isEmpty()) {
             nc = nestedCreators.get(name.toLowerCase(Locale.ENGLISH));
         }
         if (nc == null) {
             nc = createAddTypeCreator(project, parent, elementName);
         }
-        if (nc == null &&
-            (parent instanceof DynamicElementNS
-             || parent instanceof DynamicElement)
-            ) {
+        if (nc == null
+                && (parent instanceof DynamicElementNS || parent instanceof DynamicElement)) {
             final String qName = child == null ? name : child.getQName();
-            final Object nestedElement =
-                createDynamicElement(parent,
-                                     child == null ? "" : child.getNamespace(),
-                                     name, qName);
+            final Object nestedElement = createDynamicElement(parent,
+                    child == null ? "" : child.getNamespace(), name, qName);
             if (nestedElement != null) {
                 nc = new NestedCreator(null) {
                     @Override
@@ -618,12 +628,9 @@
                 project.setProjectReference(nestedElement);
             }
             return nestedElement;
-        } catch (final IllegalAccessException ie) {
+        } catch (final IllegalAccessException | InstantiationException ie) {
             // impossible as getMethods should only return public methods
             throw new BuildException(ie);
-        } catch (final InstantiationException ine) {
-            // impossible as getMethods should only return public methods
-            throw new BuildException(ine);
         } catch (final InvocationTargetException ite) {
             throw extractBuildException(ite);
         }
@@ -705,10 +712,8 @@
      * @return true if the given nested element is supported
      */
     public boolean supportsNestedElement(final String parentUri, final String elementName) {
-        if (isDynamic() || addTypeMethods.size() > 0) {
-            return true;
-        }
-        return supportsReflectElement(parentUri, elementName);
+        return isDynamic() || !addTypeMethods.isEmpty()
+                || supportsReflectElement(parentUri, elementName);
     }
 
     /**
@@ -730,11 +735,9 @@
      */
     public boolean supportsNestedElement(final String parentUri, final String elementName,
                                          final Project project, final Object parent) {
-        if (addTypeMethods.size() > 0
-            && createAddTypeCreator(project, parent, elementName) != null) {
-            return true;
-        }
-        return isDynamic() || supportsReflectElement(parentUri, elementName);
+        return !addTypeMethods.isEmpty()
+                && createAddTypeCreator(project, parent, elementName) != null
+                || isDynamic() || supportsReflectElement(parentUri, elementName);
     }
 
     /**
@@ -753,10 +756,7 @@
             return false;
         }
         String uri = ProjectHelper.extractUriFromComponentName(elementName);
-        if (uri.equals(ProjectHelper.ANT_CORE_URI)) {
-            uri = "";
-        }
-        if ("".equals(uri)) {
+        if (uri.equals(ProjectHelper.ANT_CORE_URI) || uri.isEmpty()) {
             return true;
         }
         if (parentUri.equals(ProjectHelper.ANT_CORE_URI)) {
@@ -796,12 +796,9 @@
         }
         try {
             ns.store(parent, child);
-        } catch (final IllegalAccessException ie) {
+        } catch (final IllegalAccessException | InstantiationException ie) {
             // impossible as getMethods should only return public methods
             throw new BuildException(ie);
-        } catch (final InstantiationException ine) {
-            // impossible as getMethods should only return public methods
-            throw new BuildException(ine);
         } catch (final InvocationTargetException ite) {
             throw extractBuildException(ite);
         }
@@ -897,13 +894,13 @@
      * @since Ant 1.6.3
      */
     public Method getElementMethod(final String elementName) throws BuildException {
-        final Object creator = nestedCreators.get(elementName);
+        final NestedCreator creator = nestedCreators.get(elementName);
         if (creator == null) {
             throw new UnsupportedElementException("Class "
                     + bean.getName() + " doesn't support the nested \""
                     + elementName + "\" element.", elementName);
         }
-        return ((NestedCreator) creator).method;
+        return creator.method;
     }
 
     /**
@@ -918,13 +915,13 @@
      * @since Ant 1.6.3
      */
     public Method getAttributeMethod(final String attributeName) throws BuildException {
-        final Object setter = attributeSetters.get(attributeName);
+        final AttributeSetter setter = attributeSetters.get(attributeName);
         if (setter == null) {
             throw new UnsupportedAttributeException("Class "
                     + bean.getName() + " doesn't support the \""
                     + attributeName + "\" attribute.", attributeName);
         }
-        return ((AttributeSetter) setter).method;
+        return setter.method;
     }
 
     /**
@@ -943,7 +940,7 @@
      * @see #getAttributeMap
      */
     public Enumeration<String> getAttributes() {
-        return attributeSetters.keys();
+        return Collections.enumeration(attributeSetters.keySet());
     }
 
     /**
@@ -955,7 +952,7 @@
      */
     public Map<String, Class<?>> getAttributeMap() {
         return attributeTypes.isEmpty()
-            ? Collections.<String, Class<?>> emptyMap() : Collections.unmodifiableMap(attributeTypes);
+            ? Collections.emptyMap() : Collections.unmodifiableMap(attributeTypes);
     }
 
     /**
@@ -967,7 +964,7 @@
      * @see #getNestedElementMap
      */
     public Enumeration<String> getNestedElements() {
-        return nestedTypes.keys();
+        return Collections.enumeration(nestedTypes.keySet());
     }
 
     /**
@@ -980,7 +977,7 @@
      */
     public Map<String, Class<?>> getNestedElementMap() {
         return nestedTypes.isEmpty()
-            ? Collections.<String, Class<?>> emptyMap() : Collections.unmodifiableMap(nestedTypes);
+            ? Collections.emptyMap() : Collections.unmodifiableMap(nestedTypes);
     }
 
     /**
@@ -1002,7 +999,7 @@
      */
     public List<Method> getExtensionPoints() {
         return addTypeMethods.isEmpty()
-                ? Collections.<Method> emptyList() : Collections.unmodifiableList(addTypeMethods);
+                ? Collections.emptyList() : Collections.unmodifiableList(addTypeMethods);
     }
 
     /**
@@ -1041,20 +1038,71 @@
     private AttributeSetter createAttributeSetter(final Method m,
                                                   final Class<?> arg,
                                                   final String attrName) {
+        if (Optional.class.equals(arg)) {
+            Type gpt = m.getGenericParameterTypes()[0];
+            Class<?> payload = Object.class;
+            if (gpt instanceof ParameterizedType ) {
+                Type ata = ((ParameterizedType) gpt).getActualTypeArguments()[0];
+                if (ata instanceof Class<?>) {
+                    payload = (Class<?>) ata;
+                } else if (ata instanceof ParameterizedType) {
+                    payload = (Class<?>) ((ParameterizedType) ata).getRawType();
+                }
+            }
+            final AttributeSetter wrapped = createAttributeSetter(m, payload, attrName);
+            return new AttributeSetter(m, arg, Optional::empty) {
+                @Override
+                Optional<?> toTargetType(Project project, String value)
+                    throws BuildException {
+                    return Optional.ofNullable(wrapped.toTargetType(project, value));
+                }
+            };
+        }
+        if (OptionalInt.class.equals(arg)) {
+            final AttributeSetter wrapped = createAttributeSetter(m, Integer.class, attrName);
+            return new AttributeSetter(m, arg, OptionalInt::empty) {
+                @Override
+                OptionalInt toTargetType(Project project, String value)
+                    throws BuildException {
+                    return Optional.ofNullable((Integer) wrapped.toTargetType(project, value))
+                        .map(OptionalInt::of).orElseGet(OptionalInt::empty);
+                }
+            };
+        }
+        if (OptionalLong.class.equals(arg)) {
+            final AttributeSetter wrapped = createAttributeSetter(m, Long.class, attrName);
+            return new AttributeSetter(m, arg, OptionalLong::empty) {
+                @Override
+                OptionalLong toTargetType(Project project, String value)
+                    throws BuildException {
+                    return Optional.ofNullable((Long) wrapped.toTargetType(project, value))
+                        .map(OptionalLong::of).orElseGet(OptionalLong::empty);
+                }
+            };
+        }
+        if (OptionalDouble.class.equals(arg)) {
+            final AttributeSetter wrapped = createAttributeSetter(m, Double.class, attrName);
+            return new AttributeSetter(m, arg, OptionalDouble::empty) {
+                @Override
+                Object toTargetType(Project project, String value)
+                    throws BuildException {
+                    return Optional.ofNullable((Double) wrapped.toTargetType(project, value))
+                        .map(OptionalDouble::of).orElseGet(OptionalDouble::empty);
+                }
+            };
+        }
         // use wrappers for primitive classes, e.g. int and
         // Integer are treated identically
-        final Class<?> reflectedArg = PRIMITIVE_TYPE_MAP.containsKey(arg)
-            ? PRIMITIVE_TYPE_MAP.get(arg) : arg;
+        final Class<?> reflectedArg = PRIMITIVE_TYPE_MAP.getOrDefault(arg, arg);
 
         // Object.class - it gets handled differently by AttributeSetter
-        if (java.lang.Object.class == reflectedArg) {
+        if (Object.class == reflectedArg) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException,
-                    IllegalAccessException {
+                Object toTargetType(Project project, String value)
+                    throws BuildException {
                     throw new BuildException(
-                        "Internal ant problem - this should not get called");
+                            "Internal ant problem - this should not get called");
                 }
             };
         }
@@ -1062,58 +1110,63 @@
         if (String.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException {
-                    m.invoke(parent, (Object[]) new String[] {value});
+                public String toTargetType(Project project, String t) {
+                    return t;
                 }
             };
         }
         // char and Character get special treatment - take the first character
-        if (java.lang.Character.class.equals(reflectedArg)) {
+        if (Character.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException {
-                    if (value.length() == 0) {
+                public Character toTargetType(Project project, String value) {
+                    if (value.isEmpty()) {
                         throw new BuildException("The value \"\" is not a "
                                 + "legal value for attribute \"" + attrName + "\"");
                     }
-                    m.invoke(parent, (Object[]) new Character[] {new Character(value.charAt(0))});
+                    return Character.valueOf(value.charAt(0));
                 }
             };
         }
         // boolean and Boolean get special treatment because we have a nice method in Project
-        if (java.lang.Boolean.class.equals(reflectedArg)) {
+        if (Boolean.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException {
-                    m.invoke(parent, (Object[]) new Boolean[] {
-                            Project.toBoolean(value) ? Boolean.TRUE : Boolean.FALSE });
+                public Boolean toTargetType(Project project, String value) {
+                    return Boolean.valueOf(Project.toBoolean(value));
                 }
             };
         }
         // Class doesn't have a String constructor but a decent factory method
-        if (java.lang.Class.class.equals(reflectedArg)) {
+        if (Class.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException, BuildException {
+                public Class<?> toTargetType(Project project, String value) {
                     try {
-                        m.invoke(parent, new Object[] {Class.forName(value)});
-                    } catch (final ClassNotFoundException ce) {
-                        throw new BuildException(ce);
+                        return Class.forName(value);
+                    } catch (ClassNotFoundException e) {
+                        throw new BuildException(e);
                     }
                 }
             };
         }
         // resolve relative paths through Project
-        if (java.io.File.class.equals(reflectedArg)) {
+        if (File.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException {
-                    m.invoke(parent, new Object[] {p.resolveFile(value)});
+                Object toTargetType(Project project, String value)
+                    throws BuildException {
+                    return project.resolveFile(value);
+                }
+            };
+        }
+        // resolve relative nio paths through Project
+        if (java.nio.file.Path.class.equals(reflectedArg)) {
+            return new AttributeSetter(m, arg) {
+                @Override
+                Object toTargetType(Project project, String value)
+                    throws BuildException {
+                    return project.resolveFile(value).toPath();
                 }
             };
         }
@@ -1121,9 +1174,9 @@
         if (Resource.class.equals(reflectedArg) || FileProvider.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                void set(final Project p, final Object parent, final String value) throws InvocationTargetException,
-                        IllegalAccessException, BuildException {
-                    m.invoke(parent, new Object[] {new FileResource(p, p.resolveFile(value))});
+                Object toTargetType(Project project, String value)
+                    throws BuildException {
+                    return new FileResource(project.resolveFile(value));
                 }
             };
         }
@@ -1131,40 +1184,34 @@
         if (EnumeratedAttribute.class.isAssignableFrom(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException, BuildException {
+                public EnumeratedAttribute toTargetType(Project project, String value) {
+                    EnumeratedAttribute ea;
                     try {
-                        final EnumeratedAttribute ea = (EnumeratedAttribute) reflectedArg.newInstance();
-                        ea.setValue(value);
-                        m.invoke(parent, new Object[] {ea});
-                    } catch (final InstantiationException ie) {
-                        throw new BuildException(ie);
+                        ea = (EnumeratedAttribute) reflectedArg.getDeclaredConstructor().newInstance();
+                    } catch (InstantiationException | IllegalAccessException
+                            | IllegalArgumentException | InvocationTargetException
+                            | NoSuchMethodException | SecurityException e) {
+                        throw BuildException.of(e);
                     }
+                    ea.setValue(value);
+                    return ea;
                 }
             };
         }
-
         final AttributeSetter setter = getEnumSetter(reflectedArg, m, arg);
         if (setter != null) {
             return setter;
         }
-
-        if (java.lang.Long.class.equals(reflectedArg)) {
+        if (Long.class.equals(reflectedArg)) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                        throws InvocationTargetException, IllegalAccessException, BuildException {
+                public Long toTargetType(Project project, String value) {
                     try {
-                        m.invoke(parent, new Object[] {
-                                new Long(StringUtils.parseHumanSizes(value)) });
+                        return Long.valueOf(StringUtils.parseHumanSizes(value));
                     } catch (final NumberFormatException e) {
-                        throw new BuildException("Can't assign non-numeric"
-                                                 + " value '" + value + "' to"
-                                                 + " attribute " + attrName);
-                    } catch (final InvocationTargetException e) {
-                        throw e;
-                    } catch (final IllegalAccessException e) {
-                        throw e;
+                        throw new BuildException(
+                            String.format("Can't assign non-numeric value '%s' to attribute %s",
+                                value, attrName));
                     } catch (final Exception e) {
                         throw new BuildException(e);
                     }
@@ -1196,30 +1243,32 @@
 
         return new AttributeSetter(m, arg) {
             @Override
-            public void set(final Project p, final Object parent, final String value)
-                    throws InvocationTargetException, IllegalAccessException, BuildException {
+            public Object toTargetType(Project project, String value) {
                 try {
                     final Object[] args = finalIncludeProject
-                            ? new Object[] {p, value} : new Object[] {value};
+                            ? new Object[] {project, value} : new Object[] {value};
 
                     final Object attribute = finalConstructor.newInstance(args);
-                    if (p != null) {
-                        p.setProjectReference(attribute);
+                    if (project != null) {
+                        project.setProjectReference(attribute);
                     }
-                    m.invoke(parent, new Object[] {attribute});
-                } catch (final InvocationTargetException e) {
-                    final Throwable cause = e.getCause();
-                    if (cause instanceof IllegalArgumentException) {
-                        throw new BuildException("Can't assign value '" + value
-                                                 + "' to attribute " + attrName
-                                                 + ", reason: "
-                                                 + cause.getClass()
-                                                 + " with message '"
-                                                 + cause.getMessage() + "'");
+                    return attribute;
+                } catch (final Exception e) {
+                    Throwable thw = e;
+                    while (true) {
+                        if (thw instanceof IllegalArgumentException) {
+                            throw new BuildException(String.format(
+                                "Can't convert value '%s' to type %s, reason: %s with message '%s'",
+                                value, reflectedArg, thw.getClass(), thw.getMessage()));
+                        }
+                        final Throwable _thw = thw;
+                        Optional<Throwable> next = Optional.of(thw).map(Throwable::getCause).filter(t -> t != _thw);
+                        if (!next.isPresent()) {
+                            break;
+                        }
+                        thw = next.get();
                     }
-                    throw e;
-                } catch (final InstantiationException ie) {
-                    throw new BuildException(ie);
+                    throw BuildException.of(e);
                 }
             }
         };
@@ -1230,22 +1279,18 @@
         if (reflectedArg.isEnum()) {
             return new AttributeSetter(m, arg) {
                 @Override
-                public void set(final Project p, final Object parent, final String value)
-                    throws InvocationTargetException, IllegalAccessException,
-                    BuildException {
-                    Enum<?> setValue;
+                public Enum<?> toTargetType(Project project, String value) {
                     try {
                         @SuppressWarnings({ "unchecked", "rawtypes" })
-                        final Enum<?> enumValue = Enum.valueOf((Class<? extends Enum>) reflectedArg,
-                                value);
-                        setValue = enumValue;
+                        final Enum<?> result =
+                            Enum.valueOf((Class<? extends Enum>) reflectedArg, value);
+                        return result;
                     } catch (final IllegalArgumentException e) {
-                        //there is specific logic here for the value
+                        // there is a specific logic here for the value
                         // being out of the allowed set of enumerations.
                         throw new BuildException("'" + value + "' is not a permitted value for "
                                 + reflectedArg.getName());
                     }
-                    m.invoke(parent, setValue);
                 }
             };
         }
@@ -1345,9 +1390,7 @@
                     project.setProjectReference(nestedObject);
                 }
                 return nestedObject;
-            } catch (final IllegalAccessException ex) {
-                throw new BuildException(ex);
-            } catch (final InstantiationException ex) {
+            } catch (final IllegalAccessException | InstantiationException ex) {
                 throw new BuildException(ex);
             } catch (final IllegalArgumentException ex) {
                 if (polyType == null) {
@@ -1373,9 +1416,7 @@
         public void store() {
             try {
                 nestedCreator.store(parent, nestedObject);
-            } catch (final IllegalAccessException ex) {
-                throw new BuildException(ex);
-            } catch (final InstantiationException ex) {
+            } catch (final IllegalAccessException | InstantiationException ex) {
                 throw new BuildException(ex);
             } catch (final IllegalArgumentException ex) {
                 if (polyType == null) {
@@ -1424,7 +1465,7 @@
         @Override
         Object create(final Project project, final Object parent, final Object ignore)
                 throws InvocationTargetException, IllegalAccessException {
-            return getMethod().invoke(parent, new Object[] {});
+            return getMethod().invoke(parent);
         }
     }
 
@@ -1474,8 +1515,8 @@
         }
 
         private void istore(final Object parent, final Object child)
-                throws InvocationTargetException, IllegalAccessException, InstantiationException {
-            getMethod().invoke(parent, new Object[] {child});
+                throws InvocationTargetException, IllegalAccessException {
+            getMethod().invoke(parent, child);
         }
     }
 
@@ -1486,38 +1527,50 @@
     private abstract static class AttributeSetter {
         private final Method method; // the method called to set the attribute
         private final Class<?> type;
+        private final Supplier<?> supplyWhenNull;
+
         protected AttributeSetter(final Method m, final Class<?> type) {
-            method = m;
-            this.type = type;
+            this(m, type, () -> null);
         }
-        void setObject(final Project p, final Object parent, final Object value)
+
+        protected AttributeSetter(final Method method, final Class<?> type,
+            final Supplier<?> supplyWhenNull) {
+            this.method = method;
+            this.type = type;
+            this.supplyWhenNull = supplyWhenNull;
+        }
+
+        final void setObject(final Project p, final Object parent, Object value)
                 throws InvocationTargetException, IllegalAccessException, BuildException {
             if (type != null) {
                 Class<?> useType = type;
                 if (type.isPrimitive()) {
                     if (value == null) {
-                        throw new BuildException(
-                            "Attempt to set primitive "
-                            + getPropertyName(method.getName(), "set")
-                            + " to null on " + parent);
+                        throw new BuildException("Attempt to set primitive %s to null on %s",
+                            getPropertyName(method.getName(), "set"), parent);
                     }
                     useType = PRIMITIVE_TYPE_MAP.get(type);
                 }
+                if (value == null ) {
+                    value = supplyWhenNull.get();
+                }
                 if (value == null || useType.isInstance(value)) {
-                    method.invoke(parent, new Object[] {value});
+                    method.invoke(parent, value);
                     return;
                 }
             }
-            set(p, parent, value.toString());
+            method.invoke(parent, toTargetType(p, value.toString()));
         }
-        abstract void set(Project p, Object parent, String value)
-                throws InvocationTargetException, IllegalAccessException, BuildException;
+
+        Object toTargetType(Project project, String value) {
+            throw new UnsupportedOperationException();
+        }
     }
 
     /**
      * Clears the static cache of on build finished.
      */
-    public static synchronized void clearCache() {
+    public static void clearCache() {
         HELPERS.clear();
     }
 
@@ -1532,15 +1585,13 @@
      */
     private NestedCreator createAddTypeCreator(
             final Project project, final Object parent, final String elementName) throws BuildException {
-        if (addTypeMethods.size() == 0) {
+        if (addTypeMethods.isEmpty()) {
             return null;
         }
         final ComponentHelper helper = ComponentHelper.getComponentHelper(project);
 
-        final MethodAndObject restricted =  createRestricted(
-            helper, elementName, addTypeMethods);
-        final MethodAndObject topLevel = createTopLevel(
-            helper, elementName, addTypeMethods);
+        final MethodAndObject restricted =  createRestricted(helper, elementName, addTypeMethods);
+        final MethodAndObject topLevel = createTopLevel(helper, elementName, addTypeMethods);
 
         if (restricted == null && topLevel == null) {
             return null;
@@ -1552,8 +1603,7 @@
                 + elementName);
         }
 
-        final MethodAndObject methodAndObject
-            = restricted != null ? restricted : topLevel;
+        final MethodAndObject methodAndObject = restricted == null ? topLevel : restricted;
 
         Object rObject = methodAndObject.object;
         if (methodAndObject.object instanceof PreSetDef.PreSetDefinition) {
@@ -1568,7 +1618,7 @@
             Object create(final Project project, final Object parent, final Object ignore)
                     throws InvocationTargetException, IllegalAccessException {
                 if (!getMethod().getName().endsWith("Configured")) {
-                    getMethod().invoke(parent, new Object[] {realObject});
+                    getMethod().invoke(parent, realObject);
                 }
                 return nestedObject;
             }
@@ -1582,7 +1632,7 @@
             void store(final Object parent, final Object child) throws InvocationTargetException,
                     IllegalAccessException, InstantiationException {
                 if (getMethod().getName().endsWith("Configured")) {
-                    getMethod().invoke(parent, new Object[] {realObject});
+                    getMethod().invoke(parent, realObject);
                 }
             }
         };
@@ -1601,7 +1651,7 @@
         for (int c = 0; c < size; ++c) {
             final Method current = addTypeMethods.get(c);
             if (current.getParameterTypes()[0].equals(argClass)) {
-                if (method.getName().equals("addConfigured")) {
+                if ("addConfigured".equals(method.getName())) {
                     // add configured replaces the add method
                     addTypeMethods.set(c, method);
                 }
@@ -1712,9 +1762,8 @@
         final Method addMethod = findMatchingMethod(
             restrictedDefinition.getExposedClass(project), addTypeMethods);
         if (addMethod == null) {
-            throw new BuildException(
-                "Ant Internal Error - contract mismatch for "
-                + elementName);
+            throw new BuildException("Ant Internal Error - contract mismatch for "
+                    + elementName);
         }
         final Object addedObject = restrictedDefinition.create(project);
         if (addedObject == null) {
diff --git a/src/main/org/apache/tools/ant/Location.java b/src/main/org/apache/tools/ant/Location.java
index 8e25d10..32bd7b7 100644
--- a/src/main/org/apache/tools/ant/Location.java
+++ b/src/main/org/apache/tools/ant/Location.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 package org.apache.tools.ant;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 import org.apache.tools.ant.util.FileUtils;
 import org.xml.sax.Locator;
@@ -131,8 +132,9 @@
      *         <code>"fileName: "</code> if only the file name is known,
      *         and the empty string for unknown locations.
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
 
         if (fileName != null) {
             buf.append(fileName);
@@ -155,17 +157,10 @@
      *              as this object.
      * @since Ant 1.6.3
      */
+    @Override
     public boolean equals(Object other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null) {
-            return false;
-        }
-        if (!(other.getClass() == getClass())) {
-            return false;
-        }
-        return toString().equals(other.toString());
+        return this == other || other != null && other.getClass() == getClass()
+                && toString().equals(other.toString());
     }
 
     /**
@@ -173,7 +168,8 @@
      * @return a hash code value for this location.
      * @since Ant 1.6.3
      */
+    @Override
     public int hashCode() {
-        return toString().hashCode();
+        return Objects.hash(fileName, lineNumber);
     }
 }
diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java
index d189654..12fbcf7 100644
--- a/src/main/org/apache/tools/ant/MagicNames.java
+++ b/src/main/org/apache/tools/ant/MagicNames.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -56,6 +56,12 @@
     public static final String SCRIPT_REPOSITORY = "org.apache.ant.scriptrepo";
 
     /**
+     * The name of the script cache used by the script runner.
+     * Value {@value}
+     */
+    public static final String SCRIPT_CACHE = "org.apache.ant.scriptcache";
+
+    /**
      * The name of the reference to the System Class Loader.
      * Value {@value}
      **/
@@ -202,17 +208,24 @@
     public static final String REFID_LOCAL_PROPERTIES = "ant.LocalProperties";
 
     /**
+     * Name of Ant core package
+     * Value: {@value}
+     * @since Ant 1.10.9
+     */
+    public static final String ANT_CORE_PACKAGE = "org.apache.tools.ant";
+
+    /**
      * Name of JVM system property which provides the name of the ProjectHelper class to use.
      * Value: {@value}
      */
-    public static final String PROJECT_HELPER_CLASS = "org.apache.tools.ant.ProjectHelper";
+    public static final String PROJECT_HELPER_CLASS = ANT_CORE_PACKAGE + ".ProjectHelper";
 
     /**
      * The service identifier in jars which provide ProjectHelper implementations.
      * Value: {@value}
      */
     public static final String PROJECT_HELPER_SERVICE =
-        "META-INF/services/org.apache.tools.ant.ProjectHelper";
+        "META-INF/services/" + PROJECT_HELPER_CLASS;
 
     /**
      * Name of ProjectHelper reference that we add to a project.
@@ -299,17 +312,52 @@
      * as seconds since the epoch.</p>
      *
      * Value: {@value}
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public static final String TSTAMP_NOW = "ant.tstamp.now";
 
     /**
+     * Magic property that can be set to contain a value for tstamp's
+     * "now" in order to make builds that use the task create
+     * reproducible results.
+     *
+     * <p>The value is expected to be in ISO time format
+     * (<i>1972-04-17T08:07</i>)</p>
+     *
+     * Value: {@value}
+     * @since Ant 1.10.2
+     */
+    public static final String TSTAMP_NOW_ISO = "ant.tstamp.now.iso";
+
+    /**
      * Magic property that can be set to override the java.io.tmpdir
      * system property as the location for Ant's default temporary
      * directory.
      * Value: {@value}
-     * @since Ant 1.9.15
+     * @since Ant 1.10.8
      */
     public static final String TMPDIR = "ant.tmpdir";
+
+    /**
+     * Magic property that will be set to override java.io.tmpdir
+     * system property as the location for Ant's default temporary
+     * directory if a temp file is created and {@link #TMPDIR} is not
+     * set.
+     * Value: {@value}
+     * @since Ant 1.10.9
+     */
+    public static final String AUTO_TMPDIR = "ant.auto.tmpdir";
+
+    /**
+     * Magic property that can be used to disable Nashorn compatibility mode when using GraalVM JavaScript as script
+     * engine.
+     *
+     * <p>Set this to "true" if you want to disable Nashorn compatibility mode.</p>
+     *
+     * Value: {@value}
+     * @since Ant 1.10.9
+     */
+    public static final String DISABLE_NASHORN_COMPAT = "ant.disable.graal.nashorn.compat";
+
 }
 
diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java
index 704b565..bb07cab 100644
--- a/src/main/org/apache/tools/ant/Main.java
+++ b/src/main/org/apache/tools/ant/Main.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,11 +19,11 @@
 package org.apache.tools.ant;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -33,10 +33,10 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.input.DefaultInputHandler;
 import org.apache.tools.ant.input.InputHandler;
@@ -45,10 +45,9 @@
 import org.apache.tools.ant.property.GetProperty;
 import org.apache.tools.ant.property.ResolvePropertyMap;
 import org.apache.tools.ant.util.ClasspathUtils;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.ProxySetup;
-
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * Command line entry point into Ant. This class is entered via the
@@ -68,7 +67,7 @@
      * not be seen by Main.
      */
     private static final Set<String> LAUNCH_COMMANDS = Collections
-            .unmodifiableSet(new HashSet<String>(Arrays.asList("-lib", "-cp", "-noclasspath",
+            .unmodifiableSet(new HashSet<>(Arrays.asList("-lib", "-cp", "-noclasspath",
                     "--noclasspath", "-nouserlib", "-main")));
 
     /** The default build file name. {@value} */
@@ -87,16 +86,16 @@
     private PrintStream err = System.err;
 
     /** The build targets. */
-    private final Vector<String> targets = new Vector<String>();
+    private final Vector<String> targets = new Vector<>();
 
     /** Set of properties that can be used by tasks. */
     private final Properties definedProps = new Properties();
 
     /** Names of classes to add as listeners to project. */
-    private final Vector<String> listeners = new Vector<String>(1);
+    private final Vector<String> listeners = new Vector<>(1);
 
     /** File names of property files to load on startup. */
-    private final Vector<String> propertyFiles = new Vector<String>(1);
+    private final Vector<String> propertyFiles = new Vector<>(1);
 
     /** Indicates whether this build is to support interactive input */
     private boolean allowInput = true;
@@ -155,17 +154,9 @@
      */
     private boolean proxy = false;
 
-    private final Map<Class<?>, List<String>> extraArguments = new HashMap<Class<?>, List<String>>();
+    private final Map<Class<?>, List<String>> extraArguments = new HashMap<>();
 
-    private static final GetProperty NOPROPERTIES = new GetProperty() {
-        public Object getProperty(final String aName) {
-            // No existing property takes precedence
-            return null;
-        }
-    };
-
-
-
+    private static final GetProperty NOPROPERTIES = aName -> null;
 
     /**
      * Prints the message of the Throwable if it (the message) is not
@@ -221,12 +212,8 @@
         }
 
         if (additionalUserProperties != null) {
-            for (final Enumeration<?> e = additionalUserProperties.keys();
-                    e.hasMoreElements();) {
-                final String key = (String) e.nextElement();
-                final String property = additionalUserProperties.getProperty(key);
-                definedProps.put(key, property);
-            }
+            additionalUserProperties.stringPropertyNames()
+                    .forEach(key -> definedProps.put(key, additionalUserProperties.getProperty(key)));
         }
 
         // expect the worst
@@ -355,10 +342,10 @@
                 try {
                     final File logFile = new File(args[i + 1]);
                     i++;
-                    // life-cycle of FileOutputStream is controlled by
+                    // life-cycle of OutputStream is controlled by
                     // logTo which becomes "out" and is closed in
                     // handleLogfile
-                    logTo = new PrintStream(new FileOutputStream(logFile)); //NOSONAR
+                    logTo = new PrintStream(Files.newOutputStream(logFile.toPath())); //NOSONAR
                     isLogFileUsed = true;
                 } catch (final IOException ioe) {
                     final String msg = "Cannot write on the specified log file. "
@@ -414,14 +401,8 @@
                 for (final ArgumentProcessor processor : processorRegistry.getProcessors()) {
                     final int newI = processor.readArguments(args, i);
                     if (newI != -1) {
-                        List<String> extraArgs = extraArguments.get(processor.getClass());
-                        if (extraArgs == null) {
-                            extraArgs = new ArrayList<String>();
-                            extraArguments.put(processor.getClass(), extraArgs);
-                        }
-                        for (; i < newI && i < args.length; i++) {
-                            extraArgs.add(args[i]);
-                        }
+                        List<String> extraArgs = extraArguments.computeIfAbsent(processor.getClass(), k -> new ArrayList<>());
+                        extraArgs.addAll(Arrays.asList(args).subList(newI, args.length));
                         processed = true;
                         break;
                     }
@@ -459,9 +440,6 @@
             if (searchForFile) {
                 if (searchForThis != null) {
                     buildFile = findBuildFile(System.getProperty("user.dir"), searchForThis);
-                    if (buildFile == null) {
-                        throw new BuildException("Could not locate a build file!");
-                    }
                 } else {
                     // no search file specified: so search an existing default file
                     final Iterator<ProjectHelper> it = ProjectHelperRepository.getInstance().getHelpers();
@@ -473,9 +451,9 @@
                         }
                         buildFile = findBuildFile(System.getProperty("user.dir"), searchForThis);
                     } while (buildFile == null && it.hasNext());
-                    if (buildFile == null) {
-                        throw new BuildException("Could not locate a build file!");
-                    }
+                }
+                if (buildFile == null) {
+                    throw new BuildException("Could not locate a build file!");
                 }
             } else {
                 // no build file specified: so search an existing default file
@@ -568,9 +546,9 @@
          * to help or not, so we simply look for the equals sign.
          */
         final String arg = args[argPos];
-        String name = arg.substring(2, arg.length());
-        String value = null;
-        final int posEq = name.indexOf("=");
+        String name = arg.substring(2);
+        String value;
+        final int posEq = name.indexOf('=');
         if (posEq > 0) {
             value = name.substring(posEq + 1);
             name = name.substring(0, posEq);
@@ -640,8 +618,8 @@
                                      + args[pos]);
         }
 
-        if (threadPriority.intValue() < Thread.MIN_PRIORITY
-            || threadPriority.intValue() > Thread.MAX_PRIORITY) {
+        if (threadPriority < Thread.MIN_PRIORITY
+            || threadPriority > Thread.MAX_PRIORITY) {
             throw new BuildException(
                 "Niceness value is out of the range 1-10");
         }
@@ -656,25 +634,17 @@
     private void loadPropertyFiles() {
         for (final String filename : propertyFiles) {
             final Properties props = new Properties();
-            FileInputStream fis = null;
-            try {
-                fis = new FileInputStream(filename);
+            try (InputStream fis = Files.newInputStream(Paths.get(filename))) {
                 props.load(fis);
             } catch (final IOException e) {
                 System.out.println("Could not load property file "
                                    + filename + ": " + e.getMessage());
-            } finally {
-                FileUtils.close(fis);
             }
 
             // ensure that -D properties take precedence
-            final Enumeration<?> propertyNames = props.propertyNames();
-            while (propertyNames.hasMoreElements()) {
-                final String name = (String) propertyNames.nextElement();
-                if (definedProps.getProperty(name) == null) {
-                    definedProps.put(name, props.getProperty(name));
-                }
-            }
+            props.stringPropertyNames().stream()
+                    .filter(name -> definedProps.getProperty(name) == null)
+                    .forEach(name -> definedProps.put(name, props.getProperty(name)));
         }
     }
 
@@ -779,15 +749,6 @@
             final PrintStream savedErr = System.err;
             final PrintStream savedOut = System.out;
             final InputStream savedIn = System.in;
-
-            // use a system manager that prevents from System.exit()
-            SecurityManager oldsm = null;
-            oldsm = System.getSecurityManager();
-
-                //SecurityManager can not be installed here for backwards
-                //compatibility reasons (PD). Needs to be loaded prior to
-                //ant class if we are going to implement it.
-                //System.setSecurityManager(new NoExitSecurityManager());
             try {
                 if (allowInput) {
                     project.setDefaultInputStream(System.in);
@@ -806,7 +767,7 @@
                     try {
                         project.log("Setting Ant's thread priority to "
                                 + threadPriority, Project.MSG_VERBOSE);
-                        Thread.currentThread().setPriority(threadPriority.intValue());
+                        Thread.currentThread().setPriority(threadPriority);
                     } catch (final SecurityException swallowed) {
                         //we cannot set the priority here.
                         project.log("A security manager refused to set the -nice value");
@@ -848,7 +809,7 @@
                 }
 
                 // make sure that we have a target to execute
-                if (targets.size() == 0) {
+                if (targets.isEmpty()) {
                     if (project.getDefaultTarget() != null) {
                         targets.addElement(project.getDefaultTarget());
                     }
@@ -856,22 +817,13 @@
 
                 project.executeTargets(targets);
             } finally {
-                // put back the original security manager
-                //The following will never eval to true. (PD)
-                if (oldsm != null) {
-                    System.setSecurityManager(oldsm);
-                }
-
                 System.setOut(savedOut);
                 System.setErr(savedErr);
                 System.setIn(savedIn);
             }
-        } catch (final RuntimeException exc) {
+        } catch (final RuntimeException | Error exc) {
             error = exc;
             throw exc;
-        } catch (final Error e) {
-            error = e;
-            throw e;
         } finally {
             if (!projectHelp) {
                 try {
@@ -911,11 +863,7 @@
         resolver.resolveAllProperties(props, null, false);
 
         // set user-define properties
-        for (final Entry<String, Object> ent : props.entrySet()) {
-            final String arg = ent.getKey();
-            final Object value = ent.getValue();
-            project.setUserProperty(arg, String.valueOf(value));
-        }
+        props.forEach((arg, value) -> project.setUserProperty(arg, String.valueOf(value)));
 
         project.setUserProperty(MagicNames.ANT_FILE,
                                 buildFile.getAbsolutePath());
@@ -930,7 +878,7 @@
         // Setting it here allows top-level tasks to access the
         // property.
         project.setUserProperty(MagicNames.PROJECT_INVOKED_TARGETS,
-                                CollectionUtils.flattenToString(targets));
+                String.join(",", targets));
     }
 
     /**
@@ -949,7 +897,7 @@
         for (int i = 0; i < count; i++) {
             final String className = listeners.elementAt(i);
             final BuildListener listener =
-                    (BuildListener) ClasspathUtils.newInstance(className,
+                    ClasspathUtils.newInstance(className,
                             Main.class.getClassLoader(), BuildListener.class);
             project.setProjectReference(listener);
 
@@ -970,7 +918,7 @@
         if (inputHandlerClassname == null) {
             handler = new DefaultInputHandler();
         } else {
-            handler = (InputHandler) ClasspathUtils.newInstance(
+            handler = ClasspathUtils.newInstance(
                     inputHandlerClassname, Main.class.getClassLoader(),
                     InputHandler.class);
             project.setProjectReference(handler);
@@ -992,7 +940,7 @@
             emacsMode = true;
         } else if (loggerClassname != null) {
             try {
-                logger = (BuildLogger) ClasspathUtils.newInstance(
+                logger = ClasspathUtils.newInstance(
                         loggerClassname, Main.class.getClassLoader(),
                         BuildLogger.class);
             } catch (final BuildException e) {
@@ -1096,13 +1044,10 @@
                 props.load(in);
                 in.close();
                 shortAntVersion = props.getProperty("VERSION");
-
-                final StringBuffer msg = new StringBuffer();
-                msg.append("Apache Ant(TM) version ");
-                msg.append(shortAntVersion);
-                msg.append(" compiled on ");
-                msg.append(props.getProperty("DATE"));
-                antVersion = msg.toString();
+                antVersion = "Apache Ant(TM) version " +
+                        shortAntVersion +
+                        " compiled on " +
+                        props.getProperty("DATE");
             } catch (final IOException ioe) {
                 throw new BuildException("Could not load the version information:"
                                          + ioe.getMessage());
@@ -1153,26 +1098,19 @@
      * @return the filtered targets.
      */
     private static Map<String, Target> removeDuplicateTargets(final Map<String, Target> targets) {
-        final Map<Location, Target> locationMap = new HashMap<Location, Target>();
-        for (final Entry<String, Target> entry : targets.entrySet()) {
-            final String name = entry.getKey();
-            final Target target = entry.getValue();
+        final Map<Location, Target> locationMap = new HashMap<>();
+        targets.forEach((name, target) -> {
             final Target otherTarget = locationMap.get(target.getLocation());
             // Place this entry in the location map if
             //  a) location is not in the map
             //  b) location is in map, but its name is longer
             //     (an imported target will have a name. prefix)
-            if (otherTarget == null
-                || otherTarget.getName().length() > name.length()) {
-                locationMap.put(
-                    target.getLocation(), target); // Smallest name wins
+            if (otherTarget == null || otherTarget.getName().length() > name.length()) {
+                locationMap.put(target.getLocation(), target); // Smallest name wins
             }
-        }
-        final Map<String, Target> ret = new HashMap<String, Target>();
-        for (final Target target : locationMap.values()) {
-            ret.put(target.getName(), target);
-        }
-        return ret;
+        });
+        return locationMap.values().stream()
+                .collect(Collectors.toMap(Target::getName, target -> target, (a, b) -> b));
     }
 
     /**
@@ -1191,15 +1129,15 @@
         final Map<String, Target> ptargets = removeDuplicateTargets(project.getTargets());
         // split the targets in top-level and sub-targets depending
         // on the presence of a description
-        final Vector<String> topNames = new Vector<String>();
-        final Vector<String> topDescriptions = new Vector<String>();
-        final Vector<Enumeration<String>> topDependencies = new Vector<Enumeration<String>>();
-        final Vector<String> subNames = new Vector<String>();
-        final Vector<Enumeration<String>> subDependencies = new Vector<Enumeration<String>>();
+        final Vector<String> topNames = new Vector<>();
+        final Vector<String> topDescriptions = new Vector<>();
+        final Vector<Enumeration<String>> topDependencies = new Vector<>();
+        final Vector<String> subNames = new Vector<>();
+        final Vector<Enumeration<String>> subDependencies = new Vector<>();
 
         for (final Target currentTarget : ptargets.values()) {
             final String targetName = currentTarget.getName();
-            if (targetName.equals("")) {
+            if (targetName.isEmpty()) {
                 continue;
             }
             final String targetDescription = currentTarget.getDescription();
@@ -1227,7 +1165,7 @@
                 "Main targets:", maxLength);
         //if there were no main targets, we list all subtargets
         //as it means nothing has a description
-        if (topNames.size() == 0) {
+        if (topNames.isEmpty()) {
             printSubTargets = true;
         }
         if (printSubTargets) {
@@ -1235,7 +1173,7 @@
         }
 
         final String defaultTarget = project.getDefaultTarget();
-        if (defaultTarget != null && !"".equals(defaultTarget)) {
+        if (defaultTarget != null && !defaultTarget.isEmpty()) {
             // shouldn't need to check but...
             project.log("Default target: " + defaultTarget);
         }
@@ -1287,14 +1225,14 @@
                                      final String heading,
                                      final int maxlen) {
         // now, start printing the targets and their descriptions
-        final String lSep = System.getProperty("line.separator");
+        final String eol = System.lineSeparator();
         // got a bit annoyed that I couldn't find a pad function
         StringBuilder spaces = new StringBuilder("    ");
         while (spaces.length() <= maxlen) {
             spaces.append(spaces);
         }
         final StringBuilder msg = new StringBuilder();
-        msg.append(heading).append(lSep).append(lSep);
+        msg.append(heading).append(eol).append(eol);
         final int size = names.size();
         for (int i = 0; i < size; i++) {
             msg.append(" ");
@@ -1304,19 +1242,10 @@
                     spaces.substring(0, maxlen - names.elementAt(i).length() + 2));
                 msg.append(descriptions.elementAt(i));
             }
-            msg.append(lSep);
-            if (!dependencies.isEmpty()) {
-                final Enumeration<String> deps = dependencies.elementAt(i);
-                if (deps.hasMoreElements()) {
-                    msg.append("   depends on: ");
-                    while (deps.hasMoreElements()) {
-                        msg.append(deps.nextElement());
-                        if (deps.hasMoreElements()) {
-                            msg.append(", ");
-                        }
-                    }
-                    msg.append(lSep);
-                }
+            msg.append(eol);
+            if (!dependencies.isEmpty() && dependencies.elementAt(i).hasMoreElements()) {
+                msg.append(StreamUtils.enumerationAsStream(dependencies.elementAt(i))
+                        .collect(Collectors.joining(", ", "   depends on: ", eol)));
             }
         }
         project.log(msg.toString(), Project.MSG_WARN);
diff --git a/src/main/org/apache/tools/ant/NoBannerLogger.java b/src/main/org/apache/tools/ant/NoBannerLogger.java
index a086bf5..628390d 100644
--- a/src/main/org/apache/tools/ant/NoBannerLogger.java
+++ b/src/main/org/apache/tools/ant/NoBannerLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,6 @@
 
 package org.apache.tools.ant;
 
-import org.apache.tools.ant.util.StringUtils;
-
 /**
  * Extends DefaultLogger to strip out empty targets.
  *
@@ -84,13 +82,13 @@
 
         if (event.getPriority() > msgOutputLevel
             || null == event.getMessage()
-            || "".equals(event.getMessage().trim())) {
+            || event.getMessage().trim().isEmpty()) {
                 return;
         }
 
         synchronized (this) {
             if (null != targetName) {
-                out.println(StringUtils.LINE_SEP + targetName + ":");
+                out.printf("%n%s:%n", targetName);
                 targetName = null;
             }
         }
diff --git a/src/main/org/apache/tools/ant/PathTokenizer.java b/src/main/org/apache/tools/ant/PathTokenizer.java
index 6e6bea6..0afb42c 100644
--- a/src/main/org/apache/tools/ant/PathTokenizer.java
+++ b/src/main/org/apache/tools/ant/PathTokenizer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -83,11 +83,7 @@
      * in the string after the current position; <code>false</code> otherwise.
      */
     public boolean hasMoreTokens() {
-        if (lookahead != null) {
-            return true;
-        }
-
-        return tokenizer.hasMoreTokens();
+        return lookahead != null || tokenizer.hasMoreTokens();
     }
 
     /**
@@ -127,7 +123,7 @@
         } else {
             // we are on NetWare, tokenizing is handled a little differently,
             // due to the fact that NetWare has multiple-character volume names.
-            if (token.equals(File.pathSeparator) || token.equals(":")) {
+            if (token.equals(File.pathSeparator) || ":".equals(token)) {
                 // ignore ";" and get the next token
                 token = tokenizer.nextToken().trim();
             }
@@ -138,7 +134,7 @@
 
                 // make sure we aren't going to get the path separator next
                 if (!nextToken.equals(File.pathSeparator)) {
-                    if (nextToken.equals(":")) {
+                    if (":".equals(nextToken)) {
                         if (!token.startsWith("/") && !token.startsWith("\\")
                             && !token.startsWith(".")
                             && !token.startsWith("..")) {
@@ -163,4 +159,3 @@
         return token;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java
index b8636d9..2cd2ba9 100644
--- a/src/main/org/apache/tools/ant/Project.java
+++ b/src/main/org/apache/tools/ant/Project.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,17 +23,19 @@
 import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.Arrays;
 import java.util.Collections;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.Stack;
 import java.util.Vector;
 import java.util.WeakHashMap;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.helper.DefaultExecutor;
 import org.apache.tools.ant.input.DefaultInputHandler;
@@ -46,10 +48,8 @@
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceFactory;
 import org.apache.tools.ant.types.resources.FileResource;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
-import org.apache.tools.ant.util.StringUtils;
 import org.apache.tools.ant.util.VectorSet;
 
 /**
@@ -141,17 +141,20 @@
     private String description;
 
 
+    /** lock object used when adding/removing references */
+    private final Object referencesLock = new Object();
+
     /** Map of references within the project (paths etc) (String to Object). */
     private final Hashtable<String, Object> references = new AntRefTable();
 
     /** Map of id references - used for indicating broken build files */
-    private final HashMap<String, Object> idReferences = new HashMap<String, Object>();
+    private final HashMap<String, Object> idReferences = new HashMap<>();
 
     /** Name of the project's default target. */
     private String defaultTarget;
 
     /** Map from target names to targets (String to Target). */
-    private final Hashtable<String, Target> targets = new Hashtable<String, Target>();
+    private final Hashtable<String, Target> targets = new Hashtable<>();
 
     /** Set of global filters. */
     private final FilterSet globalFilterSet = new FilterSet();
@@ -179,12 +182,7 @@
 
     /** for each thread, record whether it is currently executing
         messageLogged */
-    private final ThreadLocal<Boolean> isLoggingMessage = new ThreadLocal<Boolean>() {
-            @Override
-            protected Boolean initialValue() {
-                return Boolean.FALSE;
-            }
-        };
+    private final ThreadLocal<Boolean> isLoggingMessage = ThreadLocal.withInitial(() -> Boolean.FALSE);
 
     /**
      * The Ant core classloader--may be <code>null</code> if using
@@ -194,11 +192,11 @@
 
     /** Records the latest task to be executed on a thread. */
     private final Map<Thread, Task> threadTasks
-            = Collections.synchronizedMap(new WeakHashMap<Thread, Task>());
+            = Collections.synchronizedMap(new WeakHashMap<>());
 
     /** Records the latest task to be executed on a thread group. */
     private final Map<ThreadGroup, Task> threadGroupTasks
-            = Collections.synchronizedMap(new WeakHashMap<ThreadGroup,Task>());
+            = Collections.synchronizedMap(new WeakHashMap<>());
 
     /**
      * Called to handle any input requests.
@@ -274,7 +272,7 @@
     public Project createSubProject() {
         Project subProject = null;
         try {
-            subProject = (getClass().newInstance());
+            subProject = getClass().getDeclaredConstructor().newInstance();
         } catch (final Exception e) {
             subProject = new Project();
         }
@@ -342,8 +340,8 @@
      * @return an appropriate classloader.
      */
     public AntClassLoader createClassLoader(final Path path) {
-        return AntClassLoader
-            .newAntClassLoader(getClass().getClassLoader(), this, path, true);
+        return createClassLoader(
+            Optional.ofNullable(getCoreLoader()).orElse(getClass().getClassLoader()), path);
     }
 
     /**
@@ -355,8 +353,7 @@
      *
      * @return an appropriate classloader.
      */
-    public AntClassLoader createClassLoader(
-        final ClassLoader parent, final Path path) {
+    public AntClassLoader createClassLoader(final ClassLoader parent, final Path path) {
         return AntClassLoader.newAntClassLoader(parent, this, path, true);
     }
 
@@ -438,10 +435,8 @@
      */
     public Vector<BuildListener> getBuildListeners() {
         synchronized (listenersLock) {
-            final Vector<BuildListener> r = new Vector<BuildListener>(listeners.length);
-            for (BuildListener listener : listeners) {
-                r.add(listener);
-            }
+            final Vector<BuildListener> r = new Vector<>(listeners.length);
+            Collections.addAll(r, listeners);
             return r;
         }
     }
@@ -647,14 +642,24 @@
 
     /**
      * Return a copy of the properties table.
-     * @return a hashtable containing all properties
-     *         (including user properties).
+     * @return a hashtable containing all properties (including user
+     *         properties) known to the project directly, does not
+     *         contain local properties.
      */
     public Hashtable<String, Object> getProperties() {
         return PropertyHelper.getPropertyHelper(this).getProperties();
     }
 
     /**
+     * Returns the names of all known properties.
+     * @since 1.10.9
+     * @return the names of all known properties including local user and local properties.
+     */
+    public Set<String> getPropertyNames() {
+        return PropertyHelper.getPropertyHelper(this).getPropertyNames();
+    }
+
+    /**
      * Return a copy of the user property hashtable.
      * @return a hashtable containing just the user properties.
      */
@@ -931,8 +936,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);
@@ -946,9 +951,7 @@
      */
     public void setSystemProperties() {
         final Properties systemP = System.getProperties();
-        final Enumeration<?> e = systemP.propertyNames();
-        while (e.hasMoreElements()) {
-            final String propertyName = (String) e.nextElement();
+        for (final String propertyName : systemP.stringPropertyNames()) {
             final String value = systemP.getProperty(propertyName);
             if (value != null) {
                 this.setPropertyInternal(propertyName, value);
@@ -1047,7 +1050,7 @@
      * @since Ant 1.8.1
      */
     public Map<String, Class<?>> getCopyOfTaskDefinitions() {
-        return new HashMap<String, Class<?>>(getTaskDefinitions());
+        return new HashMap<>(getTaskDefinitions());
     }
 
     /**
@@ -1089,7 +1092,7 @@
      * @since Ant 1.8.1
      */
     public Map<String, Class<?>> getCopyOfDataTypeDefinitions() {
-        return new HashMap<String, Class<?>>(getDataTypeDefinitions());
+        return new HashMap<>(getDataTypeDefinitions());
     }
 
     /**
@@ -1169,7 +1172,7 @@
      * @since Ant 1.8.1
      */
     public Map<String, Target> getCopyOfTargets() {
-        return new HashMap<String, Target>(targets);
+        return new HashMap<>(targets);
     }
 
     /**
@@ -1226,11 +1229,11 @@
             }
             log("Attempting to create object of type " + classname, MSG_DEBUG);
             try {
-                o = Class.forName(classname, true, coreLoader).newInstance();
+                o = Class.forName(classname, true, coreLoader).getDeclaredConstructor().newInstance();
             } catch (final ClassNotFoundException seaEnEfEx) {
                 //try the current classloader
                 try {
-                    o = Class.forName(classname).newInstance();
+                    o = Class.forName(classname).getDeclaredConstructor().newInstance();
                 } catch (final Exception ex) {
                     log(ex.toString(), MSG_ERR);
                 }
@@ -1257,8 +1260,8 @@
      */
     public void executeTargets(final Vector<String> names) throws BuildException {
         setUserProperty(MagicNames.PROJECT_INVOKED_TARGETS,
-                        CollectionUtils.flattenToString(names));
-        getExecutor().executeTargets(this, names.toArray(new String[names.size()]));
+                String.join(",", names));
+        getExecutor().executeTargets(this, names.toArray(new String[0]));
     }
 
     /**
@@ -1274,12 +1277,10 @@
         final Task task = getThreadTask(Thread.currentThread());
         if (task == null) {
             log(output, isWarning ? MSG_WARN : MSG_INFO);
+        } else if (isWarning) {
+            task.handleErrorOutput(output);
         } else {
-            if (isWarning) {
-                task.handleErrorOutput(output);
-            } else {
-                task.handleOutput(output);
-            }
+            task.handleOutput(output);
         }
     }
 
@@ -1298,12 +1299,11 @@
      */
     public int defaultInput(final byte[] buffer, final int offset, final int length)
         throws IOException {
-        if (defaultInputStream != null) {
-            System.out.flush();
-            return defaultInputStream.read(buffer, offset, length);
-        } else {
+        if (defaultInputStream == null) {
             throw new EOFException("No input provided for project");
         }
+        System.out.flush();
+        return defaultInputStream.read(buffer, offset, length);
     }
 
     /**
@@ -1323,9 +1323,8 @@
         final Task task = getThreadTask(Thread.currentThread());
         if (task == null) {
             return defaultInput(buffer, offset, length);
-        } else {
-            return task.handleInput(buffer, offset, length);
         }
+        return task.handleInput(buffer, offset, length);
     }
 
     /**
@@ -1343,12 +1342,10 @@
         final Task task = getThreadTask(Thread.currentThread());
         if (task == null) {
             fireMessageLogged(this, output, isError ? MSG_ERR : MSG_INFO);
+        } else if (isError) {
+            task.handleErrorFlush(output);
         } else {
-            if (isError) {
-                task.handleErrorFlush(output);
-            } else {
-                task.handleFlush(output);
-            }
+            task.handleFlush(output);
         }
     }
 
@@ -1384,13 +1381,11 @@
      */
     public void executeSortedTargets(final Vector<Target> sortedTargets)
         throws BuildException {
-        final Set<String> succeededTargets = new HashSet<String>();
+        final Set<String> succeededTargets = new HashSet<>();
         BuildException buildException = null; // first build exception
         for (final Target curtarget : sortedTargets) {
             boolean canExecute = true;
-            for (final Enumeration<String> depIter = curtarget.getDependencies();
-                 depIter.hasMoreElements();) {
-                final String dependencyName = depIter.nextElement();
+            for (final String dependencyName : Collections.list(curtarget.getDependencies())) {
                 if (!succeededTargets.contains(dependencyName)) {
                     canExecute = false;
                     log(curtarget,
@@ -1406,12 +1401,12 @@
                     curtarget.performTasks();
                     succeededTargets.add(curtarget.getName());
                 } catch (final RuntimeException ex) {
-                    if (!(keepGoingMode)) {
+                    if (!keepGoingMode) {
                         throw ex; // throw further
                     }
                     thrownException = ex;
                 } catch (final Throwable ex) {
-                    if (!(keepGoingMode)) {
+                    if (!keepGoingMode) {
                         throw new BuildException(ex);
                     }
                     thrownException = ex;
@@ -1750,9 +1745,9 @@
             return ((ProjectComponent) o).getProject();
         }
         try {
-            final Method m = o.getClass().getMethod("getProject", (Class[]) null);
-            if (Project.class == m.getReturnType()) {
-                return (Project) m.invoke(o, (Object[]) null);
+            final Method m = o.getClass().getMethod("getProject");
+            if (Project.class.equals(m.getReturnType())) {
+                return (Project) m.invoke(o);
             }
         } catch (final Exception e) {
             //too bad
@@ -1820,9 +1815,9 @@
      */
     public final Vector<Target> topoSort(final String[] roots, final Hashtable<String, Target> targetTable,
                                  final boolean returnAll) throws BuildException {
-        final Vector<Target> ret = new VectorSet<Target>();
-        final Hashtable<String, String> state = new Hashtable<String, String>();
-        final Stack<String> visiting = new Stack<String>();
+        final Vector<Target> ret = new VectorSet<>();
+        final Hashtable<String, String> state = new Hashtable<>();
+        final Stack<String> visiting = new Stack<>();
 
         // We first run a DFS based sort using each root as a starting node.
         // This creates the minimum sequence of Targets to the root node(s).
@@ -1841,17 +1836,13 @@
                         + root);
             }
         }
-        final StringBuffer buf = new StringBuffer("Build sequence for target(s)");
+        log("Build sequence for target(s)"
+                + Arrays.stream(roots).map(root -> String.format(" `%s'", root))
+                .collect(Collectors.joining(","))
+                + " is " + ret, MSG_VERBOSE);
 
-        for (int j = 0; j < roots.length; j++) {
-            buf.append((j == 0) ? " `" : ", `").append(roots[j]).append('\'');
-        }
-        buf.append(" is ").append(ret);
-        log(buf.toString(), MSG_VERBOSE);
-
-        final Vector<Target> complete = (returnAll) ? ret : new Vector<Target>(ret);
-        for (final Enumeration<String> en = targetTable.keys(); en.hasMoreElements();) {
-            final String curTarget = en.nextElement();
+        final Vector<Target> complete = (returnAll) ? ret : new Vector<>(ret);
+        for (final String curTarget : targetTable.keySet()) {
             final String st = state.get(curTarget);
             if (st == null) {
                 tsort(curTarget, targetTable, state, visiting, complete);
@@ -1929,8 +1920,7 @@
             }
             throw new BuildException(new String(sb));
         }
-        for (final Enumeration<String> en = target.getDependencies(); en.hasMoreElements();) {
-            final String cur = en.nextElement();
+        for (final String cur : Collections.list(target.getDependencies())) {
             final String m = state.get(cur);
             if (m == null) {
                 // Not been visited
@@ -1994,17 +1984,19 @@
      * @param value The value of the reference.
      */
     public void addReference(final String referenceName, final Object value) {
-        final Object old = ((AntRefTable) references).getReal(referenceName);
-        if (old == value) {
-            // no warning, this is not changing anything
-            return;
+        synchronized (referencesLock) {
+            final Object old = ((AntRefTable) references).getReal(referenceName);
+            if (old == value) {
+                // no warning, this is not changing anything
+                return;
+            }
+            if (old != null && !(old instanceof UnknownElement)) {
+                log("Overriding previous definition of reference to " + referenceName,
+                    MSG_VERBOSE);
+            }
+            log("Adding reference: " + referenceName, MSG_DEBUG);
+            references.put(referenceName, value);
         }
-        if (old != null && !(old instanceof UnknownElement)) {
-            log("Overriding previous definition of reference to " + referenceName,
-                MSG_VERBOSE);
-        }
-        log("Adding reference: " + referenceName, MSG_DEBUG);
-        references.put(referenceName, value);
     }
 
     /**
@@ -2025,7 +2017,9 @@
      * @since Ant 1.8.0
      */
     public boolean hasReference(final String key) {
-        return references.containsKey(key);
+        synchronized (referencesLock) {
+            return references.containsKey(key);
+        }
     }
 
     /**
@@ -2038,7 +2032,9 @@
      * @since Ant 1.8.1
      */
     public Map<String, Object> getCopyOfReferences() {
-        return new HashMap<String, Object>(references);
+        synchronized (referencesLock) {
+            return new HashMap<>(references);
+        }
     }
 
     /**
@@ -2052,11 +2048,14 @@
      *         there is no such reference in the project, with type inference.
      */
     public <T> T getReference(final String key) {
-        @SuppressWarnings("unchecked")
-        final T ret = (T) references.get(key);
-        if (ret != null) {
-            return ret;
+        synchronized (referencesLock) {
+            @SuppressWarnings("unchecked")
+            final T ret = (T) references.get(key);
+            if (ret != null) {
+                return ret;
+            }
         }
+
         if (!key.equals(MagicNames.REFID_PROPERTY_HELPER)) {
             try {
                 if (PropertyHelper.getPropertyHelper(this).containsProperties(key)) {
@@ -2238,8 +2237,8 @@
         if (message == null) {
             message = String.valueOf(message);
         }
-        if (message.endsWith(StringUtils.LINE_SEP)) {
-            final int endIndex = message.length() - StringUtils.LINE_SEP.length();
+        if (message.endsWith(System.lineSeparator())) {
+            final int endIndex = message.length() - System.lineSeparator().length();
             event.setMessage(message.substring(0, endIndex), priority);
         } else {
             event.setMessage(message, priority);
@@ -2254,7 +2253,7 @@
              * Log4jListener which invokes getLogger() which in
              * turn wants to write to the console).
              *
-             * @see http://marc.theaimsgroup.com/?t=110538624200006&r=1&w=2
+             * @see https://marc.info/?l=ant-user&m=111105127200101&w=2
              *
              * We now (Ant 1.6.3 and later) simply swallow the message.
              */
@@ -2481,6 +2480,7 @@
      * @return the file resource.
      * @since Ant 1.7
      */
+    @Override
     public Resource getResource(final String name) {
         return new FileResource(getBaseDir(), name);
     }
diff --git a/src/main/org/apache/tools/ant/ProjectComponent.java b/src/main/org/apache/tools/ant/ProjectComponent.java
index 830c9d6..8b5f5a7 100644
--- a/src/main/org/apache/tools/ant/ProjectComponent.java
+++ b/src/main/org/apache/tools/ant/ProjectComponent.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -163,6 +163,7 @@
      * @throws CloneNotSupportedException does not happen,
      *                                    but is declared to allow subclasses to do so.
      */
+    @Override
     public Object clone() throws CloneNotSupportedException {
         ProjectComponent pc = (ProjectComponent) super.clone();
         pc.setLocation(getLocation());
diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java
index 907430a..5cc7527 100644
--- a/src/main/org/apache/tools/ant/ProjectHelper.java
+++ b/src/main/org/apache/tools/ant/ProjectHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,18 +38,23 @@
  */
 public class ProjectHelper {
     /** The URI for ant name space */
-    public static final String ANT_CORE_URI    = "antlib:org.apache.tools.ant";
+    public static final String ANT_CORE_URI = MagicNames.ANTLIB_PREFIX
+            + MagicNames.ANT_CORE_PACKAGE;
 
     /** The URI for antlib current definitions */
     public static final String ANT_CURRENT_URI      = "ant:current";
 
     /** The URI for ant specific attributes
      * @since Ant 1.9.1
-     * */
+     */
     public static final String ANT_ATTRIBUTE_URI      = "ant:attribute";
 
-    /** The URI for defined types/tasks - the format is antlib:&lt;package&gt; */
-    public static final String ANTLIB_URI     = "antlib:";
+    /**
+     * The URI for defined types/tasks - the format is antlib:&lt;package&gt;
+     * @deprecated use MagicNames.ANTLIB_PREFIX
+     */
+    @Deprecated
+    public static final String ANTLIB_URI = MagicNames.ANTLIB_PREFIX;
 
     /** Polymorphic attribute  */
     public static final String ANT_TYPE = "ant-type";
@@ -57,18 +62,24 @@
     /**
      * Name of JVM system property which provides the name of the
      * ProjectHelper class to use.
+     * @deprecated use MagicNames.PROJECT_HELPER_CLASS
      */
+    @Deprecated
     public static final String HELPER_PROPERTY = MagicNames.PROJECT_HELPER_CLASS;
 
     /**
      * The service identifier in jars which provide Project Helper
      * implementations.
+     * @deprecated use MagicNames.PROJECT_HELPER_SERVICE
      */
+    @Deprecated
     public static final String SERVICE_ID = MagicNames.PROJECT_HELPER_SERVICE;
 
     /**
      * name of project helper reference that we add to a project
+     * @deprecated use MagicNames.REFID_PROJECT_HELPER
      */
+    @Deprecated
     public static final String PROJECTHELPER_REFERENCE = MagicNames.REFID_PROJECT_HELPER;
 
     /**
@@ -89,7 +100,7 @@
     public static void configureProject(Project project, File buildFile) throws BuildException {
         FileResource resource = new FileResource(buildFile);
         ProjectHelper helper = ProjectHelperRepository.getInstance().getProjectHelperForBuildFile(resource);
-        project.addReference(PROJECTHELPER_REFERENCE, helper);
+        project.addReference(MagicNames.REFID_PROJECT_HELPER, helper);
         helper.parse(project, buildFile);
     }
 
@@ -146,16 +157,12 @@
         }
     }
 
-    /** Default constructor */
-    public ProjectHelper() {
-    }
-
     // -------------------- Common properties  --------------------
     // The following properties are required by import (and other tasks
     // that read build files using ProjectHelper).
 
-    private Vector<Object> importStack = new Vector<Object>();
-    private List<String[]> extensionStack = new LinkedList<String[]>();
+    private Vector<Object> importStack = new Vector<>();
+    private List<String[]> extensionStack = new LinkedList<>();
 
     /**
      *  Import stack.
@@ -181,7 +188,7 @@
         return extensionStack;
     }
 
-    private static final ThreadLocal<String> targetPrefix = new ThreadLocal<String>();
+    private static final ThreadLocal<String> targetPrefix = new ThreadLocal<>();
 
     /**
      * The prefix to prepend to imported target names.
@@ -206,11 +213,7 @@
         targetPrefix.set(prefix);
     }
 
-    private static final ThreadLocal<String> prefixSeparator = new ThreadLocal<String>() {
-            protected String initialValue() {
-                return ".";
-            }
-        };
+    private static final ThreadLocal<String> prefixSeparator = ThreadLocal.withInitial(() -> ".");
 
     /**
      * The separator between the prefix and the target name.
@@ -234,11 +237,7 @@
         prefixSeparator.set(sep);
     }
 
-    private static final ThreadLocal<Boolean> inIncludeMode = new ThreadLocal<Boolean>() {
-            protected Boolean initialValue() {
-                return Boolean.FALSE;
-            }
-        };
+    private static final ThreadLocal<Boolean> inIncludeMode = ThreadLocal.withInitial(() -> Boolean.FALSE);
 
     /**
      * Whether the current file should be read in include as opposed
@@ -268,7 +267,7 @@
      * @since Ant 1.8.0
      */
     public static void setInIncludeMode(boolean includeMode) {
-        inIncludeMode.set(Boolean.valueOf(includeMode));
+        inIncludeMode.set(includeMode);
     }
 
     // --------------------  Parse method  --------------------
@@ -297,7 +296,7 @@
      * @see org.apache.tools.ant.ProjectHelperRepository#getHelpers()
      */
     public static ProjectHelper getProjectHelper() {
-        return (ProjectHelper) ProjectHelperRepository.getInstance().getHelpers().next();
+        return ProjectHelperRepository.getInstance().getHelpers().next();
     }
 
     /**
@@ -506,7 +505,7 @@
      * @return      The stringified form of the ns name
      */
     public static String genComponentName(String uri, String name) {
-        if (uri == null || uri.equals("") || uri.equals(ANT_CORE_URI)) {
+        if (uri == null || uri.isEmpty() || uri.equals(ANT_CORE_URI)) {
             return name;
         }
         return uri + ":" + name;
@@ -568,10 +567,8 @@
             return ex;
         }
         String errorMessage
-            = "The following error occurred while executing this line:"
-            + System.getProperty("line.separator")
-            + ex.getLocation().toString()
-            + ex.getMessage();
+            = String.format("The following error occurred while executing this line:%n%s%s",
+                ex.getLocation().toString(), ex.getMessage());
         if (ex instanceof ExitStatusException) {
             int exitStatus = ((ExitStatusException) ex).getStatus();
             if (newLocation == null) {
diff --git a/src/main/org/apache/tools/ant/ProjectHelperRepository.java b/src/main/org/apache/tools/ant/ProjectHelperRepository.java
index df5d1a0..8bee97f 100644
--- a/src/main/org/apache/tools/ant/ProjectHelperRepository.java
+++ b/src/main/org/apache/tools/ant/ProjectHelperRepository.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,14 +23,17 @@
 import java.lang.reflect.Constructor;
 import java.net.URL;
 import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.helper.ProjectHelper2;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.util.LoaderUtils;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * Repository of {@link ProjectHelper} found in the classpath or via
@@ -53,7 +56,7 @@
     private static ProjectHelperRepository instance =
         new ProjectHelperRepository();
 
-    private List<Constructor<? extends ProjectHelper>> helpers = new ArrayList<Constructor<? extends ProjectHelper>>();
+    private List<Constructor<? extends ProjectHelper>> helpers = new ArrayList<>();
 
     private static Constructor<ProjectHelper2> PROJECTHELPER2_CONSTRUCTOR;
 
@@ -76,35 +79,28 @@
 
     private void collectProjectHelpers() {
         // First, try the system property
-        Constructor<? extends ProjectHelper> projectHelper = getProjectHelperBySystemProperty();
-        registerProjectHelper(projectHelper);
+        registerProjectHelper(getProjectHelperBySystemProperty());
 
         // A JDK1.3 'service' (like in JAXP). That will plug a helper
         // automatically if in CLASSPATH, with the right META-INF/services.
         try {
             ClassLoader classLoader = LoaderUtils.getContextClassLoader();
             if (classLoader != null) {
-                Enumeration<URL> resources =
-                    classLoader.getResources(ProjectHelper.SERVICE_ID);
-                while (resources.hasMoreElements()) {
-                    URL resource = resources.nextElement();
+                for (URL resource : Collections.list(classLoader.getResources(MagicNames.PROJECT_HELPER_SERVICE))) {
                     URLConnection conn = resource.openConnection();
                     conn.setUseCaches(false);
-                    projectHelper =
-                        getProjectHelperByService(conn.getInputStream());
-                    registerProjectHelper(projectHelper);
+                    registerProjectHelper(getProjectHelperByService(conn.getInputStream()));
                 }
             }
 
             InputStream systemResource =
-                ClassLoader.getSystemResourceAsStream(ProjectHelper.SERVICE_ID);
+                ClassLoader.getSystemResourceAsStream(MagicNames.PROJECT_HELPER_SERVICE);
             if (systemResource != null) {
-                projectHelper = getProjectHelperByService(systemResource);
-                registerProjectHelper(projectHelper);
+                registerProjectHelper(getProjectHelperByService(systemResource));
             }
         } catch (Exception e) {
             System.err.println("Unable to load ProjectHelper from service "
-                               + ProjectHelper.SERVICE_ID + " ("
+                               + MagicNames.PROJECT_HELPER_SERVICE + " ("
                                + e.getClass().getName()
                                + ": " + e.getMessage() + ")");
             if (DEBUG) {
@@ -164,7 +160,7 @@
     }
 
     private Constructor<? extends ProjectHelper> getProjectHelperBySystemProperty() {
-        String helperClass = System.getProperty(ProjectHelper.HELPER_PROPERTY);
+        String helperClass = System.getProperty(MagicNames.PROJECT_HELPER_CLASS);
         try {
             if (helperClass != null) {
                 return getHelperConstructor(helperClass);
@@ -172,7 +168,7 @@
         } catch (SecurityException e) {
             System.err.println("Unable to load ProjectHelper class \""
                                + helperClass + " specified in system property "
-                               + ProjectHelper.HELPER_PROPERTY + " ("
+                               + MagicNames.PROJECT_HELPER_CLASS + " ("
                                + e.getMessage() + ")");
             if (DEBUG) {
                 e.printStackTrace(System.err); //NOSONAR
@@ -185,23 +181,17 @@
         try {
             // This code is needed by EBCDIC and other strange systems.
             // It's a fix for bugs reported in xerces
-            InputStreamReader isr;
-            try {
-                isr = new InputStreamReader(is, "UTF-8");
-            } catch (java.io.UnsupportedEncodingException e) {
-                isr = new InputStreamReader(is);
-            }
-            BufferedReader rd = new BufferedReader(isr);
-
+            BufferedReader rd = new BufferedReader(new InputStreamReader(is,
+                    StandardCharsets.UTF_8));
             String helperClassName = rd.readLine();
             rd.close();
 
-            if (helperClassName != null && !"".equals(helperClassName)) {
+            if (helperClassName != null && !helperClassName.isEmpty()) {
                 return getHelperConstructor(helperClassName);
             }
         } catch (Exception e) {
             System.out.println("Unable to load ProjectHelper from service "
-                    + ProjectHelper.SERVICE_ID + " (" + e.getMessage() + ")");
+                    + MagicNames.PROJECT_HELPER_SERVICE + " (" + e.getMessage() + ")");
             if (DEBUG) {
                 e.printStackTrace(System.err); //NOSONAR
             }
@@ -252,20 +242,19 @@
      * @return the first ProjectHelper that fit the requirement (never <code>null</code>).
      */
     public ProjectHelper getProjectHelperForBuildFile(Resource buildFile) throws BuildException {
-        for (Iterator<ProjectHelper> it = getHelpers(); it.hasNext();) {
-            ProjectHelper helper = it.next();
-            if (helper.canParseBuildFile(buildFile)) {
-                if (DEBUG) {
-                    System.out.println("ProjectHelper "
-                                       + helper.getClass().getName()
-                                       + " selected for the build file "
-                                       + buildFile);
-                }
-                return helper;
-            }
+        ProjectHelper ph = StreamUtils.iteratorAsStream(getHelpers())
+                .filter(helper -> helper.canParseBuildFile(buildFile))
+                .findFirst().orElse(null);
+
+        if (ph == null) {
+            throw new BuildException("BUG: at least the ProjectHelper2 should "
+                    + "have supported the file " + buildFile);
         }
-        throw new BuildException("BUG: at least the ProjectHelper2 should "
-                                   + "have supported the file " + buildFile);
+        if (DEBUG) {
+            System.out.println("ProjectHelper " + ph.getClass().getName()
+                    + " selected for the build file " + buildFile);
+        }
+        return ph;
     }
 
     /**
@@ -276,20 +265,19 @@
      * @return the first ProjectHelper that fit the requirement (never <code>null</code>).
      */
     public ProjectHelper getProjectHelperForAntlib(Resource antlib) throws BuildException {
-        for (Iterator<ProjectHelper> it = getHelpers(); it.hasNext();) {
-            ProjectHelper helper = it.next();
-            if (helper.canParseAntlibDescriptor(antlib)) {
-                if (DEBUG) {
-                    System.out.println("ProjectHelper "
-                                       + helper.getClass().getName()
-                                       + " selected for the antlib "
-                                       + antlib);
-                }
-                return helper;
-            }
+        ProjectHelper ph = StreamUtils.iteratorAsStream(getHelpers())
+                .filter(helper -> helper.canParseAntlibDescriptor(antlib))
+                .findFirst().orElse(null);
+
+        if (ph == null) {
+            throw new BuildException("BUG: at least the ProjectHelper2 should "
+                    + "have supported the file " + antlib);
         }
-        throw new BuildException("BUG: at least the ProjectHelper2 should "
-                                   + "have supported the file " + antlib);
+        if (DEBUG) {
+            System.out.println("ProjectHelper " + ph.getClass().getName()
+                    + " selected for the antlib " + antlib);
+        }
+        return ph;
     }
 
     /**
@@ -300,40 +288,15 @@
      * @return an iterator of {@link ProjectHelper}
      */
     public Iterator<ProjectHelper> getHelpers() {
-        return new ConstructingIterator(helpers.iterator());
-    }
-
-    private static class ConstructingIterator implements Iterator<ProjectHelper> {
-        private final Iterator<Constructor<? extends ProjectHelper>> nested;
-        private boolean empty = false;
-
-        ConstructingIterator(Iterator<Constructor<? extends ProjectHelper>> nested) {
-            this.nested = nested;
-        }
-
-        public boolean hasNext() {
-            return nested.hasNext() || !empty;
-        }
-
-        public ProjectHelper next() {
-            Constructor<? extends ProjectHelper> c;
-            if (nested.hasNext()) {
-                c = nested.next();
-            } else {
-                // last but not least, ant default project helper
-                empty = true;
-                c = PROJECTHELPER2_CONSTRUCTOR;
-            }
+        Stream.Builder<Constructor<? extends ProjectHelper>> b = Stream.builder();
+        helpers.forEach(b::add);
+        return b.add(PROJECTHELPER2_CONSTRUCTOR).build().map(c -> {
             try {
                 return c.newInstance();
             } catch (Exception e) {
                 throw new BuildException("Failed to invoke no-arg constructor"
-                                         + " on " + c.getName());
+                        + " on " + c.getName());
             }
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException("remove is not supported");
-        }
+        }).map(ProjectHelper.class::cast).iterator();
     }
 }
diff --git a/src/main/org/apache/tools/ant/PropertyHelper.java b/src/main/org/apache/tools/ant/PropertyHelper.java
index a447ef7..99d1a29 100644
--- a/src/main/org/apache/tools/ant/PropertyHelper.java
+++ b/src/main/org/apache/tools/ant/PropertyHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,20 +17,18 @@
  */
 package org.apache.tools.ant;
 
-import java.text.ParsePosition;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
 
 import org.apache.tools.ant.property.GetProperty;
 import org.apache.tools.ant.property.NullReturn;
-import org.apache.tools.ant.property.ParseNextProperty;
 import org.apache.tools.ant.property.ParseProperties;
 import org.apache.tools.ant.property.PropertyExpander;
 
@@ -163,7 +161,19 @@
             String property, Object value, PropertyHelper propertyHelper);
     }
 
-    //TODO PropertyEnumerator Delegate type, would improve PropertySet
+    /**
+     * Obtains the names of all known properties.
+     *
+     * @since 1.10.9
+     */
+    public interface PropertyEnumerator extends Delegate {
+        /**
+         * Returns the names of all properties known to this delegate.
+         *
+         * @return the names of all properties known to this delegate.
+         */
+        Set<String> getPropertyNames();
+    }
 
     //  --------------------------------------------------------
     //
@@ -184,52 +194,41 @@
         }
     };
 
-    private static final PropertyExpander DEFAULT_EXPANDER = new PropertyExpander() {
-        public String parsePropertyName(
-            String s, ParsePosition pos, ParseNextProperty notUsed) {
+    private static final PropertyExpander DEFAULT_EXPANDER =
+        (s, pos, notUsed) -> {
             int index = pos.getIndex();
             //directly check near, triggering characters:
-            if (s.length() - index >= 3
-                    && '$' == s.charAt(index) && '{' == s.charAt(index + 1)) {
+            if (s.length() - index >= 3 && '$' == s.charAt(index)
+                && '{' == s.charAt(index + 1)) {
                 int start = index + 2;
                 //defer to String.indexOf() for protracted check:
                 int end = s.indexOf('}', start);
                 if (end < 0) {
-                    throw new BuildException("Syntax error in property: "
-                            + s.substring(index));
+                    throw new BuildException(
+                        "Syntax error in property: " + s.substring(index));
                 }
                 pos.setIndex(end + 1);
-                return start == end ? "" :  s.substring(start, end);
+                return start == end ? "" : s.substring(start, end);
             }
             return null;
-        }
-    };
+        };
 
     /** dummy */
-    private static final PropertyExpander SKIP_DOUBLE_DOLLAR
-        = new PropertyExpander() {
-            // CheckStyle:LineLengthCheck OFF see too long
-            /**
-             * {@inheritDoc}
-             * @see org.apache.tools.ant.property.PropertyExpander#parsePropertyName(java.lang.String, java.text.ParsePosition, org.apache.tools.ant.property.ParseNextProperty)
-             */
-            // CheckStyle:LineLengthCheck ON
-            public String parsePropertyName(
-                String s, ParsePosition pos, ParseNextProperty notUsed) {
-                int index = pos.getIndex();
-                if (s.length() - index >= 2) {
-                    /* check for $$; if found, advance by one--
-                     * this expander is at the bottom of the stack
-                     * and will thus be the last consulted,
-                     * so the next thing that ParseProperties will do
-                     * is advance the parse position beyond the second $
-                     */
-                    if ('$' == s.charAt(index) && '$' == s.charAt(++index)) {
-                        pos.setIndex(index);
-                    }
+    private static final PropertyExpander SKIP_DOUBLE_DOLLAR =
+        (s, pos, notUsed) -> {
+            int index = pos.getIndex();
+            if (s.length() - index >= 2) {
+                /* check for $$; if found, advance by one--
+                 * this expander is at the bottom of the stack
+                 * and will thus be the last consulted,
+                 * so the next thing that ParseProperties will do
+                 * is advance the parse position beyond the second $
+                 */
+                if ('$' == s.charAt(index) && '$' == s.charAt(++index)) {
+                    pos.setIndex(index);
                 }
-                return null;
             }
+            return null;
         };
 
     /**
@@ -248,24 +247,24 @@
 
     private Project project;
     private PropertyHelper next;
-    private final Hashtable<Class<? extends Delegate>, List<Delegate>> delegates = new Hashtable<Class<? extends Delegate>, List<Delegate>>();
+    private final Hashtable<Class<? extends Delegate>, List<Delegate>> delegates = new Hashtable<>();
 
     /** Project properties map (usually String to String). */
-    private Hashtable<String, Object> properties = new Hashtable<String, Object>();
+    private final Hashtable<String, Object> properties = new Hashtable<>();
 
     /**
      * Map of "user" properties (as created in the Ant task, for example).
      * Note that these key/value pairs are also always put into the
      * project properties, so only the project properties need to be queried.
      */
-    private Hashtable<String, Object> userProperties = new Hashtable<String, Object>();
+    private final Hashtable<String, Object> userProperties = new Hashtable<>();
 
     /**
      * Map of inherited "user" properties - that are those "user"
      * properties that have been created by tasks and not been set
      * from the command line or a GUI tool.
      */
-    private Hashtable<String, Object> inheritedProperties = new Hashtable<String, Object>();
+    private final Hashtable<String, Object> inheritedProperties = new Hashtable<>();
 
     /**
      * Default constructor.
@@ -394,8 +393,7 @@
     public static synchronized PropertyHelper getPropertyHelper(Project project) {
         PropertyHelper helper = null;
         if (project != null) {
-            helper = (PropertyHelper) project.getReference(MagicNames
-                                                           .REFID_PROPERTY_HELPER);
+            helper = project.getReference(MagicNames.REFID_PROPERTY_HELPER);
         }
         if (helper != null) {
             return helper;
@@ -453,11 +451,8 @@
                                    boolean inherited, boolean user,
                                    boolean isNew) {
         if (getNext() != null) {
-            boolean subst = getNext().setPropertyHook(ns, name, value, inherited, user, isNew);
             // If next has handled the property
-            if (subst) {
-                return true;
-            }
+            return getNext().setPropertyHook(ns, name, value, inherited, user, isNew);
         }
         return false;
     }
@@ -860,6 +855,18 @@
     }
 
     /**
+     * Returns the names of all known properties.
+     * @since 1.10.9
+     * @return the names of all known properties.
+     */
+    public Set<String> getPropertyNames() {
+        final Set<String> names = new HashSet<>(getProperties().keySet());
+        getDelegates(PropertyEnumerator.class)
+            .forEach(e -> names.addAll(e.getPropertyNames()));
+        return Collections.unmodifiableSet(names);
+    }
+
+    /**
      * Returns the value of a user property, if it is set.
      *
      * <p>Delegates to the one-arg version ignoring the ns parameter.</p>
@@ -911,7 +918,7 @@
     public Hashtable<String, Object> getProperties() {
         //avoid concurrent modification:
         synchronized (properties) {
-            return new Hashtable<String, Object>(properties);
+            return new Hashtable<>(properties);
         }
         // There is a better way to save the context. This shouldn't
         // delegate to next, it's for backward compatibility only.
@@ -928,7 +935,7 @@
     public Hashtable<String, Object> getUserProperties() {
         //avoid concurrent modification:
         synchronized (userProperties) {
-            return new Hashtable<String, Object>(userProperties);
+            return new Hashtable<>(userProperties);
         }
     }
 
@@ -943,7 +950,7 @@
     public Hashtable<String, Object> getInheritedProperties() {
         //avoid concurrent modification:
         synchronized (inheritedProperties) {
-            return new Hashtable<String, Object>(inheritedProperties);
+            return new Hashtable<>(inheritedProperties);
         }
     }
 
@@ -991,14 +998,11 @@
     public void copyInheritedProperties(Project other) {
         //avoid concurrent modification:
         synchronized (inheritedProperties) {
-            Enumeration<String> e = inheritedProperties.keys();
-            while (e.hasMoreElements()) {
-                String arg = e.nextElement().toString();
-                if (other.getUserProperty(arg) != null) {
-                    continue;
+            for (Map.Entry<String, Object> entry : inheritedProperties.entrySet()) {
+                String arg = entry.getKey();
+                if (other.getUserProperty(arg) == null) {
+                    other.setInheritedProperty(arg, entry.getValue().toString());
                 }
-                Object value = inheritedProperties.get(arg);
-                other.setInheritedProperty(arg, value.toString());
             }
         }
     }
@@ -1021,14 +1025,11 @@
     public void copyUserProperties(Project other) {
         //avoid concurrent modification:
         synchronized (userProperties) {
-            Enumeration<String> e = userProperties.keys();
-            while (e.hasMoreElements()) {
-                Object arg = e.nextElement();
-                if (inheritedProperties.containsKey(arg)) {
-                    continue;
+            for (Map.Entry<String, Object> entry : userProperties.entrySet()) {
+                String arg = entry.getKey();
+                if (!inheritedProperties.containsKey(arg)) {
+                    other.setUserProperty(arg, entry.getValue().toString());
                 }
-                Object value = userProperties.get(arg);
-                other.setUserProperty(arg.toString(), value.toString());
             }
         }
     }
@@ -1037,7 +1038,7 @@
     // Moved from ProjectHelper. You can override the static method -
     // this is used for backward compatibility (for code that calls
     // the parse method in ProjectHelper).
-
+    
     /**
      * Default parsing method. It is here only to support backward compatibility
      * for the static ProjectHelper.parsePropertyString().
@@ -1047,7 +1048,7 @@
         int prev = 0;
         int pos;
         //search for the next instance of $ from the 'prev' position
-        while ((pos = value.indexOf("$", prev)) >= 0) {
+        while ((pos = value.indexOf('$', prev)) >= 0) {
 
             //if there was any text before this, add it as a fragment
             //TODO, this check could be modified to go if pos>prev;
@@ -1071,12 +1072,11 @@
                 if (value.charAt(pos + 1) == '$') {
                     //backwards compatibility two $ map to one mode
                     fragments.addElement("$");
-                    prev = pos + 2;
                 } else {
                     //new behaviour: $X maps to $X for all values of X!='$'
                     fragments.addElement(value.substring(pos, pos + 2));
-                    prev = pos + 2;
                 }
+                prev = pos + 2;
             } else {
                 //property found, extract its name or bail on a typo
                 int endName = value.indexOf('}', pos);
@@ -1107,10 +1107,10 @@
             for (Class<? extends Delegate> key : getDelegateInterfaces(delegate)) {
                 List<Delegate> list = delegates.get(key);
                 if (list == null) {
-                    list = new ArrayList<Delegate>();
+                    list = new ArrayList<>();
                 } else {
                     //copy on write, top priority
-                    list = new ArrayList<Delegate>(list);
+                    list = new ArrayList<>(list);
                     list.remove(delegate);
                 }
                 list.add(0, delegate);
@@ -1131,7 +1131,7 @@
     protected <D extends Delegate> List<D> getDelegates(Class<D> type) {
         @SuppressWarnings("unchecked")
         final List<D> result = (List<D>) delegates.get(type);
-        return result == null ? Collections.<D> emptyList() : result;
+        return result == null ? Collections.emptyList() : result;
     }
 
     /**
@@ -1140,16 +1140,14 @@
      * @return Set&lt;Class&gt;
      * @since Ant 1.8.0
      */
+    @SuppressWarnings("unchecked")
     protected static Set<Class<? extends Delegate>> getDelegateInterfaces(Delegate d) {
-        final HashSet<Class<? extends Delegate>> result = new HashSet<Class<? extends Delegate>>();
+        final HashSet<Class<? extends Delegate>> result = new HashSet<>();
         Class<?> c = d.getClass();
         while (c != null) {
             for (Class<?> ifc : c.getInterfaces()) {
                 if (Delegate.class.isAssignableFrom(ifc)) {
-                    @SuppressWarnings("unchecked")
-                    final Class<? extends Delegate> delegateInterface =
-                            (Class<? extends Delegate>) ifc;
-                    result.add(delegateInterface);
+                    result.add((Class<? extends Delegate>) ifc);
                 }
             }
             c = c.getSuperclass();
@@ -1192,7 +1190,6 @@
      */
     private static boolean nullOrEmpty(Object value) {
         return value == null || "".equals(value);
-
     }
 
     /**
@@ -1206,7 +1203,7 @@
     private boolean evalAsBooleanOrPropertyName(Object value) {
         Boolean b = toBoolean(value);
         if (b != null) {
-            return b.booleanValue();
+            return b;
         }
         return getProperty(String.valueOf(value)) != null;
     }
diff --git a/src/main/org/apache/tools/ant/RuntimeConfigurable.java b/src/main/org/apache/tools/ant/RuntimeConfigurable.java
index ebd6c11..001c9d8 100644
--- a/src/main/org/apache/tools/ant/RuntimeConfigurable.java
+++ b/src/main/org/apache/tools/ant/RuntimeConfigurable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,12 +24,12 @@
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.LinkedHashMap;
-import java.util.Map.Entry;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.tools.ant.attribute.EnableAttribute;
 import org.apache.tools.ant.taskdefs.MacroDef.Attribute;
 import org.apache.tools.ant.taskdefs.MacroInstance;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.xml.sax.AttributeList;
 import org.xml.sax.helpers.AttributeListImpl;
 
@@ -43,16 +43,12 @@
     /** Serialization version */
     private static final long serialVersionUID = 1L;
 
-    /** Empty Hashtable. */
-    private static final Hashtable<String, Object> EMPTY_HASHTABLE =
-            new Hashtable<String, Object>(0);
-
     /** Name of the element to configure. */
     private String elementTag = null;
 
     /** List of child element wrappers. */
     // picking ArrayList rather than List as arrayList is Serializable
-    private ArrayList<RuntimeConfigurable> children = null;
+    private List<RuntimeConfigurable> children = null;
 
     /** The element to configure. It is only used during
      * maybeConfigure.
@@ -119,6 +115,7 @@
     }
 
     private static class EnableAttributeConsumer {
+        @SuppressWarnings("unused")
         public void add(EnableAttribute b) {
             // Ignore
         }
@@ -154,7 +151,7 @@
      * @return AttributeComponentInformation instance
      */
     private AttributeComponentInformation isRestrictedAttribute(String name, ComponentHelper componentHelper) {
-        if (name.indexOf(':') == -1) {
+        if (!name.contains(":")) {
             return new AttributeComponentInformation(null, false);
         }
         String componentName = attrToComponent(name);
@@ -176,6 +173,7 @@
      *              false.
      * @since 1.9.1
      */
+    @SuppressWarnings("deprecation")
     public boolean isEnabled(UnknownElement owner) {
         if (!namespacedAttribute) {
             return true;
@@ -183,16 +181,15 @@
         ComponentHelper componentHelper = ComponentHelper
             .getComponentHelper(owner.getProject());
 
-        IntrospectionHelper ih
-            = IntrospectionHelper.getHelper(
-                owner.getProject(), EnableAttributeConsumer.class);
-        for (int i = 0; i < attributeMap.keySet().size(); ++i) {
-            String name = (String) attributeMap.keySet().toArray()[i];
-            AttributeComponentInformation attributeComponentInformation = isRestrictedAttribute(name, componentHelper);
+        IntrospectionHelper ih = IntrospectionHelper.getHelper(owner.getProject(),
+                EnableAttributeConsumer.class);
+        for (Map.Entry<String, Object> entry : attributeMap.entrySet()) {
+            AttributeComponentInformation attributeComponentInformation
+                    = isRestrictedAttribute(entry.getKey(), componentHelper);
             if (!attributeComponentInformation.isRestricted())  {
                 continue;
             }
-            String value = (String) attributeMap.get(name);
+            String value = (String) entry.getValue();
             EnableAttribute enable = null;
             try {
                 enable = (EnableAttribute)
@@ -286,7 +283,7 @@
      * @param value the attribute's value.
      */
     public synchronized void setAttribute(String name, String value) {
-        if (name.indexOf(':') != -1) {
+        if (name.contains(":")) {
             namespacedAttribute = true;
         }
         setAttribute(name, (Object) value);
@@ -304,17 +301,17 @@
             this.polyType = value == null ? null : value.toString();
         } else {
             if (attributeMap == null) {
-                attributeMap = new LinkedHashMap<String, Object>();
+                attributeMap = new LinkedHashMap<>();
             }
-            if (name.equalsIgnoreCase("refid") && !attributeMap.isEmpty()) {
-                LinkedHashMap<String, Object> newAttributeMap = new LinkedHashMap<String, Object>();
+            if ("refid".equalsIgnoreCase(name) && !attributeMap.isEmpty()) {
+                LinkedHashMap<String, Object> newAttributeMap = new LinkedHashMap<>();
                 newAttributeMap.put(name, value);
                 newAttributeMap.putAll(attributeMap);
                 attributeMap = newAttributeMap;
             } else {
                 attributeMap.put(name, value);
             }
-            if (name.equals("id")) {
+            if ("id".equals(name)) {
                 this.id = value == null ? null : value.toString();
             }
         }
@@ -335,8 +332,7 @@
      * @since Ant 1.6
      */
     public synchronized Hashtable<String, Object> getAttributeMap() {
-        return (attributeMap == null)
-            ? EMPTY_HASHTABLE : new Hashtable<String, Object>(attributeMap);
+        return new Hashtable<>(attributeMap == null ? Collections.emptyMap() : attributeMap);
     }
 
     /**
@@ -358,7 +354,7 @@
      *              Must not be <code>null</code>.
      */
     public synchronized void addChild(RuntimeConfigurable child) {
-        children = (children == null) ? new ArrayList<RuntimeConfigurable>() : children;
+        children = (children == null) ? new ArrayList<>() : children;
         children.add(child);
     }
 
@@ -380,7 +376,7 @@
      * @since Ant 1.6
      */
     public synchronized Enumeration<RuntimeConfigurable> getChildren() {
-        return (children == null) ? new CollectionUtils.EmptyEnumeration<RuntimeConfigurable>()
+        return (children == null) ? Collections.emptyEnumeration()
             : Collections.enumeration(children);
     }
 
@@ -391,7 +387,7 @@
      *        Should not be <code>null</code>.
      */
     public synchronized void addText(String data) {
-        if (data.length() == 0) {
+        if (data.isEmpty()) {
             return;
         }
         characters = (characters == null)
@@ -492,15 +488,16 @@
             return;
         }
 
-        // Configure the object
-        Object target = (wrappedObject instanceof TypeAdapter)
-            ? ((TypeAdapter) wrappedObject).getProxy() : wrappedObject;
-
-        IntrospectionHelper ih =
-            IntrospectionHelper.getHelper(p, target.getClass());
-         ComponentHelper componentHelper = ComponentHelper.getComponentHelper(p);
         if (attributeMap != null) {
-            for (Entry<String, Object> entry : attributeMap.entrySet()) {
+            // Configure the object
+            Object target = (wrappedObject instanceof TypeAdapter)
+                    ? ((TypeAdapter) wrappedObject).getProxy() : wrappedObject;
+                    
+            IntrospectionHelper ih =
+                    IntrospectionHelper.getHelper(p, target.getClass());
+            ComponentHelper componentHelper = ComponentHelper.getComponentHelper(p);
+
+            for (Map.Entry<String, Object> entry : attributeMap.entrySet()) {
                 String name = entry.getKey();
                 // skip restricted attributes such as if:set
                 AttributeComponentInformation attributeComponentInformation = isRestrictedAttribute(name, componentHelper);
@@ -512,8 +509,8 @@
                 // MacroInstance where properties are expanded for the
                 // nested sequential
                 Object attrValue;
-                if (value instanceof Evaluable) {
-                    attrValue = ((Evaluable) value).eval();
+                if (value instanceof Evaluable<?>) {
+                    attrValue = ((Evaluable<?>) value).eval();
                 } else {
                     attrValue = PropertyHelper.getPropertyHelper(p).parseProperties(value.toString());
                 }
@@ -531,23 +528,22 @@
                     ih.setAttribute(p, target, name, attrValue);
                 } catch (UnsupportedAttributeException be) {
                     // id attribute must be set externally
-                    if (name.equals("id")) {
-                        // Do nothing
-                    } else if (getElementTag() == null) {
-                        throw be;
-                    } else {
-                        throw new BuildException(
-                            getElementTag() + " doesn't support the \""
-                            + be.getAttribute() + "\" attribute", be);
+                    if (!"id".equals(name)) {
+                        if (getElementTag() == null) {
+                            throw be;
+                        } else {
+                            throw new BuildException(
+                                getElementTag() + " doesn't support the \""
+                                + be.getAttribute() + "\" attribute", be);
+                        }
                     }
                 } catch (BuildException be) {
-                    if (name.equals("id")) {
-                        // Assume that this is an not supported attribute type
-                        // thrown for example by a dynamic attribute task
-                        // Do nothing
-                    } else {
+                    if (!"id".equals(name)) {
                         throw be;
                     }
+                    // Assume that this is an not supported attribute type
+                    // thrown for example by a dynamic attribute task --
+                    // do nothing
                 }
             }
         }
@@ -593,7 +589,7 @@
 
         // Children (this is a shadow of UnknownElement#children)
         if (r.children != null) {
-            ArrayList<RuntimeConfigurable> newChildren = new ArrayList<RuntimeConfigurable>(r.children);
+            List<RuntimeConfigurable> newChildren = new ArrayList<>(r.children);
             if (children != null) {
                 newChildren.addAll(children);
             }
@@ -603,7 +599,7 @@
         // Text
         if (r.characters != null) {
             if (characters == null
-                || characters.toString().trim().length() == 0) {
+                || characters.toString().trim().isEmpty()) {
                 characters = new StringBuffer(r.characters.toString());
             }
         }
diff --git a/src/main/org/apache/tools/ant/SubBuildListener.java b/src/main/org/apache/tools/ant/SubBuildListener.java
index 196a88b..9a5ec60 100644
--- a/src/main/org/apache/tools/ant/SubBuildListener.java
+++ b/src/main/org/apache/tools/ant/SubBuildListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/Target.java b/src/main/org/apache/tools/ant/Target.java
index 33b8b72..af8bfad 100644
--- a/src/main/org/apache/tools/ant/Target.java
+++ b/src/main/org/apache/tools/ant/Target.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,7 +55,7 @@
     private List<String> dependencies = null;
 
     /** Children of this target (tasks and data types). */
-    private List<Object> children = new ArrayList<Object>();
+    private List<Object> children = new ArrayList<>();
 
     /** Since Ant 1.6.2 */
     private Location location = Location.UNKNOWN_LOCATION;
@@ -145,36 +145,37 @@
     public static List<String> parseDepends(String depends,
                                                 String targetName,
                                                 String attributeName) {
-        List<String> list = new ArrayList<String>();
-        if (depends.length() > 0) {
-            StringTokenizer tok =
-                new StringTokenizer(depends, ",", true);
-            while (tok.hasMoreTokens()) {
-                String token = tok.nextToken().trim();
+        if (depends.isEmpty()) {
+            return new ArrayList<>();
+        }
 
-                // Make sure the dependency is not empty string
-                if ("".equals(token) || ",".equals(token)) {
+        List<String> list = new ArrayList<>();
+        StringTokenizer tok = new StringTokenizer(depends, ",", true);
+        while (tok.hasMoreTokens()) {
+            String token = tok.nextToken().trim();
+
+            // Make sure the dependency is not empty string
+            if (token.isEmpty() || ",".equals(token)) {
+                throw new BuildException("Syntax Error: "
+                                         + attributeName
+                                         + " attribute of target \""
+                                         + targetName
+                                         + "\" contains an empty string.");
+            }
+
+            list.add(token);
+
+            // Make sure that depends attribute does not
+            // end in a ,
+            if (tok.hasMoreTokens()) {
+                token = tok.nextToken();
+                if (!tok.hasMoreTokens() || !",".equals(token)) {
                     throw new BuildException("Syntax Error: "
                                              + attributeName
-                                             + " attribute of target \""
+                                             + " attribute for target \""
                                              + targetName
-                                             + "\" contains an empty string.");
-                }
-
-                list.add(token);
-
-                // Make sure that depends attribute does not
-                // end in a ,
-                if (tok.hasMoreTokens()) {
-                    token = tok.nextToken();
-                    if (!tok.hasMoreTokens() || !",".equals(token)) {
-                        throw new BuildException("Syntax Error: "
-                                                 + attributeName
-                                                 + " attribute for target \""
-                                                 + targetName
-                                                 + "\" ends with a \",\" "
-                                                 + "character");
-                    }
+                                             + "\" ends with a \",\" "
+                                             + "character");
                 }
             }
         }
@@ -225,13 +226,13 @@
      * @return an array of the tasks currently within this target
      */
     public Task[] getTasks() {
-        List<Task> tasks = new ArrayList<Task>(children.size());
+        List<Task> tasks = new ArrayList<>(children.size());
         for (Object o : children) {
             if (o instanceof Task) {
                 tasks.add((Task) o);
             }
         }
-        return tasks.toArray(new Task[tasks.size()]);
+        return tasks.toArray(new Task[0]);
     }
 
     /**
@@ -242,7 +243,7 @@
      */
     public void addDependency(String dependency) {
         if (dependencies == null) {
-            dependencies = new ArrayList<String>(2);
+            dependencies = new ArrayList<>(2);
         }
         dependencies.add(dependency);
     }
@@ -253,8 +254,8 @@
      * @return an enumeration of the dependencies of this target (enumeration of String)
      */
     public Enumeration<String> getDependencies() {
-        return Collections
-                .enumeration(dependencies == null ? Collections.<String> emptyList() : dependencies);
+        return dependencies == null ? Collections.emptyEnumeration()
+            : Collections.enumeration(dependencies);
     }
 
     /**
@@ -284,7 +285,12 @@
      */
     public void setIf(String property) {
         ifString = property == null ? "" : property;
-        setIf(new IfStringCondition(ifString));
+        setIf(() -> {
+            PropertyHelper propertyHelper =
+                PropertyHelper.getPropertyHelper(getProject());
+            Object o = propertyHelper.parseProperties(ifString);
+            return propertyHelper.testIfCondition(o);
+        });
     }
 
     /**
@@ -295,7 +301,7 @@
      * @since 1.6.2
      */
     public String getIf() {
-        return "".equals(ifString) ? null : ifString;
+        return ifString.isEmpty() ? null : ifString;
     }
 
     /**
@@ -332,7 +338,12 @@
      */
     public void setUnless(String property) {
         unlessString = property == null ? "" : property;
-        setUnless(new UnlessStringCondition(unlessString));
+        setUnless(() -> {
+            PropertyHelper propertyHelper =
+                PropertyHelper.getPropertyHelper(getProject());
+            Object o = propertyHelper.parseProperties(unlessString);
+            return !propertyHelper.testUnlessCondition(o);
+        });
     }
 
     /**
@@ -343,7 +354,7 @@
      * @since 1.6.2
      */
     public String getUnless() {
-        return "".equals(unlessString) ? null : unlessString;
+        return unlessString.isEmpty() ? null : unlessString;
     }
 
     /**
@@ -392,6 +403,7 @@
      * @return the name of this target, or <code>null</code> if the
      *         name has not been set yet.
      */
+    @Override
     public String toString() {
         return name;
     }
@@ -493,42 +505,4 @@
             children.set(index, o);
         }
     }
-
-    /**
-     * Condition evaluating the 'if' attribute with the PropertyHelper.
-     */
-    private class IfStringCondition implements Condition {
-
-        private String condition;
-
-        public IfStringCondition(String condition) {
-            this.condition = condition;
-        }
-
-        public boolean eval() throws BuildException {
-            PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(getProject());
-            Object o = propertyHelper.parseProperties(condition);
-            return propertyHelper.testIfCondition(o);
-        }
-
-    }
-
-    /**
-     * Condition evaluating the 'unless' attribute with the PropertyHelper.
-     */
-    private class UnlessStringCondition implements Condition {
-
-        private String condition;
-
-        public UnlessStringCondition(String condition) {
-            this.condition = condition;
-        }
-
-        public boolean eval() throws BuildException {
-            PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(getProject());
-            Object o = propertyHelper.parseProperties(condition);
-            return !propertyHelper.testUnlessCondition(o);
-        }
-
-    }
 }
diff --git a/src/main/org/apache/tools/ant/Task.java b/src/main/org/apache/tools/ant/Task.java
index 7e349cb..ed22c0a 100644
--- a/src/main/org/apache/tools/ant/Task.java
+++ b/src/main/org/apache/tools/ant/Task.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant;
 
 import java.io.IOException;
-import java.util.Enumeration;
+import java.util.Collections;
 
 import org.apache.tools.ant.dispatch.DispatchUtils;
 
@@ -85,10 +85,6 @@
      */
     private boolean invalid;
 
-    /** Sole constructor. */
-    public Task() {
-    }
-
     /**
      * Sets the target container of this task.
      *
@@ -201,12 +197,10 @@
      * @exception BuildException if the task cannot be configured.
      */
     public void maybeConfigure() throws BuildException {
-        if (!invalid) {
-            if (wrapper != null) {
-                wrapper.maybeConfigure(getProject());
-            }
-        } else {
+        if (invalid) {
             getReplacement();
+        } else if (wrapper != null) {
+            wrapper.maybeConfigure(getProject());
         }
     }
 
@@ -294,10 +288,10 @@
      *                 be logged.
      */
     public void log(String msg, int msgLevel) {
-        if (getProject() != null) {
-            getProject().log(this, msg, msgLevel);
-        } else {
+        if (getProject() == null) {
             super.log(msg, msgLevel);
+        } else {
+            getProject().log(this, msg, msgLevel);
         }
     }
 
@@ -327,10 +321,10 @@
      * @since 1.7
      */
     public void log(String msg, Throwable t, int msgLevel) {
-        if (getProject() != null) {
-            getProject().log(this, msg, t, msgLevel);
-        } else {
+        if (getProject() == null) {
             super.log(msg, msgLevel);
+        } else {
+            getProject().log(this, msg, t, msgLevel);
         }
     }
 
@@ -344,7 +338,11 @@
      * is still fired, but with the exception as the cause.
      */
     public final void perform() {
-        if (!invalid) {
+        if (invalid) {
+            UnknownElement ue = getReplacement();
+            Task task = ue.getTask();
+            task.perform();
+        } else {
             getProject().fireTaskStarted(this);
             Throwable reason = null;
             try {
@@ -367,10 +365,6 @@
             } finally {
                 getProject().fireTaskFinished(this, reason);
             }
-        } else {
-            UnknownElement ue = getReplacement();
-            Task task = ue.getTask();
-            task.perform();
         }
     }
 
@@ -431,11 +425,8 @@
      */
     private void replaceChildren(RuntimeConfigurable wrapper,
                                  UnknownElement parentElement) {
-        Enumeration<RuntimeConfigurable> e = wrapper.getChildren();
-        while (e.hasMoreElements()) {
-            RuntimeConfigurable childWrapper = e.nextElement();
-            UnknownElement childElement =
-                new UnknownElement(childWrapper.getElementTag());
+        for (RuntimeConfigurable childWrapper : Collections.list(wrapper.getChildren())) {
+            UnknownElement childElement = new UnknownElement(childWrapper.getElementTag());
             parentElement.addChild(childElement);
             childElement.setProject(getProject());
             childElement.setRuntimeConfigurableWrapper(childWrapper);
diff --git a/src/main/org/apache/tools/ant/TaskAdapter.java b/src/main/org/apache/tools/ant/TaskAdapter.java
index d4d8c32..77d8688 100644
--- a/src/main/org/apache/tools/ant/TaskAdapter.java
+++ b/src/main/org/apache/tools/ant/TaskAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -81,7 +81,7 @@
             // don't have to check for interface, since then
             // taskClass would be abstract too.
             try {
-                final Method executeM = taskClass.getMethod("execute", (Class[]) null);
+                final Method executeM = taskClass.getMethod("execute");
                 // don't have to check for public, since
                 // getMethod finds public method only.
                 // don't have to check for abstract, since then
@@ -122,10 +122,10 @@
      */
     public void execute() throws BuildException {
         try {
-            Method setLocationM = proxy.getClass().getMethod(
-                "setLocation", new Class[] {Location.class});
+            Method setLocationM =
+                proxy.getClass().getMethod("setLocation", Location.class);
             if (setLocationM != null) {
-                setLocationM.invoke(proxy, new Object[] {getLocation()});
+                setLocationM.invoke(proxy, getLocation());
             }
         } catch (NoSuchMethodException e) {
             // ignore this if the class being used as a task does not have
@@ -137,10 +137,10 @@
         }
 
         try {
-            Method setProjectM = proxy.getClass().getMethod(
-                "setProject", new Class[] {Project.class});
+            Method setProjectM =
+                proxy.getClass().getMethod("setProject", Project.class);
             if (setProjectM != null) {
-                setProjectM.invoke(proxy, new Object[] {getProject()});
+                setProjectM.invoke(proxy, getProject());
             }
         } catch (NoSuchMethodException e) {
             // ignore this if the class being used as a task does not have
diff --git a/src/main/org/apache/tools/ant/TaskConfigurationChecker.java b/src/main/org/apache/tools/ant/TaskConfigurationChecker.java
index 9a52043..aa711f8 100644
--- a/src/main/org/apache/tools/ant/TaskConfigurationChecker.java
+++ b/src/main/org/apache/tools/ant/TaskConfigurationChecker.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,8 +23,8 @@
 /**
  * <p>Helper class for the check of the configuration of a given task.
  * This class provides methods for making assumptions about the task configuration.
- * After collecting all violations with <tt>assert*</tt> and <tt>fail</tt>
- * methods the <tt>checkErrors</tt> will throw a BuildException with all collected
+ * After collecting all violations with <code>assert*</code> and <code>fail</code>
+ * methods the <code>checkErrors</code> will throw a BuildException with all collected
  * messages or does nothing if there wasn't any error.</p>
  *
  * <p>Example:</p>
@@ -50,12 +50,12 @@
  *     }
  * </pre>
  *
- * @see <a href="http://martinfowler.com/eaaDev/Notification.html">Notification Pattern</a>
+ * @see <a href="https://martinfowler.com/eaaDev/Notification.html">Notification Pattern</a>
  */
 public class TaskConfigurationChecker {
 
     /** List of all collected error messages. */
-    private List<String> errors = new ArrayList<String>();
+    private List<String> errors = new ArrayList<>();
 
     /** Task for which the configuration should be checked. */
     private final Task task;
@@ -94,15 +94,10 @@
      */
     public void checkErrors() throws BuildException {
         if (!errors.isEmpty()) {
-            StringBuffer sb = new StringBuffer();
-            sb.append("Configuration error on <");
-            sb.append(task.getTaskName());
-            sb.append(">:");
-            sb.append(System.getProperty("line.separator"));
+            StringBuilder sb = new StringBuilder(String.format("Configuration error on <%s>:%n",
+                    task.getTaskName()));
             for (String msg : errors) {
-                sb.append("- ");
-                sb.append(msg);
-                sb.append(System.getProperty("line.separator"));
+                sb.append(String.format("- %s%n", msg));
             }
             throw new BuildException(sb.toString(), task.getLocation());
         }
diff --git a/src/main/org/apache/tools/ant/TaskContainer.java b/src/main/org/apache/tools/ant/TaskContainer.java
index f742e9e..238eb3c 100644
--- a/src/main/org/apache/tools/ant/TaskContainer.java
+++ b/src/main/org/apache/tools/ant/TaskContainer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/TypeAdapter.java b/src/main/org/apache/tools/ant/TypeAdapter.java
index b8520fc..4dc5e03 100644
--- a/src/main/org/apache/tools/ant/TypeAdapter.java
+++ b/src/main/org/apache/tools/ant/TypeAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/UnknownElement.java b/src/main/org/apache/tools/ant/UnknownElement.java
index f0a274e..0bb755a 100644
--- a/src/main/org/apache/tools/ant/UnknownElement.java
+++ b/src/main/org/apache/tools/ant/UnknownElement.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,10 +20,11 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import org.apache.tools.ant.taskdefs.PreSetDef;
 
@@ -158,7 +159,8 @@
      * @exception BuildException if the configuration fails
      */
     public void maybeConfigure() throws BuildException {
-        if (realThing != null) {
+        final Object copy = realThing;
+        if (copy != null) {
             return;
         }
         configure(makeObject(this, getWrapper()));
@@ -176,10 +178,10 @@
         }
         realThing = realObject;
 
-        getWrapper().setProxy(realThing);
+        getWrapper().setProxy(realObject);
         Task task = null;
-        if (realThing instanceof Task) {
-            task = (Task) realThing;
+        if (realObject instanceof Task) {
+            task = (Task) realObject;
 
             task.setRuntimeConfigurableWrapper(getWrapper());
 
@@ -187,7 +189,7 @@
             // targets to work. *very* Ugly
             // The reference is replaced by RuntimeConfigurable
             if (getWrapper().getId() != null) {
-                this.getOwningTarget().replaceChild(this, (Task) realThing);
+                this.getOwningTarget().replaceChild(this, (Task) realObject);
             }
        }
 
@@ -202,7 +204,7 @@
             getWrapper().maybeConfigure(getProject());
         }
 
-        handleChildren(realThing, getWrapper());
+        handleChildren(realObject, getWrapper());
     }
 
     /**
@@ -211,8 +213,9 @@
      * @param output The output to log. Should not be <code>null</code>.
      */
     protected void handleOutput(String output) {
-        if (realThing instanceof Task) {
-            ((Task) realThing).handleOutput(output);
+        final Object copy = realThing;
+        if (copy instanceof Task) {
+            ((Task) copy).handleOutput(output);
         } else {
             super.handleOutput(output);
         }
@@ -232,12 +235,11 @@
      */
     protected int handleInput(byte[] buffer, int offset, int length)
         throws IOException {
-        if (realThing instanceof Task) {
-            return ((Task) realThing).handleInput(buffer, offset, length);
-        } else {
-            return super.handleInput(buffer, offset, length);
+        final Object copy = realThing;
+        if (copy instanceof Task) {
+            return ((Task) copy).handleInput(buffer, offset, length);
         }
-
+        return super.handleInput(buffer, offset, length);
     }
 
     /**
@@ -246,8 +248,9 @@
      * @param output The output to log. Should not be <code>null</code>.
      */
     protected void handleFlush(String output) {
-        if (realThing instanceof Task) {
-            ((Task) realThing).handleFlush(output);
+        final Object copy = realThing;
+        if (copy instanceof Task) {
+            ((Task) copy).handleFlush(output);
         } else {
             super.handleFlush(output);
         }
@@ -259,8 +262,9 @@
      * @param output The error output to log. Should not be <code>null</code>.
      */
     protected void handleErrorOutput(String output) {
-        if (realThing instanceof Task) {
-            ((Task) realThing).handleErrorOutput(output);
+        final Object copy = realThing;
+        if (copy instanceof Task) {
+            ((Task) copy).handleErrorOutput(output);
         } else {
             super.handleErrorOutput(output);
         }
@@ -272,8 +276,9 @@
      * @param output The error output to log. Should not be <code>null</code>.
      */
     protected void handleErrorFlush(String output) {
-        if (realThing instanceof Task) {
-            ((Task) realThing).handleErrorFlush(output);
+        final Object copy = realThing;
+        if (copy instanceof Task) {
+            ((Task) copy).handleErrorFlush(output);
         } else {
             super.handleErrorFlush(output);
         }
@@ -284,13 +289,14 @@
      * (e.g. a data type) then this method does nothing.
      */
     public void execute() {
-        if (realThing == null) {
+        final Object copy = realThing;
+        if (copy == null) {
             // Got here if the runtimeconfigurable is not enabled.
             return;
         }
         try {
-            if (realThing instanceof Task) {
-                ((Task) realThing).execute();
+            if (copy instanceof Task) {
+                ((Task) copy).execute();
             }
         } finally {
             // Finished executing the task
@@ -311,7 +317,7 @@
      */
     public void addChild(UnknownElement child) {
         if (children == null) {
-            children = new ArrayList<UnknownElement>();
+            children = new ArrayList<>();
         }
         children.add(child);
     }
@@ -333,6 +339,10 @@
         Object parent,
         RuntimeConfigurable parentWrapper)
         throws BuildException {
+
+        if (children == null || children.isEmpty()) {
+            return;
+        }
         if (parent instanceof TypeAdapter) {
             parent = ((TypeAdapter) parent).getProxy();
         }
@@ -341,39 +351,36 @@
         Class<?> parentClass = parent.getClass();
         IntrospectionHelper ih = IntrospectionHelper.getHelper(getProject(), parentClass);
 
-
-        if (children != null) {
-            Iterator<UnknownElement> it = children.iterator();
-            for (int i = 0; it.hasNext(); i++) {
-                RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
-                UnknownElement child = it.next();
-                try {
-                    if (!childWrapper.isEnabled(child)) {
-                        if (ih.supportsNestedElement(
-                                parentUri, ProjectHelper.genComponentName(
-                                    child.getNamespace(), child.getTag()))) {
-                            continue;
-                        }
-                        // fall tru and fail in handlechild (unsupported element)
+        Iterator<UnknownElement> it = children.iterator();
+        for (int i = 0; it.hasNext(); i++) {
+            RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
+            UnknownElement child = it.next();
+            try {
+                if (!childWrapper.isEnabled(child)) {
+                    if (ih.supportsNestedElement(
+                            parentUri, ProjectHelper.genComponentName(
+                                child.getNamespace(), child.getTag()))) {
+                        continue;
                     }
-                    if (!handleChild(
-                            parentUri, ih, parent, child, childWrapper)) {
-                        if (!(parent instanceof TaskContainer)) {
-                            ih.throwNotSupported(getProject(), parent,
-                                                 child.getTag());
-                        } else {
-                            // a task container - anything could happen - just add the
-                            // child to the container
-                            TaskContainer container = (TaskContainer) parent;
-                            container.addTask(child);
-                        }
-                    }
-                } catch (UnsupportedElementException ex) {
-                    throw new BuildException(
-                        parentWrapper.getElementTag()
-                        + " doesn't support the nested \"" + ex.getElement()
-                        + "\" element.", ex);
+                    // fall thru and fail in handlechild (unsupported element)
                 }
+                if (!handleChild(
+                        parentUri, ih, parent, child, childWrapper)) {
+                    if (!(parent instanceof TaskContainer)) {
+                        ih.throwNotSupported(getProject(), parent,
+                                             child.getTag());
+                    } else {
+                        // a task container - anything could happen - just add the
+                        // child to the container
+                        TaskContainer container = (TaskContainer) parent;
+                        container.addTask(child);
+                    }
+                }
+            } catch (UnsupportedElementException ex) {
+                throw new BuildException(
+                    parentWrapper.getElementTag()
+                    + " doesn't support the nested \"" + ex.getElement()
+                    + "\" element.", ex);
             }
         }
     }
@@ -400,7 +407,7 @@
         // Do the runtime
         getWrapper().applyPreSet(u.getWrapper());
         if (u.children != null) {
-            List<UnknownElement> newChildren = new ArrayList<UnknownElement>(u.children);
+            List<UnknownElement> newChildren = new ArrayList<>(u.children);
             if (children != null) {
                 newChildren.addAll(children);
             }
@@ -505,10 +512,9 @@
      * @return the name to use in logging messages.
      */
     public String getTaskName() {
-        //return elementName;
-        return realThing == null
-            || !(realThing instanceof Task) ? super.getTaskName()
-                                            : ((Task) realThing).getTaskName();
+        final Object copy = realThing;
+        return !(copy instanceof Task) ? super.getTaskName()
+            : ((Task) copy).getTaskName();
     }
 
     /**
@@ -518,8 +524,9 @@
      *         a task.
      */
     public Task getTask() {
-        if (realThing instanceof Task) {
-            return (Task) realThing;
+        final Object copy = realThing;
+        if (copy instanceof Task) {
+            return (Task) copy;
         }
         return null;
     }
@@ -600,7 +607,7 @@
     /**
      * like contents equals, but ignores project
      * @param obj the object to check against
-     * @return true if this unknownelement has the same contents the other
+     * @return true if this UnknownElement has the same contents the other
      */
     public boolean similar(Object obj) {
         if (obj == null) {
@@ -611,7 +618,7 @@
         }
         UnknownElement other = (UnknownElement) obj;
         // Are the names the same ?
-        if (!equalsString(elementName, other.elementName)) {
+        if (!Objects.equals(elementName, other.elementName)) {
             return false;
         }
         if (!namespace.equals(other.namespace)) {
@@ -636,7 +643,7 @@
         // Are the sub elements the same ?
         final int childrenSize = children == null ? 0 : children.size();
         if (childrenSize == 0) {
-            return other.children == null || other.children.size() == 0;
+            return other.children == null || other.children.isEmpty();
         }
         if (other.children == null) {
             return false;
@@ -646,7 +653,7 @@
         }
         for (int i = 0; i < childrenSize; ++i) {
             // children cannot be null childrenSize would have been 0
-            UnknownElement child = (UnknownElement) children.get(i); //NOSONAR
+            UnknownElement child = children.get(i); //NOSONAR
             if (!child.similar(other.children.get(i))) {
                 return false;
             }
@@ -654,10 +661,6 @@
         return true;
     }
 
-    private static boolean equalsString(String a, String b) {
-        return (a == null) ? (b == null) : a.equals(b);
-    }
-
     /**
      * Make a copy of the unknown element and set it in the new project.
      * @param newProject the project to create the UE in.
@@ -687,8 +690,7 @@
         }
         copyRC.addText(getWrapper().getText().toString());
 
-        for (Enumeration<RuntimeConfigurable> e = getWrapper().getChildren(); e.hasMoreElements();) {
-            RuntimeConfigurable r = e.nextElement();
+        for (RuntimeConfigurable r : Collections.list(getWrapper().getChildren())) {
             UnknownElement ueChild = (UnknownElement) r.getProxy();
             UnknownElement copyChild = ueChild.copy(newProject);
             copyRC.addChild(copyChild.getWrapper());
diff --git a/src/main/org/apache/tools/ant/UnsupportedAttributeException.java b/src/main/org/apache/tools/ant/UnsupportedAttributeException.java
index 1fd9ce5..226108b 100644
--- a/src/main/org/apache/tools/ant/UnsupportedAttributeException.java
+++ b/src/main/org/apache/tools/ant/UnsupportedAttributeException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/UnsupportedElementException.java b/src/main/org/apache/tools/ant/UnsupportedElementException.java
index 2a38120..0354892 100644
--- a/src/main/org/apache/tools/ant/UnsupportedElementException.java
+++ b/src/main/org/apache/tools/ant/UnsupportedElementException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/XmlLogger.java b/src/main/org/apache/tools/ant/XmlLogger.java
index 51d4776..b75ce2f 100644
--- a/src/main/org/apache/tools/ant/XmlLogger.java
+++ b/src/main/org/apache/tools/ant/XmlLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,21 +17,24 @@
  */
 package org.apache.tools.ant;
 
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.Writer;
-import java.util.Enumeration;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashSet;
 import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
 import java.util.Stack;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.apache.tools.ant.util.DOMElementWriter;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.StringUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -108,16 +111,16 @@
     private Document doc = builder.newDocument();
 
     /** Mapping for when tasks started (Task to TimedElement). */
-    private Hashtable<Task, TimedElement> tasks = new Hashtable<Task, TimedElement>();
+    private Map<Task, TimedElement> tasks = new Hashtable<>();
 
     /** Mapping for when targets started (Target to TimedElement). */
-    private Hashtable<Target, TimedElement> targets = new Hashtable<Target, XmlLogger.TimedElement>();
+    private Map<Target, TimedElement> targets = new Hashtable<>();
 
     /**
      * Mapping of threads to stacks of elements
      * (Thread to Stack of TimedElement).
      */
-    private Hashtable<Thread, Stack<TimedElement>> threadStacks = new Hashtable<Thread, Stack<TimedElement>>();
+    private Map<Thread, Stack<TimedElement>> threadStacks = new Hashtable<>();
 
     /**
      * When the build started.
@@ -133,23 +136,20 @@
         private long startTime;
         /** Element created at the start time. */
         private Element element;
+
+        @Override
         public String toString() {
             return element.getTagName() + ":" + element.getAttribute("name");
         }
     }
 
     /**
-     *  Constructs a new BuildListener that logs build events to an XML file.
-     */
-    public XmlLogger() {
-    }
-
-    /**
      * Fired when the build starts, this builds the top-level element for the
      * document and remembers the time of the start of the build.
      *
      * @param event Ignored.
      */
+    @Override
     public void buildStarted(BuildEvent event) {
         buildElement = new TimedElement();
         buildElement.startTime = System.currentTimeMillis();
@@ -163,6 +163,7 @@
      * @param event An event with any relevant extra information.
      *              Will not be <code>null</code>.
      */
+    @Override
     public void buildFinished(BuildEvent event) {
         long totalTime = System.currentTimeMillis() - buildElement.startTime;
         buildElement.element.setAttribute(TIME_ATTR, DefaultLogger.formatTime(totalTime));
@@ -179,25 +180,19 @@
         }
         String outFilename = getProperty(event, "XmlLogger.file", "log.xml");
         String xslUri = getProperty(event, "ant.XmlLogger.stylesheet.uri", "log.xsl");
-        Writer out = null;
-        try {
-            // specify output in UTF8 otherwise accented characters will blow
-            // up everything
-            OutputStream stream = outStream;
-            if (stream == null) {
-                stream = new FileOutputStream(outFilename);
-            }
-            out = new OutputStreamWriter(stream, "UTF8");
+
+        try (OutputStream stream =
+            outStream == null ? Files.newOutputStream(Paths.get(outFilename)) : outStream;
+                Writer out = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) {
             out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-            if (xslUri.length() > 0) {
-                out.write("<?xml-stylesheet type=\"text/xsl\" href=\"" + xslUri + "\"?>\n\n");
+            if (!xslUri.isEmpty()) {
+                out.write("<?xml-stylesheet type=\"text/xsl\" href=\"" + xslUri
+                    + "\"?>\n\n");
             }
             new DOMElementWriter().write(buildElement.element, out, 0, "\t");
             out.flush();
         } catch (IOException exc) {
             throw new BuildException("Unable to write log file", exc);
-        } finally {
-            FileUtils.close(out);
         }
         buildElement = null;
     }
@@ -215,16 +210,13 @@
      * @return the stack of timed elements for the current thread
      */
     private Stack<TimedElement> getStack() {
-        Stack<TimedElement> threadStack = threadStacks.get(Thread.currentThread());
-        if (threadStack == null) {
-            threadStack = new Stack<TimedElement>();
-            threadStacks.put(Thread.currentThread(), threadStack);
-        }
         /* For debugging purposes uncomment:
-        org.w3c.dom.Comment s = doc.createComment("stack=" + threadStack);
-        buildElement.element.appendChild(s);
-         */
-        return threadStack;
+        if (threadStacks.containsKey(Thread.currentThread())) {
+            org.w3c.dom.Comment s = doc.createComment("stack=" + threadStacks(Thread.currentThread()));
+            buildElement.element.appendChild(s);
+        }
+        */
+        return threadStacks.computeIfAbsent(Thread.currentThread(), k -> new Stack<>());
     }
 
     /**
@@ -235,6 +227,7 @@
      * @param event An event with any relevant extra information.
      *              Will not be <code>null</code>.
      */
+    @Override
     public void targetStarted(BuildEvent event) {
         Target target = event.getTarget();
         TimedElement targetElement = new TimedElement();
@@ -252,6 +245,7 @@
      * @param event An event with any relevant extra information.
      *              Will not be <code>null</code>.
      */
+    @Override
     public void targetFinished(BuildEvent event) {
         Target target = event.getTarget();
         TimedElement targetElement = targets.get(target);
@@ -289,6 +283,7 @@
      * @param event An event with any relevant extra information.
      *              Will not be <code>null</code>.
      */
+    @Override
     public void taskStarted(BuildEvent event) {
         TimedElement taskElement = new TimedElement();
         taskElement.startTime = System.currentTimeMillis();
@@ -312,6 +307,7 @@
      * @param event An event with any relevant extra information.
      *              Will not be <code>null</code>.
      */
+    @Override
     public void taskFinished(BuildEvent event) {
         Task task = event.getTask();
         TimedElement taskElement = tasks.get(task);
@@ -352,12 +348,10 @@
         if (element != null) {
             return element;
         }
-        for (Enumeration<Task> e = tasks.keys(); e.hasMoreElements();) {
-            Task key = e.nextElement();
-            if (key instanceof UnknownElement) {
-                if (((UnknownElement) key).getTask() == task) {
-                    return tasks.get(key);
-                }
+        final Set<Task> knownTasks = new HashSet<>(tasks.keySet());
+        for (final Task t : knownTasks) {
+            if (t instanceof UnknownElement && ((UnknownElement) t).getTask() == task) {
+                return tasks.get(t);
             }
         }
         return null;
@@ -371,6 +365,7 @@
      * @param event An event with any relevant extra information.
      *              Will not be <code>null</code>.
      */
+    @Override
     public void messageLogged(BuildEvent event) {
         int priority = event.getPriority();
         if (priority > msgOutputLevel) {
@@ -378,7 +373,7 @@
         }
         Element messageElement = doc.createElement(MESSAGE_TAG);
 
-        String name = "debug";
+        String name;
         switch (priority) {
             case Project.MSG_ERR:
                 name = "error";
@@ -432,6 +427,7 @@
      *        see {@link org.apache.tools.ant.Project#MSG_ERR Project}
      *        class for level definitions
      */
+    @Override
     public void setMessageOutputLevel(int level) {
         msgOutputLevel = level;
     }
@@ -442,6 +438,7 @@
      *
      * @param output the output PrintStream.
      */
+    @Override
     public void setOutputPrintStream(PrintStream output) {
         this.outStream = new PrintStream(output, true);
     }
@@ -452,6 +449,7 @@
      * @param emacsMode true if logger should produce emacs compatible
      *        output
      */
+    @Override
     public void setEmacsMode(boolean emacsMode) {
     }
 
@@ -462,6 +460,7 @@
      *
      * @param err the stream we are going to ignore.
      */
+    @Override
     public void setErrorPrintStream(PrintStream err) {
     }
 
diff --git a/src/main/org/apache/tools/ant/antlib.xml b/src/main/org/apache/tools/ant/antlib.xml
index 8ec6714..68bdab0 100644
--- a/src/main/org/apache/tools/ant/antlib.xml
+++ b/src/main/org/apache/tools/ant/antlib.xml
@@ -8,7 +8,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java b/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java
index fba4c99..55d6435 100644
--- a/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java
+++ b/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java b/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java
index 3e8b566..3426d68 100644
--- a/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java
+++ b/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,11 +18,10 @@
 
 package org.apache.tools.ant.attribute;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.ProjectComponent;
-import org.apache.tools.ant.RuntimeConfigurable;
 import org.apache.tools.ant.UnknownElement;
 
 
@@ -57,7 +56,7 @@
      * @return val if positive or !val if not.
      */
     protected boolean convertResult(boolean val) {
-        return positive ? val : !val;
+        return positive == val;
     }
 
     /**
@@ -66,19 +65,11 @@
      * @param el the element this attribute is in.
      * @return a map of attributes.
      */
-    protected Map getParams(UnknownElement el) {
-        Map ret = new HashMap();
-        RuntimeConfigurable rc = el.getWrapper();
-        Map<String, Object> attributes = rc.getAttributeMap(); // This does a copy!
-        for (Map.Entry<String, Object> entry : attributes.entrySet()) {
-            String key = entry.getKey();
-            String value = (String) entry.getValue();
-            if (key.startsWith("ant-attribute:param")) {
-                int pos = key.lastIndexOf(':');
-                ret.put(key.substring(pos + 1),
-                        el.getProject().replaceProperties(value));
-            }
-        }
-        return ret;
+    protected Map<String, String> getParams(UnknownElement el) {
+        // this makes a copy!
+        return el.getWrapper().getAttributeMap().entrySet().stream()
+                .filter(e -> e.getKey().startsWith("ant-attribute:param"))
+                .collect(Collectors.toMap(e -> e.getKey().substring(e.getKey().lastIndexOf(':') + 1),
+                        e -> el.getProject().replaceProperties((String) e.getValue()), (a, b) -> b));
     }
 }
diff --git a/src/main/org/apache/tools/ant/attribute/EnableAttribute.java b/src/main/org/apache/tools/ant/attribute/EnableAttribute.java
index 06c1186..a02c99c 100644
--- a/src/main/org/apache/tools/ant/attribute/EnableAttribute.java
+++ b/src/main/org/apache/tools/ant/attribute/EnableAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java b/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java
index 384476c..410f8c6 100644
--- a/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java
+++ b/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,6 +34,6 @@
      * {@inheritDoc}
      */
     public boolean isEnabled(UnknownElement el, String value) {
-        return convertResult((value == null || "".equals(value)));
+        return convertResult(value == null || value.isEmpty());
     }
 }
diff --git a/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java b/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java
index d4531c5..4a31915 100644
--- a/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java
+++ b/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java b/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java
index 5c10ea2..65de9c0 100644
--- a/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java
+++ b/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/dispatch/DispatchTask.java b/src/main/org/apache/tools/ant/dispatch/DispatchTask.java
index b88b873..9c08d6d 100644
--- a/src/main/org/apache/tools/ant/dispatch/DispatchTask.java
+++ b/src/main/org/apache/tools/ant/dispatch/DispatchTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,6 +36,7 @@
      * Get the action parameter name.
      * @return the <code>String</code> "action" by default (can be overridden).
      */
+    @Override
     public String getActionParameterName() {
         return "action";
     }
diff --git a/src/main/org/apache/tools/ant/dispatch/DispatchUtils.java b/src/main/org/apache/tools/ant/dispatch/DispatchUtils.java
index 62dd88f..b76c789 100644
--- a/src/main/org/apache/tools/ant/dispatch/DispatchUtils.java
+++ b/src/main/org/apache/tools/ant/dispatch/DispatchUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,9 +43,8 @@
             } else if (task instanceof UnknownElement) {
                 UnknownElement ue = (UnknownElement) task;
                 Object realThing = ue.getRealThing();
-                if (realThing != null
-                    && realThing instanceof Dispatchable
-                    && realThing instanceof Task) {
+                if (realThing instanceof Dispatchable
+                        && realThing instanceof Task) {
                     dispatchable = (Dispatchable) realThing;
                 }
             }
@@ -53,57 +52,51 @@
                 String mName = null;
                 try {
                     final String name = dispatchable.getActionParameterName();
-                    if (name != null && name.trim().length() > 0) {
-                        mName = "get" + name.trim().substring(0, 1).toUpperCase();
-                        if (name.length() > 1) {
-                            mName += name.substring(1);
-                        }
-                        final Class<? extends Dispatchable> c = dispatchable.getClass();
-                        final Method actionM = c.getMethod(mName, new Class[0]);
-                        if (actionM != null) {
-                            final Object o = actionM.invoke(dispatchable, (Object[]) null);
-                            if (o != null) {
-                                final String s = o.toString();
-                                if (s.trim().length() > 0) {
-                                    methodName = s.trim();
-                                    Method executeM = null;
-                                    executeM = dispatchable.getClass().getMethod(
-                                        methodName, new Class[0]);
-                                    if (executeM == null) {
-                                        throw new BuildException(
-                                            "No public " + methodName + "() in "
-                                            + dispatchable.getClass());
-                                    }
-                                    executeM.invoke(dispatchable, (Object[]) null);
-                                    if (task instanceof UnknownElement) {
-                                        ((UnknownElement) task).setRealThing(null);
-                                    }
-                                } else {
-                                    throw new BuildException(
-                                        "Dispatchable Task attribute '" + name.trim()
-                                        + "' not set or value is empty.");
-                                }
-                            } else {
-                                    throw new BuildException(
-                                        "Dispatchable Task attribute '" + name.trim()
-                                        + "' not set or value is empty.");
-                            }
-                        }
-                    } else {
+                    if (name == null || name.trim().isEmpty()) {
                         throw new BuildException(
                             "Action Parameter Name must not be empty for Dispatchable Task.");
                     }
+                    mName = "get" + name.trim().substring(0, 1).toUpperCase();
+                    if (name.length() > 1) {
+                        mName += name.substring(1);
+                    }
+                    final Class<? extends Dispatchable> c = dispatchable.getClass();
+                    final Method actionM = c.getMethod(mName);
+                    if (actionM != null) {
+                        final Object o = actionM.invoke(dispatchable, (Object[]) null);
+                        if (o == null) {
+                                throw new BuildException(
+                                    "Dispatchable Task attribute '" + name.trim()
+                                    + "' not set or value is empty.");
+                        }
+                        methodName = o.toString().trim();
+                        if (methodName.isEmpty()) {
+                            throw new BuildException(
+                                "Dispatchable Task attribute '" + name.trim()
+                                + "' not set or value is empty.");
+                        }
+                        Method executeM = dispatchable.getClass().getMethod(methodName);
+                        if (executeM == null) {
+                            throw new BuildException(
+                                "No public " + methodName + "() in "
+                                + dispatchable.getClass());
+                        }
+                        executeM.invoke(dispatchable, (Object[]) null);
+                        if (task instanceof UnknownElement) {
+                            ((UnknownElement) task).setRealThing(null);
+                        }
+                    }
                 } catch (NoSuchMethodException nsme) {
                     throw new BuildException("No public " + mName + "() in " + task.getClass());
                 }
             } else {
                 Method executeM = null;
-                executeM = task.getClass().getMethod(methodName, new Class[0]);
+                executeM = task.getClass().getMethod(methodName);
                 if (executeM == null) {
                     throw new BuildException("No public " + methodName + "() in "
                         + task.getClass());
                 }
-                executeM.invoke(task, (Object[]) null);
+                executeM.invoke(task);
                 if (task instanceof UnknownElement) {
                     ((UnknownElement) task).setRealThing(null);
                 }
@@ -115,9 +108,7 @@
             } else {
                 throw new BuildException(t);
             }
-        } catch (NoSuchMethodException e) {
-            throw new BuildException(e);
-        } catch (IllegalAccessException e) {
+        } catch (NoSuchMethodException | IllegalAccessException e) {
             throw new BuildException(e);
         }
     }
diff --git a/src/main/org/apache/tools/ant/dispatch/Dispatchable.java b/src/main/org/apache/tools/ant/dispatch/Dispatchable.java
index 41684f4..f7fa4ad 100644
--- a/src/main/org/apache/tools/ant/dispatch/Dispatchable.java
+++ b/src/main/org/apache/tools/ant/dispatch/Dispatchable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/filters/BaseFilterReader.java b/src/main/org/apache/tools/ant/filters/BaseFilterReader.java
index dfd16f1..bc97d1b 100644
--- a/src/main/org/apache/tools/ant/filters/BaseFilterReader.java
+++ b/src/main/org/apache/tools/ant/filters/BaseFilterReader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -173,7 +173,7 @@
             return null;
         }
 
-        StringBuffer line = new StringBuffer();
+        final StringBuilder line = new StringBuilder();
 
         while (ch != -1) {
             line.append((char) ch);
diff --git a/src/main/org/apache/tools/ant/filters/BaseParamFilterReader.java b/src/main/org/apache/tools/ant/filters/BaseParamFilterReader.java
index 54bc9ff..406321e 100644
--- a/src/main/org/apache/tools/ant/filters/BaseParamFilterReader.java
+++ b/src/main/org/apache/tools/ant/filters/BaseParamFilterReader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,7 +58,7 @@
      * @param parameters The parameters to be used by this filter.
      *                   Should not be <code>null</code>.
      */
-    public final void setParameters(final Parameter[] parameters) {
+    public final void setParameters(final Parameter... parameters) {
         this.parameters = parameters;
         setInitialized(false);
     }
diff --git a/src/main/org/apache/tools/ant/filters/ChainableReader.java b/src/main/org/apache/tools/ant/filters/ChainableReader.java
index 6706039..eb7770f 100644
--- a/src/main/org/apache/tools/ant/filters/ChainableReader.java
+++ b/src/main/org/apache/tools/ant/filters/ChainableReader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/filters/ClassConstants.java b/src/main/org/apache/tools/ant/filters/ClassConstants.java
index b6894f9..1ec6fa1 100644
--- a/src/main/org/apache/tools/ant/filters/ClassConstants.java
+++ b/src/main/org/apache/tools/ant/filters/ClassConstants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,9 +21,9 @@
 import java.io.Reader;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.ResourceUtils;
 
 /**
  * Assembles the constants declared in a Java class in
@@ -86,49 +86,33 @@
      * be read (for example due to the class not being found).
      */
     public int read() throws IOException {
-
         int ch = -1;
 
-        if (queuedData != null && queuedData.length() == 0) {
+        if (queuedData != null && queuedData.isEmpty()) {
             queuedData = null;
         }
 
-        if (queuedData != null) {
-            ch = queuedData.charAt(0);
-            queuedData = queuedData.substring(1);
-            if (queuedData.length() == 0) {
-                queuedData = null;
-            }
-        } else {
+        if (queuedData == null) {
             final String clazz = readFully();
-            if (clazz == null || clazz.length() == 0) {
+            if (clazz == null || clazz.isEmpty()) {
                 ch = -1;
             } else {
-                final byte[] bytes = clazz.getBytes(ResourceUtils.ISO_8859_1);
+                final byte[] bytes = clazz.getBytes(StandardCharsets.ISO_8859_1);
                 try {
-                    final Class<?> javaClassHelper =
-                        Class.forName(JAVA_CLASS_HELPER);
+                    final Class<?> javaClassHelper = Class.forName(JAVA_CLASS_HELPER);
                     if (javaClassHelper != null) {
-                        final Class<?>[] params = {
-                            byte[].class
-                        };
                         final Method getConstants =
-                            javaClassHelper.getMethod("getConstants", params);
-                        final Object[] args = {
-                            bytes
-                        };
+                            javaClassHelper.getMethod("getConstants", byte[].class);
                         // getConstants is a static method, no need to
                         // pass in the object
                         final StringBuffer sb = (StringBuffer)
-                                getConstants.invoke(null, args);
+                                getConstants.invoke(null, (Object) bytes);
                         if (sb.length() > 0) {
                             queuedData = sb.toString();
                             return read();
                         }
                     }
-                } catch (NoClassDefFoundError ex) {
-                    throw ex;
-                } catch (RuntimeException ex) {
+                } catch (NoClassDefFoundError | RuntimeException ex) {
                     throw ex;
                 } catch (InvocationTargetException ex) {
                     Throwable t = ex.getTargetException();
@@ -143,6 +127,12 @@
                     throw new BuildException(ex);
                 }
             }
+        } else {
+            ch = queuedData.charAt(0);
+            queuedData = queuedData.substring(1);
+            if (queuedData.isEmpty()) {
+                queuedData = null;
+            }
         }
         return ch;
     }
@@ -158,7 +148,6 @@
      *         the specified reader
      */
     public Reader chain(final Reader rdr) {
-        ClassConstants newFilter = new ClassConstants(rdr);
-        return newFilter;
+        return new ClassConstants(rdr);
     }
 }
diff --git a/src/main/org/apache/tools/ant/filters/ConcatFilter.java b/src/main/org/apache/tools/ant/filters/ConcatFilter.java
index 817572f..65bbfdc 100644
--- a/src/main/org/apache/tools/ant/filters/ConcatFilter.java
+++ b/src/main/org/apache/tools/ant/filters/ConcatFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -192,13 +192,11 @@
         final Parameter[] params = getParameters();
         if (params != null) {
             for (Parameter param : params) {
-                if ("prepend".equals(param.getName())) {
+                final String paramName = param.getName();
+                if ("prepend".equals(paramName)) {
                     setPrepend(new File(param.getValue()));
-                    continue;
-                }
-                if ("append".equals(param.getName())) {
+                } else if ("append".equals(paramName)) {
                     setAppend(new File(param.getValue()));
-                    continue;
                 }
             }
         }
diff --git a/src/main/org/apache/tools/ant/filters/EscapeUnicode.java b/src/main/org/apache/tools/ant/filters/EscapeUnicode.java
index dd45439..f685cbf 100644
--- a/src/main/org/apache/tools/ant/filters/EscapeUnicode.java
+++ b/src/main/org/apache/tools/ant/filters/EscapeUnicode.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -82,7 +82,10 @@
         }
 
         int ch = -1;
-        if (unicodeBuf.length() == 0) {
+        if (unicodeBuf.length() > 0) {
+            ch = (int) unicodeBuf.charAt(0);
+            unicodeBuf.deleteCharAt(0);
+        } else {
             ch = in.read();
             if (ch != -1) {
                 char achar = (char) ch;
@@ -91,9 +94,6 @@
                     ch = '\\';
                 }
             }
-        } else {
-            ch = (int) unicodeBuf.charAt(0);
-            unicodeBuf.deleteCharAt(0);
         }
         return ch;
     }
diff --git a/src/main/org/apache/tools/ant/filters/ExpandProperties.java b/src/main/org/apache/tools/ant/filters/ExpandProperties.java
index 48d9ffe..750681b 100644
--- a/src/main/org/apache/tools/ant/filters/ExpandProperties.java
+++ b/src/main/org/apache/tools/ant/filters/ExpandProperties.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 
 import java.io.IOException;
 import java.io.Reader;
-import java.util.Properties;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -98,13 +97,7 @@
                 if (propertySet == null) {
                     getProperty = PropertyHelper.getPropertyHelper(project);
                 } else {
-                    final Properties props = propertySet.getProperties();
-                    getProperty = new GetProperty() {
-
-                        public Object getProperty(String name) {
-                            return props.getProperty(name);
-                        }
-                    };
+                    getProperty = propertySet.getProperties()::getProperty;
                 }
                 Object expanded = new ParseProperties(project, PropertyHelper
                                                       .getPropertyHelper(project)
diff --git a/src/main/org/apache/tools/ant/filters/FixCrLfFilter.java b/src/main/org/apache/tools/ant/filters/FixCrLfFilter.java
index b5a0ad2..fa36366 100644
--- a/src/main/org/apache/tools/ant/filters/FixCrLfFilter.java
+++ b/src/main/org/apache/tools/ant/filters/FixCrLfFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -273,8 +273,8 @@
                 in = new MaskJavaTabLiteralsFilter(in);
             }
             // Add/Remove tabs
-            in = (tabs == AddAsisRemove.ADD) ? (Reader) new AddTabFilter(in, getTablength())
-                    : (Reader) new RemoveTabFilter(in, getTablength());
+            in = (tabs == AddAsisRemove.ADD) ? new AddTabFilter(in, getTablength())
+                    : new RemoveTabFilter(in, getTablength());
         }
         // Add missing EOF character
         in = (ctrlz == AddAsisRemove.ADD) ? new AddEofFilter(in) : in;
@@ -442,11 +442,11 @@
             return in instanceof SimpleFilterReader && ((SimpleFilterReader) in).editsBlocked();
         }
 
-        public int read() throws java.io.IOException {
+        public int read() throws IOException {
             return preemptIndex > 0 ? preempt[--preemptIndex] : in.read();
         }
 
-        public void close() throws java.io.IOException {
+        public void close() throws IOException {
             in.close();
         }
 
@@ -458,23 +458,23 @@
             return in.markSupported();
         }
 
-        public boolean ready() throws java.io.IOException {
+        public boolean ready() throws IOException {
             return in.ready();
         }
 
-        public void mark(int i) throws java.io.IOException {
+        public void mark(int i) throws IOException {
             in.mark(i);
         }
 
-        public long skip(long i) throws java.io.IOException {
+        public long skip(long i) throws IOException {
             return in.skip(i);
         }
 
-        public int read(char[] buf) throws java.io.IOException {
+        public int read(char[] buf) throws IOException {
             return read(buf, 0, buf.length);
         }
 
-        public int read(char[] buf, int start, int length) throws java.io.IOException {
+        public int read(char[] buf, int start, int length) throws IOException {
             int count = 0;
             int c = 0;
 
diff --git a/src/main/org/apache/tools/ant/filters/HeadFilter.java b/src/main/org/apache/tools/ant/filters/HeadFilter.java
index 29806b3..e823868 100644
--- a/src/main/org/apache/tools/ant/filters/HeadFilter.java
+++ b/src/main/org/apache/tools/ant/filters/HeadFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -105,7 +105,7 @@
             setInitialized(true);
         }
 
-        while (line == null || line.length() == 0) {
+        while (line == null || line.isEmpty()) {
             line = lineTokenizer.getToken(in);
             if (line == null) {
                 return -1;
@@ -188,13 +188,11 @@
         Parameter[] params = getParameters();
         if (params != null) {
             for (Parameter param : params) {
-                if (LINES_KEY.equals(param.getName())) {
+                final String paramName = param.getName();
+                if (LINES_KEY.equals(paramName)) {
                     lines = Long.parseLong(param.getValue());
-                    continue;
-                }
-                if (SKIP_KEY.equals(param.getName())) {
+                } else if (SKIP_KEY.equals(paramName)) {
                     skip = Long.parseLong(param.getValue());
-                    continue;
                 }
             }
         }
diff --git a/src/main/org/apache/tools/ant/filters/LineContains.java b/src/main/org/apache/tools/ant/filters/LineContains.java
index a549251..cb2ffe1 100644
--- a/src/main/org/apache/tools/ant/filters/LineContains.java
+++ b/src/main/org/apache/tools/ant/filters/LineContains.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,7 @@
 import org.apache.tools.ant.types.Parameter;
 
 /**
- * Filter which includes only those lines that contain all the user-specified
+ * Filter which includes only those lines that contain the user-specified
  * strings.
  *
  * Example:
@@ -45,6 +45,19 @@
  * This will include only those lines that contain <code>foo</code> and
  * <code>bar</code>.
  *
+ * Starting Ant 1.10.4, the {@code matchAny} attribute can be used to control whether any one
+ * of the user-specified strings is expected to be contained in the line or all
+ * of them are expected to be contained.
+ *
+ * For example:
+ *
+ * <pre>&lt;linecontains matchAny=&quot;true&quot;&gt;
+ *  *   &lt;contains value=&quot;foo&quot;&gt;
+ *  *   &lt;contains value=&quot;bar&quot;&gt;
+ *  * &lt;/linecontains&gt;</pre>
+ *
+ * This will include only those lines that contain either <code>foo</code> or <code>bar</code>.
+ *
  */
 public final class LineContains
     extends BaseParamFilterReader
@@ -56,7 +69,7 @@
     private static final String NEGATE_KEY = "negate";
 
     /** Vector that holds the strings that input lines must contain. */
-    private Vector<String> contains = new Vector<String>();
+    private Vector<String> contains = new Vector<>();
 
     /**
      * Remaining line to be read from this filter, or <code>null</code> if
@@ -67,6 +80,8 @@
 
     private boolean negate = false;
 
+    private boolean matchAny = false;
+
     /**
      * Constructor for "dummy" instances.
      *
@@ -116,9 +131,24 @@
 
             for (line = readLine(); line != null; line = readLine()) {
                 boolean matches = true;
-                for (int i = 0; matches && i < containsSize; i++) {
-                    String containsStr = (String) contains.elementAt(i);
+                for (int i = 0; i < containsSize; i++) {
+                    final String containsStr = contains.elementAt(i);
                     matches = line.contains(containsStr);
+                    if (!matches) {
+                        if (this.matchAny) {
+                            // this one didn't match, but we are expected to have
+                            // any one of them match. so try next
+                            continue;
+                        } else {
+                            // all were expected to match, but this one didn't.
+                            // so no point checking the rest
+                            break;
+                        }
+                    } else if (this.matchAny) {
+                        // we were expected to match any of the contains
+                        // and this one did. so no more checks needed
+                        break;
+                    }
                 }
                 if (matches ^ isNegated()) {
                     break;
@@ -158,6 +188,31 @@
     }
 
     /**
+     *
+     * @param matchAny True if this {@link LineContains} is considered a match,
+     *                 if {@code any} of the {@code contains} value match. False
+     *                 if {@code all} of the {@code contains} value are expected
+     *                 to match
+     * @since Ant 1.10.4
+     *
+     */
+    public void setMatchAny(final boolean matchAny) {
+        this.matchAny = matchAny;
+    }
+
+    /**
+     * @return Returns true if this {@link LineContains} is considered a match,
+     * if {@code any} of the {@code contains} value match. False
+     * if {@code all} of the {@code contains} value are expected
+     * to match
+     *
+     * @since Ant 1.10.4
+     */
+    public boolean isMatchAny() {
+        return this.matchAny;
+    }
+
+    /**
      * Sets the vector of words which must be contained within a line read
      * from the original stream in order for it to match this filter.
      *
@@ -195,6 +250,7 @@
         LineContains newFilter = new LineContains(rdr);
         newFilter.setContains(getContains());
         newFilter.setNegate(isNegated());
+        newFilter.setMatchAny(isMatchAny());
         return newFilter;
     }
 
diff --git a/src/main/org/apache/tools/ant/filters/LineContainsRegExp.java b/src/main/org/apache/tools/ant/filters/LineContainsRegExp.java
index b18e362..1312ff3 100644
--- a/src/main/org/apache/tools/ant/filters/LineContainsRegExp.java
+++ b/src/main/org/apache/tools/ant/filters/LineContainsRegExp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,7 +58,7 @@
     private static final String CS_KEY = "casesensitive";
 
     /** Vector that holds the expressions that input lines must contain. */
-    private Vector<RegularExpression> regexps = new Vector<RegularExpression>();
+    private Vector<RegularExpression> regexps = new Vector<>();
 
     /**
      * Remaining line to be read from this filter, or <code>null</code> if
@@ -116,15 +116,13 @@
                 line = line.substring(1);
             }
         } else {
-            final int regexpsSize = regexps.size();
-
             for (line = readLine(); line != null; line = readLine()) {
                 boolean matches = true;
-                for (int i = 0; matches && i < regexpsSize; i++) {
-                    RegularExpression regexp
-                        = (RegularExpression) regexps.elementAt(i);
-                    Regexp re = regexp.getRegexp(getProject());
-                    matches = re.matches(line, regexpOptions);
+                for (RegularExpression regexp : regexps) {
+                    if (!regexp.getRegexp(getProject()).matches(line, regexpOptions)) {
+                        matches = false;
+                        break;
+                    }
                 }
                 if (matches ^ isNegated()) {
                     break;
@@ -188,10 +186,8 @@
         LineContainsRegExp newFilter = new LineContainsRegExp(rdr);
         newFilter.setRegexps(getRegexps());
         newFilter.setNegate(isNegated());
-        newFilter
-            .setCaseSensitive(!RegexpUtil.hasFlag(regexpOptions,
-                                                  Regexp.MATCH_CASE_INSENSITIVE)
-                              );
+        newFilter.setCaseSensitive(!RegexpUtil.hasFlag(regexpOptions,
+                Regexp.MATCH_CASE_INSENSITIVE));
         return newFilter;
     }
 
@@ -223,7 +219,7 @@
     /**
      * Set the regular expression as an attribute.
      * @param pattern String
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public void setRegexp(String pattern) {
         RegularExpression regexp = new RegularExpression();
diff --git a/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java b/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java
index 2e764ae..7322827 100644
--- a/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java
+++ b/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -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/filters/PrefixLines.java b/src/main/org/apache/tools/ant/filters/PrefixLines.java
index e125aa3..89823c7 100644
--- a/src/main/org/apache/tools/ant/filters/PrefixLines.java
+++ b/src/main/org/apache/tools/ant/filters/PrefixLines.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -86,14 +86,14 @@
 
         int ch = -1;
 
-        if (queuedData != null && queuedData.length() == 0) {
+        if (queuedData != null && queuedData.isEmpty()) {
             queuedData = null;
         }
 
         if (queuedData != null) {
             ch = queuedData.charAt(0);
             queuedData = queuedData.substring(1);
-            if (queuedData.length() == 0) {
+            if (queuedData.isEmpty()) {
                 queuedData = null;
             }
         } else {
diff --git a/src/main/org/apache/tools/ant/filters/ReplaceTokens.java b/src/main/org/apache/tools/ant/filters/ReplaceTokens.java
index a2ac732..4562175 100644
--- a/src/main/org/apache/tools/ant/filters/ReplaceTokens.java
+++ b/src/main/org/apache/tools/ant/filters/ReplaceTokens.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
-import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.Properties;
@@ -62,10 +61,10 @@
     private static final String DEFAULT_END_TOKEN = "@";
 
     /** Hashtable to holds the original replacee-replacer pairs (String to String). */
-    private Hashtable<String, String> hash = new Hashtable<String, String>();
+    private Hashtable<String, String> hash = new Hashtable<>();
 
     /** This map holds the "resolved" tokens (begin- and end-tokens are added to make searching simpler) */
-    private final TreeMap<String, String> resolvedTokens = new TreeMap<String, String>();
+    private final TreeMap<String, String> resolvedTokens = new TreeMap<>();
     private boolean resolvedTokensBuilt = false;
     /** Used for comparisons and lookup into the resolvedTokens map. */
     private String readBuffer = "";
@@ -134,7 +133,7 @@
         }
 
         // is the read buffer empty?
-        if (readBuffer.length() == 0) {
+        if (readBuffer.isEmpty()) {
             int next = in.read();
             if (next == -1) {
                 return next; // end of stream. all buffers empty.
@@ -169,13 +168,13 @@
      * @return the first character from the read buffer or -1 if read buffer is empty.
      */
     private int getFirstCharacterFromReadBuffer() {
-        if (readBuffer.length() > 0) {
-            int chr = readBuffer.charAt(0);
-            readBuffer = readBuffer.substring(1);
-            return chr;
-        } else {
+        if (readBuffer.isEmpty()) {
             return -1;
         }
+
+        int chr = readBuffer.charAt(0);
+        readBuffer = readBuffer.substring(1);
+        return chr;
     }
 
     /**
@@ -330,11 +329,7 @@
 
     private void makeTokensFromProperties(Resource r) {
         Properties props = getProperties(r);
-        for (Enumeration<?> e = props.keys(); e.hasMoreElements();) {
-            String key = (String) e.nextElement();
-            String value = props.getProperty(key);
-            hash.put(key, value);
-        }
+        props.stringPropertyNames().forEach(key -> hash.put(key, props.getProperty(key)));
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/filters/SortFilter.java b/src/main/org/apache/tools/ant/filters/SortFilter.java
index be08acb..1478db3 100644
--- a/src/main/org/apache/tools/ant/filters/SortFilter.java
+++ b/src/main/org/apache/tools/ant/filters/SortFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -213,7 +213,7 @@
         } else {
             if (lines == null) {
                 // We read all lines and sort them
-                lines = new ArrayList<String>();
+                lines = new ArrayList<>();
                 for (line = readLine(); line != null; line = readLine()) {
                     lines.add(line);
                 }
@@ -222,7 +222,7 @@
             }
 
             if (iterator.hasNext()) {
-                line = (String) iterator.next();
+                line = iterator.next();
             } else {
                 line = null;
                 lines = null;
@@ -310,40 +310,30 @@
     /**
      * Scans the parameters list
      */
-    private void initialize() throws IOException {
+    private void initialize() {
         // get parameters
         Parameter[] params = getParameters();
         if (params != null) {
             for (Parameter param : params) {
                 final String paramName = param.getName();
                 if (REVERSE_KEY.equals(paramName)) {
-                    setReverse(Boolean.valueOf(param.getValue()).booleanValue());
-                    continue;
-                }
-                if (COMPARATOR_KEY.equals(paramName)) {
+                    setReverse(Boolean.parseBoolean(param.getValue()));
+                } else if (COMPARATOR_KEY.equals(paramName)) {
                     try {
-                        String className = (String) param.getValue();
+                        String className = param.getValue();
                         @SuppressWarnings("unchecked")
                         final Comparator<? super String> comparatorInstance
-                                = (Comparator<? super String>) (Class.forName(className).newInstance());
+                                = (Comparator<? super String>) (Class.forName(className).getDeclaredConstructor().newInstance());
                         setComparator(comparatorInstance);
-                        continue;
-                    } catch (InstantiationException e) {
-                        throw new BuildException(e);
-                    } catch (IllegalAccessException e) {
-                        /*
-                         * Probably a inner non-static class, this this case is
-                         * not considered
-                         */
-                        throw new BuildException(e);
-                    } catch (ClassNotFoundException e) {
-                        throw new BuildException(e);
                     } catch (ClassCastException e) {
                         throw new BuildException("Value of comparator attribute"
                                                  + " should implement"
                                                  + " java.util.Comparator"
                                                  + " interface");
                     } catch (Exception e) {
+                        /*
+                         * IAE probably means an inner non-static class, that case is not considered
+                         */
                         throw new BuildException(e);
                     }
                 }
@@ -358,17 +348,13 @@
      */
     private void sort() {
         if (comparator == null) {
-            if (reverse) {
-                Collections.sort(lines, new Comparator<String>() {
-                        public int compare(String s1, String s2) {
-                            return (-s1.compareTo(s2)); //NOSONAR
-                        }
-                    });
+            if (isReverse()) {
+                lines.sort(Comparator.reverseOrder());
             } else {
                 Collections.sort(lines);
             }
         } else {
-            Collections.sort(lines, comparator);
+            lines.sort(comparator);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/filters/StringInputStream.java b/src/main/org/apache/tools/ant/filters/StringInputStream.java
index e150e96..106c850 100644
--- a/src/main/org/apache/tools/ant/filters/StringInputStream.java
+++ b/src/main/org/apache/tools/ant/filters/StringInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/filters/StripJavaComments.java b/src/main/org/apache/tools/ant/filters/StripJavaComments.java
index 65bccd7..62c4624 100644
--- a/src/main/org/apache/tools/ant/filters/StripJavaComments.java
+++ b/src/main/org/apache/tools/ant/filters/StripJavaComments.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -139,7 +139,6 @@
      */
 
     public Reader chain(final Reader rdr) {
-        StripJavaComments newFilter = new StripJavaComments(rdr);
-        return newFilter;
+        return new StripJavaComments(rdr);
     }
 }
diff --git a/src/main/org/apache/tools/ant/filters/StripLineBreaks.java b/src/main/org/apache/tools/ant/filters/StripLineBreaks.java
index 9ba70dd..35d6525 100644
--- a/src/main/org/apache/tools/ant/filters/StripLineBreaks.java
+++ b/src/main/org/apache/tools/ant/filters/StripLineBreaks.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/filters/StripLineComments.java b/src/main/org/apache/tools/ant/filters/StripLineComments.java
index 0dbb307..a85cddc 100644
--- a/src/main/org/apache/tools/ant/filters/StripLineComments.java
+++ b/src/main/org/apache/tools/ant/filters/StripLineComments.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,7 +55,7 @@
     private static final String COMMENTS_KEY = "comment";
 
     /** Vector that holds the comment prefixes. */
-    private Vector<String> comments = new Vector<String>();
+    private Vector<String> comments = new Vector<>();
 
     /** The line that has been read ahead. */
     private String line = null;
diff --git a/src/main/org/apache/tools/ant/filters/SuffixLines.java b/src/main/org/apache/tools/ant/filters/SuffixLines.java
index 9c22d2b..76127a3 100644
--- a/src/main/org/apache/tools/ant/filters/SuffixLines.java
+++ b/src/main/org/apache/tools/ant/filters/SuffixLines.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -87,17 +87,11 @@
 
         int ch = -1;
 
-        if (queuedData != null && queuedData.length() == 0) {
+        if (queuedData != null && queuedData.isEmpty()) {
             queuedData = null;
         }
 
-        if (queuedData != null) {
-            ch = queuedData.charAt(0);
-            queuedData = queuedData.substring(1);
-            if (queuedData.length() == 0) {
-                queuedData = null;
-            }
-        } else {
+        if (queuedData == null) {
             queuedData = readLine();
             if (queuedData == null) {
                 ch = -1;
@@ -116,6 +110,12 @@
                 }
                 return read();
             }
+        } else {
+            ch = queuedData.charAt(0);
+            queuedData = queuedData.substring(1);
+            if (queuedData.isEmpty()) {
+                queuedData = null;
+            }
         }
         return ch;
     }
diff --git a/src/main/org/apache/tools/ant/filters/TabsToSpaces.java b/src/main/org/apache/tools/ant/filters/TabsToSpaces.java
index 15c7c50..43fbe59 100644
--- a/src/main/org/apache/tools/ant/filters/TabsToSpaces.java
+++ b/src/main/org/apache/tools/ant/filters/TabsToSpaces.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/filters/TailFilter.java b/src/main/org/apache/tools/ant/filters/TailFilter.java
index 0f26496..d50a473 100644
--- a/src/main/org/apache/tools/ant/filters/TailFilter.java
+++ b/src/main/org/apache/tools/ant/filters/TailFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -66,7 +66,7 @@
     /** the position in the current line */
     private int       linePos   = 0;
 
-    private LinkedList<String> lineList = new LinkedList<String>();
+    private LinkedList<String> lineList = new LinkedList<>();
 
     /**
      * Constructor for "dummy" instances.
@@ -108,7 +108,7 @@
             setInitialized(true);
         }
 
-        while (line == null || line.length() == 0) {
+        while (line == null || line.isEmpty()) {
             line = lineTokenizer.getToken(in);
             line = tailFilter(line);
             if (line == null) {
@@ -188,13 +188,11 @@
         Parameter[] params = getParameters();
         if (params != null) {
             for (Parameter param : params) {
-                if (LINES_KEY.equals(param.getName())) {
+                final String paramName = param.getName();
+                if (LINES_KEY.equals(paramName)) {
                     setLines(Long.parseLong(param.getValue()));
-                    continue;
-                }
-                if (SKIP_KEY.equals(param.getName())) {
+                } else if (SKIP_KEY.equals(paramName)) {
                     skip = Long.parseLong(param.getValue());
-                    continue;
                 }
             }
         }
diff --git a/src/main/org/apache/tools/ant/filters/TokenFilter.java b/src/main/org/apache/tools/ant/filters/TokenFilter.java
index 7da00cd..67c9283 100644
--- a/src/main/org/apache/tools/ant/filters/TokenFilter.java
+++ b/src/main/org/apache/tools/ant/filters/TokenFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 
 import java.io.IOException;
 import java.io.Reader;
-import java.util.Enumeration;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -59,15 +58,15 @@
 
 
     /** string filters */
-    private Vector<Filter>    filters   = new Vector<Filter>();
+    private Vector<Filter> filters = new Vector<>();
     /** the tokenizer to use on the input stream */
     private Tokenizer tokenizer = null;
     /** the output token termination */
-    private String    delimOutput = null;
+    private String delimOutput = null;
     /** the current string token from the input stream */
-    private String    line      = null;
+    private String line    = null;
     /** the position in the current string token */
-    private int       linePos   = 0;
+    private int    linePos = 0;
 
     /**
      * Constructor for "dummy" instances.
@@ -105,26 +104,23 @@
         if (tokenizer == null) {
             tokenizer = new LineTokenizer();
         }
-        while (line == null || line.length() == 0) {
+        while (line == null || line.isEmpty()) {
             line = tokenizer.getToken(in);
             if (line == null) {
                 return -1;
             }
-            for (Enumeration<Filter> e = filters.elements(); e.hasMoreElements();) {
-                Filter filter = e.nextElement();
+            for (Filter filter : filters) {
                 line = filter.filter(line);
                 if (line == null) {
                     break;
                 }
             }
             linePos = 0;
-            if (line != null) {
-                if (tokenizer.getPostToken().length() != 0) {
-                    if (delimOutput != null) {
-                        line = line + delimOutput;
-                    } else {
-                        line = line + tokenizer.getPostToken();
-                    }
+            if (line != null && !tokenizer.getPostToken().isEmpty()) {
+                if (delimOutput != null) {
+                    line += delimOutput;
+                } else {
+                    line += tokenizer.getPostToken();
                 }
             }
         }
@@ -374,13 +370,13 @@
             if (from == null) {
                 throw new BuildException("Missing from in stringreplace");
             }
-            StringBuffer ret = new StringBuffer();
+            final StringBuilder ret = new StringBuilder();
             int start = 0;
             int found = line.indexOf(from);
             while (found >= 0) {
                 // write everything up to the from
                 if (found > start) {
-                    ret.append(line.substring(start, found));
+                    ret.append(line, start, found);
                 }
 
                 // write the replacement to
@@ -395,7 +391,7 @@
 
             // write the remaining characters
             if (line.length() > start) {
-                ret.append(line.substring(start, line.length()));
+                ret.append(line, start, line.length());
             }
 
             return ret.toString();
@@ -594,7 +590,7 @@
          * @return the trimmed line
          */
         public String filter(String line) {
-            if (line.trim().length() == 0) {
+            if (line.trim().isEmpty()) {
                 return null;
             }
             return line;
@@ -624,7 +620,7 @@
          * @return the converted string
          */
         public String filter(String string) {
-            StringBuffer output = new StringBuffer(string.length());
+            StringBuilder output = new StringBuilder(string.length());
             for (int i = 0; i < string.length(); ++i) {
                 char ch = string.charAt(i);
                 if (!(isDeleteCharacter(ch))) {
diff --git a/src/main/org/apache/tools/ant/filters/UniqFilter.java b/src/main/org/apache/tools/ant/filters/UniqFilter.java
index 2983b6c..dfb84fd 100644
--- a/src/main/org/apache/tools/ant/filters/UniqFilter.java
+++ b/src/main/org/apache/tools/ant/filters/UniqFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/filters/util/ChainReaderHelper.java b/src/main/org/apache/tools/ant/filters/util/ChainReaderHelper.java
index f176c33..99ec773 100644
--- a/src/main/org/apache/tools/ant/filters/util/ChainReaderHelper.java
+++ b/src/main/org/apache/tools/ant/filters/util/ChainReaderHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,9 +23,13 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import java.util.Vector;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -34,7 +38,6 @@
 import org.apache.tools.ant.filters.ChainableReader;
 import org.apache.tools.ant.types.AntFilterReader;
 import org.apache.tools.ant.types.FilterChain;
-import org.apache.tools.ant.types.Parameter;
 import org.apache.tools.ant.types.Parameterizable;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.FileUtils;
@@ -44,6 +47,37 @@
  *
  */
 public final class ChainReaderHelper {
+    /**
+     * Created type.
+     */
+    public class ChainReader extends FilterReader {
+
+        private List<AntClassLoader> cleanupLoaders;
+
+        private ChainReader(Reader in, List<AntClassLoader> cleanupLoaders) {
+            super(in);
+            this.cleanupLoaders = cleanupLoaders;
+        }
+
+        public String readFully() throws IOException {
+            return ChainReaderHelper.this.readFully(this);
+        }
+
+        @Override
+        public void close() throws IOException {
+            cleanUpClassLoaders(cleanupLoaders);
+            super.close();
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                close();
+            } finally {
+                super.finalize();
+            }
+        }
+    }
 
     // default buffer size
     private static final int DEFAULT_BUFFER_SIZE = 8192;
@@ -61,7 +95,7 @@
     /**
      * Chain of filters
      */
-    public Vector<FilterChain> filterChains = new Vector<FilterChain>();
+    public Vector<FilterChain> filterChains = new Vector<>();
 
     /** The Ant project */
     private Project project = null;
@@ -69,7 +103,25 @@
     // CheckStyle:VisibilityModifier ON
 
     /**
-     * Sets the primary reader
+     * Default constructor.
+     */
+    public ChainReaderHelper() {
+    }
+
+    /**
+     * Convenience constructor.
+     * @param project ditto
+     * @param primaryReader ditto
+     * @param filterChains ditto
+     */
+    public ChainReaderHelper(Project project, Reader primaryReader,
+        Iterable<FilterChain> filterChains) {
+        withProject(project).withPrimaryReader(primaryReader)
+            .withFilterChains(filterChains);
+    }
+
+    /**
+     * Sets the primary {@link Reader}
      * @param rdr the reader object
      */
     public void setPrimaryReader(Reader rdr) {
@@ -77,6 +129,16 @@
     }
 
     /**
+     * Fluent primary {@link Reader} mutator.
+     * @param rdr Reader
+     * @return {@code this}
+     */
+    public ChainReaderHelper withPrimaryReader(Reader rdr) {
+        setPrimaryReader(rdr);
+        return this;
+    }
+
+    /**
      * Set the project to work with
      * @param project the current project
      */
@@ -85,6 +147,16 @@
     }
 
     /**
+     * Fluent {@link Project} mutator.
+     * @param project ditto
+     * @return {@code this}
+     */
+    public ChainReaderHelper withProject(Project project) {
+        setProject(project);
+        return this;
+    }
+
+    /**
      * Get the project
      *
      * @return the current project
@@ -103,6 +175,16 @@
     }
 
     /**
+     * Fluent buffer size mutator.
+     * @param size ditto
+     * @return {@code this}
+     */
+    public ChainReaderHelper withBufferSize(int size) {
+        setBufferSize(size);
+        return this;
+    }
+
+    /**
      * Sets the collection of filter reader sets
      *
      * @param fchain the filter chains collection
@@ -112,42 +194,56 @@
     }
 
     /**
+     * Fluent {@code filterChains} mutator.
+     * @param filterChains ditto
+     * @return {@code this}
+     */
+    public ChainReaderHelper withFilterChains(Iterable<FilterChain> filterChains) {
+        final Vector<FilterChain> fcs;
+        if (filterChains instanceof Vector<?>) {
+            fcs = (Vector<FilterChain>) filterChains;
+        } else {
+            fcs = new Vector<>();
+            filterChains.forEach(fcs::add);
+        }
+        setFilterChains(fcs);
+        return this;
+    }
+
+    /**
+     * Fluent mechanism to apply some {@link Consumer}.
+     * @param consumer ditto
+     * @return {@code this}
+     */
+    public ChainReaderHelper with(Consumer<ChainReaderHelper> consumer) {
+        consumer.accept(this);
+        return this;
+    }
+
+    /**
      * Assemble the reader
      * @return the assembled reader
      * @exception BuildException if an error occurs
      */
-    public Reader getAssembledReader() throws BuildException {
+    public ChainReader getAssembledReader() throws BuildException {
         if (primaryReader == null) {
             throw new BuildException("primaryReader must not be null.");
         }
 
         Reader instream = primaryReader;
-        final int filterReadersCount = filterChains.size();
-        final Vector<Object> finalFilters = new Vector<Object>();
-        final ArrayList<AntClassLoader> classLoadersToCleanUp =
-            new ArrayList<AntClassLoader>();
+        final List<AntClassLoader> classLoadersToCleanUp = new ArrayList<>();
 
-        for (int i = 0; i < filterReadersCount; i++) {
-            final FilterChain filterchain =
-                filterChains.elementAt(i);
-            final Vector<Object> filterReaders = filterchain.getFilterReaders();
-            final int readerCount = filterReaders.size();
-            for (int j = 0; j < readerCount; j++) {
-                finalFilters.addElement(filterReaders.elementAt(j));
-            }
-        }
+        final List<Object> finalFilters =
+            filterChains.stream().map(FilterChain::getFilterReaders)
+                .flatMap(Collection::stream).collect(Collectors.toList());
 
-        final int filtersCount = finalFilters.size();
-
-        if (filtersCount > 0) {
+        if (!finalFilters.isEmpty()) {
             boolean success = false;
             try {
-                for (int i = 0; i < filtersCount; i++) {
-                    Object o = finalFilters.elementAt(i);
-
+                for (Object o : finalFilters) {
                     if (o instanceof AntFilterReader) {
                         instream =
-                            expandReader((AntFilterReader) finalFilters.elementAt(i),
+                            expandReader((AntFilterReader) o,
                                          instream, classLoadersToCleanUp);
                     } else if (o instanceof ChainableReader) {
                         setProjectOnObject(o);
@@ -157,26 +253,12 @@
                 }
                 success = true;
             } finally {
-                if (!success && classLoadersToCleanUp.size() > 0) {
+                if (!success && !classLoadersToCleanUp.isEmpty()) {
                     cleanUpClassLoaders(classLoadersToCleanUp);
                 }
             }
         }
-        final Reader finalReader = instream;
-        return classLoadersToCleanUp.size() == 0 ? finalReader
-            : new FilterReader(finalReader) {
-                    public void close() throws IOException {
-                        FileUtils.close(in);
-                        cleanUpClassLoaders(classLoadersToCleanUp);
-                    }
-                    protected void finalize() throws Throwable {
-                        try {
-                            close();
-                        } finally {
-                            super.finalize();
-                        }
-                    }
-                };
+        return new ChainReader(instream, classLoadersToCleanUp);
     }
 
     /**
@@ -199,9 +281,7 @@
      * Deregisters Classloaders from the project so GC can remove them later.
      */
     private static void cleanUpClassLoaders(List<AntClassLoader> loaders) {
-        for (Iterator<AntClassLoader> it = loaders.iterator(); it.hasNext();) {
-            it.next().cleanup();
-        }
+        loaders.forEach(AntClassLoader::cleanup);
     }
 
     /**
@@ -211,8 +291,7 @@
      * @return the contents of the file as a string
      * @exception IOException if an error occurs
      */
-    public String readFully(Reader rdr)
-        throws IOException {
+    public String readFully(Reader rdr) throws IOException {
         return FileUtils.readFully(rdr, bufferSize);
     }
 
@@ -227,57 +306,45 @@
                                 final List<AntClassLoader> classLoadersToCleanUp) {
         final String className = filter.getClassName();
         final Path classpath = filter.getClasspath();
-        final Project pro = filter.getProject();
         if (className != null) {
             try {
-                Class<?> clazz = null;
-                if (classpath == null) {
-                    clazz = Class.forName(className);
-                } else {
-                    AntClassLoader al = pro.createClassLoader(classpath);
-                    classLoadersToCleanUp.add(al);
-                    clazz = Class.forName(className, true, al);
+                Class<? extends FilterReader> clazz;
+                try {
+                    if (classpath == null) {
+                        clazz = Class.forName(className)
+                            .asSubclass(FilterReader.class);
+                    } else {
+                        AntClassLoader al =
+                            filter.getProject().createClassLoader(classpath);
+                        classLoadersToCleanUp.add(al);
+                        clazz = Class.forName(className, true, al)
+                            .asSubclass(FilterReader.class);
+                    }
+                } catch (ClassCastException ex) {
+                    throw new BuildException("%s does not extend %s", className,
+                        FilterReader.class.getName());
                 }
-                if (clazz != null) {
-                    if (!FilterReader.class.isAssignableFrom(clazz)) {
-                        throw new BuildException(className + " does not extend"
-                                                 + " java.io.FilterReader");
-                    }
-                    final Constructor<?>[] constructors = clazz.getConstructors();
-                    int j = 0;
-                    boolean consPresent = false;
-                    for (; j < constructors.length; j++) {
-                        Class<?>[] types = constructors[j].getParameterTypes();
-                        if (types.length == 1
-                            && types[0].isAssignableFrom(Reader.class)) {
-                            consPresent = true;
-                            break;
-                        }
-                    }
-                    if (!consPresent) {
-                        throw new BuildException(className + " does not define"
-                                                 + " a public constructor"
-                                                 + " that takes in a Reader"
-                                                 + " as its single argument.");
-                    }
-                    final Reader[] rdr = {ancestor};
-                    Reader instream =
-                        (Reader) constructors[j].newInstance((Object[]) rdr);
-                    setProjectOnObject(instream);
-                    if (Parameterizable.class.isAssignableFrom(clazz)) {
-                        final Parameter[] params = filter.getParams();
-                        ((Parameterizable) instream).setParameters(params);
-                    }
-                    return instream;
+                Optional<Constructor<?>> ctor =
+                    Stream.of(clazz.getConstructors())
+                        .filter(c -> c.getParameterCount() == 1
+                            && c.getParameterTypes()[0]
+                                .isAssignableFrom(Reader.class))
+                        .findFirst();
+
+                Object instream = ctor
+                    .orElseThrow(() -> new BuildException(
+                        "%s does not define a public constructor that takes in a %s as its single argument.",
+                        className, Reader.class.getSimpleName()))
+                    .newInstance(ancestor);
+
+                setProjectOnObject(instream);
+                if (Parameterizable.class.isAssignableFrom(clazz)) {
+                    ((Parameterizable) instream).setParameters(filter.getParams());
                 }
-            } catch (final ClassNotFoundException cnfe) {
-                throw new BuildException(cnfe);
-            } catch (final InstantiationException ie) {
-                throw new BuildException(ie);
-            } catch (final IllegalAccessException iae) {
-                throw new BuildException(iae);
-            } catch (final InvocationTargetException ite) {
-                throw new BuildException(ite);
+                return (Reader) instream;
+            } catch (ClassNotFoundException | InstantiationException
+                    | IllegalAccessException | InvocationTargetException ex) {
+                throw new BuildException(ex);
             }
         }
         // Ant 1.7.1 and earlier ignore <filterreader> without a
diff --git a/src/main/org/apache/tools/ant/filters/util/JavaClassHelper.java b/src/main/org/apache/tools/ant/filters/util/JavaClassHelper.java
index 4e97521..a98678c 100644
--- a/src/main/org/apache/tools/ant/filters/util/JavaClassHelper.java
+++ b/src/main/org/apache/tools/ant/filters/util/JavaClassHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,6 @@
 import org.apache.bcel.classfile.ClassParser;
 import org.apache.bcel.classfile.ConstantValue;
 import org.apache.bcel.classfile.Field;
-import org.apache.bcel.classfile.JavaClass;
 
 // CheckStyle:HideUtilityClassConstructorCheck OFF - bc
 /**
@@ -31,9 +30,6 @@
  *
  */
 public final class JavaClassHelper {
-    /** System specific line separator. */
-    private static final String LS = System.getProperty("line.separator");
-
     /**
      * Get the constants declared in a file as name=value
      *
@@ -46,21 +42,16 @@
         final StringBuffer sb = new StringBuffer();
         final ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
         final ClassParser parser = new ClassParser(bis, "");
-        final JavaClass javaClass = parser.parse();
-        final Field[] fields = javaClass.getFields();
-        for (final Field field : fields) {
+        for (final Field field : parser.parse().getFields()) {
             if (field != null) {
                 final ConstantValue cv = field.getConstantValue();
                 if (cv != null) {
                     String cvs = cv.toString();
-                    //Remove start and end quotes if field is a String
+                    // Remove start and end quotes if field is a String
                     if (cvs.startsWith("\"") && cvs.endsWith("\"")) {
                         cvs = cvs.substring(1, cvs.length() - 1);
                     }
-                    sb.append(field.getName());
-                    sb.append('=');
-                    sb.append(cvs);
-                    sb.append(LS);
+                    sb.append(String.format("%s=%s%n", field.getName(), cvs));
                 }
             }
         }
diff --git a/src/main/org/apache/tools/ant/helper/AntXMLContext.java b/src/main/org/apache/tools/ant/helper/AntXMLContext.java
index 393ad5c..e0facbf 100644
--- a/src/main/org/apache/tools/ant/helper/AntXMLContext.java
+++ b/src/main/org/apache/tools/ant/helper/AntXMLContext.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -53,7 +53,7 @@
      * defined. Project maintains a Hashtable, which is not ordered.
      * This will allow description to know the original order.
      */
-    private Vector<Target> targetVector = new Vector<Target>();
+    private Vector<Target> targetVector = new Vector<>();
 
     /**
      * Parent directory of the build file. Used for resolving entities
@@ -91,7 +91,7 @@
     /** The stack of RuntimeConfigurable2 wrapping the
         objects.
     */
-    private Vector<RuntimeConfigurable> wStack = new Vector<RuntimeConfigurable>();
+    private Vector<RuntimeConfigurable> wStack = new Vector<>();
 
     /**
      * Indicates whether the project tag attributes are to be ignored
@@ -100,7 +100,7 @@
     private boolean ignoreProjectTag = false;
 
     /** Keeps track of prefix -> uri mapping during parsing */
-    private Map<String, List<String>> prefixMapping = new HashMap<String, List<String>>();
+    private Map<String, List<String>> prefixMapping = new HashMap<>();
 
 
     /** Keeps track of targets in files */
@@ -217,7 +217,7 @@
         if (wStack.size() < 1) {
             return null;
         }
-        return (RuntimeConfigurable) wStack.elementAt(wStack.size() - 1);
+        return wStack.elementAt(wStack.size() - 1);
     }
 
     /**
@@ -229,7 +229,7 @@
         if (wStack.size() < 2) {
             return null;
         }
-        return (RuntimeConfigurable) wStack.elementAt(wStack.size() - 2);
+        return wStack.elementAt(wStack.size() - 2);
     }
 
     /**
@@ -362,11 +362,7 @@
      * @param uri    a namespace uri
      */
     public void startPrefixMapping(String prefix, String uri) {
-        List<String> list = prefixMapping.get(prefix);
-        if (list == null) {
-            list = new ArrayList<String>();
-            prefixMapping.put(prefix, list);
-        }
+        List<String> list = prefixMapping.computeIfAbsent(prefix, k -> new ArrayList<>());
         list.add(uri);
     }
 
@@ -377,7 +373,7 @@
      */
     public void endPrefixMapping(String prefix) {
         List<String> list = prefixMapping.get(prefix);
-        if (list == null || list.size() == 0) {
+        if (list == null || list.isEmpty()) {
             return; // Should not happen
         }
         list.remove(list.size() - 1);
@@ -391,10 +387,10 @@
      */
     public String getPrefixMapping(String prefix) {
         List<String> list = prefixMapping.get(prefix);
-        if (list == null || list.size() == 0) {
+        if (list == null || list.isEmpty()) {
             return null;
         }
-        return (String) list.get(list.size() - 1);
+        return list.get(list.size() - 1);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/helper/DefaultExecutor.java b/src/main/org/apache/tools/ant/helper/DefaultExecutor.java
index dbdd36e..a56599b 100644
--- a/src/main/org/apache/tools/ant/helper/DefaultExecutor.java
+++ b/src/main/org/apache/tools/ant/helper/DefaultExecutor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/helper/IgnoreDependenciesExecutor.java b/src/main/org/apache/tools/ant/helper/IgnoreDependenciesExecutor.java
index be0a289..9503530 100644
--- a/src/main/org/apache/tools/ant/helper/IgnoreDependenciesExecutor.java
+++ b/src/main/org/apache/tools/ant/helper/IgnoreDependenciesExecutor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
index d2014b3..f5785b1 100644
--- a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
+++ b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.helper;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -26,6 +25,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
@@ -89,6 +89,7 @@
      *
      * @since Ant 1.8.0
      */
+    @Override
     public boolean canParseAntlibDescriptor(Resource resource) {
         return true;
     }
@@ -103,6 +104,7 @@
      *
      * @since Ant 1.8.0
      */
+    @Override
     public UnknownElement parseAntlibDescriptor(Project containingProject,
                                                 Resource resource) {
         URLProvider up = resource.as(URLProvider.class);
@@ -144,10 +146,11 @@
      * @param source  the xml source
      * @exception BuildException if an error occurs
      */
+    @Override
     public void parse(Project project, Object source) throws BuildException {
         getImportStack().addElement(source);
         AntXMLContext context = null;
-        context = (AntXMLContext) project.getReference(REFID_CONTEXT);
+        context = project.getReference(REFID_CONTEXT);
         if (context == null) {
             context = new AntXMLContext(project);
             project.addReference(REFID_CONTEXT, context);
@@ -164,7 +167,7 @@
                 newCurrent.setProject(project);
                 newCurrent.setName("");
                 context.setCurrentTarget(newCurrent);
-                context.setCurrentTargets(new HashMap<String, Target>());
+                context.setCurrentTargets(new HashMap<>());
                 context.setImplicitTarget(newCurrent);
                 parse(project, source, new RootHandler(context, mainHandler));
                 newCurrent.execute();
@@ -175,7 +178,7 @@
             }
         } else {
             // top level file
-            context.setCurrentTargets(new HashMap<String, Target>());
+            context.setCurrentTargets(new HashMap<>());
             parse(project, source, new RootHandler(context, mainHandler));
             // Execute the top-level target
             context.getImplicitTarget().execute();
@@ -207,13 +210,11 @@
         } else if (source instanceof URL) {
             url = (URL) source;
         } else if (source instanceof Resource) {
-            FileProvider fp =
-                ((Resource) source).as(FileProvider.class);
+            FileProvider fp = ((Resource) source).as(FileProvider.class);
             if (fp != null) {
                 buildFile = fp.getFile();
             } else {
-                URLProvider up =
-                    ((Resource) source).as(URLProvider.class);
+                URLProvider up = ((Resource) source).as(URLProvider.class);
                 if (up != null) {
                     url = up.getURL();
                 }
@@ -248,12 +249,11 @@
             String uri = null;
             if (buildFile != null) {
                 uri = FILE_UTILS.toURI(buildFile.getAbsolutePath());
-                inputStream = new FileInputStream(buildFile);
+                inputStream = Files.newInputStream(buildFile.toPath());
             } else {
                 uri = url.toString();
-                int pling = -1;
-                if (uri.startsWith("jar:file")
-                    && (pling = uri.indexOf("!/")) > -1) {
+                int pling = uri.indexOf("!/");
+                if (uri.startsWith("jar:file") && pling > -1) {
                     zf = new ZipFile(org.apache.tools.ant.launch.Locator
                                      .fromJarURI(uri), "UTF-8");
                     inputStream =
@@ -273,12 +273,10 @@
                         + uri + (zf != null ? " from a zip file" : ""),
                         Project.MSG_VERBOSE);
 
-            DefaultHandler hb = handler;
-
-            parser.setContentHandler(hb);
-            parser.setEntityResolver(hb);
-            parser.setErrorHandler(hb);
-            parser.setDTDHandler(hb);
+            parser.setContentHandler(handler);
+            parser.setEntityResolver(handler);
+            parser.setErrorHandler(handler);
+            parser.setDTDHandler(handler);
             parser.parse(inputSource);
         } catch (SAXParseException exc) {
             Location location = new Location(exc.getSystemId(), exc.getLineNumber(), exc
@@ -468,7 +466,7 @@
             throws SAXParseException {
             String s = new String(buf, start, count).trim();
 
-            if (s.length() > 0) {
+            if (!s.isEmpty()) {
                 throw new SAXParseException("Unexpected text \"" + s + "\"", context.getLocator());
             }
         }
@@ -488,7 +486,7 @@
      * with the implicit execution stack)
      */
     public static class RootHandler extends DefaultHandler {
-        private Stack<AntHandler> antHandlers = new Stack<AntHandler>();
+        private Stack<AntHandler> antHandlers = new Stack<>();
         private AntHandler currentHandler = null;
         private AntXMLContext context;
 
@@ -522,6 +520,7 @@
          *                 document. Will not be <code>null</code>.
          * @return an inputsource for this identifier
          */
+        @Override
         public InputSource resolveEntity(String publicId, String systemId) {
 
             context.getProject().log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
@@ -539,10 +538,10 @@
                 }
                 context.getProject().log("file=" + file, Project.MSG_DEBUG);
                 try {
-                    InputSource inputSource = new InputSource(new FileInputStream(file));
+                    InputSource inputSource = new InputSource(Files.newInputStream(file.toPath()));
                     inputSource.setSystemId(FILE_UTILS.toURI(file.getAbsolutePath()));
                     return inputSource;
-                } catch (FileNotFoundException fne) {
+                } catch (IOException fne) {
                     context.getProject().log(file.getAbsolutePath() + " could not be found",
                                              Project.MSG_WARN);
                 }
@@ -567,6 +566,7 @@
          * @exception org.xml.sax.SAXParseException if the tag given is not
          *                              <code>"project"</code>
          */
+        @Override
         public void startElement(String uri, String tag, String qname, Attributes attrs)
             throws SAXParseException {
             AntHandler next = currentHandler.onStartChild(uri, tag, qname, attrs, context);
@@ -581,6 +581,7 @@
          * @param locator The locator used by the parser.
          *                Will not be <code>null</code>.
          */
+        @Override
         public void setDocumentLocator(Locator locator) {
             context.setLocator(locator);
         }
@@ -596,10 +597,10 @@
          *
          * @exception SAXException in case of error (not thrown in this implementation)
          */
+        @Override
         public void endElement(String uri, String name, String qName) throws SAXException {
             currentHandler.onEndElement(uri, name, context);
-            AntHandler prev = (AntHandler) antHandlers.pop();
-            currentHandler = prev;
+            currentHandler = antHandlers.pop();
             if (currentHandler != null) {
                 currentHandler.onEndChild(uri, name, qName, context);
             }
@@ -613,6 +614,7 @@
          * @param count The number of characters to read.
          * @exception SAXParseException if an error occurs
          */
+        @Override
         public void characters(char[] buf, int start, int count) throws SAXParseException {
             currentHandler.characters(buf, start, count, context);
         }
@@ -623,6 +625,7 @@
          * @param prefix the namespace prefix
          * @param uri the namespace uri
          */
+        @Override
         public void startPrefixMapping(String prefix, String uri) {
             context.startPrefixMapping(prefix, uri);
         }
@@ -632,6 +635,7 @@
          *
          * @param prefix the prefix that is not mapped anymore
          */
+        @Override
         public void endPrefixMapping(String prefix) {
             context.endPrefixMapping(prefix);
         }
@@ -655,10 +659,11 @@
          * @return The project handler that handles subelements of project
          * @exception SAXParseException if the qualified name is not "project".
          */
+        @Override
         public AntHandler onStartChild(String uri, String name, String qname, Attributes attrs,
                                        AntXMLContext context) throws SAXParseException {
             if ("project".equals(name)
-                && (uri.equals("") || uri.equals(ANT_CORE_URI))) {
+                && (uri.isEmpty() || uri.equals(ANT_CORE_URI))) {
                 return ProjectHelper2.projectHandler;
             }
             if (name.equals(qname)) {
@@ -694,6 +699,7 @@
          *            encountered or if the <code>"default"</code> attribute
          *            is missing.
          */
+        @Override
         public void onStartElement(String uri, String tag, String qname, Attributes attrs,
                                    AntXMLContext context) throws SAXParseException {
             String baseDir = null;
@@ -716,48 +722,52 @@
 
             for (int i = 0; i < attrs.getLength(); i++) {
                 String attrUri = attrs.getURI(i);
-                if (attrUri != null && !attrUri.equals("") && !attrUri.equals(uri)) {
+                if (attrUri != null && !attrUri.isEmpty() && !attrUri.equals(uri)) {
                     continue; // Ignore attributes from unknown uris
                 }
-                String key = attrs.getLocalName(i);
                 String value = attrs.getValue(i);
-
-                if ("default".equals(key)) {
-                    if (value != null && !value.equals("")) {
-                        if (!context.isIgnoringProjectTag()) {
-                            project.setDefault(value);
-                        }
-                    }
-                } else if ("name".equals(key)) {
-                    if (value != null) {
-                        context.setCurrentProjectName(value);
-                        nameAttributeSet = true;
-                        if (!context.isIgnoringProjectTag()) {
-                            project.setName(value);
-                            project.addReference(value, project);
-                        } else if (isInIncludeMode()) {
-                            if (!"".equals(value) && getCurrentTargetPrefix()!= null && getCurrentTargetPrefix().endsWith(ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX))  {
-                                String newTargetPrefix = getCurrentTargetPrefix().replace(ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX, value);
-                                // help nested include tasks
-                                setCurrentTargetPrefix(newTargetPrefix);
+                switch (attrs.getLocalName(i)) {
+                    case "default":
+                        if (value != null && !value.isEmpty()) {
+                            if (!context.isIgnoringProjectTag()) {
+                                project.setDefault(value);
                             }
                         }
-                    }
-                } else if ("id".equals(key)) {
-                    if (value != null) {
-                        // What's the difference between id and name ?
-                        if (!context.isIgnoringProjectTag()) {
-                            project.addReference(value, project);
+                        break;
+                    case "name":
+                        if (value != null) {
+                            context.setCurrentProjectName(value);
+                            nameAttributeSet = true;
+                            if (!context.isIgnoringProjectTag()) {
+                                project.setName(value);
+                                project.addReference(value, project);
+                            } else if (isInIncludeMode()) {
+                                if (!value.isEmpty() && getCurrentTargetPrefix() != null
+                                        && getCurrentTargetPrefix().endsWith(ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX)) {
+                                    String newTargetPrefix = getCurrentTargetPrefix().replace(ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX, value);
+                                    // help nested include tasks
+                                    setCurrentTargetPrefix(newTargetPrefix);
+                                }
+                            }
                         }
-                    }
-                } else if ("basedir".equals(key)) {
-                    if (!context.isIgnoringProjectTag()) {
-                        baseDir = value;
-                    }
-                } else {
-                    // TODO ignore attributes in a different NS ( maybe store them ? )
-                    throw new SAXParseException("Unexpected attribute \"" + attrs.getQName(i)
-                                                + "\"", context.getLocator());
+                        break;
+                    case "id":
+                        if (value != null) {
+                            // What's the difference between id and name ?
+                            if (!context.isIgnoringProjectTag()) {
+                                project.addReference(value, project);
+                            }
+                        }
+                        break;
+                    case "basedir":
+                        if (!context.isIgnoringProjectTag()) {
+                            baseDir = value;
+                        }
+                        break;
+                    default:
+                        // TODO ignore attributes in a different NS (maybe store them ?)
+                        throw new SAXParseException("Unexpected attribute \"" + attrs.getQName(i)
+                                + "\"", context.getLocator());
                 }
             }
 
@@ -810,8 +820,8 @@
                 return;
             }
             // set explicitly before starting ?
-            if (project.getProperty("basedir") != null) {
-                project.setBasedir(project.getProperty("basedir"));
+            if (project.getProperty(MagicNames.PROJECT_BASEDIR) != null) {
+                project.setBasedir(project.getProperty(MagicNames.PROJECT_BASEDIR));
             } else {
                 // Default for baseDir is the location of the build file.
                 if (baseDir == null) {
@@ -850,10 +860,11 @@
          *            <code>"extension-point"</code>
          *            or a data type definition
          */
+        @Override
         public AntHandler onStartChild(String uri, String name, String qname, Attributes attrs,
                                        AntXMLContext context) throws SAXParseException {
-            return (name.equals("target") || name.equals("extension-point"))
-                && (uri.equals("") || uri.equals(ANT_CORE_URI))
+            return ("target".equals(name) || "extension-point".equals(name))
+                && (uri.isEmpty() || uri.equals(ANT_CORE_URI))
                 ? ProjectHelper2.targetHandler : ProjectHelper2.elementHandler;
         }
     }
@@ -883,6 +894,7 @@
          * @exception SAXParseException if an unexpected attribute is encountered
          *            or if the <code>"name"</code> attribute is missing.
          */
+        @Override
         public void onStartElement(String uri, String tag, String qname, Attributes attrs,
                                    AntXMLContext context) throws SAXParseException {
             String name = null;
@@ -899,40 +911,47 @@
 
             for (int i = 0; i < attrs.getLength(); i++) {
                 String attrUri = attrs.getURI(i);
-                if (attrUri != null && !attrUri.equals("") && !attrUri.equals(uri)) {
+                if (attrUri != null && !attrUri.isEmpty() && !attrUri.equals(uri)) {
                     continue; // Ignore attributes from unknown uris
                 }
-                String key = attrs.getLocalName(i);
                 String value = attrs.getValue(i);
-
-                if ("name".equals(key)) {
-                    name = value;
-                    if ("".equals(name)) {
-                        throw new BuildException("name attribute must " + "not be empty");
-                    }
-                } else if ("depends".equals(key)) {
-                    depends = value;
-                } else if ("if".equals(key)) {
-                    target.setIf(value);
-                } else if ("unless".equals(key)) {
-                    target.setUnless(value);
-                } else if ("id".equals(key)) {
-                    if (value != null && !value.equals("")) {
-                        context.getProject().addReference(value, target);
-                    }
-                } else if ("description".equals(key)) {
-                    target.setDescription(value);
-                } else if ("extensionOf".equals(key)) {
-                    extensionPoint = value;
-                } else if ("onMissingExtensionPoint".equals(key)) {
-                    try {
-                        extensionPointMissing = OnMissingExtensionPoint.valueOf(value);
-                    } catch (IllegalArgumentException e) {
-                        throw new BuildException("Invalid onMissingExtensionPoint " + value);
-                    }
-                } else {
-                    throw new SAXParseException("Unexpected attribute \"" + key + "\"", context
-                                                .getLocator());
+                switch (attrs.getLocalName(i)) {
+                    case "name":
+                        name = value;
+                        if (name.isEmpty()) {
+                            throw new BuildException("name attribute must not be empty");
+                        }
+                        break;
+                    case "depends":
+                        depends = value;
+                        break;
+                    case "if":
+                        target.setIf(value);
+                        break;
+                    case "unless":
+                        target.setUnless(value);
+                        break;
+                    case "id":
+                        if (value != null && !value.isEmpty()) {
+                            context.getProject().addReference(value, target);
+                        }
+                        break;
+                    case "description":
+                        target.setDescription(value);
+                        break;
+                    case "extensionOf":
+                        extensionPoint = value;
+                        break;
+                    case "onMissingExtensionPoint":
+                        try {
+                            extensionPointMissing = OnMissingExtensionPoint.valueOf(value);
+                        } catch (IllegalArgumentException e) {
+                            throw new BuildException("Invalid onMissingExtensionPoint " + value);
+                        }
+                        break;
+                    default:
+                        throw new SAXParseException("Unexpected attribute \"" + attrs.getQName(i)
+                                + "\"", context.getLocator());
                 }
             }
 
@@ -964,7 +983,7 @@
                                          target.getLocation());
             }
             Hashtable<String, Target> projectTargets = project.getTargets();
-            boolean   usedTarget = false;
+            boolean usedTarget = false;
             // If the name has not already been defined define it
             if (projectTargets.containsKey(name)) {
                 project.log("Already defined in main or a previous import, ignore " + name,
@@ -976,7 +995,7 @@
                 usedTarget = true;
             }
 
-            if (depends.length() > 0) {
+            if (!depends.isEmpty()) {
                 if (!isInIncludeMode) {
                     target.setDepends(depends);
                 } else {
@@ -1007,8 +1026,7 @@
             }
             if (extensionPoint != null) {
                 ProjectHelper helper =
-                    (ProjectHelper) context.getProject().
-                    getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+                        context.getProject().getReference(MagicNames.REFID_PROJECT_HELPER);
                 for (String extPointName : Target.parseDepends(extensionPoint, name, "extensionOf")) {
                     if (extensionPointMissing == null) {
                         extensionPointMissing = OnMissingExtensionPoint.FAIL;
@@ -1033,7 +1051,7 @@
 
         private String getTargetPrefix(AntXMLContext context) {
             String configuredValue = getCurrentTargetPrefix();
-            if (configuredValue != null && configuredValue.length() == 0) {
+            if (configuredValue != null && configuredValue.isEmpty()) {
                 configuredValue = null;
             }
             if (configuredValue != null) {
@@ -1041,7 +1059,7 @@
             }
 
             String projectName = context.getCurrentProjectName();
-            if ("".equals(projectName)) {
+            if (projectName != null && projectName.isEmpty()) {
                 projectName = null;
             }
 
@@ -1063,6 +1081,7 @@
          * @exception SAXParseException if an error occurs when initialising
          *                              the appropriate child handler
          */
+        @Override
         public AntHandler onStartChild(String uri, String name, String qname, Attributes attrs,
                                        AntXMLContext context) throws SAXParseException {
             return ProjectHelper2.elementHandler;
@@ -1076,6 +1095,7 @@
          * @param tag The name of the element.
          * @param context The current context.
          */
+        @Override
         public void onEndElement(String uri, String tag, AntXMLContext context) {
             context.setCurrentTarget(context.getImplicitTarget());
         }
@@ -1110,6 +1130,7 @@
          * @exception SAXParseException in case of error (not thrown in
          *                              this implementation)
          */
+        @Override
         public void onStartElement(String uri, String tag, String qname, Attributes attrs,
                                    AntXMLContext context) throws SAXParseException {
             RuntimeConfigurable parentWrapper = context.currentWrapper();
@@ -1151,7 +1172,7 @@
             for (int i = 0; i < attrs.getLength(); i++) {
                 String name = attrs.getLocalName(i);
                 String attrUri = attrs.getURI(i);
-                if (attrUri != null && !attrUri.equals("") && !attrUri.equals(uri)) {
+                if (attrUri != null && !attrUri.isEmpty() && !attrUri.equals(uri)) {
                     name = attrUri + ":" + attrs.getQName(i);
                 }
                 String value = attrs.getValue(i);
@@ -1196,6 +1217,7 @@
          *
          * @see ProjectHelper#addText(Project,java.lang.Object,char[],int,int)
          */
+        @Override
         public void characters(char[] buf, int start, int count,
                                AntXMLContext context) throws SAXParseException {
             RuntimeConfigurable wrapper = context.currentWrapper();
@@ -1219,6 +1241,7 @@
          * @exception SAXParseException if an error occurs when initialising
          *                              the appropriate child handler
          */
+        @Override
         public AntHandler onStartChild(String uri, String tag, String qname, Attributes attrs,
                                        AntXMLContext context) throws SAXParseException {
             return ProjectHelper2.elementHandler;
@@ -1232,6 +1255,7 @@
          * @param tag The name of the element.
          * @param context The current context.
          */
+        @Override
         public void onEndElement(String uri, String tag, AntXMLContext context) {
             context.popWrapper();
         }
diff --git a/src/main/org/apache/tools/ant/helper/ProjectHelperImpl.java b/src/main/org/apache/tools/ant/helper/ProjectHelperImpl.java
index 4b159f3..8bf889a 100644
--- a/src/main/org/apache/tools/ant/helper/ProjectHelperImpl.java
+++ b/src/main/org/apache/tools/ant/helper/ProjectHelperImpl.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,17 @@
 package org.apache.tools.ant.helper;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
 import java.util.Locale;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.IntrospectionHelper;
 import org.apache.tools.ant.Location;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.RuntimeConfigurable;
@@ -42,6 +44,7 @@
 import org.xml.sax.HandlerBase;
 import org.xml.sax.InputSource;
 import org.xml.sax.Locator;
+import org.xml.sax.Parser;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.XMLReaderAdapter;
@@ -61,7 +64,7 @@
      * SAX 1 style parser used to parse the given file. This may
      * in fact be a SAX 2 XMLReader wrapped in an XMLReaderAdapter.
      */
-    private org.xml.sax.Parser parser;
+    private Parser parser;
 
     /** The project to configure. */
     private Project project;
@@ -110,22 +113,20 @@
                 + "default plugin");
         }
         File bFile = (File) source;
-        FileInputStream inputStream = null;
-        InputSource inputSource = null;
 
         this.project = project;
         this.buildFile = new File(bFile.getAbsolutePath());
         buildFileParent = new File(this.buildFile.getParent());
 
         try {
-            try {
-                parser = JAXPUtils.getParser();
-            } catch (BuildException e) {
-                parser = new XMLReaderAdapter(JAXPUtils.getXMLReader());
-            }
+            parser = JAXPUtils.getParser();
+        } catch (BuildException e) {
+            parser = new XMLReaderAdapter(JAXPUtils.getXMLReader());
+        }
+
+        try (InputStream inputStream = Files.newInputStream(bFile.toPath())) {
             String uri = FILE_UTILS.toURI(bFile.getAbsolutePath());
-            inputStream = new FileInputStream(bFile);
-            inputSource = new InputSource(inputStream);
+            InputSource inputSource = new InputSource(inputStream);
             inputSource.setSystemId(uri);
             project.log("parsing buildfile " + bFile + " with URI = " + uri, Project.MSG_VERBOSE);
             HandlerBase hb = new RootHandler(this);
@@ -135,8 +136,8 @@
             parser.setDTDHandler(hb);
             parser.parse(inputSource);
         } catch (SAXParseException exc) {
-            Location location = new Location(exc.getSystemId(), exc.getLineNumber(), exc
-                    .getColumnNumber());
+            Location location = new Location(exc.getSystemId(), exc.getLineNumber(),
+                    exc.getColumnNumber());
 
             Throwable t = exc.getException();
             if (t instanceof BuildException) {
@@ -159,8 +160,6 @@
             throw new BuildException("Encoding of project file is invalid.", exc);
         } catch (IOException exc) {
             throw new BuildException("Error reading project file: " + exc.getMessage(), exc);
-        } finally {
-            FileUtils.close(inputStream);
         }
     }
 
@@ -244,7 +243,7 @@
         public void characters(char[] buf, int start, int count) throws SAXParseException {
             String s = new String(buf, start, count).trim();
 
-            if (s.length() > 0) {
+            if (!s.isEmpty()) {
                 throw new SAXParseException("Unexpected text \"" + s + "\"", helperImpl.locator);
             }
         }
@@ -302,10 +301,10 @@
                             + "' for compliance with other XML tools", Project.MSG_WARN);
                 }
                 try {
-                    InputSource inputSource = new InputSource(new FileInputStream(file));
+                    InputSource inputSource = new InputSource(Files.newInputStream(file.toPath()));
                     inputSource.setSystemId(FILE_UTILS.toURI(file.getAbsolutePath()));
                     return inputSource;
-                } catch (FileNotFoundException fne) {
+                } catch (IOException fne) {
                     helperImpl.project.log(file.getAbsolutePath() + " could not be found",
                             Project.MSG_WARN);
                 }
@@ -387,23 +386,26 @@
             for (int i = 0; i < attrs.getLength(); i++) {
                 String key = attrs.getName(i);
                 String value = attrs.getValue(i);
-
-                if ("default".equals(key)) {
-                    def = value;
-                } else if ("name".equals(key)) {
-                    name = value;
-                } else if ("id".equals(key)) {
-                    id = value;
-                } else if ("basedir".equals(key)) {
-                    baseDir = value;
-                } else {
-                    throw new SAXParseException(
-                            "Unexpected attribute \"" + attrs.getName(i)
-                            + "\"", helperImpl.locator);
+                switch (key) {
+                    case "default":
+                        def = value;
+                        break;
+                    case "name":
+                        name = value;
+                        break;
+                    case "id":
+                        id = value;
+                        break;
+                    case "basedir":
+                        baseDir = value;
+                        break;
+                    default:
+                        throw new SAXParseException("Unexpected attribute \"" + key + "\"",
+                                helperImpl.locator);
                 }
             }
 
-            if (def != null && !def.equals("")) {
+            if (def != null && !def.isEmpty()) {
                 helperImpl.project.setDefault(def);
             } else {
                 throw new BuildException("The default attribute is required");
@@ -418,8 +420,8 @@
                 helperImpl.project.addReference(id, helperImpl.project);
             }
 
-            if (helperImpl.project.getProperty("basedir") != null) {
-                helperImpl.project.setBasedir(helperImpl.project.getProperty("basedir"));
+            if (helperImpl.project.getProperty(MagicNames.PROJECT_BASEDIR) != null) {
+                helperImpl.project.setBasedir(helperImpl.project.getProperty(MagicNames.PROJECT_BASEDIR));
             } else {
                 if (baseDir == null) {
                     helperImpl.project.setBasedir(helperImpl.buildFileParent.getAbsolutePath());
@@ -523,26 +525,32 @@
             for (int i = 0; i < attrs.getLength(); i++) {
                 String key = attrs.getName(i);
                 String value = attrs.getValue(i);
-
-                if ("name".equals(key)) {
-                    name = value;
-                    if (name.equals("")) {
-                        throw new BuildException("name attribute must not" + " be empty",
-                                new Location(helperImpl.locator));
-                    }
-                } else if ("depends".equals(key)) {
-                    depends = value;
-                } else if ("if".equals(key)) {
-                    ifCond = value;
-                } else if ("unless".equals(key)) {
-                    unlessCond = value;
-                } else if ("id".equals(key)) {
-                    id = value;
-                } else if ("description".equals(key)) {
-                    description = value;
-                } else {
-                    throw new SAXParseException("Unexpected attribute \"" + key + "\"",
-                            helperImpl.locator);
+                switch (key) {
+                    case "name":
+                        name = value;
+                        if (name.isEmpty()) {
+                            throw new BuildException("name attribute must not be empty",
+                                    new Location(helperImpl.locator));
+                        }
+                        break;
+                    case "depends":
+                        depends = value;
+                        break;
+                    case "if":
+                        ifCond = value;
+                        break;
+                    case "unless":
+                        unlessCond = value;
+                        break;
+                    case "id":
+                        id = value;
+                        break;
+                    case "description":
+                        description = value;
+                        break;
+                    default:
+                        throw new SAXParseException("Unexpected attribute \"" + key + "\"",
+                                helperImpl.locator);
                 }
             }
 
@@ -562,13 +570,13 @@
             target.setDescription(description);
             helperImpl.project.addTarget(name, target);
 
-            if (id != null && !id.equals("")) {
+            if (id != null && !id.isEmpty()) {
                 helperImpl.project.addReference(id, target);
             }
 
             // take care of dependencies
 
-            if (depends.length() > 0) {
+            if (!depends.isEmpty()) {
                 target.setDepends(depends);
             }
         }
diff --git a/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java b/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java
index 6577c94..7fb228b 100644
--- a/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java
+++ b/src/main/org/apache/tools/ant/helper/SingleCheckExecutor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/input/DefaultInputHandler.java b/src/main/org/apache/tools/ant/input/DefaultInputHandler.java
index fa68223..46ed09b 100644
--- a/src/main/org/apache/tools/ant/input/DefaultInputHandler.java
+++ b/src/main/org/apache/tools/ant/input/DefaultInputHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/input/GreedyInputHandler.java b/src/main/org/apache/tools/ant/input/GreedyInputHandler.java
index cb52f4f..2005f39 100644
--- a/src/main/org/apache/tools/ant/input/GreedyInputHandler.java
+++ b/src/main/org/apache/tools/ant/input/GreedyInputHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -65,7 +65,7 @@
                 }
             }
             request.setInput(new String(baos.toByteArray()));
-            if (!(request.isInputValid())) {
+            if (!request.isInputValid()) {
                 throw new BuildException(
                     "Received invalid console input");
             }
diff --git a/src/main/org/apache/tools/ant/input/InputHandler.java b/src/main/org/apache/tools/ant/input/InputHandler.java
index a71546f..9b1efb0 100644
--- a/src/main/org/apache/tools/ant/input/InputHandler.java
+++ b/src/main/org/apache/tools/ant/input/InputHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/input/InputRequest.java b/src/main/org/apache/tools/ant/input/InputRequest.java
index 57a77da..552821a 100644
--- a/src/main/org/apache/tools/ant/input/InputRequest.java
+++ b/src/main/org/apache/tools/ant/input/InputRequest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/input/MultipleChoiceInputRequest.java b/src/main/org/apache/tools/ant/input/MultipleChoiceInputRequest.java
index 4baab8f..a1b0a9a 100644
--- a/src/main/org/apache/tools/ant/input/MultipleChoiceInputRequest.java
+++ b/src/main/org/apache/tools/ant/input/MultipleChoiceInputRequest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.ant.input;
 
+import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.Vector;
 
@@ -33,26 +34,39 @@
      * @param prompt The prompt to show to the user.  Must not be null.
      * @param choices holds all input values that are allowed.
      *                Must not be null.
+     * @deprecated Use {@link #MultipleChoiceInputRequest(String,Collection)} instead
      */
+    @Deprecated
     public MultipleChoiceInputRequest(String prompt, Vector<String> choices) {
+        this(prompt, (Collection<String>) choices);
+    }
+
+    /**
+     * @param prompt The prompt to show to the user.  Must not be null.
+     * @param choices holds all input values that are allowed.
+     *                Must not be null.
+     */
+    public MultipleChoiceInputRequest(String prompt, Collection<String> choices) {
         super(prompt);
         if (choices == null) {
             throw new IllegalArgumentException("choices must not be null");
         }
-        this.choices = new LinkedHashSet<String>(choices);
+        this.choices = new LinkedHashSet<>(choices);
     }
 
     /**
      * @return The possible values.
      */
     public Vector<String> getChoices() {
-        return new Vector<String>(choices);
+        return new Vector<>(choices);
     }
 
     /**
      * @return true if the input is one of the allowed values.
      */
+    @Override
     public boolean isInputValid() {
-        return choices.contains(getInput()) || ("".equals(getInput()) && getDefaultValue() != null);
+        return choices.contains(getInput())
+            || (getInput().isEmpty() && getDefaultValue() != null);
     }
 }
diff --git a/src/main/org/apache/tools/ant/input/PropertyFileInputHandler.java b/src/main/org/apache/tools/ant/input/PropertyFileInputHandler.java
index e1e3cf1..9054c95 100644
--- a/src/main/org/apache/tools/ant/input/PropertyFileInputHandler.java
+++ b/src/main/org/apache/tools/ant/input/PropertyFileInputHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,9 @@
 
 package org.apache.tools.ant.input;
 
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Properties;
 
 import org.apache.tools.ant.BuildException;
@@ -56,13 +57,13 @@
 
         Object o = props.get(request.getPrompt());
         if (o == null) {
-            throw new BuildException("Unable to find input for \'"
-                                     + request.getPrompt() + "\'");
+            throw new BuildException("Unable to find input for '"
+                                     + request.getPrompt() + "'");
         }
         request.setInput(o.toString());
         if (!request.isInputValid()) {
             throw new BuildException("Found invalid input " + o
-                                     + " for \'" + request.getPrompt() + "\'");
+                                     + " for '" + request.getPrompt() + "'");
         }
     }
 
@@ -82,7 +83,7 @@
             props = new Properties();
 
             try {
-                props.load(new FileInputStream(propsFile));
+                props.load(Files.newInputStream(Paths.get(propsFile)));
             } catch (IOException e) {
                 throw new BuildException("Couldn't load " + propsFile, e);
             }
diff --git a/src/main/org/apache/tools/ant/input/SecureInputHandler.java b/src/main/org/apache/tools/ant/input/SecureInputHandler.java
index 7fb0c34..9d9ca03 100644
--- a/src/main/org/apache/tools/ant/input/SecureInputHandler.java
+++ b/src/main/org/apache/tools/ant/input/SecureInputHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,13 +17,12 @@
  */
 package org.apache.tools.ant.input;
 
+import java.util.Arrays;
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.ReflectUtil;
 
 /**
  * Prompts and requests input.  May loop until a valid input has
- * been entered. Doesn't echo input (requires Java6). If Java6 is not
- * available, falls back to the DefaultHandler (insecure).
+ * been entered. Doesn't echo input.
  * @since Ant 1.7.1
  */
 public class SecureInputHandler extends DefaultInputHandler {
@@ -39,29 +38,16 @@
      * @param request the request to handle
      * @throws BuildException if not possible to read from console
      */
+    @SuppressWarnings("unused")
     public void handleInput(InputRequest request) throws BuildException {
-        boolean nullInput = false;
         String prompt = getPrompt(request);
-        try {
-            Object console = ReflectUtil.invokeStatic(System.class, "console");
-            do {
-                char[] input = (char[]) ReflectUtil.invoke(
-                    console, "readPassword", String.class, prompt,
-                    Object[].class, (Object[]) null);
-                if (input == null) {
-                    nullInput = true;
-                    break;
-                }
-                request.setInput(new String(input));
-                /* for security zero char array after retrieving value */
-                java.util.Arrays.fill(input, ' ');
-            } while (!request.isInputValid());
-        } catch (Exception e) {
-            /* Java6 not present use default handler */
-            super.handleInput(request);
-        }
-        if (nullInput) {
-            throw new BuildException("unexpected end of stream while reading input");
-        }
+        do {
+            char[] input = System.console().readPassword(prompt);
+            if (input == null) {
+                throw new BuildException("unexpected end of stream while reading input");
+            }
+            request.setInput(new String(input));
+            Arrays.fill(input, ' ');
+        } while (!request.isInputValid());
     }
 }
diff --git a/src/main/org/apache/tools/ant/launch/AntMain.java b/src/main/org/apache/tools/ant/launch/AntMain.java
index 4703eaa..d319ccf 100644
--- a/src/main/org/apache/tools/ant/launch/AntMain.java
+++ b/src/main/org/apache/tools/ant/launch/AntMain.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/launch/LaunchException.java b/src/main/org/apache/tools/ant/launch/LaunchException.java
index 1bb37f8..b7a5a05 100644
--- a/src/main/org/apache/tools/ant/launch/LaunchException.java
+++ b/src/main/org/apache/tools/ant/launch/LaunchException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/launch/Launcher.java b/src/main/org/apache/tools/ant/launch/Launcher.java
index 953792b..cad6359 100644
--- a/src/main/org/apache/tools/ant/launch/Launcher.java
+++ b/src/main/org/apache/tools/ant/launch/Launcher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,9 +25,6 @@
 import java.util.List;
 import java.util.StringTokenizer;
 
-
-
-
 /**
  * This is a launcher for Ant.
  *
@@ -35,9 +32,6 @@
  */
 public class Launcher {
 
-    private Launcher() {
-    }
-
     /**
      * The Ant Home (installation) Directory property.
      * {@value}
@@ -63,11 +57,6 @@
     public static final String ANT_PRIVATELIB = "lib";
 
     /**
-     * launch diagnostics flag; for debugging trouble at launch time.
-     */
-    public boolean launchDiag = false;
-
-    /**
      * The location of a per-user library directory.
      * <p>It's value is the concatenation of {@link #ANT_PRIVATEDIR}
      * with {@link #ANT_PRIVATELIB}, with an appropriate file separator
@@ -126,6 +115,13 @@
         }
     }
 
+    /**
+     * launch diagnostics flag; for debugging trouble at launch time.
+     */
+    public boolean launchDiag = false;
+
+    private Launcher() {
+    }
 
     /**
      * Add a CLASSPATH or -lib to lib path urls.
@@ -143,7 +139,7 @@
         while (tokenizer.hasMoreElements()) {
             final String elementName = tokenizer.nextToken();
             final File element = new File(elementName);
-            if (elementName.indexOf('%') != -1 && !element.exists()) {
+            if (elementName.contains("%") && !element.exists()) {
                 continue;
             }
             if (getJars && element.isDirectory()) {
@@ -156,7 +152,7 @@
                 }
             }
 
-            final URL url = Locator.fileToURL(element);
+            final URL url = new URL(element.toURI().toASCIIString());
             if (launchDiag) {
                 System.out.println("adding library URL: " + url);
             }
@@ -193,44 +189,45 @@
         }
 
         if (!antHome.exists()) {
-            throw new LaunchException("Ant home is set incorrectly or "
-                + "ant could not be located (estimated value="+antHome.getAbsolutePath()+")");
+            throw new LaunchException(
+                "Ant home is set incorrectly or ant could not be located (estimated value="
+                    + antHome.getAbsolutePath() + ")");
         }
 
-        final List<String> libPaths = new ArrayList<String>();
+        final List<String> libPaths = new ArrayList<>();
         String cpString = null;
-        final List<String> argList = new ArrayList<String>();
+        final List<String> argList = new ArrayList<>();
         String[] newArgs;
         boolean  noUserLib = false;
         boolean  noClassPath = false;
 
         for (int i = 0; i < args.length; ++i) {
-            if (args[i].equals("-lib")) {
+            if ("-lib".equals(args[i])) {
                 if (i == args.length - 1) {
-                    throw new LaunchException("The -lib argument must "
-                        + "be followed by a library location");
+                    throw new LaunchException(
+                        "The -lib argument must be followed by a library location");
                 }
                 libPaths.add(args[++i]);
-            } else if (args[i].equals("-cp")) {
+            } else if ("-cp".equals(args[i])) {
                 if (i == args.length - 1) {
-                    throw new LaunchException("The -cp argument must "
-                        + "be followed by a classpath expression");
+                    throw new LaunchException(
+                        "The -cp argument must be followed by a classpath expression");
                 }
                 if (cpString != null) {
-                    throw new LaunchException("The -cp argument must "
-                        + "not be repeated");
+                    throw new LaunchException(
+                        "The -cp argument must not be repeated");
                 }
                 cpString = args[++i];
-            } else if (args[i].equals("--nouserlib") || args[i].equals("-nouserlib")) {
+            } else if ("--nouserlib".equals(args[i]) || "-nouserlib".equals(args[i])) {
                 noUserLib = true;
-            } else if (args[i].equals("--launchdiag")) {
+            } else if ("--launchdiag".equals(args[i])) {
                 launchDiag = true;
-            } else if (args[i].equals("--noclasspath") || args[i].equals("-noclasspath")) {
+            } else if ("--noclasspath".equals(args[i]) || "-noclasspath".equals(args[i])) {
                 noClassPath = true;
-            } else if (args[i].equals("-main")) {
+            } else if ("-main".equals(args[i])) {
                 if (i == args.length - 1) {
-                    throw new LaunchException("The -main argument must "
-                            + "be followed by a library location");
+                    throw new LaunchException(
+                        "The -main argument must be followed by a library location");
                 }
                 mainClassname = args[++i];
             } else {
@@ -248,7 +245,7 @@
         if (argList.size() == args.length) {
             newArgs = args;
         } else {
-            newArgs = argList.toArray(new String[argList.size()]);
+            newArgs = argList.toArray(new String[0]);
         }
 
         final URL[] libURLs    = getLibPathURLs(
@@ -262,8 +259,8 @@
             libURLs, userURLs, systemURLs, toolsJAR);
 
         // now update the class.path property
-        final StringBuffer baseClassPath
-            = new StringBuffer(System.getProperty(JAVA_CLASS_PATH));
+        final StringBuilder baseClassPath
+            = new StringBuilder(System.getProperty(JAVA_CLASS_PATH));
         if (baseClassPath.charAt(baseClassPath.length() - 1)
                 == File.pathSeparatorChar) {
             baseClassPath.setLength(baseClassPath.length() - 1);
@@ -278,12 +275,12 @@
 
         final URLClassLoader loader = new URLClassLoader(jars, Launcher.class.getClassLoader());
         Thread.currentThread().setContextClassLoader(loader);
-        Class<?> mainClass = null;
+        Class<? extends AntMain> mainClass = null;
         int exitCode = 0;
         Throwable thrown = null;
         try {
-            mainClass = loader.loadClass(mainClassname);
-            final AntMain main = (AntMain) mainClass.newInstance();
+            mainClass = loader.loadClass(mainClassname).asSubclass(AntMain.class);
+            final AntMain main = mainClass.getDeclaredConstructor().newInstance();
             main.startAnt(newArgs, null, null);
         } catch (final InstantiationException ex) {
             System.err.println(
@@ -320,7 +317,7 @@
      */
     private URL[] getLibPathURLs(final String cpString, final List<String> libPaths)
         throws MalformedURLException {
-        final List<URL> libPathURLs = new ArrayList<URL>();
+        final List<URL> libPathURLs = new ArrayList<>();
 
         if (cpString != null) {
             addPath(cpString, false, libPathURLs);
@@ -330,7 +327,7 @@
             addPath(libPath, true, libPathURLs);
         }
 
-        return libPathURLs.toArray(new URL[libPathURLs.size()]);
+        return libPathURLs.toArray(new URL[0]);
     }
 
     /**
@@ -347,7 +344,7 @@
         if (antLibDirProperty != null) {
             antLibDir = new File(antLibDirProperty);
         }
-        if ((antLibDir == null) || !antLibDir.exists()) {
+        if (antLibDir == null || !antLibDir.exists()) {
             antLibDir = antLauncherDir;
             setProperty(ANTLIBDIR_PROPERTY, antLibDir.getAbsolutePath());
         }
@@ -389,7 +386,7 @@
             systemJars.length);
 
         if (toolsJar != null) {
-            jars[jars.length - 1] = Locator.fileToURL(toolsJar);
+            jars[jars.length - 1] = new URL(toolsJar.toURI().toASCIIString());
         }
         return jars;
     }
@@ -407,8 +404,8 @@
     }
 
     private void logPath(final String name, final File path) {
-        if(launchDiag) {
-            System.out.println(name+"= \""+path+"\"");
+        if (launchDiag) {
+            System.out.println(name + "= \"" + path + "\"");
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/launch/Locator.java b/src/main/org/apache/tools/ant/launch/Locator.java
index 0513e64..9f616b5 100644
--- a/src/main/org/apache/tools/ant/launch/Locator.java
+++ b/src/main/org/apache/tools/ant/launch/Locator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,14 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FilenameFilter;
 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;
+import java.util.stream.Stream;
 
 // CheckStyle:LineLengthCheck OFF - urls are long!
 /**
@@ -35,9 +36,9 @@
  * It is used at boot time in the launcher, and cannot make use of any of Ant's other classes.
  * <p>
  * This is a surprisingly brittle piece of code, and has had lots of bugs filed against it:
- * <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42275">running ant off a network share can cause Ant to fail</a>,
- * <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=8031">use File.toURI().toURL().toExternalForm()</a>,
- * <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42222">Locator implementation not encoding URI strings properly: spaces in paths</a>.
+ * <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=42275">running ant off a network share can cause Ant to fail</a>,
+ * <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=8031">use File.toURI().toURL().toExternalForm()</a>,
+ * <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=42222">Locator implementation not encoding URI strings properly: spaces in paths</a>.
  * It also breaks Eclipse 3.3 Betas:
  * <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=183283">Exception if installation path has spaces</a>.
  * <p>
@@ -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
@@ -95,11 +92,6 @@
             gAfterEscaping2[ch] = gHexChs[ch & NIBBLE_MASK];
         }
     }
-    /**
-     * Not instantiable
-     */
-    private Locator() {
-    }
 
     /**
      * Find the directory or jar file the class has been loaded from.
@@ -130,7 +122,7 @@
         if (c == null) {
             c = Locator.class.getClassLoader();
         }
-        URL url = null;
+        URL url;
         if (c == null) {
             url = ClassLoader.getSystemResource(resource);
         } else {
@@ -141,21 +133,19 @@
             try {
                 if (u.startsWith("jar:file:")) {
                     return new File(fromJarURI(u));
-                } else if (u.startsWith("file:")) {
+                }
+                if (u.startsWith("file:")) {
                     int tail = u.indexOf(resource);
                     String dirName = u.substring(0, tail);
                     return new File(fromURI(dirName));
                 }
             } catch (IllegalArgumentException e) {
                 //unable to determine the URI for reasons unknown.
-                return null;
             }
         }
         return null;
     }
 
-
-
     /**
      * Constructs a file path from a <code>file:</code> URI.
      *
@@ -164,7 +154,7 @@
      * <p>Prior to Java 1.4,<!-- TODO is JDK version actually relevant? -->
      * swallows '%' that are not followed by two characters.</p>
      *
-     * See <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
+     * See <a href="https://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
      * which makes some mention of how
      * characters not supported by URI Reference syntax should be escaped.
      *
@@ -174,57 +164,6 @@
      * @since Ant 1.6
      */
     public static String fromURI(String uri) {
-        return fromURIJava13(uri);
-        // #buzilla8031: first try Java 1.4.
-        // TODO should use java.net.URI now that we can rely on 1.4...
-        // but check for UNC-related regressions, e.g. #42275
-        // (and remember that \\server\share\file -> file:////server/share/file
-        // rather than -> file://server/share/file as it should;
-        // fixed only in JDK 7's java.nio.file.Path.toUri)
-        // return fromUriJava14(uri);
-    }
-
-    /**
-     * Java1.4+ code to extract the path from the URI.
-     * @param uri
-     * @return null if a conversion was not possible
-     */
-    /* currently unused:
-    private static String fromUriJava14(String uri) {
-        // Also check for properly formed URIs. Ant formerly recommended using
-        // nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't
-        // do that (just "foo.xml" is correct) but for compatibility we special-case
-        // things when the path is not absolute, and fall back to the old parsing behavior.
-        if (uri.startsWith("file:/")) {
-            try {
-                File f = new File(URI.create(encodeURI(uri)));
-                //bug #42227 forgot to decode before returning
-                return decodeUri(f.getAbsolutePath());
-            } catch (IllegalArgumentException e) {
-                // Bad URI, pass this on.
-                // no, this is downgraded to a warning after various
-                // JRE bugs surfaced. Hand off
-                // to our built in code on a failure
-                //throw new IllegalArgumentException(
-                //   "Bad URI " + uri + ":" + e.getMessage(), e);
-                e.printStackTrace();
-            } catch (Exception e) {
-                // Unexpected exception? Should not happen.
-                e.printStackTrace();
-            }
-        }
-        return null;
-    }
-     */
-
-    /**
-     * @param uri uri to expand
-     * @return the decoded URI
-     * @since Ant1.7.1
-     */
-    private static String fromURIJava13(String uri) {
-        // Fallback method for Java 1.3 or earlier.
-
         URL url = null;
         try {
             url = new URL(uri);
@@ -234,7 +173,7 @@
         if (url == null || !("file".equals(url.getProtocol()))) {
             throw new IllegalArgumentException(ERROR_NOT_FILE_URI + uri);
         }
-        StringBuffer buf = new StringBuffer(url.getHost());
+        StringBuilder buf = new StringBuilder(url.getHost());
         if (buf.length() > 0) {
             buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
         }
@@ -257,7 +196,7 @@
             int posi = cwd.indexOf(':');
             boolean pathStartsWithFileSeparator = path.startsWith(File.separator);
             boolean pathStartsWithUNC = path.startsWith("" + File.separator + File.separator);
-            if ((posi > 0) && pathStartsWithFileSeparator && !pathStartsWithUNC) {
+            if (posi > 0 && pathStartsWithFileSeparator && !pathStartsWithUNC) {
                 path = cwd.substring(0, posi + 1) + path;
             }
         } catch (UnsupportedEncodingException exc) {
@@ -292,7 +231,7 @@
      * @since Ant 1.7
      */
     public static String decodeUri(String uri) throws UnsupportedEncodingException {
-        if (uri.indexOf('%') == -1) {
+        if (!uri.contains("%")) {
             return uri;
         }
         ByteArrayOutputStream sb = new ByteArrayOutputStream(uri.length());
@@ -312,11 +251,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());
     }
 
     /**
@@ -324,14 +263,13 @@
      * 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;
-        StringBuffer sb = null;
+        StringBuilder sb = null;
         for (; i < len; i++) {
             ch = path.charAt(i);
             // if it's not an ASCII character, break here, and use UTF-8 encoding
@@ -340,7 +278,7 @@
             }
             if (gNeedEscaping[ch]) {
                 if (sb == null) {
-                    sb = new StringBuffer(path.substring(0, i));
+                    sb = new StringBuilder(path.substring(0, i));
                 }
                 sb.append('%');
                 sb.append(gAfterEscaping1[ch]);
@@ -354,17 +292,15 @@
         // we saw some non-ascii character
         if (i < len) {
             if (sb == null) {
-                sb = new StringBuffer(path.substring(0, i));
+                sb = new StringBuilder(path.substring(0, i));
             }
             // get UTF-8 bytes for the remaining sub-string
-            byte[] bytes = null;
-            byte b;
-            bytes = path.substring(i).getBytes(URI_ENCODING);
+            byte[] bytes = path.substring(i).getBytes(StandardCharsets.UTF_8);
             len = bytes.length;
 
             // for each byte
             for (i = 0; i < len; i++) {
-                b = bytes[i];
+                byte b = bytes[i];
                 // for non-ascii character: make it positive, then escape
                 if (b < 0) {
                     ch = b + BYTE_SIZE;
@@ -444,8 +380,6 @@
             toolsJar = new File(javaHome + libToolsJar);
         }
         if (!toolsJar.exists()) {
-            System.out.println("Unable to locate tools.jar. "
-                 + "Expected to find it in " + toolsJar.getPath());
             return null;
         }
         return toolsJar;
@@ -466,7 +400,7 @@
      */
     public static URL[] getLocationURLs(File location)
          throws MalformedURLException {
-        return getLocationURLs(location, new String[]{".jar"});
+        return getLocationURLs(location, ".jar");
     }
 
     /**
@@ -484,8 +418,8 @@
      *            formed.
      */
     public static URL[] getLocationURLs(File location,
-                                        final String[] extensions)
-         throws MalformedURLException {
+                                        final String... extensions)
+            throws MalformedURLException {
         URL[] urls = new URL[0];
 
         if (!location.exists()) {
@@ -503,22 +437,21 @@
             }
             return urls;
         }
-        File[] matches = location.listFiles(
-            new FilenameFilter() {
-                public boolean accept(File dir, String name) {
-                    String littleName = name.toLowerCase(Locale.ENGLISH);
-                    for (int i = 0; i < extensions.length; ++i) {
-                        if (littleName.endsWith(extensions[i])) {
-                            return true;
-                        }
-                    }
-                    return false;
-                }
-            });
+        File[] matches = location.listFiles((dir, name) -> {
+            String littleName = name.toLowerCase(Locale.ENGLISH);
+            return Stream.of(extensions).anyMatch(littleName::endsWith);
+        });
         urls = new URL[matches.length];
         for (int i = 0; i < matches.length; ++i) {
             urls[i] = fileToURL(matches[i]);
         }
         return urls;
     }
+
+    /**
+     * Not instantiable
+     */
+    private Locator() {
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java b/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
index fb22f75..384f370 100644
--- a/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
+++ b/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,11 @@
  */
 package org.apache.tools.ant.listener;
 
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Properties;
 
 import org.apache.tools.ant.DefaultLogger;
@@ -162,7 +163,7 @@
             Properties prop = new Properties();
 
             if (userColorFile != null) {
-                in = new FileInputStream(userColorFile);
+                in = Files.newInputStream(Paths.get(userColorFile));
             } else {
                 in = getClass().getResourceAsStream(systemColorFile);
             }
@@ -212,7 +213,7 @@
                 colorsSet = true;
             }
 
-            final StringBuffer msg = new StringBuffer(message);
+            final StringBuilder msg = new StringBuilder(message);
             switch (priority) {
                 case Project.MSG_ERR:
                     msg.insert(0, errColor);
diff --git a/src/main/org/apache/tools/ant/listener/BigProjectLogger.java b/src/main/org/apache/tools/ant/listener/BigProjectLogger.java
index 7d618bc..952a67d 100644
--- a/src/main/org/apache/tools/ant/listener/BigProjectLogger.java
+++ b/src/main/org/apache/tools/ant/listener/BigProjectLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,12 +17,9 @@
  */
 package org.apache.tools.ant.listener;
 
-import java.io.File;
-
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.SubBuildListener;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * This is a special logger that is designed to make it easier to work
@@ -120,18 +117,11 @@
      * @param event An event with any relevant extra information. Must not be <code>null</code>.
      */
     public void subBuildStarted(BuildEvent event) {
-        String name = extractNameOrDefault(event);
         Project project = event.getProject();
-
-        File base = project == null ? null : project.getBaseDir();
-        String path =
-            (base == null)
-            ? "With no base directory"
-            : "In " + base.getAbsolutePath();
-        printMessage(StringUtils.LINE_SEP + getHeader()
-                + StringUtils.LINE_SEP + "Entering project " + name
-                        + StringUtils.LINE_SEP + path
-                        + StringUtils.LINE_SEP + getFooter(),
+        String path = (project == null) ? "With no base directory"
+                : "In " + project.getBaseDir().getAbsolutePath();
+        printMessage(String.format("%n%s%nEntering project %s%n%s%n%s", getHeader(),
+                extractNameOrDefault(event), path, getFooter()),
                 out,
                 event.getPriority());
     }
@@ -154,12 +144,9 @@
 
     /** {@inheritDoc} */
     public void subBuildFinished(BuildEvent event) {
-        String name = extractNameOrDefault(event);
-        String failed = event.getException() != null ? "failing " : "";
-        printMessage(StringUtils.LINE_SEP + getHeader()
-                + StringUtils.LINE_SEP + "Exiting " + failed + "project "
-                + name
-                + StringUtils.LINE_SEP + getFooter(),
+        printMessage(String.format("%n%s%nExiting %sproject %s%n%s",
+                getHeader(), event.getException() != null ? "failing " : "",
+                extractNameOrDefault(event), getFooter()),
                 out,
                 event.getPriority());
     }
diff --git a/src/main/org/apache/tools/ant/listener/CommonsLoggingListener.java b/src/main/org/apache/tools/ant/listener/CommonsLoggingListener.java
index cb4baa1..f813eba 100644
--- a/src/main/org/apache/tools/ant/listener/CommonsLoggingListener.java
+++ b/src/main/org/apache/tools/ant/listener/CommonsLoggingListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,6 +26,7 @@
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildListener;
 import org.apache.tools.ant.BuildLogger;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.UnknownElement;
@@ -61,11 +62,11 @@
     /**
      * name of the category under which target events are logged
      */
-    public static final String TARGET_LOG = "org.apache.tools.ant.Target";
+    public static final String TARGET_LOG = MagicNames.ANT_CORE_PACKAGE + ".Target";
     /**
      * name of the category under which project events are logged
      */
-    public static final String PROJECT_LOG = "org.apache.tools.ant.Project";
+    public static final String PROJECT_LOG = MagicNames.ANT_CORE_PACKAGE + ".Project";
 
     /**
      * Construct the listener and make sure that a LogFactory
@@ -78,7 +79,7 @@
         if (suffix != null) {
             suffix = suffix.replace('.', '-');
             suffix = suffix.replace(' ', '-');
-            cat = cat + "." + suffix;
+            cat += "." + suffix;
         }
         final PrintStream tmpOut = System.out;
         final PrintStream tmpErr = System.err;
@@ -102,6 +103,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void buildStarted(final BuildEvent event) {
         final Log log = getLog(PROJECT_LOG, null);
 
@@ -111,6 +113,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void buildFinished(final BuildEvent event) {
         if (initialized) {
             final Log log = getLog(PROJECT_LOG, event.getProject().getName());
@@ -128,6 +131,7 @@
      * @see BuildListener#targetStarted
      * {@inheritDoc}.
      */
+    @Override
     public void targetStarted(final BuildEvent event) {
         if (initialized) {
             final Log log = getLog(TARGET_LOG,
@@ -143,6 +147,7 @@
      * @see BuildListener#targetFinished
      * {@inheritDoc}.
      */
+    @Override
     public void targetFinished(final BuildEvent event) {
         if (initialized) {
             final String targetName = event.getTarget().getName();
@@ -162,6 +167,7 @@
      * @see BuildListener#taskStarted
      * {@inheritDoc}.
      */
+    @Override
     public void taskStarted(final BuildEvent event) {
         if (initialized) {
             final Task task = event.getTask();
@@ -184,6 +190,7 @@
      * @see BuildListener#taskFinished
      * {@inheritDoc}.
      */
+    @Override
     public void taskFinished(final BuildEvent event) {
         if (initialized) {
             final Task task = event.getTask();
@@ -213,16 +220,16 @@
      * @see BuildListener#messageLogged
      * {@inheritDoc}.
      */
+    @Override
     public void messageLogged(final BuildEvent event) {
         if (initialized) {
             Object categoryObject = event.getTask();
-            String categoryString = null;
+            String categoryString;
             String categoryDetail = null;
 
             if (categoryObject == null) {
                 categoryObject = event.getTarget();
                 if (categoryObject == null) {
-                    categoryObject = event.getProject();
                     categoryString = PROJECT_LOG;
                     categoryDetail = event.getProject().getName();
                 } else {
@@ -275,8 +282,6 @@
                 }
                 break;
             case Project.MSG_VERBOSE:
-                log.debug(message);
-                break;
             case Project.MSG_DEBUG:
                 log.debug(message);
                 break;
@@ -298,6 +303,7 @@
      * This is not used, the logger config is used instead.
      * @param level ignored
      */
+    @Override
     public void setMessageOutputLevel(final int level) {
         // Use the logger config
     }
@@ -306,6 +312,7 @@
      * Set the output print stream.
      * @param output the output stream
      */
+    @Override
     public void setOutputPrintStream(final PrintStream output) {
         this.out = output;
     }
@@ -315,6 +322,7 @@
      * This is ignored.
      * @param emacsMode ignored
      */
+    @Override
     public void setEmacsMode(final boolean emacsMode) {
         // Doesn't make sense for c-l. Use the logger config
     }
@@ -323,6 +331,7 @@
      * Set the error print stream.
      * @param err the error stream
      */
+    @Override
     public void setErrorPrintStream(final PrintStream err) {
         this.err = err;
     }
diff --git a/src/main/org/apache/tools/ant/listener/Log4jListener.java b/src/main/org/apache/tools/ant/listener/Log4jListener.java
index b691300..169fdf5 100644
--- a/src/main/org/apache/tools/ant/listener/Log4jListener.java
+++ b/src/main/org/apache/tools/ant/listener/Log4jListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,6 +20,7 @@
 import org.apache.log4j.Logger;
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Target;
 import org.apache.tools.ant.Task;
@@ -36,21 +37,25 @@
 
     /**
      * log category we log into
+     * @deprecated use MagicNames.ANT_CORE_PACKAGE
      */
-    public static final String LOG_ANT = "org.apache.tools.ant";
+    @Deprecated
+    public static final String LOG_ANT = MagicNames.ANT_CORE_PACKAGE;
 
     /**
      * Construct the listener
      */
     public Log4jListener() {
         // trigger the log4j initialization (if at all it's not yet initialized)
-        final Logger log = Logger.getLogger(LOG_ANT);
+        @SuppressWarnings("unused")
+        final Logger log = Logger.getLogger(MagicNames.ANT_CORE_PACKAGE);
     }
 
     /**
      * @see BuildListener#buildStarted
      * {@inheritDoc}.
      */
+    @Override
     public void buildStarted(final BuildEvent event) {
         final Logger log = Logger.getLogger(Project.class.getName());
         log.info("Build started.");
@@ -60,6 +65,7 @@
      * @see BuildListener#buildFinished
      * {@inheritDoc}.
      */
+    @Override
     public void buildFinished(final BuildEvent event) {
         final Logger log = Logger.getLogger(Project.class.getName());
         if (event.getException() == null) {
@@ -73,6 +79,7 @@
      * @see BuildListener#targetStarted
      * {@inheritDoc}.
      */
+    @Override
     public void targetStarted(final BuildEvent event) {
         final Logger log = Logger.getLogger(Target.class.getName());
         log.info("Target \"" + event.getTarget().getName() + "\" started.");
@@ -82,6 +89,7 @@
      * @see BuildListener#targetFinished
      * {@inheritDoc}.
      */
+    @Override
     public void targetFinished(final BuildEvent event) {
         final String targetName = event.getTarget().getName();
         final Logger cat = Logger.getLogger(Target.class.getName());
@@ -97,6 +105,7 @@
      * @see BuildListener#taskStarted
      * {@inheritDoc}.
      */
+    @Override
     public void taskStarted(final BuildEvent event) {
         final Task task = event.getTask();
         final Logger log = Logger.getLogger(task.getClass().getName());
@@ -107,6 +116,7 @@
      * @see BuildListener#taskFinished
      * {@inheritDoc}.
      */
+    @Override
     public void taskFinished(final BuildEvent event) {
         final Task task = event.getTask();
         final Logger log = Logger.getLogger(task.getClass().getName());
@@ -122,7 +132,7 @@
      * @see BuildListener#messageLogged
      * {@inheritDoc}.
      */
-    /** {@inheritDoc}. */
+    @Override
     public void messageLogged(final BuildEvent event) {
         Object categoryObject = event.getTask();
         if (categoryObject == null) {
@@ -145,8 +155,6 @@
                 log.info(event.getMessage());
                 break;
             case Project.MSG_VERBOSE:
-                log.debug(event.getMessage());
-                break;
             case Project.MSG_DEBUG:
                 log.debug(event.getMessage());
                 break;
diff --git a/src/main/org/apache/tools/ant/listener/MailLogger.java b/src/main/org/apache/tools/ant/listener/MailLogger.java
index 2de55bf..897f000 100644
--- a/src/main/org/apache/tools/ant/listener/MailLogger.java
+++ b/src/main/org/apache/tools/ant/listener/MailLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,29 +17,28 @@
  */
 package org.apache.tools.ant.listener;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Map;
 import java.util.Properties;
 import java.util.StringTokenizer;
 import java.util.Vector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DefaultLogger;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.email.EmailAddress;
-import org.apache.tools.ant.taskdefs.email.Header;
 import org.apache.tools.ant.taskdefs.email.Mailer;
 import org.apache.tools.ant.taskdefs.email.Message;
 import org.apache.tools.ant.util.ClasspathUtils;
 import org.apache.tools.ant.util.DateUtils;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 import org.apache.tools.mail.MailMessage;
 
 /**
@@ -48,12 +47,12 @@
  *  <ul>
  *    <li> MailLogger.mailhost [default: localhost] - Mail server to use</li>
  *    <li> MailLogger.port [default: 25] - Default port for SMTP </li>
- *    <li> Maillogger.user [no default] - user name for SMTP auth
- *    (requires JavaMail)</li>
- *    <li> Maillogger.password [no default] - password for SMTP auth
- *    (requires JavaMail)</li>
- *    <li> Maillogger.ssl [default: false] - on or true if ssl is
- *    needed (requires JavaMail)</li>
+ *    <li> MailLogger.user [no default] - user name for SMTP auth
+ *    (requires Java or Jakarta Mail)</li>
+ *    <li> MailLogger.password [no default] - password for SMTP auth
+ *    (requires Java or Jakarta Mail)</li>
+ *    <li> MailLogger.ssl [default: false] - on or true if ssl is
+ *    needed (requires Java or Jakarta Mail)</li>
  *    <li> MailLogger.from [required] - Mail "from" address</li>
  *    <li> MailLogger.from [no default] - Mail "replyto" address(es),
  *    comma-separated</li>
@@ -83,8 +82,8 @@
  *    mail body for a successful build, default is to send the logfile</li>
  *    <li> MailLogger.mimeType [default: text/plain] - MIME-Type of email</li>
  *    <li> MailLogger.charset [no default] - character set of email</li>
- *    <li> Maillogger.starttls.enable [default: false] - on or true if
- *    STARTTLS should be supported (requires JavaMail)</li>
+ *    <li> MailLogger.starttls.enable [default: false] - on or true if
+ *    STARTTLS should be supported (requires Java or Jakarta Mail)</li>
  *    <li> MailLogger.properties.file [no default] - Filename of
  *    properties file that will override other values.</li>
  *  </ul>
@@ -96,21 +95,22 @@
  *
  */
 public class MailLogger extends DefaultLogger {
+    private static final String DEFAULT_MIME_TYPE = "text/plain";
+
     /** Buffer in which the message is constructed prior to sending */
     private StringBuffer buffer = new StringBuffer();
 
-    private static final String DEFAULT_MIME_TYPE = "text/plain";
-
     /**
      *  Sends an e-mail with the log results.
      *
      * @param event the build finished event
      */
+    @Override
     public void buildFinished(BuildEvent event) {
         super.buildFinished(event);
 
         Project project = event.getProject();
-        Hashtable<String, Object> properties = project.getProperties();
+        Map<String, Object> properties = project.getProperties();
 
         // overlay specified properties file (if any), which overrides project
         // settings
@@ -119,7 +119,7 @@
         if (filename != null) {
             InputStream is = null;
             try {
-                is = new FileInputStream(filename);
+                is = Files.newInputStream(Paths.get(filename));
                 fileProperties.load(is);
             } catch (IOException ioe) {
                 // ignore because properties file is not required
@@ -128,11 +128,8 @@
             }
         }
 
-        for (Enumeration<?> e = fileProperties.keys(); e.hasMoreElements();) {
-            String key = (String) e.nextElement();
-            String value = fileProperties.getProperty(key);
-            properties.put(key, project.replaceProperties(value));
-        }
+        fileProperties.stringPropertyNames()
+                .forEach(key -> properties.put(key, project.replaceProperties(fileProperties.getProperty(key))));
 
         boolean success = (event.getException() == null);
         String prefix = success ? "success" : "failure";
@@ -167,8 +164,8 @@
                 .subject(getValue(
                              properties, prefix + ".subject",
                              (success) ? "Build Success" : "Build Failure"));
-            if (values.user().equals("")
-                && values.password().equals("")
+            if (values.user().isEmpty()
+                && values.password().isEmpty()
                 && !values.ssl() && !values.starttls()) {
                 sendMail(values, buffer.substring(0));
             } else {
@@ -309,8 +306,9 @@
      *
      * @param message the message being logger
      */
+    @Override
     protected void log(String message) {
-        buffer.append(message).append(StringUtils.LINE_SEP);
+        buffer.append(message).append(System.lineSeparator());
     }
 
 
@@ -324,7 +322,7 @@
      *      Set to null to make required.
      * @return                The value of the property, or default value.
      */
-    private String getValue(Hashtable<String, Object> properties, String name,
+    private String getValue(Map<String, Object> properties, String name,
                             String defaultValue) {
         String propertyName = "MailLogger." + name;
         String value = (String) properties.get(propertyName);
@@ -353,7 +351,7 @@
         mailMessage.setHeader("Date", DateUtils.getDateForHeader());
 
         mailMessage.from(values.from());
-        if (!values.replytoList().equals("")) {
+        if (!values.replytoList().isEmpty()) {
             StringTokenizer t = new StringTokenizer(
                 values.replytoList(), ", ", false);
             while (t.hasMoreTokens()) {
@@ -367,15 +365,15 @@
 
         mailMessage.setSubject(values.subject());
 
-        if (values.charset().length() > 0) {
+        if (values.charset().isEmpty()) {
+            mailMessage.setHeader("Content-Type", values.mimeType());
+        } else {
             mailMessage.setHeader("Content-Type", values.mimeType()
                                   + "; charset=\"" + values.charset() + "\"");
-        } else {
-            mailMessage.setHeader("Content-Type", values.mimeType());
         }
 
         PrintStream ps = mailMessage.getPrintStream();
-        ps.println(values.body().length() > 0 ? values.body() : message);
+        ps.println(values.body().isEmpty() ? message : values.body());
 
         mailMessage.sendAndClose();
     }
@@ -388,16 +386,14 @@
     private void sendMimeMail(Project project, Values values, String message) {
         Mailer mailer = null;
         try {
-            mailer = (Mailer) ClasspathUtils.newInstance(
-                    "org.apache.tools.ant.taskdefs.email.MimeMailer",
+            mailer = ClasspathUtils.newInstance(getMailerImplementation(),
                     MailLogger.class.getClassLoader(), Mailer.class);
         } catch (BuildException e) {
-            Throwable t = e.getCause() == null ? e : e.getCause();
-            log("Failed to initialise MIME mail: " + t.getMessage());
+            logBuildException("Failed to initialise MIME mail: ", e);
             return;
         }
-        // convert the replyTo string into a vector of emailaddresses
-        Vector<EmailAddress> replyToList = vectorizeEmailAddresses(values.replytoList());
+        // convert the replyTo string into a vector of EmailAddresses
+        Vector<EmailAddress> replyToList = splitEmailAddresses(values.replytoList());
         mailer.setHost(values.mailhost());
         mailer.setPort(values.port());
         mailer.setUser(values.user());
@@ -405,34 +401,62 @@
         mailer.setSSL(values.ssl());
         mailer.setEnableStartTLS(values.starttls());
         Message mymessage =
-            new Message(values.body().length() > 0 ? values.body() : message);
+            new Message(!values.body().isEmpty() ? values.body() : message);
         mymessage.setProject(project);
         mymessage.setMimeType(values.mimeType());
-        if (values.charset().length() > 0) {
+        if (!values.charset().isEmpty()) {
             mymessage.setCharset(values.charset());
         }
         mailer.setMessage(mymessage);
         mailer.setFrom(new EmailAddress(values.from()));
         mailer.setReplyToList(replyToList);
-        Vector<EmailAddress> toList = vectorizeEmailAddresses(values.toList());
+        Vector<EmailAddress> toList = splitEmailAddresses(values.toList());
         mailer.setToList(toList);
-        Vector<EmailAddress> toCcList = vectorizeEmailAddresses(values.toCcList());
+        Vector<EmailAddress> toCcList = splitEmailAddresses(values.toCcList());
         mailer.setCcList(toCcList);
-        Vector<EmailAddress> toBccList = vectorizeEmailAddresses(values.toBccList());
+        Vector<EmailAddress> toBccList = splitEmailAddresses(values.toBccList());
         mailer.setBccList(toBccList);
-        mailer.setFiles(new Vector<File>());
+        mailer.setFiles(new Vector<>());
         mailer.setSubject(values.subject());
-        mailer.setHeaders(new Vector<Header>());
+        mailer.setHeaders(new Vector<>());
         mailer.send();
     }
-    private Vector<EmailAddress> vectorizeEmailAddresses(String listString) {
-        Vector<EmailAddress> emailList = new Vector<EmailAddress>();
-        StringTokenizer tokens = new StringTokenizer(listString, ",");
-        while (tokens.hasMoreTokens()) {
-            emailList.addElement(new EmailAddress(tokens.nextToken()));
+
+    private Vector<EmailAddress> splitEmailAddresses(String listString) {
+        return Stream.of(listString.split(",")).map(EmailAddress::new)
+            .collect(Collectors.toCollection(Vector::new));
+    }
+
+    private String getMailerImplementation() {
+        //check to make sure that activation.jar
+        //and mail.jar are available - see bug 31969
+        try {
+            Class.forName("jakarta.activation.DataHandler");
+            Class.forName("jakarta.mail.internet.MimeMessage");
+
+            return "org.apache.tools.ant.taskdefs.email.JakartaMimeMailer";
+        } catch (ClassNotFoundException cnfe) {
+            logBuildException("Could not find Jakarta MIME mail: ",
+                    new BuildException(cnfe));
         }
-        return emailList;
+
+        try {
+            Class.forName("javax.activation.DataHandler");
+            Class.forName("javax.mail.internet.MimeMessage");
+
+            return "org.apache.tools.ant.taskdefs.email.MimeMailer";
+        } catch (ClassNotFoundException cnfe) {
+            logBuildException("Could not find MIME mail: ",
+                    new BuildException(cnfe));
+        }
+
+        return "org.apache.tools.ant.taskdefs.email.Mailer";
+    }
+
+    private void logBuildException(String reason, BuildException e) {
+        Throwable t = e.getCause() == null ? e : e.getCause();
+        if (Project.MSG_WARN <= msgOutputLevel) {
+            log(reason + t.getMessage());
+        }
     }
 }
-
-
diff --git a/src/main/org/apache/tools/ant/listener/ProfileLogger.java b/src/main/org/apache/tools/ant/listener/ProfileLogger.java
index bbf5bb4..50ad01b 100644
--- a/src/main/org/apache/tools/ant/listener/ProfileLogger.java
+++ b/src/main/org/apache/tools/ant/listener/ProfileLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,6 @@
 
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.DefaultLogger;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * This is a special logger that is designed to profile builds.
@@ -32,7 +31,7 @@
  */
 public class ProfileLogger extends DefaultLogger {
 
-    private Map<Object, Date> profileData = new ConcurrentHashMap<Object, Date>();
+    private Map<Object, Date> profileData = new ConcurrentHashMap<>();
 
     /**
      * Logs a message to say that the target has started.
@@ -41,6 +40,7 @@
      *            An event with any relevant extra information. Must not be
      *            <code>null</code>.
      */
+    @Override
     public void targetStarted(BuildEvent event) {
         Date now = new Date();
         String name = "Target " + event.getTarget().getName();
@@ -55,8 +55,9 @@
      *            An event with any relevant extra information. Must not be
      *            <code>null</code>.
      */
+    @Override
     public void targetFinished(BuildEvent event) {
-        Date start = (Date) profileData.remove(event.getTarget());
+        Date start = profileData.remove(event.getTarget());
         String name = "Target " + event.getTarget().getName();
         logFinish(event, start, name);
     }
@@ -68,6 +69,7 @@
      *            An event with any relevant extra information. Must not be
      *            <code>null</code>.
      */
+    @Override
     public void taskStarted(BuildEvent event) {
         String name = event.getTask().getTaskName();
         Date now = new Date();
@@ -82,29 +84,29 @@
      *            An event with any relevant extra information. Must not be
      *            <code>null</code>.
      */
+    @Override
     public void taskFinished(BuildEvent event) {
-        Date start = (Date) profileData.remove(event.getTask());
+        Date start = profileData.remove(event.getTask());
         String name = event.getTask().getTaskName();
         logFinish(event, start, name);
     }
 
     private void logFinish(BuildEvent event, Date start, String name) {
         Date now = new Date();
-        String msg = null;
+        String msg;
         if (start != null) {
             long diff = now.getTime() - start.getTime();
-            msg = StringUtils.LINE_SEP + name + ": finished " + now + " ("
-                    + diff + "ms)";
+            msg = String.format("%n%s: finished %s (%d)", name, now, diff);
         } else {
-            msg = StringUtils.LINE_SEP + name + ": finished " + now
-                    + " (unknown duration, start not detected)";
+            msg = String.format("%n%s: finished %s (unknown duration, start not detected)",
+                    name, now);
         }
         printMessage(msg, out, event.getPriority());
         log(msg);
     }
 
     private void logStart(BuildEvent event, Date start, String name) {
-        String msg = StringUtils.LINE_SEP + name + ": started " + start;
+        String msg = String.format("%n%s: started %s", name, start);
         printMessage(msg, out, event.getPriority());
         log(msg);
     }
diff --git a/src/main/org/apache/tools/ant/listener/SilentLogger.java b/src/main/org/apache/tools/ant/listener/SilentLogger.java
index 6ddfd7f..6e9b227 100644
--- a/src/main/org/apache/tools/ant/listener/SilentLogger.java
+++ b/src/main/org/apache/tools/ant/listener/SilentLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/listener/SimpleBigProjectLogger.java b/src/main/org/apache/tools/ant/listener/SimpleBigProjectLogger.java
index 18f8dc6..b29cd63 100644
--- a/src/main/org/apache/tools/ant/listener/SimpleBigProjectLogger.java
+++ b/src/main/org/apache/tools/ant/listener/SimpleBigProjectLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,14 +33,14 @@
      * @param event the event to work on
      * @return the target name -including the owning project name (if non-null)
      */
+    @Override
     protected String extractTargetName(BuildEvent event) {
         String targetName = super.extractTargetName(event);
         String projectName = extractProjectName(event);
-        if (projectName != null && targetName != null) {
-            return projectName + '.' + targetName;
-        } else {
+        if (projectName == null || targetName == null) {
             return targetName;
         }
+        return projectName + '.' + targetName;
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/listener/TimestampedLogger.java b/src/main/org/apache/tools/ant/listener/TimestampedLogger.java
index 91296e3..0488b45 100644
--- a/src/main/org/apache/tools/ant/listener/TimestampedLogger.java
+++ b/src/main/org/apache/tools/ant/listener/TimestampedLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,13 +30,13 @@
      */
     public static final String SPACER = " - at ";
 
-
     /**
      * This is an override point: the message that indicates whether a build failed.
      * Subclasses can change/enhance the message.
      *
      * @return The classic "BUILD FAILED" plus a timestamp
      */
+    @Override
     protected String getBuildFailedMessage() {
         return super.getBuildFailedMessage() + SPACER + getTimestamp();
     }
@@ -47,6 +47,7 @@
      *
      * @return The classic "BUILD SUCCESSFUL" plus a timestamp
      */
+    @Override
     protected String getBuildSuccessfulMessage() {
         return super.getBuildSuccessfulMessage() + SPACER + getTimestamp();
     }
diff --git a/src/main/org/apache/tools/ant/listener/defaults.properties b/src/main/org/apache/tools/ant/listener/defaults.properties
index 2994382..11996d8 100644
--- a/src/main/org/apache/tools/ant/listener/defaults.properties
+++ b/src/main/org/apache/tools/ant/listener/defaults.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
diff --git a/src/main/org/apache/tools/ant/loader/AntClassLoader2.java b/src/main/org/apache/tools/ant/loader/AntClassLoader2.java
index 1a4cac6..33bbc62 100644
--- a/src/main/org/apache/tools/ant/loader/AntClassLoader2.java
+++ b/src/main/org/apache/tools/ant/loader/AntClassLoader2.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,6 +25,10 @@
  *             Just use {@link AntClassLoader} itself.
  */
 public class AntClassLoader2 extends AntClassLoader {
+    static {
+        registerAsParallelCapable();
+    }
+
     /** No args constructor. */
     public AntClassLoader2() {
     }
diff --git a/src/main/org/apache/tools/ant/loader/AntClassLoader5.java b/src/main/org/apache/tools/ant/loader/AntClassLoader5.java
index 15c29df..0cc8df7 100644
--- a/src/main/org/apache/tools/ant/loader/AntClassLoader5.java
+++ b/src/main/org/apache/tools/ant/loader/AntClassLoader5.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,6 +27,10 @@
  *             Just use {@link AntClassLoader} itself.
  */
 public class AntClassLoader5 extends AntClassLoader {
+    static {
+        registerAsParallelCapable();
+    }
+
     /**
      * Creates a classloader for the given project using the classpath given.
      *
diff --git a/src/main/org/apache/tools/ant/property/GetProperty.java b/src/main/org/apache/tools/ant/property/GetProperty.java
index c08808a..11ef213 100644
--- a/src/main/org/apache/tools/ant/property/GetProperty.java
+++ b/src/main/org/apache/tools/ant/property/GetProperty.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/property/LocalProperties.java b/src/main/org/apache/tools/ant/property/LocalProperties.java
index c9ce3af..327f978 100644
--- a/src/main/org/apache/tools/ant/property/LocalProperties.java
+++ b/src/main/org/apache/tools/ant/property/LocalProperties.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,8 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.PropertyHelper;
 
+import java.util.Set;
+
 /**
  * Thread local class containing local properties.
  * @since Ant 1.8.0
@@ -28,7 +30,7 @@
 public class LocalProperties
     extends InheritableThreadLocal<LocalPropertyStack>
     implements PropertyHelper.PropertyEvaluator,
-    PropertyHelper.PropertySetter {
+        PropertyHelper.PropertySetter, PropertyHelper.PropertyEnumerator {
 
     /**
      * Get a localproperties for the given project.
@@ -36,8 +38,8 @@
      * @return the localproperties.
      */
     public static synchronized LocalProperties get(Project project) {
-        LocalProperties l = (LocalProperties) project.getReference(
-            MagicNames.REFID_LOCAL_PROPERTIES);
+        LocalProperties l =
+            project.getReference(MagicNames.REFID_LOCAL_PROPERTIES);
         if (l == null) {
             l = new LocalProperties();
             project.addReference(MagicNames.REFID_LOCAL_PROPERTIES, l);
@@ -62,14 +64,11 @@
      * Get the initial value.
      * @return a new localproperties stack.
      */
+    @Override
     protected synchronized LocalPropertyStack initialValue() {
         return new LocalPropertyStack();
     }
 
-    private LocalPropertyStack current() {
-        return (LocalPropertyStack) get();
-    }
-
     // --------------------------------------------------
     //
     //  Local property adding and scoping
@@ -81,17 +80,17 @@
      * @param property the property name to add.
      */
     public void addLocal(String property) {
-        current().addLocal(property);
+        get().addLocal(property);
     }
 
     /** enter the scope */
     public void enterScope() {
-        current().enterScope();
+        get().enterScope();
     }
 
     /** exit the scope */
     public void exitScope() {
-        current().exitScope();
+        get().exitScope();
     }
 
     // --------------------------------------------------
@@ -105,7 +104,7 @@
      * To be called from the parallel thread itself.
      */
     public void copy() {
-        set(current().copy());
+        set(get().copy());
     }
 
     // --------------------------------------------------
@@ -120,8 +119,9 @@
      * @param helper the invoking PropertyHelper.
      * @return Object value.
      */
+    @Override
     public Object evaluate(String property, PropertyHelper helper) {
-        return current().evaluate(property, helper);
+        return get().evaluate(property, helper);
     }
 
     /**
@@ -131,9 +131,10 @@
      * @param propertyHelper the invoking PropertyHelper.
      * @return true if this entity 'owns' the property.
      */
+    @Override
     public boolean setNew(
         String property, Object value, PropertyHelper propertyHelper) {
-        return current().setNew(property, value, propertyHelper);
+        return get().setNew(property, value, propertyHelper);
     }
 
     /**
@@ -143,10 +144,14 @@
      * @param propertyHelper the invoking PropertyHelper.
      * @return true if this entity 'owns' the property.
      */
+    @Override
     public boolean set(
         String property, Object value, PropertyHelper propertyHelper) {
-        return current().set(property, value, propertyHelper);
+        return get().set(property, value, propertyHelper);
+    }
+
+    @Override
+    public Set<String> getPropertyNames() {
+        return get().getPropertyNames();
     }
 }
-
-
diff --git a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java
index 482f28c..3b63931 100644
--- a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java
+++ b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,9 +17,15 @@
  */
 package org.apache.tools.ant.property;
 
+import java.util.AbstractCollection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collector;
 
 import org.apache.tools.ant.PropertyHelper;
 
@@ -29,7 +35,7 @@
  * @since Ant 1.8.0
  */
 public class LocalPropertyStack {
-    private final LinkedList<Map<String, Object>> stack = new LinkedList<Map<String, Object>>();
+    private final Deque<Map<String, Object>> stack = new LinkedList<>();
     private final Object LOCK = new Object();
 
     // --------------------------------------------------
@@ -56,7 +62,7 @@
      */
     public void enterScope() {
         synchronized (LOCK) {
-            stack.addFirst(new ConcurrentHashMap<String, Object>());
+            stack.addFirst(new ConcurrentHashMap<>());
         }
     }
 
@@ -147,6 +153,20 @@
         return true;
     }
 
+    /**
+     * Returns the names of all known local properties.
+     * @since 1.10.9
+     * @return the names of all known local properties.
+     */
+    public Set<String> getPropertyNames() {
+        final Set<String> names = stack.stream().map(Map::keySet)
+            .collect(Collector.of(HashSet::new,
+                    AbstractCollection::addAll,
+                (ns1, ns2) -> { ns1.addAll(ns2); return ns1; },
+                Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH));
+        return Collections.unmodifiableSet(names);
+    }
+
     private Map<String, Object> getMapForProperty(String property) {
         synchronized (LOCK) {
             for (Map<String, Object> map : stack) {
diff --git a/src/main/org/apache/tools/ant/property/NullReturn.java b/src/main/org/apache/tools/ant/property/NullReturn.java
index 067aa9f..2232c13 100644
--- a/src/main/org/apache/tools/ant/property/NullReturn.java
+++ b/src/main/org/apache/tools/ant/property/NullReturn.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,6 +32,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public String toString() {
         return "null";
     }
diff --git a/src/main/org/apache/tools/ant/property/ParseNextProperty.java b/src/main/org/apache/tools/ant/property/ParseNextProperty.java
index 5e5dfc0..943099f 100644
--- a/src/main/org/apache/tools/ant/property/ParseNextProperty.java
+++ b/src/main/org/apache/tools/ant/property/ParseNextProperty.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/property/ParseProperties.java b/src/main/org/apache/tools/ant/property/ParseProperties.java
index f03f966..421937e 100644
--- a/src/main/org/apache/tools/ant/property/ParseProperties.java
+++ b/src/main/org/apache/tools/ant/property/ParseProperties.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 
 import java.text.ParsePosition;
 import java.util.Collection;
+import java.util.Objects;
 
 import org.apache.tools.ant.Project;
 
@@ -49,6 +50,7 @@
      * Get the project.
      * @return the current Ant project.
      */
+    @Override
     public Project getProject() {
         return project;
     }
@@ -90,7 +92,7 @@
      *         <code>null</code> if the original string is <code>null</code>.
      */
     public Object parseProperties(String value) {
-        if (value == null || "".equals(value)) {
+        if (value == null || value.isEmpty()) {
             return value;
         }
         final int len = value.length();
@@ -99,7 +101,7 @@
         if (o != null && pos.getIndex() >= len) {
             return o;
         }
-        StringBuffer sb = new StringBuffer(len * 2);
+        StringBuilder sb = new StringBuilder(len * 2);
         if (o == null) {
             sb.append(value.charAt(pos.getIndex()));
             pos.setIndex(pos.getIndex() + 1);
@@ -157,6 +159,7 @@
      * property doesn't expand to a value, the property's name is
      * returned.
      */
+    @Override
     public Object parseNextProperty(String value, ParsePosition pos) {
         final int start = pos.getIndex();
 
@@ -183,14 +186,9 @@
     }
 
     private String parsePropertyName(String value, ParsePosition pos) {
-        for (PropertyExpander propertyExpander : expanders) {
-            String propertyName = propertyExpander.parsePropertyName(value, pos, this);
-            if (propertyName == null) {
-                continue;
-            }
-            return propertyName;
-        }
-        return null;
+        return expanders.stream()
+            .map(xp -> xp.parsePropertyName(value, pos, this))
+            .filter(Objects::nonNull).findFirst().orElse(null);
     }
 
     private Object getProperty(String propertyName) {
diff --git a/src/main/org/apache/tools/ant/property/PropertyExpander.java b/src/main/org/apache/tools/ant/property/PropertyExpander.java
index a2b4d63..1cad474 100644
--- a/src/main/org/apache/tools/ant/property/PropertyExpander.java
+++ b/src/main/org/apache/tools/ant/property/PropertyExpander.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java b/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java
index 5bdd354..a65cbf8 100644
--- a/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java
+++ b/src/main/org/apache/tools/ant/property/ResolvePropertyMap.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,7 +30,7 @@
  * @since Ant 1.8.0
  */
 public class ResolvePropertyMap implements GetProperty {
-    private final Set<String> seen = new HashSet<String>();
+    private final Set<String> seen = new HashSet<>();
     private final ParseProperties parseProperties;
     private final GetProperty master;
     private Map<String, Object> map;
@@ -58,10 +58,11 @@
      * @param name name of the property.
      * @return the property value, or null for no match or for name being null.
      */
+    @Override
     public Object getProperty(String name) {
         if (seen.contains(name)) {
-            throw new BuildException(
-                "Property " + name + " was circularly " + "defined.");
+            throw new BuildException("Property %s was circularly defined.",
+                name);
         }
 
         try {
@@ -90,7 +91,7 @@
 
             String recursiveCallKey = name;
             if (prefix != null && !expandingLHS && !prefixValues) {
-                // only look up unprefixed properties inside the map
+                // only look up nonprefixed properties inside the map
                 // if prefixValues is true or we are expanding the key
                 // itself
                 recursiveCallKey = prefix + name;
@@ -110,6 +111,7 @@
      * @param map the map to resolve properties in.
      * @deprecated since Ant 1.8.2, use the three-arg method instead.
      */
+    @Deprecated
     public void resolveAllProperties(Map<String, Object> map) {
         resolveAllProperties(map, null, false);
     }
@@ -121,6 +123,7 @@
      * will finally receive - may be null.
      * @deprecated since Ant 1.8.2, use the three-arg method instead.
      */
+    @Deprecated
     public void resolveAllProperties(Map<String, Object> map, String prefix) {
         resolveAllProperties(map, null, false);
     }
diff --git a/src/main/org/apache/tools/ant/property/package.html b/src/main/org/apache/tools/ant/property/package.html
index 7a497ec..a0db80d 100644
--- a/src/main/org/apache/tools/ant/property/package.html
+++ b/src/main/org/apache/tools/ant/property/package.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,6 +15,11 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
+<html lang="en">
+<head>
+  <title>Helper classes for Ant properties</title>
+</head>
 <body>
-  Contains helper classes for ant properties.
+  Contains helper classes for Ant properties.
 </body>
+</html>
diff --git a/src/main/org/apache/tools/ant/taskdefs/AbstractCvsTask.java b/src/main/org/apache/tools/ant/taskdefs/AbstractCvsTask.java
index 59f91c8..4dc2a77 100644
--- a/src/main/org/apache/tools/ant/taskdefs/AbstractCvsTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/AbstractCvsTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,13 +20,15 @@
 
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -34,7 +36,6 @@
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.types.Environment;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * original Cvs.java 1.20
@@ -56,10 +57,10 @@
 
     private Commandline cmd = new Commandline();
 
-    private ArrayList<Module> modules = new ArrayList<Module>();
+    private List<Module> modules = new ArrayList<>();
 
     /** list of Commandline children */
-    private Vector<Commandline> vecCommandlines = new Vector<Commandline>();
+    private List<Commandline> commandlines = new Vector<>();
 
     /**
      * the CVSROOT variable.
@@ -155,11 +156,6 @@
     private OutputStream outputStream;
     private OutputStream errorStream;
 
-    /** empty no-arg constructor*/
-    public AbstractCvsTask() {
-        super();
-    }
-
     /**
      * sets the handler
      * @param handler a handler able of processing the output and error streams from the cvs exe
@@ -207,8 +203,7 @@
                 try {
                     setOutputStream(new PrintStream(
                                         new BufferedOutputStream(
-                                            new FileOutputStream(output
-                                                                 .getPath(),
+                                            FileUtils.newOutputStream(Paths.get(output.getPath()),
                                                                  append))));
                 } catch (IOException e) {
                     throw new BuildException(e, getLocation());
@@ -247,7 +242,7 @@
                 try {
                     setErrorStream(new PrintStream(
                                        new BufferedOutputStream(
-                                           new FileOutputStream(error.getPath(),
+                                           FileUtils.newOutputStream(Paths.get(error.getPath()),
                                                                 append))));
                 } catch (IOException e) {
                     throw new BuildException(e, getLocation());
@@ -311,14 +306,14 @@
                 var.setKey("CVS_PASSFILE");
                 var.setValue(String.valueOf(passFile));
                 env.addVariable(var);
-                log("Using cvs passfile: " + String.valueOf(passFile),
+                log("Using cvs passfile: " + passFile,
                     Project.MSG_VERBOSE);
             } else if (!passFile.canRead()) {
-                log("cvs passfile: " + String.valueOf(passFile)
+                log("cvs passfile: " + passFile
                     + " ignored as it is not readable",
                     Project.MSG_WARN);
             } else {
-                log("cvs passfile: " + String.valueOf(passFile)
+                log("cvs passfile: " + passFile
                     + " ignored as it is not a file",
                     Project.MSG_WARN);
             }
@@ -358,12 +353,9 @@
             log("retCode=" + retCode, Project.MSG_DEBUG);
 
             if (failOnError && Execute.isFailure(retCode)) {
-                throw new BuildException("cvs exited with error code "
-                                         + retCode
-                                         + StringUtils.LINE_SEP
-                                         + "Command line was ["
-                                         + actualCommandLine + "]",
-                                         getLocation());
+                throw new BuildException(
+                        String.format("cvs exited with error code %s%nCommand line was [%s]",
+                                retCode, actualCommandLine), getLocation());
             }
         } catch (IOException e) {
             if (failOnError) {
@@ -392,11 +384,12 @@
      * @throws BuildException if failonerror is set to true and the
      * cvs command fails.
      */
+    @Override
     public void execute() throws BuildException {
 
         String savedCommand = getCommand();
 
-        if (this.getCommand() == null && vecCommandlines.size() == 0) {
+        if (this.getCommand() == null && commandlines.isEmpty()) {
             // re-implement legacy behaviour:
             this.setCommand(AbstractCvsTask.DEFAULT_COMMAND);
         }
@@ -410,10 +403,7 @@
         }
 
         try {
-            final int size = vecCommandlines.size();
-            for (int i = 0; i < size; i++) {
-                this.runCommand((Commandline) vecCommandlines.elementAt(i));
-            }
+            commandlines.forEach(this::runCommand);
         } finally {
             if (cloned != null) {
                 removeCommandline(cloned);
@@ -428,24 +418,15 @@
 
         String cmdLine = Commandline.describeCommand(execute
                 .getCommandline());
-        StringBuffer stringBuffer = removeCvsPassword(cmdLine);
+        StringBuilder buf = removeCvsPassword(cmdLine);
 
-        String newLine = StringUtils.LINE_SEP;
         String[] variableArray = execute.getEnvironment();
-
         if (variableArray != null) {
-            stringBuffer.append(newLine);
-            stringBuffer.append(newLine);
-            stringBuffer.append("environment:");
-            stringBuffer.append(newLine);
-            for (String variable : variableArray) {
-                stringBuffer.append(newLine);
-                stringBuffer.append("\t");
-                stringBuffer.append(variable);
-            }
+            buf.append(Arrays.stream(variableArray).map(variable -> String.format("%n\t%s", variable))
+                    .collect(Collectors.joining("", String.format("%n%nenvironment:%n"), "")));
         }
 
-        return stringBuffer.toString();
+        return buf.toString();
     }
 
     /**
@@ -456,24 +437,23 @@
      * @param cmdLine the CVS command line
      * @return a StringBuffer where the password has been removed (if available)
      */
-    private StringBuffer removeCvsPassword(String cmdLine) {
-        StringBuffer stringBuffer = new StringBuffer(cmdLine);
+    private StringBuilder removeCvsPassword(String cmdLine) {
+        StringBuilder buf = new StringBuilder(cmdLine);
 
         int start = cmdLine.indexOf("-d:");
 
         if (start >= 0) {
-            int stop = cmdLine.indexOf("@", start);
-            int startproto = cmdLine.indexOf(":", start);
-            int startuser = cmdLine.indexOf(":", startproto + 1);
-            int startpass = cmdLine.indexOf(":", startuser + 1);
-            stop = cmdLine.indexOf("@", start);
+            int stop = cmdLine.indexOf('@', start);
+            int startproto = cmdLine.indexOf(':', start);
+            int startuser = cmdLine.indexOf(':', startproto + 1);
+            int startpass = cmdLine.indexOf(':', startuser + 1);
             if (stop >= 0 && startpass > startproto && startpass < stop) {
                 for (int i = startpass + 1; i < stop; i++) {
-                    stringBuffer.replace(i, i + 1, "*");
+                    buf.replace(i, i + 1, "*");
                 }
             }
         }
-        return stringBuffer;
+        return buf;
     }
 
     /**
@@ -485,10 +465,8 @@
     public void setCvsRoot(String root) {
 
         // Check if not real cvsroot => set it to null
-        if (root != null) {
-            if (root.trim().equals("")) {
-                root = null;
-            }
+        if (root != null && root.trim().isEmpty()) {
+            root = null;
         }
 
         this.cvsRoot = root;
@@ -509,11 +487,8 @@
      * @param rsh the CVS_RSH variable
      */
     public void setCvsRsh(String rsh) {
-        // Check if not real cvsrsh => set it to null
-        if (rsh != null) {
-            if (rsh.trim().equals("")) {
-                rsh = null;
-            }
+        if (rsh != null && rsh.trim().isEmpty()) {
+            rsh = null;
         }
 
         this.cvsRsh = rsh;
@@ -542,7 +517,6 @@
      * @return the port of CVS
      */
     public int getPort() {
-
         return this.port;
     }
 
@@ -560,7 +534,6 @@
      * @return password file
      */
     public File getPassFile() {
-
         return this.passFile;
     }
 
@@ -583,7 +556,6 @@
      * @return directory where the checked out files should be placed
      */
     public File getDest() {
-
         return this.dest;
     }
 
@@ -602,7 +574,6 @@
      * @return package/module
      */
     public String getPackage() {
-
         return this.cvsPackage;
     }
     /**
@@ -620,7 +591,7 @@
      */
     public void setTag(String p) {
         // Check if not real tag => set it to null
-        if (p != null && p.trim().length() > 0) {
+        if (p != null && !p.trim().isEmpty()) {
             tag = p;
             addCommandArgument("-r" + p);
         }
@@ -656,7 +627,7 @@
      * can understand see man cvs
      */
     public void setDate(String p) {
-        if (p != null && p.trim().length() > 0) {
+        if (p != null && !p.trim().isEmpty()) {
             addCommandArgument("-D");
             addCommandArgument(p);
         }
@@ -702,7 +673,6 @@
         reallyquiet = q;
     }
 
-
     /**
      * If true, report only and don't change any files.
      *
@@ -801,7 +771,7 @@
      * @param c command line which should be removed
      */
     protected void removeCommandline(Commandline c) {
-        vecCommandlines.removeElement(c);
+        commandlines.remove(c);
     }
 
     /**
@@ -825,9 +795,9 @@
         }
         this.configureCommandline(c);
         if (insertAtStart) {
-            vecCommandlines.insertElementAt(c, 0);
+            commandlines.add(0, c);
         } else {
-            vecCommandlines.addElement(c);
+            commandlines.add(c);
         }
     }
 
@@ -862,13 +832,12 @@
     }
 
     protected List<Module> getModules() {
-        @SuppressWarnings("unchecked")
-        final List<Module> clone = (List<Module>) modules.clone();
-        return clone;
+        return new ArrayList<>(modules);
     }
 
     public static final class Module {
         private String name;
+
         public void setName(String s) {
             name = s;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java b/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java
index e9e8f16..16d2712 100644
--- a/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/AbstractJarSignerTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,6 +40,17 @@
  */
 
 public abstract class AbstractJarSignerTask extends Task {
+    /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_NO_SOURCE =
+        "jar must be set through jar attribute or nested filesets";
+
+    /**
+     * name of JDK program we are looking for
+     */
+    protected static final String JARSIGNER_COMMAND = "jarsigner";
+
     // CheckStyle:VisibilityModifier OFF - bc
     /**
      * The name of the jar file.
@@ -81,12 +92,7 @@
     /**
      * the filesets of the jars to sign
      */
-    protected Vector<FileSet> filesets = new Vector<FileSet>();
-    /**
-     * name of JDK program we are looking for
-     */
-    protected static final String JARSIGNER_COMMAND = "jarsigner";
-
+    protected Vector<FileSet> filesets = new Vector<>();
     // CheckStyle:VisibilityModifier ON
 
     /**
@@ -100,12 +106,6 @@
     private Environment sysProperties = new Environment();
 
     /**
-     * error string for unit test verification: {@value}
-     */
-    public static final String ERROR_NO_SOURCE = "jar must be set through jar attribute "
-            + "or nested filesets";
-
-    /**
      * Path holding all non-filesets of filesystem resources we want to sign.
      *
      * @since Ant 1.7
@@ -122,11 +122,11 @@
     /**
      * Values for the providerName, providerClass, and providerArg options.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     private String providerName, providerClass, providerArg;
 
-    private List<Commandline.Argument> additionalArgs = new ArrayList<Commandline.Argument>();
+    private List<Commandline.Argument> additionalArgs = new ArrayList<>();
 
     /**
      * Set the maximum memory to be used by the jarsigner process
@@ -247,7 +247,7 @@
      *
      * @param providerName the value for the -providerName command line argument
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setProviderName(String providerName) {
         this.providerName = providerName;
@@ -258,7 +258,7 @@
      *
      * @param providerClass the value for the -providerClass command line argument
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setProviderClass(String providerClass) {
         this.providerClass = providerClass;
@@ -269,7 +269,7 @@
      *
      * @param providerArg the value for the -providerArg command line argument
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setProviderArg(String providerArg) {
         this.providerArg = providerArg;
@@ -281,7 +281,7 @@
      *
      * @param arg the argument to add
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void addArg(Commandline.Argument arg) {
         additionalArgs.add(arg);
@@ -310,7 +310,7 @@
     private RedirectorElement createRedirector() {
         RedirectorElement result = new RedirectorElement();
         if (storepass != null) {
-            StringBuffer input = new StringBuffer(storepass).append('\n');
+            StringBuilder input = new StringBuilder(storepass).append('\n');
             if (keypass != null) {
                 input.append(keypass).append('\n');
             }
@@ -385,7 +385,6 @@
         addValue(cmd, "-J-D" + property.getContent());
     }
 
-
     /**
      * bind to a keystore if the attributes are there
      * @param cmd command to configure
@@ -448,8 +447,7 @@
      * @return a vector of FileSet instances
      */
     protected Vector<FileSet> createUnifiedSources() {
-        @SuppressWarnings("unchecked")
-        Vector<FileSet> sources = (Vector<FileSet>) filesets.clone();
+        Vector<FileSet> sources = new Vector<>(filesets);
         if (jar != null) {
             //we create a fileset with the source file.
             //this lets us combine our logic for handling output directories,
@@ -483,7 +481,7 @@
      * @since Ant 1.7
      */
     protected boolean hasResources() {
-        return path != null || filesets.size() > 0;
+        return !(path == null && filesets.isEmpty());
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java
index 78d0689..2472ea5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Ant.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,19 +19,19 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.lang.reflect.Method;
-import java.util.Enumeration;
+import java.nio.file.Files;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.BuildListener;
 import org.apache.tools.ant.DefaultLogger;
 import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Main;
@@ -88,10 +88,10 @@
     private boolean inheritRefs = false;
 
     /** the properties to pass to the new project */
-    private Vector<Property> properties = new Vector<Property>();
+    private List<Property> properties = new Vector<>();
 
     /** the references to pass to the new project */
-    private Vector<Reference> references = new Vector<Reference>();
+    private List<Reference> references = new Vector<>();
 
     /** the temporary project created to run the build file */
     private Project newProject;
@@ -100,10 +100,10 @@
     private PrintStream out = null;
 
     /** the sets of properties to pass to the new project */
-    private Vector<PropertySet> propertySets = new Vector<PropertySet>();
+    private List<PropertySet> propertySets = new Vector<>();
 
     /** the targets to call on the new project */
-    private Vector<String> targets = new Vector<String>();
+    private List<String> targets = new Vector<>();
 
     /** whether the target attribute was specified **/
     private boolean targetAttributeSet = false;
@@ -165,6 +165,7 @@
     /**
      * Creates a Project instance for the project to call.
      */
+    @Override
     public void init() {
         newProject = getProject().createSubProject();
         newProject.setJavaVersionProperty();
@@ -194,20 +195,17 @@
     private void initializeProject() {
         newProject.setInputHandler(getProject().getInputHandler());
 
-        Iterator<BuildListener> iter = getBuildListeners();
-        while (iter.hasNext()) {
-            newProject.addBuildListener((BuildListener) iter.next());
-        }
+        getProject().getBuildListeners().forEach(bl -> newProject.addBuildListener(bl));
 
         if (output != null) {
-            File outfile = null;
+            File outfile;
             if (dir != null) {
                 outfile = FILE_UTILS.resolveFile(dir, output);
             } else {
                 outfile = getProject().resolveFile(output);
             }
             try {
-                out = new PrintStream(new FileOutputStream(outfile));
+                out = new PrintStream(Files.newOutputStream(outfile.toPath()));
                 DefaultLogger logger = new DefaultLogger();
                 logger.setMessageOutputLevel(Project.MSG_INFO);
                 logger.setOutputPrintStream(out);
@@ -247,6 +245,7 @@
      * @see Task#handleOutput(String)
      * @since Ant 1.5
      */
+    @Override
     public void handleOutput(String outputToHandle) {
         if (newProject != null) {
             newProject.demuxOutput(outputToHandle, false);
@@ -269,6 +268,7 @@
      * @see Task#handleInput(byte[], int, int)
      * @since Ant 1.6
      */
+    @Override
     public int handleInput(byte[] buffer, int offset, int length)
         throws IOException {
         if (newProject != null) {
@@ -285,6 +285,7 @@
      * @see Task#handleFlush(String)
      * @since Ant 1.5.2
      */
+    @Override
     public void handleFlush(String toFlush) {
         if (newProject != null) {
             newProject.demuxFlush(toFlush, false);
@@ -302,6 +303,7 @@
      * @see Task#handleErrorOutput(String)
      * @since Ant 1.5
      */
+    @Override
     public void handleErrorOutput(String errorOutputToHandle) {
         if (newProject != null) {
             newProject.demuxOutput(errorOutputToHandle, true);
@@ -318,6 +320,7 @@
      * @see Task#handleErrorFlush(String)
      * @since Ant 1.5.2
      */
+    @Override
     public void handleErrorFlush(String errorOutputToFlush) {
         if (newProject != null) {
             newProject.demuxFlush(errorOutputToFlush, true);
@@ -331,10 +334,11 @@
      * @throws BuildException if a target tries to call itself;
      * probably also if a BuildException is thrown by the new project.
      */
+    @Override
     public void execute() throws BuildException {
         File savedDir = dir;
         String savedAntFile = antFile;
-        Vector<String> locals = new VectorSet<String>(targets);
+        Vector<String> locals = new VectorSet<>(targets);
         try {
             getNewProject();
 
@@ -367,26 +371,22 @@
             antFile = file.getAbsolutePath();
 
             log("calling target(s) "
-                + ((locals.size() > 0) ? locals.toString() : "[default]")
+                + (locals.isEmpty() ? "[default]" : locals.toString())
                 + " in build file " + antFile, Project.MSG_VERBOSE);
             newProject.setUserProperty(MagicNames.ANT_FILE, antFile);
 
             String thisAntFile = getProject().getProperty(MagicNames.ANT_FILE);
             // Are we trying to call the target in which we are defined (or
             // the build file if this is a top level task)?
-            if (thisAntFile != null
-                && file.equals(getProject().resolveFile(thisAntFile))
-                && getOwningTarget() != null) {
-
-                if (getOwningTarget().getName().equals("")) {
-                    if (getTaskName().equals("antcall")) {
-                        throw new BuildException("antcall must not be used at"
-                                                 + " the top level.");
-                    }
-                    throw new BuildException(getTaskName() + " task at the"
-                                + " top level must not invoke"
-                                + " its own build file.");
+            if (thisAntFile != null && file.equals(getProject().resolveFile(thisAntFile))
+                    && getOwningTarget() != null && getOwningTarget().getName().isEmpty()) {
+                if ("antcall".equals(getTaskName())) {
+                    throw new BuildException(
+                            "antcall must not be used at the top level.");
                 }
+                throw new BuildException(
+                        "%s task at the top level must not invoke its own build file.",
+                        getTaskName());
             }
 
             try {
@@ -396,7 +396,7 @@
                     ex, getLocation());
             }
 
-            if (locals.size() == 0) {
+            if (locals.isEmpty()) {
                 String defaultTarget = newProject.getDefaultTarget();
                 if (defaultTarget != null) {
                     locals.add(defaultTarget);
@@ -410,31 +410,26 @@
                 String owningTargetName = getOwningTarget().getName();
 
                 if (locals.contains(owningTargetName)) {
-                    throw new BuildException(getTaskName() + " task calling "
-                                             + "its own parent target.");
+                    throw new BuildException(
+                        "%s task calling its own parent target.",
+                        getTaskName());
                 }
-                boolean circular = false;
-                for (Iterator<String> it = locals.iterator();
-                     !circular && it.hasNext();) {
-                    Target other =
-                        getProject().getTargets().get(it.next());
-                    circular |= (other != null
-                                 && other.dependsOn(owningTargetName));
-                }
-                if (circular) {
-                    throw new BuildException(getTaskName()
-                                             + " task calling a target"
-                                             + " that depends on"
-                                             + " its parent target \'"
-                                             + owningTargetName
-                                             + "\'.");
+
+                final Map<String, Target> targetsMap = getProject().getTargets();
+
+                if (locals.stream().map(targetsMap::get)
+                    .filter(Objects::nonNull)
+                    .anyMatch(other -> other.dependsOn(owningTargetName))) {
+                    throw new BuildException(
+                        "%s task calling a target that depends on its parent target '%s'.",
+                        getTaskName(), owningTargetName);
                 }
             }
 
             addReferences();
 
-            if (locals.size() > 0 && !(locals.size() == 1
-                                       && "".equals(locals.get(0)))) {
+            if (!locals.isEmpty() && !(locals.size() == 1
+                    && locals.get(0) != null && locals.get(0).isEmpty())) {
                 BuildException be = null;
                 try {
                     log("Entering " + antFile + "...", Project.MSG_VERBOSE);
@@ -467,8 +462,8 @@
     /**
      * Get the default build file name to use when launching the task.
      * <p>
-     * This function may be overriden by providers of custom ProjectHelper so they can implement easily their sub
-     * launcher.
+     * This function may be overridden by providers of custom ProjectHelper so they can easily
+     * implement their sublauncher.
      *
      * @return the name of the default file
      * @since Ant 1.8.0
@@ -485,10 +480,10 @@
     private void overrideProperties() throws BuildException {
         // remove duplicate properties - last property wins
         // Needed for backward compatibility
-        Set<String> set = new HashSet<String>();
+        Set<String> set = new HashSet<>();
         for (int i = properties.size() - 1; i >= 0; --i) {
             Property p = properties.get(i);
-            if (p.getName() != null && !p.getName().equals("")) {
+            if (p.getName() != null && !p.getName().isEmpty()) {
                 if (set.contains(p.getName())) {
                     properties.remove(i);
                 } else {
@@ -496,12 +491,9 @@
                 }
             }
         }
-        Enumeration<Property> e = properties.elements();
-        while (e.hasMoreElements()) {
-            Property p = e.nextElement();
-            p.setProject(newProject);
-            p.execute();
-        }
+        properties.stream().peek(p -> p.setProject(newProject))
+            .forEach(Property::execute);
+
         if (useNativeBasedir) {
             addAlmostAll(getProject().getInheritedProperties(),
                          PropertyType.INHERITED);
@@ -518,14 +510,13 @@
      * @throws BuildException if a reference does not have a refid.
      */
     private void addReferences() throws BuildException {
-        @SuppressWarnings("unchecked")
-        Hashtable<String, Object> thisReferences
-            = (Hashtable<String, Object>) getProject().getReferences().clone();
+        Map<String, Object> thisReferences =
+            new HashMap<>(getProject().getReferences());
         for (Reference ref : references) {
             String refid = ref.getRefId();
             if (refid == null) {
-                throw new BuildException("the refid attribute is required"
-                                         + " for reference elements");
+                throw new BuildException(
+                    "the refid attribute is required for reference elements");
             }
             if (!thisReferences.containsKey(refid)) {
                 log("Parent project doesn't contain any reference '"
@@ -545,7 +536,7 @@
         // Now add all references that are not defined in the
         // subproject, if inheritRefs is true
         if (inheritRefs) {
-            Hashtable<String, Object> newReferences = newProject.getReferences();
+            Map<String, Object> newReferences = newProject.getReferences();
             for (String key : thisReferences.keySet()) {
                 if (newReferences.containsKey(key)) {
                     continue;
@@ -577,32 +568,32 @@
         Class<?> c = orig.getClass();
         Object copy = orig;
         try {
-            Method cloneM = c.getMethod("clone", new Class[0]);
+            Method cloneM = c.getMethod("clone");
             if (cloneM != null) {
-                copy = cloneM.invoke(orig, new Object[0]);
+                copy = cloneM.invoke(orig);
                 log("Adding clone of reference " + oldKey, Project.MSG_DEBUG);
             }
         } catch (Exception e) {
             // not Clonable
         }
 
-
         if (copy instanceof ProjectComponent) {
             ((ProjectComponent) copy).setProject(newProject);
         } else {
             try {
                 Method setProjectM =
-                    c.getMethod("setProject", new Class[] {Project.class});
+                    c.getMethod("setProject", Project.class);
                 if (setProjectM != null) {
-                    setProjectM.invoke(copy, new Object[] {newProject});
+                    setProjectM.invoke(copy, newProject);
                 }
             } catch (NoSuchMethodException e) {
                 // ignore this if the class being referenced does not have
                 // a set project method.
             } catch (Exception e2) {
-                String msg = "Error setting new project instance for "
-                    + "reference with id " + oldKey;
-                throw new BuildException(msg, e2, getLocation());
+                throw new BuildException(
+                    "Error setting new project instance for "
+                        + "reference with id " + oldKey,
+                    e2, getLocation());
             }
         }
         newProject.addReference(newKey, copy);
@@ -618,29 +609,31 @@
      * user property or an inherited property).
      * @since Ant 1.8.0
      */
-    private void addAlmostAll(Hashtable<?, ?> props, PropertyType type) {
-        Enumeration<?> e = props.keys();
-        while (e.hasMoreElements()) {
-            String key = e.nextElement().toString();
+    private void addAlmostAll(Map<?, ?> props, PropertyType type) {
+        props.forEach((k, v) -> {
+            String key = k.toString();
             if (MagicNames.PROJECT_BASEDIR.equals(key)
-                || MagicNames.ANT_FILE.equals(key)) {
+                    || MagicNames.ANT_FILE.equals(key)) {
                 // basedir and ant.file get special treatment in execute()
-                continue;
+                return;
             }
-
-            String value = props.get(key).toString();
-            if (type == PropertyType.PLAIN) {
+            String value = v.toString();
+            switch (type) {
+            case PLAIN:
                 // don't re-set user properties, avoid the warning message
                 if (newProject.getProperty(key) == null) {
                     // no user property
                     newProject.setNewProperty(key, value);
                 }
-            } else if (type == PropertyType.USER) {
+                break;
+            case USER:
                 newProject.setUserProperty(key, value);
-            } else if (type == PropertyType.INHERITED) {
+                break;
+            case INHERITED:
                 newProject.setInheritedProperty(key, value);
+                break;
             }
-        }
+        });
     }
 
     /**
@@ -672,7 +665,7 @@
      * @param targetToAdd the name of the target to invoke.
      */
     public void setTarget(String targetToAdd) {
-        if (targetToAdd.equals("")) {
+        if (targetToAdd.isEmpty()) {
             throw new BuildException("target attribute must not be empty");
         }
         targets.add(targetToAdd);
@@ -698,7 +691,7 @@
         Property p = new Property(true, getProject());
         p.setProject(getNewProject());
         p.setTaskName("property");
-        properties.addElement(p);
+        properties.add(p);
         return p;
     }
 
@@ -708,7 +701,7 @@
      * @param ref <code>Reference</code> to add.
      */
     public void addReference(Reference ref) {
-        references.addElement(ref);
+        references.add(ref);
     }
 
     /**
@@ -722,7 +715,7 @@
                 "nested target is incompatible with the target attribute");
         }
         String name = t.getName();
-        if (name.equals("")) {
+        if (name.isEmpty()) {
             throw new BuildException("target name must not be empty");
         }
         targets.add(name);
@@ -735,7 +728,7 @@
      * @since Ant 1.6
      */
     public void addPropertyset(PropertySet ps) {
-        propertySets.addElement(ps);
+        propertySets.add(ps);
     }
 
     /**
@@ -751,24 +744,13 @@
     }
 
     /**
-     * @since Ant 1.6.2
-     */
-    private Iterator<BuildListener> getBuildListeners() {
-        return getProject().getBuildListeners().iterator();
-    }
-
-    /**
      * Helper class that implements the nested &lt;reference&gt;
      * element of &lt;ant&gt; and &lt;antcall&gt;.
      */
+    @SuppressWarnings("deprecation")
     public static class Reference
         extends org.apache.tools.ant.types.Reference {
 
-        /** Creates a reference to be configured by Ant. */
-        public Reference() {
-            super();
-        }
-
         private String targetid = null;
 
         /**
@@ -824,10 +806,7 @@
         }
     }
 
-    private static final class PropertyType {
-        private PropertyType() {}
-        private static final PropertyType PLAIN = new PropertyType();
-        private static final PropertyType INHERITED = new PropertyType();
-        private static final PropertyType USER = new PropertyType();
+    private enum PropertyType {
+        PLAIN, INHERITED, USER
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/AntStructure.java b/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
index 331c1a9..5978ee0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
+++ b/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,15 +19,20 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.Enumeration;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Hashtable;
-import java.util.Vector;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.IntrospectionHelper;
@@ -36,7 +41,6 @@
 import org.apache.tools.ant.TaskContainer;
 import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.types.Reference;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Creates a partial DTD for Ant from the currently known tasks.
@@ -48,9 +52,6 @@
  */
 public class AntStructure extends Task {
 
-    private static final String LINE_SEP
-        = System.getProperty("line.separator");
-
     private File output;
     private StructurePrinter printer = new DTDPrinter();
 
@@ -83,54 +84,33 @@
             throw new BuildException("output attribute is required", getLocation());
         }
 
-        PrintWriter out = null;
-        try {
-            FileOutputStream fos = null;
-            try {
-                fos = new FileOutputStream(output);
-                out = new PrintWriter(new OutputStreamWriter(fos, "UTF8"));
-            } catch (final UnsupportedEncodingException ue) {
-                FileUtils.close(fos);
-                /*
-                 * Plain impossible with UTF8, see
-                 * http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html
-                 *
-                 * fallback to platform specific anyway.
-                 */
-                out = new PrintWriter(new FileWriter(output));
-            }
+        try (PrintWriter out = new PrintWriter(new OutputStreamWriter(
+                Files.newOutputStream(output.toPath()), StandardCharsets.UTF_8))) {
 
             printer.printHead(out, getProject(),
-                              new Hashtable<String, Class<?>>(getProject().getTaskDefinitions()),
-                              new Hashtable<String, Class<?>>(getProject().getDataTypeDefinitions()));
+                    new Hashtable<>(getProject().getTaskDefinitions()),
+                    new Hashtable<>(getProject().getDataTypeDefinitions()));
 
             printer.printTargetDecl(out);
 
-            for (final String typeName : getProject().getCopyOfDataTypeDefinitions()
-                .keySet()) {
-                printer.printElementDecl(
-                                     out, getProject(), typeName,
-                                     getProject().getDataTypeDefinitions().get(typeName));
+            for (final String typeName : getProject().getCopyOfDataTypeDefinitions().keySet()) {
+                printer.printElementDecl(out, getProject(), typeName,
+                        getProject().getDataTypeDefinitions().get(typeName));
             }
 
             for (final String tName : getProject().getCopyOfTaskDefinitions().keySet()) {
                 printer.printElementDecl(out, getProject(), tName,
-                                         getProject().getTaskDefinitions().get(tName));
+                        getProject().getTaskDefinitions().get(tName));
             }
 
             printer.printTail(out);
 
             if (out.checkError()) {
-                throw new IOException("Encountered an error writing Ant"
-                                      + " structure");
+                throw new IOException("Encountered an error writing Ant structure");
             }
         } catch (final IOException ioe) {
             throw new BuildException("Error writing "
-                                     + output.getAbsolutePath(), ioe, getLocation());
-        } finally {
-            if (out != null) {
-                out.close();
-            }
+                    + output.getAbsolutePath(), ioe, getLocation());
         }
     }
 
@@ -184,15 +164,17 @@
         private static final String TASKS = "%tasks;";
         private static final String TYPES = "%types;";
 
-        private final Hashtable<String, String> visited = new Hashtable<String, String>();
+        private final Hashtable<String, String> visited = new Hashtable<>();
 
+        @Override
         public void printTail(final PrintWriter out) {
             visited.clear();
         }
 
+        @Override
         public void printHead(final PrintWriter out, final Project p, final Hashtable<String, Class<?>> tasks,
                               final Hashtable<String, Class<?>> types) {
-            printHead(out, tasks.keys(), types.keys());
+            printHead(out, tasks.keySet(), types.keySet());
         }
 
 
@@ -202,36 +184,18 @@
          * <p>Basically this prints the XML declaration, defines some
          * entities and the project element.</p>
          */
-        private void printHead(final PrintWriter out, final Enumeration<String> tasks,
-                               final Enumeration<String> types) {
+        private void printHead(final PrintWriter out, final Set<String> tasks,
+                               final Set<String> types) {
             out.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
             out.println("<!ENTITY % boolean \"(true|false|on|off|yes|no)\">");
-            out.print("<!ENTITY % tasks \"");
-            boolean first = true;
-            while (tasks.hasMoreElements()) {
-                final String tName = tasks.nextElement();
-                if (!first) {
-                    out.print(" | ");
-                } else {
-                    first = false;
-                }
-                out.print(tName);
-            }
-            out.println("\">");
-            out.print("<!ENTITY % types \"");
-            first = true;
-            while (types.hasMoreElements()) {
-                final String typeName = types.nextElement();
-                if (!first) {
-                    out.print(" | ");
-                } else {
-                    first = false;
-                }
-                out.print(typeName);
-            }
-            out.println("\">");
 
-            out.println("");
+            out.println(tasks.stream().collect(
+                Collectors.joining(" | ", "<!ENTITY % tasks \"", "\">")));
+
+            out.println(types.stream().collect(
+                Collectors.joining(" | ", "<!ENTITY % types \"", "\">")));
+
+            out.println();
 
             out.print("<!ELEMENT project (target | extension-point | ");
             out.print(TASKS);
@@ -248,6 +212,7 @@
         /**
          * Prints the definition for the target element.
          */
+        @Override
         public void printTargetDecl(final PrintWriter out) {
             out.print("<!ELEMENT target (");
             out.print(TASKS);
@@ -281,6 +246,7 @@
         /**
          * Print the definition for a given element.
          */
+        @Override
         public void printElementDecl(final PrintWriter out, final Project p,
                                      final String name, final Class<?> element) {
 
@@ -289,7 +255,7 @@
             }
             visited.put(name, "");
 
-            IntrospectionHelper ih = null;
+            IntrospectionHelper ih;
             try {
                 ih = IntrospectionHelper.getHelper(p, element);
             } catch (final Throwable t) {
@@ -301,111 +267,79 @@
                 return;
             }
 
-            StringBuffer sb = new StringBuffer("<!ELEMENT ");
-            sb.append(name).append(" ");
+            StringBuilder sb = new StringBuilder("<!ELEMENT ").append(name).append(" ");
 
-            if (org.apache.tools.ant.types.Reference.class.equals(element)) {
-                sb.append("EMPTY>").append(LINE_SEP);
-                sb.append("<!ATTLIST ").append(name);
-                sb.append(LINE_SEP).append("          id ID #IMPLIED");
-                sb.append(LINE_SEP).append("          refid IDREF #IMPLIED");
-                sb.append(">").append(LINE_SEP);
+            if (Reference.class.equals(element)) {
+                sb.append(String.format("EMPTY>%n<!ATTLIST %s%n"
+                                + "          id ID #IMPLIED%n          refid IDREF #IMPLIED>%n",
+                        name));
                 out.println(sb);
                 return;
             }
 
-            final Vector<String> v = new Vector<String>();
+            final List<String> v = new ArrayList<>();
             if (ih.supportsCharacters()) {
-                v.addElement("#PCDATA");
+                v.add("#PCDATA");
             }
 
             if (TaskContainer.class.isAssignableFrom(element)) {
-                v.addElement(TASKS);
+                v.add(TASKS);
             }
 
-            Enumeration<String> e = ih.getNestedElements();
-            while (e.hasMoreElements()) {
-                v.addElement(e.nextElement());
-            }
+            v.addAll(Collections.list(ih.getNestedElements()));
+
+            final Collector<CharSequence, ?, String> joinAlts =
+                Collectors.joining(" | ", "(", ")");
 
             if (v.isEmpty()) {
                 sb.append("EMPTY");
             } else {
-                sb.append("(");
-                final int count = v.size();
-                for (int i = 0; i < count; i++) {
-                    if (i != 0) {
-                        sb.append(" | ");
-                    }
-                    sb.append(v.elementAt(i));
-                }
-                sb.append(")");
-                if (count > 1 || !v.elementAt(0).equals("#PCDATA")) {
+                sb.append(v.stream().collect(joinAlts));
+                if (v.size() > 1 || !"#PCDATA".equals(v.get(0))) {
                     sb.append("*");
                 }
             }
             sb.append(">");
             out.println(sb);
 
-            sb = new StringBuffer("<!ATTLIST ");
-            sb.append(name);
-            sb.append(LINE_SEP).append("          id ID #IMPLIED");
+            sb = new StringBuilder();
+            sb.append(String.format("<!ATTLIST %s%n          id ID #IMPLIED", name));
 
-            e = ih.getAttributes();
-            while (e.hasMoreElements()) {
-                final String attrName = e.nextElement();
+            for (final String attrName : Collections.list(ih.getAttributes())) {
                 if ("id".equals(attrName)) {
                     continue;
                 }
 
-                sb.append(LINE_SEP).append("          ")
-                    .append(attrName).append(" ");
+                sb.append(String.format("%n          %s ", attrName));
                 final Class<?> type = ih.getAttributeType(attrName);
-                if (type.equals(java.lang.Boolean.class)
-                    || type.equals(java.lang.Boolean.TYPE)) {
+                if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
                     sb.append(BOOLEAN).append(" ");
                 } else if (Reference.class.isAssignableFrom(type)) {
                     sb.append("IDREF ");
                 } else if (EnumeratedAttribute.class.isAssignableFrom(type)) {
                     try {
                         final EnumeratedAttribute ea =
-                            (EnumeratedAttribute) type.newInstance();
+                            type.asSubclass(EnumeratedAttribute.class).getDeclaredConstructor().newInstance();
                         final String[] values = ea.getValues();
-                        if (values == null
-                            || values.length == 0
+                        if (values == null || values.length == 0
                             || !areNmtokens(values)) {
                             sb.append("CDATA ");
                         } else {
-                            sb.append("(");
-                            for (int i = 0; i < values.length; i++) {
-                                if (i != 0) {
-                                    sb.append(" | ");
-                                }
-                                sb.append(values[i]);
-                            }
-                            sb.append(") ");
+                            sb.append(Stream.of(values).collect(joinAlts)).append(" ");
                         }
-                    } catch (final InstantiationException ie) {
-                        sb.append("CDATA ");
-                    } catch (final IllegalAccessException ie) {
+                    } catch (final InstantiationException | IllegalAccessException
+                            | NoSuchMethodException | InvocationTargetException ie) {
                         sb.append("CDATA ");
                     }
                 } else if (Enum.class.isAssignableFrom(type)) {
                     try {
-                        final Object[] values = (Object[]) type.getMethod("values", (Class[])  null)
-                            .invoke(null, (Object[]) null);
+                        final Enum<?>[] values =
+                            (Enum<?>[]) type.getMethod("values").invoke(null);
                         if (values.length == 0) {
                             sb.append("CDATA ");
                         } else {
-                            sb.append('(');
-                            for (int i = 0; i < values.length; i++) {
-                                if (i != 0) {
-                                    sb.append(" | ");
-                                }
-                                sb.append(type.getMethod("name", (Class[]) null)
-                                          .invoke(values[i], (Object[]) null));
-                            }
-                            sb.append(") ");
+                            sb.append(Stream.of(values).map(Enum::name)
+                                .collect(joinAlts)).append(" ");
                         }
                     } catch (final Exception x) {
                         sb.append("CDATA ");
@@ -415,12 +349,10 @@
                 }
                 sb.append("#IMPLIED");
             }
-            sb.append(">").append(LINE_SEP);
+            sb.append(String.format(">%n"));
             out.println(sb);
 
-            final int count = v.size();
-            for (int i = 0; i < count; i++) {
-                final String nestedName = v.elementAt(i);
+            for (String nestedName : v) {
                 if (!"#PCDATA".equals(nestedName)
                     && !TASKS.equals(nestedName)
                     && !TYPES.equals(nestedName)) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/Antlib.java b/src/main/org/apache/tools/ant/taskdefs/Antlib.java
index 8ff836a..b7ac88c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Antlib.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Antlib.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,11 +22,11 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.ComponentHelper;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.ProjectHelperRepository;
@@ -79,7 +79,7 @@
             // Should be safe to parse
             ProjectHelper parser = null;
             Object p =
-                project.getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+                project.getReference(MagicNames.REFID_PROJECT_HELPER);
             if (p instanceof ProjectHelper) {
                 parser = (ProjectHelper) p;
                 if (!parser.canParseAntlibDescriptor(antlibResource)) {
@@ -94,7 +94,7 @@
             UnknownElement ue =
                 parser.parseAntlibDescriptor(project, antlibResource);
             // Check name is "antlib"
-            if (!(ue.getTag().equals(TAG))) {
+            if (!TAG.equals(ue.getTag())) {
                 throw new BuildException(
                     "Unexpected tag " + ue.getTag() + " expecting "
                     + TAG, ue.getLocation());
@@ -116,7 +116,7 @@
     //
     private ClassLoader classLoader;
     private String uri = "";
-    private List<Object> tasks = new ArrayList<Object>();
+    private List<Task> tasks = new ArrayList<>();
 
     /**
      * Set the class loader for this antlib.
@@ -149,6 +149,7 @@
      *
      * @param nestedTask Nested task to execute in antlib
      */
+    @Override
     public void addTask(Task nestedTask) {
         tasks.add(nestedTask);
     }
@@ -157,10 +158,12 @@
      * Execute the nested tasks, setting the classloader for
      * any tasks that derive from Definer.
      */
+    @Override
     public void execute() {
         //TODO handle tasks added via #addTask()
-        for (Iterator<Object> i = tasks.iterator(); i.hasNext();) {
-            UnknownElement ue = (UnknownElement) i.next();
+
+        for (Task task : tasks) {
+            UnknownElement ue = (UnknownElement) task;
             setLocation(ue.getLocation());
             ue.maybeConfigure();
             Object configuredObject = ue.getRealThing();
@@ -169,9 +172,9 @@
             }
             if (!(configuredObject instanceof AntlibDefinition)) {
                 throw new BuildException(
-                    "Invalid task in antlib " + ue.getTag()
-                    + " " + configuredObject.getClass() + " does not "
-                    + "extend org.apache.tools.ant.taskdefs.AntlibDefinition");
+                    "Invalid task in antlib %s %s does not extend %s",
+                    ue.getTag(), configuredObject.getClass(),
+                    AntlibDefinition.class.getName());
             }
             AntlibDefinition def = (AntlibDefinition) configuredObject;
             def.setURI(uri);
diff --git a/src/main/org/apache/tools/ant/taskdefs/AntlibDefinition.java b/src/main/org/apache/tools/ant/taskdefs/AntlibDefinition.java
index eef3334..ed39cb4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/AntlibDefinition.java
+++ b/src/main/org/apache/tools/ant/taskdefs/AntlibDefinition.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,11 +44,11 @@
      * @throws BuildException if a reserved URI is used
      */
     public void setURI(String uri) throws BuildException {
-        if (uri.equals(ProjectHelper.ANT_CORE_URI)) {
+        if (ProjectHelper.ANT_CORE_URI.equals(uri)) {
             uri = "";
         }
         if (uri.startsWith("ant:")) {
-            throw new BuildException("Attempt to use a reserved URI " + uri);
+            throw new BuildException("Attempt to use a reserved URI %s", uri);
         }
         this.uri = uri;
     }
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 ab527b8..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.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_8)) {
-           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/AttributeNamespaceDef.java b/src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java
index c374d6f..1ddca7c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/AugmentReference.java b/src/main/org/apache/tools/ant/taskdefs/AugmentReference.java
index 7402d44..3ddfb92 100644
--- a/src/main/org/apache/tools/ant/taskdefs/AugmentReference.java
+++ b/src/main/org/apache/tools/ant/taskdefs/AugmentReference.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,7 +46,7 @@
         hijackId();
         if (getProject().hasReference(id)) {
             Object result = getProject().getReference(id);
-            log("project reference " + id + "=" + String.valueOf(result), Project.MSG_DEBUG);
+            log("project reference " + id + "=" + result, Project.MSG_DEBUG);
             return result;
         }
         throw new BuildException("Unknown reference \"" + id + "\"");
diff --git a/src/main/org/apache/tools/ant/taskdefs/Available.java b/src/main/org/apache/tools/ant/taskdefs/Available.java
index d8eb82f..ecd45b6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Available.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Available.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,7 +31,6 @@
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Will set the given property if the requested resource is available at
@@ -160,7 +159,7 @@
      * @param classname the name of the class required.
      */
     public void setClassname(String classname) {
-        if (!"".equals(classname)) {
+        if (!classname.isEmpty()) {
             this.classname = classname;
         }
     }
@@ -193,9 +192,9 @@
      *             the type in its own class.
      * @param type the type of resource
      */
+    @Deprecated
     public void setType(String type) {
-        log("DEPRECATED - The setType(String) method has been deprecated."
-            + " Use setType(Available.FileDir) instead.",
+        log("DEPRECATED - The setType(String) method has been deprecated. Use setType(Available.FileDir) instead.",
             Project.MSG_WARN);
         this.type = new FileDir();
         this.type.setValue(type);
@@ -227,6 +226,7 @@
      *
      * @exception BuildException if the task is not configured correctly.
      */
+    @Override
     public void execute() throws BuildException {
         if (property == null) {
             throw new BuildException("property attribute is required",
@@ -239,11 +239,8 @@
                 PropertyHelper ph = PropertyHelper.getPropertyHelper(getProject());
                 Object oldvalue = ph.getProperty(property);
                 if (null != oldvalue && !oldvalue.equals(value)) {
-                    log("DEPRECATED - <available> used to override an existing"
-                        + " property."
-                        + StringUtils.LINE_SEP
-                        + "  Build file should not reuse the same property"
-                        + " name for different values.",
+                    log(String.format("DEPRECATED - <available> used to override an existing property.%n"
+                            + "  Build file should not reuse the same property name for different values."),
                         Project.MSG_WARN);
                 }
                 // NB: this makes use of Project#setProperty rather than Project#setNewProperty
@@ -261,17 +258,19 @@
      * @return boolean is the resource is available.
      * @exception BuildException if the condition is not configured correctly
      */
+    @Override
     public boolean eval() throws BuildException {
         try {
             if (classname == null && file == null && resource == null) {
-                throw new BuildException("At least one of (classname|file|"
-                                         + "resource) is required", getLocation());
+                throw new BuildException(
+                    "At least one of (classname|file|resource) is required",
+                    getLocation());
             }
             if (type != null) {
                 if (file == null) {
-                    throw new BuildException("The type attribute is only valid "
-                                             + "when specifying the file "
-                                             + "attribute.", getLocation());
+                    throw new BuildException(
+                        "The type attribute is only valid when specifying the file attribute.",
+                        getLocation());
                 }
             }
             if (classpath != null) {
@@ -284,13 +283,13 @@
             } else {
                 setTaskName("available");
             }
-            if ((classname != null) && !checkClass(classname)) {
+            if (classname != null && !checkClass(classname)) {
                 log("Unable to load class " + classname + appendix,
                     Project.MSG_VERBOSE);
                 return false;
             }
-            if ((file != null) && !checkFile()) {
-                StringBuffer buf = new StringBuffer("Unable to find ");
+            if (file != null && !checkFile()) {
+                StringBuilder buf = new StringBuilder("Unable to find ");
                 if (type != null) {
                     buf.append(type).append(' ');
                 }
@@ -298,7 +297,7 @@
                 log(buf.toString(), Project.MSG_VERBOSE);
                 return false;
             }
-            if ((resource != null) && !checkResource(resource)) {
+            if (resource != null && !checkResource(resource)) {
                 log("Unable to load resource " + resource + appendix,
                     Project.MSG_VERBOSE);
                 return false;
@@ -334,62 +333,64 @@
     private boolean checkFile() {
         if (filepath == null) {
             return checkFile(file, filename);
-        } else {
-            String[] paths = filepath.list();
-            for (int i = 0; i < paths.length; ++i) {
-                log("Searching " + paths[i], Project.MSG_VERBOSE);
-                File path = new File(paths[i]);
+        }
+        String[] paths = filepath.list();
+        for (String p : paths) {
+            log("Searching " + p, Project.MSG_VERBOSE);
+            File path = new File(p);
 
-                // **   full-pathname specified == path in list
-                // **   simple name specified   == path in list
-                if (path.exists()
-                    && (filename.equals(paths[i])
-                        || filename.equals(path.getName()))) {
-                    if (type == null) {
-                        log("Found: " + path, Project.MSG_VERBOSE);
-                        return true;
-                    } else if (type.isDir()
-                               && path.isDirectory()) {
-                        log("Found directory: " + path, Project.MSG_VERBOSE);
-                        return true;
-                    } else if (type.isFile()
-                               && path.isFile()) {
-                        log("Found file: " + path, Project.MSG_VERBOSE);
-                        return true;
-                    }
-                    // not the requested type
-                    return false;
+            // **   full-pathname specified == path in list
+            // **   simple name specified   == path in list
+            if (path.exists()
+                && (filename.equals(p)
+                    || filename.equals(path.getName()))) {
+                if (type == null) {
+                    log("Found: " + path, Project.MSG_VERBOSE);
+                    return true;
                 }
-                File parent = path.getParentFile();
-                // **   full-pathname specified == parent dir of path in list
-                if (parent != null && parent.exists()
-                    && filename.equals(parent.getAbsolutePath())) {
-                    if (type == null) {
-                        log("Found: " + parent, Project.MSG_VERBOSE);
-                        return true;
-                    } else if (type.isDir()) {
-                        log("Found directory: " + parent, Project.MSG_VERBOSE);
-                        return true;
-                    }
-                    // not the requested type
-                    return false;
+                if (type.isDir()
+                           && path.isDirectory()) {
+                    log("Found directory: " + path, Project.MSG_VERBOSE);
+                    return true;
                 }
-                // **   simple name specified   == path in list + name
-                if (path.exists() && path.isDirectory()) {
-                    if (checkFile(new File(path, filename),
-                                  filename + " in " + path)) {
-                        return true;
-                    }
+                if (type.isFile()
+                           && path.isFile()) {
+                    log("Found file: " + path, Project.MSG_VERBOSE);
+                    return true;
                 }
+                // not the requested type
+                return false;
+            }
+            File parent = path.getParentFile();
+            // **   full-pathname specified == parent dir of path in list
+            if (parent != null && parent.exists()
+                && filename.equals(parent.getAbsolutePath())) {
+                if (type == null) {
+                    log("Found: " + parent, Project.MSG_VERBOSE);
+                    return true;
+                }
+                if (type.isDir()) {
+                    log("Found directory: " + parent, Project.MSG_VERBOSE);
+                    return true;
+                }
+                // not the requested type
+                return false;
+            }
+            // **   simple name specified   == path in list + name
+            if (path.exists() && path.isDirectory()) {
+                if (checkFile(new File(path, filename),
+                              filename + " in " + path)) {
+                    return true;
+                }
+            }
 
-                // **   simple name specified   == parent dir + name
-                while (searchParents && parent != null && parent.exists()) {
-                    if (checkFile(new File(parent, filename),
-                                  filename + " in " + parent)) {
-                        return true;
-                    }
-                    parent = parent.getParentFile();
+            // **   simple name specified   == parent dir + name
+            while (searchParents && parent != null && parent.exists()) {
+                if (checkFile(new File(parent, filename),
+                              filename + " in " + parent)) {
+                    return true;
                 }
+                parent = parent.getParentFile();
             }
         }
         return false;
@@ -405,7 +406,8 @@
                     log("Found directory: " + text, Project.MSG_VERBOSE);
                 }
                 return f.isDirectory();
-            } else if (type.isFile()) {
+            }
+            if (type.isFile()) {
                 if (f.isFile()) {
                     log("Found file: " + text, Project.MSG_VERBOSE);
                 }
@@ -494,6 +496,7 @@
          * @see EnumeratedAttribute#getValues
          * {@inheritDoc}.
          */
+        @Override
         public String[] getValues() {
             return VALUES;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/BUnzip2.java b/src/main/org/apache/tools/ant/taskdefs/BUnzip2.java
index e4a7995..b364b59 100644
--- a/src/main/org/apache/tools/ant/taskdefs/BUnzip2.java
+++ b/src/main/org/apache/tools/ant/taskdefs/BUnzip2.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,9 +20,10 @@
 
 
 import java.io.BufferedInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.FileUtils;
@@ -60,12 +61,12 @@
             log("Expanding " + srcResource.getName() + " to "
                 + dest.getAbsolutePath());
 
-            FileOutputStream out = null;
+            OutputStream out = null;
             CBZip2InputStream zIn = null;
             InputStream fis = null;
             BufferedInputStream bis = null;
             try {
-                out = new FileOutputStream(dest);
+                out = Files.newOutputStream(dest.toPath());
                 fis = srcResource.getInputStream();
                 bis = new BufferedInputStream(fis);
                 int b = bis.read();
diff --git a/src/main/org/apache/tools/ant/taskdefs/BZip2.java b/src/main/org/apache/tools/ant/taskdefs/BZip2.java
index f5944df..0b410e7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/BZip2.java
+++ b/src/main/org/apache/tools/ant/taskdefs/BZip2.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,8 +20,8 @@
 
 
 import java.io.BufferedOutputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.FileUtils;
@@ -44,7 +44,7 @@
         CBZip2OutputStream zOut = null;
         try {
             BufferedOutputStream bos =
-                new BufferedOutputStream(new FileOutputStream(zipFile));
+                new BufferedOutputStream(Files.newOutputStream(zipFile.toPath()));
             bos.write('B');
             bos.write('Z');
             zOut = new CBZip2OutputStream(bos);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Basename.java b/src/main/org/apache/tools/ant/taskdefs/Basename.java
index 0415af7..7b6d434 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Basename.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Basename.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -85,6 +85,7 @@
      * @throws BuildException if required attributes are not supplied
      * property and attribute are required attributes
      */
+    @Override
     public void execute() throws BuildException {
         if (property == null) {
             throw new BuildException("property attribute required", getLocation());
@@ -92,19 +93,21 @@
         if (file == null) {
             throw new BuildException("file attribute required", getLocation());
         }
-        String value = file.getName();
-        if (suffix != null && value.endsWith(suffix)) {
-            // if the suffix does not starts with a '.' and the
-            // char preceding the suffix is a '.', we assume the user
-            // wants to remove the '.' as well (see docs)
-            int pos = value.length() - suffix.length();
-            if (pos > 0 && suffix.charAt(0) != '.'
-                && value.charAt(pos - 1) == '.') {
-                pos--;
-            }
-            value = value.substring(0, pos);
+        getProject().setNewProperty(property,
+            removeExtension(file.getName(), suffix));
+    }
+
+    private String removeExtension(String s, String ext) {
+        if (ext == null || !s.endsWith(ext)) {
+            return s;
         }
-        getProject().setNewProperty(property, value);
+        int clipFrom = s.length() - ext.length();
+        // if the suffix does not starts with a '.' and the
+        // char preceding the suffix is a '.', we assume the user
+        // wants to remove the '.' as well (see docs)
+        if (ext.charAt(0) != '.' && clipFrom > 0 && s.charAt(clipFrom - 1) == '.') {
+            clipFrom -= 1;
+        }
+        return s.substring(0, clipFrom);
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/BindTargets.java b/src/main/org/apache/tools/ant/taskdefs/BindTargets.java
index 3c07e28..763f484 100644
--- a/src/main/org/apache/tools/ant/taskdefs/BindTargets.java
+++ b/src/main/org/apache/tools/ant/taskdefs/BindTargets.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,11 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.ProjectHelper.OnMissingExtensionPoint;
 import org.apache.tools.ant.Task;
@@ -33,7 +34,7 @@
 
     private String extensionPoint;
 
-    private final List<String> targets = new ArrayList<String>();
+    private final List<String> targets = new ArrayList<>();
 
     private OnMissingExtensionPoint onMissingExtensionPoint;
 
@@ -54,13 +55,8 @@
     }
 
     public void setTargets(final String target) {
-        final String[] inputs = target.split(",");
-        for (int i = 0; i < inputs.length; i++) {
-            final String input = inputs[i].trim();
-            if (input.length() > 0) {
-                targets.add(input);
-            }
-        }
+        Stream.of(target.split(",")).map(String::trim).filter(s -> !s.isEmpty())
+            .forEach(targets::add);
     }
 
     @Override
@@ -70,21 +66,18 @@
         }
 
         if (getOwningTarget() == null
-                || !"".equals(getOwningTarget().getName())) {
-            throw new BuildException(
-                    "bindtargets only allowed as a top-level task");
+                || !getOwningTarget().getName().isEmpty()) {
+            throw new BuildException("bindtargets only allowed as a top-level task");
         }
 
         if (onMissingExtensionPoint == null) {
             onMissingExtensionPoint = OnMissingExtensionPoint.FAIL;
         }
-        final ProjectHelper helper = (ProjectHelper) getProject().getReference(
-                ProjectHelper.PROJECTHELPER_REFERENCE);
+        final ProjectHelper helper = getProject().getReference(MagicNames.REFID_PROJECT_HELPER);
 
-        for (final Iterator<String> itTarget = targets.iterator(); itTarget.hasNext();) {
+        for (String target : targets) {
             helper.getExtensionStack().add(new String[] {extensionPoint,
-                    itTarget.next(), onMissingExtensionPoint.name()});
+                target, onMissingExtensionPoint.name()});
         }
-
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/BuildNumber.java b/src/main/org/apache/tools/ant/taskdefs/BuildNumber.java
index 7a66125..ce61ae2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/BuildNumber.java
+++ b/src/main/org/apache/tools/ant/taskdefs/BuildNumber.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,13 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.Properties;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.util.FileUtils;
 
@@ -39,8 +39,7 @@
  * @since Ant 1.5
  * @ant.task name="buildnumber"
  */
-public class BuildNumber
-     extends Task {
+public class BuildNumber extends Task {
     /**
      * The name of the property in which the build number is stored.
      */
@@ -54,7 +53,6 @@
     /** The File in which the build number is stored.  */
     private File myFile;
 
-
     /**
      * The file in which the build number is stored. Defaults to
      * "build.number" if not specified.
@@ -65,14 +63,13 @@
         myFile = file;
     }
 
-
     /**
      * Run task.
      *
      * @exception BuildException if an error occurs
      */
-    public void execute()
-         throws BuildException {
+    @Override
+    public void execute() throws BuildException {
         File savedFile = myFile; // may be altered in validate
 
         validate();
@@ -84,26 +81,12 @@
             String.valueOf(buildNumber + 1));
 
         // Write the properties file back out
-        FileOutputStream output = null;
 
-        try {
-            output = new FileOutputStream(myFile);
-
-            final String header = "Build Number for ANT. Do not edit!";
-
-            properties.store(output, header);
+        try (OutputStream output = Files.newOutputStream(myFile.toPath())) {
+            properties.store(output, "Build Number for ANT. Do not edit!");
         } catch (final IOException ioe) {
-            final String message = "Error while writing " + myFile;
-
-            throw new BuildException(message, ioe);
+            throw new BuildException("Error while writing " + myFile, ioe);
         } finally {
-            if (null != output) {
-                try {
-                    output.close();
-                } catch (final IOException ioe) {
-                    log("error closing output stream " + ioe, Project.MSG_ERR);
-                }
-            }
             myFile = savedFile;
         }
 
@@ -112,7 +95,6 @@
             String.valueOf(buildNumber));
     }
 
-
     /**
      * Utility method to retrieve build number from properties object.
      *
@@ -129,43 +111,28 @@
         try {
             return Integer.parseInt(buildNumber);
         } catch (final NumberFormatException nfe) {
-            final String message =
-                myFile + " contains a non integer build number: " + buildNumber;
-            throw new BuildException(message, nfe);
+            throw new BuildException(
+                myFile + " contains a non integer build number: " + buildNumber,
+                nfe);
         }
     }
 
-
     /**
      * Utility method to load properties from file.
      *
      * @return the loaded properties
      * @throws BuildException if something goes wrong
      */
-    private Properties loadProperties()
-         throws BuildException {
-        FileInputStream input = null;
-
-        try {
+    private Properties loadProperties() throws BuildException {
+        try (InputStream input = Files.newInputStream(myFile.toPath())) {
             final Properties properties = new Properties();
-
-            input = new FileInputStream(myFile);
             properties.load(input);
             return properties;
         } catch (final IOException ioe) {
             throw new BuildException(ioe);
-        } finally {
-            if (null != input) {
-                try {
-                    input.close();
-                } catch (final IOException ioe) {
-                    log("error closing input stream " + ioe, Project.MSG_ERR);
-                }
-            }
         }
     }
 
-
     /**
      * Validate that the task parameters are valid.
      *
@@ -181,21 +148,18 @@
             try {
                 FILE_UTILS.createNewFile(myFile);
             } catch (final IOException ioe) {
-                final String message =
-                    myFile + " doesn't exist and new file can't be created.";
-                throw new BuildException(message, ioe);
+                throw new BuildException(
+                    myFile + " doesn't exist and new file can't be created.",
+                    ioe);
             }
         }
 
         if (!myFile.canRead()) {
-            final String message = "Unable to read from " + myFile + ".";
-            throw new BuildException(message);
+            throw new BuildException("Unable to read from " + myFile + ".");
         }
 
         if (!myFile.canWrite()) {
-            final String message = "Unable to write to " + myFile + ".";
-            throw new BuildException(message);
+            throw new BuildException("Unable to write to " + myFile + ".");
         }
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/CVSPass.java b/src/main/org/apache/tools/ant/taskdefs/CVSPass.java
index 1d3ad83..5c58e03 100644
--- a/src/main/org/apache/tools/ant/taskdefs/CVSPass.java
+++ b/src/main/org/apache/tools/ant/taskdefs/CVSPass.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,7 +29,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Adds an new entry to a CVS password file.
@@ -82,6 +81,7 @@
      *
      * @exception BuildException if something goes wrong with the build
      */
+    @Override
     public final void execute() throws BuildException {
         if (cvsRoot == null) {
             throw new BuildException("cvsroot is required");
@@ -97,7 +97,7 @@
         BufferedReader reader = null;
         BufferedWriter writer = null;
         try {
-            StringBuffer buf = new StringBuffer();
+            StringBuilder buf = new StringBuilder();
 
             if (passFile.exists()) {
                 reader = new BufferedReader(new FileReader(passFile));
@@ -106,7 +106,7 @@
 
                 while ((line = reader.readLine()) != null) {
                     if (!line.startsWith(cvsRoot)) {
-                        buf.append(line).append(StringUtils.LINE_SEP);
+                        buf.append(line).append(System.lineSeparator());
                     }
                 }
             }
diff --git a/src/main/org/apache/tools/ant/taskdefs/CallTarget.java b/src/main/org/apache/tools/ant/taskdefs/CallTarget.java
index d8a0e8c..017490d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/CallTarget.java
+++ b/src/main/org/apache/tools/ant/taskdefs/CallTarget.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.PropertySet;
 
@@ -99,7 +100,7 @@
                 "Attribute target or at least one nested target is required.",
                  getLocation());
         }
-        callee.setAntfile(getProject().getProperty("ant.file"));
+        callee.setAntfile(getProject().getProperty(MagicNames.ANT_FILE));
         callee.setInheritAll(inheritAll);
         callee.setInheritRefs(inheritRefs);
         callee.execute();
diff --git a/src/main/org/apache/tools/ant/taskdefs/Checksum.java b/src/main/org/apache/tools/ant/taskdefs/Checksum.java
index ff95dac..a1b78aa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Checksum.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Checksum.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,11 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.security.DigestInputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -47,7 +48,6 @@
 import org.apache.tools.ant.types.resources.Union;
 import org.apache.tools.ant.types.resources.selectors.Type;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Used to create or verify file checksums.
@@ -70,6 +70,7 @@
             super.add(u);
             super.add(Type.FILE);
         }
+        @Override
         public void add(ResourceCollection rc) {
             u.add(rc);
         }
@@ -109,14 +110,14 @@
      * Key:   java.util.File (source file)
      * Value: java.lang.String (digest)
      */
-    private Map<File, byte[]> allDigests = new HashMap<File, byte[]>();
+    private Map<File, byte[]> allDigests = new HashMap<>();
     /**
      * Holds relative file names for all files (always with a forward slash).
      * This is used to calculate the total hash.
      * Key:   java.util.File (source file)
      * Value: java.lang.String (relative file name)
      */
-    private Map<File, String> relativeFilePaths = new HashMap<File, String>();
+    private Map<File, String> relativeFilePaths = new HashMap<>();
     /**
      * Property where totalChecksum gets set.
      */
@@ -137,7 +138,7 @@
     /**
      * Stores SourceFile, DestFile pairs and SourceFile, Property String pairs.
      */
-    private Hashtable<File, Object> includeFileMap = new Hashtable<File, Object>();
+    private Hashtable<File, Object> includeFileMap = new Hashtable<>();
     /**
      * Message Digest instance
      */
@@ -152,7 +153,7 @@
     private int readBufferSize = BUFFER_SIZE;
 
     /**
-     * Formater for the checksum file.
+     * Formatter for the checksum file.
      */
     private MessageFormat format = FormatElement.getDefault().getFormat();
 
@@ -261,12 +262,12 @@
      * Specify the pattern to use as a MessageFormat pattern.
      *
      * <p>{0} gets replaced by the checksum, {1} by the filename.</p>
-     * @param p a <code>String</code> value
+     * @param pattern a <code>String</code> value
      *
      * @since 1.7.0
      */
-    public void setPattern(String p) {
-        format = new MessageFormat(p);
+    public void setPattern(String pattern) {
+        format = new MessageFormat(pattern);
     }
 
     /**
@@ -293,13 +294,13 @@
      * Calculate the checksum(s).
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         isCondition = false;
         boolean value = validateAndExecute();
         if (verifyProperty != null) {
-            getProject().setNewProperty(
-                verifyProperty,
-                (value ? Boolean.TRUE.toString() : Boolean.FALSE.toString()));
+            getProject().setNewProperty(verifyProperty,
+                Boolean.toString(value));
         }
     }
 
@@ -310,6 +311,7 @@
      * false otherwise.
      * @throws BuildException on error
      */
+    @Override
     public boolean eval() throws BuildException {
         isCondition = true;
         return validateAndExecute();
@@ -325,7 +327,7 @@
             throw new BuildException(
                 "Specify at least one source - a file or a resource collection.");
         }
-        if (!(resources == null || resources.isFilesystemOnly())) {
+        if (resources != null && !resources.isFilesystemOnly()) {
             throw new BuildException("Can only calculate checksums for file-based resources.");
         }
         if (file != null && file.exists() && file.isDirectory()) {
@@ -368,10 +370,8 @@
         if (provider != null) {
             try {
                 messageDigest = MessageDigest.getInstance(algorithm, provider);
-            } catch (NoSuchAlgorithmException noalgo) {
+            } catch (NoSuchAlgorithmException | NoSuchProviderException noalgo) {
                 throw new BuildException(noalgo, getLocation());
-            } catch (NoSuchProviderException noprovider) {
-                throw new BuildException(noprovider, getLocation());
             }
         } else {
             try {
@@ -385,14 +385,13 @@
         }
         if (fileext == null) {
             fileext = "." + algorithm;
-        } else if (fileext.trim().length() == 0) {
+        } else if (fileext.trim().isEmpty()) {
             throw new BuildException("File extension when specified must not be an empty string");
         }
         try {
             if (resources != null) {
                 for (Resource r : resources) {
-                    File src = r.as(FileProvider.class)
-                        .getFile();
+                    File src = r.as(FileProvider.class).getFile();
                     if (totalproperty != null || todir != null) {
                         // Use '/' to calculate digest based on file name.
                         // This is required in order to get the same result
@@ -462,8 +461,7 @@
             // This directory will exist
             directory = file.getParentFile();
         }
-        File checksumFile = new File(directory, file.getName() + fileext);
-        return checksumFile;
+        return new File(directory, file.getName() + fileext);
     }
 
     /**
@@ -471,8 +469,8 @@
      */
     private boolean generateChecksums() throws BuildException {
         boolean checksumMatches = true;
-        FileInputStream fis = null;
-        FileOutputStream fos = null;
+        InputStream fis = null;
+        OutputStream fos = null;
         byte[] buf = new byte[readBufferSize];
         try {
             for (Map.Entry<File, Object> e : includeFileMap.entrySet()) {
@@ -481,7 +479,7 @@
                 if (!isCondition) {
                     log("Calculating " + algorithm + " checksum for " + src, Project.MSG_VERBOSE);
                 }
-                fis = new FileInputStream(src);
+                fis = Files.newInputStream(src.toPath());
                 DigestInputStream dis = new DigestInputStream(fis,
                                                               messageDigest);
                 while (dis.read(buf, 0, readBufferSize) != -1) {
@@ -497,7 +495,7 @@
                 String checksum = createDigestString(fileDigest);
                 //can either be a property name string or a file
                 Object destination = e.getValue();
-                if (destination instanceof java.lang.String) {
+                if (destination instanceof String) {
                     String prop = (String) destination;
                     if (isCondition) {
                         checksumMatches
@@ -505,7 +503,7 @@
                     } else {
                         getProject().setNewProperty(prop, checksum);
                     }
-                } else if (destination instanceof java.io.File) {
+                } else if (destination instanceof File) {
                     if (isCondition) {
                         File existingFile = (File) destination;
                         if (existingFile.exists()) {
@@ -523,7 +521,7 @@
                         }
                     } else {
                         File dest = (File) destination;
-                        fos = new FileOutputStream(dest);
+                        fos = Files.newOutputStream(dest.toPath());
                         fos.write(format.format(new Object[] {
                                                     checksum,
                                                     src.getName(),
@@ -537,7 +535,7 @@
                                                                      src),
                                                     src.getAbsolutePath()
                                                 }).getBytes());
-                        fos.write(StringUtils.LINE_SEP.getBytes());
+                        fos.write(System.lineSeparator().getBytes());
                         fos.close();
                         fos = null;
                     }
@@ -546,17 +544,12 @@
             if (totalproperty != null) {
                 // Calculate the total checksum
                 // Convert the keys (source files) into a sorted array.
-                File[] keyArray = allDigests.keySet().toArray(new File[allDigests.size()]);
+                File[] keyArray = allDigests.keySet().toArray(new File[0]);
                 // File is Comparable, but sort-order is platform
                 // dependent (case-insensitive on Windows)
-                Arrays.sort(keyArray, new Comparator<File>() {
-                        public int compare(File f1, File f2) {
-                            return f1 == null ? (f2 == null ? 0 : -1)
-                                : (f2 == null ? 1
-                                   : getRelativeFilePath(f1)
-                                   .compareTo(getRelativeFilePath(f2)));
-                        }
-                    });
+                Arrays.sort(keyArray, Comparator.nullsFirst(
+                    Comparator.comparing(this::getRelativeFilePath)));
+
                 // Loop over the checksums and generate a total hash.
                 messageDigest.reset();
                 for (File src : keyArray) {
@@ -583,11 +576,7 @@
     private String createDigestString(byte[] fileDigest) {
         StringBuilder checksumSb = new StringBuilder();
         for (byte digestByte : fileDigest) {
-            String hexStr = Integer.toHexString(BYTE_MASK & digestByte);
-            if (hexStr.length() < 2) {
-                checksumSb.append("0");
-            }
-            checksumSb.append(hexStr);
+            checksumSb.append(String.format("%02x", BYTE_MASK & digestByte));
         }
         return checksumSb.toString();
     }
@@ -616,7 +605,7 @@
         // two characters form the hex value.
         for (int i = 0, j = 0; j < l; i++) {
             int f = Character.digit(data[j++], WORD) << NIBBLE;
-            f = f | Character.digit(data[j++], WORD);
+            f |= Character.digit(data[j++], WORD);
             out[i] = (byte) (f & BYTE_MASK);
         }
 
@@ -629,20 +618,15 @@
      * @since 1.7
      */
     private String readChecksum(File f) {
-        BufferedReader diskChecksumReader = null;
-        try {
-            diskChecksumReader = new BufferedReader(new FileReader(f));
+        try (BufferedReader diskChecksumReader =
+            new BufferedReader(new FileReader(f))) {
             Object[] result = format.parse(diskChecksumReader.readLine());
             if (result == null || result.length == 0 || result[0] == null) {
                 throw new BuildException("failed to find a checksum");
             }
             return (String) result[0];
-        } catch (IOException e) {
+        } catch (IOException | ParseException e) {
             throw new BuildException("Couldn't read checksum file " + f, e);
-        } catch (ParseException e) {
-            throw new BuildException("Couldn't read checksum file " + f, e);
-        } finally {
-            FileUtils.close(diskChecksumReader);
         }
     }
 
@@ -650,13 +634,12 @@
      * @since Ant 1.8.2
      */
     private String getRelativeFilePath(File f) {
-        String path = (String) relativeFilePaths.get(f);
+        String path = relativeFilePaths.get(f);
         if (path == null) {
             //bug 37386. this should not occur, but it has, once.
-            throw new BuildException("Internal error: "
-                                     + "relativeFilePaths could not match file "
-                                     + f + "\n"
-                                     + "please file a bug report on this");
+            throw new BuildException(
+                "Internal error: relativeFilePaths could not match file %s\nplease file a bug report on this",
+                f);
         }
         return path;
     }
@@ -667,7 +650,7 @@
      * @since 1.7
      */
     public static class FormatElement extends EnumeratedAttribute {
-        private static HashMap<String, MessageFormat> formatMap = new HashMap<String, MessageFormat>();
+        private static HashMap<String, MessageFormat> formatMap = new HashMap<>();
         private static final String CHECKSUM = "CHECKSUM";
         private static final String MD5SUM = "MD5SUM";
         private static final String SVF = "SVF";
@@ -678,11 +661,6 @@
             formatMap.put(SVF, new MessageFormat("MD5 ({1}) = {0}"));
         }
 
-        /** Constructor for FormatElement */
-        public FormatElement() {
-            super();
-        }
-
         /**
          * Get the default value - CHECKSUM.
          * @return the defaul value.
@@ -698,13 +676,14 @@
          * @return a <code>MessageFormat</code> object.
          */
         public MessageFormat getFormat() {
-            return (MessageFormat) formatMap.get(getValue());
+            return formatMap.get(getValue());
         }
 
         /**
          * Get the valid values.
          * @return an array of values.
          */
+        @Override
         public String[] getValues() {
             return new String[] {CHECKSUM, MD5SUM, SVF};
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Chmod.java b/src/main/org/apache/tools/ant/taskdefs/Chmod.java
index ac0c3d8..53c232e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Chmod.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Chmod.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,6 +58,7 @@
      * @param project the project for this task.
      * @see org.apache.tools.ant.ProjectComponent#setProject
      */
+    @Override
     public void setProject(Project project) {
         super.setProject(project);
         defaultSet.setProject(project);
@@ -77,6 +78,7 @@
      * The directory which holds the files whose permissions must be changed.
      * @param src the directory.
      */
+    @Override
     public void setDir(File src) {
         defaultSet.setDir(src);
     }
@@ -154,6 +156,7 @@
     /**
      * Check the attributes and nested elements.
      */
+    @Override
     protected void checkConfiguration() {
         if (!havePerm) {
             throw new BuildException("Required attribute perm not set in chmod",
@@ -170,6 +173,7 @@
      * Carry out the chmoding.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
         /*
          * In Ant 1.1, <chmod dir="foo" /> means, change the permissions
@@ -186,7 +190,7 @@
                 }
             }
         } else if (isValidOs()) {
-            // we are chmodding the given directory
+            // we are chmoding the given directory
             Execute execute = prepareExec();
             Commandline cloned = (Commandline) cmdl.clone();
             cloned.createArgument().setValue(defaultSet.getDir(getProject())
@@ -210,9 +214,10 @@
      * @throws BuildException always.
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setExecutable(String e) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the executable attribute", getLocation());
+            + " doesn't support the executable attribute", getLocation());
     }
 
     /**
@@ -222,9 +227,10 @@
      * @throws BuildException always.
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setCommand(Commandline cmdl) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the command attribute", getLocation());
+            + " doesn't support the command attribute", getLocation());
     }
 
     /**
@@ -233,9 +239,10 @@
      * @throws BuildException always.
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setSkipEmptyFilesets(boolean skip) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the skipemptyfileset attribute", getLocation());
+            + " doesn't support the skipemptyfileset attribute", getLocation());
     }
 
     /**
@@ -244,9 +251,10 @@
      * @throws BuildException always.
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setAddsourcefile(boolean b) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the addsourcefile attribute", getLocation());
+            + " doesn't support the addsourcefile attribute", getLocation());
     }
 
     /**
@@ -254,6 +262,7 @@
      * Always include unix.
      * @return true if the os is valid.
      */
+    @Override
     protected boolean isValidOs() {
         return getOs() == null && getOsFamily() == null
             ? Os.isFamily(Os.FAMILY_UNIX) : super.isValidOs();
diff --git a/src/main/org/apache/tools/ant/taskdefs/Classloader.java b/src/main/org/apache/tools/ant/taskdefs/Classloader.java
index a7b9691..a1a2f15 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Classloader.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Classloader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -70,12 +70,6 @@
     private boolean parentFirst = true;
     private String parentName = null;
 
-    /**
-     * Default constructor
-     */
-    public Classloader() {
-    }
-
     /** Name of the loader. If none, the default loader will be modified
      *
      * @param name the name of this loader
@@ -101,6 +95,7 @@
      * @param b if true reverse the normal classloader lookup.
      * @deprecated use setParentFirst with a negated argument instead
      */
+    @Deprecated
     public void setReverse(boolean b) {
         this.parentFirst = !b;
     }
@@ -129,7 +124,7 @@
      * @throws BuildException if there is a problem.
      */
     public void setClasspathRef(Reference pathRef) throws BuildException {
-        classpath = (Path) pathRef.getReferencedObject(getProject());
+        classpath = pathRef.getReferencedObject(getProject());
     }
 
     /**
@@ -156,17 +151,17 @@
         return this.classpath.createPath();
     }
 
-
     /**
      * do the classloader manipulation.
      */
+    @Override
     public void execute() {
         try {
             // Gump friendly - don't mess with the core loader if only classpath
-            if ("only".equals(getProject().getProperty("build.sysclasspath"))
+            if ("only".equals(getProject().getProperty(MagicNames.BUILD_SYSCLASSPATH))
                 && (name == null || SYSTEM_LOADER_REF.equals(name))) {
-                log("Changing the system loader is disabled "
-                    + "by build.sysclasspath=only", Project.MSG_WARN);
+                log("Changing the system loader is disabled by "
+                        + MagicNames.BUILD_SYSCLASSPATH + "=only", Project.MSG_WARN);
                 return;
             }
 
@@ -186,6 +181,7 @@
                 return;
             }
 
+            @SuppressWarnings("resource")
             AntClassLoader acl = (AntClassLoader) obj;
             boolean existingLoader = acl != null;
 
@@ -219,7 +215,7 @@
                 if (name == null) {
                     // This allows the core loader to load optional tasks
                     // without delegating
-                    acl.addLoaderPackageRoot("org.apache.tools.ant.taskdefs.optional");
+                    acl.addLoaderPackageRoot(MagicNames.ANT_CORE_PACKAGE + ".taskdefs.optional");
                     getProject().setCoreLoader(acl);
                 }
             }
diff --git a/src/main/org/apache/tools/ant/taskdefs/CloseResources.java b/src/main/org/apache/tools/ant/taskdefs/CloseResources.java
index 6916abc..1aac2ee 100644
--- a/src/main/org/apache/tools/ant/taskdefs/CloseResources.java
+++ b/src/main/org/apache/tools/ant/taskdefs/CloseResources.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/CommandLauncherTask.java b/src/main/org/apache/tools/ant/taskdefs/CommandLauncherTask.java
index 1e1bf94..35abafa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/CommandLauncherTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/CommandLauncherTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/Componentdef.java b/src/main/org/apache/tools/ant/taskdefs/Componentdef.java
index 1c5590c..e90b983 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Componentdef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Componentdef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/Concat.java b/src/main/org/apache/tools/ant/taskdefs/Concat.java
index a095a4e..09127a9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Concat.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Concat.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,6 +26,7 @@
 import java.io.Reader;
 import java.io.StringReader;
 import java.io.Writer;
+import java.nio.file.Files;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
@@ -57,7 +57,6 @@
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.ReaderInputStream;
 import org.apache.tools.ant.util.ResourceUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * This class contains the 'concat' task, used to concatenate a series
@@ -130,7 +129,7 @@
         public void setFile(File file) throws BuildException {
             // non-existing files are not allowed
             if (!file.exists()) {
-                throw new BuildException("File " + file + " does not exist.");
+                throw new BuildException("File %s does not exist.", file);
             }
 
             BufferedReader reader = null;
@@ -139,7 +138,7 @@
                     reader = new BufferedReader(new FileReader(file));
                 } else {
                     reader = new BufferedReader(
-                        new InputStreamReader(new FileInputStream(file),
+                        new InputStreamReader(Files.newInputStream(file.toPath()),
                                               this.encoding));
                 }
                 value = FileUtils.safeReadFully(reader);
@@ -181,7 +180,7 @@
             if (value == null) {
                 value = "";
             }
-            if (value.trim().length() == 0) {
+            if (value.trim().isEmpty()) {
                 value = "";
             }
             if (trimLeading) {
@@ -213,27 +212,165 @@
     }
 
     /**
+     * This class reads a Reader and ensures it ends with the desired linebreak
+     * @since Ant 1.10.10
+     */
+    private final class LastLineFixingReader extends Reader {
+        private final Reader reader;
+        private int lastPos = 0;
+        private final char[] lastChars = new char[eolString.length()];
+        private boolean needAddSeparator = false;
+
+        private LastLineFixingReader(Reader reader) {
+            this.reader = reader;
+        }
+
+        /**
+         * Read a character from the current reader object. Advance
+         * to the next if the reader is finished.
+         * @return the character read, -1 for EOF on the last reader.
+         * @exception IOException - possibly thrown by the read for a reader
+         *            object.
+         */
+        @Override
+        public int read() throws IOException {
+            if (needAddSeparator) {
+                if (lastPos >= eolString.length()) {
+                    return -1;
+                } else {
+                    return eolString.charAt(lastPos++);
+                }
+            }
+            int ch = reader.read();
+            if (ch == -1) {
+                if (isMissingEndOfLine()) {
+                    needAddSeparator = true;
+                    lastPos = 1;
+                    return eolString.charAt(0);
+                }
+            } else {
+                addLastChar((char) ch);
+                return ch;
+            }
+            return -1;
+        }
+
+        /**
+         * Read into the buffer <code>cbuf</code>.
+         * @param cbuf The array to be read into.
+         * @param off The offset.
+         * @param len The length to read.
+         * @exception IOException - possibly thrown by the reads to the
+         *            reader objects.
+         */
+        @Override
+        public int read(char[] cbuf, int off, int len)
+            throws IOException {
+
+            int amountRead = 0;
+            while (true) {
+                if (needAddSeparator) {
+                    if (lastPos >= eolString.length()) {
+                        break;
+                    }
+                    cbuf[off] = eolString.charAt(lastPos++);
+                    len--;
+                    off++;
+                    amountRead++;
+                    if (len == 0) {
+                        return amountRead;
+                    }
+                    continue;
+                }
+                int nRead = reader.read(cbuf, off, len);
+                if (nRead == -1 || nRead == 0) {
+                    if (isMissingEndOfLine()) {
+                        needAddSeparator = true;
+                        lastPos = 0;
+                    } else {
+                        break;
+                    }
+                } else {
+                    for (int i = nRead;
+                         i > (nRead - lastChars.length);
+                         --i) {
+                        if (i <= 0) {
+                            break;
+                        }
+                        addLastChar(cbuf[off + i - 1]);
+                    }
+                    len -= nRead;
+                    off += nRead;
+                    amountRead += nRead;
+                    if (len == 0) {
+                        return amountRead;
+                    }
+                }
+            }
+            if (amountRead == 0) {
+                return -1;
+            }
+            return amountRead;
+        }
+
+        /**
+         * Close the current reader
+         */
+        @Override
+        public void close() throws IOException {
+            reader.close();
+        }
+
+        /**
+         * if checking for end of line at end of file
+         * add a character to the lastchars buffer
+         */
+        private void addLastChar(char ch) {
+            System.arraycopy(lastChars, 1, lastChars, 0, lastChars.length - 2 + 1);
+            lastChars[lastChars.length - 1] = ch;
+        }
+
+        /**
+         * return true if the lastchars buffer does
+         * not contain the line separator
+         */
+        private boolean isMissingEndOfLine() {
+            for (int i = 0; i < lastChars.length; ++i) {
+                if (lastChars[i] != eolString.charAt(i)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
      * This class reads from each of the source files in turn.
-     * The concatentated result can then be filtered as
+     * The concatenated result can then be filtered as
      * a single stream.
      */
     private final class MultiReader<S> extends Reader {
         private Reader reader = null;
-        private int    lastPos = 0;
-        private char[] lastChars = new char[eolString.length()];
-        private boolean needAddSeparator = false;
         private Iterator<S> readerSources;
         private ReaderFactory<S> factory;
+        private final boolean filterBeforeConcat;
 
-        private MultiReader(Iterator<S> readerSources, ReaderFactory<S> factory) {
+        private MultiReader(Iterator<S> readerSources, ReaderFactory<S> factory,
+                boolean filterBeforeConcat) {
             this.readerSources = readerSources;
             this.factory = factory;
+            this.filterBeforeConcat = filterBeforeConcat;
         }
 
         private Reader getReader() throws IOException {
             if (reader == null && readerSources.hasNext()) {
                 reader = factory.getReader(readerSources.next());
-                Arrays.fill(lastChars, (char) 0);
+                if (isFixLastLine()) {
+                    reader = new LastLineFixingReader(reader);
+                }
+                if (filterBeforeConcat) {
+                    reader = getFilteredReader(reader);
+                }
             }
             return reader;
         }
@@ -250,26 +387,13 @@
          * @exception IOException - possibly thrown by the read for a reader
          *            object.
          */
+        @Override
         public int read() throws IOException {
-            if (needAddSeparator) {
-                if (lastPos >= eolString.length()) {
-                    lastPos = 0;
-                    needAddSeparator = false;
-                } else {
-                    return eolString.charAt(lastPos++);
-                }
-            }
             while (getReader() != null) {
                 int ch = getReader().read();
                 if (ch == -1) {
                     nextReader();
-                    if (isFixLastLine() && isMissingEndOfLine()) {
-                        needAddSeparator = true;
-                        lastPos = 1;
-                        return eolString.charAt(0);
-                    }
                 } else {
-                    addLastChar((char) ch);
                     return ch;
                 }
             }
@@ -284,43 +408,16 @@
          * @exception IOException - possibly thrown by the reads to the
          *            reader objects.
          */
+        @Override
         public int read(char[] cbuf, int off, int len)
             throws IOException {
 
             int amountRead = 0;
-            while (getReader() != null || needAddSeparator) {
-                if (needAddSeparator) {
-                    cbuf[off] = eolString.charAt(lastPos++);
-                    if (lastPos >= eolString.length()) {
-                        lastPos = 0;
-                        needAddSeparator = false;
-                    }
-                    len--;
-                    off++;
-                    amountRead++;
-                    if (len == 0) {
-                        return amountRead;
-                    }
-                    continue;
-                }
+            while (getReader() != null) {
                 int nRead = getReader().read(cbuf, off, len);
                 if (nRead == -1 || nRead == 0) {
                     nextReader();
-                    if (isFixLastLine() && isMissingEndOfLine()) {
-                        needAddSeparator = true;
-                        lastPos = 0;
-                    }
                 } else {
-                    if (isFixLastLine()) {
-                        for (int i = nRead;
-                                 i > (nRead - lastChars.length);
-                                 --i) {
-                            if (i <= 0) {
-                                break;
-                            }
-                            addLastChar(cbuf[off + i - 1]);
-                        }
-                    }
                     len -= nRead;
                     off += nRead;
                     amountRead += nRead;
@@ -331,44 +428,20 @@
             }
             if (amountRead == 0) {
                 return -1;
-            } else {
-                return amountRead;
             }
+            return amountRead;
         }
 
         /**
          * Close the current reader
          */
+        @Override
         public void close() throws IOException {
             if (reader != null) {
                 reader.close();
             }
         }
 
-        /**
-         * if checking for end of line at end of file
-         * add a character to the lastchars buffer
-         */
-        private void addLastChar(char ch) {
-            for (int i = lastChars.length - 2; i >= 0; --i) {
-                lastChars[i] = lastChars[i + 1];
-            }
-            lastChars[lastChars.length - 1] = ch;
-        }
-
-        /**
-         * return true if the lastchars buffer does
-         * not contain the line separator
-         */
-        private boolean isMissingEndOfLine() {
-            for (int i = 0; i < lastChars.length; ++i) {
-                if (lastChars[i] != eolString.charAt(i)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
         private boolean isFixLastLine() {
             return fixLastLine && textBuffer == null;
         }
@@ -380,14 +453,21 @@
         private ConcatResource(ResourceCollection c) {
             this.c = c;
         }
+        @Override
         public InputStream getInputStream() {
             if (binary) {
                 ConcatResourceInputStream result = new ConcatResourceInputStream(c);
                 result.setManagingComponent(this);
                 return result;
             }
-            Reader resourceReader = getFilteredReader(
-                    new MultiReader<Resource>(c.iterator(), resourceReaderFactory));
+            Reader resourceReader;
+            if (filterBeforeConcat) {
+                resourceReader = new MultiReader<>(c.iterator(),
+                        resourceReaderFactory, true);
+            } else {
+                resourceReader = getFilteredReader(
+                        new MultiReader<>(c.iterator(), resourceReaderFactory, false));
+            }
             Reader rdr;
             if (header == null && footer == null) {
                 rdr = resourceReader;
@@ -415,15 +495,16 @@
                         readers[pos] = getFilteredReader(readers[pos]);
                     }
                 }
-                rdr = new MultiReader<Reader>(Arrays.asList(readers).iterator(),
-                        identityReaderFactory);
+                rdr = new MultiReader<>(Arrays.asList(readers).iterator(),
+                        identityReaderFactory, false);
             }
             return outputEncoding == null ? new ReaderInputStream(rdr)
                     : new ReaderInputStream(rdr, outputEncoding);
         }
+        @Override
         public String getName() {
             return resourceName == null
-                    ? "concat (" + String.valueOf(c) + ")" : resourceName;
+                    ? "concat (" + c + ")" : resourceName;
         }
     }
 
@@ -453,6 +534,9 @@
     /** Stores the binary attribute */
     private boolean binary;
 
+    /** Stores the filterBeforeConcat attribute */
+    private boolean filterBeforeConcat;
+
     // Child elements.
 
     /**
@@ -489,6 +573,7 @@
     private String resourceName;
 
     private ReaderFactory<Resource> resourceReaderFactory = new ReaderFactory<Resource>() {
+        @Override
         public Reader getReader(Resource o) throws IOException {
             InputStream is = o.getInputStream();
             return new BufferedReader(encoding == null
@@ -497,11 +582,7 @@
         }
     };
 
-    private ReaderFactory<Reader> identityReaderFactory = new ReaderFactory<Reader>() {
-        public Reader getReader(Reader o) {
-            return o;
-        }
-    };
+    private ReaderFactory<Reader> identityReaderFactory = o -> o;
 
     /**
      * Construct a new Concat task.
@@ -526,7 +607,7 @@
         binary = false;
         outputWriter = null;
         textBuffer = null;
-        eolString = StringUtils.LINE_SEP;
+        eolString = System.lineSeparator();
         rc = null;
         ignoreEmpty = true;
         force = false;
@@ -591,6 +672,7 @@
      * @since Ant 1.6
      * @deprecated use #setOverwrite instead
      */
+    @Deprecated
     public void setForce(boolean forceOverwrite) {
         this.forceOverwrite = forceOverwrite;
     }
@@ -622,7 +704,7 @@
      * Sets the behavior when no source resource files are available. If set to
      * <code>false</code> the destination file will always be created.
      * Defaults to <code>true</code>.
-     * @param ignoreEmpty if false honour destinationfile creation.
+     * @param ignoreEmpty if false, honour destination file creation.
      * @since Ant 1.8.0
      */
     public void setIgnoreEmpty(boolean ignoreEmpty) {
@@ -690,14 +772,14 @@
      */
     public void addFilterChain(FilterChain filterChain) {
         if (filterChains == null) {
-            filterChains = new Vector<FilterChain>();
+            filterChains = new Vector<>();
         }
         filterChains.addElement(filterChain);
     }
 
     /**
      * This method adds text which appears in the 'concat' element.
-     * @param text the text to be concated.
+     * @param text the text to be concatenated.
      */
     public void addText(String text) {
         if (textBuffer == null) {
@@ -750,11 +832,11 @@
      */
     public void setEol(FixCRLF.CrLf crlf) {
         String s = crlf.getValue();
-        if (s.equals("cr") || s.equals("mac")) {
+        if ("cr".equals(s) || "mac".equals(s)) {
             eolString = "\r";
-        } else if (s.equals("lf") || s.equals("unix")) {
+        } else if ("lf".equals(s) || "unix".equals(s)) {
             eolString = "\n";
-        } else if (s.equals("crlf") || s.equals("dos")) {
+        } else if ("crlf".equals(s) || "dos".equals(s)) {
             eolString = "\r\n";
         }
     }
@@ -781,8 +863,20 @@
     }
 
     /**
+     * Set the filterBeforeConcat attribute. If true, concat will filter each
+     * input through the filterchain before concatenating the results. This
+     * allows to e.g. use the FileTokenizer to tokenize each input.
+     * @param filterBeforeConcat if true, filter each input before concatenation
+     * @since Ant 1.10.10
+     */
+    public void setFilterBeforeConcat(final boolean filterBeforeConcat) {
+        this.filterBeforeConcat = filterBeforeConcat;
+    }
+
+    /**
      * Execute the concat task.
      */
+    @Override
     public void execute() {
         validate();
         if (binary && dest == null) {
@@ -794,7 +888,7 @@
             log(dest + " is up-to-date.", Project.MSG_VERBOSE);
             return;
         }
-        if (c.size() == 0 && ignoreEmpty) {
+        if (c.isEmpty() && ignoreEmpty) {
             return;
         }
         try {
@@ -813,15 +907,19 @@
      * Implement ResourceCollection.
      * @return Iterator&lt;Resource&gt;.
      */
+    @Override
     public Iterator<Resource> iterator() {
         validate();
-        return Collections.<Resource>singletonList(new ConcatResource(getResources())).iterator();
+        return Collections
+            .<Resource> singletonList(new ConcatResource(getResources()))
+            .iterator();
     }
 
     /**
      * Implement ResourceCollection.
      * @return 1.
      */
+    @Override
     public int size() {
         return 1;
     }
@@ -830,6 +928,7 @@
      * Implement ResourceCollection.
      * @return false.
      */
+    @Override
     public boolean isFilesystemOnly() {
         return false;
     }
@@ -850,8 +949,7 @@
             }
             if (encoding != null || outputEncoding != null) {
                 throw new BuildException(
-                    "Setting input or output encoding is incompatible with binary"
-                    + " concatenation");
+                    "Setting input or output encoding is incompatible with binary concatenation");
             }
             if (filterChains != null) {
                 throw new BuildException(
@@ -897,8 +995,9 @@
             checkDestNotInSources.add(rc);
             checkDestNotInSources.add(dest);
             if (checkDestNotInSources.size() > 0) {
-                throw new BuildException("Destination resource " + dest
-                        + " was specified as an input resource.");
+                throw new BuildException(
+                    "Destination resource %s was specified as an input resource.",
+                    dest);
             }
         }
         Restrict noexistRc = new Restrict();
@@ -914,15 +1013,8 @@
     }
 
     private boolean isUpToDate(ResourceCollection c) {
-        if (dest == null || forceOverwrite) {
-            return false;
-        }
-        for (Resource r : c) {
-            if (SelectorUtils.isOutOfDate(r, dest, FILE_UTILS.getFileTimestampGranularity())) {
-                return false;
-            }
-        }
-        return true;
+        return dest != null && !forceOverwrite
+                && c.stream().noneMatch(r -> SelectorUtils.isOutOfDate(r, dest, FILE_UTILS.getFileTimestampGranularity()));
     }
 
     /**
@@ -932,7 +1024,7 @@
      * for &quot;ignorable whitespace&quot; as well.</p>
      */
     private void sanitizeText() {
-        if (textBuffer != null && "".equals(textBuffer.toString().trim())) {
+        if (textBuffer != null && textBuffer.toString().trim().isEmpty()) {
             textBuffer = null;
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ConditionTask.java b/src/main/org/apache/tools/ant/taskdefs/ConditionTask.java
index 60904e0..74dd9eb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ConditionTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ConditionTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -107,16 +107,18 @@
      */
     public void execute() throws BuildException {
         if (countConditions() > 1) {
-            throw new BuildException("You must not nest more than one condition into <"
-                    + getTaskName() + ">");
+            throw new BuildException(
+                "You must not nest more than one condition into <%s>",
+                getTaskName());
         }
         if (countConditions() < 1) {
-            throw new BuildException("You must nest a condition into <" + getTaskName() + ">");
+            throw new BuildException("You must nest a condition into <%s>",
+                getTaskName());
         }
         if (property == null) {
             throw new BuildException("The property attribute is required.");
         }
-        Condition c = (Condition) getConditions().nextElement();
+        Condition c = getConditions().nextElement();
         if (c.eval()) {
             log("Condition true; setting " + property + " to " + value, Project.MSG_DEBUG);
             PropertyHelper.getPropertyHelper(getProject()).setNewProperty(property, value);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Copy.java b/src/main/org/apache/tools/ant/taskdefs/Copy.java
index 371c366..4851bac 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Copy.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Copy.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,11 +21,13 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -39,7 +41,6 @@
 import org.apache.tools.ant.types.Mapper;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.types.ResourceFactory;
 import org.apache.tools.ant.types.resources.FileProvider;
 import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.util.FileNameMapper;
@@ -49,6 +50,7 @@
 import org.apache.tools.ant.util.LinkedHashtable;
 import org.apache.tools.ant.util.ResourceUtils;
 import org.apache.tools.ant.util.SourceFileScanner;
+import org.apache.tools.ant.util.StringUtils;
 
 /**
  * <p>Copies a file or directory to a new file
@@ -69,13 +71,14 @@
     private static final String MSG_WHEN_COPYING_EMPTY_RC_TO_FILE =
         "Cannot perform operation from directory to file.";
 
+    @Deprecated
+    static final String LINE_SEPARATOR = StringUtils.LINE_SEP;
     static final File NULL_FILE_PLACEHOLDER = new File("/NULL_FILE");
-    static final String LINE_SEPARATOR = System.getProperty("line.separator");
     // CheckStyle:VisibilityModifier OFF - bc
     protected File file = null;     // the source file
     protected File destFile = null; // the destination file
     protected File destDir = null;  // the destination directory
-    protected Vector<ResourceCollection> rcs = new Vector<ResourceCollection>();
+    protected Vector<ResourceCollection> rcs = new Vector<>();
     // here to provide API backwards compatibility
     protected Vector<ResourceCollection> filesets = rcs;
 
@@ -88,15 +91,15 @@
     protected boolean includeEmpty = true;
     protected boolean failonerror = true;
 
-    protected Hashtable<String, String[]> fileCopyMap = new LinkedHashtable<String, String[]>();
-    protected Hashtable<String, String[]> dirCopyMap = new LinkedHashtable<String, String[]>();
-    protected Hashtable<File, File> completeDirMap = new LinkedHashtable<File, File>();
+    protected Hashtable<String, String[]> fileCopyMap = new LinkedHashtable<>();
+    protected Hashtable<String, String[]> dirCopyMap = new LinkedHashtable<>();
+    protected Hashtable<File, File> completeDirMap = new LinkedHashtable<>();
 
     protected Mapper mapperElement = null;
     protected FileUtils fileUtils;
     //CheckStyle:VisibilityModifier ON
-    private final Vector<FilterChain> filterChains = new Vector<FilterChain>();
-    private final Vector<FilterSet> filterSets = new Vector<FilterSet>();
+    private final Vector<FilterChain> filterChains = new Vector<>();
+    private final Vector<FilterSet> filterSets = new Vector<>();
     private String inputEncoding = null;
     private String outputEncoding = null;
     private long granularity = 0;
@@ -476,18 +479,17 @@
                separate lists and then each list is handled in one go.
             */
 
-            final HashMap<File, List<String>> filesByBasedir = new HashMap<File, List<String>>();
-            final HashMap<File, List<String>> dirsByBasedir = new HashMap<File, List<String>>();
-            final HashSet<File> baseDirs = new HashSet<File>();
-            final ArrayList<Resource> nonFileResources = new ArrayList<Resource>();
-            final int size = rcs.size();
-            for (int i = 0; i < size; i++) {
-                final ResourceCollection rc = rcs.elementAt(i);
+            final Map<File, List<String>> filesByBasedir = new HashMap<>();
+            final Map<File, List<String>> dirsByBasedir = new HashMap<>();
+            final Set<File> baseDirs = new HashSet<>();
+            final List<Resource> nonFileResources = new ArrayList<>();
+
+            for (ResourceCollection rc : rcs) {
 
                 // Step (1) - beware of the ZipFileSet
                 if (rc instanceof FileSet && rc.isFilesystemOnly()) {
                     final FileSet fs = (FileSet) rc;
-                    DirectoryScanner ds = null;
+                    DirectoryScanner ds;
                     try {
                         ds = fs.getDirectoryScanner(getProject());
                     } catch (final BuildException e) {
@@ -495,23 +497,20 @@
                             || !getMessage(e).endsWith(DirectoryScanner
                                                        .DOES_NOT_EXIST_POSTFIX)) {
                             throw e;
-                        } else {
-                            if (!quiet) {
-                                log("Warning: " + getMessage(e), Project.MSG_ERR);
-                            }
-                            continue;
                         }
+                        if (!quiet) {
+                            log("Warning: " + getMessage(e), Project.MSG_ERR);
+                        }
+                        continue;
                     }
                     final File fromDir = fs.getDir(getProject());
 
-                    final String[] srcFiles = ds.getIncludedFiles();
-                    final String[] srcDirs = ds.getIncludedDirectories();
                     if (!flatten && mapperElement == null
                         && ds.isEverythingIncluded() && !fs.hasPatterns()) {
                         completeDirMap.put(fromDir, destDir);
                     }
-                    add(fromDir, srcFiles, filesByBasedir);
-                    add(fromDir, srcDirs, dirsByBasedir);
+                    add(fromDir, ds.getIncludedFiles(), filesByBasedir);
+                    add(fromDir, ds.getIncludedDirectories(), dirsByBasedir);
                     baseDirs.add(fromDir);
                 } else { // not a fileset or contains non-file resources
 
@@ -576,9 +575,9 @@
                 }
             }
 
-            if (nonFileResources.size() > 0 || singleResource != null) {
+            if (!nonFileResources.isEmpty() || singleResource != null) {
                 final Resource[] nonFiles =
-                    nonFileResources.toArray(new Resource[nonFileResources.size()]);
+                    nonFileResources.toArray(new Resource[0]);
                 // restrict to out-of-date resources
                 final Map<Resource, String[]> map = scan(nonFiles, destDir);
                 if (singleResource != null) {
@@ -647,8 +646,9 @@
         }
     }
 
-    private void iterateOverBaseDirs(
-        final HashSet<File> baseDirs, final HashMap<File, List<String>> dirsByBasedir, final HashMap<File, List<String>> filesByBasedir) {
+    private void iterateOverBaseDirs(final Set<File> baseDirs,
+        final Map<File, List<String>> dirsByBasedir,
+        final Map<File, List<String>> filesByBasedir) {
 
         for (final File f : baseDirs) {
             final List<String> files = filesByBasedir.get(f);
@@ -674,7 +674,7 @@
      * @exception BuildException if an error occurs.
      */
     protected void validateAttributes() throws BuildException {
-        if (file == null && rcs.size() == 0) {
+        if (file == null && rcs.isEmpty()) {
             throw new BuildException(
                 "Specify at least one source--a file or a resource collection.");
         }
@@ -688,36 +688,36 @@
         if (file != null && file.isDirectory()) {
             throw new BuildException("Use a resource collection to copy directories.");
         }
-        if (destFile != null && rcs.size() > 0) {
+        if (destFile != null && !rcs.isEmpty()) {
             if (rcs.size() > 1) {
                 throw new BuildException(
                     "Cannot concatenate multiple files into a single file.");
-            } else {
-                final ResourceCollection rc = rcs.elementAt(0);
-                if (!rc.isFilesystemOnly() && !supportsNonFileResources()) {
-                    throw new BuildException("Only FileSystem resources are"
-                                             + " supported.");
-                }
-                if (rc.size() == 0) {
-                    throw new BuildException(MSG_WHEN_COPYING_EMPTY_RC_TO_FILE);
-                } else if (rc.size() == 1) {
-                    final Resource res = rc.iterator().next();
-                    final FileProvider r = res.as(FileProvider.class);
-                    if (file == null) {
-                        if (r != null) {
-                            file = r.getFile();
-                        } else {
-                            singleResource = res;
-                        }
-                        rcs.removeElementAt(0);
+            }
+            final ResourceCollection rc = rcs.elementAt(0);
+            if (!rc.isFilesystemOnly() && !supportsNonFileResources()) {
+                throw new BuildException(
+                    "Only FileSystem resources are supported.");
+            }
+            if (rc.isEmpty()) {
+                throw new BuildException(MSG_WHEN_COPYING_EMPTY_RC_TO_FILE);
+            }
+            if (rc.size() == 1) {
+                final Resource res = rc.iterator().next();
+                final FileProvider r = res.as(FileProvider.class);
+                if (file == null) {
+                    if (r != null) {
+                        file = r.getFile();
                     } else {
-                        throw new BuildException(
-                            "Cannot concatenate multiple files into a single file.");
+                        singleResource = res;
                     }
+                    rcs.removeElementAt(0);
                 } else {
                     throw new BuildException(
                         "Cannot concatenate multiple files into a single file.");
                 }
+            } else {
+                throw new BuildException(
+                    "Cannot concatenate multiple files into a single file.");
             }
         }
         if (destFile != null) {
@@ -773,13 +773,13 @@
                             final FileNameMapper mapper, final Hashtable<String, String[]> map) {
         String[] toCopy = null;
         if (forceOverwrite) {
-            final List<String> v = new ArrayList<String>();
+            final List<String> v = new ArrayList<>();
             for (String name : names) {
                 if (mapper.mapFileName(name) != null) {
                     v.add(name);
                 }
             }
-            toCopy = v.toArray(new String[v.size()]);
+            toCopy = v.toArray(new String[0]);
         } else {
             final SourceFileScanner ds = new SourceFileScanner(this);
             toCopy = ds.restrict(names, fromDir, toDir, mapper, granularity);
@@ -815,25 +815,19 @@
      */
     protected Map<Resource, String[]> buildMap(final Resource[] fromResources, final File toDir,
                            final FileNameMapper mapper) {
-        final HashMap<Resource, String[]> map = new HashMap<Resource, String[]>();
-        Resource[] toCopy = null;
+        final Map<Resource, String[]> map = new HashMap<>();
+        Resource[] toCopy;
         if (forceOverwrite) {
-            final List<Resource> v = new ArrayList<Resource>();
+            final List<Resource> v = new ArrayList<>();
             for (Resource rc : fromResources) {
                 if (mapper.mapFileName(rc.getName()) != null) {
                     v.add(rc);
                 }
             }
-            toCopy = v.toArray(new Resource[v.size()]);
+            toCopy = v.toArray(new Resource[0]);
         } else {
-            toCopy = ResourceUtils.selectOutOfDateSources(this, fromResources,
-                                                          mapper,
-                                                          new ResourceFactory() {
-                                            public Resource getResource(final String name) {
-                                                return new FileResource(toDir, name);
-                                            }
-                                                          },
-                                                          granularity);
+            toCopy = ResourceUtils.selectOutOfDateSources(this, fromResources, mapper,
+                    name -> new FileResource(toDir, name), granularity);
         }
         for (Resource rc : toCopy) {
             final String[] mappedFiles = mapper.mapFileName(rc.getName());
@@ -860,7 +854,7 @@
      * This is a good method for subclasses to override.
      */
     protected void doFileOperations() {
-        if (fileCopyMap.size() > 0) {
+        if (!fileCopyMap.isEmpty()) {
             log("Copying " + fileCopyMap.size()
                 + " file" + (fileCopyMap.size() == 1 ? "" : "s")
                 + " to " + destDir.getAbsolutePath());
@@ -912,10 +906,10 @@
         if (includeEmpty) {
             int createCount = 0;
             for (final String[] dirs : dirCopyMap.values()) {
-                for (int i = 0; i < dirs.length; i++) {
-                    final File d = new File(dirs[i]);
+                for (String dir : dirs) {
+                    final File d = new File(dir);
                     if (!d.exists()) {
-                        if (!(d.mkdirs() || d.isDirectory())) {
+                        if (!d.mkdirs() && !d.isDirectory()) {
                             log("Unable to create directory "
                                 + d.getAbsolutePath(), Project.MSG_ERR);
                         } else {
@@ -943,7 +937,7 @@
      * @since Ant 1.7
      */
     protected void doResourceOperations(final Map<Resource, String[]> map) {
-        if (map.size() > 0) {
+        if (!map.isEmpty()) {
             log("Copying " + map.size()
                 + " resource" + (map.size() == 1 ? "" : "s")
                 + " to " + destDir.getAbsolutePath());
@@ -1020,12 +1014,8 @@
     private static void add(File baseDir, final String[] names, final Map<File, List<String>> m) {
         if (names != null) {
             baseDir = getKeyFile(baseDir);
-            List<String> l = m.get(baseDir);
-            if (l == null) {
-                l = new ArrayList<String>(names.length);
-                m.put(baseDir, l);
-            }
-            l.addAll(java.util.Arrays.asList(names));
+            List<String> l = m.computeIfAbsent(baseDir, k -> new ArrayList<>(names.length));
+            l.addAll(Arrays.asList(names));
         }
     }
 
@@ -1081,7 +1071,7 @@
      */
     private String getDueTo(final Exception ex) {
         final boolean baseIOException = ex.getClass() == IOException.class;
-        final StringBuffer message = new StringBuffer();
+        final StringBuilder message = new StringBuilder();
         if (!baseIOException || ex.getMessage() == null) {
             message.append(ex.getClass().getName());
         }
@@ -1092,15 +1082,10 @@
             message.append(ex.getMessage());
         }
         if (ex.getClass().getName().contains("MalformedInput")) {
-            message.append(LINE_SEPARATOR);
-            message.append(
-                "This is normally due to the input file containing invalid");
-             message.append(LINE_SEPARATOR);
-            message.append("bytes for the character encoding used : ");
-            message.append(
-                (inputEncoding == null
-                 ? fileUtils.getDefaultEncoding() : inputEncoding));
-            message.append(LINE_SEPARATOR);
+            message.append(String.format(
+                    "%nThis is normally due to the input file containing invalid"
+                            + "%nbytes for the character encoding used : %s%n",
+                    inputEncoding == null ? fileUtils.getDefaultEncoding() : inputEncoding));
         }
         return message.toString();
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/CopyPath.java b/src/main/org/apache/tools/ant/taskdefs/CopyPath.java
index e5003d1..7ea9f1d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/CopyPath.java
+++ b/src/main/org/apache/tools/ant/taskdefs/CopyPath.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -63,6 +63,7 @@
     private File destDir;
 
     // TODO not read, yet in a public setter
+    @SuppressWarnings("unused")
     private long granularity = FILE_UTILS.getFileTimestampGranularity();
 
     private boolean preserveLastModified = false;
@@ -180,7 +181,7 @@
         for (String sourceFileName : sourceFiles) {
 
             File sourceFile = new File(sourceFileName);
-            String[] toFiles = (String[]) mapper.mapFileName(sourceFileName);
+            String[] toFiles = mapper.mapFileName(sourceFileName);
             if (toFiles == null) {
                 continue;
             }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Copydir.java b/src/main/org/apache/tools/ant/taskdefs/Copydir.java
index 26fc715..27a96e2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Copydir.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Copydir.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,6 +35,7 @@
  * @deprecated The copydir task is deprecated since Ant 1.2.  Use copy instead.
  */
 
+@Deprecated
 public class Copydir extends MatchingTask {
 
     private File srcDir;
@@ -42,7 +43,7 @@
     private boolean filtering = false;
     private boolean flatten = false;
     private boolean forceOverwrite = false;
-    private Hashtable<String, String> filecopyList = new Hashtable<String, String>();
+    private Map<String, String> filecopyList = new Hashtable<>();
 
     /**
      * The src attribute
@@ -94,6 +95,7 @@
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         log("DEPRECATED - The copydir task is deprecated.  Use copy instead.");
 
@@ -119,8 +121,7 @@
         DirectoryScanner ds = super.getDirectoryScanner(srcDir);
 
         try {
-            String[] files = ds.getIncludedFiles();
-            scanDir(srcDir, destDir, files);
+            scanDir(srcDir, destDir, ds.getIncludedFiles());
             if (filecopyList.size() > 0) {
                 log("Copying " + filecopyList.size() + " file"
                     + (filecopyList.size() == 1 ? "" : "s")
diff --git a/src/main/org/apache/tools/ant/taskdefs/Copyfile.java b/src/main/org/apache/tools/ant/taskdefs/Copyfile.java
index e9acb1d..30b496e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Copyfile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Copyfile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,6 +34,7 @@
  * copy instead.
  */
 
+@Deprecated
 public class Copyfile extends Task {
 
     private File srcFile;
@@ -80,6 +81,7 @@
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         log("DEPRECATED - The copyfile task is deprecated.  Use copy instead.");
 
@@ -107,9 +109,9 @@
             try {
                 getProject().copyFile(srcFile, destFile, filtering, forceOverwrite);
             } catch (IOException ioe) {
-                String msg = "Error copying file: " + srcFile.getAbsolutePath()
-                    + " due to " + ioe.getMessage();
-                throw new BuildException(msg);
+                throw new BuildException(
+                    "Error copying file: " + srcFile.getAbsolutePath()
+                        + " due to " + ioe.getMessage());
             }
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Cvs.java b/src/main/org/apache/tools/ant/taskdefs/Cvs.java
index 822a4ea..b97d53f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Cvs.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Cvs.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/DefBase.java b/src/main/org/apache/tools/ant/taskdefs/DefBase.java
index ca38fdd..d694060 100644
--- a/src/main/org/apache/tools/ant/taskdefs/DefBase.java
+++ b/src/main/org/apache/tools/ant/taskdefs/DefBase.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,6 +20,7 @@
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
@@ -145,7 +146,7 @@
             // task we want to define will never be a Task but always
             // be wrapped into a TaskAdapter.
             ((AntClassLoader) createdLoader)
-                .addSystemPackageRoot("org.apache.tools.ant");
+                .addSystemPackageRoot(MagicNames.ANT_CORE_PACKAGE);
         }
         return createdLoader;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/DefaultExcludes.java b/src/main/org/apache/tools/ant/taskdefs/DefaultExcludes.java
index 6b912e2..3f12943 100644
--- a/src/main/org/apache/tools/ant/taskdefs/DefaultExcludes.java
+++ b/src/main/org/apache/tools/ant/taskdefs/DefaultExcludes.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,9 @@
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
-import org.apache.tools.ant.util.StringUtils;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
 
 /**
  * Alters the default excludes for the <strong>entire</strong> build..
@@ -45,32 +47,26 @@
      *
      * @exception BuildException if something goes wrong with the build
      */
+    @Override
     public void execute() throws BuildException {
-        if (!defaultrequested && add.equals("") && remove.equals("") && !echo) {
-            throw new BuildException("<defaultexcludes> task must set "
-                + "at least one attribute (echo=\"false\""
-                + " doesn't count since that is the default");
+        if (!defaultrequested && add.isEmpty() && remove.isEmpty() && !echo) {
+            throw new BuildException(
+                "<defaultexcludes> task must set at least one attribute (echo=\"false\" doesn't count since that is the default");
         }
         if (defaultrequested) {
             DirectoryScanner.resetDefaultExcludes();
         }
-        if (!add.equals("")) {
+        if (!add.isEmpty()) {
             DirectoryScanner.addDefaultExclude(add);
         }
-        if (!remove.equals("")) {
+        if (!remove.isEmpty()) {
             DirectoryScanner.removeDefaultExclude(remove);
         }
         if (echo) {
-            StringBuffer message
-                = new StringBuffer("Current Default Excludes:");
-            message.append(StringUtils.LINE_SEP);
-            String[] excludes = DirectoryScanner.getDefaultExcludes();
-            for (int i = 0; i < excludes.length; i++) {
-                message.append("  ");
-                message.append(excludes[i]);
-                message.append(StringUtils.LINE_SEP);
-            }
-            log(message.toString(), logLevel);
+            String message = Arrays.stream(DirectoryScanner.getDefaultExcludes())
+                    .map(exclude -> String.format("  %s%n", exclude))
+                    .collect(Collectors.joining("", "Current Default Excludes:%n", ""));
+            log(message, logLevel);
         }
     }
 
@@ -111,5 +107,4 @@
         this.echo = echo;
     }
 
-
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Definer.java b/src/main/org/apache/tools/ant/taskdefs/Definer.java
index 98a22be..adfde30 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Definer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Definer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -50,15 +50,11 @@
 
     /**
      * the extension of an antlib file for autoloading.
-     * {@value[
+     * {@value /antlib.xml}
      */
     private static final String ANTLIB_XML = "/antlib.xml";
 
-    private static final ThreadLocal<Map<URL, Location>> RESOURCE_STACK = new ThreadLocal<Map<URL, Location>>() {
-        protected Map<URL, Location> initialValue() {
-            return new HashMap<URL, Location>();
-        }
-    };
+    private static final ThreadLocal<Map<URL, Location>> RESOURCE_STACK = ThreadLocal.withInitial(HashMap::new);
 
     private String name;
     private String classname;
@@ -120,9 +116,10 @@
          * get the values
          * @return an array of the allowed values for this attribute.
          */
+        @Override
         public String[] getValues() {
             return new String[] {POLICY_FAIL, POLICY_REPORT, POLICY_IGNORE,
-                    POLICY_FAILALL};
+                POLICY_FAILALL};
         }
     }
 
@@ -139,6 +136,7 @@
          * get the values
          * @return an array of the allowed values for this attribute.
          */
+        @Override
         public String[] getValues() {
             return new String[] {"properties", "xml"};
         }
@@ -203,6 +201,7 @@
      *
      * @exception BuildException if an error occurs
      */
+    @Override
     public void execute() throws BuildException {
         ClassLoader al = createLoader();
 
@@ -224,23 +223,22 @@
                 setResource(makeResourceFromURI(uri1));
             } else {
                 throw new BuildException(
-                        "Only antlib URIs can be located from the URI alone,"
-                                + " not the URI '" + getURI() + "'");
+                    "Only antlib URIs can be located from the URI alone, not the URI '"
+                        + getURI() + "'");
             }
         }
 
         if (name != null) {
             if (classname == null) {
-                throw new BuildException(
-                    "classname attribute of " + getTaskName() + " element "
-                    + "is undefined", getLocation());
+                throw new BuildException("classname attribute of "
+                    + getTaskName() + " element is undefined", getLocation());
             }
             addDefinition(al, name, classname);
         } else {
             if (classname != null) {
-                String msg = "You must not specify classname "
-                    + "together with file or resource.";
-                throw new BuildException(msg, getLocation());
+                throw new BuildException(
+                    "You must not specify classname together with file or resource.",
+                    getLocation());
             }
             final Enumeration<URL> urls;
             if (file == null) {
@@ -264,21 +262,19 @@
                 if (fmt == Format.PROPERTIES) {
                     loadProperties(al, url);
                     break;
+                } else if (RESOURCE_STACK.get().get(url) != null) {
+                    log("Warning: Recursive loading of " + url
+                        + " ignored"
+                        + " at " + getLocation()
+                        + " originally loaded at "
+                        + RESOURCE_STACK.get().get(url),
+                        Project.MSG_WARN);
                 } else {
-                    if (RESOURCE_STACK.get().get(url) != null) {
-                        log("Warning: Recursive loading of " + url
-                            + " ignored"
-                            + " at " + getLocation()
-                            + " originally loaded at "
-                            + RESOURCE_STACK.get().get(url),
-                            Project.MSG_WARN);
-                    } else {
-                        try {
-                            RESOURCE_STACK.get().put(url, getLocation());
-                            loadAntlib(al, url);
-                        } finally {
-                            RESOURCE_STACK.get().remove(url);
-                        }
+                    try {
+                        RESOURCE_STACK.get().put(url, getLocation());
+                        loadAntlib(al, url);
+                    } finally {
+                        RESOURCE_STACK.get().remove(url);
                     }
                 }
             }
@@ -291,7 +287,6 @@
      * @param uri the xml namespace uri that to convert.
      * @return the name of a resource. It may not exist
      */
-
     public static String makeResourceFromURI(String uri) {
         String path = uri.substring(MagicNames.ANTLIB_PREFIX.length());
         String resource;
@@ -301,7 +296,7 @@
             resource = path.substring("//".length());
             if (!resource.endsWith(".xml")) {
                 //if we haven't already named an XML file, it gets antlib.xml
-                resource = resource + ANTLIB_XML;
+                resource += ANTLIB_XML;
             }
         } else {
             //convert from a package to a path
@@ -320,7 +315,7 @@
      */
     private URL fileToURL() {
         String message = null;
-        if (!(file.exists())) {
+        if (!file.exists()) {
             message = "File " + file + " does not exist";
         }
         if (message == null && !(file.isFile())) {
@@ -392,9 +387,7 @@
      * @param url the url to get the definitions from
      */
     protected void loadProperties(ClassLoader al, URL url) {
-        InputStream is = null;
-        try {
-            is = url.openStream();
+        try (InputStream is = url.openStream()) {
             if (is == null) {
                 log("Could not load definitions from " + url,
                     Project.MSG_WARN);
@@ -402,16 +395,13 @@
             }
             Properties props = new Properties();
             props.load(is);
-            Enumeration<?> keys = props.keys();
-            while (keys.hasMoreElements()) {
-                name = ((String) keys.nextElement());
+            for (String key : props.stringPropertyNames()) {
+                name = key;
                 classname = props.getProperty(name);
                 addDefinition(al, name, classname);
             }
         } catch (IOException ex) {
             throw new BuildException(ex, getLocation());
-        } finally {
-            FileUtils.close(is);
         }
     }
 
@@ -473,12 +463,12 @@
         if (definerSet) {
             tooManyDefinitions();
         }
-        if (!antlib.startsWith("antlib:")) {
+        if (!antlib.startsWith(MagicNames.ANTLIB_PREFIX)) {
             throw new BuildException(
-                "Invalid antlib attribute - it must start with antlib:");
+                "Invalid antlib attribute - it must start with " + MagicNames.ANTLIB_PREFIX);
         }
         setURI(antlib);
-        this.resource = antlib.substring("antlib:".length()).replace('.', '/')
+        this.resource = antlib.substring(MagicNames.ANTLIB_PREFIX.length()).replace('.', '/')
             + "/antlib.xml";
         definerSet = true;
     }
@@ -560,7 +550,6 @@
         this.adaptToClass = adaptToClass;
     }
 
-
     /**
      * Add a definition using the attributes of Definer
      *
@@ -602,15 +591,16 @@
                 ComponentHelper.getComponentHelper(getProject())
                         .addDataTypeDefinition(def);
             } catch (ClassNotFoundException cnfe) {
-                String msg = getTaskName() + " class " + classname
-                        + " cannot be found"
-                        + "\n using the classloader " + al;
-                throw new BuildException(msg, cnfe, getLocation());
+                throw new BuildException(
+                    getTaskName() + " class " + classname
+                        + " cannot be found\n using the classloader " + al,
+                    cnfe, getLocation());
             } catch (NoClassDefFoundError ncdfe) {
-                String msg = getTaskName() + " A class needed by class "
-                        + classname + " cannot be found: " + ncdfe.getMessage()
-                        + "\n using the classloader " + al;
-                throw new BuildException(msg, ncdfe, getLocation());
+                throw new BuildException(
+                    getTaskName() + " A class needed by class " + classname
+                        + " cannot be found: " + ncdfe.getMessage()
+                        + "\n using the classloader " + al,
+                    ncdfe, getLocation());
             }
         } catch (BuildException ex) {
             switch (onError) {
@@ -634,7 +624,7 @@
      */
     private void tooManyDefinitions() {
         throw new BuildException(
-            "Only one of the attributes name, file and resource"
-            + " can be set", getLocation());
+            "Only one of the attributes name, file and resource can be set",
+            getLocation());
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java
index f887695..82d84e1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Delete.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,9 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Iterator;
@@ -60,7 +63,6 @@
 import org.apache.tools.ant.types.selectors.SizeSelector;
 import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.SymbolicLinkUtils;
 
 /**
  * Deletes a file or directory, or set of files defined by a fileset.
@@ -79,33 +81,41 @@
 public class Delete extends MatchingTask {
     private static final ResourceComparator REVERSE_FILESYSTEM = new Reverse(new FileSystem());
     private static final ResourceSelector EXISTS = new Exists();
+    private static FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     private static class ReverseDirs implements ResourceCollection {
-        static final Comparator<Comparable<?>> REVERSE = new Comparator<Comparable<?>>() {
-            public int compare(Comparable<?> foo, Comparable<?> bar) {
-                return ((Comparable) foo).compareTo(bar) * -1;
-            }
-        };
+
         private Project project;
         private File basedir;
         private String[] dirs;
+
         ReverseDirs(Project project, File basedir, String[] dirs) {
             this.project = project;
             this.basedir = basedir;
             this.dirs = dirs;
-            Arrays.sort(this.dirs, REVERSE);
+            Arrays.sort(this.dirs, Comparator.reverseOrder());
         }
+
+        @Override
         public Iterator<Resource> iterator() {
             return new FileResourceIterator(project, basedir, dirs);
         }
-        public boolean isFilesystemOnly() { return true; }
-        public int size() { return dirs.length; }
+
+        @Override
+        public boolean isFilesystemOnly() {
+            return true;
+        }
+
+        @Override
+        public int size() {
+            return dirs.length;
+        }
     }
 
     // CheckStyle:VisibilityModifier OFF - bc
     protected File file = null;
     protected File dir = null;
-    protected Vector<FileSet> filesets = new Vector<FileSet>();
+    protected Vector<FileSet> filesets = new Vector<>();
     protected boolean usedMatchingTask = false;
     // by default, remove matching empty dirs
     protected boolean includeEmpty = false;
@@ -117,9 +127,6 @@
     private boolean deleteOnExit = false;
     private boolean removeNotFollowedSymlinks = false;
     private Resources rcs = null;
-    private static FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    private static SymbolicLinkUtils SYMLINK_UTILS =
-        SymbolicLinkUtils.getSymbolicLinkUtils();
     private boolean performGc = Os.isFamily("windows");
 
     /**
@@ -175,9 +182,9 @@
      *
      * @param failonerror true or false
      */
-     public void setFailOnError(boolean failonerror) {
-         this.failonerror = failonerror;
-     }
+    public void setFailOnError(boolean failonerror) {
+        this.failonerror = failonerror;
+    }
 
     /**
      * If true, on failure to delete, note the error and set
@@ -185,10 +192,9 @@
      *
      * @param deleteOnExit true or false
      */
-     public void setDeleteOnExit(boolean deleteOnExit) {
-         this.deleteOnExit = deleteOnExit;
-     }
-
+    public void setDeleteOnExit(boolean deleteOnExit) {
+        this.deleteOnExit = deleteOnExit;
+    }
 
     /**
      * If true, delete empty directories.
@@ -213,10 +219,10 @@
         performGc = b;
     }
 
-   /**
-    * Adds a set of files to be deleted.
-    * @param set the set of files to be deleted
-    */
+    /**
+     * Adds a set of files to be deleted.
+     * @param set the set of files to be deleted
+     */
     public void addFileset(FileSet set) {
         filesets.addElement(set);
     }
@@ -240,6 +246,7 @@
      * add a name entry on the include list
      * @return a NameEntry object to be configured
      */
+    @Override
     public PatternSet.NameEntry createInclude() {
         usedMatchingTask = true;
         return super.createInclude();
@@ -249,6 +256,7 @@
      * add a name entry on the include files list
      * @return a PatternFileNameEntry object to be configured
      */
+    @Override
     public PatternSet.NameEntry createIncludesFile() {
         usedMatchingTask = true;
         return super.createIncludesFile();
@@ -258,6 +266,7 @@
      * add a name entry on the exclude list
      * @return a NameEntry object to be configured
      */
+    @Override
     public PatternSet.NameEntry createExclude() {
         usedMatchingTask = true;
         return super.createExclude();
@@ -267,6 +276,7 @@
      * add a name entry on the include files list
      * @return a PatternFileNameEntry object to be configured
      */
+    @Override
     public PatternSet.NameEntry createExcludesFile() {
         usedMatchingTask = true;
         return super.createExcludesFile();
@@ -276,6 +286,7 @@
      * add a set of patterns
      * @return PatternSet object to be configured
      */
+    @Override
     public PatternSet createPatternSet() {
         usedMatchingTask = true;
         return super.createPatternSet();
@@ -287,6 +298,7 @@
      *
      * @param includes the string containing the include patterns
      */
+    @Override
     public void setIncludes(String includes) {
         usedMatchingTask = true;
         super.setIncludes(includes);
@@ -298,6 +310,7 @@
      *
      * @param excludes the string containing the exclude patterns
      */
+    @Override
     public void setExcludes(String excludes) {
         usedMatchingTask = true;
         super.setExcludes(excludes);
@@ -310,6 +323,7 @@
      *                           should be used, "false"|"off"|"no" when they
      *                           shouldn't be used.
      */
+    @Override
     public void setDefaultexcludes(boolean useDefaultExcludes) {
         usedMatchingTask = true;
         super.setDefaultexcludes(useDefaultExcludes);
@@ -321,6 +335,7 @@
      * @param includesfile A string containing the filename to fetch
      * the include patterns from.
      */
+    @Override
     public void setIncludesfile(File includesfile) {
         usedMatchingTask = true;
         super.setIncludesfile(includesfile);
@@ -332,6 +347,7 @@
      * @param excludesfile A string containing the filename to fetch
      * the include patterns from.
      */
+    @Override
     public void setExcludesfile(File excludesfile) {
         usedMatchingTask = true;
         super.setExcludesfile(excludesfile);
@@ -343,6 +359,7 @@
      * @param isCaseSensitive "true"|"on"|"yes" if file system is case
      *                           sensitive, "false"|"off"|"no" when not.
      */
+    @Override
     public void setCaseSensitive(boolean isCaseSensitive) {
         usedMatchingTask = true;
         super.setCaseSensitive(isCaseSensitive);
@@ -353,6 +370,7 @@
      *
      * @param followSymlinks whether or not symbolic links should be followed
      */
+    @Override
     public void setFollowSymlinks(boolean followSymlinks) {
         usedMatchingTask = true;
         super.setFollowSymlinks(followSymlinks);
@@ -374,6 +392,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addSelector(SelectSelector selector) {
         usedMatchingTask = true;
         super.addSelector(selector);
@@ -384,6 +403,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addAnd(AndSelector selector) {
         usedMatchingTask = true;
         super.addAnd(selector);
@@ -394,6 +414,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addOr(OrSelector selector) {
         usedMatchingTask = true;
         super.addOr(selector);
@@ -404,6 +425,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addNot(NotSelector selector) {
         usedMatchingTask = true;
         super.addNot(selector);
@@ -414,6 +436,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addNone(NoneSelector selector) {
         usedMatchingTask = true;
         super.addNone(selector);
@@ -424,6 +447,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addMajority(MajoritySelector selector) {
         usedMatchingTask = true;
         super.addMajority(selector);
@@ -434,6 +458,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addDate(DateSelector selector) {
         usedMatchingTask = true;
         super.addDate(selector);
@@ -444,6 +469,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addSize(SizeSelector selector) {
         usedMatchingTask = true;
         super.addSize(selector);
@@ -454,6 +480,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addFilename(FilenameSelector selector) {
         usedMatchingTask = true;
         super.addFilename(selector);
@@ -464,6 +491,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addCustom(ExtendSelector selector) {
         usedMatchingTask = true;
         super.addCustom(selector);
@@ -474,6 +502,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addContains(ContainsSelector selector) {
         usedMatchingTask = true;
         super.addContains(selector);
@@ -484,6 +513,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addPresent(PresentSelector selector) {
         usedMatchingTask = true;
         super.addPresent(selector);
@@ -494,6 +524,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addDepth(DepthSelector selector) {
         usedMatchingTask = true;
         super.addDepth(selector);
@@ -504,6 +535,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addDepend(DependSelector selector) {
         usedMatchingTask = true;
         super.addDepend(selector);
@@ -514,6 +546,7 @@
      *
      * @param selector the selector to be added
      */
+    @Override
     public void addContainsRegexp(ContainsRegexpSelector selector) {
         usedMatchingTask = true;
         super.addContainsRegexp(selector);
@@ -525,6 +558,7 @@
      * @param selector the selector to add
      * @since ant 1.6
      */
+    @Override
     public void addModified(ModifiedSelector selector) {
         usedMatchingTask = true;
         super.addModified(selector);
@@ -536,6 +570,7 @@
      * @param selector the selector to be added
      * @since Ant 1.6
      */
+    @Override
     public void add(FileSelector selector) {
         usedMatchingTask = true;
         super.add(selector);
@@ -546,20 +581,21 @@
      *
      * @exception BuildException if an error occurs
      */
+    @Override
     public void execute() throws BuildException {
         if (usedMatchingTask) {
-            log("DEPRECATED - Use of the implicit FileSet is deprecated.  "
-                + "Use a nested fileset element instead.", quiet ? Project.MSG_VERBOSE : verbosity);
+            log("DEPRECATED - Use of the implicit FileSet is deprecated.  Use a nested fileset element instead.",
+                quiet ? Project.MSG_VERBOSE : verbosity);
         }
 
-        if (file == null && dir == null && filesets.size() == 0 && rcs == null) {
-            throw new BuildException("At least one of the file or dir "
-                                     + "attributes, or a nested resource collection, "
-                                     + "must be set.");
+        if (file == null && dir == null && filesets.isEmpty() && rcs == null) {
+            throw new BuildException(
+                "At least one of the file or dir attributes, or a nested resource collection, must be set.");
         }
 
         if (quiet && failonerror) {
-            throw new BuildException("quiet and failonerror cannot both be set to true", getLocation());
+            throw new BuildException(
+                "quiet and failonerror cannot both be set to true", getLocation());
         }
 
         // delete the single file
@@ -567,8 +603,8 @@
             if (file.exists()) {
                 if (file.isDirectory()) {
                     log("Directory " + file.getAbsolutePath()
-                        + " cannot be removed using the file attribute.  "
-                        + "Use dir instead.", quiet ? Project.MSG_VERBOSE : verbosity);
+                        + " cannot be removed using the file attribute.  Use dir instead.",
+                        quiet ? Project.MSG_VERBOSE : verbosity);
                 } else {
                     log("Deleting: " + file.getAbsolutePath());
 
@@ -626,11 +662,10 @@
             filesets.add(implicit);
         }
 
-        final int size = filesets.size();
         for (FileSet fs : filesets) {
             if (fs.getProject() == null) {
-                log("Deleting fileset with no project specified;"
-                    + " assuming executing project", Project.MSG_VERBOSE);
+                log("Deleting fileset with no project specified; assuming executing project",
+                    Project.MSG_VERBOSE);
                 fs = (FileSet) fs.clone();
                 fs.setProject(getProject());
             }
@@ -649,19 +684,22 @@
                 // iterating, capture the results now and store them
                 final String[] files = ds.getIncludedFiles();
                 resourcesToDelete.add(new ResourceCollection() {
-                        public boolean isFilesystemOnly() {
-                            return true;
-                        }
+                    @Override
+                    public boolean isFilesystemOnly() {
+                        return true;
+                    }
 
-                        public int size() {
-                            return files.length;
-                        }
+                    @Override
+                    public int size() {
+                        return files.length;
+                    }
 
-                        public Iterator<Resource> iterator() {
-                            return new FileResourceIterator(getProject(),
-                                                            fsDir, files);
-                        }
-                    });
+                    @Override
+                    public Iterator<Resource> iterator() {
+                        return new FileResourceIterator(getProject(),
+                                fsDir, files);
+                    }
+                });
                 if (includeEmpty) {
                     filesetDirs.add(new ReverseDirs(getProject(), fsDir,
                             ds.getIncludedDirectories()));
@@ -672,12 +710,17 @@
                     if (n.length > 0) {
                         String[] links = new String[n.length];
                         System.arraycopy(n, 0, links, 0, n.length);
-                        Arrays.sort(links, ReverseDirs.REVERSE);
+                        Arrays.sort(links, Comparator.reverseOrder());
                         for (String link : links) {
-                            try {
-                                SYMLINK_UTILS.deleteSymbolicLink(new File(link), this);
-                            } catch (java.io.IOException ex) {
-                                handle(ex);
+                            final Path filePath = Paths.get(link);
+                            if (!Files.isSymbolicLink(filePath)) {
+                                // it's not a symbolic link, so move on
+                                continue;
+                            }
+                            // it's a symbolic link, so delete it
+                            final boolean deleted = filePath.toFile().delete();
+                            if (!deleted) {
+                                handle("Could not delete symbolic link at " + filePath);
                             }
                         }
                     }
@@ -704,7 +747,7 @@
                     if (!f.exists()) {
                         continue;
                     }
-                    if (!(f.isDirectory()) || f.list().length == 0) {
+                    if (!f.isDirectory() || f.list().length == 0) {
                         log("Deleting " + f, verbosity);
                         if (!delete(f) && failonerror) {
                             handle("Unable to delete "
@@ -832,14 +875,13 @@
         }
     }
 
-    private boolean isDanglingSymlink(File f) {
-        try {
-            return SYMLINK_UTILS.isDanglingSymbolicLink(f);
-        } catch (java.io.IOException e) {
-            log("Error while trying to detect " + f.getAbsolutePath()
-                + " as broken symbolic link. " + e.getMessage(),
-                quiet ? Project.MSG_VERBOSE : verbosity);
+    private boolean isDanglingSymlink(final File f) {
+        if (!Files.isSymbolicLink(f.toPath())) {
+            // it's not a symlink, so clearly it's not a dangling one
             return false;
         }
+        // it's a symbolic link, now  check the existence of the (target) file (by "following links")
+        final boolean targetFileExists = Files.exists(f.toPath());
+        return !targetFileExists;
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Deltree.java b/src/main/org/apache/tools/ant/taskdefs/Deltree.java
index 8657d76..5c36f5b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Deltree.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Deltree.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
@@ -72,33 +71,26 @@
 
             log("Deleting: " + dir.getAbsolutePath());
 
-            try {
-                removeDir(dir);
-            } catch (IOException ioe) {
-                String msg = "Unable to delete " + dir.getAbsolutePath();
-                throw new BuildException(msg, getLocation());
-            }
+            removeDir(dir);
         }
     }
 
-    private void removeDir(File dir) throws IOException {
+    private void removeDir(File dir) {
 
         // check to make sure that the given dir isn't a symlink
         // the comparison of absolute path and canonical path
         // catches this
 
-        //        if (dir.getCanonicalPath().equals(dir.getAbsolutePath())) {
+        // if (dir.getCanonicalPath().equals(dir.getAbsolutePath())) {
         // (costin) It will not work if /home/costin is symlink to
-        // /da0/home/costin ( taz for example )
+        // /da0/home/costin (taz for example)
         for (String s : dir.list()) {
             File f = new File(dir, s);
             if (f.isDirectory()) {
                 removeDir(f);
-            } else {
-                if (!f.delete()) {
-                    throw new BuildException("Unable to delete file "
-                                             + f.getAbsolutePath());
-                }
+            } else if (!f.delete()) {
+                throw new BuildException("Unable to delete file "
+                        + f.getAbsolutePath());
             }
         }
         if (!dir.delete()) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/DependSet.java b/src/main/org/apache/tools/ant/taskdefs/DependSet.java
index 549e0ff..c6bc151 100644
--- a/src/main/org/apache/tools/ant/taskdefs/DependSet.java
+++ b/src/main/org/apache/tools/ant/taskdefs/DependSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,6 +38,7 @@
 import org.apache.tools.ant.types.resources.selectors.Exists;
 import org.apache.tools.ant.types.resources.selectors.Not;
 import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * Examines and removes out of date target files.  If any of the target files
@@ -102,12 +103,15 @@
         private HideMissingBasedir(FileSet fs) {
             this.fs = fs;
         }
+        @Override
         public Iterator<Resource> iterator() {
             return basedirExists() ? fs.iterator() : Resources.EMPTY_ITERATOR;
         }
+        @Override
         public int size() {
             return basedirExists() ? fs.size() : 0;
         }
+        @Override
         public boolean isFilesystemOnly() {
             return true;
         }
@@ -191,6 +195,7 @@
      * Execute the task.
      * @throws BuildException if errors occur.
      */
+    @Override
     public void execute() throws BuildException {
         if (sources == null) {
           throw new BuildException(
@@ -201,12 +206,11 @@
               "At least one set of target files must be specified");
         }
         //no sources = nothing to compare; no targets = nothing to delete:
-        if (sources.size() > 0 && targets.size() > 0 && !uptodate(sources, targets)) {
+        if (!sources.isEmpty() && !targets.isEmpty() && !uptodate(sources, targets)) {
            log("Deleting all target files.", Project.MSG_VERBOSE);
            if (verbose) {
-               String[] t = targets.list();
-               for (int i = 0; i < t.length; i++) {
-                   log("Deleting " + t[i]);
+               for (String t : targets.list()) {
+                   log("Deleting " + t);
                }
            }
            Delete delete = new Delete();
@@ -222,7 +226,7 @@
         datesel.setMillis(System.currentTimeMillis());
         datesel.setWhen(TimeComparison.AFTER);
         // don't whine because a file has changed during the last
-        // second (or whathever our current granularity may be)
+        // second (or whatever our current granularity may be)
         datesel.setGranularity(0);
         logFuture(targets, datesel);
 
@@ -245,7 +249,7 @@
             logMissing(missingSources, "source");
             return false;
         }
-        Resource newestSource = (Resource) getNewest(sources);
+        Resource newestSource = getNewest(sources);
         logWithModificationTime(newestSource, "newest source");
         return oldestTarget.getLastModified() >= newestSource.getLastModified();
     }
@@ -260,19 +264,7 @@
     }
 
     private Resource getXest(ResourceCollection rc, ResourceComparator c) {
-        Iterator<Resource> i = rc.iterator();
-        if (!i.hasNext()) {
-            return null;
-
-        }
-        Resource xest = i.next();
-        while (i.hasNext()) {
-            Resource next = i.next();
-            if (c.compare(xest, next) < 0) {
-                xest = next;
-            }
-        }
-        return xest;
+        return StreamUtils.iteratorAsStream(rc.iterator()).max(c).orElse(null);
     }
 
     private Resource getOldest(ResourceCollection rc) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/DiagnosticsTask.java b/src/main/org/apache/tools/ant/taskdefs/DiagnosticsTask.java
index c745cfb..0504492 100644
--- a/src/main/org/apache/tools/ant/taskdefs/DiagnosticsTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/DiagnosticsTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/Dirname.java b/src/main/org/apache/tools/ant/taskdefs/Dirname.java
index 9e085e7..8a17065 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Dirname.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Dirname.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -68,15 +68,14 @@
      * Execute this task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         if (property == null) {
             throw new BuildException("property attribute required", getLocation());
         }
         if (file == null) {
             throw new BuildException("file attribute required", getLocation());
-        } else {
-            String value = file.getParent();
-            getProject().setNewProperty(property, value);
         }
+        getProject().setNewProperty(property, file.getParent());
     }
 }
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/taskdefs/Ear.java b/src/main/org/apache/tools/ant/taskdefs/Ear.java
index 6e08ecd..1adb811 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Ear.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Ear.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,6 +55,7 @@
      * @deprecated since 1.5.x.
      *             Use setDestFile(destfile) instead.
      */
+    @Deprecated
     public void setEarfile(File earFile) {
         setDestFile(earFile);
     }
@@ -66,9 +67,9 @@
     public void setAppxml(File descr) {
         deploymentDescriptor = descr;
         if (!deploymentDescriptor.exists()) {
-            throw new BuildException("Deployment descriptor: "
-                                     + deploymentDescriptor
-                                     + " does not exist.");
+            throw new BuildException(
+                "Deployment descriptor: %s does not exist.",
+                deploymentDescriptor);
         }
 
         // Create a ZipFileSet for this file, and pass it up.
@@ -78,7 +79,6 @@
         super.addFileset(fs);
     }
 
-
     /**
      * Adds zipfileset.
      *
@@ -91,13 +91,13 @@
         super.addFileset(fs);
     }
 
-
     /**
      * Initialize the output stream.
      * @param zOut the zip output stream.
      * @throws IOException on I/O errors
      * @throws BuildException on other errors
      */
+    @Override
     protected void initZipOutputStream(ZipOutputStream zOut)
         throws IOException, BuildException {
         // If no webxml file is specified, it's an error.
@@ -116,6 +116,7 @@
      * @param mode the Unix permissions to set.
      * @throws IOException on error
      */
+    @Override
     protected void zipFile(File file, ZipOutputStream zOut, String vPath,
                            int mode)
         throws IOException {
@@ -147,6 +148,7 @@
      * Make sure we don't think we already have a application.xml next
      * time this task gets executed.
      */
+    @Override
     protected void cleanUp() {
         descriptorAdded = false;
         super.cleanUp();
diff --git a/src/main/org/apache/tools/ant/taskdefs/Echo.java b/src/main/org/apache/tools/ant/taskdefs/Echo.java
index f1e13c8..de65994 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Echo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Echo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,7 +31,6 @@
 import org.apache.tools.ant.types.resources.LogOutputResource;
 import org.apache.tools.ant.types.resources.StringResource;
 import org.apache.tools.ant.util.ResourceUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Writes a message to the Ant logging facilities.
@@ -61,15 +60,12 @@
      * @exception BuildException if something goes wrong with the build
      */
     public void execute() throws BuildException {
-        final String msg = "".equals(message) ? StringUtils.LINE_SEP : message;
         try {
-            ResourceUtils
-                    .copyResource(new StringResource(msg), output == null
-                                  ? new LogOutputResource(this, logLevel)
-                                  : output,
-                                  null, null, false, false, append, null,
-                                  "".equals(encoding) ? null : encoding,
-                                  getProject(), force);
+            ResourceUtils.copyResource(
+                    new StringResource(message.isEmpty() ? System.lineSeparator() : message),
+                    output == null ? new LogOutputResource(this, logLevel) : output,
+                    null, null, false, false, append, null,
+                    encoding.isEmpty() ? null : encoding, getProject(), force);
         } catch (IOException ioe) {
             throw new BuildException(ioe, getLocation());
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/EchoXML.java b/src/main/org/apache/tools/ant/taskdefs/EchoXML.java
index 5524c0d..1203c3a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/EchoXML.java
+++ b/src/main/org/apache/tools/ant/taskdefs/EchoXML.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.OutputStream;
 
 import org.apache.tools.ant.BuildException;
@@ -58,7 +57,7 @@
 
     /**
      * Set the namespace policy for the xml file
-     * @param n namespace policy: "ignore," "elementsOnly," or "all"
+     * @param n namespace policy: "ignore", "elementsOnly", or "all"
      * @see org.apache.tools.ant.util.DOMElementWriter.XmlNamespacePolicy
      */
     public void setNamespacePolicy(NamespacePolicy n) {
@@ -77,26 +76,19 @@
      * Execute the task.
      */
     public void execute() {
-        DOMElementWriter writer =
-            new DOMElementWriter(!append, namespacePolicy.getPolicy());
-        OutputStream os = null;
-        try {
-            if (file != null) {
-                os = new FileOutputStream(file.getAbsolutePath(), append);
-            } else {
-                os = new LogOutputStream(this, Project.MSG_INFO);
-            }
-            Node n = getFragment().getFirstChild();
-            if (n == null) {
-                throw new BuildException(ERROR_NO_XML);
-            }
+        Node n = getFragment().getFirstChild();
+        if (n == null) {
+            throw new BuildException(ERROR_NO_XML);
+        }
+
+        DOMElementWriter writer = new DOMElementWriter(!append, namespacePolicy.getPolicy());
+        try (OutputStream os = (file == null) ? new LogOutputStream(this, Project.MSG_INFO)
+                : FileUtils.newOutputStream(file.toPath(), append)) {
             writer.write((Element) n, os);
-        } catch (BuildException e) {
-            throw e;
+        } catch (BuildException be) {
+            throw be;
         } catch (Exception e) {
             throw new BuildException(e);
-        } finally {
-            FileUtils.close(os);
         }
     }
 
@@ -114,6 +106,7 @@
         public NamespacePolicy(String s) {
             setValue(s);
         }
+
         /** {@inheritDoc}. */
         @Override
         public String[] getValues() {
@@ -124,14 +117,15 @@
             String s = getValue();
             if (IGNORE.equalsIgnoreCase(s)) {
                 return DOMElementWriter.XmlNamespacePolicy.IGNORE;
-            } else if (ELEMENTS.equalsIgnoreCase(s)) {
+            }
+            if (ELEMENTS.equalsIgnoreCase(s)) {
                 return
                     DOMElementWriter.XmlNamespacePolicy.ONLY_QUALIFY_ELEMENTS;
-            } else if (ALL.equalsIgnoreCase(s)) {
-                return DOMElementWriter.XmlNamespacePolicy.QUALIFY_ALL;
-            } else {
-                throw new BuildException("Invalid namespace policy: " + s);
             }
+            if (ALL.equalsIgnoreCase(s)) {
+                return DOMElementWriter.XmlNamespacePolicy.QUALIFY_ALL;
+            }
+            throw new BuildException("Invalid namespace policy: " + s);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Exec.java b/src/main/org/apache/tools/ant/taskdefs/Exec.java
index 8247023..8e2b5bb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Exec.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Exec.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,6 +44,7 @@
  *             delegate to {@link org.apache.tools.ant.taskdefs.Execute Execute}
  *             instead.
  */
+@Deprecated
 public class Exec extends Task {
     private String os;
     private String out;
@@ -63,13 +64,14 @@
             + "the Exec class");
         System.err.println("is considered to be dead code by the Ant "
             + "developers and is unmaintained.");
-        System.err.println("Don\'t use it!");
+        System.err.println("Don't use it!");
     }
 
     /**
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         run(command);
     }
@@ -160,9 +162,8 @@
             if (err != 0) {
                 if (failOnError) {
                     throw new BuildException("Exec returned: " + err, getLocation());
-                } else {
-                    log("Result: " + err, Project.MSG_ERR);
                 }
+                log("Result: " + err, Project.MSG_ERR);
             }
         } catch (IOException ioe) {
             throw new BuildException("Error exec: " + command, ioe, getLocation());
@@ -262,6 +263,7 @@
             }
         }
 
+        @Override
         public void run() {
             try {
                 try {
diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecTask.java b/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
index 30f673a..eebf6ae 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -125,7 +125,7 @@
      */
     public void setTimeout(Integer value) {
         setTimeout(
-            (Long) ((value == null) ? null : new Long(value.intValue())));
+            (value == null) ? null : (long) value);
     }
 
     /**
@@ -168,8 +168,7 @@
      * @ant.attribute ignore="true"
      */
     public void setCommand(Commandline cmdl) {
-        log("The command attribute is deprecated.\n"
-            + "Please use the executable attribute and nested arg elements.",
+        log("The command attribute is deprecated.\nPlease use the executable attribute and nested arg elements.",
             Project.MSG_WARN);
         this.cmdl = cmdl;
     }
@@ -192,8 +191,8 @@
      */
     public void setInput(File input) {
         if (inputString != null) {
-            throw new BuildException("The \"input\" and \"inputstring\" "
-                + "attributes cannot both be specified");
+            throw new BuildException(
+                "The \"input\" and \"inputstring\" attributes cannot both be specified");
         }
         this.input = input;
         incompatibleWithSpawn = true;
@@ -206,8 +205,8 @@
      */
     public void setInputString(String inputString) {
         if (input != null) {
-            throw new BuildException("The \"input\" and \"inputstring\" "
-                + "attributes cannot both be specified");
+            throw new BuildException(
+                "The \"input\" and \"inputstring\" attributes cannot both be specified");
         }
         this.inputString = inputString;
         incompatibleWithSpawn = true;
@@ -382,6 +381,36 @@
     }
 
     /**
+     * Whether output should be discarded.
+     *
+     * <p>Defaults to false.</p>
+     *
+     * @param discard
+     *            if true output streams are discarded.
+     *
+     * @since Ant 1.10.10
+     * @see #setDiscardError
+     */
+    public void setDiscardOutput(final boolean discard) {
+        redirector.setDiscardOutput(discard);
+    }
+
+    /**
+     * Whether error output should be discarded.
+     *
+     * <p>Defaults to false.</p>
+     *
+     * @param discard
+     *            if true error streams are discarded.
+     *
+     * @since Ant 1.10.10
+     * @see #setDiscardOutput
+     */
+    public void setDiscardError(final boolean discard) {
+        redirector.setDiscardError(discard);
+    }
+
+    /**
      * Add a <code>RedirectorElement</code> to this task.
      *
      * @param redirectorElement   <code>RedirectorElement</code>.
@@ -485,6 +514,7 @@
      * <li>this list is not exhaustive or limitative</li>
      * </ul>
      */
+    @Override
     public void execute() throws BuildException {
         // Quick fail if this is not a valid OS for the command
         if (!isValidOs()) {
@@ -634,9 +664,8 @@
                 String msg = "Timeout: killed the sub-process";
                 if (failOnError) {
                     throw new BuildException(msg);
-                } else {
-                    log(msg, Project.MSG_WARN);
                 }
+                log(msg, Project.MSG_WARN);
             }
             maybeSetResultPropertyValue(returnCode);
             redirector.complete();
@@ -644,9 +673,8 @@
                 if (failOnError) {
                     throw new BuildException(getTaskType() + " returned: "
                         + returnCode, getLocation());
-                } else {
-                    log("Result: " + returnCode, Project.MSG_ERR);
                 }
+                log("Result: " + returnCode, Project.MSG_ERR);
             }
         } else {
             exe.spawn();
@@ -673,9 +701,8 @@
             if (failIfExecFails) {
                 throw new BuildException("Execute failed: " + e.toString(), e,
                                          getLocation());
-            } else {
-                log("Execute failed: " + e.toString(), Project.MSG_ERR);
             }
+            log("Execute failed: " + e.toString(), Project.MSG_ERR);
         } finally {
             // close the output file if required
             logFlush();
@@ -702,7 +729,7 @@
      */
     protected ExecuteWatchdog createWatchdog() throws BuildException {
         return (timeout == null)
-            ? null : new ExecuteWatchdog(timeout.longValue());
+            ? null : new ExecuteWatchdog(timeout);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/Execute.java b/src/main/org/apache/tools/ant/taskdefs/Execute.java
index 9b4c268..402f3c7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Execute.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Execute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,11 +24,10 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.StringReader;
-import java.util.ArrayList;
+import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -38,7 +37,6 @@
 import org.apache.tools.ant.taskdefs.launcher.CommandLauncher;
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Runs an external program.
@@ -54,18 +52,6 @@
      */
     public static final int INVALID = Integer.MAX_VALUE;
 
-    private String[] cmdl = null;
-    private String[] env = null;
-    private int exitValue = INVALID;
-    private ExecuteStreamHandler streamHandler;
-    private final ExecuteWatchdog watchdog;
-    private File workingDirectory = null;
-    private Project project = null;
-    private boolean newEnvironment = false;
-
-    /** Controls whether the VM is used to launch commands, where possible. */
-    private boolean useVMLauncher = true;
-
     private static String antWorkingDirectory = System.getProperty("user.dir");
     private static Map<String, String> procEnvironment = null;
 
@@ -81,6 +67,18 @@
         }
     }
 
+    private String[] cmdl = null;
+    private String[] env = null;
+    private int exitValue = INVALID;
+    private ExecuteStreamHandler streamHandler;
+    private final ExecuteWatchdog watchdog;
+    private File workingDirectory = null;
+    private Project project = null;
+    private boolean newEnvironment = false;
+
+    /** Controls whether the VM is used to launch commands, where possible. */
+    private boolean useVMLauncher = true;
+
     /**
      * Set whether or not you want the process to be spawned.
      * Default is not spawned.
@@ -104,7 +102,7 @@
      * @return a map containing the environment variables.
      * @since Ant 1.8.2
      */
-    public static synchronized Map<String,String> getEnvironmentVariables() {
+    public static synchronized Map<String, String> getEnvironmentVariables() {
         if (procEnvironment != null) {
             return procEnvironment;
         }
@@ -117,7 +115,7 @@
             }
         }
 
-        procEnvironment = new LinkedHashMap<String, String>();
+        procEnvironment = new LinkedHashMap<>();
         try {
             ByteArrayOutputStream out = new ByteArrayOutputStream();
             Execute exe = new Execute(new PumpStreamHandler(out));
@@ -135,33 +133,33 @@
                 procEnvironment = getVMSLogicals(in);
                 return procEnvironment;
             }
-            String var = null;
-            String line, lineSep = StringUtils.LINE_SEP;
+            StringBuilder var = null;
+            String line;
             while ((line = in.readLine()) != null) {
-                if (line.indexOf('=') == -1) {
-                    // Chunk part of previous env var (UNIX env vars can
-                    // contain embedded new lines).
-                    if (var == null) {
-                        var = lineSep + line;
-                    } else {
-                        var += lineSep + line;
-                    }
-                } else {
+                if (line.contains("=")) {
                     // New env var...append the previous one if we have it.
                     if (var != null) {
-                        int eq = var.indexOf("=");
+                        int eq = var.toString().indexOf('=');
                         procEnvironment.put(var.substring(0, eq),
                                             var.substring(eq + 1));
                     }
-                    var = line;
+                    var = new StringBuilder(line);
+                } else {
+                    // Chunk part of previous env var (UNIX env vars can
+                    // contain embedded new lines).
+                    if (var == null) {
+                        var = new StringBuilder(System.lineSeparator() + line);
+                    } else {
+                        var.append(System.lineSeparator()).append(line);
+                    }
                 }
             }
             // Since we "look ahead" before adding, there's one last env var.
             if (var != null) {
-                int eq = var.indexOf("=");
+                int eq = var.toString().indexOf('=');
                 procEnvironment.put(var.substring(0, eq), var.substring(eq + 1));
             }
-        } catch (java.io.IOException exc) {
+        } catch (IOException exc) {
             exc.printStackTrace(); //NOSONAR
             // Just try to see how much we got
         }
@@ -177,10 +175,8 @@
      */
     @Deprecated
     public static synchronized Vector<String> getProcEnvironment() {
-        Vector<String> v = new Vector<String>();
-        for (Entry<String, String> entry : getEnvironmentVariables().entrySet()) {
-            v.add(entry.getKey() + "=" + entry.getValue());
-        }
+        Vector<String> v = new Vector<>();
+        getEnvironmentVariables().forEach((key, value) -> v.add(key + "=" + value));
         return v;
     }
 
@@ -195,16 +191,17 @@
         if (Os.isFamily("os/2")) {
             // OS/2 - use same mechanism as Windows 2000
             return new String[] {"cmd", "/c", "set"};
-        } else if (Os.isFamily("windows")) {
+        }
+        if (Os.isFamily("windows")) {
             // Determine if we're running under XP/2000/NT or 98/95
             if (Os.isFamily("win9x")) {
                 // Windows 98/95
                 return new String[] {"command.com", "/c", "set"};
-            } else {
-                // Windows XP/2000/NT/2003
-                return new String[] {"cmd", "/c", "set"};
             }
-        } else if (Os.isFamily("z/os") || Os.isFamily("unix")) {
+            // Windows XP/2000/NT/2003
+            return new String[] {"cmd", "/c", "set"};
+        }
+        if (Os.isFamily("z/os") || Os.isFamily("unix")) {
             // On most systems one could use: /bin/sh -c env
 
             // Some systems have /bin/env, others /usr/bin/env, just try
@@ -218,16 +215,17 @@
                 cmd[0] = "env";
             }
             return cmd;
-        } else if (Os.isFamily("netware") || Os.isFamily("os/400")) {
+        }
+        if (Os.isFamily("netware") || Os.isFamily("os/400")) {
             // rely on PATH
             return new String[] {"env"};
-        } else if (Os.isFamily("openvms")) {
-            return new String[] {"show", "logical"};
-        } else {
-            // MAC OS 9 and previous
-            // TODO: I have no idea how to get it, someone must fix it
-            return null;
         }
+        if (Os.isFamily("openvms")) {
+            return new String[] {"show", "logical"};
+        }
+        // MAC OS 9 and previous
+        // TODO: I have no idea how to get it, someone must fix it
+        return null;
     }
 
     /**
@@ -244,13 +242,13 @@
         if (Os.isFamily("z/os")) {
             try {
                 return bos.toString("Cp1047");
-            } catch (java.io.UnsupportedEncodingException e) {
+            } catch (UnsupportedEncodingException e) {
                 // noop default encoding used
             }
         } else if (Os.isFamily("os/400")) {
             try {
                 return bos.toString("Cp500");
-            } catch (java.io.UnsupportedEncodingException e) {
+            } catch (UnsupportedEncodingException e) {
                 // noop default encoding used
             }
         }
@@ -417,7 +415,7 @@
                                  String[] env, File dir, boolean useVM)
         throws IOException {
         if (dir != null && !dir.exists()) {
-            throw new BuildException(dir + " doesn't exist.");
+            throw new BuildException("%s doesn't exist.", dir);
         }
 
         CommandLauncher vmLauncher = CommandLauncher.getVMLauncher(project);
@@ -430,12 +428,12 @@
      * Runs a process defined by the command line and returns its exit status.
      *
      * @return the exit status of the subprocess or <code>INVALID</code>.
-     * @exception java.io.IOException The exception is thrown, if launching
+     * @exception IOException The exception is thrown, if launching
      *            of the subprocess failed.
      */
     public int execute() throws IOException {
         if (workingDirectory != null && !workingDirectory.exists()) {
-            throw new BuildException(workingDirectory + " doesn't exist.");
+            throw new BuildException("%s doesn't exist.", workingDirectory);
         }
         final Process process = launch(project, getCommandline(),
                                        getEnvironment(), workingDirectory,
@@ -486,13 +484,13 @@
      * Starts a process defined by the command line.
      * Ant will not wait for this process, nor log its output.
      *
-     * @throws java.io.IOException The exception is thrown, if launching
+     * @throws IOException The exception is thrown, if launching
      *            of the subprocess failed.
      * @since Ant 1.6
      */
     public void spawn() throws IOException {
         if (workingDirectory != null && !workingDirectory.exists()) {
-            throw new BuildException(workingDirectory + " doesn't exist.");
+            throw new BuildException("%s doesn't exist.", workingDirectory);
         }
         final Process process = launch(project, getCommandline(),
                                        getEnvironment(), workingDirectory,
@@ -611,7 +609,7 @@
             return env;
         }
         Map<String, String> osEnv =
-            new LinkedHashMap<String, String>(getEnvironmentVariables());
+            new LinkedHashMap<>(getEnvironmentVariables());
         for (String keyValue : env) {
             String key = keyValue.substring(0, keyValue.indexOf('='));
             // Find the key in the current environment copy
@@ -623,7 +621,7 @@
 
                 for (String osEnvItem : osEnv.keySet()) {
                     // Nb: using default locale as key is a env name
-                    if (osEnvItem.toLowerCase().equals(key.toLowerCase())) {
+                    if (osEnvItem.equalsIgnoreCase(key)) {
                         // Use the original case of the key
                         key = osEnvItem;
                         break;
@@ -635,11 +633,8 @@
             osEnv.put(key, keyValue.substring(key.length() + 1));
         }
 
-        ArrayList<String> l = new ArrayList<String>();
-        for (Entry<String, String> entry : osEnv.entrySet()) {
-            l.add(entry.getKey() + "=" + entry.getValue());
-        }
-        return l.toArray(new String[osEnv.size()]);
+        return osEnv.entrySet().stream()
+            .map(e -> e.getKey() + "=" + e.getValue()).toArray(String[]::new);
     }
 
     /**
@@ -650,7 +645,7 @@
      * @param cmdline The command to execute.
      * @throws BuildException if the command does not exit successfully.
      */
-    public static void runCommand(Task task, String[] cmdline)
+    public static void runCommand(Task task, String... cmdline)
         throws BuildException {
         try {
             task.log(Commandline.describeCommand(cmdline),
@@ -664,7 +659,7 @@
                 throw new BuildException(cmdline[0]
                     + " failed with return code " + retval, task.getLocation());
             }
-        } catch (java.io.IOException exc) {
+        } catch (IOException exc) {
             throw new BuildException("Could not launch " + cmdline[0] + ": "
                 + exc, task.getLocation());
         }
@@ -694,9 +689,9 @@
      */
     private static Map<String, String> getVMSLogicals(BufferedReader in)
         throws IOException {
-        HashMap<String, String> logicals = new HashMap<String, String>();
+        Map<String, String> logicals = new HashMap<>();
         String logName = null, logValue = null, newLogName;
-        String line = null;
+        String line;
         // CheckStyle:MagicNumber OFF
         while ((line = in.readLine()) != null) {
             // parse the VMS logicals into required format ("VAR=VAL[,VAL2]")
diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java
index 08fd8cd..0964c91 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -97,6 +97,7 @@
      * @deprecated since 1.4.x.
      *             manage output at the task level.
      */
+    @Deprecated
     public void setOutput(PrintStream out) {
     }
 
@@ -122,7 +123,7 @@
             if (sysProperties != null) {
                 sysProperties.setSystem();
             }
-            Class<?> target = null;
+            Class<?> target;
             try {
                 if (classpath == null) {
                     target = Class.forName(classname);
@@ -137,18 +138,18 @@
                     target = Class.forName(classname, true, loader);
                 }
             } catch (ClassNotFoundException e) {
-                throw new BuildException("Could not find " + classname + "."
-                                         + " Make sure you have it in your"
-                                         + " classpath");
+                throw new BuildException(
+                    "Could not find %s. Make sure you have it in your classpath",
+                    classname);
             }
-            main = target.getMethod("main", new Class[] {String[].class});
+            main = target.getMethod("main", String[].class);
             if (main == null) {
-                throw new BuildException("Could not find main() method in "
-                                         + classname);
+                throw new BuildException("Could not find main() method in %s",
+                    classname);
             }
             if ((main.getModifiers() & Modifier.STATIC) == 0) {
-                throw new BuildException("main() method in " + classname
-                    + " is not declared static");
+                throw new BuildException(
+                    "main() method in %s is not declared static", classname);
             }
             if (timeout == null) {
                 run(); //NOSONAR
@@ -163,7 +164,7 @@
                 // main thread will still be there to let the new thread
                 // finish
                 thread.setDaemon(true);
-                Watchdog w = new Watchdog(timeout.longValue());
+                Watchdog w = new Watchdog(timeout);
                 w.addTimeoutObserver(this);
                 synchronized (this) {
                     thread.start();
@@ -187,12 +188,7 @@
             if (caught != null) {
                 throw caught;
             }
-        } catch (BuildException e) {
-            throw e;
-        } catch (SecurityException e) {
-            throw e;
-        } catch (ThreadDeath e) {
-            // TODO could perhaps also call thread.stop(); not sure if anyone cares
+        } catch (BuildException | ThreadDeath | SecurityException e) {
             throw e;
         } catch (Throwable e) {
             throw new BuildException(e);
@@ -212,6 +208,7 @@
      * Run this ExecuteJava in a Thread.
      * @since Ant 1.5
      */
+    @Override
     public void run() {
         final Object[] argument = {javaCommand.getArguments()};
         try {
@@ -242,6 +239,7 @@
      * @param w the responsible Watchdog.
      * @since Ant 1.5
      */
+    @Override
     public synchronized void timeoutOccured(Watchdog w) {
         if (thread != null) {
             timedOut = true;
@@ -286,7 +284,7 @@
             = new Execute(redirector.createHandler(),
                           timeout == null
                           ? null
-                          : new ExecuteWatchdog(timeout.longValue()));
+                          : new ExecuteWatchdog(timeout));
         exe.setAntRun(pc.getProject());
         if (Os.isFamily("openvms")) {
             setupCommandLineForVMS(exe, cmdl.getCommandline());
diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java
index 44a7977..bbc9dbb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,9 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.Vector;
 
@@ -61,8 +63,9 @@
     // switching type to "dir" when we encounter a DirSet that would
     // be more difficult to achieve otherwise.
 
-    protected Vector<AbstractFileSet> filesets = new Vector<AbstractFileSet>(); // contains AbstractFileSet
-                                              // (both DirSet and FileSet)
+    // (both DirSet and FileSet)
+    protected Vector<AbstractFileSet> filesets = new Vector<>();
+
     private Union resources = null;
     private boolean relative = false;
     private boolean parallel = false;
@@ -248,7 +251,7 @@
      */
     public Commandline.Marker createSrcfile() {
         if (srcFilePos != null) {
-            throw new BuildException(getTaskType() + " doesn\'t support multiple "
+            throw new BuildException(getTaskType() + " doesn't support multiple "
                                      + "srcfile elements.", getLocation());
         }
         srcFilePos = cmdl.createMarker();
@@ -262,7 +265,7 @@
      */
     public Commandline.Marker createTargetfile() {
         if (targetFilePos != null) {
-            throw new BuildException(getTaskType() + " doesn\'t support multiple "
+            throw new BuildException(getTaskType() + " doesn't support multiple "
                                      + "targetfile elements.", getLocation());
         }
         targetFilePos = cmdl.createMarker();
@@ -297,6 +300,7 @@
     /**
      * Check the configuration of this ExecuteOn instance.
      */
+    @Override
     protected void checkConfiguration() {
 //     * @TODO using taskName here is brittle, as a user could override it.
 //     *       this should probably be modified to use the classname instead.
@@ -304,7 +308,7 @@
             log("!! execon is deprecated. Use apply instead. !!");
         }
         super.checkConfiguration();
-        if (filesets.size() == 0 && resources == null) {
+        if (filesets.isEmpty() && resources == null) {
             throw new BuildException("no resources specified",
                                      getLocation());
         }
@@ -327,6 +331,7 @@
      * @return <code>ExecuteStreamHandler</code>.
      * @throws BuildException on error.
      */
+    @Override
     protected ExecuteStreamHandler createHandler() throws BuildException {
         //if we have a RedirectorElement, return a decoy
         return (redirectorElement == null) ? super.createHandler() : new PumpStreamHandler();
@@ -335,6 +340,7 @@
     /**
      * Set up the I/O Redirector.
      */
+    @Override
     protected void setupRedirector() {
         super.setupRedirector();
         redirector.setAppendProperties(true);
@@ -345,23 +351,21 @@
      * @param exe the Execute instance representing the external process.
      * @throws BuildException on error
      */
+    @Override
     protected void runExec(Execute exe) throws BuildException {
         int totalFiles = 0;
         int totalDirs = 0;
         boolean haveExecuted = false;
         try {
-            Vector<String> fileNames = new Vector<String>();
-            Vector<File> baseDirs = new Vector<File>();
-            final int size = filesets.size();
-            for (int i = 0; i < size; i++) {
+            Vector<String> fileNames = new Vector<>();
+            Vector<File> baseDirs = new Vector<>();
+            for (AbstractFileSet fs : filesets) {
                 String currentType = type;
-                AbstractFileSet fs = filesets.elementAt(i);
                 if (fs instanceof DirSet) {
                     if (!FileDirBoth.DIR.equals(type)) {
                         log("Found a nested dirset but type is " + type + ". "
-                            + "Temporarily switching to type=\"dir\" on the"
-                            + " assumption that you really did mean"
-                            + " <dirset> not <fileset>.", Project.MSG_DEBUG);
+                            + "Temporarily switching to type=\"dir\" on the assumption that you really did mean <dirset> not <fileset>.",
+                            Project.MSG_DEBUG);
                         currentType = FileDirBoth.DIR;
                     }
                 }
@@ -383,21 +387,19 @@
                         baseDirs.add(base);
                     }
                 }
-                if (fileNames.size() == 0 && skipEmpty) {
+                if (fileNames.isEmpty() && skipEmpty) {
                     logSkippingFileset(currentType, ds, base);
                     continue;
                 }
                 if (!parallel) {
-                    String[] s = new String[fileNames.size()];
-                    fileNames.copyInto(s);
-                    for (int j = 0; j < s.length; j++) {
-                        String[] command = getCommandline(s[j], base);
+                    for (String srcFile : fileNames) {
+                        String[] command = getCommandline(srcFile, base);
                         log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
                         exe.setCommandline(command);
 
                         if (redirectorElement != null) {
                             setupRedirector();
-                            redirectorElement.configure(redirector, s[j]);
+                            redirectorElement.configure(redirector, srcFile);
                         }
                         if (redirectorElement != null || haveExecuted) {
                             // need to reset the stream handler to restart
@@ -408,8 +410,8 @@
                         runExecute(exe);
                         haveExecuted = true;
                     }
-                    fileNames.removeAllElements();
-                    baseDirs.removeAllElements();
+                    fileNames.clear();
+                    baseDirs.clear();
                 }
             }
 
@@ -463,12 +465,12 @@
                         }
                         runExecute(exe);
                         haveExecuted = true;
-                        fileNames.removeAllElements();
-                        baseDirs.removeAllElements();
+                        fileNames.clear();
+                        baseDirs.clear();
                     }
                 }
             }
-            if (parallel && (fileNames.size() > 0 || !skipEmpty)) {
+            if (parallel && (!fileNames.isEmpty() || !skipEmpty)) {
                 runParallel(exe, fileNames, baseDirs);
                 haveExecuted = true;
             }
@@ -513,31 +515,31 @@
      */
     protected String[] getCommandline(String[] srcFiles, File[] baseDirs) {
         final char fileSeparator = File.separatorChar;
-        Vector<String> targets = new Vector<String>();
+        List<String> targets = new ArrayList<>();
         if (targetFilePos != null) {
-            Set<String> addedFiles = new HashSet<String>();
+            Set<String> addedFiles = new HashSet<>();
             for (String srcFile : srcFiles) {
                 String[] subTargets = mapper.mapFileName(srcFile);
                 if (subTargets != null) {
-                    for (int j = 0; j < subTargets.length; j++) {
-                        String name = null;
-                        if (!relative) {
-                            name = new File(destDir, subTargets[j]).getAbsolutePath();
+                    for (String subTarget : subTargets) {
+                        String name;
+                        if (relative) {
+                            name = subTarget;
                         } else {
-                            name = subTargets[j];
+                            name = new File(destDir, subTarget).getAbsolutePath();
                         }
                         if (forwardSlash && fileSeparator != '/') {
                             name = name.replace(fileSeparator, '/');
                         }
                         if (!addedFiles.contains(name)) {
-                            targets.addElement(name);
+                            targets.add(name);
                             addedFiles.add(name);
                         }
                     }
                 }
             }
         }
-        String[] targetFiles = (String[]) targets.toArray(new String[targets.size()]);
+        String[] targetFiles = targets.toArray(new String[0]);
 
         if (!addSourceFile) {
             srcFiles = new String[0];
@@ -613,8 +615,8 @@
             if (forwardSlash && fileSeparator != '/') {
                 src = src.replace(fileSeparator, '/');
             }
-            if (srcFilePos != null && (srcFilePos.getPrefix().length() > 0
-                    || srcFilePos.getSuffix().length() > 0)) {
+            if (srcFilePos != null
+                    && (!srcFilePos.getPrefix().isEmpty() || !srcFilePos.getSuffix().isEmpty())) {
                 src = srcFilePos.getPrefix() + src + srcFilePos.getSuffix();
             }
             result[srcIndex + i] = src;
@@ -685,10 +687,8 @@
     protected void runParallel(Execute exe, Vector<String> fileNames,
                                Vector<File> baseDirs)
         throws IOException, BuildException {
-        String[] s = new String[fileNames.size()];
-        fileNames.copyInto(s);
-        File[] b = new File[baseDirs.size()];
-        baseDirs.copyInto(b);
+        String[] s = fileNames.toArray(new String[0]);
+        File[] b = baseDirs.toArray(new File[0]);
 
         if (maxParallel <= 0 || s.length == 0 /* this is skipEmpty == false */) {
             String[] command = getCommandline(s, b);
@@ -739,7 +739,7 @@
                                           String[] arguments,
                                           int insertPosition,
                                           String prefix, String suffix) {
-        if (prefix.length() == 0 && suffix.length() == 0) {
+        if (prefix.isEmpty() && suffix.isEmpty()) {
             System.arraycopy(targetFiles, 0, arguments, insertPosition,
                              targetFiles.length);
         } else {
@@ -759,11 +759,13 @@
         public static final String FILE = "file";
         /** Dir value */
         public static final String DIR = "dir";
+
         /**
+         * {@inheritDoc}
          * @see EnumeratedAttribute#getValues
          */
-        /** {@inheritDoc}. */
-       public String[] getValues() {
+        @Override
+        public String[] getValues() {
             return new String[] {FILE, DIR, "both"};
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java
index 1c5f973..0e91ff6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java
index cc3933e..7a29668 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -74,6 +74,7 @@
      *             Use constructor with a long type instead.
      * (1.4.x compatibility)
      */
+    @Deprecated
     public ExecuteWatchdog(int timeout) {
         this((long) timeout);
     }
@@ -81,7 +82,7 @@
     /**
      * Watches the given process and terminates it, if it runs for too long.
      * All information from the previous run are reset.
-     * @param process the process to monitor. It cannot be <tt>null</tt>
+     * @param process the process to monitor. It cannot be <code>null</code>
      * @throws IllegalStateException if a process is still being monitored.
      */
     public synchronized void start(Process process) {
@@ -112,6 +113,7 @@
      * This can be called in the watchdog thread
      * @param w the watchdog
      */
+    @Override
     public synchronized void timeoutOccured(Watchdog w) {
         try {
             try {
@@ -158,8 +160,8 @@
 
     /**
      * Indicates whether or not the watchdog is still monitoring the process.
-     * @return  <tt>true</tt> if the process is still running, otherwise
-     *          <tt>false</tt>.
+     * @return  <code>true</code> if the process is still running, otherwise
+     *          <code>false</code>.
      */
     public boolean isWatching() {
         return watch;
@@ -167,11 +169,10 @@
 
     /**
      * Indicates whether the last process run was killed on timeout or not.
-     * @return  <tt>true</tt> if the process was killed otherwise
-     *          <tt>false</tt>.
+     * @return  <code>true</code> if the process was killed otherwise
+     *          <code>false</code>.
      */
     public boolean killedProcess() {
         return killedProcess;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/Exit.java b/src/main/org/apache/tools/ant/taskdefs/Exit.java
index 3f82302..6ef274b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Exit.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Exit.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -50,12 +50,13 @@
 public class Exit extends Task {
 
     private static class NestedCondition extends ConditionBase implements Condition {
+        @Override
         public boolean eval() {
             if (countConditions() != 1) {
                 throw new BuildException(
                     "A single nested condition is required.");
             }
-            return ((Condition) (getConditions().nextElement())).eval();
+            return getConditions().nextElement().eval();
         }
     }
 
@@ -116,7 +117,7 @@
      * @param i   the <code>int</code> status
      */
     public void setStatus(int i) {
-        status = Integer.valueOf(i);
+        status = i;
     }
 
     /**
@@ -131,20 +132,19 @@
      * the if and unless parameters (if present).
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         boolean fail = (nestedConditionPresent()) ? testNestedCondition()
                      : (testIfCondition() && testUnlessCondition());
         if (fail) {
             String text = null;
-            if (message != null && message.trim().length() > 0) {
+            if (message != null && !message.trim().isEmpty()) {
                 text = message.trim();
             } else {
-                if (ifCondition != null && !"".equals(ifCondition)
-                    && testIfCondition()) {
+                if (!isNullOrEmpty(ifCondition) && testIfCondition()) {
                     text = "if=" + ifCondition;
                 }
-                if (unlessCondition != null && !"".equals(unlessCondition)
-                    && testUnlessCondition()) {
+                if (!isNullOrEmpty(unlessCondition) && testUnlessCondition()) {
                     if (text == null) {
                         text = "";
                     } else {
@@ -154,18 +154,20 @@
                 }
                 if (nestedConditionPresent()) {
                     text = "condition satisfied";
-                } else {
-                    if (text == null) {
-                        text = "No message";
-                    }
+                } else if (text == null) {
+                    text = "No message";
                 }
             }
             log("failing due to " + text, Project.MSG_DEBUG);
-            throw ((status == null) ? new BuildException(text)
-             : new ExitStatusException(text, status.intValue()));
+            throw status == null ? new BuildException(text)
+                : new ExitStatusException(text, status);
         }
     }
 
+    private boolean isNullOrEmpty(Object value) {
+        return value == null || "".equals(value);
+    }
+
     /**
      * Set a multiline message.
      * @param msg the message to display
@@ -217,8 +219,8 @@
         boolean result = nestedConditionPresent();
 
         if (result && ifCondition != null || unlessCondition != null) {
-            throw new BuildException("Nested conditions "
-                + "not permitted in conjunction with if/unless attributes");
+            throw new BuildException(
+                "Nested conditions not permitted in conjunction with if/unless attributes");
         }
 
         return result && nestedCondition.eval();
diff --git a/src/main/org/apache/tools/ant/taskdefs/Expand.java b/src/main/org/apache/tools/ant/taskdefs/Expand.java
index 039f203..19f27fb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Expand.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Expand.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,13 +20,14 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.Vector;
 
@@ -58,12 +59,19 @@
  *           name="unwar"
  */
 public class Expand extends Task {
+    public static final String NATIVE_ENCODING = "native-encoding";
+
+    /** Error message when more that one mapper is defined */
+    public static final String ERROR_MULTIPLE_MAPPERS = "Cannot define more than one mapper";
+
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
     private static final int BUFFER_SIZE = 1024;
     private File dest; //req
     private File source; // req
     private boolean overwrite = true;
     private Mapper mapperElement = null;
-    private Vector<PatternSet> patternsets = new Vector<PatternSet>();
+    private List<PatternSet> patternsets = new Vector<>();
     private Union resources = new Union();
     private boolean resourcesSpecified = false;
     private boolean failOnEmptyArchive = false;
@@ -71,13 +79,7 @@
     private boolean scanForUnicodeExtraFields = true;
     private Boolean allowFilesToEscapeDest = null;
 
-    public static final String NATIVE_ENCODING = "native-encoding";
-
     private String encoding;
-    /** Error message when more that one mapper is defined */
-    public static final String ERROR_MULTIPLE_MAPPERS = "Cannot define more than one mapper";
-
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     /**
      * Creates an Expand instance and sets encoding to UTF-8.
@@ -121,14 +123,15 @@
      *
      * @exception BuildException Thrown in unrecoverable error.
      */
+    @Override
     public void execute() throws BuildException {
         if ("expand".equals(getTaskType())) {
             log("!! expand is deprecated. Use unzip instead. !!");
         }
 
         if (source == null && !resourcesSpecified) {
-            throw new BuildException("src attribute and/or resources must be "
-                                     + "specified");
+            throw new BuildException(
+                "src attribute and/or resources must be specified");
         }
 
         if (dest == null) {
@@ -144,13 +147,14 @@
             if (source.isDirectory()) {
                 throw new BuildException("Src must not be a directory."
                     + " Use nested filesets instead.", getLocation());
-            } else if (!source.exists()) {
-                throw new BuildException("src '" + source + "' doesn't exist.");
-            } else if (!source.canRead()) {
-                throw new BuildException("src '" + source + "' cannot be read.");
-            } else {
-                expandFile(FILE_UTILS, source, dest);
             }
+            if (!source.exists()) {
+                throw new BuildException("src '" + source + "' doesn't exist.");
+            }
+            if (!source.canRead()) {
+                throw new BuildException("src '" + source + "' cannot be read.");
+            }
+            expandFile(FILE_UTILS, source, dest);
         }
         for (Resource r : resources) {
             if (!r.isExists()) {
@@ -176,7 +180,6 @@
      */
     protected void expandFile(FileUtils fileUtils, File srcF, File dir) {
         log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO);
-        ZipFile zf = null;
         FileNameMapper mapper = getMapper();
         if (!srcF.exists()) {
             throw new BuildException("Unable to expand "
@@ -184,13 +187,12 @@
                     + " as the file does not exist",
                     getLocation());
         }
-        try {
-            zf = new ZipFile(srcF, encoding, scanForUnicodeExtraFields);
+        try (ZipFile zf = new ZipFile(srcF, encoding, scanForUnicodeExtraFields)) {
             boolean empty = true;
-            Enumeration<ZipEntry> e = zf.getEntries();
-            while (e.hasMoreElements()) {
+            Enumeration<ZipEntry> entries = zf.getEntries();
+            while (entries.hasMoreElements()) {
+                ZipEntry ze = entries.nextElement();
                 empty = false;
-                ZipEntry ze = e.nextElement();
                 InputStream is = null;
                 log("extracting " + ze.getName(), Project.MSG_DEBUG);
                 try {
@@ -203,7 +205,7 @@
                 }
             }
             if (empty && getFailOnEmptyArchive()) {
-                throw new BuildException("archive '" + srcF + "' is empty");
+                throw new BuildException("archive '%s' is empty", srcF);
             }
             log("expand complete", Project.MSG_VERBOSE);
         } catch (IOException ioe) {
@@ -211,8 +213,6 @@
                 "Error while expanding " + srcF.getPath()
                 + "\n" + ioe.toString(),
                 ioe);
-        } finally {
-            ZipFile.closeQuietly(zf);
         }
     }
 
@@ -223,8 +223,8 @@
      * @param dir       the destination directory
      */
     protected void expandResource(Resource srcR, File dir) {
-        throw new BuildException("only filesystem based resources are"
-                                 + " supported by this task.");
+        throw new BuildException(
+            "only filesystem based resources are supported by this task.");
     }
 
     /**
@@ -232,13 +232,10 @@
      * @return a filenamemapper for a file
      */
     protected FileNameMapper getMapper() {
-        FileNameMapper mapper = null;
         if (mapperElement != null) {
-            mapper = mapperElement.getImplementation();
-        } else {
-            mapper = new IdentityMapper();
+            return mapperElement.getImplementation();
         }
-        return mapper;
+        return new IdentityMapper();
     }
 
     // CheckStyle:ParameterNumberCheck OFF - bc
@@ -260,7 +257,7 @@
                                boolean isDirectory, FileNameMapper mapper)
                                throws IOException {
 
-        final boolean entryNameStartsWithPathSpec = entryName.length() > 0
+        final boolean entryNameStartsWithPathSpec = !entryName.isEmpty()
             && (entryName.charAt(0) == File.separatorChar
                 || entryName.charAt(0) == '/'
                 || entryName.charAt(0) == '\\');
@@ -272,13 +269,12 @@
         boolean allowedOutsideOfDest = Boolean.TRUE == getAllowFilesToEscapeDest()
             || null == getAllowFilesToEscapeDest() && !stripAbsolutePathSpec && entryNameStartsWithPathSpec;
 
-        if (patternsets != null && patternsets.size() > 0) {
+        if (patternsets != null && !patternsets.isEmpty()) {
             String name = entryName.replace('/', File.separatorChar)
                 .replace('\\', File.separatorChar);
 
-            boolean included = false;
-            Set<String> includePatterns = new HashSet<String>();
-            Set<String> excludePatterns = new HashSet<String>();
+            Set<String> includePatterns = new HashSet<>();
+            Set<String> excludePatterns = new HashSet<>();
             for (PatternSet p : patternsets) {
                 String[] incls = p.getIncludePatterns(getProject());
                 if (incls == null || incls.length == 0) {
@@ -308,20 +304,23 @@
                 }
             }
 
-            for (Iterator<String> iter = includePatterns.iterator();
-                 !included && iter.hasNext();) {
-                String pattern = iter.next();
-                included = SelectorUtils.matchPath(pattern, name);
+            boolean included = false;
+            for (String pattern : includePatterns) {
+                if (SelectorUtils.matchPath(pattern, name)) {
+                    included = true;
+                    break;
+                }
             }
 
-            for (Iterator<String> iter = excludePatterns.iterator();
-                 included && iter.hasNext();) {
-                String pattern = iter.next();
-                included = !SelectorUtils.matchPath(pattern, name);
+            for (String pattern : excludePatterns) {
+                if (SelectorUtils.matchPath(pattern, name)) {
+                    included = false;
+                    break;
+                }
             }
 
             if (!included) {
-                //Do not process this file
+                // Do not process this file
                 log("skipping " + entryName
                     + " as it is excluded or not included.",
                     Project.MSG_VERBOSE);
@@ -359,20 +358,11 @@
                 f.mkdirs();
             } else {
                 byte[] buffer = new byte[BUFFER_SIZE];
-                int length = 0;
-                FileOutputStream fos = null;
-                try {
-                    fos = new FileOutputStream(f);
-
-                    while ((length =
-                            compressedInputStream.read(buffer)) >= 0) {
+                try (OutputStream fos = Files.newOutputStream(f.toPath())) {
+                    int length;
+                    while ((length = compressedInputStream.read(buffer)) >= 0) {
                         fos.write(buffer, 0, length);
                     }
-
-                    fos.close();
-                    fos = null;
-                } finally {
-                    FileUtils.close(fos);
                 }
             }
 
@@ -419,7 +409,7 @@
      * @param set a pattern set
      */
     public void addPatternset(PatternSet set) {
-        patternsets.addElement(set);
+        patternsets.add(set);
     }
 
     /**
@@ -544,7 +534,7 @@
      * Whether to allow the extracted file or directory to be outside of the dest directory.
      *
      * @param b the flag
-     * @since Ant 1.9.12
+     * @since Ant 1.10.4
      */
     public void setAllowFilesToEscapeDest(boolean b) {
         allowFilesToEscapeDest = b;
@@ -555,7 +545,7 @@
      *
      * @return {@code null} if the flag hasn't been set explicitly,
      * otherwise the value set by the user.
-     * @since Ant 1.9.12
+     * @since Ant 1.10.4
      */
     public Boolean getAllowFilesToEscapeDest() {
         return allowFilesToEscapeDest;
diff --git a/src/main/org/apache/tools/ant/taskdefs/Filter.java b/src/main/org/apache/tools/ant/taskdefs/Filter.java
index 390ba5b..78a5ebd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Filter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Filter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -69,6 +69,7 @@
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         boolean isFiltersFromFile =
             filtersFile != null && token == null && value == null;
@@ -76,9 +77,9 @@
             filtersFile == null && token != null && value != null;
 
         if (!isFiltersFromFile && !isSingleFilter) {
-            throw new BuildException("both token and value parameters, or "
-                                     + "only a filtersFile parameter is "
-                                     + "required", getLocation());
+            throw new BuildException(
+                "both token and value parameters, or only a filtersFile parameter is required",
+                getLocation());
         }
 
         if (isSingleFilter) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java b/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java
index 290fe66..cff7ed8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java
+++ b/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,11 +20,11 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.file.Files;
 import java.util.Enumeration;
 import java.util.NoSuchElementException;
 import java.util.Vector;
@@ -115,6 +115,7 @@
      * @return a Reader.
      * @since Ant 1.7?
      */
+    @Override
     public final Reader chain(final Reader rdr) {
         return filter.chain(rdr);
     }
@@ -181,15 +182,16 @@
      * @deprecated since 1.4.x.
      *             Use {@link #setEol setEol} instead.
      */
+    @Deprecated
     public void setCr(AddAsisRemove attr) {
         log("DEPRECATED: The cr attribute has been deprecated,",
             Project.MSG_WARN);
         log("Please use the eol attribute instead", Project.MSG_WARN);
         String option = attr.getValue();
         CrLf c = new CrLf();
-        if (option.equals("remove")) {
+        if ("remove".equals(option)) {
             c.setValue("lf");
-        } else if (option.equals("asis")) {
+        } else if ("asis".equals(option)) {
             c.setValue("asis");
         } else {
             // must be "add"
@@ -282,6 +284,7 @@
      * Executes the task.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
         // first off, make sure that we've got a srcdir and destdir
         validate();
@@ -321,22 +324,21 @@
         }
         if (!srcDir.exists()) {
             throw new BuildException(
-                FIXCRLF_ERROR + "srcdir does not exist: '" + srcDir + "'");
+                FIXCRLF_ERROR + "srcdir does not exist: '%s'", srcDir);
         }
         if (!srcDir.isDirectory()) {
             throw new BuildException(
-                FIXCRLF_ERROR + "srcdir is not a directory: '" + srcDir + "'");
+                FIXCRLF_ERROR + "srcdir is not a directory: '%s'", srcDir);
         }
         if (destDir != null) {
             if (!destDir.exists()) {
                 throw new BuildException(
-                    FIXCRLF_ERROR + "destdir does not exist: '"
-                    + destDir + "'");
+                    FIXCRLF_ERROR + "destdir does not exist: '%s'", destDir);
             }
             if (!destDir.isDirectory()) {
                 throw new BuildException(
-                    FIXCRLF_ERROR + "destdir is not a directory: '"
-                    + destDir + "'");
+                    FIXCRLF_ERROR + "destdir is not a directory: '%s'",
+                    destDir);
             }
         }
     }
@@ -349,7 +351,7 @@
         if (fcv == null) {
             FilterChain fc = new FilterChain();
             fc.add(filter);
-            fcv = new Vector<FilterChain>(1);
+            fcv = new Vector<>(1);
             fcv.add(fc);
         }
         File tmpFile = FILE_UTILS.createTempFile(getProject(), "fixcrlf", "", null, true, true);
@@ -390,6 +392,7 @@
      * Deprecated, the functionality has been moved to filters.FixCrLfFilter.
      * @deprecated since 1.7.0.
      */
+    @Deprecated
     protected class OneLiner implements Enumeration<Object> {
         private static final int UNDEF = -1;
         private static final int NOTJAVA = 0;
@@ -420,7 +423,7 @@
                 reader = new BufferedReader(
                     ((encoding == null) ? new FileReader(srcFile)
                     : new InputStreamReader(
-                    new FileInputStream(srcFile), encoding)), INBUFLEN);
+                    Files.newInputStream(srcFile.toPath()), encoding)), INBUFLEN);
 
                 nextLine();
             } catch (IOException e) {
@@ -465,7 +468,7 @@
                     switch (ch) {
                     case '\r':
                         ch = reader.read();
-                        if ((char) (ch) == '\n') {
+                        if ((char) ch == '\n') {
                             eolcount += 2;
                             eolStr.append("\r\n");
                         } else {
@@ -548,6 +551,7 @@
         /**
          * @return true if there is more elements.
          */
+        @Override
         public boolean hasMoreElements() {
             return !reachedEof;
         }
@@ -557,6 +561,7 @@
          * @return the next element.
          * @throws NoSuchElementException if there is no more.
          */
+        @Override
         public Object nextElement()
             throws NoSuchElementException {
             if (!hasMoreElements()) {
@@ -672,22 +677,24 @@
      */
     public static class AddAsisRemove extends EnumeratedAttribute {
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
             return new String[] {"add", "asis", "remove"};
         }
     }
 
     /**
-     * Enumerated attribute with the values "asis", "cr", "lf" and "crlf".
+     * Enumerated attribute with the values "asis", "cr", "lf", "crlf", "mac", "unix" and "dos.
      */
     public static class CrLf extends EnumeratedAttribute {
         /**
          * @see EnumeratedAttribute#getValues
          * {@inheritDoc}.
          */
+        @Override
         public String[] getValues() {
             return new String[] {"asis", "cr", "lf", "crlf", "mac", "unix",
-                    "dos"};
+                "dos"};
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/GUnzip.java b/src/main/org/apache/tools/ant/taskdefs/GUnzip.java
index b891bae..ead0f11 100644
--- a/src/main/org/apache/tools/ant/taskdefs/GUnzip.java
+++ b/src/main/org/apache/tools/ant/taskdefs/GUnzip.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,12 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.zip.GZIPInputStream;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Expands a file that has been compressed with the GZIP
@@ -44,6 +43,7 @@
      * Get the default extension.
      * @return the value ".gz"
      */
+    @Override
     protected String getDefaultExtension() {
         return DEFAULT_EXTENSION;
     }
@@ -51,18 +51,14 @@
     /**
      * Implement the gunzipping.
      */
+    @Override
     protected void extract() {
         if (srcResource.getLastModified() > dest.lastModified()) {
             log("Expanding " + srcResource.getName() + " to "
                         + dest.getAbsolutePath());
-
-            FileOutputStream out = null;
-            GZIPInputStream zIn = null;
-            InputStream fis = null;
-            try {
-                out = new FileOutputStream(dest);
-                fis = srcResource.getInputStream();
-                zIn = new GZIPInputStream(fis);
+            try (OutputStream out = Files.newOutputStream(dest.toPath());
+                    GZIPInputStream zIn =
+                        new GZIPInputStream(srcResource.getInputStream())) {
                 byte[] buffer = new byte[BUFFER_SIZE];
                 int count = 0;
                 do {
@@ -72,10 +68,6 @@
             } catch (IOException ioe) {
                 String msg = "Problem expanding gzip " + ioe.getMessage();
                 throw new BuildException(msg, ioe, getLocation());
-            } finally {
-                FileUtils.close(fis);
-                FileUtils.close(out);
-                FileUtils.close(zIn);
             }
         }
     }
@@ -91,6 +83,7 @@
      * @return true if this task supports non file resources.
      * @since Ant 1.7
      */
+    @Override
     protected boolean supportsNonFileResources() {
         return getClass().equals(GUnzip.class);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/GZip.java b/src/main/org/apache/tools/ant/taskdefs/GZip.java
index 029f414..0530a74 100644
--- a/src/main/org/apache/tools/ant/taskdefs/GZip.java
+++ b/src/main/org/apache/tools/ant/taskdefs/GZip.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,11 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.file.Files;
 import java.util.zip.GZIPOutputStream;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Compresses a file with the GZIP algorithm. Normally used to compress
@@ -38,16 +37,14 @@
     /**
      * perform the GZip compression operation.
      */
+    @Override
     protected void pack() {
-        GZIPOutputStream zOut = null;
-        try {
-            zOut = new GZIPOutputStream(new FileOutputStream(zipFile));
+        try (GZIPOutputStream zOut =
+            new GZIPOutputStream(Files.newOutputStream(zipFile.toPath()))) {
             zipResource(getSrcResource(), zOut);
         } catch (IOException ioe) {
             String msg = "Problem creating gzip " + ioe.getMessage();
             throw new BuildException(msg, ioe, getLocation());
-        } finally {
-            FileUtils.close(zOut);
         }
     }
 
@@ -62,6 +59,7 @@
      * @return true if this case supports non file resources.
      * @since Ant 1.7
      */
+    @Override
     protected boolean supportsNonFileResources() {
         return getClass().equals(GZip.class);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/GenerateKey.java b/src/main/org/apache/tools/ant/taskdefs/GenerateKey.java
index 14709a4..e713e86 100644
--- a/src/main/org/apache/tools/ant/taskdefs/GenerateKey.java
+++ b/src/main/org/apache/tools/ant/taskdefs/GenerateKey.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,11 @@
  */
 package org.apache.tools.ant.taskdefs;
 
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
@@ -83,7 +86,7 @@
      * A class corresponding to the dname nested element.
      */
     public static class DistinguishedName {
-        private Vector<DnameParam> params = new Vector<DnameParam>();
+        private List<DnameParam> params = new Vector<>();
 
         /**
          * Create a param nested element.
@@ -91,8 +94,7 @@
          */
         public Object createParam() {
             DnameParam param = new DnameParam();
-            params.addElement(param);
-
+            params.add(param);
             return param;
         }
 
@@ -101,7 +103,7 @@
          * @return an enumeration of the nested parameters.
          */
         public Enumeration<DnameParam> getParams() {
-            return params.elements();
+            return Collections.enumeration(params);
         }
 
         /**
@@ -111,26 +113,10 @@
          * This is used on the command line.
          * @return a string rep of this name
          */
+        @Override
         public String toString() {
-            final int size = params.size();
-            final StringBuffer sb = new StringBuffer();
-            boolean firstPass = true;
-
-            for (int i = 0; i < size; i++) {
-                if (!firstPass) {
-                    sb.append(" ,");
-                }
-                firstPass = false;
-
-                final DnameParam param = (DnameParam) params.elementAt(i);
-                if (param.isComplete()) {
-                    sb.append(encode(param.getName()));
-                    sb.append('=');
-                    sb.append(encode(param.getValue()));
-                }
-            }
-
-            return sb.toString();
+            return params.stream().map(p -> encode(p.getName()) + "=" + encode(p.getValue()))
+                .collect(Collectors.joining(", "));
         }
 
         /**
@@ -141,26 +127,7 @@
          * @return the encoded value.
          */
         public String encode(final String string) {
-            int end = string.indexOf(',');
-
-            if (-1 == end) {
-              return string;
-            }
-
-            final StringBuffer sb = new StringBuffer();
-
-            int start = 0;
-
-            while (-1 != end) {
-                sb.append(string.substring(start, end));
-                sb.append("\\,");
-                start = end + 1;
-                end = string.indexOf(',', start);
-            }
-
-            sb.append(string.substring(start));
-
-            return sb.toString();
+            return String.join("\\,", string.split(","));
         }
     }
 
@@ -198,12 +165,11 @@
      */
     public DistinguishedName createDname() throws BuildException {
         if (null != expandedDname) {
-            throw new BuildException("DName sub-element can only be "
-                                     + "specified once.");
+            throw new BuildException("DName sub-element can only be specified once.");
         }
         if (null != dname) {
-            throw new BuildException("It is not possible to specify dname "
-                                    + " both as attribute and element.");
+            throw new BuildException(
+                "It is not possible to specify dname  both as attribute and element.");
         }
         expandedDname = new DistinguishedName();
         return expandedDname;
@@ -216,8 +182,8 @@
      */
     public void setDname(final String dname) {
         if (null != expandedDname) {
-            throw new BuildException("It is not possible to specify dname "
-                                    + " both as attribute and element.");
+            throw new BuildException(
+                "It is not possible to specify dname  both as attribute and element.");
         }
         this.dname = dname;
     }
@@ -229,12 +195,7 @@
      * @since Ant 1.9.14
      */
     public void setSaname(final String saname) {
-        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_7)) {
-            this.saname = saname;
-        } else {
-            log("The SubjectAlternativeName extension is not available for "
-               +"the Java Version being used.");
-        }
+        this.saname = saname;
     }
 
     /**
@@ -340,6 +301,7 @@
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
 
         if (null == alias) {
@@ -354,7 +316,7 @@
             throw new BuildException("dname must be set");
         }
 
-        final StringBuffer sb = new StringBuffer();
+        final StringBuilder sb = new StringBuilder();
 
         sb.append("-genkey ");
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/Get.java b/src/main/org/apache/tools/ant/taskdefs/Get.java
index a939a70..03915cc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Get.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Get.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -27,7 +26,10 @@
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
+import java.nio.file.Files;
 import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.zip.GZIPInputStream;
 
 import org.apache.tools.ant.BuildException;
@@ -35,6 +37,7 @@
 import org.apache.tools.ant.Main;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.email.Header;
 import org.apache.tools.ant.types.Mapper;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
@@ -43,6 +46,7 @@
 import org.apache.tools.ant.types.resources.URLResource;
 import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Gets a particular file from a URL source.
@@ -90,6 +94,9 @@
                            DEFAULT_AGENT_PREFIX + "/"
                            + Main.getShortAntVersion());
 
+    // Store headers as key/value pair without duplicate in keys
+    private Map<String, String> headers = new LinkedHashMap<>();
+
     /**
      * Does the work.
      *
@@ -110,7 +117,7 @@
                     if (path.endsWith("/")) {
                         path = path.substring(0, path.length() - 1);
                     }
-                    final int slash = path.lastIndexOf("/");
+                    final int slash = path.lastIndexOf('/');
                     if (slash > -1) {
                         path = path.substring(slash + 1);
                     }
@@ -122,11 +129,13 @@
                         log("skipping " + r + " - mapper can't handle it",
                             Project.MSG_WARN);
                         continue;
-                    } else if (d.length == 0) {
+                    }
+                    if (d.length == 0) {
                         log("skipping " + r + " - mapper returns no file name",
                             Project.MSG_WARN);
                         continue;
-                    } else if (d.length > 1) {
+                    }
+                    if (d.length > 1) {
                         log("skipping " + r + " - mapper returns multiple file"
                             + " names", Project.MSG_WARN);
                         continue;
@@ -172,13 +181,9 @@
     public boolean doGet(final int logLevel, final DownloadProgress progress)
             throws IOException {
         checkAttributes();
-        for (final Resource r : sources) {
-            final URLProvider up = r.as(URLProvider.class);
-            final URL source = up.getURL();
-            return doGet(source, destination, logLevel, progress);
-        }
-        /*NOTREACHED*/
-        return false;
+        return doGet(sources.iterator().next().as(URLProvider.class).getURL(),
+                destination, logLevel, progress);
+
     }
 
     /**
@@ -208,7 +213,7 @@
             return true;
         }
 
-        //dont do any progress, unless asked
+        // don't do any progress, unless asked
         if (progress == null) {
             progress = new NullProgress();
         }
@@ -269,7 +274,7 @@
      */
     private void checkAttributes() {
 
-        if (userAgent == null || userAgent.trim().length() == 0) {
+        if (userAgent == null || userAgent.trim().isEmpty()) {
             throw new BuildException("userAgent may not be null or empty");
         }
 
@@ -280,8 +285,8 @@
         for (final Resource r : sources) {
             final URLProvider up = r.as(URLProvider.class);
             if (up == null) {
-                throw new BuildException("Only URLProvider resources are"
-                                         + " supported", getLocation());
+                throw new BuildException(
+                    "Only URLProvider resources are supported", getLocation());
             }
         }
 
@@ -291,9 +296,8 @@
 
         if (destination.exists() && sources.size() > 1
             && !destination.isDirectory()) {
-            throw new BuildException("The specified destination is not a"
-                                     + " directory",
-                                     getLocation());
+            throw new BuildException(
+                "The specified destination is not a directory", getLocation());
         }
 
         if (destination.exists() && !destination.canWrite()) {
@@ -384,7 +388,6 @@
         useTimestamp = v;
     }
 
-
     /**
      * Username for basic auth.
      *
@@ -407,7 +410,7 @@
      * If true, credentials are set when following a redirect to a new location.
      *
      * @param v "true" to enable sending the credentials on redirect; "false" otherwise
-     * @since Ant 1.9.17
+     * @since Ant 1.10.13
      */
     public void setAuthenticateOnRedirect(final boolean v) {
         this.authenticateOnRedirect = v;
@@ -496,6 +499,21 @@
     }
 
     /**
+     * Add a nested header
+     * @param header to be added
+     *
+     */
+    public void addConfiguredHeader(Header header) {
+        if (header != null) {
+            String key = StringUtils.trimToNull(header.getName());
+            String value = StringUtils.trimToNull(header.getValue());
+            if (key != null && value != null) {
+                this.headers.put(key, value);
+            }
+        }
+    }
+
+    /**
      * Define the mapper to map source to destination files.
      * @return a mapper to be configured.
      * @exception BuildException if more than one mapper is defined.
@@ -527,6 +545,18 @@
     }
 
     /**
+     * Does the response code represent a redirection?
+     *
+     * @since 1.10.10
+     */
+    public static boolean isMoved(final int responseCode) {
+        return responseCode == HttpURLConnection.HTTP_MOVED_PERM
+            || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
+            || responseCode == HttpURLConnection.HTTP_SEE_OTHER
+            || responseCode == HTTP_MOVED_TEMP;
+    }
+
+    /**
      * Interface implemented for reporting
      * progress of downloading.
      */
@@ -556,6 +586,7 @@
         /**
          * begin a download
          */
+        @Override
         public void beginDownload() {
         }
 
@@ -563,12 +594,14 @@
          * tick handler
          *
          */
+        @Override
         public void onTick() {
         }
 
         /**
          * end a download
          */
+        @Override
         public void endDownload() {
         }
     }
@@ -593,6 +626,7 @@
         /**
          * begin a download
          */
+        @Override
         public void beginDownload() {
             dots = 0;
         }
@@ -601,6 +635,7 @@
          * tick handler
          *
          */
+        @Override
         public void onTick() {
             out.print(".");
             if (dots++ > DOTS_PER_LINE) {
@@ -612,6 +647,7 @@
         /**
          * end a download
          */
+        @Override
         public void endDownload() {
             out.println();
             out.flush();
@@ -739,6 +775,12 @@
                 connection.setRequestProperty("Accept-Encoding", GZIP_CONTENT_ENCODING);
             }
 
+            for (final Map.Entry<String, String> header : headers.entrySet()) {
+                //we do not log the header value as it may contain sensitive data like passwords
+                log(String.format("Adding header '%s' ", header.getKey()));
+                connection.setRequestProperty(header.getKey(), header.getValue());
+            }
+
             if (connection instanceof HttpURLConnection) {
                 ((HttpURLConnection) connection).setInstanceFollowRedirects(false);
                 connection.setUseCaches(httpUseCaches);
@@ -786,9 +828,8 @@
                     if (ignoreErrors) {
                         log(message, logLevel);
                         return null;
-                    } else {
-                        throw new BuildException(message);
                     }
+                    throw new BuildException(message);
                 }
             }
 
@@ -800,13 +841,6 @@
             return connection;
         }
 
-        private boolean isMoved(final int responseCode) {
-            return responseCode == HttpURLConnection.HTTP_MOVED_PERM
-                    || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
-                    || responseCode == HttpURLConnection.HTTP_SEE_OTHER
-                    || responseCode == HTTP_MOVED_TEMP;
-        }
-
         private boolean downloadFile() throws IOException {
             for (int i = 0; i < numberRetries; i++) {
                 // this three attempt trick is to get round quirks in different
@@ -833,7 +867,7 @@
                 is = new GZIPInputStream(is);
             }
 
-            os = new FileOutputStream(dest);
+            os = Files.newOutputStream(dest.toPath());
             progress.beginDownload();
             boolean finished = false;
             try {
diff --git a/src/main/org/apache/tools/ant/taskdefs/HostInfo.java b/src/main/org/apache/tools/ant/taskdefs/HostInfo.java
index 1391298..14d8096 100644
--- a/src/main/org/apache/tools/ant/taskdefs/HostInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/HostInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,7 @@
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.util.Arrays;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -105,8 +105,9 @@
      * @throws BuildException
      *             on error.
      */
+    @Override
     public void execute() throws BuildException {
-        if (host == null || "".equals(host)) {
+        if (host == null || host.isEmpty()) {
             executeLocal();
         } else {
             executeRemote();
@@ -115,15 +116,9 @@
 
     private void executeLocal() {
         try {
-            inetAddrs = new LinkedList<InetAddress>();
-            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
-            while (interfaces.hasMoreElements()) {
-                NetworkInterface currentif = interfaces.nextElement();
-                Enumeration<InetAddress> addrs = currentif.getInetAddresses();
-                while (addrs.hasMoreElements()) {
-                    inetAddrs.add(addrs.nextElement());
-                }
-            }
+            inetAddrs = new LinkedList<>();
+            Collections.list(NetworkInterface.getNetworkInterfaces())
+                    .forEach(netInterface -> inetAddrs.addAll(Collections.list(netInterface.getInetAddresses())));
             selectAddresses();
 
             if (nameAddr != null && hasHostName(nameAddr)) {
@@ -175,34 +170,32 @@
         if (best == null) {
             // none selected so far, so this one is better.
             best = current;
+        } else if (current == null || current.isLoopbackAddress()) {
+            // definitely not better than the previously selected address.
+        } else if (current.isLinkLocalAddress()) {
+            // link local considered better than loopback
+            if (best.isLoopbackAddress()) {
+                best = current;
+            }
+        } else if (current.isSiteLocalAddress()) {
+            // site local considered better than link local (and loopback)
+            // address with hostname resolved considered better than
+            // address without hostname
+            if (best.isLoopbackAddress()
+                    || best.isLinkLocalAddress()
+                    || (best.isSiteLocalAddress() && !hasHostName(best))) {
+                best = current;
+            }
         } else {
-            if (current == null || current.isLoopbackAddress()) {
-                // definitely not better than the previously selected address.
-            } else if (current.isLinkLocalAddress()) {
-                // link local considered better than loopback
-                if (best.isLoopbackAddress()) {
-                    best = current;
-                }
-            } else if (current.isSiteLocalAddress()) {
-                // site local considered better than link local (and loopback)
-                // address with hostname resolved considered better than
-                // address without hostname
-                if (best.isLoopbackAddress()
-                        || best.isLinkLocalAddress()
-                        || (best.isSiteLocalAddress() && !hasHostName(best))) {
-                    best = current;
-                }
-            } else {
-                // current is a "Global address", considered better than
-                // site local (and better than link local, loopback)
-                // address with hostname resolved considered better than
-                // address without hostname
-                if (best.isLoopbackAddress()
-                        || best.isLinkLocalAddress()
-                        || best.isSiteLocalAddress()
-                        || !hasHostName(best)) {
-                    best = current;
-                }
+            // current is a "Global address", considered better than
+            // site local (and better than link local, loopback)
+            // address with hostname resolved considered better than
+            // address without hostname
+            if (best.isLoopbackAddress()
+                    || best.isLinkLocalAddress()
+                    || best.isSiteLocalAddress()
+                    || !hasHostName(best)) {
+                best = current;
             }
         }
         return best;
diff --git a/src/main/org/apache/tools/ant/taskdefs/ImportTask.java b/src/main/org/apache/tools/ant/taskdefs/ImportTask.java
index 0ddd597..79685ce 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ImportTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ImportTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,6 +24,7 @@
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.ProjectHelperRepository;
@@ -63,12 +64,13 @@
  * @ant.task category="control"
  */
 public class ImportTask extends Task {
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
     private String file;
     private boolean optional;
     private String targetPrefix = ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX;
     private String prefixSeparator = ".";
     private final Union resources = new Union();
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     public ImportTask() {
         resources.setCache(true);
@@ -126,28 +128,25 @@
         resources.add(r);
     }
 
+    @Override
     public void execute() {
-        if (file == null && resources.size() == 0) {
-            throw new BuildException("import requires file attribute or"
-                                     + " at least one nested resource");
+        if (file == null && resources.isEmpty()) {
+            throw new BuildException(
+                "import requires file attribute or at least one nested resource");
         }
         if (getOwningTarget() == null
-            || !"".equals(getOwningTarget().getName())) {
+            || !getOwningTarget().getName().isEmpty()) {
             throw new BuildException("import only allowed as a top-level task");
         }
 
-        ProjectHelper helper =
-                (ProjectHelper) getProject().
-                    getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+        ProjectHelper helper = getProject().getReference(MagicNames.REFID_PROJECT_HELPER);
 
         if (helper == null) {
             // this happens if the projecthelper was not registered with the project.
             throw new BuildException("import requires support in ProjectHelper");
         }
 
-        Vector<Object> importStack = helper.getImportStack();
-
-        if (importStack.size() == 0) {
+        if (helper.getImportStack().isEmpty()) {
             // this happens if ant is used with a project
             // helper that doesn't set the import.
             throw new BuildException("import requires support in ProjectHelper");
@@ -169,8 +168,6 @@
 
     private void importResource(ProjectHelper helper,
                                 Resource importedResource) {
-        Vector<Object> importStack = helper.getImportStack();
-
         getProject().log("Importing file " + importedResource + " from "
                          + getLocation().getFileName(), Project.MSG_VERBOSE);
 
@@ -181,13 +178,12 @@
             if (optional) {
                 getProject().log(message, Project.MSG_VERBOSE);
                 return;
-            } else {
-                throw new BuildException(message);
             }
+            throw new BuildException(message);
         }
 
-        if (!isInIncludeMode() &&
-            hasAlreadyBeenImported(importedResource, importStack)) {
+        if (!isInIncludeMode() && hasAlreadyBeenImported(importedResource,
+            helper.getImportStack())) {
             getProject().log(
                 "Skipped already imported file:\n   "
                 + importedResource + "\n", Project.MSG_VERBOSE);
@@ -206,10 +202,10 @@
                 prefix = oldPrefix + oldSep + targetPrefix;
             } else if (isInIncludeMode()) {
                 prefix = targetPrefix;
-            } else if (!ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX.equals(targetPrefix)) {
-                prefix = targetPrefix;
-            } else {
+            } else if (ProjectHelper.USE_PROJECT_NAME_AS_TARGET_PREFIX.equals(targetPrefix)) {
                 prefix = oldPrefix;
+            } else {
+                prefix = targetPrefix;
             }
             setProjectHelperProps(prefix, prefixSeparator,
                                   isInIncludeMode());
@@ -220,12 +216,12 @@
             // push current stacks into the sub helper
             subHelper.getImportStack().addAll(helper.getImportStack());
             subHelper.getExtensionStack().addAll(helper.getExtensionStack());
-            getProject().addReference(ProjectHelper.PROJECTHELPER_REFERENCE, subHelper);
+            getProject().addReference(MagicNames.REFID_PROJECT_HELPER, subHelper);
 
             subHelper.parse(getProject(), importedResource);
 
             // push back the stack from the sub helper to the main one
-            getProject().addReference(ProjectHelper.PROJECTHELPER_REFERENCE, helper);
+            getProject().addReference(MagicNames.REFID_PROJECT_HELPER, helper);
             helper.getImportStack().clear();
             helper.getImportStack().addAll(subHelper.getImportStack());
             helper.getExtensionStack().clear();
@@ -263,9 +259,8 @@
             } catch (MalformedURLException ex) {
                 log(ex.toString(), Project.MSG_VERBOSE);
             }
-            throw new BuildException("failed to resolve " + file
-                                     + " relative to "
-                                     + getLocation().getFileName());
+            throw new BuildException("failed to resolve %s relative to %s",
+                file, getLocation().getFileName());
         }
         return null;
     }
@@ -277,22 +272,14 @@
 
     private boolean hasAlreadyBeenImported(Resource importedResource,
                                            Vector<Object> importStack) {
-        File importedFile = null;
-        FileProvider fp = importedResource.as(FileProvider.class);
-        if (fp != null) {
-            importedFile = fp.getFile();
-        }
-        URL importedURL = null;
-        URLProvider up = importedResource.as(URLProvider.class);
-        if (up != null) {
-            importedURL = up.getURL();
-        }
-        for (Object o : importStack) {
-            if (isOneOf(o, importedResource, importedFile, importedURL)) {
-                return true;
-            }
-        }
-        return false;
+        File importedFile = importedResource.asOptional(FileProvider.class)
+            .map(FileProvider::getFile).orElse(null);
+
+        URL importedURL = importedResource.asOptional(URLProvider.class)
+            .map(URLProvider::getURL).orElse(null);
+
+        return importStack.stream().anyMatch(
+            o -> isOneOf(o, importedResource, importedFile, importedURL));
     }
 
     private boolean isOneOf(Object o, Resource importedResource,
@@ -310,9 +297,7 @@
             }
             if (importedURL != null) {
                 URLProvider up = ((Resource) o).as(URLProvider.class);
-                if (up != null && up.getURL().equals(importedURL)) {
-                    return true;
-                }
+                return up != null && up.getURL().equals(importedURL);
             }
         }
         return false;
diff --git a/src/main/org/apache/tools/ant/taskdefs/Input.java b/src/main/org/apache/tools/ant/taskdefs/Input.java
index 2f5eea0..f1f7212 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Input.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Input.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,7 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import java.util.Vector;
-
+import java.util.List;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.input.DefaultInputHandler;
@@ -59,6 +58,7 @@
         public void setRefid(final String refid) {
             this.refid = refid;
         }
+
         /**
          * Get the refid of this Handler.
          * @return String refid.
@@ -66,6 +66,7 @@
         public String getRefid() {
             return refid;
         }
+
         /**
          * Set the InputHandler classname.
          * @param classname the String classname.
@@ -73,6 +74,7 @@
         public void setClassname(final String classname) {
             this.classname = classname;
         }
+
         /**
          * Get the classname of the InputHandler.
          * @return String classname.
@@ -80,6 +82,7 @@
         public String getClassname() {
             return classname;
         }
+
         /**
          * Set the handler type.
          * @param type a HandlerType.
@@ -87,6 +90,7 @@
         public void setType(final HandlerType type) {
             this.type = type;
         }
+
         /**
          * Get the handler type.
          * @return a HandlerType object.
@@ -94,21 +98,22 @@
         public HandlerType getType() {
             return type;
         }
+
         private InputHandler getInputHandler() {
             if (type != null) {
                return type.getInputHandler();
             }
             if (refid != null) {
                try {
-                   return (InputHandler) (getProject().getReference(refid));
+                   return getProject().getReference(refid);
                } catch (final ClassCastException e) {
                    throw new BuildException(
                        refid + " does not denote an InputHandler", e);
                }
             }
             if (classname != null) {
-               return (InputHandler) (ClasspathUtils.newInstance(classname,
-                   createLoader(), InputHandler.class));
+               return ClasspathUtils.newInstance(classname,
+                   createLoader(), InputHandler.class);
             }
             throw new BuildException(
                 "Must specify refid, classname or type");
@@ -132,6 +137,7 @@
         public String[] getValues() {
             return VALUES;
         }
+
         private InputHandler getInputHandler() {
             return HANDLERS[getIndex()];
         }
@@ -192,19 +198,13 @@
      * @param msg The message to be displayed.
      */
     public void addText(final String msg) {
-        if (messageAttribute && "".equals(msg.trim())) {
+        if (messageAttribute && msg.trim().isEmpty()) {
             return;
         }
         message += getProject().replaceProperties(msg);
     }
 
     /**
-     * No arg constructor.
-     */
-    public Input () {
-    }
-
-    /**
      * Actual method executed by ant.
      * @throws BuildException on error
      */
@@ -219,7 +219,7 @@
 
         InputRequest request = null;
         if (validargs != null) {
-            final Vector<String> accept = StringUtils.split(validargs, ',');
+            final List<String> accept = StringUtils.split(validargs, ',');
             request = new MultipleChoiceInputRequest(message, accept);
         } else {
             request = new InputRequest(message);
@@ -233,7 +233,7 @@
         h.handleInput(request);
 
         String value = request.getInput();
-        if ((value == null || value.trim().length() == 0)
+        if ((value == null || value.trim().isEmpty())
             && defaultvalue != null) {
             value = defaultvalue;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java b/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java
index 3122115..55e22f6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/JDBCTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,13 @@
 
 package org.apache.tools.ant.taskdefs;
 
+import java.lang.reflect.InvocationTargetException;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.Driver;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Properties;
@@ -61,7 +61,7 @@
         Statement stmt=null;
         try {
             if (tableName == null) {
-                throw new BuildException("TableName must be specified",location);
+                throw new BuildException("TableName must be specified", location);
             }
             String sql = "SELECT * FROM "+tableName;
             stmt= conn.createStatement();
@@ -98,7 +98,7 @@
      * getting an OutOfMemoryError when calling this task
      * multiple times in a row.
      */
-    private static Hashtable<String, AntClassLoader> LOADER_MAP = new Hashtable<String, AntClassLoader>(HASH_TABLE_SIZE);
+    private static final Hashtable<String, AntClassLoader> LOADER_MAP = new Hashtable<>(HASH_TABLE_SIZE);
 
     private boolean caching = true;
 
@@ -152,7 +152,7 @@
      *
      * @since Ant 1.8.0
      */
-    private List<Property> connectionProperties = new ArrayList<Property>();
+    private List<Property> connectionProperties = new ArrayList<>();
 
     /**
      * Sets the classpath for loading the driver.
@@ -344,20 +344,17 @@
             throw new BuildException("Url attribute must be set!", getLocation());
         }
         try {
-
             log("connecting to " + getUrl(), Project.MSG_VERBOSE);
             Properties info = new Properties();
             info.put("user", getUserId());
             info.put("password", getPassword());
 
-            for (Iterator<Property> props = connectionProperties.iterator();
-                 props.hasNext();) {
-                Property p = props.next();
+            for (Property p : connectionProperties) {
                 String name = p.getName();
                 String value = p.getValue();
                 if (name == null || value == null) {
-                    log("Only name/value pairs are supported as connection"
-                        + " properties.", Project.MSG_WARN);
+                    log("Only name/value pairs are supported as connection properties.",
+                        Project.MSG_WARN);
                 } else {
                     log("Setting connection property " + name + " to " + value,
                         Project.MSG_VERBOSE);
@@ -376,14 +373,12 @@
             return conn;
         } catch (SQLException e) {
             // failed to connect
-            if (!failOnConnectionError) {
-                log("Failed to connect: " + e.getMessage(), Project.MSG_WARN);
-                return null;
-            } else {
+            if (failOnConnectionError) {
                 throw new BuildException(e, getLocation());
             }
+            log("Failed to connect: " + e.getMessage(), Project.MSG_WARN);
+            return null;
         }
-
     }
 
     /**
@@ -397,9 +392,9 @@
             throw new BuildException("Driver attribute must be set!", getLocation());
         }
 
-        Driver driverInstance = null;
+        Driver driverInstance;
         try {
-            Class<?> dc;
+            Class<? extends Driver> dc;
             if (classpath != null) {
                 // check first that it is not already loaded otherwise
                 // consecutive runs seems to end into an OutOfMemoryError
@@ -425,13 +420,13 @@
                                 Project.MSG_VERBOSE);
                     }
                 }
-                dc = loader.loadClass(driver);
+                dc = loader.loadClass(driver).asSubclass(Driver.class);
             } else {
                 log("Loading " + driver + " using system loader.",
                     Project.MSG_VERBOSE);
-                dc = Class.forName(driver);
+                dc = Class.forName(driver).asSubclass(Driver.class);
             }
-            driverInstance = (Driver) dc.newInstance();
+            driverInstance = dc.getDeclaredConstructor().newInstance();
         } catch (ClassNotFoundException e) {
             throw new BuildException(
                     "Class Not Found: JDBC driver " + driver + " could not be loaded",
@@ -442,16 +437,15 @@
                     "Illegal Access: JDBC driver " + driver + " could not be loaded",
                     e,
                     getLocation());
-        } catch (InstantiationException e) {
+        } catch (InstantiationException | NoSuchMethodException | InvocationTargetException e) {
             throw new BuildException(
-                    "Instantiation Exception: JDBC driver " + driver + " could not be loaded",
+                    e.getClass().getSimpleName() + ": JDBC driver " + driver + " could not be loaded",
                     e,
                     getLocation());
         }
         return driverInstance;
     }
 
-
     /**
      * Set the caching attribute.
      * @param value a <code>boolean</code> value
diff --git a/src/main/org/apache/tools/ant/taskdefs/Jar.java b/src/main/org/apache/tools/ant/taskdefs/Jar.java
index adea841..0c7bff9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Jar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Jar.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -29,12 +28,16 @@
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.SortedMap;
 import java.util.StringTokenizer;
 import java.util.TreeMap;
 import java.util.Vector;
@@ -47,12 +50,15 @@
 import org.apache.tools.ant.types.ArchiveFileSet;
 import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Mapper;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.ZipFileSet;
 import org.apache.tools.ant.types.spi.Service;
+import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.StreamUtils;
 import org.apache.tools.zip.JarMarker;
 import org.apache.tools.zip.ZipExtraField;
 import org.apache.tools.zip.ZipOutputStream;
@@ -74,7 +80,7 @@
     /**
      * List of all known SPI Services
      */
-    private List<Service> serviceList = new ArrayList<Service>();
+    private List<Service> serviceList = new ArrayList<>();
 
     /** merged manifests added through addConfiguredManifest */
     private Manifest configuredManifest;
@@ -138,7 +144,7 @@
      *
      * @since Ant 1.6
      */
-    private Vector<String> rootEntries;
+    private List<String> rootEntries;
 
     /**
      * Path containing jars that shall be indexed in addition to this archive.
@@ -147,6 +153,14 @@
      */
     private Path indexJars;
 
+    /**
+     * A mapper used to convert the jars to entries in the index.
+     *
+     * @since Ant 1.10.9
+     */
+    private FileNameMapper indexJarsMapper = null;
+
+
     // CheckStyle:LineLength OFF - Link is too long.
     /**
      * Strict mode for checking rules of the JAR-Specification.
@@ -182,7 +196,7 @@
         emptyBehavior = "create";
         setEncoding("UTF8");
         setZip64Mode(Zip64ModeAttribute.NEVER);
-        rootEntries = new Vector<String>();
+        rootEntries = new Vector<>();
     }
 
     /**
@@ -190,6 +204,7 @@
      * @param we not used
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setWhenempty(WhenEmpty we) {
         log("JARs are never empty, they contain at least a manifest file",
             Project.MSG_WARN);
@@ -225,6 +240,7 @@
      * @deprecated since 1.5.x.
      *             Use setDestFile(File) instead.
      */
+    @Deprecated
     public void setJarfile(File jarFile) {
         setDestFile(jarFile);
     }
@@ -249,7 +265,7 @@
      * jars on Java 1.4 or earlier Ant will not include META-INF
      * unless explicitly asked to.</p>
      *
-     * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408526">
+     * @see <a href="https://bugs.openjdk.java.net/browse/JDK-4408526">
      * jar -i omits service providers in index.list</a>
      * @since Ant 1.8.0
      * @param flag a <code>boolean</code> value, defaults to false
@@ -301,29 +317,13 @@
     }
 
     private Manifest getManifest(File manifestFile) {
-
-        Manifest newManifest = null;
-        FileInputStream fis = null;
-        InputStreamReader isr = null;
-        try {
-            fis = new FileInputStream(manifestFile);
-            if (manifestEncoding == null) {
-                isr = new InputStreamReader(fis);
-            } else {
-                isr = new InputStreamReader(fis, manifestEncoding);
-            }
-            newManifest = getManifest(isr);
-        } catch (UnsupportedEncodingException e) {
-            throw new BuildException("Unsupported encoding while reading manifest: "
-                                     + e.getMessage(), e);
+        try (InputStreamReader isr = new InputStreamReader(
+            Files.newInputStream(manifestFile.toPath()), getManifestCharset())) {
+            return getManifest(isr);
         } catch (IOException e) {
             throw new BuildException("Unable to read manifest file: "
-                                     + manifestFile
-                                     + " (" + e.getMessage() + ")", e);
-        } finally {
-            FileUtils.close(isr);
+                + manifestFile + " (" + e.getMessage() + ")", e);
         }
-        return newManifest;
     }
 
     /**
@@ -332,38 +332,25 @@
      * @since Ant 1.5.2
      */
     private Manifest getManifestFromJar(File jarFile) throws IOException {
-        ZipFile zf = null;
-        try {
-            zf = new ZipFile(jarFile);
-
+        try (ZipFile zf = new ZipFile(jarFile)) {
             // must not use getEntry as "well behaving" applications
             // must accept the manifest in any capitalization
-            Enumeration<? extends ZipEntry> e = zf.entries();
-            while (e.hasMoreElements()) {
-                ZipEntry ze = e.nextElement();
-                if (ze.getName().equalsIgnoreCase(MANIFEST_NAME)) {
-                    InputStreamReader isr =
-                        new InputStreamReader(zf.getInputStream(ze), "UTF-8");
-                    return getManifest(isr);
-                }
+            ZipEntry ze = StreamUtils.enumerationAsStream(zf.entries())
+                    .filter(entry -> MANIFEST_NAME.equalsIgnoreCase(entry.getName()))
+                    .findFirst().orElse(null);
+            if (ze == null) {
+                return null;
             }
-            return null;
-        } finally {
-            if (zf != null) {
-                try {
-                    zf.close();
-                } catch (IOException e) {
-                    // TODO - log an error?  throw an exception?
-                }
+            try (InputStreamReader isr = new InputStreamReader(zf.getInputStream(ze),
+                    StandardCharsets.UTF_8)) {
+                return getManifest(isr);
             }
         }
     }
 
     private Manifest getManifest(Reader r) {
-
-        Manifest newManifest = null;
         try {
-            newManifest = new Manifest(r);
+            return new Manifest(r);
         } catch (ManifestException e) {
             log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
             throw new BuildException("Invalid Manifest: " + manifestFile,
@@ -372,29 +359,12 @@
             throw new BuildException("Unable to read manifest file"
                                      + " (" + e.getMessage() + ")", e);
         }
-        return newManifest;
     }
 
     private boolean jarHasIndex(File jarFile) throws IOException {
-        ZipFile zf = null;
-        try {
-            zf = new ZipFile(jarFile);
-            Enumeration<? extends ZipEntry> e = zf.entries();
-            while (e.hasMoreElements()) {
-                ZipEntry ze = e.nextElement();
-                if (ze.getName().equalsIgnoreCase(INDEX_NAME)) {
-                    return true;
-                }
-            }
-            return false;
-        } finally {
-            if (zf != null) {
-                try {
-                    zf.close();
-                } catch (IOException e) {
-                    // TODO - log an error?  throw an exception?
-                }
-            }
+        try (ZipFile zf = new ZipFile(jarFile)) {
+            return StreamUtils.enumerationAsStream(zf.entries())
+                    .anyMatch(ze -> INDEX_NAME.equalsIgnoreCase(ze.getName()));
         }
     }
 
@@ -416,7 +386,7 @@
         mergeManifestsMain = config != null && "merge".equals(config.getValue());
 
         if (filesetManifestConfig != null
-            && !filesetManifestConfig.getValue().equals("skip")) {
+            && !"skip".equals(filesetManifestConfig.getValue())) {
 
             doubleFilePass = true;
         }
@@ -446,6 +416,30 @@
     }
 
     /**
+     * Add a mapper used to convert the jars to entries in the index.
+     *
+     * @param mapper a mapper
+     * @since Ant 1.10.9
+     */
+    public void addConfiguredIndexJarsMapper(Mapper mapper) {
+        if (indexJarsMapper != null) {
+            throw new BuildException("Cannot define more than one indexjar-mapper",
+                    getLocation());
+        }
+        indexJarsMapper = mapper.getImplementation();
+    }
+
+    /**
+     * Returns the mapper used to convert the jars to entries in the index. May be null.
+     *
+     * @since Ant 1.10.9
+     */
+    public FileNameMapper getIndexJarsMapper() {
+        return indexJarsMapper;
+    }
+
+
+    /**
      * A nested SPI service element.
      * @param service the nested element.
      * @since Ant 1.7
@@ -461,19 +455,12 @@
      */
     private void writeServices(ZipOutputStream zOut) throws IOException {
         for (Service service : serviceList) {
-           InputStream is = null;
-           try {
-               is = service.getAsStream();
-               //stolen from writeManifest
+            try (InputStream is = service.getAsStream()) {
+                //stolen from writeManifest
                super.zipFile(is, zOut,
                              "META-INF/services/" + service.getType(),
                              System.currentTimeMillis(), null,
                              ZipFileSet.DEFAULT_FILE_MODE);
-           } finally {
-               // technically this is unnecessary since
-               // Service.getAsStream returns a ByteArrayInputStream
-               // and not closing it wouldn't do any harm.
-               FileUtils.close(is);
            }
         }
     }
@@ -505,6 +492,7 @@
      * @throws IOException on I/O errors
      * @throws BuildException on other errors
      */
+    @Override
     protected void initZipOutputStream(ZipOutputStream zOut)
         throws IOException, BuildException {
 
@@ -518,12 +506,10 @@
     private Manifest createManifest()
         throws BuildException {
         try {
-            if (manifest == null) {
-                if (manifestFile != null) {
-                    // if we haven't got the manifest yet, attempt to
-                    // get it now and have manifest be the final merge
-                    manifest = getManifest(manifestFile);
-                }
+            if (manifest == null && manifestFile != null) {
+                // if we haven't got the manifest yet, attempt to
+                // get it now and have manifest be the final merge
+                manifest = getManifest(manifestFile);
             }
 
             // fileset manifest must come even before the default
@@ -574,15 +560,14 @@
 
     private void writeManifest(ZipOutputStream zOut, Manifest manifest)
         throws IOException {
-        for (String warning : Collections.list(manifest.getWarnings())) {
-            log("Manifest warning: " + warning, Project.MSG_WARN);
-        }
+        StreamUtils.enumerationAsStream(manifest.getWarnings())
+                .forEach(warning -> log("Manifest warning: " + warning, Project.MSG_WARN));
 
         zipDir((Resource) null, zOut, "META-INF/", ZipFileSet.DEFAULT_DIR_MODE,
                JAR_MARKER);
         // time to write the manifest
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        OutputStreamWriter osw = new OutputStreamWriter(baos, Manifest.JAR_ENCODING);
+        OutputStreamWriter osw = new OutputStreamWriter(baos, Manifest.JAR_CHARSET);
         PrintWriter writer = new PrintWriter(osw);
         manifest.write(writer, flattenClassPaths);
         if (writer.checkError()) {
@@ -610,6 +595,7 @@
      * @throws IOException on I/O errors
      * @throws BuildException on other errors
      */
+    @Override
     protected void finalizeZipOutputStream(ZipOutputStream zOut)
         throws IOException, BuildException {
 
@@ -621,7 +607,7 @@
     /**
      * Create the index list to speed up classloading.
      * This is a JDK 1.3+ specific feature and is enabled by default. See
-     * <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index">
+     * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Index">
      * the JAR index specification</a> for more details.
      *
      * @param zOut the zip stream representing the jar being built.
@@ -631,8 +617,7 @@
     private void createIndexList(ZipOutputStream zOut) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         // encoding must be UTF8 as specified in the specs.
-        PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos,
-                                                                    "UTF8"));
+        PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8));
 
         // version-info blankline
         writer.println("JarIndex-Version: 1.0");
@@ -641,32 +626,23 @@
         // header newline
         writer.println(zipFile.getName());
 
-        writeIndexLikeList(new ArrayList<String>(addedDirs.keySet()),
+        writeIndexLikeList(new ArrayList<>(addedDirs.keySet()),
                            rootEntries, writer);
         writer.println();
 
         if (indexJars != null) {
-            Manifest mf = createManifest();
-            Manifest.Attribute classpath =
-                mf.getMainSection().getAttribute(Manifest.ATTRIBUTE_CLASSPATH);
-            String[] cpEntries = null;
-            if (classpath != null && classpath.getValue() != null) {
-                StringTokenizer tok = new StringTokenizer(classpath.getValue(),
-                                                          " ");
-                cpEntries = new String[tok.countTokens()];
-                int c = 0;
-                while (tok.hasMoreTokens()) {
-                    cpEntries[c++] = tok.nextToken();
-                }
+            FileNameMapper mapper = indexJarsMapper;
+            if (mapper == null) {
+                mapper = createDefaultIndexJarsMapper();
             }
             for (String indexJarEntry : indexJars.list()) {
-                String name = findJarName(indexJarEntry, cpEntries);
-                if (name != null) {
-                    ArrayList<String> dirs = new ArrayList<String>();
-                    ArrayList<String> files = new ArrayList<String>();
+                String[] names = mapper.mapFileName(indexJarEntry);
+                if (names != null && names.length > 0) {
+                    ArrayList<String> dirs = new ArrayList<>();
+                    ArrayList<String> files = new ArrayList<>();
                     grabFilesAndDirs(indexJarEntry, dirs, files);
                     if (dirs.size() + files.size() > 0) {
-                        writer.println(name);
+                        writer.println(names[0]);
                         writeIndexLikeList(dirs, files, writer);
                         writer.println();
                     }
@@ -678,18 +654,39 @@
             throw new IOException("Encountered an error writing jar index");
         }
         writer.close();
-        ByteArrayInputStream bais =
-            new ByteArrayInputStream(baos.toByteArray());
-        try {
+        try (ByteArrayInputStream bais =
+            new ByteArrayInputStream(baos.toByteArray())) {
             super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis(),
                           null, ZipFileSet.DEFAULT_FILE_MODE);
-        } finally {
-            // not really required
-            FileUtils.close(bais);
         }
     }
 
     /**
+     * Creates a mapper for the index based on the classpath attribute in the manifest.
+     * See {@link #findJarName(String, String[])} for more details.
+     *
+     * @return a mapper
+     * @since Ant 1.10.9
+     */
+    private FileNameMapper createDefaultIndexJarsMapper() {
+        Manifest mf = createManifest();
+        Manifest.Attribute classpath =
+                mf.getMainSection().getAttribute(Manifest.ATTRIBUTE_CLASSPATH);
+        String[] cpEntries = null;
+        if (classpath != null && classpath.getValue() != null) {
+            StringTokenizer tok = new StringTokenizer(classpath.getValue(),
+                    " ");
+            cpEntries = new String[tok.countTokens()];
+            int c = 0;
+            while (tok.hasMoreTokens()) {
+                cpEntries[c++] = tok.nextToken();
+            }
+        }
+
+        return new IndexJarsFilenameMapper(cpEntries);
+    }
+
+    /**
      * Overridden from Zip class to deal with manifests and index lists.
      * @param is the stream to read data for the entry from.  The
      * caller of the method is responsible for closing the stream.
@@ -701,6 +698,7 @@
      * @param mode the Unix permissions to set.
      * @throws IOException on error
      */
+    @Override
     protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath,
                            long lastModified, File fromArchive, int mode)
         throws IOException {
@@ -715,7 +713,7 @@
                            Project.MSG_WARN);
         } else {
             if (index && !vPath.contains("/")) {
-                rootEntries.addElement(vPath);
+                rootEntries.add(vPath);
             }
             super.zipFile(is, zOut, vPath, lastModified, fromArchive, mode);
         }
@@ -726,40 +724,29 @@
             // If this is the same name specified in 'manifest', this
             // is the manifest to use
             log("Found manifest " + file, Project.MSG_VERBOSE);
-            try {
-                if (is != null) {
-                    InputStreamReader isr;
-                    if (manifestEncoding == null) {
-                        isr = new InputStreamReader(is);
-                    } else {
-                        isr = new InputStreamReader(is, manifestEncoding);
-                    }
+            if (is == null) {
+                manifest = getManifest(file);
+            } else {
+                try (InputStreamReader isr =
+                    new InputStreamReader(is, getManifestCharset())) {
                     manifest = getManifest(isr);
-                } else {
-                    manifest = getManifest(file);
                 }
-            } catch (UnsupportedEncodingException e) {
-                throw new BuildException("Unsupported encoding while reading "
-                    + "manifest: " + e.getMessage(), e);
             }
         } else if (filesetManifestConfig != null
-                    && !filesetManifestConfig.getValue().equals("skip")) {
+                    && !"skip".equals(filesetManifestConfig.getValue())) {
             // we add this to our group of fileset manifests
             logWhenWriting("Found manifest to merge in file " + file,
                            Project.MSG_VERBOSE);
 
             try {
-                Manifest newManifest = null;
-                if (is != null) {
-                    InputStreamReader isr;
-                    if (manifestEncoding == null) {
-                        isr = new InputStreamReader(is);
-                    } else {
-                        isr = new InputStreamReader(is, manifestEncoding);
-                    }
-                    newManifest = getManifest(isr);
-                } else {
+                Manifest newManifest;
+                if (is == null) {
                     newManifest = getManifest(file);
+                } else {
+                    try (InputStreamReader isr =
+                        new InputStreamReader(is, getManifestCharset())) {
+                        newManifest = getManifest(isr);
+                    }
                 }
 
                 if (filesetManifest == null) {
@@ -815,6 +802,7 @@
      *
      * @exception BuildException if it likes
      */
+    @Override
     protected ArchiveState getResourcesToAdd(ResourceCollection[] rcs,
                                              File zipFile,
                                              boolean needsUpdate)
@@ -885,50 +873,48 @@
      * @return true for historic reasons
      * @throws BuildException on error
      */
+    @Override
     protected boolean createEmptyZip(File zipFile) throws BuildException {
         if (!createEmpty) {
             return true;
         }
 
-        if (emptyBehavior.equals("skip")) {
+        if ("skip".equals(emptyBehavior)) {
             if (!skipWriting) {
                 log("Warning: skipping " + archiveType + " archive "
                     + zipFile + " because no files were included.",
                     Project.MSG_WARN);
             }
             return true;
-        } else if (emptyBehavior.equals("fail")) {
+        }
+        if ("fail".equals(emptyBehavior)) {
             throw new BuildException("Cannot create " + archiveType
                                      + " archive " + zipFile
                                      + ": no files were included.",
                                      getLocation());
         }
 
-        ZipOutputStream zOut = null;
-        try {
-            if (!skipWriting) {
-                log("Building MANIFEST-only jar: "
+        if (!skipWriting) {
+            log("Building MANIFEST-only jar: "
                     + getDestFile().getAbsolutePath());
-            }
-            zOut = new ZipOutputStream(getDestFile());
 
-            zOut.setEncoding(getEncoding());
-            zOut.setUseZip64(getZip64Mode().getMode());
-            if (isCompress()) {
-                zOut.setMethod(ZipOutputStream.DEFLATED);
-            } else {
-                zOut.setMethod(ZipOutputStream.STORED);
+            try (ZipOutputStream zOut = new ZipOutputStream(getDestFile())) {
+                zOut.setEncoding(getEncoding());
+                zOut.setUseZip64(getZip64Mode().getMode());
+                if (isCompress()) {
+                    zOut.setMethod(ZipOutputStream.DEFLATED);
+                } else {
+                    zOut.setMethod(ZipOutputStream.STORED);
+                }
+                initZipOutputStream(zOut);
+                finalizeZipOutputStream(zOut);
+            } catch (IOException ioe) {
+                throw new BuildException("Could not create almost empty JAR archive"
+                                         + " (" + ioe.getMessage() + ")", ioe,
+                                         getLocation());
+            } finally {
+                createEmpty = false;
             }
-            initZipOutputStream(zOut);
-            finalizeZipOutputStream(zOut);
-        } catch (IOException ioe) {
-            throw new BuildException("Could not create almost empty JAR archive"
-                                     + " (" + ioe.getMessage() + ")", ioe,
-                                     getLocation());
-        } finally {
-            // Close the output stream.
-            FileUtils.close(zOut);
-            createEmpty = false;
         }
         return true;
     }
@@ -939,6 +925,7 @@
      *
      * @see Zip#cleanUp
      */
+    @Override
     protected void cleanUp() {
         super.cleanUp();
         checkJarSpec();
@@ -950,18 +937,17 @@
             filesetManifest = null;
             originalManifest = null;
         }
-        rootEntries.removeAllElements();
+        rootEntries.clear();
     }
 
     // CheckStyle:LineLength OFF - Link is too long.
     /**
      * Check against packaging spec
-     * @see "http://java.sun.com/j2se/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersioning"
+     * @see "https://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html"
      */
     // CheckStyle:LineLength ON
     private void checkJarSpec() {
-        String br = System.getProperty("line.separator");
-        StringBuffer message = new StringBuffer();
+        StringBuilder message = new StringBuilder();
         Section mainSection = (configuredManifest == null)
                             ? null
                             : configuredManifest.getMainSection();
@@ -983,14 +969,11 @@
         }
 
         if (message.length() > 0) {
-            message.append(br);
-            message.append("Location: ").append(getLocation());
-            message.append(br);
-            if (strict.getValue().equalsIgnoreCase("fail")) {
+            message.append(String.format("%nLocation: %s%n", getLocation()));
+            if ("fail".equalsIgnoreCase(strict.getValue())) {
                 throw new BuildException(message.toString(), getLocation());
-            } else {
-                logWhenWriting(message.toString(), strict.getLogLevel());
             }
+            logWhenWriting(message.toString(), strict.getLogLevel());
         }
     }
 
@@ -1001,6 +984,7 @@
      *
      * @since 1.44, Ant 1.5
      */
+    @Override
     public void reset() {
         super.reset();
         emptyBehavior = "create";
@@ -1019,6 +1003,7 @@
          * Get the list of valid strings.
          * @return the list of values - "skip", "merge" and "mergewithoutmain"
          */
+        @Override
         public String[] getValues() {
             return new String[] {"skip", "merge", "mergewithoutmain"};
         }
@@ -1058,7 +1043,7 @@
             // and the check is not case insensitive.
             // see sun.misc.JarIndex
             // see also
-            // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408526
+            // https://bugs.openjdk.java.net/browse/JDK-4408526
             if (!indexMetaInf && dir.startsWith("META-INF")) {
                 continue;
             }
@@ -1066,9 +1051,7 @@
             writer.println(dir);
         }
 
-        for (String file : files) {
-            writer.println(file);
-        }
+        files.forEach(writer::println);
     }
 
     /**
@@ -1094,39 +1077,27 @@
     protected static String findJarName(String fileName,
                                               String[] classpath) {
         if (classpath == null) {
-            return (new File(fileName)).getName();
+            return new File(fileName).getName();
         }
         fileName = fileName.replace(File.separatorChar, '/');
-        TreeMap<String, String> matches = new TreeMap<String, String>(new Comparator<Object>() {
-                // longest match comes first
-                public int compare(Object o1, Object o2) {
-                    if (o1 instanceof String && o2 instanceof String) {
-                        return ((String) o2).length()
-                            - ((String) o1).length();
-                    }
-                    return 0;
-                }
-            });
+        SortedMap<String, String> matches = new TreeMap<>(Comparator
+            .<String> comparingInt(s -> s == null ? 0 : s.length()).reversed());
 
-        for (int i = 0; i < classpath.length; i++) {
-            if (fileName.endsWith(classpath[i])) {
-                matches.put(classpath[i], classpath[i]);
-            } else {
-                int slash = classpath[i].indexOf("/");
-                String candidate = classpath[i];
-                while (slash > -1) {
-                    candidate = candidate.substring(slash + 1);
-                    if (fileName.endsWith(candidate)) {
-                        matches.put(candidate, classpath[i]);
-                        break;
-                    }
-                    slash = candidate.indexOf("/");
+        for (String element : classpath) {
+            String candidate = element;
+            while (true) {
+                if (fileName.endsWith(candidate)) {
+                    matches.put(candidate, element);
+                    break;
                 }
+                int slash = candidate.indexOf('/');
+                if (slash < 0) {
+                    break;
+                }
+                candidate = candidate.substring(slash + 1);
             }
         }
-
-        return matches.size() == 0
-            ? null : (String) matches.get(matches.firstKey());
+        return matches.isEmpty() ? null : matches.get(matches.firstKey());
     }
 
     /**
@@ -1141,51 +1112,43 @@
     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");
-            Enumeration<org.apache.tools.zip.ZipEntry> entries = zf.getEntries();
-            HashSet<String> dirSet = new HashSet<String>();
-            while (entries.hasMoreElements()) {
-                org.apache.tools.zip.ZipEntry ze =
-                    entries.nextElement();
+        try (org.apache.tools.zip.ZipFile zf = new org.apache.tools.zip.ZipFile(file, "utf-8")) {
+            Set<String> dirSet = new HashSet<>();
+            StreamUtils.enumerationAsStream(zf.getEntries()).forEach(ze -> {
                 String name = ze.getName();
                 if (ze.isDirectory()) {
                     dirSet.add(name);
-                } else if (name.indexOf("/") == -1) {
+                } else if (!name.contains("/")) {
                     files.add(name);
                 } else {
                     // a file, not in the root
                     // since the jar may be one without directory
                     // entries, add the parent dir of this file as
                     // well.
-                    dirSet.add(name.substring(0, name.lastIndexOf("/") + 1));
+                    dirSet.add(name.substring(0, name.lastIndexOf('/') + 1));
                 }
-            }
+            });
             dirs.addAll(dirSet);
-        } finally {
-            if (zf != null) {
-                zf.close();
-            }
         }
     }
 
     private Resource[][] grabManifests(ResourceCollection[] rcs) {
         Resource[][] manifests = new Resource[rcs.length][];
         for (int i = 0; i < rcs.length; i++) {
-            Resource[][] resources = null;
+            Resource[][] resources;
             if (rcs[i] instanceof FileSet) {
                 resources = grabResources(new FileSet[] {(FileSet) rcs[i]});
             } else {
-                resources = grabNonFileSetResources(new ResourceCollection[] {rcs[i]});
+                resources = grabNonFileSetResources(
+                    new ResourceCollection[] {rcs[i]});
             }
             for (int j = 0; j < resources[0].length; j++) {
                 String name = resources[0][j].getName().replace('\\', '/');
                 if (rcs[i] instanceof ArchiveFileSet) {
                     ArchiveFileSet afs = (ArchiveFileSet) rcs[i];
-                    if (!"".equals(afs.getFullpath(getProject()))) {
+                    if (!afs.getFullpath(getProject()).isEmpty()) {
                         name = afs.getFullpath(getProject());
-                    } else if (!"".equals(afs.getPrefix(getProject()))) {
+                    } else if (!afs.getPrefix(getProject()).isEmpty()) {
                         String prefix = afs.getPrefix(getProject());
                         if (!prefix.endsWith("/") && !prefix.endsWith("\\")) {
                             prefix += "/";
@@ -1193,7 +1156,7 @@
                         name = prefix + name;
                     }
                 }
-                if (name.equalsIgnoreCase(MANIFEST_NAME)) {
+                if (MANIFEST_NAME.equalsIgnoreCase(name)) {
                     manifests[i] = new Resource[] {resources[0][j]};
                     break;
                 }
@@ -1205,11 +1168,26 @@
         return manifests;
     }
 
+    private Charset getManifestCharset() {
+        if (manifestEncoding == null) {
+            return Charset.defaultCharset();
+        }
+        try {
+            return Charset.forName(manifestEncoding);
+        } catch (IllegalArgumentException e) {
+            throw new BuildException(
+                "Unsupported encoding while reading manifest: "
+                    + e.getMessage(),
+                e);
+        }
+    }
+
     /** The strict enumerated type. */
     public static class StrictMode extends EnumeratedAttribute {
         /** Public no arg constructor. */
         public StrictMode() {
         }
+
         /**
          * Constructor with an arg.
          * @param value the enumerated value as a string.
@@ -1217,18 +1195,56 @@
         public StrictMode(String value) {
             setValue(value);
         }
+
         /**
          * Get List of valid strings.
          * @return the list of values.
          */
+        @Override
         public String[] getValues() {
             return new String[] {"fail", "warn", "ignore"};
         }
+
         /**
          * @return The log level according to the strict mode.
          */
         public int getLogLevel() {
-            return (getValue().equals("ignore")) ? Project.MSG_VERBOSE : Project.MSG_WARN;
+            return "ignore".equals(getValue()) ? Project.MSG_VERBOSE : Project.MSG_WARN;
+        }
+    }
+
+    /**
+     * A mapper for the index based on the classpath attribute in the manifest.
+     * See {@link #findJarName(String, String[])} for more details.
+     *
+     * @since Ant 1.10.9
+     */
+    private static class IndexJarsFilenameMapper implements FileNameMapper {
+
+        private String[] classpath;
+
+        IndexJarsFilenameMapper(String[] classpath) {
+            this.classpath = classpath;
+        }
+
+        /**
+         * Empty implementation.
+         */
+        @Override
+        public void setFrom(String from) {
+        }
+
+        /**
+         * Empty implementation.
+         */
+        @Override
+        public void setTo(String to) {
+        }
+
+        @Override
+        public String[] mapFileName(String sourceFileName) {
+            String result = findJarName(sourceFileName, classpath);
+            return result == null ? null : new String[] {result};
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Java.java b/src/main/org/apache/tools/ant/taskdefs/Java.java
index a49a34f..7c55bbe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Java.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Java.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -50,6 +50,8 @@
  * @ant.task category="java"
  */
 public class Java extends Task {
+    private static final String TIMEOUT_MESSAGE =
+            "Timeout: killed the sub-process";
 
     private CommandlineJava cmdl = new CommandlineJava();
     private Environment env = new Environment();
@@ -76,9 +78,6 @@
     private boolean spawn = false;
     private boolean incompatibleWithSpawn = false;
 
-    private static final String TIMEOUT_MESSAGE =
-        "Timeout: killed the sub-process";
-
     /**
      * Normal constructor
      */
@@ -98,6 +97,7 @@
      * @throws BuildException if failOnError is set to true and the application
      * returns a nonzero result code.
      */
+    @Override
     public void execute() throws BuildException {
         File savedDir = dir;
         Permissions savedPermissions = perm;
@@ -142,34 +142,40 @@
     protected void checkConfiguration() throws BuildException {
         String classname = getCommandLine().getClassname();
         String module = getCommandLine().getModule();
-        if (classname == null && getCommandLine().getJar() == null && module == null) {
+        final String sourceFile = getCommandLine().getSourceFile();
+        if (classname == null && getCommandLine().getJar() == null && module == null && sourceFile == null) {
             throw new BuildException("Classname must not be null.");
         }
         if (!fork && getCommandLine().getJar() != null) {
-            throw new BuildException("Cannot execute a jar in non-forked mode."
-                                     + " Please set fork='true'. ");
+            throw new BuildException(
+                "Cannot execute a jar in non-forked mode. Please set fork='true'. ");
         }
         if (!fork && getCommandLine().getModule() != null) {
-            throw new BuildException("Cannot execute a module in non-forked mode."
-                                     + " Please set fork='true'. ");
+            throw new BuildException(
+                "Cannot execute a module in non-forked mode. Please set fork='true'. ");
+        }
+        if (!fork && sourceFile != null) {
+            throw new BuildException("Cannot execute sourcefile in non-forked mode. Please set fork='true'");
         }
         if (spawn && !fork) {
-            throw new BuildException("Cannot spawn a java process in non-forked mode."
-                                     + " Please set fork='true'. ");
+            throw new BuildException(
+                "Cannot spawn a java process in non-forked mode. Please set fork='true'. ");
         }
         if (getCommandLine().getClasspath() != null
             && getCommandLine().getJar() != null) {
-            log("When using 'jar' attribute classpath-settings are ignored. "
-                + "See the manual for more information.", Project.MSG_VERBOSE);
+            log("When using 'jar' attribute classpath-settings are ignored. See the manual for more information.",
+                Project.MSG_VERBOSE);
         }
         if (spawn && incompatibleWithSpawn) {
-            getProject().log("spawn does not allow attributes related to input, "
-            + "output, error, result", Project.MSG_ERR);
+            getProject().log(
+                "spawn does not allow attributes related to input, output, error, result",
+                Project.MSG_ERR);
             getProject().log("spawn also does not allow timeout", Project.MSG_ERR);
-            getProject().log("finally, spawn is not compatible "
-                + "with a nested I/O <redirector>", Project.MSG_ERR);
-            throw new BuildException("You have used an attribute "
-                + "or nested element which is not compatible with spawn");
+            getProject().log(
+                "finally, spawn is not compatible with a nested I/O <redirector>",
+                Project.MSG_ERR);
+            throw new BuildException(
+                "You have used an attribute or nested element which is not compatible with spawn");
         }
         if (getCommandLine().getAssertions() != null && !fork) {
             log("Assertion statements are currently ignored in non-forked mode");
@@ -189,8 +195,8 @@
                     Project.MSG_WARN);
             }
             if (newEnvironment || null != env.getVariables()) {
-                log("Changes to environment variables are ignored when same "
-                    + "JVM is used.", Project.MSG_WARN);
+                log("Changes to environment variables are ignored when same JVM is used.",
+                    Project.MSG_WARN);
             }
             if (getCommandLine().getBootclasspath() != null) {
                 log("bootclasspath ignored when same JVM is used.",
@@ -215,19 +221,17 @@
     protected int executeJava(CommandlineJava commandLine) {
         try {
             if (fork) {
-                if (!spawn) {
-                    return fork(commandLine.getCommandline());
-                } else {
+                if (spawn) {
                     spawn(commandLine.getCommandline());
                     return 0;
                 }
-            } else {
-                try {
-                    run(commandLine);
-                    return 0;
-                } catch (ExitException ex) {
-                    return ex.getStatus();
-                }
+                return fork(commandLine.getCommandline());
+            }
+            try {
+                run(commandLine);
+                return 0;
+            } catch (ExitException ex) {
+                return ex.getStatus();
             }
         } catch (BuildException e) {
             if (e.getLocation() == null && getLocation() != null) {
@@ -235,23 +239,21 @@
             }
             if (failOnError) {
                 throw e;
-            } else {
-                if (TIMEOUT_MESSAGE.equals(e.getMessage())) {
-                    log(TIMEOUT_MESSAGE);
-                } else {
-                    log(e);
-                }
-                return -1;
             }
+            if (TIMEOUT_MESSAGE.equals(e.getMessage())) {
+                log(TIMEOUT_MESSAGE);
+            } else {
+                log(e);
+            }
+            return -1;
         } catch (ThreadDeath t) {
             throw t; // cf. NB #47191
         } catch (Throwable t) {
             if (failOnError) {
                 throw new BuildException(t, getLocation());
-            } else {
-                log(t);
-                return -1;
             }
+            log(t);
+            return -1;
         }
     }
 
@@ -357,12 +359,14 @@
      *
      * @param jarfile the jarfile to execute.
      *
-     * @throws BuildException if there is also a main class specified.
+     * @throws BuildException if there is also a {@code classname}, {@code module}
+     *              or {@code sourcefile} attribute specified
      */
     public void setJar(File jarfile) throws BuildException {
-        if (getCommandLine().getClassname() != null || getCommandLine().getModule() != null) {
-            throw new BuildException("Cannot use 'jar' with 'classname' or 'module' "
-                                     + "attributes in same command.");
+        if (getCommandLine().getClassname() != null || getCommandLine().getModule() != null
+                || getCommandLine().getSourceFile() != null) {
+            throw new BuildException(
+                    "Cannot use combination of 'jar', 'sourcefile', 'classname', 'module' attributes in same command");
         }
         getCommandLine().setJar(jarfile.getAbsolutePath());
     }
@@ -372,12 +376,12 @@
      *
      * @param s the name of the main class.
      *
-     * @throws BuildException if the jar attribute has been set.
+     * @throws BuildException if there is also a {@code jar} or {@code sourcefile} attribute specified
      */
     public void setClassname(String s) throws BuildException {
-        if (getCommandLine().getJar() != null) {
-            throw new BuildException("Cannot use 'jar' and 'classname' "
-                                     + "attributes in same command");
+        if (getCommandLine().getJar() != null || getCommandLine().getSourceFile() != null) {
+            throw new BuildException(
+                "Cannot use combination of 'jar', 'classname', sourcefile attributes in same command");
         }
         getCommandLine().setClassname(s);
     }
@@ -387,18 +391,38 @@
      *
      * @param module the name of the module.
      *
-     * @throws BuildException if the jar attribute has been set.
+     * @throws BuildException if there is also a {@code jar} or {@code sourcefile} attribute specified
      * @since 1.9.7
      */
     public void setModule(String module) throws BuildException {
-        if (getCommandLine().getJar() != null) {
-            throw new BuildException("Cannot use 'jar' and 'module' "
-                                     + "attributes in same command");
+        if (getCommandLine().getJar() != null || getCommandLine().getSourceFile() != null) {
+            throw new BuildException(
+                    "Cannot use combination of 'jar', 'module', sourcefile attributes in same command");
         }
         getCommandLine().setModule(module);
     }
 
     /**
+     * Set the Java source-file to execute. Support for single file source program
+     * execution, in Java, is only available since Java 11.
+     *
+     * @param sourceFile The path to the source file
+     * @throws BuildException if there is also a {@code jar}, {@code classname}
+     *              or {@code module} attribute specified
+     * @since Ant 1.10.5
+     */
+    public void setSourceFile(final String sourceFile) throws BuildException {
+        final String jar = getCommandLine().getJar();
+        final String className = getCommandLine().getClassname();
+        final String module = getCommandLine().getModule();
+        if (jar != null || className != null || module != null) {
+            throw new BuildException("Cannot use 'sourcefile' in combination with 'jar' or " +
+                    "'module' or 'classname'");
+        }
+        getCommandLine().setSourceFile(sourceFile);
+    }
+
+    /**
      * Deprecated: use nested arg instead.
      * Set the command line arguments for the class.
      *
@@ -407,8 +431,8 @@
      * @ant.attribute ignore="true"
      */
     public void setArgs(String s) {
-        log("The args attribute is deprecated. "
-            + "Please use nested arg elements.", Project.MSG_WARN);
+        log("The args attribute is deprecated. Please use nested arg elements.",
+            Project.MSG_WARN);
         getCommandLine().createArgument().setLine(s);
     }
 
@@ -475,8 +499,8 @@
      * @param s jvmargs.
      */
     public void setJvmargs(String s) {
-        log("The jvmargs attribute is deprecated. "
-            + "Please use nested jvmarg elements.", Project.MSG_WARN);
+        log("The jvmargs attribute is deprecated. Please use nested jvmarg elements.",
+            Project.MSG_WARN);
         getCommandLine().createVmArgument().setLine(s);
     }
 
@@ -557,8 +581,8 @@
      */
     public void setInput(File input) {
         if (inputString != null) {
-            throw new BuildException("The \"input\" and \"inputstring\" "
-                + "attributes cannot both be specified");
+            throw new BuildException(
+                "The \"input\" and \"inputstring\" attributes cannot both be specified");
         }
         this.input = input;
         incompatibleWithSpawn = true;
@@ -571,8 +595,8 @@
      */
     public void setInputString(String inputString) {
         if (input != null) {
-            throw new BuildException("The \"input\" and \"inputstring\" "
-                + "attributes cannot both be specified");
+            throw new BuildException(
+                "The \"input\" and \"inputstring\" attributes cannot both be specified");
         }
         this.inputString = inputString;
         incompatibleWithSpawn = true;
@@ -684,6 +708,36 @@
     }
 
     /**
+     * Whether output should be discarded.
+     *
+     * <p>Defaults to false.</p>
+     *
+     * @param discard
+     *            if true output streams are discarded.
+     *
+     * @since Ant 1.10.10
+     * @see #setDiscardError
+     */
+    public void setDiscardOutput(final boolean discard) {
+        redirector.setDiscardOutput(discard);
+    }
+
+    /**
+     * Whether error output should be discarded.
+     *
+     * <p>Defaults to false.</p>
+     *
+     * @param discard
+     *            if true error streams are discarded.
+     *
+     * @since Ant 1.10.10
+     * @see #setDiscardOutput
+     */
+    public void setDiscardError(final boolean discard) {
+        redirector.setDiscardError(discard);
+    }
+
+    /**
      * Set the timeout in milliseconds after which the process will be killed.
      *
      * @param value timeout in milliseconds.
@@ -726,6 +780,7 @@
      *
      * @since Ant 1.5
      */
+    @Override
     protected void handleOutput(String output) {
         if (redirector.getOutputStream() != null) {
             redirector.handleOutput(output);
@@ -746,6 +801,7 @@
      * @exception IOException if the data cannot be read.
      * @since Ant 1.6
      */
+    @Override
     public int handleInput(byte[] buffer, int offset, int length)
         throws IOException {
         // Should work whether or not redirector.inputStream == null:
@@ -759,6 +815,7 @@
      *
      * @since Ant 1.5.2
      */
+    @Override
     protected void handleFlush(String output) {
         if (redirector.getOutputStream() != null) {
             redirector.handleFlush(output);
@@ -774,6 +831,7 @@
      *
      * @since Ant 1.5
      */
+    @Override
     protected void handleErrorOutput(String output) {
         if (redirector.getErrorStream() != null) {
             redirector.handleErrorOutput(output);
@@ -789,6 +847,7 @@
      *
      * @since Ant 1.5.2
      */
+    @Override
     protected void handleErrorFlush(String output) {
         if (redirector.getErrorStream() != null) {
             redirector.handleErrorFlush(output);
@@ -840,7 +899,7 @@
     }
 
     /**
-     * Executes the given classname with the given arguments in a separate VM.
+     * Executes the given source-file or classname with the given arguments in a separate VM.
      * @param command String[] of command-line arguments.
      */
     private int fork(String[] command) throws BuildException {
@@ -895,8 +954,8 @@
     private void setupEnvironment(Execute exe) {
         String[] environment = env.getVariables();
         if (environment != null) {
-            for (int i = 0; i < environment.length; i++) {
-                log("Setting environment variable: " + environment[i],
+            for (String element : environment) {
+                log("Setting environment variable: " + element,
                     Project.MSG_VERBOSE);
             }
         }
@@ -912,7 +971,7 @@
     private void setupWorkingDir(Execute exe) {
         if (dir == null) {
             dir = getProject().getBaseDir();
-        } else if (!dir.exists() || !dir.isDirectory()) {
+        } else if (!dir.isDirectory()) {
             throw new BuildException(dir.getAbsolutePath()
                                      + " is not a valid directory",
                                      getLocation());
@@ -960,10 +1019,7 @@
     protected void run(String classname, Vector<String> args) throws BuildException {
         CommandlineJava cmdj = new CommandlineJava();
         cmdj.setClassname(classname);
-        final int size = args.size();
-        for (int i = 0; i < size; i++) {
-            cmdj.createArgument().setValue(args.elementAt(i));
-        }
+        args.forEach(arg -> cmdj.createArgument().setValue(arg));
         run(cmdj);
     }
 
@@ -987,7 +1043,7 @@
         if (timeout == null) {
             return null;
         }
-        return new ExecuteWatchdog(timeout.longValue());
+        return new ExecuteWatchdog(timeout);
     }
 
     /**
@@ -1018,4 +1074,6 @@
     public CommandlineJava.SysProperties getSysProperties() {
         return getCommandLine().getSystemProperties();
     }
+
+
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Javac.java b/src/main/org/apache/tools/ant/taskdefs/Javac.java
index a9bcb6a..f79a4aa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Javac.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Javac.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,16 +19,15 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileFilter;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.TreeMap;
 
 import org.apache.tools.ant.BuildException;
@@ -124,7 +123,7 @@
     protected boolean failOnError = true;
     protected boolean listFiles = false;
     protected File[] compileList = new File[0];
-    private Map<String, Long> packageInfos = new HashMap<String, Long>();
+    private Map<String, Long> packageInfos = new HashMap<>();
     // CheckStyle:VisibilityModifier ON
 
     private String source;
@@ -146,23 +145,17 @@
     }
 
     private String assumedJavaVersion() {
-        if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_4)) {
-            return CompilerAdapterFactory.COMPILER_JAVAC_1_4;
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5)) {
-            return CompilerAdapterFactory.COMPILER_JAVAC_1_5;
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6)) {
-            return CompilerAdapterFactory.COMPILER_JAVAC_1_6;
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_7)) {
-            return CompilerAdapterFactory.COMPILER_JAVAC_1_7;
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8)) {
+        if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8)) {
             return CompilerAdapterFactory.COMPILER_JAVAC_1_8;
-        } else if (JavaEnvUtils.isAtLeastJavaVersion("10")) {
-            return CompilerAdapterFactory.COMPILER_JAVAC_10_PLUS;
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_9)) {
-            return CompilerAdapterFactory.COMPILER_JAVAC_9;
-        } else {
-            return CompilerAdapterFactory.COMPILER_CLASSIC;
         }
+        if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_9)) {
+            return CompilerAdapterFactory.COMPILER_JAVAC_9;
+        }
+        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_10)) {
+            return CompilerAdapterFactory.COMPILER_JAVAC_10_PLUS;
+        }
+        // as we are assumed to be 1.8+ and classic refers to the really old ones,  default to modern
+        return CompilerAdapterFactory.COMPILER_MODERN;
     }
 
     /**
@@ -808,7 +801,7 @@
      * @param include if true, includes Ant's own classpath in the classpath
      */
     public void setIncludeantruntime(final boolean include) {
-        includeAntRuntime = Boolean.valueOf(include);
+        includeAntRuntime = include;
     }
 
     /**
@@ -816,7 +809,7 @@
      * @return whether or not the ant classpath is to be included in the classpath
      */
     public boolean getIncludeantruntime() {
-        return includeAntRuntime != null ? includeAntRuntime.booleanValue() : true;
+        return includeAntRuntime == null || includeAntRuntime;
     }
 
     /**
@@ -1060,8 +1053,8 @@
      */
     public void add(final CompilerAdapter adapter) {
         if (nestedAdapter != null) {
-            throw new BuildException("Can't have more than one compiler"
-                                     + " adapter");
+            throw new BuildException(
+                "Can't have more than one compiler adapter");
         }
         nestedAdapter = adapter;
     }
@@ -1109,7 +1102,7 @@
      */
     protected void resetFileLists() {
         compileList = new File[0];
-        packageInfos = new HashMap<String, Long>();
+        packageInfos = new HashMap<>();
     }
 
     /**
@@ -1152,9 +1145,8 @@
             }
 
             final DirectoryScanner ds = this.getDirectoryScanner(srcDir);
-            final String[] files = ds.getIncludedFiles();
 
-            scanDir(srcDir, destDir != null ? destDir : srcDir, files);
+            scanDir(srcDir, destDir != null ? destDir : srcDir, ds.getIncludedFiles());
         }
     }
 
@@ -1162,8 +1154,8 @@
         final FileUtils fu = FileUtils.getFileUtils();
         for (String pathElement : moduleSourcepath.list()) {
             boolean valid = false;
-            for (Map.Entry<String,Collection<File>> modules : resolveModuleSourcePathElement(
-                    getProject().getBaseDir(), pathElement).entrySet()) {
+            for (Map.Entry<String, Collection<File>> modules : resolveModuleSourcePathElement(
+                getProject().getBaseDir(), pathElement).entrySet()) {
                 final String moduleName = modules.getKey();
                 for (File srcDir : modules.getValue()) {
                     if (srcDir.exists()) {
@@ -1264,8 +1256,8 @@
             if (isJdkCompiler(compilerImpl)) {
                 compilerImpl = CompilerAdapterFactory.COMPILER_EXTJAVAC;
             } else {
-                log("Since compiler setting isn't classic or modern, "
-                    + "ignoring fork setting.", Project.MSG_WARN);
+                log("Since compiler setting isn't classic or modern, ignoring fork setting.",
+                    Project.MSG_WARN);
             }
         }
         return compilerImpl;
@@ -1320,13 +1312,12 @@
         if (destDir != null && !destDir.isDirectory()) {
             throw new BuildException("destination directory \""
                                      + destDir
-                                     + "\" does not exist "
-                                     + "or is not a directory", getLocation());
+                                     + "\" does not exist or is not a directory", getLocation());
         }
-        if (includeAntRuntime == null && getProject().getProperty("build.sysclasspath") == null) {
-            log(getLocation() + "warning: 'includeantruntime' was not set, " +
-                    "defaulting to build.sysclasspath=last; set to false for repeatable builds",
-                    Project.MSG_WARN);
+        if (includeAntRuntime == null && getProject().getProperty(MagicNames.BUILD_SYSCLASSPATH) == null) {
+            log(getLocation() + "warning: 'includeantruntime' was not set, defaulting to "
+                            + MagicNames.BUILD_SYSCLASSPATH + "=last; set to false for repeatable builds",
+                Project.MSG_WARN);
         }
     }
 
@@ -1344,9 +1335,8 @@
                 + (destDir != null ? " to " + destDir : ""));
 
             if (listFiles) {
-                for (int i = 0; i < compileList.length; i++) {
-                  final String filename = compileList[i].getAbsolutePath();
-                  log(filename);
+                for (File element : compileList) {
+                  log(element.getAbsolutePath());
                 }
             }
 
@@ -1381,9 +1371,8 @@
                 }
                 if (failOnError) {
                     throw new BuildException(FAIL_MSG, getLocation());
-                } else {
-                    log(FAIL_MSG, Project.MSG_ERR);
                 }
+                log(FAIL_MSG, Project.MSG_ERR);
             }
         }
     }
@@ -1405,20 +1394,19 @@
     }
 
     private void lookForPackageInfos(final File srcDir, final File[] newFiles) {
-        for (int i = 0; i < newFiles.length; i++) {
-            final File f = newFiles[i];
-            if (!f.getName().equals("package-info.java")) {
+        for (File f : newFiles) {
+            if (!"package-info.java".equals(f.getName())) {
                 continue;
             }
-            final String path = FILE_UTILS.removeLeadingPath(srcDir, f).
-                    replace(File.separatorChar, '/');
+            final String path = FILE_UTILS.removeLeadingPath(srcDir, f)
+                    .replace(File.separatorChar, '/');
             final String suffix = "/package-info.java";
             if (!path.endsWith(suffix)) {
                 log("anomalous package-info.java path: " + path, Project.MSG_WARN);
                 continue;
             }
             final String pkg = path.substring(0, path.length() - suffix.length());
-            packageInfos.put(pkg, new Long(f.lastModified()));
+            packageInfos.put(pkg, f.lastModified());
         }
     }
 
@@ -1428,27 +1416,24 @@
      * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43114">Bug #43114</a>
      */
     private void generateMissingPackageInfoClasses(final File dest) throws IOException {
-        for (final Entry<String, Long> entry : packageInfos.entrySet()) {
+        for (final Map.Entry<String, Long> entry : packageInfos.entrySet()) {
             final String pkg = entry.getKey();
             final Long sourceLastMod = entry.getValue();
             final File pkgBinDir = new File(dest, pkg.replace('/', File.separatorChar));
             pkgBinDir.mkdirs();
             final File pkgInfoClass = new File(pkgBinDir, "package-info.class");
-            if (pkgInfoClass.isFile() && pkgInfoClass.lastModified() >= sourceLastMod.longValue()) {
+            if (pkgInfoClass.isFile() && pkgInfoClass.lastModified() >= sourceLastMod) {
                 continue;
             }
             log("Creating empty " + pkgInfoClass);
-            final OutputStream os = new FileOutputStream(pkgInfoClass);
-            try {
+            try (OutputStream os = Files.newOutputStream(pkgInfoClass.toPath())) {
                 os.write(PACKAGE_INFO_CLASS_HEADER);
-                final byte[] name = pkg.getBytes("UTF-8");
+                final byte[] name = pkg.getBytes(StandardCharsets.UTF_8);
                 final int length = name.length + /* "/package-info" */ 13;
                 os.write((byte) length / 256);
                 os.write((byte) length % 256);
                 os.write(name);
                 os.write(PACKAGE_INFO_CLASS_FOOTER);
-            } finally {
-                os.close();
             }
         }
     }
@@ -1460,7 +1445,7 @@
      * @since 1.9.7
      */
     private static boolean hasPath(final Path path) {
-        return path != null && path.size() > 0;
+        return path != null && !path.isEmpty();
     }
 
     /**
@@ -1471,10 +1456,10 @@
      * @return a mapping from module name to module source roots
      * @since 1.9.7
      */
-    private static Map<String,Collection<File>> resolveModuleSourcePathElement(
+    private static Map<String, Collection<File>> resolveModuleSourcePathElement(
             final File projectDir,
             final String element) {
-        final Map<String,Collection<File>> result = new TreeMap<String, Collection<File>>();
+        final Map<String, Collection<File>> result = new TreeMap<>();
         for (CharSequence resolvedElement : expandGroups(element)) {
             findModules(projectDir, resolvedElement.toString(), result);
         }
@@ -1494,7 +1479,7 @@
      */
     private static Collection<? extends CharSequence> expandGroups(
             final CharSequence element) {
-        List<StringBuilder> result = new ArrayList<StringBuilder>();
+        List<StringBuilder> result = new ArrayList<>();
         result.add(new StringBuilder());
         StringBuilder resolved = new StringBuilder();
         for (int i = 0; i < element.length(); i++) {
@@ -1508,7 +1493,7 @@
                                 element,
                                 i));
                     }
-                    final Collection<? extends CharSequence> parts = resolveGroup(element.subSequence(i+1, end));
+                    final Collection<? extends CharSequence> parts = resolveGroup(element.subSequence(i + 1, end));
                     switch (parts.size()) {
                         case 0:
                             break;
@@ -1517,7 +1502,7 @@
                             break;
                         default:
                             final List<StringBuilder> oldRes = result;
-                            result = new ArrayList<StringBuilder>(oldRes.size() * parts.size());
+                            result = new ArrayList<>(oldRes.size() * parts.size());
                             for (CharSequence part : parts) {
                                 for (CharSequence prefix : oldRes) {
                                     result.add(new StringBuilder(prefix).append(resolved).append(part));
@@ -1544,7 +1529,7 @@
      * @since 1.9.7
      */
     private static Collection<? extends CharSequence> resolveGroup(final CharSequence group) {
-        final Collection<CharSequence> result = new ArrayList<CharSequence>();
+        final Collection<CharSequence> result = new ArrayList<>();
         int start = 0;
         int depth = 0;
         for (int i = 0; i < group.length(); i++) {
@@ -1606,32 +1591,32 @@
     private static void findModules(
             final File root,
             String pattern,
-            final Map<String,Collection<File>> collector) {
+            final Map<String, Collection<File>> collector) {
         pattern = pattern
                 .replace('/', File.separatorChar)
                 .replace('\\', File.separatorChar);
         final int startIndex = pattern.indexOf(MODULE_MARKER);
         if (startIndex == -1) {
             findModules(root, pattern, null, collector);
-        } else {
-            if (startIndex == 0) {
-                throw new BuildException("The modulesourcepath entry must be a folder.");
-            }
-            final int endIndex = startIndex + MODULE_MARKER.length();
-            if (pattern.charAt(startIndex - 1) != File.separatorChar) {
-                    throw new BuildException("The module mark must be preceded by separator");
-            }
-            if (endIndex < pattern.length() && pattern.charAt(endIndex) != File.separatorChar) {
-                throw new BuildException("The module mark must be followed by separator");
-            }
-            if (pattern.indexOf(MODULE_MARKER, endIndex) != -1) {
-                throw new BuildException("The modulesourcepath entry must contain at most one module mark");
-            }
-            final String pathToModule = pattern.substring(0, startIndex);
-            final String pathInModule = endIndex == pattern.length()
-                    ? null : pattern.substring(endIndex + 1);  //+1 the separator
-            findModules(root, pathToModule, pathInModule, collector);
+            return;
         }
+        if (startIndex == 0) {
+            throw new BuildException("The modulesourcepath entry must be a folder.");
+        }
+        final int endIndex = startIndex + MODULE_MARKER.length();
+        if (pattern.charAt(startIndex - 1) != File.separatorChar) {
+                throw new BuildException("The module mark must be preceded by separator");
+        }
+        if (endIndex < pattern.length() && pattern.charAt(endIndex) != File.separatorChar) {
+            throw new BuildException("The module mark must be followed by separator");
+        }
+        if (pattern.indexOf(MODULE_MARKER, endIndex) != -1) {
+            throw new BuildException("The modulesourcepath entry must contain at most one module mark");
+        }
+        final String pathToModule = pattern.substring(0, startIndex);
+        final String pathInModule = endIndex == pattern.length()
+                ? null : pattern.substring(endIndex + 1);  //+1 the separator
+        findModules(root, pathToModule, pathInModule, collector);
     }
 
     /**
@@ -1647,26 +1632,15 @@
         final String pathToModule,
         final String pathInModule,
         final Map<String,Collection<File>> collector) {
-        final FileUtils fu = FileUtils.getFileUtils();
-        final File f = fu.resolveFile(root, pathToModule);
+        final File f = FileUtils.getFileUtils().resolveFile(root, pathToModule);
         if (!f.isDirectory()) {
             return;
         }
-        final File[] modules = f.listFiles(new FileFilter() {
-            public boolean accept(File pathname) {
-                return pathname.isDirectory();
-            }
-        });
-        for (File module : modules) {
+        for (File module : f.listFiles(File::isDirectory)) {
             final String moduleName = module.getName();
-            final File moduleSourceRoot = pathInModule == null ?
-                    module :
-                    new File(module, pathInModule);
-            Collection<File> moduleRoots = collector.get(moduleName);
-            if (moduleRoots == null) {
-                moduleRoots = new ArrayList<File>();
-                collector.put(moduleName, moduleRoots);
-            }
+            final File moduleSourceRoot = pathInModule == null
+                    ? module : new File(module, pathInModule);
+            Collection<File> moduleRoots = collector.computeIfAbsent(moduleName, k -> new ArrayList<>());
             moduleRoots.add(moduleSourceRoot);
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Javadoc.java b/src/main/org/apache/tools/ant/taskdefs/Javadoc.java
index ce79c27..efee9d3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Javadoc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Javadoc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,18 +20,17 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
-import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -39,8 +38,10 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -60,7 +61,6 @@
 import org.apache.tools.ant.types.resources.FileProvider;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Generates Javadoc documentation for a collection
@@ -86,10 +86,6 @@
  * @ant.task category="java"
  */
 public class Javadoc extends Task {
-    // Whether *this VM* is 1.4+ (but also check executable != null).
-
-    private static final boolean JAVADOC_5 =
-        !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_4);
 
     private static final String LOAD_FRAME = "function loadFrames() {";
     private static final int LOAD_FRAME_LEN = LOAD_FRAME.length();
@@ -227,7 +223,7 @@
     public class DocletInfo extends ExtensionInfo {
 
         /** Collection of doclet parameters. */
-        private final Vector<DocletParam> params = new Vector<DocletParam>();
+        private final List<DocletParam> params = new Vector<>();
 
         /**
          * Create a doclet parameter to be configured by Ant.
@@ -236,8 +232,7 @@
          */
         public DocletParam createParam() {
             final DocletParam param = new DocletParam();
-            params.addElement(param);
-
+            params.add(param);
             return param;
         }
 
@@ -247,7 +242,7 @@
          * @return an Enumeration of DocletParam instances.
          */
         public Enumeration<DocletParam> getParams() {
-            return params.elements();
+            return Collections.enumeration(params);
         }
     }
 
@@ -380,8 +375,11 @@
      * contains special handling for FileSets that has to occur at
      * task runtime.</p>
      */
-    public class ResourceCollectionContainer {
-        private final ArrayList<ResourceCollection> rcs = new ArrayList<ResourceCollection>();
+    public class ResourceCollectionContainer
+        implements Iterable<ResourceCollection> {
+
+        private final List<ResourceCollection> rcs = new ArrayList<>();
+
         /**
          * Add a resource collection to the container.
          * @param rc the collection to add.
@@ -394,7 +392,8 @@
          * Get an iterator on the collection.
          * @return an iterator.
          */
-        private Iterator<ResourceCollection> iterator() {
+        @Override
+        public Iterator<ResourceCollection> iterator() {
             return rcs.iterator();
         }
     }
@@ -424,12 +423,12 @@
      * @param value the argument value.
      */
     private void addArgIfNotEmpty(final String key, final String value) {
-        if (value != null && value.length() != 0) {
-            cmd.createArgument().setValue(key);
-            cmd.createArgument().setValue(value);
-        } else {
+        if (value == null || value.isEmpty()) {
             log("Warning: Leaving out empty argument '" + key + "'",
                 Project.MSG_WARN);
+        } else {
+            cmd.createArgument().setValue(key);
+            cmd.createArgument().setValue(value);
         }
     }
 
@@ -445,10 +444,10 @@
     private boolean failOnWarning = false;
     private Path sourcePath = null;
     private File destDir = null;
-    private final Vector<SourceFile> sourceFiles = new Vector<SourceFile>();
-    private final Vector<PackageName> packageNames = new Vector<PackageName>();
-    private final Vector<PackageName> excludePackageNames = new Vector<PackageName>(1);
-    private final List<PackageName> moduleNames = new ArrayList<PackageName>();
+    private final List<SourceFile> sourceFiles = new Vector<>();
+    private final List<PackageName> packageNames = new Vector<>();
+    private final List<PackageName> excludePackageNames = new Vector<>(1);
+    private final List<PackageName> moduleNames = new ArrayList<>();
     private boolean author = true;
     private boolean version = true;
     private DocletInfo doclet = null;
@@ -458,9 +457,9 @@
     private Path moduleSourcePath = null;
     private String group = null;
     private String packageList = null;
-    private final Vector<LinkArgument> links = new Vector<LinkArgument>();
-    private final Vector<GroupArgument> groups = new Vector<GroupArgument>();
-    private final Vector<Object> tags = new Vector<Object>();
+    private final List<LinkArgument> links = new Vector<>();
+    private final List<GroupArgument> groups = new Vector<>();
+    private final List<Object> tags = new Vector<>();
     private boolean useDefaultExcludes = true;
     private Html doctitle = null;
     private Html header = null;
@@ -480,7 +479,7 @@
 
     private final ResourceCollectionContainer nestedSourceFiles
         = new ResourceCollectionContainer();
-    private final Vector<DirSet> packageSets = new Vector<DirSet>();
+    private final List<DirSet> packageSets = new Vector<>();
 
     /**
      * Work around command line length limit by using an external file
@@ -571,7 +570,7 @@
      *
      * @param mp a Path instance containing the modules.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setModulePath(final Path mp) {
         if (modulePath == null) {
@@ -587,7 +586,7 @@
      *
      * @return a new Path instance to be configured by the Ant core.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public Path createModulePath() {
         if (modulePath == null) {
@@ -601,7 +600,7 @@
      *
      * @param r the reference containing the module path definition.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setModulePathref(final Reference r) {
         createModulePath().setRefid(r);
@@ -612,7 +611,7 @@
      *
      * @param mp a Path instance containing the sources for modules.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setModuleSourcePath(final Path mp) {
         if (moduleSourcePath == null) {
@@ -628,7 +627,7 @@
      *
      * @return a new Path instance to be configured by the Ant core.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public Path createModuleSourcePath() {
         if (moduleSourcePath == null) {
@@ -642,7 +641,7 @@
      *
      * @param r the reference containing the module source path definition.
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setModuleSourcePathref(final Reference r) {
         createModuleSourcePath().setRefid(r);
@@ -680,7 +679,7 @@
      * @param sf the source file to be processed.
      */
     public void addSource(final SourceFile sf) {
-        sourceFiles.addElement(sf);
+        sourceFiles.add(sf);
     }
 
     /**
@@ -706,12 +705,10 @@
      *
      * @param modules a comma separated list of module names
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void setModulenames(final String modules) {
-        final StringTokenizer tok = new StringTokenizer(modules, ",");
-        while (tok.hasMoreTokens()) {
-            final String m = tok.nextToken();
+        for (String m : modules.split(",")) {
             final PackageName mn = new PackageName();
             mn.setName(m);
             addModule(mn);
@@ -727,7 +724,7 @@
      * @param pn the package name, possibly wildcarded.
      */
     public void addPackage(final PackageName pn) {
-        packageNames.addElement(pn);
+        packageNames.add(pn);
     }
 
     /**
@@ -735,7 +732,7 @@
      *
      * @param mn the module name
      *
-     * @since Ant 1.9.14
+     * @since Ant 1.10.6
      */
     public void addModule(final PackageName mn) {
         moduleNames.add(mn);
@@ -763,7 +760,7 @@
      * @param pn the name of the package (wildcards are not permitted).
      */
     public void addExcludePackage(final PackageName pn) {
-        excludePackageNames.addElement(pn);
+        excludePackageNames.add(pn);
     }
 
     /**
@@ -887,7 +884,7 @@
      * @param tagletInfo information about the taglet.
      */
     public void addTaglet(final ExtensionInfo tagletInfo) {
-        tags.addElement(tagletInfo);
+        tags.add(tagletInfo);
     }
 
     /**
@@ -1165,7 +1162,7 @@
         final String linkOfflineError = "The linkoffline attribute must include"
             + " a URL and a package-list file location separated by a"
             + " space";
-        if (src.trim().length() == 0) {
+        if (src.trim().isEmpty()) {
             throw new BuildException(linkOfflineError);
         }
         final StringTokenizer tok = new StringTokenizer(src, " ", false);
@@ -1306,7 +1303,7 @@
      */
     public LinkArgument createLink() {
         final LinkArgument la = new LinkArgument();
-        links.addElement(la);
+        links.add(la);
         return la;
     }
 
@@ -1419,7 +1416,7 @@
      */
     public TagArgument createTag() {
         final TagArgument ta = new TagArgument();
-        tags.addElement (ta);
+        tags.add(ta);
         return ta;
     }
 
@@ -1492,48 +1489,47 @@
             final StringTokenizer tok = new StringTokenizer(verboseScope, ",");
             while (tok.hasMoreTokens()) {
                 final String next = tok.nextToken().trim();
-                if (next.equals("all")) {
+                if ("all".equals(next)) {
                     if (gotAll) {
-                        getProject().log ("Repeated tag scope element: all",
+                        getProject().log("Repeated tag scope element: all",
                                           Project.MSG_VERBOSE);
                     }
                     gotAll = true;
                 } else {
                     int i;
                     for (i = 0; i < SCOPE_ELEMENTS.length; i++) {
-                        if (next.equals (SCOPE_ELEMENTS[i])) {
+                        if (SCOPE_ELEMENTS[i].equals(next)) {
                             break;
                         }
                     }
                     if (i == SCOPE_ELEMENTS.length) {
-                        throw new BuildException ("Unrecognised scope element: "
-                                                  + next);
-                    } else {
-                        if (elements[i]) {
-                            getProject().log ("Repeated tag scope element: "
-                                              + next, Project.MSG_VERBOSE);
-                        }
-                        elements[i] = true;
-                        gotNotAll = true;
+                        throw new BuildException(
+                            "Unrecognised scope element: %s", next);
                     }
+                    if (elements[i]) {
+                        getProject().log("Repeated tag scope element: " + next,
+                            Project.MSG_VERBOSE);
+                    }
+                    elements[i] = true;
+                    gotNotAll = true;
                 }
             }
 
             if (gotNotAll && gotAll) {
-                throw new BuildException ("Mixture of \"all\" and other scope "
-                                          + "elements in tag parameter.");
+                throw new BuildException(
+                    "Mixture of \"all\" and other scope elements in tag parameter.");
             }
             if (!gotNotAll && !gotAll) {
-                throw new BuildException ("No scope elements specified in tag "
-                                          + "parameter.");
+                throw new BuildException(
+                    "No scope elements specified in tag parameter.");
             }
             if (gotAll) {
                 this.scope = "a";
             } else {
-                final StringBuffer buff = new StringBuffer (elements.length);
+                final StringBuilder buff = new StringBuilder(elements.length);
                 for (int i = 0; i < elements.length; i++) {
                     if (elements[i]) {
-                        buff.append (SCOPE_ELEMENTS[i].charAt(0));
+                        buff.append(SCOPE_ELEMENTS[i].charAt(0));
                     }
                 }
                 this.scope = buff.toString();
@@ -1556,17 +1552,17 @@
          *                           is <code>null</code> or empty.
          */
         public String getParameter() throws BuildException {
-            if (name == null || name.equals("")) {
-                throw new BuildException ("No name specified for custom tag.");
+            if (name == null || name.isEmpty()) {
+                throw new BuildException("No name specified for custom tag.");
             }
             if (getDescription() != null) {
                 return name + ":" + (enabled ? "" : "X")
                     + scope + ":" + getDescription();
-            } else if (!enabled || !"a".equals(scope)) {
-                return name + ":" + (enabled ? "" : "X") + scope;
-            } else {
-                return name;
             }
+            if (!enabled || !"a".equals(scope)) {
+                return name + ":" + (enabled ? "" : "X") + scope;
+            }
+            return name;
         }
     }
 
@@ -1577,22 +1573,16 @@
      */
     public GroupArgument createGroup() {
         final GroupArgument ga = new GroupArgument();
-        groups.addElement(ga);
+        groups.add(ga);
         return ga;
     }
 
-
     /**
      * A class corresponding to the group nested element.
      */
     public class GroupArgument {
         private Html title;
-        private final Vector<PackageName> packages = new Vector<PackageName>();
-
-        /** Constructor for GroupArgument */
-        public GroupArgument() {
-            //empty
-        }
+        private final List<PackageName> packages = new Vector<>();
 
         /**
          * Set the title attribute using a string.
@@ -1603,6 +1593,7 @@
             h.addText(src);
             addTitle(h);
         }
+
         /**
          * Set the title attribute using a nested Html value.
          * @param text a <code>Html</code> value
@@ -1632,12 +1623,13 @@
                 addPackage(pn);
             }
         }
+
         /**
          * Add a package nested element.
          * @param pn a nested element specifying the package.
          */
         public void addPackage(final PackageName pn) {
-            packages.addElement(pn);
+            packages.add(pn);
         }
 
         /**
@@ -1645,15 +1637,8 @@
          * @return the packages as a string
          */
         public String getPackages() {
-            final StringBuffer p = new StringBuffer();
-            final int size = packages.size();
-            for (int i = 0; i < size; i++) {
-                if (i > 0) {
-                    p.append(":");
-                }
-                p.append(packages.elementAt(i).toString());
-            }
-            return p.toString();
+            return packages.stream().map(Object::toString)
+                .collect(Collectors.joining(":"));
         }
     }
 
@@ -1717,7 +1702,7 @@
      * @since 1.5
      */
     public void addPackageset(final DirSet packageSet) {
-        packageSets.addElement(packageSet);
+        packageSets.add(packageSet);
     }
 
     /**
@@ -1824,7 +1809,7 @@
     public void execute() throws BuildException {
         checkTaskName();
 
-        final Vector<String> packagesToDoc = new Vector<String>();
+        final List<String> packagesToDoc = new Vector<>();
         final Path sourceDirs = new Path(getProject());
 
         checkPackageAndSourcePath();
@@ -1836,8 +1821,7 @@
         parsePackages(packagesToDoc, sourceDirs);
         checkPackages(packagesToDoc, sourceDirs);
 
-        @SuppressWarnings("unchecked")
-        final Vector<SourceFile> sourceFilesToDoc = (Vector<SourceFile>) sourceFiles.clone();
+        final List<SourceFile> sourceFilesToDoc = new ArrayList<>(sourceFiles);
         addSourceFiles(sourceFilesToDoc);
 
         checkPackagesToDoc(packagesToDoc, sourceFilesToDoc);
@@ -1862,8 +1846,12 @@
         doDocFilesSubDirs(toExecute); // docfilessubdir attribute
         doModuleArguments(toExecute);
 
-        doJava14(toExecute);
-        if (breakiterator && (doclet == null || JAVADOC_5)) {
+        doTags(toExecute);
+        doSource(toExecute);
+        doLinkSource(toExecute);
+        doNoqualifier(toExecute);
+		
+        if (breakiterator) {
             toExecute.createArgument().setValue("-breakiterator");
         }
         // If using an external file, write the command line options to it
@@ -1930,7 +1918,7 @@
                 throw new BuildException("Javadoc returned " + ret,
                                          getLocation());
             }
-            if (out.sawWarnings() && failOnWarning) {
+            if (failOnWarning && (out.sawWarnings() || err.sawWarnings())) {
                 throw new BuildException("Javadoc issued warnings.",
                                          getLocation());
             }
@@ -1966,25 +1954,24 @@
         }
     }
 
-    private void checkPackages(final Vector<String> packagesToDoc, final Path sourceDirs) {
-        if (packagesToDoc.size() != 0 && sourceDirs.size() == 0) {
-            final String msg = "sourcePath attribute must be set when "
-                + "specifying package names.";
-            throw new BuildException(msg);
+    private void checkPackages(final List<String> packagesToDoc, final Path sourceDirs) {
+        if (!packagesToDoc.isEmpty() && sourceDirs.isEmpty()) {
+            throw new BuildException(
+                "sourcePath attribute must be set when specifying package names.");
         }
     }
 
     private void checkPackagesToDoc(
-        final Vector<String> packagesToDoc, final Vector<SourceFile> sourceFilesToDoc) {
-        if (packageList == null && packagesToDoc.size() == 0
-            && sourceFilesToDoc.size() == 0 && moduleNames.isEmpty()) {
+        final List<String> packagesToDoc, final List<SourceFile> sourceFilesToDoc) {
+        if (packageList == null && packagesToDoc.isEmpty()
+            && sourceFilesToDoc.isEmpty() && moduleNames.isEmpty()) {
             throw new BuildException("No source files, no packages and no modules have "
                                      + "been specified.");
         }
     }
 
     private void doSourcePath(final Commandline toExecute, final Path sourceDirs) {
-        if (sourceDirs.size() > 0) {
+        if (!sourceDirs.isEmpty()) {
             toExecute.createArgument().setValue("-sourcepath");
             toExecute.createArgument().setPath(sourceDirs);
         }
@@ -2009,7 +1996,7 @@
         }
 
         if (classpath == null) {
-            classpath = (new Path(getProject())).concatSystemClasspath("last");
+            classpath = new Path(getProject()).concatSystemClasspath("last");
         } else {
             classpath = classpath.concatSystemClasspath("ignore");
         }
@@ -2034,14 +2021,12 @@
     private void doDoclet(final Commandline toExecute) {
         if (doclet != null) {
             if (doclet.getName() == null) {
-                throw new BuildException("The doclet name must be specified.",
-                    getLocation());
+                throw new BuildException("The doclet name must be specified.", getLocation());
             }
             toExecute.createArgument().setValue("-doclet");
             toExecute.createArgument().setValue(doclet.getName());
             if (doclet.getPath() != null) {
-                final Path docletPath
-                    = doclet.getPath().concatSystemClasspath("ignore");
+                final Path docletPath = doclet.getPath().concatSystemClasspath("ignore");
                 if (docletPath.size() != 0) {
                     toExecute.createArgument().setValue("-docletpath");
                     toExecute.createArgument().setPath(docletPath);
@@ -2062,7 +2047,6 @@
     private void writeExternalArgs(final Commandline toExecute) {
         // If using an external file, write the command line options to it
         File optionsTmpFile = null;
-        BufferedWriter optionsListWriter = null;
         try {
             optionsTmpFile = FILE_UTILS.createTempFile(
                 getProject(), "javadocOptions", "", null, true, true);
@@ -2070,23 +2054,20 @@
             toExecute.clearArgs();
             toExecute.createArgument().setValue(
                 "@" + optionsTmpFile.getAbsolutePath());
-            optionsListWriter = new BufferedWriter(
-                new FileWriter(optionsTmpFile.getAbsolutePath(), true));
-            for (int i = 0; i < listOpt.length; i++) {
-                final String string = listOpt[i];
-                if (string.startsWith("-J-")) {
-                    toExecute.createArgument().setValue(string);
-                } else  {
-                    if (string.startsWith("-")) {
-                        optionsListWriter.write(string);
+            try (BufferedWriter optionsListWriter = new BufferedWriter(
+                new FileWriter(optionsTmpFile.getAbsolutePath(), true))) {
+                for (final String opt : listOpt) {
+                    if (opt.startsWith("-J-")) {
+                        toExecute.createArgument().setValue(opt);
+                    } else if (opt.startsWith("-")) {
+                        optionsListWriter.write(opt);
                         optionsListWriter.write(" ");
                     } else {
-                        optionsListWriter.write(quoteString(string));
+                        optionsListWriter.write(quoteString(opt));
                         optionsListWriter.newLine();
                     }
                 }
             }
-            optionsListWriter.close();
         } catch (final IOException ex) {
             if (optionsTmpFile != null) {
                 optionsTmpFile.delete();
@@ -2094,8 +2075,6 @@
             throw new BuildException(
                 "Error creating or writing temporary file for javadoc options",
                 ex, getLocation());
-        } finally {
-            FileUtils.close(optionsListWriter);
         }
     }
 
@@ -2112,85 +2091,78 @@
     }
 
     private void doLinks(final Commandline toExecute) {
-        if (links.size() != 0) {
-            for (final Enumeration<LinkArgument> e = links.elements(); e.hasMoreElements();) {
-                final LinkArgument la = e.nextElement();
-
-                if (la.getHref() == null || la.getHref().length() == 0) {
-                    log("No href was given for the link - skipping",
-                        Project.MSG_VERBOSE);
+        for (final LinkArgument la : links) {
+            if (la.getHref() == null || la.getHref().isEmpty()) {
+                log("No href was given for the link - skipping",
+                    Project.MSG_VERBOSE);
+                continue;
+            }
+            String link = null;
+            if (la.shouldResolveLink()) {
+                final File hrefAsFile =
+                    getProject().resolveFile(la.getHref());
+                if (hrefAsFile.exists()) {
+                    try {
+                        link = FILE_UTILS.getFileURL(hrefAsFile)
+                            .toExternalForm();
+                    } catch (final MalformedURLException ex) {
+                        // should be impossible
+                        log("Warning: link location was invalid "
+                            + hrefAsFile, Project.MSG_WARN);
+                    }
+                }
+            }
+            if (link == null) {
+                // is the href a valid URL
+                try {
+                    final URL base = new URL("file://.");
+                    // created for the side effect of throwing a MalformedURLException
+                    new URL(base, la.getHref()); //NOSONAR
+                    link = la.getHref();
+                } catch (final MalformedURLException mue) {
+                    // ok - just skip
+                    log("Link href \"" + la.getHref()
+                        + "\" is not a valid url - skipping link",
+                        Project.MSG_WARN);
                     continue;
                 }
-                String link = null;
-                if (la.shouldResolveLink()) {
-                    final File hrefAsFile =
-                        getProject().resolveFile(la.getHref());
-                    if (hrefAsFile.exists()) {
-                        try {
-                            link = FILE_UTILS.getFileURL(hrefAsFile)
-                                .toExternalForm();
-                        } catch (final MalformedURLException ex) {
-                            // should be impossible
-                            log("Warning: link location was invalid "
-                                + hrefAsFile, Project.MSG_WARN);
-                        }
-                    }
-                }
-                if (link == null) {
-                    // is the href a valid URL
-                    try {
-                        final URL base = new URL("file://.");
-                        // created for the side effect of throwing a MalformedURLException
-                        new URL(base, la.getHref()); //NOSONAR
-                        link = la.getHref();
-                    } catch (final MalformedURLException mue) {
-                        // ok - just skip
-                        log("Link href \"" + la.getHref()
-                            + "\" is not a valid url - skipping link",
-                            Project.MSG_WARN);
-                        continue;
-                    }
-                }
+            }
 
-                if (la.isLinkOffline()) {
-                    final File packageListLocation = la.getPackagelistLoc();
-                    URL packageListURL = la.getPackagelistURL();
-                    if (packageListLocation == null
-                        && packageListURL == null) {
-                        throw new BuildException("The package list"
-                                                 + " location for link "
-                                                 + la.getHref()
-                                                 + " must be provided "
-                                                 + "because the link is "
-                                                 + "offline");
-                    }
-                    if (packageListLocation != null) {
-                        final File packageListFile =
-                            new File(packageListLocation, "package-list");
-                        if (packageListFile.exists()) {
-                            try {
-                                packageListURL =
-                                    FILE_UTILS.getFileURL(packageListLocation);
-                            } catch (final MalformedURLException ex) {
-                                log("Warning: Package list location was "
-                                    + "invalid " + packageListLocation,
-                                    Project.MSG_WARN);
-                            }
-                        } else {
-                            log("Warning: No package list was found at "
-                                + packageListLocation, Project.MSG_VERBOSE);
-                        }
-                    }
-                    if (packageListURL != null) {
-                        toExecute.createArgument().setValue("-linkoffline");
-                        toExecute.createArgument().setValue(link);
-                        toExecute.createArgument()
-                            .setValue(packageListURL.toExternalForm());
-                    }
-                } else {
-                    toExecute.createArgument().setValue("-link");
-                    toExecute.createArgument().setValue(link);
+            if (la.isLinkOffline()) {
+                final File packageListLocation = la.getPackagelistLoc();
+                URL packageListURL = la.getPackagelistURL();
+                if (packageListLocation == null
+                    && packageListURL == null) {
+                    throw new BuildException(
+                        "The package list location for link " + la.getHref()
+                            + " must be provided because the link is offline");
                 }
+                if (packageListLocation != null) {
+                    final File packageListFile =
+                        new File(packageListLocation, "package-list");
+                    if (packageListFile.exists()) {
+                        try {
+                            packageListURL =
+                                FILE_UTILS.getFileURL(packageListLocation);
+                        } catch (final MalformedURLException ex) {
+                            log("Warning: Package list location was "
+                                + "invalid " + packageListLocation,
+                                Project.MSG_WARN);
+                        }
+                    } else {
+                        log("Warning: No package list was found at "
+                            + packageListLocation, Project.MSG_VERBOSE);
+                    }
+                }
+                if (packageListURL != null) {
+                    toExecute.createArgument().setValue("-linkoffline");
+                    toExecute.createArgument().setValue(link);
+                    toExecute.createArgument()
+                        .setValue(packageListURL.toExternalForm());
+                }
+            } else {
+                toExecute.createArgument().setValue("-link");
+                toExecute.createArgument().setValue(link);
             }
         }
     }
@@ -2212,7 +2184,7 @@
             final StringTokenizer tok = new StringTokenizer(group, ",", false);
             while (tok.hasMoreTokens()) {
                 final String grp = tok.nextToken().trim();
-                final int space = grp.indexOf(" ");
+                final int space = grp.indexOf(' ');
                 if (space > 0) {
                     final String name = grp.substring(0, space);
                     final String pkgList = grp.substring(space + 1);
@@ -2226,97 +2198,87 @@
 
     // add the group arguments
     private void doGroups(final Commandline toExecute) {
-        if (groups.size() != 0) {
-            for (final Enumeration<GroupArgument> e = groups.elements(); e.hasMoreElements();) {
-                final GroupArgument ga = e.nextElement();
-                final String title = ga.getTitle();
-                final String packages = ga.getPackages();
-                if (title == null || packages == null) {
-                    throw new BuildException("The title and packages must "
-                                             + "be specified for group "
-                                             + "elements.");
-                }
-                toExecute.createArgument().setValue("-group");
-                toExecute.createArgument().setValue(expand(title));
-                toExecute.createArgument().setValue(packages);
+        for (final GroupArgument ga : groups) {
+            final String title = ga.getTitle();
+            final String packages = ga.getPackages();
+            if (title == null || packages == null) {
+                throw new BuildException(
+                    "The title and packages must be specified for group elements.");
             }
+            toExecute.createArgument().setValue("-group");
+            toExecute.createArgument().setValue(expand(title));
+            toExecute.createArgument().setValue(packages);
         }
     }
 
-    // Do java1.4 arguments
-    private void doJava14(final Commandline toExecute) {
-        for (final Enumeration<Object> e = tags.elements(); e.hasMoreElements();) {
-            final Object element = e.nextElement();
-            if (element instanceof TagArgument) {
-                final TagArgument ta = (TagArgument) element;
-                final File tagDir = ta.getDir(getProject());
-                if (tagDir == null) {
-                    // The tag element is not used as a fileset,
-                    // but specifies the tag directly.
-                    toExecute.createArgument().setValue ("-tag");
-                    toExecute.createArgument()
-                        .setValue (ta.getParameter());
-                } else {
-                    // The tag element is used as a
-                    // fileset. Parse all the files and create
-                    // -tag arguments.
-                    final DirectoryScanner tagDefScanner =
-                        ta.getDirectoryScanner(getProject());
-                    for (String file : tagDefScanner.getIncludedFiles()) {
-                        final File tagDefFile = new File(tagDir, file);
-                        try {
-                            final BufferedReader in = new BufferedReader(
-                                    new FileReader(tagDefFile));
-                            String line = null;
-                            while ((line = in.readLine()) != null) {
-                                toExecute.createArgument().setValue("-tag");
-                                toExecute.createArgument().setValue(line);
-                            }
-                            in.close();
-                        } catch (final IOException ioe) {
-                            throw new BuildException("Couldn't read  tag file from "
-                                    + tagDefFile.getAbsolutePath(), ioe);
-                        }
-                    }
-                }
-            } else {
-                final ExtensionInfo tagletInfo = (ExtensionInfo) element;
-                toExecute.createArgument().setValue("-taglet");
-                toExecute.createArgument().setValue(tagletInfo
-                                                    .getName());
-                if (tagletInfo.getPath() != null) {
-                    final Path tagletPath = tagletInfo.getPath()
-                        .concatSystemClasspath("ignore");
-                    if (tagletPath.size() != 0) {
-                        toExecute.createArgument()
-                            .setValue("-tagletpath");
-                        toExecute.createArgument().setPath(tagletPath);
-                    }
-                }
-            }
-        }
-
-        final String sourceArg = source != null ? source
-            : getProject().getProperty(MagicNames.BUILD_JAVAC_SOURCE);
-        if (sourceArg != null) {
-            toExecute.createArgument().setValue("-source");
-            toExecute.createArgument().setValue(sourceArg);
-        }
-
-        if (linksource && doclet == null) {
-            toExecute.createArgument().setValue("-linksource");
-        }
+    private void doNoqualifier(final Commandline toExecute) {
         if (noqualifier != null && doclet == null) {
             toExecute.createArgument().setValue("-noqualifier");
             toExecute.createArgument().setValue(noqualifier);
         }
     }
 
+    private void doLinkSource(final Commandline toExecute) {
+        if (linksource && doclet == null) {
+            toExecute.createArgument().setValue("-linksource");
+        }
+    }
+
+    private void doSource(final Commandline toExecute) {
+        final String sourceArg = source != null ? source : getProject().getProperty(MagicNames.BUILD_JAVAC_SOURCE);
+        if (sourceArg != null) {
+            toExecute.createArgument().setValue("-source");
+            toExecute.createArgument().setValue(sourceArg);
+        }
+    }
+
+    private void doTags(final Commandline toExecute) {
+        for (final Object element : tags) {
+            if (element instanceof TagArgument) {
+                final TagArgument ta = (TagArgument) element;
+                final File tagDir = ta.getDir(getProject());
+                if (tagDir == null) {
+                    // The tag element is not used as a fileset,
+                    // but specifies the tag directly.
+                    toExecute.createArgument().setValue("-tag");
+                    toExecute.createArgument().setValue(ta.getParameter());
+                } else {
+                    // The tag element is used as a
+                    // fileset. Parse all the files and create
+                    // -tag arguments.
+                    final DirectoryScanner tagDefScanner = ta.getDirectoryScanner(getProject());
+                    for (String file : tagDefScanner.getIncludedFiles()) {
+                        final File tagDefFile = new File(tagDir, file);
+                        try (final BufferedReader in = new BufferedReader(new FileReader(tagDefFile))) {
+                            in.lines().forEach(line -> {
+                                toExecute.createArgument().setValue("-tag");
+                                toExecute.createArgument().setValue(line);
+                            });
+                        } catch (final IOException ioe) {
+                            throw new BuildException("Couldn't read tag file from " + tagDefFile.getAbsolutePath(),
+                                    ioe);
+                        }
+                    }
+                }
+            } else {
+                final ExtensionInfo tagletInfo = (ExtensionInfo) element;
+                toExecute.createArgument().setValue("-taglet");
+                toExecute.createArgument().setValue(tagletInfo.getName());
+                if (tagletInfo.getPath() != null) {
+                    final Path tagletPath = tagletInfo.getPath().concatSystemClasspath("ignore");
+                    if (!tagletPath.isEmpty()) {
+                        toExecute.createArgument().setValue("-tagletpath");
+                        toExecute.createArgument().setPath(tagletPath);
+                    }
+                }
+            }
+        }
+    }
+
     private void doDocFilesSubDirs(final Commandline toExecute) {
         if (docFilesSubDirs) {
             toExecute.createArgument().setValue("-docfilessubdirs");
-            if (excludeDocFilesSubDir != null
-                && excludeDocFilesSubDir.trim().length() > 0) {
+            if (excludeDocFilesSubDir != null && !excludeDocFilesSubDir.trim().isEmpty()) {
                 toExecute.createArgument().setValue("-excludedocfilessubdir");
                 toExecute.createArgument().setValue(excludeDocFilesSubDir);
             }
@@ -2325,10 +2287,10 @@
 
     private void doSourceAndPackageNames(
         final Commandline toExecute,
-        final Vector<String> packagesToDoc,
-        final Vector<SourceFile> sourceFilesToDoc,
+        final List<String> packagesToDoc,
+        final List<SourceFile> sourceFilesToDoc,
         final boolean useExternalFile,
-        final File    tmpList,
+        final File tmpList,
         final BufferedWriter srcListWriter)
         throws IOException {
         for (final String packageName : packagesToDoc) {
@@ -2369,15 +2331,13 @@
      */
     private String quoteString(final String str) {
         if (!containsWhitespace(str)
-            && str.indexOf('\'') == -1
-            && str.indexOf('"') == -1) {
+            && !str.contains("'") && !str.contains("\"")) {
             return str;
         }
-        if (str.indexOf('\'') == -1) {
+        if (!str.contains("'")) {
             return quoteString(str, '\'');
-        } else {
-            return quoteString(str, '"');
         }
+        return quoteString(str, '"');
     }
 
     private boolean containsWhitespace(final String s) {
@@ -2390,7 +2350,7 @@
     }
 
     private String quoteString(final String str, final char delim) {
-        final StringBuffer buf = new StringBuffer(str.length() * 2);
+        final StringBuilder buf = new StringBuilder(str.length() * 2);
         buf.append(delim);
         boolean lastCharWasCR = false;
         for (final char c : str.toCharArray()) {
@@ -2436,13 +2396,11 @@
      *
      * @since 1.7
      */
-    private void addSourceFiles(final Vector<SourceFile> sf) {
-        final Iterator<ResourceCollection> e = nestedSourceFiles.iterator();
-        while (e.hasNext()) {
-            ResourceCollection rc = e.next();
+    private void addSourceFiles(final List<SourceFile> sf) {
+        for (ResourceCollection rc : nestedSourceFiles) {
             if (!rc.isFilesystemOnly()) {
-                throw new BuildException("only file system based resources are"
-                                         + " supported by javadoc");
+                throw new BuildException(
+                    "only file system based resources are supported by javadoc");
             }
             if (rc instanceof FileSet) {
                 final FileSet fs = (FileSet) rc;
@@ -2456,7 +2414,7 @@
                 }
             }
             for (final Resource r : rc) {
-                sf.addElement(new SourceFile(r.as(FileProvider.class).getFile()));
+                sf.add(new SourceFile(r.as(FileProvider.class).getFile()));
             }
         }
     }
@@ -2469,10 +2427,9 @@
      *
      * @since 1.5
      */
-    private void parsePackages(final Vector<String> pn, final Path sp) {
-        final HashSet<String> addedPackages = new HashSet<String>();
-        @SuppressWarnings("unchecked")
-        final Vector<DirSet> dirSets = (Vector<DirSet>) packageSets.clone();
+    private void parsePackages(final List<String> pn, final Path sp) {
+        final Set<String> addedPackages = new HashSet<>();
+        final List<DirSet> dirSets = new ArrayList<>(packageSets);
 
         // for each sourcePath entry, add a directoryset with includes
         // taken from packagenames attribute and nested package
@@ -2481,51 +2438,35 @@
         if (sourcePath != null) {
             final PatternSet ps = new PatternSet();
             ps.setProject(getProject());
-            if (packageNames.size() > 0) {
-                final Enumeration<PackageName> e = packageNames.elements();
-                while (e.hasMoreElements()) {
-                    final PackageName p = e.nextElement();
-                    String pkg = p.getName().replace('.', '/');
-                    if (pkg.endsWith("*")) {
-                        pkg += "*";
-                    }
-                    ps.createInclude().setName(pkg);
-                }
-            } else {
+            if (packageNames.isEmpty()) {
                 ps.createInclude().setName("**");
+            } else {
+                packageNames.stream().map(PackageName::getName)
+                    .map(s -> s.replace('.', '/').replaceFirst("\\*$", "**"))
+                    .forEach(pkg -> ps.createInclude().setName(pkg));
             }
 
-            final Enumeration<PackageName> e = excludePackageNames.elements();
-            while (e.hasMoreElements()) {
-                final PackageName p = e.nextElement();
-                String pkg = p.getName().replace('.', '/');
-                if (pkg.endsWith("*")) {
-                    pkg += "*";
-                }
-                ps.createExclude().setName(pkg);
-            }
+            excludePackageNames.stream().map(PackageName::getName)
+                .map(s -> s.replace('.', '/').replaceFirst("\\*$", "**"))
+                .forEach(pkg -> ps.createExclude().setName(pkg));
 
-
-            final String[] pathElements = sourcePath.list();
-            for (int i = 0; i < pathElements.length; i++) {
-                final File dir = new File(pathElements[i]);
+            for (String pathElement : sourcePath.list()) {
+                final File dir = new File(pathElement);
                 if (dir.isDirectory()) {
                     final DirSet ds = new DirSet();
                     ds.setProject(getProject());
                     ds.setDefaultexcludes(useDefaultExcludes);
                     ds.setDir(dir);
                     ds.createPatternSet().addConfiguredPatternset(ps);
-                    dirSets.addElement(ds);
+                    dirSets.add(ds);
                 } else {
-                    log("Skipping " + pathElements[i]
+                    log("Skipping " + pathElement
                         + " since it is no directory.", Project.MSG_WARN);
                 }
             }
         }
 
-        final Enumeration<DirSet> e = dirSets.elements();
-        while (e.hasMoreElements()) {
-            final DirSet ds = e.nextElement();
+        for (DirSet ds : dirSets) {
             final File baseDir = ds.getDir(getProject());
             log("scanning " + baseDir + " for packages.", Project.MSG_DEBUG);
             final DirectoryScanner dsc = ds.getDirectoryScanner(getProject());
@@ -2533,20 +2474,14 @@
             for (String dir : dsc.getIncludedDirectories()) {
                 // are there any java files in this directory?
                 final File pd = new File(baseDir, dir);
-                final String[] files = pd.list(new FilenameFilter () {
-                        public boolean accept(final File dir1, final String name) {
-                            return name.endsWith(".java")
-                                || (includeNoSourcePackages
-                                    && name.equals("package.html"));
-                        }
-                    });
+                final String[] files = pd.list((directory,
+                    name) -> name.endsWith(".java") || (includeNoSourcePackages
+                        && name.equals("package.html")));
 
                 if (files.length > 0) {
-                    if ("".equals(dir)) {
+                    if (dir.isEmpty()) {
                         log(baseDir
-                            + " contains source files in the default package,"
-                            + " you must specify them as source files"
-                            + " not packages.",
+                            + " contains source files in the default package, you must specify them as source files not packages.",
                             Project.MSG_WARN);
                     } else {
                         containsPackages = true;
@@ -2554,7 +2489,7 @@
                                 dir.replace(File.separatorChar, '.');
                         if (!addedPackages.contains(packageName)) {
                             addedPackages.add(packageName);
-                            pn.addElement(packageName);
+                            pn.add(packageName);
                         }
                     }
                 }
@@ -2564,7 +2499,7 @@
                 // Path.list does it for us.
                 sp.createPathElement().setLocation(baseDir);
             } else {
-                log(baseDir + " doesn\'t contain any packages, dropping it.",
+                log(baseDir + " doesn't contain any packages, dropping it.",
                     Project.MSG_VERBOSE);
             }
         }
@@ -2579,18 +2514,17 @@
                 Project.MSG_VERBOSE);
             return;
         }
-        final String fixData;
         final InputStream in = Javadoc.class
             .getResourceAsStream("javadoc-frame-injections-fix.txt");
         if (in == null) {
-            throw new FileNotFoundException("Missing resource "
-                                            + "'javadoc-frame-injections-fix.txt' in "
-                                            + "classpath.");
+            throw new FileNotFoundException(
+                "Missing resource 'javadoc-frame-injections-fix.txt' in classpath.");
         }
+        final String fixData;
         try {
             fixData =
                 fixLineFeeds(FileUtils
-                             .readFully(new InputStreamReader(in, "US-ASCII")))
+                             .readFully(new InputStreamReader(in, StandardCharsets.US_ASCII)))
                 .trim();
         } finally {
             FileUtils.close(in);
@@ -2619,14 +2553,10 @@
             : FILE_UTILS.getDefaultEncoding();
         // we load the whole file as one String (toc/index files are
         // generally small, because they only contain frameset declaration):
-        final InputStream fin = new FileInputStream(file);
         String fileContents;
-        try {
-            fileContents =
-                fixLineFeeds(FileUtils
-                             .safeReadFully(new InputStreamReader(fin, enc)));
-        } finally {
-            FileUtils.close(fin);
+        try (InputStreamReader reader =
+            new InputStreamReader(Files.newInputStream(file.toPath()), enc)) {
+            fileContents = fixLineFeeds(FileUtils.safeReadFully(reader));
         }
 
         // check if file may be vulnerable because it was not
@@ -2635,14 +2565,11 @@
             // we need to patch the file!
             final String patchedFileContents = patchContent(fileContents, fixData);
             if (!patchedFileContents.equals(fileContents)) {
-                final FileOutputStream fos = new FileOutputStream(file);
-                try {
-                    final OutputStreamWriter w = new OutputStreamWriter(fos, enc);
+                try (final OutputStreamWriter w =
+                    new OutputStreamWriter(Files.newOutputStream(file.toPath()), enc)) {
                     w.write(patchedFileContents);
                     w.close();
                     return 1;
-                } finally {
-                    FileUtils.close(fos);
                 }
             }
         }
@@ -2651,7 +2578,7 @@
 
     private String fixLineFeeds(final String orig) {
         return orig.replace("\r\n", "\n")
-            .replace("\n", StringUtils.LINE_SEP);
+            .replace("\n", System.lineSeparator());
     }
 
     private String patchContent(final String fileContents, final String fixData) {
@@ -2666,16 +2593,10 @@
 
     private void doModuleArguments(Commandline toExecute) {
         if (!moduleNames.isEmpty()) {
-            StringBuilder sb = null;
-            for (PackageName mn : moduleNames) {
-                if (sb == null) {
-                    sb = new StringBuilder(mn.getName());
-                } else {
-                    sb.append(",").append(mn.getName());
-                }
-            }
             toExecute.createArgument().setValue("--module");
-            toExecute.createArgument().setValue(sb.toString());
+            toExecute.createArgument()
+                .setValue(moduleNames.stream().map(PackageName::getName)
+                          .collect(Collectors.joining(",")));
         }
         if (modulePath != null) {
             toExecute.createArgument().setValue("--module-path");
@@ -2702,7 +2623,7 @@
 
         @Override
         protected void processLine(final String line, final int messageLevel) {
-            if (line.contains("warning")) {
+            if (line.matches("(\\d) warning[s]?$")) {
                 sawWarnings = true;
             }
             if (messageLevel == Project.MSG_INFO
@@ -2724,7 +2645,6 @@
             }
         }
 
-
         protected void logFlush() {
             if (queuedLine != null) {
                 super.processLine(queuedLine, Project.MSG_VERBOSE);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Jikes.java b/src/main/org/apache/tools/ant/taskdefs/Jikes.java
index 7c1d62d..8498527 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Jikes.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Jikes.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,10 +21,10 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.util.Locale;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.condition.Os;
 import org.apache.tools.ant.util.FileUtils;
 
 /**
@@ -62,7 +62,7 @@
             + "the Jikes class");
         System.err.println("is considered to be dead code by the Ant "
             + "developers and is unmaintained.");
-        System.err.println("Don\'t use it!");
+        System.err.println("Don't use it!");
 
         this.jop = jop;
         this.command = command;
@@ -78,18 +78,12 @@
         File tmpFile = null;
 
         try {
-            String myos = System.getProperty("os.name");
-
             // Windows has a 32k limit on total arg size, so
             // create a temporary file to store all the arguments
-
-            if (myos.toLowerCase(Locale.ENGLISH).contains("windows")
-                && args.length > MAX_FILES_ON_COMMAND_LINE) {
-                BufferedWriter out = null;
-                try {
-                    tmpFile = FileUtils.getFileUtils().createTempFile(project, "jikes",
-                            "tmp", null, false, true);
-                    out = new BufferedWriter(new FileWriter(tmpFile));
+            if (Os.isFamily(Os.FAMILY_WINDOWS) && args.length > MAX_FILES_ON_COMMAND_LINE) {
+                tmpFile = FileUtils.getFileUtils().createTempFile(project, "jikes",
+                        "tmp", null, false, true);
+                try (BufferedWriter out = new BufferedWriter(new FileWriter(tmpFile))) {
                     for (String arg : args) {
                         out.write(arg);
                         out.newLine();
@@ -98,10 +92,7 @@
                     commandArray = new String[] {command,
                                                "@" + tmpFile.getAbsolutePath()};
                 } catch (IOException e) {
-                    throw new BuildException("Error creating temporary file",
-                                             e);
-                } finally {
-                    FileUtils.close(out);
+                    throw new BuildException("Error creating temporary file", e);
                 }
             } else {
                 commandArray = new String[args.length + 1];
@@ -123,10 +114,8 @@
                 throw new BuildException("Error running Jikes compiler", e);
             }
         } finally {
-            if (tmpFile != null) {
-                if (!tmpFile.delete()) {
-                    tmpFile.deleteOnExit();
-                }
+            if (tmpFile != null && !tmpFile.delete()) {
+                tmpFile.deleteOnExit();
             }
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/JikesOutputParser.java b/src/main/org/apache/tools/ant/taskdefs/JikesOutputParser.java
index 5ffb954..c53f907 100644
--- a/src/main/org/apache/tools/ant/taskdefs/JikesOutputParser.java
+++ b/src/main/org/apache/tools/ant/taskdefs/JikesOutputParser.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -100,7 +100,7 @@
             + "JikesOutputParser class");
         System.err.println("is considered to be dead code by the Ant "
             + "developers and is unmaintained.");
-        System.err.println("Don\'t use it!");
+        System.err.println("Don't use it!");
 
         this.task = task;
         this.emacsMode = emacsMode;
@@ -133,7 +133,7 @@
 
         while ((line = reader.readLine()) != null) {
             lower = line.toLowerCase();
-            if (line.trim().equals("")) {
+            if (line.trim().isEmpty()) {
                 continue;
             }
             if (lower.contains("error")) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/KeySubst.java b/src/main/org/apache/tools/ant/taskdefs/KeySubst.java
index ee476e7..a6961bd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/KeySubst.java
+++ b/src/main/org/apache/tools/ant/taskdefs/KeySubst.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -48,7 +48,7 @@
     private File source = null;
     private File dest = null;
     private String sep = "*";
-    private Hashtable<String, String> replacements = new Hashtable<String, String>();
+    private Hashtable<String, String> replacements = new Hashtable<>();
 
     /**
      * Do the execution.
@@ -72,13 +72,11 @@
             String newline = null;
             line = br.readLine();
             while (line != null) {
-                if (line.length() == 0) {
-                    bw.newLine();
-                } else {
+                if (!line.isEmpty()) {
                     newline = KeySubst.replace(line, replacements);
                     bw.write(newline);
-                    bw.newLine();
                 }
+                bw.newLine();
                 line = br.readLine();
             }
             bw.flush();
@@ -128,7 +126,7 @@
      * @param keys a <code>String</code> value
      */
     public void setKeys(String keys) {
-        if (keys != null && keys.length() > 0) {
+        if (keys != null && !keys.isEmpty()) {
             StringTokenizer tok =
             new StringTokenizer(keys, this.sep, false);
             while (tok.hasMoreTokens()) {
@@ -150,7 +148,7 @@
      */
     public static void main(String[] args) {
         try {
-            Hashtable<String, String> hash = new Hashtable<String, String>();
+            Hashtable<String, String> hash = new Hashtable<>();
             hash.put("VERSION", "1.0.3");
             hash.put("b", "ffff");
             System.out.println(KeySubst.replace("$f ${VERSION} f ${b} jj $",
@@ -169,7 +167,7 @@
      */
     public static String replace(String origString, Hashtable<String, String> keys)
         throws BuildException {
-        StringBuffer finalString = new StringBuffer();
+        final StringBuilder finalString = new StringBuilder();
         int index = 0;
         int i = 0;
         String key = null;
@@ -177,7 +175,7 @@
         while ((index = origString.indexOf("${", i)) > -1) {
             key = origString.substring(index + 2, origString.indexOf("}",
                                        index + 3));
-            finalString.append(origString.substring(i, index));
+            finalString.append(origString, i, index);
             if (keys.containsKey(key)) {
                 finalString.append(keys.get(key));
             } else {
diff --git a/src/main/org/apache/tools/ant/taskdefs/Length.java b/src/main/org/apache/tools/ant/taskdefs/Length.java
index 68fb20a..45e8fe7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Length.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Length.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -108,7 +108,7 @@
      * @param ell the long length to compare with.
      */
     public synchronized void setLength(long ell) {
-        length = new Long(ell);
+        length = ell;
     }
 
     /**
@@ -152,7 +152,7 @@
      * @param trim <code>boolean</code>.
      */
     public synchronized void setTrim(boolean trim) {
-        this.trim = trim ? Boolean.TRUE : Boolean.FALSE;
+        this.trim = trim;
     }
 
     /**
@@ -160,25 +160,31 @@
      * @return boolean trim setting.
      */
     public boolean getTrim() {
-        return trim != null && trim.booleanValue();
+        return Boolean.TRUE.equals(trim);
     }
 
     /**
      * Execute the length task.
      */
+    @Override
     public void execute() {
         validate();
-        PrintStream ps = new PrintStream((property != null)
-            ? (OutputStream) new PropertyOutputStream(getProject(), property)
-            : (OutputStream) new LogOutputStream(this, Project.MSG_INFO));
+        OutputStream out =
+            property == null ? new LogOutputStream(this, Project.MSG_INFO)
+                : new PropertyOutputStream(getProject(), property);
+        PrintStream ps = new PrintStream(out);
 
-        if (STRING.equals(mode)) {
+        switch (mode) {
+        case STRING:
             ps.print(getLength(string, getTrim()));
             ps.close();
-        } else if (EACH.equals(mode)) {
+            break;
+        case EACH:
             handleResources(new EachHandler(ps));
-        } else if (ALL.equals(mode)) {
+            break;
+        case ALL:
             handleResources(new AllHandler(ps));
+            break;
         }
     }
 
@@ -187,6 +193,7 @@
      * @return true if the condition is true.
      * @throws BuildException if an error occurs.
      */
+    @Override
     public boolean eval() {
         validate();
         if (length == null) {
@@ -194,11 +201,11 @@
         }
         Long ell;
         if (STRING.equals(mode)) {
-            ell = new Long(getLength(string, getTrim()));
+            ell = getLength(string, getTrim());
         } else {
             AccumHandler h = new AccumHandler();
             handleResources(h);
-            ell = new Long(h.getAccum());
+            ell = h.getAccum();
         }
         return when.evaluate(ell.compareTo(length));
     }
@@ -206,25 +213,26 @@
     private void validate() {
         if (string != null) {
             if (resources != null) {
-                throw new BuildException("the string length function"
-                    + " is incompatible with the file/resource length function");
+                throw new BuildException(
+                    "the string length function is incompatible with the file/resource length function");
             }
             if (!(STRING.equals(mode))) {
-                throw new BuildException("the mode attribute is for use"
-                    + " with the file/resource length function");
+                throw new BuildException(
+                    "the mode attribute is for use with the file/resource length function");
             }
         } else if (resources != null) {
-            if (!(EACH.equals(mode) || ALL.equals(mode))) {
-                throw new BuildException("invalid mode setting for"
-                    + " file/resource length function: \"" + mode + "\"");
-            } else if (trim != null) {
-                throw new BuildException("the trim attribute is"
-                    + " for use with the string length function only");
+            if (!EACH.equals(mode) && !ALL.equals(mode)) {
+                throw new BuildException(
+                    "invalid mode setting for file/resource length function: \""
+                        + mode + "\"");
+            }
+            if (trim != null) {
+                throw new BuildException(
+                    "the trim attribute is for use with the string length function only");
             }
         } else {
-            throw new BuildException("you must set either the string attribute"
-                + " or specify one or more files using the file attribute or"
-                + " nested resource collections");
+            throw new BuildException(
+                "you must set either the string attribute or specify one or more files using the file attribute or nested resource collections");
         }
     }
 
@@ -253,6 +261,7 @@
          * Return the possible values for FileMode.
          * @return <code>String[]</code>.
          */
+        @Override
         public String[] getValues() {
             return MODES;
         }
@@ -268,6 +277,7 @@
 
     private abstract class Handler {
         private PrintStream ps;
+
         Handler(PrintStream ps) {
             this.ps = ps;
         }
@@ -287,6 +297,8 @@
         EachHandler(PrintStream ps) {
             super(ps);
         }
+
+        @Override
         protected void handle(Resource r) {
             getPs().print(r.toString());
             getPs().print(" : ");
@@ -306,12 +318,16 @@
         AccumHandler() {
             super(null);
         }
+
         protected AccumHandler(PrintStream ps) {
             super(ps);
         }
+
         protected long getAccum() {
             return accum;
         }
+
+        @Override
         protected synchronized void handle(Resource r) {
             long size = r.getSize();
             if (size == Resource.UNKNOWN_SIZE) {
@@ -326,6 +342,8 @@
         AllHandler(PrintStream ps) {
             super(ps);
         }
+
+        @Override
         void complete() {
             getPs().print(getAccum());
             super.complete();
diff --git a/src/main/org/apache/tools/ant/taskdefs/LoadFile.java b/src/main/org/apache/tools/ant/taskdefs/LoadFile.java
index c450a0e..89bed09 100644
--- a/src/main/org/apache/tools/ant/taskdefs/LoadFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/LoadFile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java b/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java
index 6086318..e46d34a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java
+++ b/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,9 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
 import java.util.Properties;
 import java.util.Vector;
 
@@ -30,6 +32,7 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.filters.util.ChainReaderHelper;
+import org.apache.tools.ant.filters.util.ChainReaderHelper.ChainReader;
 import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
@@ -37,8 +40,6 @@
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.types.resources.JavaResource;
-import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.ResourceUtils;
 
 /**
  * Load a file's contents as Ant properties.
@@ -56,7 +57,7 @@
     /**
      * Holds filterchains
      */
-    private final Vector<FilterChain> filterChains = new Vector<FilterChain>();
+    private final List<FilterChain> filterChains = new Vector<>();
 
     /**
      * Encoding to use for input; defaults to the platform's default encoding.
@@ -92,8 +93,8 @@
      * encoding. <p>
      *
      * For a list of possible values see
-     * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">
-     * http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html
+     * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+     * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html
      * </a>.</p>
      *
      * @param encoding The new Encoding value
@@ -159,6 +160,7 @@
      *
      * @exception BuildException if something goes wrong with the build
      */
+    @Override
     public final void execute() throws BuildException {
         //validation
         if (src == null) {
@@ -172,30 +174,21 @@
             }
             throw new BuildException("Source resource does not exist: " + src);
         }
-        BufferedInputStream bis = null;
-        Reader instream = null;
-        ByteArrayInputStream tis = null;
 
-        try {
-            bis = new BufferedInputStream(src.getInputStream());
-            if (encoding == null) {
-                instream = new InputStreamReader(bis);
-            } else {
-                instream = new InputStreamReader(bis, encoding);
-            }
-            ChainReaderHelper crh = new ChainReaderHelper();
-            crh.setPrimaryReader(instream);
-            crh.setFilterChains(filterChains);
-            crh.setProject(getProject());
-            instream = crh.getAssembledReader();
+        Charset charset = encoding == null ? Charset.defaultCharset() : Charset.forName(encoding);
 
-            String text = crh.readFully(instream);
+        try (ChainReader instream = new ChainReaderHelper(getProject(),
+            new InputStreamReader(new BufferedInputStream(src.getInputStream()), charset), filterChains)
+                .getAssembledReader()) {
 
-            if (text != null && text.length() != 0) {
+            String text = instream.readFully();
+
+            if (text != null && !text.isEmpty()) {
                 if (!text.endsWith("\n")) {
-                    text = text + "\n";
+                    text += "\n";
                 }
-                tis = new ByteArrayInputStream(text.getBytes(ResourceUtils.ISO_8859_1));
+                ByteArrayInputStream tis = new ByteArrayInputStream(
+                    text.getBytes(StandardCharsets.ISO_8859_1));
                 final Properties props = new Properties();
                 props.load(tis);
 
@@ -207,9 +200,6 @@
             }
         } catch (final IOException ioe) {
             throw new BuildException("Unable to load file: " + ioe, ioe, getLocation());
-        } finally {
-            FileUtils.close(bis);
-            FileUtils.close(tis);
         }
     }
 
@@ -218,7 +208,7 @@
      * @param filter the filter to add
      */
     public final void addFilterChain(FilterChain filter) {
-        filterChains.addElement(filter);
+        filterChains.add(filter);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/LoadResource.java b/src/main/org/apache/tools/ant/taskdefs/LoadResource.java
index f68b5ba..a9e4c62 100644
--- a/src/main/org/apache/tools/ant/taskdefs/LoadResource.java
+++ b/src/main/org/apache/tools/ant/taskdefs/LoadResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,19 +19,18 @@
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.List;
 import java.util.Vector;
-
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.filters.util.ChainReaderHelper;
+import org.apache.tools.ant.filters.util.ChainReaderHelper.ChainReader;
 import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Load a resource into a property
@@ -70,15 +69,15 @@
     /**
      * Holds FilterChains
      */
-    private final Vector<FilterChain> filterChains = new Vector<FilterChain>();
+    private final List<FilterChain> filterChains = new Vector<>();
 
     /**
      * Encoding to use for input, defaults to the platform's default
      * encoding. <p>
      *
      * For a list of possible values see
-     * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">
-     * http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html
+     * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+     * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html
      * </a>.</p>
      *
      * @param encoding The new Encoding value
@@ -124,6 +123,7 @@
      *
      * @exception BuildException if something goes wrong with the build
      */
+    @Override
     public final void execute()
         throws BuildException {
         //validation
@@ -134,82 +134,67 @@
             throw new BuildException("output property not defined");
         }
         if (quiet && failOnError) {
-            throw new BuildException("quiet and failonerror cannot both be "
-                                     + "set to true");
+            throw new BuildException("quiet and failonerror cannot both be set to true");
         }
         if (!src.isExists()) {
             String message = src + " doesn't exist";
             if (failOnError) {
                 throw new BuildException(message);
-            } else {
-                log(message, quiet ? Project.MSG_WARN : Project.MSG_ERR);
-                return;
             }
+            log(message, quiet ? Project.MSG_WARN : Project.MSG_ERR);
+            return;
         }
-        InputStream is = null;
-        BufferedInputStream bis = null;
-        Reader instream = null;
+
         log("loading " + src + " into property " + property,
             Project.MSG_VERBOSE);
+
+        Charset charset = encoding == null ? Charset.defaultCharset()
+            : Charset.forName(encoding);
         try {
             final long len = src.getSize();
-            log("resource size = "
-                + (len != Resource.UNKNOWN_SIZE ? String.valueOf(len)
-                   : "unknown"), Project.MSG_DEBUG);
+            log("resource size = " + (len != Resource.UNKNOWN_SIZE
+                ? String.valueOf(len) : "unknown"), Project.MSG_DEBUG);
             //discard most of really big resources
             final int size = (int) len;
             //open up the resource
-            is = src.getInputStream();
-            bis = new BufferedInputStream(is);
-            if (encoding == null) {
-                instream = new InputStreamReader(bis);
-            } else {
-                instream = new InputStreamReader(bis, encoding);
-            }
 
-            String text = "";
+            String text;
             if (size != 0) {
-                ChainReaderHelper crh = new ChainReaderHelper();
-                if (len != Resource.UNKNOWN_SIZE) {
-                    crh.setBufferSize(size);
-                }
-                crh.setPrimaryReader(instream);
-                crh.setFilterChains(filterChains);
-                crh.setProject(getProject());
-                instream = crh.getAssembledReader();
+                try (ChainReader chainReader = new ChainReaderHelper(
+                    getProject(),
+                    new InputStreamReader(
+                        new BufferedInputStream(src.getInputStream()), charset),
+                    filterChains).with(crh -> {
+                        if (src.getSize() != Resource.UNKNOWN_SIZE) {
+                            crh.setBufferSize(size);
+                        }
+                    }).getAssembledReader()) {
 
-                text = crh.readFully(instream);
+                    text = chainReader.readFully();
+                }
             } else {
                 log("Do not set property " + property + " as its length is 0.",
                     quiet ? Project.MSG_VERBOSE : Project.MSG_INFO);
+                text = null;
             }
 
-            if (text != null) {
-                if (text.length() > 0) {
-                    getProject().setNewProperty(property, text);
-                    log("loaded " + text.length() + " characters",
-                        Project.MSG_VERBOSE);
-                    log(property + " := " + text, Project.MSG_DEBUG);
-                }
+            if (text != null && !text.isEmpty()) {
+                getProject().setNewProperty(property, text);
+                log("loaded " + text.length() + " characters",
+                    Project.MSG_VERBOSE);
+                log(property + " := " + text, Project.MSG_DEBUG);
             }
-
         } catch (final IOException ioe) {
-            final String message = "Unable to load resource: "
-                + ioe.toString();
+            final String message = "Unable to load resource: " + ioe;
             if (failOnError) {
                 throw new BuildException(message, ioe, getLocation());
-            } else {
-                log(message, quiet ? Project.MSG_VERBOSE : Project.MSG_ERR);
             }
+            log(message, quiet ? Project.MSG_VERBOSE : Project.MSG_ERR);
         } catch (final BuildException be) {
             if (failOnError) {
                 throw be;
-            } else {
-                log(be.getMessage(),
-                    quiet ? Project.MSG_VERBOSE : Project.MSG_ERR);
             }
-        } finally {
-            FileUtils.close(is);
+            log(be.getMessage(), quiet ? Project.MSG_VERBOSE : Project.MSG_ERR);
         }
     }
 
@@ -218,7 +203,7 @@
      * @param filter the filter to add
      */
     public final void addFilterChain(FilterChain filter) {
-        filterChains.addElement(filter);
+        filterChains.add(filter);
     }
 
     /**
@@ -227,8 +212,8 @@
      */
     public void addConfigured(ResourceCollection a) {
         if (a.size() != 1) {
-            throw new BuildException("only single argument resource collections"
-                                     + " are supported");
+            throw new BuildException(
+                "only single argument resource collections are supported");
         }
         src = a.iterator().next();
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Local.java b/src/main/org/apache/tools/ant/taskdefs/Local.java
index 3fdf9b5..1b6179e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Local.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Local.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,15 +17,48 @@
  */
 package org.apache.tools.ant.taskdefs;
 
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.function.Consumer;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.property.LocalProperties;
 
 /**
- * Task to create a local property in the current scope.
+ * Task to create local properties in the current scope.
  */
 public class Local extends Task {
+    /**
+     * Nested {@code name} element.
+     * @since Ant 1.10.13
+     */
+    public static class Name implements Consumer<LocalProperties> {
+        private String text;
+
+        /**
+         * Set the property name.
+         * @param text
+         */
+        public void addText(String text) {
+            this.text = text;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void accept(LocalProperties localProperties) {
+            if (text == null) {
+                throw new BuildException("nested name element is missing text");
+            }
+            localProperties.addLocal(text);
+        }
+    }
+
     private String name;
+    
+    private final Set<Name> nameElements = new LinkedHashSet<>();
 
     /**
      * Set the name attribute.
@@ -36,12 +69,28 @@
     }
 
     /**
+     * Create a nested {@code name} element.
+     * @return {@link Name}
+     * @since Ant 1.10.13
+     */
+    public Name createName() {
+        final Name result = new Name();
+        nameElements.add(result);
+        return result;
+    }
+
+    /**
      * Run the task.
      */
     public void execute() {
-        if (name == null) {
-            throw new BuildException("Missing attribute name");
+        if (name == null && nameElements.isEmpty()) {
+            throw new BuildException("Found no configured local property names");
         }
-        LocalProperties.get(getProject()).addLocal(name);
+        final LocalProperties localProperties = LocalProperties.get(getProject());
+
+        if (name != null) {
+            localProperties.addLocal(name);
+        }
+        nameElements.forEach(n -> n.accept(localProperties));
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java b/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java
index 370bcdd..84eb14d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java
+++ b/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
index ed16cf3..33afe49 100644
--- a/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,11 +18,9 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import java.io.IOException;
-
-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.
@@ -57,14 +55,10 @@
     /**
      * Stop the log stream handler.
      */
+    @Override
     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/MacroDef.java b/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
index 79b6984..10edf06 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 
 import org.apache.tools.ant.AntTypeDefinition;
 import org.apache.tools.ant.BuildException;
@@ -42,13 +43,13 @@
 public class MacroDef extends AntlibDefinition  {
 
     private NestedSequential nestedSequential;
-    private String     name;
-    private boolean    backTrace = true;
-    private List<Attribute>       attributes = new ArrayList<Attribute>();
-    private Map<String, TemplateElement>        elements   = new HashMap<String, TemplateElement>();
-    private String     textName   = null;
-    private Text       text       = null;
-    private boolean    hasImplicitElement = false;
+    private String name;
+    private boolean backTrace = true;
+    private List<Attribute> attributes = new ArrayList<>();
+    private Map<String, TemplateElement> elements = new HashMap<>();
+    private String textName = null;
+    private Text text = null;
+    private boolean hasImplicitElement = false;
 
     /**
      * Name of the definition
@@ -76,8 +77,8 @@
         for (Attribute attribute : attributes) {
             if (text.getName().equals(attribute.getName())) {
                 throw new BuildException(
-                    "the name \"" + text.getName()
-                    + "\" is already used as an attribute");
+                    "the name \"%s\" is already used as an attribute",
+                    text.getName());
             }
         }
         this.text = text;
@@ -132,13 +133,14 @@
      * This is a simple task container.
      */
     public static class NestedSequential implements TaskContainer {
-        private List<Task> nested = new ArrayList<Task>();
+        private List<Task> nested = new ArrayList<>();
 
         /**
          * Add a task or type to the container.
          *
          * @param task an unknown element.
          */
+        @Override
         public void addTask(Task task) {
             nested.add(task);
         }
@@ -235,7 +237,7 @@
      * @return true if the name consists of valid name characters
      */
     private static boolean isValidName(String name) {
-        if (name.length() == 0) {
+        if (name.isEmpty()) {
             return false;
         }
         for (int i = 0; i < name.length(); ++i) {
@@ -258,16 +260,14 @@
         }
         if (attribute.getName().equals(textName)) {
             throw new BuildException(
-                "the name \"" + attribute.getName()
-                + "\" has already been used by the text element");
+                "the name \"%s\" has already been used by the text element",
+                attribute.getName());
         }
-        final int size = attributes.size();
         for (Attribute att : attributes) {
             if (att.getName().equals(attribute.getName())) {
                 throw new BuildException(
-                    "the name \"" + attribute.getName()
-                        + "\" has already been used in "
-                        + "another attribute element");
+                    "the name \"%s\" has already been used in another attribute element",
+                    attribute.getName());
             }
         }
         attributes.add(attribute);
@@ -285,11 +285,10 @@
         }
         if (elements.get(element.getName()) != null) {
             throw new BuildException(
-                "the element " + element.getName()
-                + " has already been specified");
+                "the element %s has already been specified", element.getName());
         }
         if (hasImplicitElement
-            || (element.isImplicit() && elements.size() != 0)) {
+            || (element.isImplicit() && !elements.isEmpty())) {
             throw new BuildException(
                 "Only one element allowed when using implicit elements");
         }
@@ -300,6 +299,7 @@
     /**
      * Create a new ant type based on the embedded tasks and types.
      */
+    @Override
     public void execute() {
         if (nestedSequential == null) {
             throw new BuildException("Missing sequential element");
@@ -321,7 +321,6 @@
         log("creating macro  " + name, Project.MSG_VERBOSE);
     }
 
-
     /**
      * An attribute for the MacroDef task.
      *
@@ -339,8 +338,8 @@
          */
         public void setName(String name) {
             if (!isValidName(name)) {
-                throw new BuildException(
-                    "Illegal name [" + name + "] for attribute");
+                throw new BuildException("Illegal name [%s] for attribute",
+                    name);
             }
             this.name = name.toLowerCase(Locale.ENGLISH);
         }
@@ -411,6 +410,7 @@
          * @param obj an <code>Object</code> value
          * @return a <code>boolean</code> value
          */
+        @Override
         public boolean equals(Object obj) {
             if (obj == null) {
                 return false;
@@ -426,21 +426,16 @@
             } else if (!name.equals(other.name)) {
                 return false;
             }
-            if (defaultValue == null) {
-                if (other.defaultValue != null) {
-                    return false;
-                }
-            } else if (!defaultValue.equals(other.defaultValue)) {
-                return false;
-            }
-            return true;
+            return defaultValue == null ? other.defaultValue == null
+                    : defaultValue.equals(other.defaultValue);
         }
 
         /**
          * @return a hash code value for this object.
          */
+        @Override
         public int hashCode() {
-            return objectHashCode(defaultValue) + objectHashCode(name);
+            return Objects.hashCode(defaultValue) + Objects.hashCode(name);
         }
     }
 
@@ -462,8 +457,8 @@
          */
         public void setName(String name) {
             if (!isValidName(name)) {
-                throw new BuildException(
-                    "Illegal name [" + name + "] for attribute");
+                throw new BuildException("Illegal name [%s] for element",
+                    name);
             }
             this.name = name.toLowerCase(Locale.ENGLISH);
         }
@@ -543,6 +538,7 @@
          * @param obj an <code>Object</code> value
          * @return a <code>boolean</code> value
          */
+        @Override
         public boolean equals(Object obj) {
             if (obj == null) {
                 return false;
@@ -551,24 +547,21 @@
                 return false;
             }
             Text other = (Text) obj;
-            return safeCompare(name, other.name)
+            return Objects.equals(name, other.name)
                 && optional == other.optional
                 && trim == other.trim
-                && safeCompare(defaultString, other.defaultString);
+                && Objects.equals(defaultString, other.defaultString);
         }
 
         /**
          * @return a hash code value for this object.
          */
+        @Override
         public int hashCode() {
-            return objectHashCode(name);
+            return Objects.hashCode(name);
         }
     }
 
-    private static boolean safeCompare(Object a, Object b) {
-        return a == null ? b == null : a.equals(b);
-    }
-
     /**
      * A nested element for the MacroDef task.
      */
@@ -586,8 +579,8 @@
          */
         public void setName(String name) {
             if (!isValidName(name)) {
-                throw new BuildException(
-                    "Illegal name [" + name + "] for macro element");
+                throw new BuildException("Illegal name [%s] for macro element",
+                    name);
             }
             this.name = name.toLowerCase(Locale.ENGLISH);
         }
@@ -667,6 +660,7 @@
          * @param obj an <code>Object</code> value
          * @return a <code>boolean</code> value
          */
+        @Override
         public boolean equals(Object obj) {
             if (obj == this) {
                 return true;
@@ -684,8 +678,9 @@
         /**
          * @return a hash code value for this object.
          */
+        @Override
         public int hashCode() {
-            return objectHashCode(name)
+            return Objects.hashCode(name)
                 + (optional ? 1 : 0) + (implicit ? 1 : 0);
         }
 
@@ -704,12 +699,10 @@
             return true;
         }
 
-        if (obj == null) {
+        if (obj == null || !obj.getClass().equals(getClass())) {
             return false;
         }
-        if (!obj.getClass().equals(getClass())) {
-            return false;
-        }
+
         MacroDef other = (MacroDef) obj;
         if (name == null) {
             return other.name == null;
@@ -720,41 +713,29 @@
         // Allow two macro definitions with the same location
         // to be treated as similar - bugzilla 31215
         if (other.getLocation() != null
-            && other.getLocation().equals(getLocation())
-            && !same) {
+                && other.getLocation().equals(getLocation())
+                && !same) {
             return true;
         }
         if (text == null) {
             if (other.text != null) {
                 return false;
             }
-        } else {
-            if (!text.equals(other.text)) {
-                return false;
-            }
+        } else if (!text.equals(other.text)) {
+            return false;
         }
-        if (getURI() == null || getURI().equals("")
-            || getURI().equals(ProjectHelper.ANT_CORE_URI)) {
-            if (!(other.getURI() == null || other.getURI().equals("")
-                  || other.getURI().equals(ProjectHelper.ANT_CORE_URI))) {
+        if (getURI() == null || getURI().isEmpty()
+                || getURI().equals(ProjectHelper.ANT_CORE_URI)) {
+            if (other.getURI() != null && !other.getURI().isEmpty()
+                    && !other.getURI().equals(ProjectHelper.ANT_CORE_URI)) {
                 return false;
             }
-        } else {
-            if (!getURI().equals(other.getURI())) {
-                return false;
-            }
+        } else if (!getURI().equals(other.getURI())) {
+            return false;
         }
 
-        if (!nestedSequential.similar(other.nestedSequential)) {
-            return false;
-        }
-        if (!attributes.equals(other.attributes)) {
-            return false;
-        }
-        if (!elements.equals(other.elements)) {
-            return false;
-        }
-        return true;
+        return nestedSequential.similar(other.nestedSequential)
+                && attributes.equals(other.attributes) && elements.equals(other.elements);
     }
 
     /**
@@ -800,6 +781,7 @@
          * @param project the current project
          * @return the created object
          */
+        @Override
         public Object create(Project project) {
             Object o = super.create(project);
             if (o == null) {
@@ -816,6 +798,7 @@
          * @param project the current project
          * @return true if the definitions are the same
          */
+        @Override
         public boolean sameDefinition(AntTypeDefinition other, Project project) {
             if (!super.sameDefinition(other, project)) {
                 return false;
@@ -831,6 +814,7 @@
          * @param project the current project
          * @return true if the definitions are the same
          */
+        @Override
         public boolean similarDefinition(
             AntTypeDefinition other, Project project) {
             if (!super.similarDefinition(other, project)) {
@@ -841,12 +825,4 @@
         }
     }
 
-    private static int objectHashCode(Object o) {
-        if (o == null) {
-            return 0;
-        } else {
-            return o.hashCode();
-        }
-    }
-
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
index 124f09e..077b6d5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,15 +19,13 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.tools.ant.BuildException;
@@ -50,13 +48,13 @@
  */
 public class MacroInstance extends Task implements DynamicAttribute, TaskContainer {
     private MacroDef macroDef;
-    private Map<String, String>      map = new HashMap<String, String>();
-    private Map<String, MacroDef.TemplateElement>      nsElements = null;
-    private Map<String, UnknownElement>      presentElements;
-    private Hashtable<String, String> localAttributes;
-    private String    text = null;
-    private String    implicitTag =     null;
-    private List<Task>      unknownElements = new ArrayList<Task>();
+    private Map<String, String> map = new HashMap<>();
+    private Map<String, MacroDef.TemplateElement> nsElements = null;
+    private Map<String, UnknownElement> presentElements;
+    private Map<String, String> localAttributes;
+    private String text = null;
+    private String implicitTag = null;
+    private List<Task> unknownElements = new ArrayList<>();
 
     /**
      * Called from MacroDef.MyAntTypeDefinition#create()
@@ -80,6 +78,7 @@
      * @param name the name of the attribute
      * @param value the value of the attribute
      */
+    @Override
     public void setDynamicAttribute(String name, String value) {
         map.put(name.toLowerCase(Locale.ENGLISH), value);
     }
@@ -91,22 +90,22 @@
      * @deprecated since 1.6.x.
      * @throws BuildException always
      */
+    @Deprecated
     public Object createDynamicElement(String name) throws BuildException {
         throw new BuildException("Not implemented any more");
     }
 
     private Map<String, MacroDef.TemplateElement> getNsElements() {
         if (nsElements == null) {
-            nsElements = new HashMap<String, MacroDef.TemplateElement>();
-            for (Entry<String, MacroDef.TemplateElement> entry : macroDef.getElements().entrySet()) {
-            nsElements.put((String) entry.getKey(),
-                           entry.getValue());
-            MacroDef.TemplateElement te = (MacroDef.TemplateElement)
-                entry.getValue();
-            if (te.isImplicit()) {
-                implicitTag = te.getName();
+            nsElements = new HashMap<>();
+            for (Map.Entry<String, MacroDef.TemplateElement> entry : macroDef
+                .getElements().entrySet()) {
+                nsElements.put(entry.getKey(), entry.getValue());
+                MacroDef.TemplateElement te = entry.getValue();
+                if (te.isImplicit()) {
+                    implicitTag = te.getName();
+                }
             }
-         }
         }
         return nsElements;
     }
@@ -116,6 +115,7 @@
      *
      * @param nestedTask a nested element.
      */
+    @Override
     public void addTask(Task nestedTask) {
         unknownElements.add(nestedTask);
     }
@@ -124,15 +124,15 @@
         if (implicitTag != null) {
             return;
         }
-        for (Iterator<Task> i = unknownElements.iterator(); i.hasNext();) {
-            UnknownElement ue = (UnknownElement) i.next();
+        for (Task task : unknownElements) {
+            UnknownElement ue = (UnknownElement) task;
             String name = ProjectHelper.extractNameFromComponentName(
                 ue.getTag()).toLowerCase(Locale.ENGLISH);
             if (getNsElements().get(name) == null) {
-                throw new BuildException("unsupported element " + name);
+                throw new BuildException("unsupported element %s", name);
             }
             if (presentElements.get(name) != null) {
-                throw new BuildException("Element " + name + " already present");
+                throw new BuildException("Element %s already present", name);
             }
             presentElements.put(name, ue);
         }
@@ -142,13 +142,14 @@
      * Embedded element in macro instance
      */
     public static class Element implements TaskContainer {
-        private List<Task> unknownElements = new ArrayList<Task>();
+        private List<Task> unknownElements = new ArrayList<>();
 
         /**
          * Add an unknown element (to be snipped into the macroDef instance)
          *
          * @param nestedTask an unknown element
          */
+        @Override
         public void addTask(Task nestedTask) {
             unknownElements.add(nestedTask);
         }
@@ -169,8 +170,8 @@
         if (s == null) {
             return null;
         }
-        StringBuffer ret = new StringBuffer();
-        StringBuffer macroName = null;
+        StringBuilder ret = new StringBuilder();
+        StringBuilder macroName = null;
 
         int state = STATE_NORMAL;
         for (final char ch : s.toCharArray()) {
@@ -185,7 +186,7 @@
                 case STATE_EXPECT_BRACKET:
                     if (ch == '{') {
                         state = STATE_EXPECT_NAME;
-                        macroName = new StringBuffer();
+                        macroName = new StringBuilder();
                     } else if (ch == '@') {
                         state = STATE_NORMAL;
                         ret.append('@');
@@ -202,7 +203,7 @@
                     if (ch == '}') {
                         state = STATE_NORMAL;
                         String name = macroName.toString().toLowerCase(Locale.ENGLISH); //NOSONAR
-                        String value = (String) macroMapping.get(name);
+                        String value = macroMapping.get(name);
                         if (value == null) {
                             ret.append("@{");
                             ret.append(name);
@@ -276,9 +277,7 @@
         rc.addText(macroSubs(ue.getWrapper().getText().toString(),
                              localAttributes));
 
-        Enumeration<RuntimeConfigurable> e = ue.getWrapper().getChildren();
-        while (e.hasMoreElements()) {
-            RuntimeConfigurable r = e.nextElement();
+        for (RuntimeConfigurable r : Collections.list(ue.getWrapper().getChildren())) {
             UnknownElement unknownElement = (UnknownElement) r.getProxy();
             String tag = unknownElement.getTaskType();
             if (tag != null) {
@@ -291,40 +290,36 @@
                 rc.addChild(child.getWrapper());
                 ret.addChild(child);
             } else if (templateElement.isImplicit()) {
-                if (unknownElements.size() == 0 && !templateElement.isOptional()) {
+                if (unknownElements.isEmpty() && !templateElement.isOptional()) {
                     throw new BuildException(
-                        "Missing nested elements for implicit element "
-                        + templateElement.getName());
+                        "Missing nested elements for implicit element %s",
+                        templateElement.getName());
                 }
-                for (Iterator<Task> i = unknownElements.iterator();
-                     i.hasNext();) {
-                    UnknownElement child
-                        = copy((UnknownElement) i.next(), true);
+                for (Task task : unknownElements) {
+                    UnknownElement child = copy((UnknownElement) task, true);
                     rc.addChild(child.getWrapper());
                     ret.addChild(child);
                 }
             } else {
                 UnknownElement presentElement =
-                    (UnknownElement) presentElements.get(tag);
+                    presentElements.get(tag);
                 if (presentElement == null) {
                     if (!templateElement.isOptional()) {
                         throw new BuildException(
-                            "Required nested element "
-                            + templateElement.getName() + " missing");
+                            "Required nested element %s missing",
+                            templateElement.getName());
                     }
                     continue;
                 }
                 String presentText =
                     presentElement.getWrapper().getText().toString();
-                if (!"".equals(presentText)) {
+                if (!presentText.isEmpty()) {
                     rc.addText(macroSubs(presentText, localAttributes));
                 }
                 List<UnknownElement> list = presentElement.getChildren();
                 if (list != null) {
-                    for (Iterator<UnknownElement> i = list.iterator();
-                         i.hasNext();) {
-                        UnknownElement child
-                            = copy(i.next(), true);
+                    for (UnknownElement unknownElement2 : list) {
+                        UnknownElement child = copy(unknownElement2, true);
                         rc.addChild(child.getWrapper());
                         ret.addChild(child);
                     }
@@ -340,14 +335,15 @@
      * and calls perform on the unknown element.
      *
      */
+    @Override
     public void execute() {
-        presentElements = new HashMap<String, UnknownElement>();
+        presentElements = new HashMap<>();
         getNsElements();
         processTasks();
-        localAttributes = new Hashtable<String, String>();
-        Set<String> copyKeys = new HashSet<String>(map.keySet());
+        localAttributes = new Hashtable<>();
+        Set<String> copyKeys = new HashSet<>(map.keySet());
         for (Attribute attribute : macroDef.getAttributes()) {
-            String value = (String) map.get(attribute.getName());
+            String value = map.get(attribute.getName());
             if (value == null && "description".equals(attribute.getName())) {
                 value = getDescription();
             }
@@ -356,21 +352,19 @@
                 value = macroSubs(value, localAttributes);
             }
             if (value == null) {
-                throw new BuildException(
-                    "required attribute " + attribute.getName() + " not set");
+                throw new BuildException("required attribute %s not set",
+                    attribute.getName());
             }
             localAttributes.put(attribute.getName(), value);
             copyKeys.remove(attribute.getName());
         }
-        if (copyKeys.contains("id")) {
-            copyKeys.remove("id");
-        }
+        copyKeys.remove("id");
+
         if (macroDef.getText() != null) {
             if (text == null) {
                 String defaultText =  macroDef.getText().getDefault();
                 if (!macroDef.getText().getOptional() && defaultText == null) {
-                    throw new BuildException(
-                        "required text missing");
+                    throw new BuildException("required text missing");
                 }
                 text = defaultText == null ? "" : defaultText;
             }
@@ -378,24 +372,20 @@
                 text = text.trim();
             }
             localAttributes.put(macroDef.getText().getName(), text);
-        } else {
-            if (text != null && !text.trim().equals("")) {
-                throw new BuildException(
-                    "The \"" + getTaskName() + "\" macro does not support"
-                    + " nested text data.");
-            }
-        }
-        if (copyKeys.size() != 0) {
+        } else if (text != null && !text.trim().isEmpty()) {
             throw new BuildException(
-                "Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
-                + copyKeys);
+                "The \"%s\" macro does not support nested text data.",
+                getTaskName());
+        }
+        if (!copyKeys.isEmpty()) {
+            throw new BuildException("Unknown attribute"
+                + (copyKeys.size() > 1 ? "s " : " ") + copyKeys);
         }
 
         // need to set the project on unknown element
         UnknownElement c = copy(macroDef.getNestedTask(), false);
         c.init();
-        LocalProperties localProperties
-            = LocalProperties.get(getProject());
+        LocalProperties localProperties = LocalProperties.get(getProject());
         localProperties.enterScope();
         try {
             c.perform();
diff --git a/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java b/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java
index 5c1e44c..69af070 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MakeUrl.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,6 @@
 import java.io.File;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.ListIterator;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -42,6 +41,13 @@
  */
 
 public class MakeUrl extends Task {
+    // error message strings
+    /** Missing file */
+    public static final String ERROR_MISSING_FILE = "A source file is missing: ";
+    /** No property defined */
+    public static final String ERROR_NO_PROPERTY = "No property defined";
+    /** No files defined */
+    public static final String ERROR_NO_FILES = "No files defined";
 
     /**
      * name of the property to set
@@ -61,26 +67,18 @@
     /**
      * filesets of nested files to add to this url
      */
-    private List<FileSet> filesets = new LinkedList<FileSet>();
+    private List<FileSet> filesets = new LinkedList<>();
 
     /**
      * paths to add
      */
-    private List<Path> paths = new LinkedList<Path>();
+    private List<Path> paths = new LinkedList<>();
 
     /**
      * validation flag
      */
     private boolean validate = true;
 
-    // error message strings
-    /** Missing file */
-    public static final String ERROR_MISSING_FILE = "A source file is missing: ";
-    /** No property defined */
-    public static final String ERROR_NO_PROPERTY = "No property defined";
-    /** No files defined */
-    public static final String ERROR_NO_FILES = "No files defined";
-
     /**
      * set the name of a property to fill with the URL
      *
@@ -149,13 +147,10 @@
         }
         int count = 0;
         StringBuilder urls = new StringBuilder();
-        ListIterator<FileSet> list = filesets.listIterator();
-        while (list.hasNext()) {
-            FileSet set = list.next();
-            DirectoryScanner scanner = set.getDirectoryScanner(getProject());
-            String[] files = scanner.getIncludedFiles();
-            for (int i = 0; i < files.length; i++) {
-                File f = new File(scanner.getBasedir(), files[i]);
+        for (FileSet fs : filesets) {
+            DirectoryScanner scanner = fs.getDirectoryScanner(getProject());
+            for (String file : scanner.getIncludedFiles()) {
+                File f = new File(scanner.getBasedir(), file);
                 validateFile(f);
                 String asUrl = toURL(f);
                 urls.append(asUrl);
@@ -181,9 +176,8 @@
         if (count > 0) {
             urls.delete(urls.length() - separator.length(), urls.length());
             return new String(urls);
-        } else {
-            return "";
         }
+        return "";
     }
 
 
@@ -198,12 +192,9 @@
         }
         int count = 0;
         StringBuilder urls = new StringBuilder();
-        ListIterator<Path> list = paths.listIterator();
-        while (list.hasNext()) {
-            Path path = list.next();
-            String[] elements = path.list();
-            for (int i = 0; i < elements.length; i++) {
-                File f = new File(elements[i]);
+        for (Path path : paths) {
+            for (String element : path.list()) {
+                File f = new File(element);
                 validateFile(f);
                 String asUrl = toURL(f);
                 urls.append(asUrl);
@@ -224,7 +215,7 @@
      */
     private void validateFile(File fileToCheck) {
         if (validate && !fileToCheck.exists()) {
-            throw new BuildException(ERROR_MISSING_FILE + fileToCheck.toString());
+            throw new BuildException(ERROR_MISSING_FILE + fileToCheck);
         }
     }
 
@@ -243,23 +234,23 @@
         }
         String url;
         String filesetURL = filesetsToURL();
-        if (file != null) {
+        if (file == null) {
+            url = filesetURL;
+        } else {
             validateFile(file);
             url = toURL(file);
             //and add any files if also defined
-            if (filesetURL.length() > 0) {
-                url = url + separator + filesetURL;
+            if (!filesetURL.isEmpty()) {
+                url += separator + filesetURL;
             }
-        } else {
-            url = filesetURL;
         }
         //add path URLs
         String pathURL = pathsToURL();
-        if (pathURL.length() > 0) {
-            if (url.length() > 0) {
-                url = url + separator + pathURL;
-            } else {
+        if (!pathURL.isEmpty()) {
+            if (url.isEmpty()) {
                 url = pathURL;
+            } else {
+                url += separator + pathURL;
             }
         }
         log("Setting " + property + " to URL " + url, Project.MSG_VERBOSE);
@@ -287,12 +278,9 @@
      * @return the file converted to a URL
      */
     private String toURL(File fileToConvert) {
-        String url;
         //create the URL
         //ant equivalent of  fileToConvert.toURI().toURL().toExternalForm();
-        url = FileUtils.getFileUtils().toURI(fileToConvert.getAbsolutePath());
-
-        return url;
+        return FileUtils.getFileUtils().toURI(fileToConvert.getAbsolutePath());
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Manifest.java b/src/main/org/apache/tools/ant/taskdefs/Manifest.java
index 1daf52f..6417a8d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Manifest.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Manifest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,22 +25,25 @@
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.CollectionUtils;
-import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * Holds the data of a jar manifest.
  *
  * Manifests are processed according to the
- * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html">Jar
+ * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html">Jar
  * file specification</a>.
  * Specifically, a manifest element consists of
  * a set of attributes and sections. These sections in turn may contain
@@ -88,8 +91,11 @@
     public static final String ERROR_FROM_FORBIDDEN = "Manifest attributes should not start "
                         + "with \"" + ATTRIBUTE_FROM + "\" in \"";
 
+    /** Charset to be used for JAR files. */
+    public static final Charset JAR_CHARSET = StandardCharsets.UTF_8;
     /** Encoding to be used for JAR files. */
-    public static final String JAR_ENCODING = "UTF-8";
+    @Deprecated
+    public static final String JAR_ENCODING = JAR_CHARSET.name();
 
     private static final String ATTRIBUTE_MANIFEST_VERSION_LC =
         ATTRIBUTE_MANIFEST_VERSION.toLowerCase(Locale.ENGLISH);
@@ -127,7 +133,7 @@
         private String name = null;
 
         /** The attribute's value */
-        private Vector<String> values = new Vector<String>();
+        private Vector<String> values = new Vector<>();
 
         /**
          * For multivalued attributes, this is the index of the attribute
@@ -168,14 +174,7 @@
          */
         @Override
         public int hashCode() {
-            int hashCode = 0;
-
-            if (name != null) {
-                hashCode += getKey().hashCode();
-            }
-
-            hashCode += values.hashCode();
-            return hashCode;
+            return Objects.hash(getKey(), values);
         }
 
         /**
@@ -196,12 +195,8 @@
             Attribute rhsAttribute = (Attribute) rhs;
             String lhsKey = getKey();
             String rhsKey = rhsAttribute.getKey();
-            if ((lhsKey == null && rhsKey != null)
-                 || (lhsKey != null && !lhsKey.equals(rhsKey))) {
-                return false;
-            }
-
-            return values.equals(rhsAttribute.values);
+            return (lhsKey != null || rhsKey == null)
+                    && (lhsKey == null || lhsKey.equals(rhsKey)) && values.equals(rhsAttribute.values);
         }
 
         /**
@@ -216,8 +211,7 @@
             int index = line.indexOf(": ");
             if (index == -1) {
                 throw new ManifestException("Manifest line \"" + line
-                    + "\" is not valid as it does not "
-                    + "contain a name and a value separated by ': ' ");
+                    + "\" is not valid as it does not contain a name and a value separated by ': '");
             }
             name = line.substring(0, index);
             setValue(line.substring(index + 2));
@@ -247,10 +241,7 @@
          * @return the attribute's key.
          */
         public String getKey() {
-            if (name == null) {
-                return null;
-            }
-            return name.toLowerCase(Locale.ENGLISH);
+            return name == null ? null : name.toLowerCase(Locale.ENGLISH);
         }
 
         /**
@@ -273,16 +264,8 @@
          * @return the attribute's value.
          */
         public String getValue() {
-            if (values.size() == 0) {
-                return null;
-            }
-
-            String fullValue = "";
-            for (Enumeration<String> e = getValues(); e.hasMoreElements();) {
-                String value = e.nextElement();
-                fullValue += value + " ";
-            }
-            return fullValue.trim();
+            return values.isEmpty() ? null
+                : String.join(" ", values);
         }
 
         /**
@@ -314,8 +297,7 @@
          * @param line the continuation line.
          */
         public void addContinuation(String line) {
-            String currentValue = values.elementAt(currentIndex);
-            setValue(currentValue + line.substring(1));
+            setValue(values.elementAt(currentIndex) + line.substring(1));
         }
 
         /**
@@ -343,12 +325,12 @@
          */
         public void write(PrintWriter writer, boolean flatten)
             throws IOException {
-            if (!flatten) {
-            for (Enumeration<String> e = getValues(); e.hasMoreElements();) {
-                writeValue(writer, e.nextElement());
-            }
-            } else {
+            if (flatten) {
                 writeValue(writer, getValue());
+            } else {
+                for (String value : values) {
+                    writeValue(writer, value);
+                }
             }
         }
 
@@ -362,8 +344,8 @@
          */
         private void writeValue(PrintWriter writer, String value)
              throws IOException {
-            String line = null;
-            int nameLength = name.getBytes(JAR_ENCODING).length;
+            String line;
+            int nameLength = name.getBytes(JAR_CHARSET).length;
             if (nameLength > MAX_NAME_VALUE_LENGTH) {
                 if (nameLength > MAX_NAME_LENGTH) {
                     throw new IOException("Unable to write manifest line "
@@ -374,14 +356,14 @@
             } else {
                 line = name + ": " + value;
             }
-            while (line.getBytes(JAR_ENCODING).length > MAX_SECTION_LENGTH) {
+            while (line.getBytes(JAR_CHARSET).length > MAX_SECTION_LENGTH) {
                 // try to find a MAX_LINE_LENGTH byte section
                 int breakIndex = MAX_SECTION_LENGTH;
                 if (breakIndex >= line.length()) {
                     breakIndex = line.length() - 1;
                 }
                 String section = line.substring(0, breakIndex);
-                while (section.getBytes(JAR_ENCODING).length > MAX_SECTION_LENGTH
+                while (section.getBytes(JAR_CHARSET).length > MAX_SECTION_LENGTH
                      && breakIndex > 0) {
                     breakIndex--;
                     section = line.substring(0, breakIndex);
@@ -404,7 +386,7 @@
      */
     public static class Section {
         /** Warnings for this section */
-        private Vector<String> warnings = new Vector<String>();
+        private List<String> warnings = new Vector<>();
 
         /**
          * The section's name if any. The main section in a
@@ -413,7 +395,7 @@
         private String name = null;
 
         /** The section's attributes.*/
-        private Map<String, Attribute> attributes = new LinkedHashMap<String, Attribute>();
+        private Map<String, Attribute> attributes = new LinkedHashMap<>();
 
         /**
          * The name of the section; optional -default is the main section.
@@ -450,21 +432,20 @@
             Attribute attribute = null;
             while (true) {
                 String line = reader.readLine();
-                if (line == null || line.length() == 0) {
+                if (line == null || line.isEmpty()) {
                     return null;
                 }
                 if (line.charAt(0) == ' ') {
                     // continuation line
                     if (attribute == null) {
-                        if (name != null) {
-                            // a continuation on the first line is a
-                            // continuation of the name - concatenate this
-                            // line and the name
-                            name += line.substring(1);
-                        } else {
+                        if (name == null) {
                             throw new ManifestException("Can't start an "
                                 + "attribute with a continuation line " + line);
                         }
+                        // a continuation on the first line is a
+                        // continuation of the name - concatenate this
+                        // line and the name
+                        name += line.substring(1);
                     } else {
                         attribute.addContinuation(line);
                     }
@@ -507,25 +488,19 @@
                     && !(name.toLowerCase(Locale.ENGLISH)
                          .equals(section.getName().toLowerCase(Locale.ENGLISH))))
                 ) {
-                throw new ManifestException("Unable to merge sections "
-                    + "with different names");
+                throw new ManifestException(
+                    "Unable to merge sections with different names");
             }
 
-            Enumeration<String> e = section.getAttributeKeys();
             Attribute classpathAttribute = null;
-            while (e.hasMoreElements()) {
-                String attributeName = e.nextElement();
+            for (String attributeName : Collections.list(section.getAttributeKeys())) {
                 Attribute attribute = section.getAttribute(attributeName);
-                if (attributeName.equalsIgnoreCase(ATTRIBUTE_CLASSPATH)) {
+                if (ATTRIBUTE_CLASSPATH.equalsIgnoreCase(attributeName)) {
                     if (classpathAttribute == null) {
                         classpathAttribute = new Attribute();
                         classpathAttribute.setName(ATTRIBUTE_CLASSPATH);
                     }
-                    Enumeration<String> cpe = attribute.getValues();
-                    while (cpe.hasMoreElements()) {
-                        String value = cpe.nextElement();
-                        classpathAttribute.addValue(value);
-                    }
+                    Collections.list(attribute.getValues()).forEach(classpathAttribute::addValue);
                 } else {
                     // the merge file always wins
                     storeAttribute(attribute);
@@ -536,21 +511,14 @@
                 if (mergeClassPaths) {
                     Attribute currentCp = getAttribute(ATTRIBUTE_CLASSPATH);
                     if (currentCp != null) {
-                        for (Enumeration<String> attribEnum = currentCp.getValues();
-                             attribEnum.hasMoreElements();) {
-                            String value = attribEnum.nextElement();
-                            classpathAttribute.addValue(value);
-                        }
+                        Collections.list(currentCp.getValues()).forEach(classpathAttribute::addValue);
                     }
                 }
                 storeAttribute(classpathAttribute);
             }
 
             // add in the warnings
-            Enumeration<String> warnEnum = section.warnings.elements();
-            while (warnEnum.hasMoreElements()) {
-                warnings.addElement(warnEnum.nextElement());
-            }
+            warnings.addAll(section.warnings);
         }
 
         /**
@@ -582,11 +550,8 @@
                 Attribute nameAttr = new Attribute(ATTRIBUTE_NAME, name);
                 nameAttr.write(writer);
             }
-            Enumeration<String> e = getAttributeKeys();
-            while (e.hasMoreElements()) {
-                String key = e.nextElement();
-                Attribute attribute = getAttribute(key);
-                attribute.write(writer, flatten);
+            for (String key : Collections.list(getAttributeKeys())) {
+                getAttribute(key).write(writer, flatten);
             }
             writer.print(EOL);
         }
@@ -610,7 +575,7 @@
          *         key of an attribute of the section.
          */
         public Enumeration<String> getAttributeKeys() {
-            return CollectionUtils.asEnumeration(attributes.keySet().iterator());
+            return Collections.enumeration(attributes.keySet());
         }
 
         /**
@@ -623,10 +588,7 @@
          */
         public String getAttributeValue(String attributeName) {
             Attribute attribute = getAttribute(attributeName.toLowerCase(Locale.ENGLISH));
-            if (attribute == null) {
-                return null;
-            }
-            return attribute.getValue();
+            return attribute == null ? null : attribute.getValue();
         }
 
         /**
@@ -650,9 +612,8 @@
              throws ManifestException {
             String check = addAttributeAndCheck(attribute);
             if (check != null) {
-                throw new BuildException("Specify the section name using "
-                    + "the \"name\" attribute of the <section> element rather "
-                    + "than using a \"Name\" manifest attribute");
+                throw new BuildException(
+                    "Specify the section name using the \"name\" attribute of the <section> element rather than using a \"Name\" manifest attribute");
             }
         }
 
@@ -674,15 +635,14 @@
             }
             String attributeKey = attribute.getKey();
             if (attributeKey.equals(ATTRIBUTE_NAME_LC)) {
-                warnings.addElement("\"" + ATTRIBUTE_NAME + "\" attributes "
-                    + "should not occur in the main section and must be the "
-                    + "first element in all other sections: \""
+                warnings.add("\"" + ATTRIBUTE_NAME
+                    + "\" attributes should not occur in the main section and must be the first element in all other sections: \""
                     + attribute.getName() + ": " + attribute.getValue() + "\"");
                 return attribute.getValue();
             }
 
             if (attributeKey.startsWith(ATTRIBUTE_FROM_LC)) {
-                warnings.addElement(ERROR_FROM_FORBIDDEN
+                warnings.add(ERROR_FROM_FORBIDDEN
                     + attribute.getName() + ": " + attribute.getValue() + "\"");
             } else {
                 // classpath attributes go into a vector
@@ -693,20 +653,14 @@
                     if (classpathAttribute == null) {
                         storeAttribute(attribute);
                     } else {
-                        warnings.addElement("Multiple Class-Path attributes "
-                            + "are supported but violate the Jar "
-                            + "specification and may not be correctly "
-                            + "processed in all environments");
-                        Enumeration<String> e = attribute.getValues();
-                        while (e.hasMoreElements()) {
-                            String value = e.nextElement();
-                            classpathAttribute.addValue(value);
-                        }
+                        warnings.add(
+                            "Multiple Class-Path attributes are supported but violate the Jar specification and may not be correctly processed in all environments");
+                        Collections.list(attribute.getValues()).forEach(classpathAttribute::addValue);
                     }
                 } else if (attributes.containsKey(attributeKey)) {
                     throw new ManifestException("The attribute \""
-                        + attribute.getName() + "\" may not occur more "
-                        + "than once in the same section");
+                        + attribute.getName()
+                        + "\" may not occur more than once in the same section");
                 } else {
                     storeAttribute(attribute);
                 }
@@ -724,13 +678,9 @@
         public Object clone() {
             Section cloned = new Section();
             cloned.setName(name);
-            Enumeration<String> e = getAttributeKeys();
-            while (e.hasMoreElements()) {
-                String key = e.nextElement();
-                Attribute attribute = getAttribute(key);
-                cloned.storeAttribute(new Attribute(attribute.getName(),
-                                                    attribute.getValue()));
-            }
+            StreamUtils.enumerationAsStream(getAttributeKeys())
+                    .map(key -> new Attribute(getAttribute(key).getName(),
+                    getAttribute(key).getValue())).forEach(cloned::storeAttribute);
             return cloned;
         }
 
@@ -743,8 +693,7 @@
             if (attribute == null) {
                 return;
             }
-            String attributeKey = attribute.getKey();
-            attributes.put(attributeKey, attribute);
+            attributes.put(attribute.getKey(), attribute);
         }
 
         /**
@@ -753,7 +702,7 @@
          * @return an Enumeration of warning strings.
          */
         public Enumeration<String> getWarnings() {
-            return warnings.elements();
+            return Collections.enumeration(warnings);
         }
 
         /**
@@ -794,7 +743,7 @@
     private Section mainSection = new Section();
 
     /** The named sections of this manifest */
-    private Map<String, Section> sections = new LinkedHashMap<String, Section>();
+    private Map<String, Section> sections = new LinkedHashMap<>();
 
     /**
      * Construct a manifest from Ant's default manifest file.
@@ -804,38 +753,25 @@
      *            default manifest
      */
     public static Manifest getDefaultManifest() throws BuildException {
-        InputStream in = null;
-        InputStreamReader insr = null;
-        try {
-            String defManifest = "/org/apache/tools/ant/defaultManifest.mf";
-            in = Manifest.class.getResourceAsStream(defManifest);
+        String defManifest = "/org/apache/tools/ant/defaultManifest.mf";
+        try (InputStream in = Manifest.class.getResourceAsStream(defManifest)) {
             if (in == null) {
-                throw new BuildException("Could not find default manifest: "
-                    + defManifest);
+                throw new BuildException("Could not find default manifest: %s",
+                    defManifest);
             }
-            try {
-                insr = new InputStreamReader(in, "UTF-8");
-                Manifest defaultManifest = new Manifest(insr);
-                String version = System.getProperty("java.runtime.version");
-                if (version == null) {
-                    version = System.getProperty("java.vm.version");
-                }
-                Attribute createdBy = new Attribute("Created-By",
-                    version + " ("
-                    + System.getProperty("java.vm.vendor") + ")");
-                defaultManifest.getMainSection().storeAttribute(createdBy);
-                return defaultManifest;
-            } catch (UnsupportedEncodingException e) {
-                insr = new InputStreamReader(in);
-                return new Manifest(insr);
+            Manifest defaultManifest = new Manifest(new InputStreamReader(in, JAR_CHARSET));
+            String version = System.getProperty("java.runtime.version");
+            if (version == null) {
+                version = System.getProperty("java.vm.version");
             }
+            Attribute createdBy = new Attribute("Created-By", version
+                    + " (" + System.getProperty("java.vm.vendor") + ")");
+            defaultManifest.getMainSection().storeAttribute(createdBy);
+            return defaultManifest;
         } catch (ManifestException e) {
             throw new BuildException("Default manifest is invalid !!", e);
         } catch (IOException e) {
             throw new BuildException("Unable to read default manifest", e);
-        } finally {
-            FileUtils.close(insr);
-            FileUtils.close(in);
         }
     }
 
@@ -864,20 +800,20 @@
             mainSection.removeAttribute(ATTRIBUTE_MANIFEST_VERSION);
         }
 
-        String line = null;
+        String line;
         while ((line = reader.readLine()) != null) {
-            if (line.length() == 0) {
+            if (line.isEmpty()) {
                 continue;
             }
 
             Section section = new Section();
             if (nextSectionName == null) {
                 Attribute sectionName = new Attribute(line);
-                if (!sectionName.getName().equalsIgnoreCase(ATTRIBUTE_NAME)) {
-                    throw new ManifestException("Manifest sections should "
-                        + "start with a \"" + ATTRIBUTE_NAME
-                        + "\" attribute and not \""
-                        + sectionName.getName() + "\"");
+                if (!ATTRIBUTE_NAME.equalsIgnoreCase(sectionName.getName())) {
+                    throw new ManifestException(
+                        "Manifest sections should start with a \""
+                            + ATTRIBUTE_NAME + "\" attribute and not \""
+                            + sectionName.getName() + "\"");
                 }
                 nextSectionName = sectionName.getValue();
             } else {
@@ -922,7 +858,7 @@
         if (attribute.getKey() == null || attribute.getValue() == null) {
             throw new BuildException("Attributes must have name and value");
         }
-        if (attribute.getKey().equals(ATTRIBUTE_MANIFEST_VERSION_LC)) {
+        if (ATTRIBUTE_MANIFEST_VERSION_LC.equals(attribute.getKey())) {
             manifestVersion = attribute.getValue();
         } else {
             mainSection.addConfiguredAttribute(attribute);
@@ -986,12 +922,9 @@
                  manifestVersion = other.manifestVersion;
              }
 
-             Enumeration<String> e = other.getSectionNames();
-             while (e.hasMoreElements()) {
-                 String sectionName = e.nextElement();
+             for (String sectionName : Collections.list(other.getSectionNames())) {
                  Section ourSection = sections.get(sectionName);
-                 Section otherSection
-                    = other.sections.get(sectionName);
+                 Section otherSection = other.sections.get(sectionName);
                  if (ourSection == null) {
                      if (otherSection != null) {
                          addConfiguredSection((Section) otherSection.clone());
@@ -1077,22 +1010,14 @@
      * @return an enumeration of warning strings
      */
     public Enumeration<String> getWarnings() {
-        Vector<String> warnings = new Vector<String>();
+        // create a vector and add in the warnings for the main section
+        List<String> warnings = Collections.list(mainSection.getWarnings());
 
-        Enumeration<String> warnEnum = mainSection.getWarnings();
-        while (warnEnum.hasMoreElements()) {
-            warnings.addElement(warnEnum.nextElement());
-        }
+        // add in the warnings for all the sections
+        sections.values().stream().map(section -> Collections.list(section.getWarnings()))
+                .forEach(warnings::addAll);
 
-        // create a vector and add in the warnings for all the sections
-        for (Section section : sections.values()) {
-            Enumeration<String> e2 = section.getWarnings();
-            while (e2.hasMoreElements()) {
-                warnings.addElement(e2.nextElement());
-            }
-        }
-
-        return warnings.elements();
+        return Collections.enumeration(warnings);
     }
 
     /**
@@ -1136,11 +1061,8 @@
             return false;
         }
 
-        if (!mainSection.equals(rhsManifest.mainSection)) {
-            return false;
-        }
+        return mainSection.equals(rhsManifest.mainSection) && sections.equals(rhsManifest.sections);
 
-        return sections.equals(rhsManifest.sections);
     }
 
     /**
@@ -1178,6 +1100,6 @@
      * @return an Enumeration of section names
      */
     public Enumeration<String> getSectionNames() {
-        return CollectionUtils.asEnumeration(sections.keySet().iterator());
+        return Collections.enumeration(sections.keySet());
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java b/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java
index 4a4f231..a1710bf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.UnsupportedEncodingException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
@@ -52,6 +51,7 @@
      * separated list of files and directories relative to the jar
      * file's parent directory.
      */
+    @Override
     public void execute() {
         if (name == null) {
             throw new BuildException("Missing 'property' attribute!");
@@ -60,13 +60,13 @@
             throw new BuildException("Missing 'jarfile' attribute!");
         }
         if (getProject().getProperty(name) != null) {
-            throw new BuildException("Property '" + name + "' already set!");
+            throw new BuildException("Property '%s' already set!", name);
         }
         if (path == null) {
             throw new BuildException("Missing nested <classpath>!");
         }
 
-        StringBuffer tooLongSb = new StringBuffer();
+        StringBuilder tooLongSb = new StringBuilder();
         for (int i = 0; i < maxParentLevels + 1; i++) {
             tooLongSb.append("../");
         }
@@ -76,11 +76,10 @@
         final FileUtils fileUtils = FileUtils.getFileUtils();
         dir = fileUtils.normalize(dir.getAbsolutePath());
 
-        String[] elements = path.list();
-        StringBuffer buffer = new StringBuffer();
-        for (int i = 0; i < elements.length; ++i) {
+        StringBuilder buffer = new StringBuilder();
+        for (String element : path.list()) {
             // Normalize the current file
-            File pathEntry = new File(elements[i]);
+            File pathEntry = new File(element);
             String fullPath = pathEntry.getAbsolutePath();
             pathEntry = fileUtils.normalize(fullPath);
 
@@ -108,18 +107,15 @@
             // No match, so bail out!
             if (relPath.equals(canonicalPath)
                 || relPath.startsWith(tooLongPrefix)) {
-                throw new BuildException("No suitable relative path from "
-                                         + dir + " to " + fullPath);
+                throw new BuildException(
+                    "No suitable relative path from %s to %s", dir, fullPath);
             }
 
             if (pathEntry.isDirectory() && !relPath.endsWith("/")) {
-                relPath = 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
@@ -149,7 +145,7 @@
     public void setJarFile(File jarfile) {
         File parent = jarfile.getParentFile();
         if (!parent.isDirectory()) {
-            throw new BuildException("Jar's directory not found: " + parent);
+            throw new BuildException("Jar's directory not found: %s", parent);
         }
         this.dir = parent;
     }
@@ -162,8 +158,8 @@
      */
     public void setMaxParentLevels(int levels) {
         if (levels < 0) {
-            throw new BuildException("maxParentLevels must not be a negative"
-                                     + " number");
+            throw new BuildException(
+                "maxParentLevels must not be a negative number");
         }
         this.maxParentLevels = levels;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ManifestException.java b/src/main/org/apache/tools/ant/taskdefs/ManifestException.java
index c4e7213..c92074d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ManifestException.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ManifestException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java b/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
index ff6961b..2345b31 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,20 +19,18 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.util.Enumeration;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
-import org.apache.tools.ant.taskdefs.Manifest.Attribute;
 import org.apache.tools.ant.types.EnumeratedAttribute;
-import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * Creates a manifest file for inclusion in a JAR, Ant task wrapper
@@ -91,6 +89,7 @@
          *
          * @return a String array of the allowed values.
          */
+        @Override
         public String[] getValues() {
             return new String[] {"update", "replace"};
         }
@@ -113,12 +112,8 @@
      */
     public void addConfiguredSection(Manifest.Section section)
          throws ManifestException {
-        Enumeration<String> attributeKeys = section.getAttributeKeys();
-        while (attributeKeys.hasMoreElements()) {
-            Attribute attribute = section.getAttribute(
-                attributeKeys.nextElement());
-            checkAttribute(attribute);
-        }
+        StreamUtils.enumerationAsStream(section.getAttributeKeys())
+                .map(section::getAttribute).forEach(this::checkAttribute);
         nestedManifest.addConfiguredSection(section);
     }
 
@@ -143,7 +138,7 @@
      *   alphanum:   {A-Z} | {a-z} | {0-9}
      *   headerchar: alphanum | - | _
      * </pre>
-     * So the resulting regexp would be <tt>[A-Za-z0-9][A-Za-z0-9-_]*</tt>.
+     * So the resulting regexp would be <code>[A-Za-z0-9][A-Za-z0-9-_]*</code>.
      *
      * Because of JDK 1.2 compliance and the possible absence of a
      * regexp matcher we can not use regexps here. Instead we have to
@@ -157,13 +152,15 @@
         char ch = name.charAt(0);
 
         if (ch == '-' || ch == '_') {
-            throw new BuildException("Manifest attribute names must not start with '" + ch + "'.");
+            throw new BuildException(
+                "Manifest attribute names must not start with '%c'.", ch);
         }
 
         for (int i = 0; i < name.length(); i++) {
             ch = name.charAt(i);
             if (VALID_ATTRIBUTE_CHARS.indexOf(ch) < 0) {
-                throw new BuildException("Manifest attribute names must not contain '" + ch + "'");
+                throw new BuildException(
+                    "Manifest attribute names must not contain '%c'", ch);
             }
         }
     }
@@ -219,6 +216,7 @@
      *
      * @throws BuildException if the manifest cannot be written.
      */
+    @Override
     public void execute() throws BuildException {
         if (manifestFile == null) {
             throw new BuildException("the file attribute is required");
@@ -229,15 +227,9 @@
         BuildException error = null;
 
         if (manifestFile.exists()) {
-            FileInputStream fis = null;
-            InputStreamReader isr = null;
-            try {
-                fis = new FileInputStream(manifestFile);
-                if (encoding == null) {
-                    isr = new InputStreamReader(fis, "UTF-8");
-                } else {
-                    isr = new InputStreamReader(fis, encoding);
-                }
+            Charset charset = Charset.forName(encoding == null ? "UTF-8" : encoding);
+            try (InputStreamReader isr = new InputStreamReader(
+                Files.newInputStream(manifestFile.toPath()), charset)) {
                 current = new Manifest(isr);
             } catch (ManifestException m) {
                 error = new BuildException("Existing manifest " + manifestFile
@@ -245,19 +237,14 @@
             } catch (IOException e) {
                 error = new BuildException("Failed to read " + manifestFile,
                                            e, getLocation());
-            } finally {
-                FileUtils.close(isr);
             }
         }
 
-        //look for and print warnings
-        for (Enumeration<String> e = nestedManifest.getWarnings();
-                e.hasMoreElements();) {
-            log("Manifest warning: " + e.nextElement(),
-                    Project.MSG_WARN);
-        }
+        // look for and print warnings
+        StreamUtils.enumerationAsStream(nestedManifest.getWarnings())
+                .forEach(e -> log("Manifest warning: " + e, Project.MSG_WARN));
         try {
-            if (mode.getValue().equals("update") && manifestFile.exists()) {
+            if ("update".equals(mode.getValue()) && manifestFile.exists()) {
                 if (current != null) {
                     toWrite.merge(current, false, mergeClassPaths);
                 } else if (error != null) {
@@ -276,11 +263,8 @@
             return;
         }
 
-        PrintWriter w = null;
-        try {
-            FileOutputStream fos = new FileOutputStream(manifestFile);
-            OutputStreamWriter osw = new OutputStreamWriter(fos, Manifest.JAR_ENCODING);
-            w = new PrintWriter(osw);
+        try (PrintWriter w = new PrintWriter(new OutputStreamWriter(
+            Files.newOutputStream(manifestFile.toPath()), Manifest.JAR_CHARSET))) {
             toWrite.write(w, flattenClassPaths);
             if (w.checkError()) {
                 throw new IOException("Encountered an error writing manifest");
@@ -288,8 +272,6 @@
         } catch (IOException e) {
             throw new BuildException("Failed to write " + manifestFile,
                                      e, getLocation());
-        } finally {
-            FileUtils.close(w);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java b/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java
index 8707a39..063b720 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -62,6 +62,7 @@
     // CheckStyle:VisibilityModifier ON
 
     /** {@inheritDoc}. */
+    @Override
     public void setProject(Project project) {
         super.setProject(project);
         fileset.setProject(project);
@@ -128,14 +129,14 @@
     public void XsetItems(String itemString) {
         log("The items attribute is deprecated. "
             + "Please use the includes attribute.", Project.MSG_WARN);
-        if (itemString == null || itemString.equals("*")
-            || itemString.equals(".")) {
+        if (itemString == null || "*".equals(itemString)
+            || ".".equals(itemString)) {
             createInclude().setName("**");
         } else {
             StringTokenizer tok = new StringTokenizer(itemString, ", ");
             while (tok.hasMoreTokens()) {
                 String pattern = tok.nextToken().trim();
-                if (pattern.length() > 0) {
+                if (!pattern.isEmpty()) {
                     createInclude().setName(pattern + "/**");
                 }
             }
@@ -161,7 +162,7 @@
     public void XsetIgnore(String ignoreString) {
         log("The ignore attribute is deprecated."
             + "Please use the excludes attribute.", Project.MSG_WARN);
-        if (ignoreString != null && ignoreString.length() > 0) {
+        if (ignoreString != null && !ignoreString.isEmpty()) {
             StringTokenizer tok = new StringTokenizer(ignoreString, ", ",
                                                       false);
             while (tok.hasMoreTokens()) {
@@ -237,6 +238,7 @@
      *
      * @return whether any selectors are in this container
      */
+    @Override
     public boolean hasSelectors() {
         return fileset.hasSelectors();
     }
@@ -246,6 +248,7 @@
      *
      * @return the number of selectors in this container
      */
+    @Override
     public int selectorCount() {
         return fileset.selectorCount();
     }
@@ -255,6 +258,7 @@
      * @param p the current project
      * @return an array of selectors in this container
      */
+    @Override
     public FileSelector[] getSelectors(Project p) {
         return fileset.getSelectors(p);
     }
@@ -264,6 +268,7 @@
      *
      * @return an enumerator that goes through each of the selectors
      */
+    @Override
     public Enumeration<FileSelector> selectorElements() {
         return fileset.selectorElements();
     }
@@ -273,6 +278,7 @@
      *
      * @param selector the new selector to add
      */
+    @Override
     public void appendSelector(FileSelector selector) {
         fileset.appendSelector(selector);
     }
@@ -283,6 +289,7 @@
      * add a "Select" selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addSelector(SelectSelector selector) {
         fileset.addSelector(selector);
     }
@@ -291,6 +298,7 @@
      * add an "And" selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addAnd(AndSelector selector) {
         fileset.addAnd(selector);
     }
@@ -299,6 +307,7 @@
      * add an "Or" selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addOr(OrSelector selector) {
         fileset.addOr(selector);
     }
@@ -307,6 +316,7 @@
      * add a "Not" selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addNot(NotSelector selector) {
         fileset.addNot(selector);
     }
@@ -315,6 +325,7 @@
      * add a "None" selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addNone(NoneSelector selector) {
         fileset.addNone(selector);
     }
@@ -323,6 +334,7 @@
      * add a majority selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addMajority(MajoritySelector selector) {
         fileset.addMajority(selector);
     }
@@ -331,6 +343,7 @@
      * add a selector date entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addDate(DateSelector selector) {
         fileset.addDate(selector);
     }
@@ -339,6 +352,7 @@
      * add a selector size entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addSize(SizeSelector selector) {
         fileset.addSize(selector);
     }
@@ -347,6 +361,7 @@
      * add a selector filename entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addFilename(FilenameSelector selector) {
         fileset.addFilename(selector);
     }
@@ -355,6 +370,7 @@
      * add an extended selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addCustom(ExtendSelector selector) {
         fileset.addCustom(selector);
     }
@@ -363,6 +379,7 @@
      * add a contains selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addContains(ContainsSelector selector) {
         fileset.addContains(selector);
     }
@@ -371,6 +388,7 @@
      * add a present selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addPresent(PresentSelector selector) {
         fileset.addPresent(selector);
     }
@@ -379,6 +397,7 @@
      * add a depth selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addDepth(DepthSelector selector) {
         fileset.addDepth(selector);
     }
@@ -387,6 +406,7 @@
      * add a depends selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addDepend(DependSelector selector) {
         fileset.addDepend(selector);
     }
@@ -395,6 +415,7 @@
      * add a regular expression selector entry on the selector list
      * @param selector the selector to add
      */
+    @Override
     public void addContainsRegexp(ContainsRegexpSelector selector) {
         fileset.addContainsRegexp(selector);
     }
@@ -404,6 +425,7 @@
      * @param selector the selector to add
      * @since ant 1.6
      */
+    @Override
     public void addDifferent(DifferentSelector selector) {
         fileset.addDifferent(selector);
     }
@@ -413,6 +435,7 @@
      * @param selector the selector to add
      * @since ant 1.6
      */
+    @Override
     public void addType(TypeSelector selector) {
         fileset.addType(selector);
     }
@@ -422,6 +445,7 @@
      * @param selector the selector to add
      * @since ant 1.6
      */
+    @Override
     public void addModified(ModifiedSelector selector) {
         fileset.addModified(selector);
     }
@@ -431,6 +455,7 @@
      * @param selector the selector to add
      * @since Ant 1.6
      */
+    @Override
     public void add(FileSelector selector) {
         fileset.add(selector);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Mkdir.java b/src/main/org/apache/tools/ant/taskdefs/Mkdir.java
index 71b6c94..a69050d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Mkdir.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Mkdir.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,29 +46,30 @@
      * create the directory and all parents
      * @throws BuildException if dir is somehow invalid, or creation failed.
      */
+    @Override
     public void execute() throws BuildException {
         if (dir == null) {
             throw new BuildException("dir attribute is required", getLocation());
         }
 
         if (dir.isFile()) {
-            throw new BuildException("Unable to create directory as a file "
-                                     + "already exists with that name: "
-                                     + dir.getAbsolutePath());
+            throw new BuildException(
+                "Unable to create directory as a file already exists with that name: %s",
+                dir.getAbsolutePath());
         }
 
         if (!dir.exists()) {
             boolean result = mkdirs(dir);
             if (!result) {
                 if (dir.exists()) {
-                    log("A different process or task has already created "
-                        + "dir " + dir.getAbsolutePath(),
-                        Project.MSG_VERBOSE);
+                    log("A different process or task has already created dir "
+                        + dir.getAbsolutePath(), Project.MSG_VERBOSE);
                     return;
                 }
-                String msg = "Directory " + dir.getAbsolutePath()
-                    + " creation was not successful for an unknown reason";
-                throw new BuildException(msg, getLocation());
+                throw new BuildException(
+                    "Directory " + dir.getAbsolutePath()
+                        + " creation was not successful for an unknown reason",
+                    getLocation());
             }
             log("Created dir: " + dir.getAbsolutePath());
         } else {
@@ -111,4 +112,3 @@
         return true;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/Move.java b/src/main/org/apache/tools/ant/taskdefs/Move.java
index 0149cc8..7dadc1b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Move.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Move.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
@@ -27,7 +26,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.types.FilterSet;
 import org.apache.tools.ant.types.FilterSetCollection;
 
 /**
@@ -81,6 +79,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     protected void validateAttributes() throws BuildException {
         if (file != null && file.isDirectory()) {
             if ((destFile != null && destDir != null)
@@ -104,12 +103,13 @@
     /**
      * Override copy's doFileOperations to move the files instead of copying them.
      */
+    @Override
     protected void doFileOperations() {
         //Attempt complete directory renames, if any, first.
         if (completeDirMap.size() > 0) {
-            for (Iterator fromDirs = completeDirMap.keySet().iterator(); fromDirs.hasNext();) {
-                File fromDir = (File) fromDirs.next();
-                File toDir = (File) completeDirMap.get(fromDir);
+            for (Map.Entry<File, File> entry : completeDirMap.entrySet()) {
+                File fromDir = entry.getKey();
+                File toDir = entry.getValue();
                 boolean renamed = false;
                 try {
                     log("Attempting to rename dir: " + fromDir + " to " + toDir, verbosity);
@@ -125,9 +125,7 @@
                     fs.setDir(fromDir);
                     addFileset(fs);
                     DirectoryScanner ds = fs.getDirectoryScanner(getProject());
-                    String[] files = ds.getIncludedFiles();
-                    String[] dirs = ds.getIncludedDirectories();
-                    scan(fromDir, toDir, files, dirs);
+                    scan(fromDir, toDir, ds.getIncludedFiles(), ds.getIncludedDirectories());
                 }
             }
         }
@@ -136,14 +134,14 @@
             log("Moving " + moveCount + " file" + ((moveCount == 1) ? "" : "s")
                     + " to " + destDir.getAbsolutePath());
 
-            for (Iterator fromFiles = fileCopyMap.keySet().iterator(); fromFiles.hasNext();) {
-                String fromFile = (String) fromFiles.next();
+            for (Map.Entry<String, String[]> entry : fileCopyMap.entrySet()) {
+                String fromFile = entry.getKey();
                 File f = new File(fromFile);
                 boolean selfMove = false;
                 if (f.exists()) { //Is this file still available to be moved?
-                    String[] toFiles = (String[]) fileCopyMap.get(fromFile);
+                    String[] toFiles = entry.getValue();
                     for (int i = 0; i < toFiles.length; i++) {
-                        String toFile = (String) toFiles[i];
+                        String toFile = toFiles[i];
 
                         if (fromFile.equals(toFile)) {
                             log("Skipping self-move of " + fromFile, verbosity);
@@ -179,7 +177,7 @@
                     }
                     File d = new File(toDirName);
                     if (!d.exists()) {
-                        if (!(d.mkdirs() || d.exists())) {
+                        if (!d.mkdirs() && !d.exists()) {
                             log("Unable to create directory "
                                     + d.getAbsolutePath(), Project.MSG_ERR);
                         } else {
@@ -214,16 +212,15 @@
             log("Attempting to rename: " + fromFile + " to " + toFile, verbosity);
             moved = renameFile(fromFile, toFile, filtering, forceOverwrite);
         } catch (IOException ioe) {
-            String msg = "Failed to rename " + fromFile
-                + " to " + toFile + " due to " + ioe.getMessage();
-            throw new BuildException(msg, ioe, getLocation());
+            throw new BuildException("Failed to rename " + fromFile + " to "
+                + toFile + " due to " + ioe.getMessage(), ioe, getLocation());
         }
 
         if (!moved) {
             copyFile(fromFile, toFile, filtering, overwrite);
             if (!getFileUtils().tryHardToDelete(fromFile, performGc)) {
-                throw new BuildException("Unable to delete " + "file "
-                        + fromFile.getAbsolutePath());
+                throw new BuildException("Unable to delete file %s",
+                    fromFile.getAbsolutePath());
             }
         }
     }
@@ -243,9 +240,7 @@
             if (filtering) {
                 executionFilters.addFilterSet(getProject().getGlobalFilterSet());
             }
-            for (Iterator filterIter = getFilterSets().iterator(); filterIter.hasNext();) {
-                executionFilters.addFilterSet((FilterSet) filterIter.next());
-            }
+            getFilterSets().forEach(executionFilters::addFilterSet);
             getFileUtils().copyFile(fromFile, toFile, executionFilters,
                                     getFilterChains(),
                                     forceOverwrite,
@@ -255,9 +250,8 @@
                                     getOutputEncoding(),
                                     getProject(), getForce());
         } catch (IOException ioe) {
-            String msg = "Failed to copy " + fromFile
-                    + " to " + toFile + " due to " + ioe.getMessage();
-            throw new BuildException(msg, ioe, getLocation());
+            throw new BuildException("Failed to copy " + fromFile + " to "
+                + toFile + " due to " + ioe.getMessage(), ioe, getLocation());
         }
     }
 
@@ -272,8 +266,7 @@
             return false;
         }     // maybe io error?
 
-        for (int i = 0; i < list.length; i++) {
-            String s = list[i];
+        for (String s : list) {
             File f = new File(d, s);
             if (f.isDirectory()) {
                 if (!okToDelete(f)) {
@@ -305,22 +298,24 @@
             return;
         }      // on an io error list() can return null
 
-        for (int i = 0; i < list.length; i++) {
-            String s = list[i];
+        for (String s : list) {
             File f = new File(d, s);
             if (f.isDirectory()) {
                 deleteDir(f);
-            } else if (deleteFiles && !getFileUtils().tryHardToDelete(f,
-                                                                      performGc)) {
-                throw new BuildException("Unable to delete file " + f.getAbsolutePath());
+            } else if (deleteFiles
+                && !getFileUtils().tryHardToDelete(f, performGc)) {
+                throw new BuildException("Unable to delete file %s",
+                    f.getAbsolutePath());
             } else {
-                throw new BuildException("UNEXPECTED ERROR - The file "
-                        + f.getAbsolutePath() + " should not exist!");
+                throw new BuildException(
+                    "UNEXPECTED ERROR - The file %s should not exist!",
+                    f.getAbsolutePath());
             }
         }
         log("Deleting directory " + d.getAbsolutePath(), verbosity);
         if (!getFileUtils().tryHardToDelete(d, performGc)) {
-            throw new BuildException("Unable to delete directory " + d.getAbsolutePath());
+            throw new BuildException("Unable to delete directory %s",
+                d.getAbsolutePath());
         }
     }
 
@@ -344,19 +339,21 @@
      */
     protected boolean renameFile(File sourceFile, File destFile, boolean filtering,
                                  boolean overwrite) throws IOException, BuildException {
-        if (destFile.isDirectory() || filtering || getFilterSets().size() > 0
-                || getFilterChains().size() > 0) {
+        if (destFile.isDirectory() || filtering || !getFilterSets().isEmpty()
+                || !getFilterChains().isEmpty()) {
             return false;
         }
 
         // identical logic lives in ResourceUtils.copyResource():
         if (destFile.isFile() && !destFile.canWrite()) {
             if (!getForce()) {
-                throw new IOException("can't replace read-only destination "
-                                      + "file " + destFile);
-            } else if (!getFileUtils().tryHardToDelete(destFile)) {
-                throw new IOException("failed to delete read-only "
-                                      + "destination file " + destFile);
+                throw new IOException(String.format(
+                    "can't replace read-only destination file %s", destFile));
+            }
+            if (!getFileUtils().tryHardToDelete(destFile)) {
+                throw new IOException(String.format(
+                    "failed to delete read-only destination file %s",
+                    destFile));
             }
         }
 
@@ -373,9 +370,10 @@
                     + " is a no-op.", Project.MSG_VERBOSE);
                 return true;
             }
-            if (!(getFileUtils().areSame(sourceFile, destFile)
-                  || getFileUtils().tryHardToDelete(destFile, performGc))) {
-                throw new BuildException("Unable to remove existing file " + destFile);
+            if (!getFileUtils().areSame(sourceFile, destFile)
+                    && !getFileUtils().tryHardToDelete(destFile, performGc)) {
+                throw new BuildException("Unable to remove existing file %s",
+                    destFile);
             }
         }
         return sourceFile.renameTo(destFile);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Nice.java b/src/main/org/apache/tools/ant/taskdefs/Nice.java
index 5898cae..9550316 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Nice.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Nice.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -48,12 +48,11 @@
      */
     private String currentPriority;
 
-
-
     /**
      * Execute the task
      * @exception BuildException if something goes wrong with the build
      */
+    @Override
     public void execute() throws BuildException {
 
         Thread self = Thread.currentThread();
@@ -63,9 +62,9 @@
             getProject().setNewProperty(currentPriority, current);
         }
         //if there is a new priority, and it is different, change it
-        if (newPriority != null && priority != newPriority.intValue()) {
+        if (newPriority != null && priority != newPriority) {
             try {
-                self.setPriority(newPriority.intValue());
+                self.setPriority(newPriority);
             } catch (SecurityException e) {
                 //catch permissions denial and keep going
                 log("Unable to set new priority -a security manager is in the way",
@@ -93,7 +92,7 @@
         if (newPriority < Thread.MIN_PRIORITY || newPriority > Thread.MAX_PRIORITY) {
             throw new BuildException("The thread priority is out of the range 1-10");
         }
-        this.newPriority = new Integer(newPriority);
+        this.newPriority = newPriority;
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Pack.java b/src/main/org/apache/tools/ant/taskdefs/Pack.java
index 63dfe05..eaf3f3b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Pack.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Pack.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,6 +38,7 @@
 
 public abstract class Pack extends Task {
     private static final int BUFFER_SIZE = 8 * 1024;
+
     // CheckStyle:VisibilityModifier OFF - bc
     protected File zipFile;
     protected File source;
@@ -91,13 +92,14 @@
      */
     public void addConfigured(ResourceCollection a) {
         if (a.size() == 0) {
-            throw new BuildException("No resource selected, " + getTaskName()
-                    + " needs exactly one resource.");
+            throw new BuildException(
+                "No resource selected, %s needs exactly one resource.",
+                getTaskName());
         }
         if (a.size() != 1) {
-            throw new BuildException(getTaskName()
-                    + " cannot handle multiple resources at once. (" + a.size()
-                    + " resources were selected.)");
+            throw new BuildException(
+                "%s cannot handle multiple resources at once. (%d resources were selected.)",
+                getTaskName(), a.size());
         }
         setSrcResource(a.iterator().next());
     }
@@ -112,13 +114,14 @@
         }
 
         if (zipFile.isDirectory()) {
-            throw new BuildException("zipfile attribute must not "
-                                    + "represent a directory!", getLocation());
+            throw new BuildException(
+                "zipfile attribute must not represent a directory!",
+                getLocation());
         }
 
         if (getSrcResource() == null) {
-            throw new BuildException("src attribute or nested resource is"
-                                     + " required", getLocation());
+            throw new BuildException(
+                "src attribute or nested resource is required", getLocation());
         }
     }
 
@@ -126,6 +129,7 @@
      * validate, then hand off to the subclass
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         validate();
 
@@ -177,11 +181,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/Parallel.java b/src/main/org/apache/tools/ant/taskdefs/Parallel.java
index f46d4ad..757c804 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Parallel.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Parallel.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.List;
 import java.util.Vector;
 
@@ -28,7 +27,6 @@
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.TaskContainer;
 import org.apache.tools.ant.property.LocalProperties;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Executes the contained tasks in separate threads, continuing
@@ -56,21 +54,22 @@
     /** Class which holds a list of tasks to execute */
     public static class TaskList implements TaskContainer {
         /** Collection holding the nested tasks */
-        private List tasks = new ArrayList();
+        private List<Task> tasks = new ArrayList<>();
 
         /**
-         * Add a nested task to execute parallel (asynchron).
+         * Add a nested task to execute in parallel (asynchronously).
          * <p>
          * @param nestedTask  Nested task to be executed in parallel.
          *                    must not be null.
          */
+        @Override
         public void addTask(Task nestedTask) {
             tasks.add(nestedTask);
         }
     }
 
     /** Collection holding the nested tasks */
-    private Vector nestedTasks = new Vector();
+    private Vector<Task> nestedTasks = new Vector<>();
 
     /** Semaphore to notify of completed threads */
     private final Object semaphore = new Object();
@@ -96,7 +95,7 @@
      */
     private boolean failOnAny;
 
-    /** The dameon task list if any */
+    /** The daemon task list if any */
     private TaskList daemonTasks;
 
     /** Accumulation of exceptions messages from all nested tasks */
@@ -150,6 +149,7 @@
      * Add a nested task to execute in parallel.
      * @param nestedTask  Nested task to be executed in parallel
      */
+    @Override
     public void addTask(Task nestedTask) {
         nestedTasks.addElement(nestedTask);
     }
@@ -195,13 +195,12 @@
         this.timeout = timeout;
     }
 
-
-
     /**
      * Execute the parallel tasks
      *
      * @exception BuildException if any of the threads failed.
      */
+    @Override
     public void execute() throws BuildException {
         updateThreadCounts();
         if (numThreads == 0) {
@@ -215,8 +214,8 @@
      */
     private void updateThreadCounts() {
         if (numThreadsPerProcessor != 0) {
-            numThreads = Runtime.getRuntime().availableProcessors() *
-                    numThreadsPerProcessor;
+            numThreads = Runtime.getRuntime().availableProcessors()
+                    * numThreadsPerProcessor;
         }
     }
 
@@ -224,8 +223,8 @@
         if (runnables == null) {
             return;
         }
-        for (int i = 0; i < runnables.length; ++i) {
-            Throwable t = runnables[i].getException();
+        for (TaskRunnable runnable : runnables) {
+            Throwable t = runnable.getException();
             if (t != null) {
                 numExceptions++;
                 if (firstException == null) {
@@ -243,7 +242,7 @@
                     // location should match the exit status
                     firstLocation = ex.getLocation();
                 }
-                exceptionMessage.append(StringUtils.LINE_SEP);
+                exceptionMessage.append(System.lineSeparator());
                 exceptionMessage.append(t.getMessage());
             }
         }
@@ -255,28 +254,21 @@
      * @exception BuildException if any of the threads failed.
      */
     private void spinThreads() throws BuildException {
-        final int numTasks = nestedTasks.size();
-        TaskRunnable[] runnables = new TaskRunnable[numTasks];
         stillRunning = true;
         timedOut = false;
         boolean interrupted = false;
 
-        int threadNumber = 0;
-        for (Enumeration e = nestedTasks.elements(); e.hasMoreElements();
-             threadNumber++) {
-            Task nestedTask = (Task) e.nextElement();
-            runnables[threadNumber]
-                = new TaskRunnable(nestedTask);
-        }
+        TaskRunnable[] runnables = nestedTasks.stream().map(TaskRunnable::new)
+            .toArray(TaskRunnable[]::new);
 
+        final int numTasks = nestedTasks.size();
         final int maxRunning = numTasks < numThreads ? numTasks : numThreads;
-        TaskRunnable[] running = new TaskRunnable[maxRunning];
 
-        threadNumber = 0;
+        TaskRunnable[] running = new TaskRunnable[maxRunning];
         ThreadGroup group = new ThreadGroup("parallel");
 
         TaskRunnable[] daemons = null;
-        if (daemonTasks != null && daemonTasks.tasks.size() != 0) {
+        if (daemonTasks != null && !daemonTasks.tasks.isEmpty()) {
             daemons = new TaskRunnable[daemonTasks.tasks.size()];
         }
 
@@ -292,7 +284,7 @@
             // start any daemon threads
             if (daemons != null) {
                 for (int i = 0; i < daemons.length; ++i) {
-                    daemons[i] = new TaskRunnable((Task) daemonTasks.tasks.get(i));
+                    daemons[i] = new TaskRunnable(daemonTasks.tasks.get(i));
                     Thread daemonThread =  new Thread(group, daemons[i]);
                     daemonThread.setDaemon(true);
                     daemonThread.start();
@@ -301,6 +293,7 @@
 
             // now run main threads in limited numbers...
             // start initial batch of threads
+            int threadNumber = 0;
             for (int i = 0; i < maxRunning; ++i) {
                 running[i] = runnables[threadNumber++];
                 Thread thread =  new Thread(group, running[i]);
@@ -310,6 +303,7 @@
             if (timeout != 0) {
                 // start the timeout thread
                 Thread timeoutThread = new Thread() {
+                    @Override
                     public synchronized void run() {
                         try {
                             final long start = System.currentTimeMillis();
@@ -393,17 +387,16 @@
         if (numExceptions == 1) {
             if (firstException instanceof BuildException) {
                 throw (BuildException) firstException;
-            } else {
-                throw new BuildException(firstException);
             }
-        } else if (numExceptions > 1) {
+            throw new BuildException(firstException);
+        }
+        if (numExceptions > 1) {
             if (firstExitStatus == null) {
                 throw new BuildException(exceptionMessage.toString(),
                                          firstLocation);
-            } else {
-                throw new ExitStatusException(exceptionMessage.toString(),
-                                              firstExitStatus, firstLocation);
             }
+            throw new ExitStatusException(exceptionMessage.toString(),
+                                          firstExitStatus, firstLocation);
         }
     }
 
@@ -453,6 +446,7 @@
          * Executes the task within a thread and takes care about
          * Exceptions raised within the task.
          */
+        @Override
         public void run() {
             try {
                 LocalProperties.get(getProject()).copy();
diff --git a/src/main/org/apache/tools/ant/taskdefs/Patch.java b/src/main/org/apache/tools/ant/taskdefs/Patch.java
index 96ab082..5aca771 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Patch.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Patch.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -74,7 +74,7 @@
      */
     public void setPatchfile(File file) {
         if (!file.exists()) {
-            throw new BuildException("patchfile " + file + " doesn\'t exist",
+            throw new BuildException("patchfile " + file + " doesn't exist",
                                      getLocation());
         }
         cmd.createArgument().setValue("-i");
@@ -165,12 +165,13 @@
      * execute patch
      * @throws BuildException when it all goes a bit pear shaped
      */
+    @Override
     public void execute() throws BuildException {
         if (!havePatchfile) {
             throw new BuildException("patchfile argument is required",
                                      getLocation());
         }
-        Commandline toExecute = (Commandline) cmd.clone();
+        Commandline toExecute =  (Commandline) cmd.clone();
         toExecute.setExecutable(PATCH);
 
         if (originalFile != null) {
@@ -182,18 +183,14 @@
                                   null);
         exe.setCommandline(toExecute.getCommandline());
 
-        if (directory != null) {
-            if (directory.exists() && directory.isDirectory()) {
-                exe.setWorkingDirectory(directory);
-            } else if (!directory.isDirectory()) {
+        if (directory == null) {
+            exe.setWorkingDirectory(getProject().getBaseDir());
+        } else {
+            if (!directory.isDirectory()) {
                 throw new BuildException(directory + " is not a directory.",
                                          getLocation());
-            } else {
-                throw new BuildException("directory " + directory
-                                         + " doesn\'t exist", getLocation());
             }
-        } else {
-            exe.setWorkingDirectory(getProject().getBaseDir());
+            exe.setWorkingDirectory(directory);
         }
 
         log(toExecute.describeCommand(), Project.MSG_VERBOSE);
@@ -204,9 +201,8 @@
                     + returncode;
                 if (failOnError) {
                     throw new BuildException(msg);
-                } else {
-                    log(msg, Project.MSG_ERR);
                 }
+                log(msg, Project.MSG_ERR);
             }
         } catch (IOException e) {
             throw new BuildException(e, getLocation());
diff --git a/src/main/org/apache/tools/ant/taskdefs/PathConvert.java b/src/main/org/apache/tools/ant/taskdefs/PathConvert.java
index 0fc1f5b..45b2a6e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/PathConvert.java
+++ b/src/main/org/apache/tools/ant/taskdefs/PathConvert.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,12 +17,19 @@
  */
 package org.apache.tools.ant.taskdefs;
 
+import java.io.Closeable;
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Iterator;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.util.List;
-import java.util.StringTokenizer;
+import java.util.Objects;
 import java.util.Vector;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -38,6 +45,7 @@
 import org.apache.tools.ant.types.resources.Union;
 import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.IdentityMapper;
+import org.apache.tools.ant.util.PropertyOutputStream;
 
 /**
  * Converts path and classpath information to a specific target OS
@@ -47,6 +55,29 @@
  * @ant.task category="utility"
  */
 public class PathConvert extends Task {
+    private abstract class Output<T extends Closeable> implements Consumer<String>, Closeable {
+        final T target;
+
+        Output(T target) {
+            this.target = target;
+        }
+
+        @Override
+        public void close() throws IOException {
+            target.close();
+        }
+
+        @Override
+        public void accept(String t) {
+            try {
+                doAccept(t);
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        abstract void doAccept(String t) throws Exception;
+    }
 
     /**
      * Set if we're running on windows
@@ -57,19 +88,19 @@
     /**
      * Path to be converted
      */
-    private Resources path = null;
+    private Resources path;
     /**
      * Reference to path/fileset to convert
      */
-    private Reference refid = null;
+    private Reference refid;
     /**
      * The target OS type
      */
-    private String targetOS = null;
+    private String targetOS;
     /**
      * Set when targetOS is set to windows
      */
-    private boolean targetWindows = false;
+    private boolean targetWindows;
     /**
      * Set if we should create a new property even if the result is empty
      */
@@ -77,30 +108,27 @@
     /**
      * The property to receive the conversion
      */
-    private String property = null;
+    private String property;
     /**
      * Path prefix map
      */
-    private Vector prefixMap = new Vector();
+    private List<MapEntry> prefixMap = new Vector<>();
     /**
      * User override on path sep char
      */
-    private String pathSep = null;
+    private String pathSep;
     /**
      * User override on directory sep char
      */
-    private String dirSep = null;
+    private String dirSep;
 
     /** Filename mapper */
-    private Mapper mapper = null;
+    private Mapper mapper;
 
     private boolean preserveDuplicates;
 
-    /**
-     * Construct a new instance of the PathConvert task.
-     */
-    public PathConvert() {
-    }
+    /** Destination {@link Resource} */
+    private Resource dest;
 
     /**
      * Helper class, holds the nested &lt;map&gt; values. Elements will look like
@@ -142,8 +170,8 @@
          */
         public String apply(String elem) {
             if (from == null || to == null) {
-                throw new BuildException("Both 'from' and 'to' must be set "
-                     + "in a map entry");
+                throw new BuildException(
+                    "Both 'from' and 'to' must be set in a map entry");
             }
             // If we're on windows, then do the comparison ignoring case
             // and treat the two directory characters the same
@@ -202,7 +230,7 @@
     private synchronized Resources getPath() {
         if (path == null) {
             path = new Resources(getProject());
-            path.setCache(true);
+            path.setCache(false);
         }
         return path;
     }
@@ -213,7 +241,7 @@
      */
     public MapEntry createMap() {
         MapEntry entry = new MapEntry();
-        prefixMap.addElement(entry);
+        prefixMap.add(entry);
         return entry;
     }
 
@@ -251,7 +279,7 @@
         // validateSetup code, the same assumptions can be made as
         // with windows - that ; is the path separator
 
-        targetWindows = !targetOS.equals("unix") && !targetOS.equals("tandem");
+        targetWindows = !"unix".equals(targetOS) && !"tandem".equals(targetOS);
     }
 
     /**
@@ -293,7 +321,6 @@
         pathSep = sep;
     }
 
-
     /**
      * Set the default directory separator string;
      * defaults to current JVM {@link java.io.File#separator File.separator}.
@@ -330,6 +357,20 @@
     }
 
     /**
+     * Set destination resource.
+     * @param dest
+     * @since Ant 1.10.13
+     */
+    public void setDest(Resource dest) {
+        if (dest != null) {
+            if (this.dest != null) {
+                throw new BuildException("@dest already set");
+            }
+        }
+        this.dest = dest;
+    }
+
+    /**
      * Do the execution.
      * @throws BuildException if something is invalid.
      */
@@ -344,63 +385,26 @@
             if (isReference()) {
                 Object o = refid.getReferencedObject(getProject());
                 if (!(o instanceof ResourceCollection)) {
-                    throw new BuildException("refid '" + refid.getRefId()
-                        + "' does not refer to a resource collection.");
+                    throw new BuildException(
+                        "refid '%s' does not refer to a resource collection.",
+                        refid.getRefId());
                 }
                 getPath().add((ResourceCollection) o);
             }
             validateSetup(); // validate our setup
 
-            // Currently, we deal with only two path formats: Unix and Windows
-            // And Unix is everything that is not Windows
-            // (with the exception for NetWare and OS/2 below)
-
-            // for NetWare and OS/2, piggy-back on Windows, since here and
-            // in the apply code, the same assumptions can be made as with
-            // windows - that \\ is an OK separator, and do comparisons
-            // case-insensitive.
-            String fromDirSep = onWindows ? "\\" : "/";
-
-            StringBuffer rslt = new StringBuffer();
-
-            ResourceCollection resources = isPreserveDuplicates() ? (ResourceCollection) path : new Union(path);
-            List ret = new ArrayList();
-            FileNameMapper mapperImpl = mapper == null ? new IdentityMapper() : mapper.getImplementation();
-            for (Resource r : resources) {
-                String[] mapped = mapperImpl.mapFileName(String.valueOf(r));
-                for (int m = 0; mapped != null && m < mapped.length; ++m) {
-                    ret.add(mapped[m]);
-                }
-            }
             boolean first = true;
-            for (Iterator mappedIter = ret.iterator(); mappedIter.hasNext();) {
-                String elem = mapElement((String) mappedIter.next()); // Apply the path prefix map
-
-                // Now convert the path and file separator characters from the
-                // current os to the target os.
-
-                if (!first) {
-                    rslt.append(pathSep);
+            try (Output<?> o = createOutput()) {
+                for (String s : (Iterable<String>) streamResources()::iterator) {
+                    if (first) {
+                        first = false;
+                    } else {
+                        o.accept(pathSep);
+                    }
+                    o.accept(s);
                 }
-                first = false;
-
-                StringTokenizer stDirectory = new StringTokenizer(elem, fromDirSep, true);
-
-                while (stDirectory.hasMoreTokens()) {
-                    String token = stDirectory.nextToken();
-                    rslt.append(fromDirSep.equals(token) ? dirSep : token);
-                }
-            }
-            // Place the result into the specified property,
-            // unless setonempty == false
-            if (setonempty || rslt.length() > 0) {
-                String value = rslt.toString();
-                if (property == null) {
-                    log(value);
-                } else {
-                    log("Set property " + property + " = " + value, Project.MSG_VERBOSE);
-                    getProject().setNewProperty(property, value);
-                }
+            } catch (IOException e) {
+                throw new BuildException(e);
             }
         } finally {
             path = savedPath;
@@ -409,6 +413,65 @@
         }
     }
 
+    @SuppressWarnings("resource")
+    private Output<?> createOutput() throws IOException {
+        if (dest != null) {
+            return new Output<Writer>(new OutputStreamWriter(dest.getOutputStream())) {
+
+                @Override
+                void doAccept(String t) throws IOException {
+                    target.write(t);
+                }
+            };
+        }
+        // avoid OutputStreamWriter's buffering:
+        final OutputStream out;
+        if (property == null) {
+            out = new LogOutputStream(this);
+        } else {
+            out = new PropertyOutputStream(getProject(), property) {
+                @Override
+                public void close() {
+                    if (setonempty || size() > 0) {
+                        super.close();
+                        log("Set property " + property + " = " + getProject().getProperty(property),
+                            Project.MSG_VERBOSE);
+                    }
+                }
+            };
+        }
+        return new Output<OutputStream>(out) {
+
+            @Override
+            void doAccept(String t) throws IOException {
+                target.write(t.getBytes());
+            }
+        };
+    }
+
+    private Stream<String> streamResources() {
+        ResourceCollection resources = isPreserveDuplicates() ? path : Union.getInstance(path);
+        FileNameMapper mapperImpl = mapper == null ? new IdentityMapper() : mapper.getImplementation();
+
+        final boolean parallel = false;
+        Stream<String> result = StreamSupport.stream(resources.spliterator(), parallel).map(String::valueOf)
+            .map(mapperImpl::mapFileName).filter(Objects::nonNull).flatMap(Stream::of).map(this::mapElement);
+
+        // Currently, we deal with only two path formats: Unix and Windows
+        // And Unix is everything that is not Windows
+        // (with the exception for NetWare and OS/2 below)
+
+        // for NetWare and OS/2, piggy-back on Windows, since here and
+        // in the apply code, the same assumptions can be made as with
+        // windows - that \\ is an OK separator, and do comparisons
+        // case-insensitive.
+        final String fromDirSep = onWindows ? "\\" : "/";
+        if (fromDirSep.equals(dirSep)) {
+            return result;
+        }
+        return result.map(s -> s.replace(fromDirSep, dirSep));
+    }
+
     /**
      * Apply the configured map to a path element. The map is used to convert
      * between Windows drive letters and Unix paths. If no map is configured,
@@ -418,28 +481,8 @@
      * @return String Updated element.
      */
     private String mapElement(String elem) {
-
-        int size = prefixMap.size();
-
-        if (size != 0) {
-
-            // Iterate over the map entries and apply each one.
-            // Stop when one of the entries actually changes the element.
-
-            for (int i = 0; i < size; i++) {
-                MapEntry entry = (MapEntry) prefixMap.elementAt(i);
-                String newElem = entry.apply(elem);
-
-                // Note I'm using "!=" to see if we got a new object back from
-                // the apply method.
-
-                if (newElem != elem) {
-                    elem = newElem;
-                    break; // We applied one, so we're done
-                }
-            }
-        }
-        return elem;
+        final Predicate<Object> changed = o -> o != elem;
+        return prefixMap.stream().map(e -> e.apply(elem)).filter(changed).findFirst().orElse(elem);
     }
 
     /**
@@ -472,10 +515,12 @@
      * @throws BuildException if something is not set up properly.
      */
     private void validateSetup() throws BuildException {
-
         if (path == null) {
             throw new BuildException("You must specify a path to convert");
         }
+        if (property != null && dest != null) {
+            throw new BuildException("@property and @dest are mutually exclusive");
+        }
         // Determine the separator strings.  The dirsep and pathsep attributes
         // override the targetOS settings.
         String dsep = File.separator;
@@ -503,9 +548,8 @@
      * @return BuildException.
      */
     private BuildException noChildrenAllowed() {
-        return new BuildException("You must not specify nested "
-             + "elements when using the refid attribute.");
+        return new BuildException(
+            "You must not specify nested elements when using the refid attribute.");
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java b/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java
index fe57704..635b93d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -56,6 +56,7 @@
      * Add a nested task to predefine attributes and elements on.
      * @param nestedTask  Nested task/type to extend.
      */
+    @Override
     public void addTask(Task nestedTask) {
         if (this.nestedTask != null) {
             throw new BuildException("Only one nested element allowed");
@@ -71,6 +72,7 @@
     /**
      * Make a new definition.
      */
+    @Override
     public void execute() {
         if (nestedTask == null) {
             throw new BuildException("Missing nested element");
@@ -89,7 +91,7 @@
         AntTypeDefinition def = helper.getDefinition(componentName);
         if (def == null) {
             throw new BuildException(
-                "Unable to find typedef " + componentName);
+                "Unable to find typedef %s", componentName);
         }
         PreSetDefinition newDef = new PreSetDefinition(def, nestedTask);
 
@@ -129,7 +131,8 @@
          *
          * @param clazz a <code>Class</code> value.
          */
-        public void setClass(Class clazz) {
+        @Override
+        public void setClass(Class<?> clazz) {
             throw new BuildException("Not supported");
         }
 
@@ -138,6 +141,7 @@
          *
          * @param className a <code>String</code> value.
          */
+        @Override
         public void setClassName(String className) {
             throw new BuildException("Not supported");
         }
@@ -146,6 +150,7 @@
          * Get the classname of the definition.
          * @return the name of the class of this definition.
          */
+        @Override
         public String getClassName() {
             return parent.getClassName();
         }
@@ -155,7 +160,8 @@
          * NOT Supported
          * @param adapterClass the adapterClass.
          */
-        public void setAdapterClass(Class adapterClass) {
+        @Override
+        public void setAdapterClass(Class<?> adapterClass) {
             throw new BuildException("Not supported");
         }
 
@@ -164,7 +170,8 @@
          * NOT SUPPORTED
          * @param adaptToClass the assignable class.
          */
-        public void setAdaptToClass(Class adaptToClass) {
+        @Override
+        public void setAdaptToClass(Class<?> adaptToClass) {
             throw new BuildException("Not supported");
         }
 
@@ -174,6 +181,7 @@
          * NOT SUPPORTED
          * @param classLoader the classLoader.
          */
+        @Override
         public void setClassLoader(ClassLoader classLoader) {
             throw new BuildException("Not supported");
         }
@@ -182,6 +190,7 @@
          * Get the classloader for this definition.
          * @return the classloader for this definition.
          */
+        @Override
         public ClassLoader getClassLoader() {
             return parent.getClassLoader();
         }
@@ -191,7 +200,8 @@
          * @param project the current project.
          * @return the exposed class.
          */
-        public Class getExposedClass(Project project) {
+        @Override
+        public Class<?> getExposedClass(Project project) {
             return parent.getExposedClass(project);
         }
 
@@ -200,7 +210,8 @@
          * @param project the current project.
          * @return the type of the definition.
          */
-        public Class getTypeClass(Project project) {
+        @Override
+        public Class<?> getTypeClass(Project project) {
             return parent.getTypeClass(project);
         }
 
@@ -209,6 +220,7 @@
          * Check if the attributes are correct.
          * @param project the current project.
          */
+        @Override
         public void checkClass(Project project) {
             parent.checkClass(project);
         }
@@ -240,6 +252,7 @@
          * @param project the current project.
          * @return this object.
          */
+        @Override
         public Object create(Project project) {
             return this;
         }
@@ -251,6 +264,7 @@
          * @param project the current project.
          * @return true if the definitions are the same.
          */
+        @Override
         public boolean sameDefinition(AntTypeDefinition other, Project project) {
             return (other != null && other.getClass() == getClass() && parent != null
                 && parent.sameDefinition(((PreSetDefinition) other).parent, project)
@@ -264,6 +278,7 @@
          * @param project the current project.
          * @return true if the definitions are similar.
          */
+        @Override
         public boolean similarDefinition(
             AntTypeDefinition other, Project project) {
             return (other != null && other.getClass().getName().equals(
diff --git a/src/main/org/apache/tools/ant/taskdefs/ProcessDestroyer.java b/src/main/org/apache/tools/ant/taskdefs/ProcessDestroyer.java
index bc3ff49..fd46e3c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ProcessDestroyer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ProcessDestroyer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.Set;
 
 /**
  * Destroys all registered <code>Process</code>es when the VM exits.
@@ -30,7 +30,8 @@
  */
 class ProcessDestroyer implements Runnable {
     private static final int THREAD_DIE_TIMEOUT = 20000;
-    private HashSet processes = new HashSet();
+
+    private final Set<Process> processes = new HashSet<>();
     // methods to register and unregister shutdown hooks
     private Method addShutdownHookMethod;
     private Method removeShutdownHookMethod;
@@ -49,6 +50,7 @@
         public ProcessDestroyerImpl() {
             super("ProcessDestroyer Shutdown Hook");
         }
+        @Override
         public void run() {
             if (shouldDestroy) {
                 ProcessDestroyer.this.run();
@@ -74,12 +76,11 @@
         try {
             // check to see if the shutdown hook methods exists
             // (support pre-JDK 1.3 and Non-Sun VMs)
-            Class[] paramTypes = {Thread.class};
             addShutdownHookMethod =
-                Runtime.class.getMethod("addShutdownHook", paramTypes);
+                Runtime.class.getMethod("addShutdownHook", Thread.class);
 
             removeShutdownHookMethod =
-                Runtime.class.getMethod("removeShutdownHook", paramTypes);
+                Runtime.class.getMethod("removeShutdownHook", Thread.class);
             // wait to add shutdown hook as needed
         } catch (NoSuchMethodException e) {
             // it just won't be added as a shutdown hook... :(
@@ -95,9 +96,8 @@
     private void addShutdownHook() {
         if (addShutdownHookMethod != null && !running) {
             destroyProcessThread = new ProcessDestroyerImpl();
-            Object[] args = {destroyProcessThread};
             try {
-                addShutdownHookMethod.invoke(Runtime.getRuntime(), args);
+                addShutdownHookMethod.invoke(Runtime.getRuntime(), destroyProcessThread);
                 added = true;
             } catch (IllegalAccessException e) {
                 e.printStackTrace(); //NOSONAR
@@ -119,13 +119,9 @@
      */
     private void removeShutdownHook() {
         if (removeShutdownHookMethod != null && added && !running) {
-            Object[] args = {destroyProcessThread};
             try {
-                Boolean removed =
-                    (Boolean) removeShutdownHookMethod.invoke(
-                        Runtime.getRuntime(),
-                        args);
-                if (!removed.booleanValue()) {
+                if (!Boolean.TRUE.equals(removeShutdownHookMethod
+                    .invoke(Runtime.getRuntime(), destroyProcessThread))) {
                     System.err.println("Could not remove shutdown hook");
                 }
             } catch (IllegalAccessException e) {
@@ -141,7 +137,7 @@
             }
             // start the hook thread, a unstarted thread may not be
             // eligible for garbage collection
-            // Cf.: http://developer.java.sun.com/developer/bugParade/bugs/4533087.html
+            // Cf.: https://bugs.openjdk.java.net/browse/JDK-4533087
             destroyProcessThread.setShouldDestroy(false);
             if (!destroyProcessThread.getThreadGroup().isDestroyed()) {
                 // start() would throw IllegalThreadStateException from
@@ -180,7 +176,7 @@
     public boolean add(Process process) {
         synchronized (processes) {
             // if this list is empty, register the shutdown hook
-            if (processes.size() == 0) {
+            if (processes.isEmpty()) {
                 addShutdownHook();
             }
             return processes.add(process);
@@ -198,7 +194,7 @@
     public boolean remove(Process process) {
         synchronized (processes) {
             boolean processRemoved = processes.remove(process);
-            if (processRemoved && processes.size() == 0) {
+            if (processRemoved && processes.isEmpty()) {
                 removeShutdownHook();
             }
             return processRemoved;
@@ -208,13 +204,11 @@
     /**
      * Invoked by the VM when it is exiting.
      */
+    @Override
     public void run() {
         synchronized (processes) {
             running = true;
-            Iterator e = processes.iterator();
-            while (e.hasNext()) {
-                ((Process) e.next()).destroy();
-            }
+            processes.forEach(Process::destroy);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ProjectHelperTask.java b/src/main/org/apache/tools/ant/taskdefs/ProjectHelperTask.java
index 8f348a7..7ee0404 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ProjectHelperTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ProjectHelperTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 import org.apache.tools.ant.BuildException;
@@ -33,7 +32,7 @@
  */
 public class ProjectHelperTask extends Task {
 
-    private List projectHelpers = new ArrayList();
+    private List<ProjectHelper> projectHelpers = new ArrayList<>();
 
     public synchronized void addConfigured(ProjectHelper projectHelper) {
         this.projectHelpers.add(projectHelper);
@@ -41,10 +40,7 @@
 
     @Override
     public void execute() throws BuildException {
-        ProjectHelperRepository repo = ProjectHelperRepository.getInstance();
-        for (Iterator it = projectHelpers.iterator(); it.hasNext();) {
-            ProjectHelper helper = (ProjectHelper) it.next();
-            repo.registerProjectHelper(helper.getClass());
-        }
+        projectHelpers.stream().map(ProjectHelper::getClass).forEach(
+            ProjectHelperRepository.getInstance()::registerProjectHelper);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Property.java b/src/main/org/apache/tools/ant/taskdefs/Property.java
index a6b51a2..cd930db 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Property.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Property.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,11 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
 
@@ -225,9 +224,8 @@
                 msg = currentValue + msg;
             }
             internalSetValue(msg);
-        } else if (msg.trim().length() > 0) {
-            throw new BuildException("can't combine nested text with value"
-                                     + " attribute");
+        } else if (!msg.trim().isEmpty()) {
+            throw new BuildException("can't combine nested text with value attribute");
         }
     }
 
@@ -415,7 +413,7 @@
      * @param prefix prefix
      *
      * @ant.attribute group="noname"
-     * @since Ant 1.9.12
+     * @since Ant 1.10.4
      */
     public void setRuntime(String prefix) {
         this.runtime = prefix;
@@ -424,7 +422,7 @@
     /**
      * Get the runtime attribute.
      * @return the runtime attribute
-     * @since Ant 1.9.12
+     * @since Ant 1.10.4
      */
     public String getRuntime() {
         return runtime;
@@ -507,27 +505,31 @@
 
         if (name != null) {
             if (untypedValue == null && ref == null) {
-                throw new BuildException("You must specify value, location or "
-                                         + "refid with the name attribute",
-                                         getLocation());
+                throw new BuildException(
+                    "You must specify value, location or refid with the name attribute",
+                    getLocation());
             }
         } else {
-            if (url == null && file == null && resource == null && env == null && runtime == null) {
-                throw new BuildException("You must specify url, file, resource, "
-                                         + "environment or runtime when not using the "
-                                         + "name attribute", getLocation());
+            if (url == null && file == null && resource == null
+                && env == null && runtime == null) {
+                throw new BuildException(
+                    "You must specify url, file, resource, environment or runtime when not using the name attribute",
+                    getLocation());
             }
         }
 
         if (url == null && file == null && resource == null && prefix != null) {
-            throw new BuildException("Prefix is only valid when loading from "
-                                     + "a url, file or resource", getLocation());
+            throw new BuildException(
+                "Prefix is only valid when loading from a url, file or resource",
+                getLocation());
         }
 
         if (name != null && untypedValue != null) {
             if (relative) {
                 try {
-                    File from = untypedValue instanceof File ? (File)untypedValue : new File(untypedValue.toString());
+                    File from =
+                        untypedValue instanceof File ? (File) untypedValue
+                            : new File(untypedValue.toString());
                     File to = basedir != null ? basedir : getProject().getBaseDir();
                     String relPath = FileUtils.getRelativePath(to, from);
                     relPath = relPath.replace('/', File.separatorChar);
@@ -560,7 +562,7 @@
             loadRuntime(runtime);
         }
 
-        if ((name != null) && (ref != null)) {
+        if (name != null && ref != null) {
             try {
                 addProperty(name,
                             ref.getReferencedObject(getProject()).toString());
@@ -584,13 +586,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) {
@@ -604,7 +601,7 @@
      * definition.
      * @param props The property object to load into
      * @param is    The input stream from where to load
-     * @param isXml <tt>true</tt> if we should try to load from xml
+     * @param isXml <code>true</code> if we should try to load from xml
      * @throws IOException if something goes wrong
      * @since 1.8.0
      * @see "http://java.sun.com/dtd/properties.dtd"
@@ -631,12 +628,8 @@
         log("Loading " + file.getAbsolutePath(), Project.MSG_VERBOSE);
         try {
             if (file.exists()) {
-                FileInputStream  fis = null;
-                try {
-                    fis = new FileInputStream(file);
+                try (InputStream fis = Files.newInputStream(file.toPath())) {
                     loadProperties(props, fis, file.getName().endsWith(".xml"));
-                } finally {
-                    FileUtils.close(fis);
                 }
                 addProperties(props);
             } else {
@@ -655,34 +648,20 @@
     protected void loadResource(String name) {
         Properties props = new Properties();
         log("Resource Loading " + name, Project.MSG_VERBOSE);
-        InputStream is = null;
-        ClassLoader cL = null;
-        boolean cleanup = false;
-        try {
-            if (classpath != null) {
-                cleanup = true;
-                cL = getProject().createClassLoader(classpath);
+        ClassLoader cL = (classpath == null) ? this.getClass().getClassLoader()
+                : getProject().createClassLoader(classpath);
+        try (InputStream is = (cL == null) ? ClassLoader.getSystemResourceAsStream(name)
+                : cL.getResourceAsStream(name)) {
+            if (is == null) {
+                log("Unable to find resource " + name, Project.MSG_WARN);
             } else {
-                cL = this.getClass().getClassLoader();
-            }
-
-            if (cL == null) {
-                is = ClassLoader.getSystemResourceAsStream(name);
-            } else {
-                is = cL.getResourceAsStream(name);
-            }
-
-            if (is != null) {
                 loadProperties(props, is, name.endsWith(".xml"));
                 addProperties(props);
-            } else {
-                log("Unable to find resource " + name, Project.MSG_WARN);
             }
         } catch (IOException ex) {
             throw new BuildException(ex, getLocation());
         } finally {
-            FileUtils.close(is);
-            if (cleanup && cL != null) {
+            if (classpath != null && cL != null) {
                 ((AntClassLoader) cL).cleanup();
             }
         }
@@ -698,9 +677,8 @@
             prefix += ".";
         }
         log("Loading Environment " + prefix, Project.MSG_VERBOSE);
-        Map osEnv = Execute.getEnvironmentVariables();
-        for (Iterator e = osEnv.entrySet().iterator(); e.hasNext();) {
-            Map.Entry entry = (Map.Entry) e.next();
+        Map<String, String> osEnv = Execute.getEnvironmentVariables();
+        for (Map.Entry<String, String> entry : osEnv.entrySet()) {
             props.put(prefix + entry.getKey(), entry.getValue());
         }
         addProperties(props);
@@ -709,7 +687,7 @@
     /**
      * load the runtime values
      * @param prefix prefix to place before them
-     * @since 1.9.12
+     * @since 1.10.4
      */
     protected void loadRuntime(String prefix) {
         Properties props = new Properties();
@@ -731,18 +709,17 @@
      * @param props the properties to iterate over
      */
     protected void addProperties(Properties props) {
-        HashMap m = new HashMap(props);
-        resolveAllProperties(m);
-        for (Iterator it = m.keySet().iterator(); it.hasNext();) {
-            Object k = it.next();
+        Map<String, Object> m = new HashMap<>();
+        props.forEach((k, v) -> {
             if (k instanceof String) {
-                String propertyName = (String) k;
-                if (prefix != null) {
-                    propertyName = prefix + propertyName;
-                }
-                addProperty(propertyName, m.get(k));
+                m.put((String) k, v);
             }
-        }
+        });
+        resolveAllProperties(m);
+        m.forEach((k, v) -> {
+            String propertyName = prefix == null ? k : prefix + k;
+            addProperty(propertyName, v);
+        });
     }
 
     /**
@@ -777,7 +754,7 @@
      * resolve properties inside a properties hashtable
      * @param props properties object to resolve
      */
-    private void resolveAllProperties(Map props) throws BuildException {
+    private void resolveAllProperties(Map<String, Object> props) throws BuildException {
         PropertyHelper propertyHelper
             = PropertyHelper.getPropertyHelper(getProject());
         new ResolvePropertyMap(
diff --git a/src/main/org/apache/tools/ant/taskdefs/PropertyHelperTask.java b/src/main/org/apache/tools/ant/taskdefs/PropertyHelperTask.java
index 5e8867a..27bf715 100644
--- a/src/main/org/apache/tools/ant/taskdefs/PropertyHelperTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/PropertyHelperTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 import org.apache.tools.ant.BuildException;
@@ -69,7 +68,7 @@
     }
 
     private PropertyHelper propertyHelper;
-    private List delegates;
+    private List<Object> delegates;
 
     /**
      * Add a new PropertyHelper to be set on the Project.
@@ -104,13 +103,14 @@
      * Execute the task.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
         if (getProject() == null) {
             throw new BuildException("Project instance not set");
         }
         if (propertyHelper == null && delegates == null) {
-            throw new BuildException("Either a new PropertyHelper"
-                    + " or one or more PropertyHelper delegates are required");
+            throw new BuildException(
+                "Either a new PropertyHelper or one or more PropertyHelper delegates are required");
         }
         PropertyHelper ph = propertyHelper;
         if (ph == null) {
@@ -120,8 +120,7 @@
         }
         synchronized (ph) {
             if (delegates != null) {
-                for (Iterator iter = delegates.iterator(); iter.hasNext();) {
-                    Object o = iter.next();
+                for (Object o : delegates) {
                     PropertyHelper.Delegate delegate = o instanceof DelegateElement
                             ? ((DelegateElement) o).resolve() : (PropertyHelper.Delegate) o;
                     log("Adding PropertyHelper delegate " + delegate, Project.MSG_DEBUG);
@@ -136,9 +135,9 @@
         }
     }
 
-    private synchronized List getAddDelegateList() {
+    private synchronized List<Object> getAddDelegateList() {
         if (delegates == null) {
-            delegates = new ArrayList();
+            delegates = new ArrayList<>();
         }
         return delegates;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java
index e7d24c7..0a856cb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/Recorder.java b/src/main/org/apache/tools/ant/taskdefs/Recorder.java
index 2640e90..05beb8e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Recorder.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Recorder.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -67,8 +67,7 @@
     /** Strip task banners if true.  */
     private boolean emacsMode = false;
     /** The list of recorder entries. */
-    private static Hashtable<String, RecorderEntry> recorderEntries
-            = new Hashtable<String, RecorderEntry>();
+    private static Map<String, RecorderEntry> recorderEntries = new Hashtable<>();
 
     //////////////////////////////////////////////////////////////////////
     // CONSTRUCTORS / INITIALIZERS
@@ -158,7 +157,7 @@
         recorder.setMessageOutputLevel(loglevel);
         recorder.setEmacsMode(emacsMode);
         if (start != null) {
-            if (start.booleanValue()) {
+            if (start) {
                 recorder.reopenFile();
                 recorder.setRecordState(start);
             } else {
@@ -215,7 +214,7 @@
             if (append == null) {
                 entry.openFile(false);
             } else {
-                entry.openFile(append.booleanValue());
+                entry.openFile(append);
             }
             entry.setProject(proj);
             recorderEntries.put(name, entry);
@@ -306,16 +305,8 @@
      *
      * @since Ant 1.7
      */
-    @SuppressWarnings("unchecked")
     private void cleanup() {
-        Hashtable<String, RecorderEntry> entries
-                = (Hashtable<String, RecorderEntry>) recorderEntries.clone();
-        for (Map.Entry<String, RecorderEntry> entry : entries.entrySet()) {
-            RecorderEntry re = entry.getValue();
-            if (re.getProject() == getProject()) {
-                recorderEntries.remove(entry.getKey());
-            }
-        }
+        recorderEntries.entrySet().removeIf(e -> e.getValue().getProject() == getProject());
         getProject().removeBuildListener(this);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java b/src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java
index adbb265..ee6f363 100644
--- a/src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java
+++ b/src/main/org/apache/tools/ant/taskdefs/RecorderEntry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,9 +17,9 @@
  */
 package org.apache.tools.ant.taskdefs;
 
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.nio.file.Paths;
 
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildException;
@@ -27,7 +27,7 @@
 import org.apache.tools.ant.DefaultLogger;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.SubBuildListener;
-import org.apache.tools.ant.util.StringUtils;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * This is a class that represents a recorder. This is the listener to the
@@ -84,7 +84,7 @@
     public void setRecordState(Boolean state) {
         if (state != null) {
             flush();
-            record = state.booleanValue();
+            record = state;
         }
     }
 
@@ -107,10 +107,9 @@
             Throwable error = event.getException();
 
             if (error == null) {
-                out.println(StringUtils.LINE_SEP + "BUILD SUCCESSFUL");
+                out.printf("%nBUILD SUCCESSFUL%n");
             } else {
-                out.println(StringUtils.LINE_SEP + "BUILD FAILED"
-                            + StringUtils.LINE_SEP);
+                out.printf("%nBUILD FAILED%n%n");
                 error.printStackTrace(out); //NOSONAR
             }
         }
@@ -148,8 +147,7 @@
      */
     public void targetStarted(BuildEvent event) {
         log(">> TARGET STARTED -- " + event.getTarget(), Project.MSG_DEBUG);
-        log(StringUtils.LINE_SEP + event.getTarget().getName() + ":",
-            Project.MSG_INFO);
+        log(String.format("%n%s:", event.getTarget().getName()), Project.MSG_INFO);
         targetStartTime = System.currentTimeMillis();
     }
 
@@ -190,7 +188,7 @@
     public void messageLogged(BuildEvent event) {
         log("--- MESSAGE LOGGED", Project.MSG_DEBUG);
 
-        StringBuffer buf = new StringBuffer();
+        final StringBuilder buf = new StringBuilder();
 
         if (event.getTask() != null) {
             String name = event.getTask().getTaskName();
@@ -274,12 +272,12 @@
 
 
         if (minutes > 0) {
-            return Long.toString(minutes) + " minute"
+            return minutes + " minute"
                  + (minutes == 1 ? " " : "s ")
-                 + Long.toString(seconds % 60) + " second"
+                 + seconds % 60 + " second"
                  + (seconds % 60 == 1 ? "" : "s");
         } else {
-            return Long.toString(seconds) + " second"
+            return seconds + " second"
                  + (seconds % 60 == 1 ? "" : "s");
         }
         // CheckStyle:MagicNumber ON
@@ -357,7 +355,7 @@
     private void openFileImpl(boolean append) throws BuildException {
         if (out == null) {
             try {
-                out = new PrintStream(new FileOutputStream(filename, append));
+                out = new PrintStream(FileUtils.newOutputStream(Paths.get(filename), append));
             } catch (IOException ioe) {
                 throw new BuildException("Problems opening file using a "
                                          + "recorder entry", ioe);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Redirector.java b/src/main/org/apache/tools/ant/taskdefs/Redirector.java
index 9871d16..2ca7bd0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Redirector.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Redirector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,6 +31,7 @@
 import java.io.StringReader;
 import java.util.Arrays;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -44,9 +45,9 @@
 import org.apache.tools.ant.util.LazyFileOutputStream;
 import org.apache.tools.ant.util.LeadPipeInputStream;
 import org.apache.tools.ant.util.LineOrientedOutputStreamRedirector;
+import org.apache.tools.ant.util.NullOutputStream;
 import org.apache.tools.ant.util.OutputStreamFunneler;
 import org.apache.tools.ant.util.ReaderInputStream;
-import org.apache.tools.ant.util.StringUtils;
 import org.apache.tools.ant.util.TeeOutputStream;
 
 /**
@@ -197,6 +198,11 @@
     /** Is the output binary or can we safely split it into lines? */
     private boolean outputIsBinary = false;
 
+    /** Flag which indicates if error and output files are to be discarded. */
+    private boolean discardOut = false;
+
+    private boolean discardErr = false;
+
     /**
      * Create a redirector instance for the given task
      *
@@ -443,6 +449,40 @@
     }
 
     /**
+     * Whether output should be discarded.
+     *
+     * <p>Defaults to false.</p>
+     *
+     * @param discard
+     *            if true output streams are discarded.
+     *
+     * @since Ant 1.10.10
+     * @see #setDiscardError
+     */
+    public void setDiscardOutput(final boolean discard) {
+        synchronized (outMutex) {
+            discardOut = discard;
+        }
+    }
+
+    /**
+     * Whether error output should be discarded.
+     *
+     * <p>Defaults to false.</p>
+     *
+     * @param discard
+     *            if true error streams are discarded.
+     *
+     * @since Ant 1.10.10
+     * @see #setDiscardOutput
+     */
+    public void setDiscardError(final boolean discard) {
+        synchronized (errMutex) {
+            discardErr = discard;
+        }
+    }
+
+    /**
      * If true, (error and non-error) output will be "teed", redirected as
      * specified while being sent to Ant's logging mechanism as if no
      * redirection had taken place. Defaults to false.
@@ -549,24 +589,12 @@
      *            contains the property value.
      * @param propertyName
      *            the property name.
-     *
-     * @exception IOException
-     *                if the value cannot be read form the stream.
      */
     private void setPropertyFromBAOS(final ByteArrayOutputStream baos,
-            final String propertyName) throws IOException {
-
-        final BufferedReader in = new BufferedReader(new StringReader(Execute
-                .toString(baos)));
-        String line = null;
-        final StringBuffer val = new StringBuffer();
-        while ((line = in.readLine()) != null) {
-            if (val.length() != 0) {
-                val.append(StringUtils.LINE_SEP);
-            }
-            val.append(line);
-        }
-        managingTask.getProject().setNewProperty(propertyName, val.toString());
+                                     final String propertyName) {
+        final BufferedReader in = new BufferedReader(new StringReader(Execute.toString(baos)));
+        managingTask.getProject().setNewProperty(propertyName,
+                in.lines().collect(Collectors.joining(System.lineSeparator())));
     }
 
     /**
@@ -585,7 +613,7 @@
             }
 
             if ((outputFilterChains != null && outputFilterChains.size() > 0)
-                    || !(outputEncoding.equalsIgnoreCase(inputEncoding))) {
+                    || !outputEncoding.equalsIgnoreCase(inputEncoding)) {
                 try {
                     final LeadPipeInputStream snk = new LeadPipeInputStream();
                     snk.setManagingComponent(managingTask);
@@ -627,7 +655,7 @@
             }
 
             if ((errorFilterChains != null && errorFilterChains.size() > 0)
-                    || !(errorEncoding.equalsIgnoreCase(inputEncoding))) {
+                    || !errorEncoding.equalsIgnoreCase(inputEncoding)) {
                 try {
                     final LeadPipeInputStream snk = new LeadPipeInputStream();
                     snk.setManagingComponent(managingTask);
@@ -674,10 +702,9 @@
                 } catch (final IOException eyeOhEx) {
                     throw new BuildException(eyeOhEx);
                 }
-                ((ConcatFileInputStream) inputStream)
-                        .setManagingComponent(managingTask);
+                ((ConcatFileInputStream) inputStream).setManagingComponent(managingTask);
             } else if (inputString != null) {
-                final StringBuffer buf = new StringBuffer("Using input ");
+                final StringBuilder buf = new StringBuilder("Using input ");
                 if (logInputString) {
                     buf.append('"').append(inputString).append('"');
                 } else {
@@ -707,10 +734,19 @@
 
     /** outStreams */
     private void outStreams() {
-        if (out != null && out.length > 0) {
-            final String logHead = new StringBuffer("Output ").append(
-                    ((appendOut) ? "appended" : "redirected")).append(" to ")
-                    .toString();
+        final boolean haveOutputFiles = out != null && out.length > 0;
+        if (discardOut) {
+            if (haveOutputFiles || outputProperty != null) {
+                throw new BuildException("Cant discard output when output or outputProperty"
+                        + " are set");
+            }
+            managingTask.log("Discarding output", Project.MSG_VERBOSE);
+            outputStream = NullOutputStream.INSTANCE;
+            return;
+        }
+        if (haveOutputFiles) {
+            final String logHead = "Output "
+                    + ((appendOut) ? "appended" : "redirected") + " to ";
             outputStream = foldFiles(out, logHead, Project.MSG_VERBOSE,
                     appendOut, createEmptyFilesOut);
         }
@@ -730,10 +766,19 @@
     }
 
     private void errorStreams() {
-        if (error != null && error.length > 0) {
-            final String logHead = new StringBuffer("Error ").append(
-                    ((appendErr) ? "appended" : "redirected")).append(" to ")
-                    .toString();
+        final boolean haveErrorFiles = error != null && error.length > 0;
+        if (discardErr) {
+            if (haveErrorFiles || errorProperty != null || logError) {
+                throw new BuildException("Cant discard error output when error, errorProperty"
+                        + " or logError are set");
+            }
+            managingTask.log("Discarding error output", Project.MSG_VERBOSE);
+            errorStream = NullOutputStream.INSTANCE;
+            return;
+        }
+        if (haveErrorFiles) {
+            final String logHead = "Error "
+                    + ((appendErr) ? "appended" : "redirected") + " to ";
             errorStream = foldFiles(error, logHead, Project.MSG_VERBOSE,
                     appendErr, createEmptyFilesErr);
         } else if (!(logError || outputStream == null) && errorProperty == null) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/Rename.java b/src/main/org/apache/tools/ant/taskdefs/Rename.java
index cce74e2..b32fe43 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Rename.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Rename.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/Replace.java b/src/main/org/apache/tools/ant/taskdefs/Replace.java
index 128933f..66cdef4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Replace.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Replace.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,8 +21,6 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -30,8 +28,8 @@
 import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.io.Writer;
+import java.nio.file.Files;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
@@ -46,7 +44,7 @@
 import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.types.resources.Union;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * Replaces all occurrences of one or more string tokens with given
@@ -70,7 +68,7 @@
     private Resource propertyResource = null;
     private Resource replaceFilterResource = null;
     private Properties properties = null;
-    private ArrayList<Replacefilter> replacefilters = new ArrayList<Replacefilter>();
+    private List<Replacefilter> replacefilters = new ArrayList<>();
 
     private File dir = null;
 
@@ -146,39 +144,34 @@
         public void validate() throws BuildException {
             //Validate mandatory attributes
             if (token == null) {
-                String message = "token is a mandatory for replacefilter.";
-                throw new BuildException(message);
+                throw new BuildException(
+                    "token is a mandatory for replacefilter.");
             }
 
-            if ("".equals(token.getText())) {
-                String message = "The token must not be an empty "
-                    + "string.";
-                throw new BuildException(message);
+            if (token.getText().isEmpty()) {
+                throw new BuildException(
+                    "The token must not be an empty string.");
             }
 
             //value and property are mutually exclusive attributes
-            if ((value != null) && (property != null)) {
-                String message = "Either value or property "
-                    + "can be specified, but a replacefilter "
-                    + "element cannot have both.";
-                throw new BuildException(message);
+            if (value != null && property != null) {
+                throw new BuildException(
+                    "Either value or property can be specified, but a replacefilter element cannot have both.");
             }
 
-            if ((property != null)) {
+            if (property != null) {
                 //the property attribute must have access to a property file
                 if (propertyResource == null) {
-                    String message = "The replacefilter's property attribute "
-                        + "can only be used with the replacetask's "
-                        + "propertyFile/Resource attribute.";
-                    throw new BuildException(message);
+                    throw new BuildException(
+                        "The replacefilter's property attribute can only be used with the replacetask's propertyFile/Resource attribute.");
                 }
 
                 //Make sure property exists in property file
                 if (properties == null
                     || properties.getProperty(property) == null) {
-                    String message = "property \"" + property
-                        + "\" was not found in " + propertyResource.getName();
-                    throw new BuildException(message);
+                    throw new BuildException(
+                        "property \"%s\" was not found in %s", property,
+                        propertyResource.getName());
                 }
             }
 
@@ -192,14 +185,15 @@
         public String getReplaceValue() {
             if (property != null) {
                 return properties.getProperty(property);
-            } else if (value != null) {
-                return value.getText();
-            } else if (Replace.this.value != null) {
-                return Replace.this.value.getText();
-            } else {
-                //Default is empty string
-                return "";
             }
+            if (value != null) {
+                return value.getText();
+            }
+            if (Replace.this.value != null) {
+                return Replace.this.value.getText();
+            }
+            //Default is empty string
+            return "";
         }
 
         /**
@@ -291,7 +285,7 @@
          * The filter expects from the component providing the input that data
          * is only added by that component to the end of this StringBuffer.
          * This StringBuffer will be modified by this filter, and expects that
-         * another component will only added to this StringBuffer.
+         * another component will only append to this StringBuffer.
          * @param input The input for this filter.
          */
         void setInputBuffer(StringBuffer input) {
@@ -310,7 +304,7 @@
             String t = getToken();
             if (inputBuffer.length() > t.length()) {
                 int pos = replace();
-                pos = Math.max((inputBuffer.length() - t.length()), pos);
+                pos = Math.max(inputBuffer.length() - t.length(), pos);
                 outputBuffer.append(inputBuffer.substring(0, pos));
                 inputBuffer.delete(0, pos);
                 return true;
@@ -355,12 +349,13 @@
      * a StringBuffer. Compatible with the Replacefilter.
      * @since 1.7
      */
-    private class FileInput /* JDK 5: implements Closeable */ {
+    private class FileInput implements AutoCloseable {
+        private static final int BUFF_SIZE = 4096;
+
         private StringBuffer outputBuffer;
         private final InputStream is;
         private Reader reader;
         private char[] buffer;
-        private static final int BUFF_SIZE = 4096;
 
         /**
          * Constructs the input component. Opens the file for reading.
@@ -370,9 +365,11 @@
         FileInput(File source) throws IOException {
             outputBuffer = new StringBuffer();
             buffer = new char[BUFF_SIZE];
-            is = new FileInputStream(source);
+            is = Files.newInputStream(source.toPath());
             try {
-                reader = new BufferedReader(encoding != null ? new InputStreamReader(is, encoding) : new InputStreamReader(is));
+                reader = new BufferedReader(
+                    encoding != null ? new InputStreamReader(is, encoding)
+                        : new InputStreamReader(is));
             } finally {
                 if (reader == null) {
                     is.close();
@@ -395,8 +392,7 @@
          * @throws IOException When the file cannot be read from.
          */
         boolean readChunk() throws IOException {
-            int bufferLength = 0;
-            bufferLength = reader.read(buffer);
+            int bufferLength = reader.read(buffer);
             if (bufferLength < 0) {
                 return false;
             }
@@ -408,6 +404,7 @@
          * Closes the file.
          * @throws IOException When the file cannot be closed.
          */
+        @Override
         public void close() throws IOException {
             is.close();
         }
@@ -419,7 +416,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;
@@ -430,9 +427,11 @@
          * @throws IOException When the file cannot be read from.
          */
         FileOutput(File out) throws IOException {
-            os = new FileOutputStream(out);
+            os = Files.newOutputStream(out.toPath());
             try {
-                writer = new BufferedWriter(encoding != null ? new OutputStreamWriter(os, encoding) : new OutputStreamWriter(os));
+                writer = new BufferedWriter(
+                    encoding != null ? new OutputStreamWriter(os, encoding)
+                        : new OutputStreamWriter(os));
             } finally {
                 if (writer == null) {
                     os.close();
@@ -478,6 +477,7 @@
          * Closes the file.
          * @throws IOException When the file cannot be closed.
          */
+        @Override
         public void close() throws IOException {
             os.close();
         }
@@ -488,9 +488,9 @@
      * Do the execution.
      * @throws BuildException if we can't build
      */
+    @Override
     public void execute() throws BuildException {
-
-        ArrayList savedFilters = (ArrayList) replacefilters.clone();
+        List<Replacefilter> savedFilters = new ArrayList<>(replacefilters);
         Properties savedProperties =
             properties == null ? null : (Properties) properties.clone();
 
@@ -498,12 +498,12 @@
             // line separators in values and tokens are "\n"
             // in order to compare with the file contents, replace them
             // as needed
-            StringBuffer val = new StringBuffer(value.getText());
+            StringBuilder val = new StringBuilder(value.getText());
             stringReplace(val, "\r\n", "\n");
-            stringReplace(val, "\n", StringUtils.LINE_SEP);
-            StringBuffer tok = new StringBuffer(token.getText());
+            stringReplace(val, "\n", System.lineSeparator());
+            StringBuilder tok = new StringBuilder(token.getText());
             stringReplace(tok, "\r\n", "\n");
-            stringReplace(tok, "\n", StringUtils.LINE_SEP);
+            stringReplace(tok, "\n", System.lineSeparator());
             Replacefilter firstFilter = createPrimaryfilter();
             firstFilter.setToken(tok.toString());
             firstFilter.setValue(val.toString());
@@ -511,14 +511,12 @@
 
         try {
             if (replaceFilterResource != null) {
-                Properties props = getProperties(replaceFilterResource);
-                Iterator e = getOrderedIterator(props);
-                while (e.hasNext()) {
-                    String tok = e.next().toString();
+                final Properties properties = getProperties(replaceFilterResource);
+                StreamUtils.iteratorAsStream(getOrderedIterator(properties)).forEach(tok -> {
                     Replacefilter replaceFilter = createReplacefilter();
                     replaceFilter.setToken(tok);
-                    replaceFilter.setValue(props.getProperty(tok));
-                }
+                    replaceFilter.setValue(properties.getProperty(tok));
+                });
             }
 
             validateAttributes();
@@ -537,19 +535,15 @@
 
             if (dir != null) {
                 DirectoryScanner ds = super.getDirectoryScanner(dir);
-                String[] srcs = ds.getIncludedFiles();
-
-                for (int i = 0; i < srcs.length; i++) {
-                    File file = new File(dir, srcs[i]);
+                for (String src : ds.getIncludedFiles()) {
+                    File file = new File(dir, src);
                     processFile(file);
                 }
             }
 
             if (resources != null) {
                 for (Resource r : resources) {
-                    FileProvider fp =
-                    r.as(FileProvider.class);
-                    processFile(fp.getFile());
+                    processFile(r.as(FileProvider.class).getFile());
                 }
             }
 
@@ -575,23 +569,24 @@
      */
     public void validateAttributes() throws BuildException {
         if (sourceFile == null && dir == null && resources == null) {
-            String message = "Either the file or the dir attribute "
-                + "or nested resources must be specified";
-            throw new BuildException(message, getLocation());
+            throw new BuildException(
+                "Either the file or the dir attribute or nested resources must be specified",
+                getLocation());
         }
         if (propertyResource != null && !propertyResource.isExists()) {
-            String message = "Property file " + propertyResource.getName()
-                + " does not exist.";
-            throw new BuildException(message, getLocation());
+            throw new BuildException("Property file "
+                + propertyResource.getName() + " does not exist.",
+                getLocation());
         }
-        if (token == null && replacefilters.size() == 0) {
-            String message = "Either token or a nested replacefilter "
-                + "must be specified";
-            throw new BuildException(message, getLocation());
+        if (token == null && replacefilters.isEmpty()) {
+            throw new BuildException(
+                "Either token or a nested replacefilter must be specified",
+                getLocation());
         }
-        if (token != null && "".equals(token.getText())) {
-            String message = "The token attribute must not be an empty string.";
-            throw new BuildException(message, getLocation());
+        if (token != null && token.getText().isEmpty()) {
+            throw new BuildException(
+                "The token attribute must not be an empty string.",
+                getLocation());
         }
     }
 
@@ -603,12 +598,7 @@
      */
     public void validateReplacefilters()
             throws BuildException {
-        final int size = replacefilters.size();
-        for (int i = 0; i < size; i++) {
-            Replacefilter element =
-                (Replacefilter) replacefilters.get(i);
-            element.validate();
-        }
+        replacefilters.forEach(Replacefilter::validate);
     }
 
     /**
@@ -632,18 +622,12 @@
         throws BuildException {
         Properties props = new Properties();
 
-        InputStream in = null;
-        try {
-            in = propertyResource.getInputStream();
+        try (InputStream in = propertyResource.getInputStream()) {
             props.load(in);
         } catch (IOException e) {
-            String message = "Property resource (" + propertyResource.getName()
-                + ") cannot be loaded.";
-            throw new BuildException(message);
-        } finally {
-            FileUtils.close(in);
+            throw new BuildException("Property resource (%s) cannot be loaded.",
+                propertyResource.getName());
         }
-
         return props;
     }
 
@@ -668,26 +652,19 @@
             File temp = FILE_UTILS.createTempFile(getProject(), "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) {
@@ -714,11 +691,7 @@
      * Flushes all filters.
      */
     private void flushFilterChain() {
-        final int size = replacefilters.size();
-        for (int i = 0; i < size; i++) {
-            Replacefilter filter = (Replacefilter) replacefilters.get(i);
-            filter.flush();
-        }
+        replacefilters.forEach(Replacefilter::flush);
     }
 
     /**
@@ -726,14 +699,7 @@
      * @return true if the filter chain produced new output.
      */
     private boolean processFilterChain() {
-        final int size = replacefilters.size();
-        for (int i = 0; i < size; i++) {
-            Replacefilter filter = (Replacefilter) replacefilters.get(i);
-            if (!filter.process()) {
-                return false;
-            }
-        }
-        return true;
+        return replacefilters.stream().allMatch(Replacefilter::process);
     }
 
     /**
@@ -756,13 +722,14 @@
      * @param filename <code>String</code>.
      */
     private void logFilterChain(String filename) {
-        final int size = replacefilters.size();
-        for (int i = 0; i < size; i++) {
-            Replacefilter filter = (Replacefilter) replacefilters.get(i);
-            log("Replacing in " + filename + ": " + filter.getToken()
-                    + " --> " + filter.getReplaceValue(), Project.MSG_VERBOSE);
-        }
+        replacefilters
+            .forEach(
+                filter -> log(
+                    "Replacing in " + filename + ": " + filter.getToken()
+                        + " --> " + filter.getReplaceValue(),
+                    Project.MSG_VERBOSE));
     }
+
     /**
      * Set the source file; required unless <code>dir</code> is set.
      * @param file source <code>File</code>.
@@ -951,7 +918,7 @@
      * @param str1 String
      * @param str2 String
      */
-    private void stringReplace(StringBuffer str, String str1, String str2) {
+    private void stringReplace(StringBuilder str, String str1, String str2) {
         int found = str.indexOf(str1);
         final int str1Length = str1.length();
         final int str2Length = str2.length();
@@ -967,18 +934,9 @@
      *
      * @param props Properties
      */
-    private Iterator<Object> getOrderedIterator(Properties props) {
-        List<Object> keys = new ArrayList<Object>(props.keySet());
-        Collections.sort(keys, new Comparator<Object>() {
-                //Override annotation is not supported as long as we want to support building Ant on Java 1.5
-                public int compare(Object key1, Object key2) {
-                    return compare(key1.toString(), key2.toString());
-                }
-
-                private int compare(String key1, String key2) {
-                    return key2.length() - key1.length();
-                }
-            });
+    private Iterator<String> getOrderedIterator(Properties props) {
+        List<String> keys = new ArrayList<>(props.stringPropertyNames());
+        keys.sort(Comparator.comparingInt(String::length).reversed());
         return keys.iterator();
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ResourceCount.java b/src/main/org/apache/tools/ant/taskdefs/ResourceCount.java
index b29b57b..d087844 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ResourceCount.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ResourceCount.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -61,8 +61,8 @@
     public void setRefid(Reference r) {
         Object o = r.getReferencedObject();
         if (!(o instanceof ResourceCollection)) {
-            throw new BuildException(r.getRefId()
-                + " doesn\'t denote a ResourceCollection");
+            throw new BuildException("%s doesn't denote a ResourceCollection",
+                r.getRefId());
         }
         add((ResourceCollection) o);
     }
@@ -70,6 +70,7 @@
     /**
      * Execute as a Task.
      */
+    @Override
     public void execute() {
         if (rc == null) {
             throw new BuildException(ONE_NESTED_MESSAGE);
@@ -86,6 +87,7 @@
      * @return true if the specified ResourceCollection satisfies the set criteria.
      * @throws BuildException if an error occurs.
      */
+    @Override
     public boolean eval() {
         if (rc == null) {
             throw new BuildException(ONE_NESTED_MESSAGE);
@@ -93,7 +95,7 @@
         if (count == null) {
             throw new BuildException(COUNT_REQUIRED);
         }
-        return when.evaluate(new Integer(rc.size()).compareTo(count));
+        return when.evaluate(Integer.valueOf(rc.size()).compareTo(count));
     }
 
     /**
@@ -101,7 +103,7 @@
      * @param c number of Resources as int.
      */
     public void setCount(int c) {
-        count = new Integer(c);
+        count = c;
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/Retry.java b/src/main/org/apache/tools/ant/taskdefs/Retry.java
index bca5c15..e1681d1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Retry.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Retry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.TaskContainer;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Retries the nested task a set number of times
@@ -48,11 +47,11 @@
      * set the task
      * @param t the task to retry.
      */
+    @Override
     public synchronized void addTask(Task t) {
         if (nestedTask != null) {
             throw new BuildException(
-                "The retry task container accepts a single nested task"
-                + " (which may be a sequential task container)");
+                "The retry task container accepts a single nested task (which may be a sequential task container)");
         }
         nestedTask = t;
     }
@@ -81,8 +80,9 @@
      * perform the work
      * @throws BuildException if there is an error.
      */
+    @Override
     public void execute() throws BuildException {
-        StringBuffer errorMessages = new StringBuffer();
+        StringBuilder errorMessages = new StringBuilder();
         for (int i = 0; i <= retryCount; i++) {
             try {
                 nestedTask.perform();
@@ -90,13 +90,9 @@
             } catch (Exception e) {
                 errorMessages.append(e.getMessage());
                 if (i >= retryCount) {
-                    StringBuffer exceptionMessage = new StringBuffer();
-                    exceptionMessage.append("Task [").append(nestedTask.getTaskName());
-                    exceptionMessage.append("] failed after [").append(retryCount);
-                    exceptionMessage.append("] attempts; giving up.").append(StringUtils.LINE_SEP);
-                    exceptionMessage.append("Error messages:").append(StringUtils.LINE_SEP);
-                    exceptionMessage.append(errorMessages);
-                    throw new BuildException(exceptionMessage.toString(), getLocation());
+                    throw new BuildException(String.format(
+                            "Task [%s] failed after [%d] attempts; giving up.%nError messages:%n%s",
+                            nestedTask.getTaskName(), retryCount, errorMessages), getLocation());
                 }
                 String msg;
                 if (retryDelay > 0) {
@@ -105,7 +101,7 @@
                     msg = "Attempt [" + i + "]: error occurred; retrying...";
                 }
                 log(msg, e, Project.MSG_INFO);
-                errorMessages.append(StringUtils.LINE_SEP);
+                errorMessages.append(System.lineSeparator());
                 if (retryDelay > 0) {
                     try {
                         Thread.sleep(retryDelay);
diff --git a/src/main/org/apache/tools/ant/taskdefs/Rmic.java b/src/main/org/apache/tools/ant/taskdefs/Rmic.java
index e20518a..ece5a94 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Rmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Rmic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.rmi.Remote;
 import java.util.Vector;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -67,16 +68,16 @@
  *
  * <p>It is possible to use different compilers. This can be selected
  * with the &quot;build.rmic&quot; property or the <code>compiler</code>
- * attribute. <a name="compilervalues">There are three choices</a>:</p>
+ * attribute. <span id="compilervalues">There are three choices</span>:</p>
  *
  * <ul>
  *   <li>sun (the standard compiler of the JDK)</li>
  *   <li>kaffe (the standard compiler of
- *       <a href="http://www.kaffe.org">Kaffe</a>)</li>
+ *       <a href="https://github.com/kaffe/kaffe">Kaffe</a>)</li>
  *   <li>weblogic</li>
  * </ul>
  *
- * <p>The <a href="http://dione.zcu.cz/~toman40/miniRMI/">miniRMI</a>
+ * <p>The miniRMI
  * project contains a compiler implementation for this task as well,
  * please consult miniRMI's documentation to learn how to use it.</p>
  *
@@ -91,6 +92,23 @@
     public static final String ERROR_RMIC_FAILED
         = "Rmic failed; see the compiler error output for details.";
 
+    /** unable to verify message */
+    public static final String ERROR_UNABLE_TO_VERIFY_CLASS = "Unable to verify class ";
+    /** could not be found message */
+    public static final String ERROR_NOT_FOUND = ". It could not be found.";
+    /** not defined message */
+    public static final String ERROR_NOT_DEFINED = ". It is not defined.";
+    /** loaded error message */
+    public static final String ERROR_LOADING_CAUSED_EXCEPTION = ". Loading caused Exception: ";
+    /** base not exists message */
+    public static final String ERROR_NO_BASE_EXISTS = "base or destdir does not exist: ";
+    /** base not a directory message */
+    public static final String ERROR_NOT_A_DIR = "base or destdir is not a directory:";
+    /** base attribute not set message */
+    public static final String ERROR_BASE_NOT_SET = "base or destdir attribute must be set!";
+
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
     private File baseDir;
     private File destDir;
     private String classname;
@@ -109,28 +127,11 @@
     private boolean includeAntRuntime = true;
     private boolean includeJavaRuntime = false;
 
-    private Vector compileList = new Vector();
+    private Vector<String> compileList = new Vector<>();
 
     private AntClassLoader loader = null;
 
     private FacadeTaskHelper facade;
-    /** unable to verify message */
-    public static final String ERROR_UNABLE_TO_VERIFY_CLASS = "Unable to verify class ";
-    /** could not be found message */
-    public static final String ERROR_NOT_FOUND = ". It could not be found.";
-    /** not defined message */
-    public static final String ERROR_NOT_DEFINED = ". It is not defined.";
-    /** loaded error message */
-    public static final String ERROR_LOADING_CAUSED_EXCEPTION = ". Loading caused Exception: ";
-    /** base not exists message */
-    public static final String ERROR_NO_BASE_EXISTS = "base or destdir does not exist: ";
-    /** base not a directory message */
-    public static final String ERROR_NOT_A_DIR = "base or destdir is not a directory:";
-    /** base attribute not set message */
-    public static final String ERROR_BASE_NOT_SET = "base or destdir attribute must be set!";
-
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
     private String executable = null;
 
     private boolean listFiles = false;
@@ -405,7 +406,7 @@
      * Gets file list to compile.
      * @return the list of files to compile.
      */
-    public Vector getFileList() {
+    public Vector<String> getFileList() {
         return compileList;
     }
 
@@ -484,7 +485,7 @@
     /**
      * @return the compile list.
      */
-    public Vector getCompileList() {
+    public Vector<String> getCompileList() {
         return compileList;
     }
 
@@ -496,7 +497,7 @@
      * @since Ant 1.5
      */
     public void setCompiler(String compiler) {
-        if (compiler.length() > 0) {
+        if (!compiler.isEmpty()) {
             facade.setImplementation(compiler);
         }
     }
@@ -612,9 +613,8 @@
             if (verify) {
                 log("Verify has been turned on.", Project.MSG_VERBOSE);
             }
-            RmicAdapter adapter =
-                nestedAdapter != null ? nestedAdapter :
-                RmicAdapterFactory.getRmic(getCompiler(), this,
+            RmicAdapter adapter = nestedAdapter != null ? nestedAdapter
+                    : RmicAdapterFactory.getRmic(getCompiler(), this,
                                            createCompilerClasspath());
 
             // now we need to populate the compiler adapter
@@ -627,8 +627,7 @@
             // specific classname is not given
             if (classname == null) {
                 DirectoryScanner ds = this.getDirectoryScanner(baseDir);
-                String[] files = ds.getIncludedFiles();
-                scanDir(baseDir, files, adapter.getMapper());
+                scanDir(baseDir, ds.getIncludedFiles(), adapter.getMapper());
             } else {
                 // otherwise perform a timestamp comparison - at least
                 String path = classname.replace('.', File.separatorChar)
@@ -651,9 +650,7 @@
                     + outputDir, Project.MSG_INFO);
 
                 if (listFiles) {
-                    for (int i = 0; i < fileCount; i++) {
-                        log(compileList.get(i).toString());
-                    }
+                    compileList.forEach(this::log);
                 }
 
                 // finally, lets execute the compiler!!
@@ -674,11 +671,8 @@
                     log("sourcebase attribute will be ignored.",
                         Project.MSG_WARN);
                 } else {
-                    for (int j = 0; j < fileCount; j++) {
-                        moveGeneratedFile(outputDir, sourceBase,
-                                          (String) compileList.elementAt(j),
-                                          adapter);
-                    }
+                    compileList.forEach(f -> moveGeneratedFile(outputDir,
+                        sourceBase, f, adapter));
                 }
             }
         } finally {
@@ -713,16 +707,14 @@
             return;
         }
 
-        for (int i = 0; i < generatedFiles.length; i++) {
-            final String generatedFile = generatedFiles[i];
+        for (String generatedFile : generatedFiles) {
             if (!generatedFile.endsWith(".class")) {
                 // don't know how to handle that - a IDL file doesn't
                 // have a corresponding Java source for example.
                 continue;
             }
-            String sourceFileName = StringUtils.removeSuffix(generatedFile,
-                                                             ".class")
-                + ".java";
+            String sourceFileName =
+                StringUtils.removeSuffix(generatedFile, ".class") + ".java";
 
             File oldFile = new File(baseDir, sourceFileName);
             if (!oldFile.exists()) {
@@ -734,17 +726,15 @@
             try {
                 if (filtering) {
                     FILE_UTILS.copyFile(oldFile, newFile,
-                                        new FilterSetCollection(getProject()
-                                                                .getGlobalFilterSet()));
+                            new FilterSetCollection(getProject().getGlobalFilterSet()));
                 } else {
                     FILE_UTILS.copyFile(oldFile, newFile);
                 }
                 oldFile.delete();
             } catch (IOException ioe) {
-                String msg = "Failed to copy " + oldFile + " to " + newFile
-                    + " due to "
-                    + ioe.getMessage();
-                throw new BuildException(msg, ioe, getLocation());
+                throw new BuildException("Failed to copy " + oldFile + " to "
+                    + newFile + " due to " + ioe.getMessage(), ioe,
+                    getLocation());
             }
         }
     }
@@ -768,11 +758,9 @@
             SourceFileScanner sfs = new SourceFileScanner(this);
             newFiles = sfs.restrict(files, baseDir, getOutputDir(), mapper);
         }
-        for (int i = 0; i < newFiles.length; i++) {
-            String name = newFiles[i].replace(File.separatorChar, '.');
-            name = name.substring(0, name.lastIndexOf(".class"));
-            compileList.addElement(name);
-        }
+        Stream.of(newFiles).map(s -> s.replace(File.separatorChar, '.'))
+            .map(s -> s.substring(0, s.lastIndexOf(".class")))
+            .forEach(compileList::add);
     }
 
     /**
@@ -782,12 +770,9 @@
      */
     public boolean isValidRmiRemote(String classname) {
         try {
-            Class testClass = loader.loadClass(classname);
+            Class<?> testClass = loader.loadClass(classname);
             // One cannot RMIC an interface for "classic" RMI (JRMP)
-            if (testClass.isInterface() && !iiop && !idl) {
-                return false;
-            }
-            return isValidRmiRemote(testClass);
+            return (!testClass.isInterface() || iiop || idl) && isValidRmiRemote(testClass);
         } catch (ClassNotFoundException e) {
             log(ERROR_UNABLE_TO_VERIFY_CLASS + classname + ERROR_NOT_FOUND,
                 Project.MSG_WARN);
@@ -810,26 +795,17 @@
      * @return the topmost interface that extends Remote, or null if there
      *         is none.
      */
-    public Class getRemoteInterface(Class testClass) {
-        if (Remote.class.isAssignableFrom(testClass)) {
-            Class [] interfaces = testClass.getInterfaces();
-            if (interfaces != null) {
-                for (int i = 0; i < interfaces.length; i++) {
-                    if (Remote.class.isAssignableFrom(interfaces[i])) {
-                        return interfaces[i];
-                    }
-                }
-            }
-        }
-        return null;
+    public Class<?> getRemoteInterface(Class<?> testClass) {
+        return Stream.of(testClass.getInterfaces())
+            .filter(Remote.class::isAssignableFrom).findFirst().orElse(null);
     }
 
     /**
      * Check to see if the class or (super)interfaces implement
      * java.rmi.Remote.
      */
-    private boolean isValidRmiRemote (Class testClass) {
-        return getRemoteInterface(testClass) != null;
+    private boolean isValidRmiRemote(Class<?> testClass) {
+        return Remote.class.isAssignableFrom(testClass);
     }
 
     /**
@@ -846,7 +822,7 @@
      * implementation.
      */
     public class ImplementationSpecificArgument extends
-                                                    org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
+        org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
         /**
          * Only pass the specified argument if the
          * chosen compiler implementation matches the
diff --git a/src/main/org/apache/tools/ant/taskdefs/SQLExec.java b/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
index 25bc68a..dc116a3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,14 +20,13 @@
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.Reader;
 import java.io.StringReader;
+import java.nio.charset.Charset;
 import java.sql.Blob;
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -36,7 +35,7 @@
 import java.sql.SQLWarning;
 import java.sql.Statement;
 import java.sql.Types;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Locale;
 import java.util.StringTokenizer;
 import java.util.Vector;
@@ -128,7 +127,7 @@
     /**
      * SQL transactions to perform
      */
-    private Vector transactions = new Vector();
+    private List<Transaction> transactions = new Vector<>();
 
     /**
      * SQL Statement delimiter
@@ -352,7 +351,7 @@
      */
     public Transaction createTransaction() {
         Transaction t = new Transaction();
-        transactions.addElement(t);
+        transactions.add(t);
         return t;
     }
 
@@ -562,8 +561,8 @@
      */
     public void setCsvQuoteCharacter(String s) {
         if (s != null && s.length() > 1) {
-            throw new BuildException("The quote character must be a single"
-                                     + " character.");
+            throw new BuildException(
+                "The quote character must be a single character.");
         }
         csvQuoteChar = s;
     }
@@ -614,17 +613,17 @@
      */
     @Override
     public void execute() throws BuildException {
-        Vector savedTransaction = (Vector) transactions.clone();
+        List<Transaction> savedTransaction = new Vector<>(transactions);
         String savedSqlCommand = sqlCommand;
 
         sqlCommand = sqlCommand.trim();
 
         try {
-            if (srcFile == null && sqlCommand.length() == 0 && resources == null) {
-                if (transactions.size() == 0) {
-                    throw new BuildException("Source file or resource collection, "
-                                             + "transactions or sql statement "
-                                             + "must be set!", getLocation());
+            if (srcFile == null && sqlCommand.isEmpty() && resources == null) {
+                if (transactions.isEmpty()) {
+                    throw new BuildException(
+                        "Source file or resource collection, transactions or sql statement must be set!",
+                        getLocation());
                 }
             }
 
@@ -661,7 +660,7 @@
                         FileProvider fp =
                             output.as(FileProvider.class);
                         if (fp != null) {
-                            os = new FileOutputStream(fp.getFile(), append);
+                            os = FileUtils.newOutputStream(fp.getFile().toPath(), append);
                         } else {
                             if (append) {
                                 Appendable a =
@@ -688,10 +687,8 @@
                     }
 
                     // Process all transactions
-                    for (Enumeration e = transactions.elements();
-                         e.hasMoreElements();) {
-
-                        ((Transaction) e.nextElement()).runTransaction(out);
+                    for (Transaction txn : transactions) {
+                        txn.runTransaction(out);
                         if (!isAutocommit()) {
                             log("Committing transaction", Project.MSG_VERBOSE);
                             getConnection().commit();
@@ -700,33 +697,19 @@
                 } finally {
                     FileUtils.close(out);
                 }
-            } catch (IOException e) {
+            } catch (IOException | SQLException e) {
                 closeQuietly();
                 setErrorProperty();
-                if (onError.equals("abort")) {
-                    throw new BuildException(e, getLocation());
-                }
-            } catch (SQLException e) {
-                closeQuietly();
-                setErrorProperty();
-                if (onError.equals("abort")) {
+                if ("abort".equals(onError)) {
                     throw new BuildException(e, getLocation());
                 }
             } 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");
@@ -746,10 +729,10 @@
     protected void runStatements(Reader reader, PrintStream out)
         throws SQLException, IOException {
         StringBuffer sql = new StringBuffer();
-        String line;
 
         BufferedReader in = new BufferedReader(reader);
 
+        String line;
         while ((line = in.readLine()) != null) {
             if (!keepformat) {
                 line = line.trim();
@@ -801,7 +784,7 @@
      */
     protected void execSQL(String sql, PrintStream out) throws SQLException {
         // Check and ignore empty statements
-        if ("".equals(sql.trim())) {
+        if (sql.trim().isEmpty()) {
             return;
         }
 
@@ -849,20 +832,14 @@
         } catch (SQLException e) {
             log("Failed to execute: " + sql, Project.MSG_ERR);
             setErrorProperty();
-            if (!onError.equals("abort")) {
+            if (!"abort".equals(onError)) {
                 log(e.toString(), Project.MSG_ERR);
             }
-            if (!onError.equals("continue")) {
+            if (!"continue".equals(onError)) {
                 throw e;
             }
         } finally {
-            if (resultSet != null) {
-                try {
-                    resultSet.close();
-                } catch (SQLException e) {
-                    //ignore
-                }
-            }
+            FileUtils.close(resultSet);
         }
     }
 
@@ -876,13 +853,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();
-            }
         }
     }
 
@@ -955,7 +927,7 @@
      * @since Ant 1.7
      */
     private void closeQuietly() {
-        if (!isAutocommit() && getConnection() != null && onError.equals("abort")) {
+        if (!isAutocommit() && getConnection() != null && "abort".equals(onError)) {
             try {
                 getConnection().rollback();
             } catch (SQLException ex) {
@@ -964,7 +936,6 @@
         }
     }
 
-
     /**
      * Caches the connection returned by the base class's getConnection method.
      *
@@ -1004,7 +975,6 @@
             statement = getConnection().createStatement();
             statement.setEscapeProcessing(escapeProcessing);
         }
-
         return statement;
     }
 
@@ -1071,18 +1041,15 @@
          */
         public void addConfigured(ResourceCollection a) {
             if (a.size() != 1) {
-                throw new BuildException("only single argument resource "
-                                         + "collections are supported.");
+                throw new BuildException(
+                    "only single argument resource collections are supported.");
             }
             setSrcResource(a.iterator().next());
         }
 
-        /**
-         *
-         */
         private void runTransaction(PrintStream out)
             throws IOException, SQLException {
-            if (tSqlCommand.length() != 0) {
+            if (!tSqlCommand.isEmpty()) {
                 log("Executing commands", Project.MSG_INFO);
                 runStatements(new StringReader(tSqlCommand), out);
             }
@@ -1090,16 +1057,11 @@
             if (tSrcResource != null) {
                 log("Executing resource: " + tSrcResource.toString(),
                     Project.MSG_INFO);
-                InputStream is = null;
-                Reader reader = null;
-                try {
-                    is = tSrcResource.getInputStream();
-                    reader = (encoding == null) ? new InputStreamReader(is)
-                        : new InputStreamReader(is, encoding);
+                Charset charset = encoding == null ? Charset.defaultCharset()
+                    : Charset.forName(encoding);
+                try (Reader reader = new InputStreamReader(
+                    tSrcResource.getInputStream(), charset)) {
                     runStatements(reader, out);
-                } finally {
-                    FileUtils.close(is);
-                    FileUtils.close(reader);
                 }
             }
         }
@@ -1115,33 +1077,31 @@
             }
             // no match
             return -1;
-        } else {
-            String d = delimiter.trim().toLowerCase(Locale.ENGLISH);
-            if (delimiterType.equals(DelimiterType.NORMAL)) {
-                // still trying to avoid wasteful copying, see
-                // StringUtils.endsWith
-                int endIndex = delimiter.length() - 1;
-                int bufferIndex = buf.length() - 1;
-                while (bufferIndex >= 0 && Character.isWhitespace(buf.charAt(bufferIndex))) {
-                    --bufferIndex;
-                }
-                if (bufferIndex < endIndex) {
+        }
+        String d = delimiter.trim().toLowerCase(Locale.ENGLISH);
+        if (DelimiterType.NORMAL.equals(delimiterType)) {
+            // still trying to avoid wasteful copying, see
+            // StringUtils.endsWith
+            int endIndex = delimiter.length() - 1;
+            int bufferIndex = buf.length() - 1;
+            while (bufferIndex >= 0 && Character.isWhitespace(buf.charAt(bufferIndex))) {
+                --bufferIndex;
+            }
+            if (bufferIndex < endIndex) {
+                return -1;
+            }
+            while (endIndex >= 0) {
+                if (buf.substring(bufferIndex, bufferIndex + 1).toLowerCase(Locale.ENGLISH)
+                        .charAt(0) != d.charAt(endIndex)) {
                     return -1;
                 }
-                while (endIndex >= 0) {
-                    if (buf.substring(bufferIndex, bufferIndex + 1).toLowerCase(Locale.ENGLISH)
-                            .charAt(0) != d.charAt(endIndex)) {
-                        return -1;
-                    }
-                    bufferIndex--;
-                    endIndex--;
-                }
-                return bufferIndex + 1;
-            } else {
-                return currentLine.trim().toLowerCase(Locale.ENGLISH).equals(d)
-                    ? buf.length() - currentLine.length() : -1;
+                bufferIndex--;
+                endIndex--;
             }
+            return bufferIndex + 1;
         }
+        return currentLine.trim().toLowerCase(Locale.ENGLISH).equals(d)
+            ? buf.length() - currentLine.length() : -1;
     }
 
     private void printWarnings(SQLWarning warning, boolean force)
diff --git a/src/main/org/apache/tools/ant/taskdefs/SendEmail.java b/src/main/org/apache/tools/ant/taskdefs/SendEmail.java
index 1db8de3..3a61c0d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SendEmail.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SendEmail.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/Sequential.java b/src/main/org/apache/tools/ant/taskdefs/Sequential.java
index f2f88a9..c5cefe1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Sequential.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Sequential.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,7 +17,7 @@
  */
 package org.apache.tools.ant.taskdefs;
 
-import java.util.Iterator;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -41,15 +41,16 @@
 public class Sequential extends Task implements TaskContainer {
 
     /** Optional Vector holding the nested tasks */
-    private Vector nestedTasks = new Vector();
+    private List<Task> nestedTasks = new Vector<>();
 
     /**
      * Add a nested task to Sequential.
      *
      * @param nestedTask  Nested task to execute Sequential
      */
+    @Override
     public void addTask(Task nestedTask) {
-        nestedTasks.addElement(nestedTask);
+        nestedTasks.add(nestedTask);
     }
 
     /**
@@ -57,15 +58,13 @@
      *
      * @throws BuildException if one of the nested tasks fails.
      */
+    @Override
     public void execute() throws BuildException {
         LocalProperties localProperties
             = LocalProperties.get(getProject());
         localProperties.enterScope();
         try {
-            for (Iterator i = nestedTasks.iterator(); i.hasNext();) {
-                Task nestedTask = (Task) i.next();
-                nestedTask.perform();
-            }
+            nestedTasks.forEach(Task::perform);
         } finally {
             localProperties.exitScope();
         }
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..3e708f4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/SetPermissions.java
@@ -0,0 +1,230 @@
+/*
+ *  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
+ *
+ *      https://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(",")) //NOSONAR
+                .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);
+    }
+
+    @Override
+    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;
+            }
+            throw new BuildException(msg, exc);
+        }
+        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", Project.MSG_DEBUG);
+        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);
+            }
+            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/SignJar.java b/src/main/org/apache/tools/ant/taskdefs/SignJar.java
index bb17174..6066d87 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SignJar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SignJar.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,14 +36,13 @@
 /**
  * Signs JAR or ZIP files with the javasign command line tool. The tool detailed
  * dependency checking: files are only signed if they are not signed. The
- * <tt>signjar</tt> attribute can point to the file to generate; if this file
+ * <code>signjar</code> attribute can point to the file to generate; if this file
  * exists then its modification date is used as a cue as to whether to resign
  * any JAR file.
  *
- * Timestamp driven signing is based on the unstable and inadequately documented
- * information in the Java1.5 docs
- * @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/time-of-signing-beta1.html">
- * beta documentation</a>
+ * Timestamp signature support is based on Java 8
+ * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/time-of-signing.html">
+ * documentation</a>
  * @ant.task category="java"
  * @since Ant 1.1
  */
@@ -53,6 +52,38 @@
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_TODIR_AND_SIGNEDJAR
+            = "'destdir' and 'signedjar' cannot both be set";
+    /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_TOO_MANY_MAPPERS = "Too many mappers";
+    /**
+     * error string for unit test verification {@value}
+     */
+    public static final String ERROR_SIGNEDJAR_AND_PATHS
+        = "You cannot specify the signed JAR when using paths or filesets";
+    /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_BAD_MAP = "Cannot map source file to anything sensible: ";
+    /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_MAPPER_WITHOUT_DEST
+        = "The destDir attribute is required if a mapper is set";
+    /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_NO_ALIAS = "alias attribute must be set";
+    /**
+     * error string for unit test verification: {@value}
+     */
+    public static final String ERROR_NO_STOREPASS = "storepass attribute must be set";
+
+    /**
      * name to a signature file
      */
     protected String sigfile;
@@ -129,36 +160,10 @@
     private String digestAlg;
 
     /**
-     * error string for unit test verification: {@value}
+     * tsa digest algorithm
      */
-    public static final String ERROR_TODIR_AND_SIGNEDJAR
-            = "'destdir' and 'signedjar' cannot both be set";
-    /**
-     * error string for unit test verification: {@value}
-     */
-    public static final String ERROR_TOO_MANY_MAPPERS = "Too many mappers";
-    /**
-     * error string for unit test verification {@value}
-     */
-    public static final String ERROR_SIGNEDJAR_AND_PATHS
-        = "You cannot specify the signed JAR when using paths or filesets";
-    /**
-     * error string for unit test verification: {@value}
-     */
-    public static final String ERROR_BAD_MAP = "Cannot map source file to anything sensible: ";
-    /**
-     * error string for unit test verification: {@value}
-     */
-    public static final String ERROR_MAPPER_WITHOUT_DEST
-        = "The destDir attribute is required if a mapper is set";
-    /**
-     * error string for unit test verification: {@value}
-     */
-    public static final String ERROR_NO_ALIAS = "alias attribute must be set";
-    /**
-     * error string for unit test verification: {@value}
-     */
-    public static final String ERROR_NO_STOREPASS = "storepass attribute must be set";
+    private String tsaDigestAlg;
+
     // CheckStyle:VisibilityModifier ON
 
     /**
@@ -369,6 +374,26 @@
     }
 
     /**
+     * TSA Digest Algorithm; optional
+     *
+     * @param digestAlg the tsa digest algorithm
+     * @since Ant 1.10.2
+     */
+    public void setTSADigestAlg(String digestAlg) {
+        this.tsaDigestAlg = digestAlg;
+    }
+
+    /**
+     * TSA Digest Algorithm; optional
+     *
+     * @return String
+     * @since Ant 1.10.2
+     */
+    public String getTSADigestAlg() {
+        return tsaDigestAlg;
+    }
+
+    /**
      * sign the jar(s)
      *
      * @throws BuildException on errors
@@ -424,14 +449,7 @@
 
             Path sources = createUnifiedSourcePath();
             //set up our mapping policy
-            FileNameMapper destMapper;
-            if (hasMapper) {
-                destMapper = mapper;
-            } else {
-                //no mapper? use the identity policy
-                destMapper = new IdentityMapper();
-            }
-
+            FileNameMapper destMapper = hasMapper ? mapper : new IdentityMapper();
 
             //at this point the paths are set up with lists of files,
             //and the mapper is ready to map from source dirs to dest files
@@ -570,6 +588,11 @@
                 addProxyFor(cmd, "http");
             }
         }
+
+        if (tsaDigestAlg != null) {
+            addValue(cmd, "-tsadigestalg");
+            addValue(cmd, tsaDigestAlg);
+        }
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/Sleep.java b/src/main/org/apache/tools/ant/taskdefs/Sleep.java
index 7f124cc..5afd0b0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Sleep.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Sleep.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -64,15 +64,12 @@
      */
     private int milliseconds = 0;
 
-
-
     /**
      * Creates new instance
      */
     public Sleep() {
     }
 
-
     /**
      * seconds to add to the sleep time
      *
@@ -82,7 +79,6 @@
         this.seconds = seconds;
     }
 
-
     /**
      * hours to add to the sleep time.
      *
@@ -92,7 +88,6 @@
         this.hours = hours;
     }
 
-
     /**
      * minutes to add to the sleep time
      *
@@ -102,7 +97,6 @@
         this.minutes = minutes;
     }
 
-
     /**
      * milliseconds to add to the sleep time
      *
@@ -112,7 +106,6 @@
         this.milliseconds = milliseconds;
     }
 
-
     /**
      * sleep for a period of time
      *
@@ -126,7 +119,6 @@
         }
     }
 
-
     /**
      * flag controlling whether to break the build on an error.
      *
@@ -136,7 +128,6 @@
         this.failOnError = failOnError;
     }
 
-
     /**
      * return time to sleep
      *
@@ -150,7 +141,6 @@
         // CheckStyle:MagicNumber ON
     }
 
-
     /**
      * verify parameters
      *
@@ -159,12 +149,10 @@
     public void validate()
         throws BuildException {
         if (getSleepTime() < 0) {
-            throw new BuildException("Negative sleep periods are not "
-                                     + "supported");
+            throw new BuildException("Negative sleep periods are not supported");
         }
     }
 
-
     /**
      * Executes this build task.
      *
@@ -182,12 +170,9 @@
         } catch (Exception e) {
             if (failOnError) {
                 throw new BuildException(e);
-            } else {
-                String text = e.toString();
-                log(text, Project.MSG_ERR);
             }
+            log(e.toString(), Project.MSG_ERR);
         }
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java b/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java
index c7afc4d..2c4aaee 100644
--- a/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java
+++ b/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,7 +58,6 @@
         this(is, os, closeWhenExhausted, false);
     }
 
-
     /**
      * Create a new StreamPumper.
      * <p><b>Note:</b> If you set useAvailable to true, you must
@@ -114,6 +113,7 @@
      *
      * Terminates as soon as the input stream is closed or an error occurs.
      */
+    @Override
     public void run() {
         synchronized (this) {
             started = true;
diff --git a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
index ac023c4..6e09032 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -72,17 +72,17 @@
     private boolean failOnError = true;
     private String output  = null;
 
-    private Vector properties = new Vector();
-    private Vector references = new Vector();
-    private Vector propertySets = new Vector();
+    private List<Property> properties = new Vector<>();
+    private List<Ant.Reference> references = new Vector<>();
+    private List<PropertySet> propertySets = new Vector<>();
 
     /** the targets to call on the new project */
-    private Vector/*<TargetElement>*/ targets = new Vector();
+    private List<TargetElement> targets = new Vector<>();
 
     /**
      * Get the default build file name to use when launching the task.
      * <p>
-     * This function may be overriden by providers of custom ProjectHelper so
+     * This function may be overridden by providers of custom ProjectHelper so
      * they can implement easily their sub launcher.
      * </p>
      *
@@ -227,7 +227,7 @@
                     log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
                 }
             } catch (RuntimeException ex) {
-                if (!(getProject().isKeepGoingMode())) {
+                if (!getProject().isKeepGoingMode()) {
                     if (verbose && subdirPath != null) {
                         log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
                     }
@@ -235,7 +235,7 @@
                 }
                 thrownException = ex;
             } catch (Throwable ex) {
-                if (!(getProject().isKeepGoingMode())) {
+                if (!getProject().isKeepGoingMode()) {
                     if (verbose && subdirPath != null) {
                         log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
                     }
@@ -297,11 +297,7 @@
         ant = createAntTask(directory);
         String antfilename = file.getAbsolutePath();
         ant.setAntfile(antfilename);
-        final int size = targets.size();
-        for (int i = 0; i < size; i++) {
-            TargetElement targetElement = (TargetElement) targets.get(i);
-            ant.addConfiguredTarget(targetElement);
-        }
+        targets.forEach(ant::addConfiguredTarget);
 
         try {
             if (verbose) {
@@ -332,13 +328,8 @@
     private boolean isHardError(Throwable t) {
         if (t instanceof BuildException) {
             return isHardError(t.getCause());
-        } else if (t instanceof OutOfMemoryError) {
-            return true;
-        } else if (t instanceof ThreadDeath) {
-            return true;
-        } else { // incl. t == null
-            return false;
         }
+        return t instanceof OutOfMemoryError || t instanceof ThreadDeath;
     }
 
     /**
@@ -393,8 +384,7 @@
      * @since Ant 1.7
      */
     public void addConfiguredTarget(TargetElement t) {
-        String name = t.getName();
-        if ("".equals(name)) {
+        if (t.getName().isEmpty()) {
             throw new BuildException("target name must not be empty");
         }
         targets.add(t);
@@ -446,7 +436,7 @@
      * @param  p the property to pass on explicitly to the sub-build.
      */
     public void addProperty(Property p) {
-        properties.addElement(p);
+        properties.add(p);
     }
 
     /**
@@ -456,7 +446,7 @@
      * @param  r the reference to pass on explicitly to the sub-build.
      */
     public void addReference(Ant.Reference r) {
-        references.addElement(r);
+        references.add(r);
     }
 
     /**
@@ -465,7 +455,7 @@
      * @param ps the propertyset
      */
     public void addPropertyset(PropertySet ps) {
-        propertySets.addElement(ps);
+        propertySets.add(ps);
     }
 
     /**
@@ -579,7 +569,7 @@
     private Ant createAntTask(File directory) {
         Ant antTask = new Ant(this);
         antTask.init();
-        if (subTarget != null && subTarget.length() > 0) {
+        if (subTarget != null && !subTarget.isEmpty()) {
             antTask.setTarget(subTarget);
         }
 
@@ -595,18 +585,14 @@
         }
 
         antTask.setInheritAll(inheritAll);
-        for (Enumeration i = properties.elements(); i.hasMoreElements();) {
-            copyProperty(antTask.createProperty(), (Property) i.nextElement());
-        }
 
-        for (Enumeration i = propertySets.elements(); i.hasMoreElements();) {
-            antTask.addPropertyset((PropertySet) i.nextElement());
-        }
+        properties.forEach(p -> copyProperty(antTask.createProperty(), p));
+
+        propertySets.forEach(antTask::addPropertyset);
 
         antTask.setInheritRefs(inheritRefs);
-        for (Enumeration i = references.elements(); i.hasMoreElements();) {
-            antTask.addReference((Ant.Reference) i.nextElement());
-        }
+
+        references.forEach(antTask::addReference);
 
         return antTask;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Sync.java b/src/main/org/apache/tools/ant/taskdefs/Sync.java
index 57d2f09..48eb647 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Sync.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Sync.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,12 +19,12 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -40,6 +40,7 @@
 import org.apache.tools.ant.types.resources.selectors.Exists;
 import org.apache.tools.ant.types.selectors.FileSelector;
 import org.apache.tools.ant.types.selectors.NoneSelector;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Synchronize a local target directory from the files defined
@@ -105,7 +106,7 @@
         File toDir = myCopy.getToDir();
 
         // The complete list of files to copy
-        Set allFiles = myCopy.nonOrphans;
+        Set<String> allFiles = myCopy.nonOrphans;
 
         // If the destination directory didn't already exist,
         // or was empty, then no previous file removal is necessary!
@@ -124,7 +125,7 @@
         // will hold the directories matched by SyncTarget in reversed
         // lexicographic order (order is important, that's why we use
         // a LinkedHashSet
-        Set preservedDirectories = new LinkedHashSet();
+        Set<File> preservedDirectories = new LinkedHashSet<>();
 
         // Get rid of all files not listed in the source filesets.
         log("PASS#2: Removing orphan files from " + toDir, Project.MSG_DEBUG);
@@ -186,15 +187,15 @@
      * Position 0 of the array is the number of orphaned directories.
      * Position 1 of the array is the number or orphaned files.
      */
-    private int[] removeOrphanFiles(Set nonOrphans, File toDir,
-                                    Set preservedDirectories) {
+    private int[] removeOrphanFiles(Set<String> nonOrphans, File toDir,
+                                    Set<File> preservedDirectories) {
         int[] removedCount = new int[] {0, 0};
         String[] excls =
-            (String[]) nonOrphans.toArray(new String[nonOrphans.size() + 1]);
+            nonOrphans.toArray(new String[nonOrphans.size() + 1]);
         // want to keep toDir itself
         excls[nonOrphans.size()] = "";
 
-        DirectoryScanner ds = null;
+        DirectoryScanner ds;
         if (syncTarget != null) {
             FileSet fs = syncTarget.toFileSet(false);
             fs.setDir(toDir);
@@ -213,8 +214,8 @@
             FileSelector[] s = syncTarget.getSelectors(getProject());
             if (s.length > 0) {
                 NoneSelector ns = new NoneSelector();
-                for (int i = 0; i < s.length; i++) {
-                    ns.appendSelector(s[i]);
+                for (FileSelector element : s) {
+                    ns.appendSelector(element);
                 }
                 fs.appendSelector(ns);
             }
@@ -222,6 +223,10 @@
         } else {
             ds = new DirectoryScanner();
             ds.setBasedir(toDir);
+            // set the case sensitivity of the directory scanner based on the
+            // directory we are scanning, if we are able to determine that detail.
+            // Else let the directory scanner default it to whatever it does internally
+            FileUtils.isCaseSensitiveFileSystem(toDir.toPath()).ifPresent(ds::setCaseSensitive);
         }
         ds.addExcludes(excls);
 
@@ -249,7 +254,7 @@
         }
 
         Boolean ped = getExplicitPreserveEmptyDirs();
-        if (ped != null && ped.booleanValue() != myCopy.getIncludeEmptyDirs()) {
+        if (ped != null && ped != myCopy.getIncludeEmptyDirs()) {
             FileSet fs = syncTarget.toFileSet(true);
             fs.setDir(toDir);
             String[] preservedDirs =
@@ -281,7 +286,7 @@
      * @return the number of empty directories actually removed.
      */
     private int removeEmptyDirectories(File dir, boolean removeIfEmpty,
-                                       Set preservedEmptyDirectories) {
+                                       Set<File> preservedEmptyDirectories) {
         int removedCount = 0;
         if (dir.isDirectory()) {
             File[] children = dir.listFiles();
@@ -320,11 +325,9 @@
      *
      * @since Ant 1.8.0
      */
-    private int removeEmptyDirectories(Set preservedEmptyDirectories) {
+    private int removeEmptyDirectories(Set<File> preservedEmptyDirectories) {
         int removedCount = 0;
-        for (Iterator iter = preservedEmptyDirectories.iterator();
-             iter.hasNext();) {
-            File f = (File) iter.next();
+        for (File f : preservedEmptyDirectories) {
             String[] s = f.list();
             if (s == null || s.length == 0) {
                 log("Removing empty directory: " + f, Project.MSG_DEBUG);
@@ -431,8 +434,8 @@
      */
     public void addPreserveInTarget(SyncTarget s) {
         if (syncTarget != null) {
-            throw new BuildException("you must not specify multiple "
-                                     + "preserveintarget elements.");
+            throw new BuildException(
+                "you must not specify multiple preserveintarget elements.");
         }
         syncTarget = s;
     }
@@ -454,11 +457,7 @@
 
         // List of files that must be copied, irrelevant from the
         // fact that they are newer or not than the destination.
-        private Set nonOrphans = new HashSet();
-
-        /** Constructor for MyCopy. */
-        public MyCopy() {
-        }
+        private Set<String> nonOrphans = new HashSet<>();
 
         /**
          * @see Copy#scan(File, File, String[], String[])
@@ -471,12 +470,8 @@
 
             super.scan(fromDir, toDir, files, dirs);
 
-            for (int i = 0; i < files.length; ++i) {
-                nonOrphans.add(files[i]);
-            }
-            for (int i = 0; i < dirs.length; ++i) {
-                nonOrphans.add(dirs[i]);
-            }
+            Collections.addAll(nonOrphans, files);
+            Collections.addAll(nonOrphans, dirs);
         }
 
         /**
@@ -484,12 +479,11 @@
          * {@inheritDoc}
          */
         @Override
-        protected Map scan(Resource[] resources, File toDir) {
+        protected Map<Resource, String[]> scan(Resource[] resources, File toDir) {
             assertTrue("No mapper", mapperElement == null);
 
-            for (int i = 0; i < resources.length; i++) {
-                nonOrphans.add(resources[i].getName());
-            }
+            Stream.of(resources).map(Resource::getName).forEach(nonOrphans::add);
+
             return super.scan(resources, toDir);
         }
 
@@ -536,6 +530,7 @@
          * This just changes the default value of "defaultexcludes" from
          * true to false.
          */
+        // TODO does it? ^
         public SyncTarget() {
             super();
         }
@@ -548,8 +543,8 @@
          */
         @Override
         public void setDir(File dir) throws BuildException {
-            throw new BuildException("preserveintarget doesn't support the dir "
-                                     + "attribute");
+            throw new BuildException(
+                "preserveintarget doesn't support the dir attribute");
         }
 
         /**
@@ -560,7 +555,7 @@
          * @since Ant 1.8.0
          */
         public void setPreserveEmptyDirs(boolean b) {
-            preserveEmptyDirs = Boolean.valueOf(b);
+            preserveEmptyDirs = b;
         }
 
         /**
@@ -585,8 +580,8 @@
                 PatternSet ps = mergePatterns(getProject());
                 fs.appendIncludes(ps.getIncludePatterns(getProject()));
                 fs.appendExcludes(ps.getExcludePatterns(getProject()));
-                for (Enumeration e = selectorElements(); e.hasMoreElements();) {
-                    fs.appendSelector((FileSelector) e.nextElement());
+                for (FileSelector sel : getSelectors(getProject())) {
+                    fs.appendSelector(sel);
                 }
                 fs.setDefaultexcludes(getDefaultexcludes());
             }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Tar.java b/src/main/org/apache/tools/ant/taskdefs/Tar.java
index 1ab2d33..b5a254f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Tar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Tar.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,14 +20,15 @@
 
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Files;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -109,10 +110,10 @@
     private TarLongFileMode longFileMode = new TarLongFileMode();
 
     // need to keep the package private version for backwards compatibility
-    Vector<TarFileSet> filesets = new Vector<TarFileSet>();
+    Vector<TarFileSet> filesets = new Vector<>();
     // we must keep two lists since other classes may modify the
     // filesets Vector (it is package private) without us noticing
-    private final Vector<ResourceCollection> resourceCollections = new Vector<ResourceCollection>();
+    private final List<ResourceCollection> resourceCollections = new Vector<>();
 
     // CheckStyle:VisibilityModifier ON
 
@@ -198,8 +199,7 @@
      */
     @Deprecated
     public void setLongfile(final String mode) {
-        log("DEPRECATED - The setLongfile(String) method has been deprecated."
-            + " Use setLongfile(Tar.TarLongFileMode) instead.");
+        log("DEPRECATED - The setLongfile(String) method has been deprecated. Use setLongfile(Tar.TarLongFileMode) instead.");
         this.longFileMode = new TarLongFileMode();
         longFileMode.setValue(mode);
     }
@@ -230,6 +230,7 @@
      * <li>  none - no compression
      * <li>  gzip - Gzip compression
      * <li>  bzip2 - Bzip2 compression
+     * <li>xz - XZ compression, requires XZ for Java
      * </ul>
      * @param mode the compression method.
      */
@@ -242,7 +243,7 @@
      * default encoding.
      *
      * <p>For a list of possible values see <a
-     * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.</p>
+     * href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.</p>
      * @param encoding the encoding name
      *
      * @since Ant 1.9.5
@@ -272,8 +273,7 @@
                                      getLocation());
         }
 
-        @SuppressWarnings("unchecked")
-        final Vector<TarFileSet> savedFileSets = (Vector<TarFileSet>) filesets.clone();
+        final Vector<TarFileSet> savedFileSets = new Vector<>(filesets);
         try {
             if (baseDir != null) {
                 if (!baseDir.exists()) {
@@ -287,20 +287,19 @@
                 filesets.addElement(mainFileSet);
             }
 
-            if (filesets.size() == 0 && resourceCollections.size() == 0) {
-                throw new BuildException("You must supply either a basedir "
-                                         + "attribute or some nested resource"
-                                         + " collections.",
-                                         getLocation());
+            if (filesets.isEmpty() && resourceCollections.isEmpty()) {
+                throw new BuildException(
+                    "You must supply either a basedir attribute or some nested resource collections.",
+                    getLocation());
             }
 
             // check if tar is out of date with respect to each
             // fileset
             boolean upToDate = true;
-            for(final TarFileSet tfs : filesets) {
+            for (final TarFileSet tfs : filesets) {
                 upToDate &= check(tfs);
             }
-            for(final ResourceCollection rcol : resourceCollections) {
+            for (final ResourceCollection rcol : resourceCollections) {
                 upToDate &= check(rcol);
             }
 
@@ -313,19 +312,17 @@
             final File parent = tarFile.getParentFile();
             if (parent != null && !parent.isDirectory()
                 && !(parent.mkdirs() || parent.isDirectory())) {
-                throw new BuildException("Failed to create missing parent"
-                                         + " directory for " + tarFile);
+                throw new BuildException(
+                    "Failed to create missing parent directory for %s",
+                    tarFile);
             }
 
             log("Building tar: " + tarFile.getAbsolutePath(), Project.MSG_INFO);
 
-            TarOutputStream tOut = null;
-            try {
-                tOut = new TarOutputStream(
-                    compression.compress(
-                        new BufferedOutputStream(
-                            new FileOutputStream(tarFile))),
-                    encoding);
+            try (TarOutputStream tOut = new TarOutputStream(
+                compression.compress(new BufferedOutputStream(
+                    Files.newOutputStream(tarFile.toPath()))),
+                encoding)) {
                 tOut.setDebug(true);
                 if (longFileMode.isTruncateMode()) {
                     tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE);
@@ -349,8 +346,6 @@
             } catch (final IOException ioe) {
                 final String msg = "Problem creating TAR: " + ioe.getMessage();
                 throw new BuildException(msg, ioe, getLocation());
-            } finally {
-                FileUtils.close(tOut);
             }
         } finally {
             filesets = savedFileSets;
@@ -404,15 +399,15 @@
 
         if (tarFileSet != null) {
             final String fullpath = tarFileSet.getFullpath(this.getProject());
-            if (fullpath.length() > 0) {
-                vPath = fullpath;
-            } else {
+            if (fullpath.isEmpty()) {
                 // don't add "" to the archive
-                if (vPath.length() <= 0) {
+                if (vPath.isEmpty()) {
                     return;
                 }
 
                 vPath = getCanonicalPrefix(tarFileSet, this.getProject()) + vPath;
+            } else {
+                vPath = fullpath;
             }
 
             preserveLeadingSlashes = tarFileSet.getPreserveLeadingSlashes();
@@ -461,9 +456,9 @@
             if (r instanceof TarResource) {
                 final TarResource tr = (TarResource) r;
                 te.setUserName(tr.getUserName());
-                te.setUserId(tr.getUid());
+                te.setUserId(tr.getLongUid());
                 te.setGroupName(tr.getGroup());
-                te.setGroupId(tr.getGid());
+                te.setGroupId(tr.getLongGid());
                 String linkName = tr.getLinkName();
                 byte linkFlag = tr.getLinkFlag();
                 if (linkFlag == TarConstants.LF_LINK &&
@@ -603,8 +598,8 @@
         } else if (!rc.isFilesystemOnly() && !supportsNonFileResources()) {
             throw new BuildException("only filesystem resources are supported");
         } else if (rc.isFilesystemOnly()) {
-            final Set<File> basedirs = new HashSet<File>();
-            final Map<File, List<String>> basedirToFilesMap = new HashMap<File, List<String>>();
+            final Set<File> basedirs = new HashSet<>();
+            final Map<File, List<String>> basedirToFilesMap = new HashMap<>();
             for (final Resource res : rc) {
                 final FileResource r = ResourceUtils
                     .asFileResource(res.as(FileProvider.class));
@@ -613,11 +608,7 @@
                     base = Copy.NULL_FILE_PLACEHOLDER;
                 }
                 basedirs.add(base);
-                List<String> files = basedirToFilesMap.get(base);
-                if (files == null) {
-                    files = new Vector<String>();
-                    basedirToFilesMap.put(base, files);
-                }
+                List<String> files = basedirToFilesMap.computeIfAbsent(base, k -> new Vector<>());
                 if (base == Copy.NULL_FILE_PLACEHOLDER) {
                     files.add(r.getFile().getAbsolutePath());
                 } else {
@@ -630,9 +621,7 @@
                 upToDate &= check(tmpBase, files);
             }
         } else { // non-file resources
-            final Iterator<Resource> iter = rc.iterator();
-            while (upToDate && iter.hasNext()) {
-                final Resource r = iter.next();
+            for (Resource r : rc) {
                 upToDate = archiveIsUpToDate(r);
             }
         }
@@ -649,15 +638,12 @@
      * @since Ant 1.7
      */
     protected boolean check(final File basedir, final String[] files) {
-        boolean upToDate = true;
-        if (!archiveIsUpToDate(files, basedir)) {
-            upToDate = false;
-        }
+        boolean upToDate = archiveIsUpToDate(files, basedir);
 
-        for (int i = 0; i < files.length; ++i) {
-            if (tarFile.equals(new File(basedir, files[i]))) {
-                throw new BuildException("A tar file cannot include "
-                                         + "itself", getLocation());
+        for (String file : files) {
+            if (tarFile.equals(new File(basedir, file))) {
+                throw new BuildException("A tar file cannot include itself",
+                    getLocation());
             }
         }
         return upToDate;
@@ -674,7 +660,7 @@
      * @since Ant 1.9.5
      */
     protected boolean check(final File basedir, final Collection<String> files) {
-        return check(basedir, files.toArray(new String[files.size()]));
+        return check(basedir, files.toArray(new String[0]));
     }
 
     /**
@@ -695,20 +681,17 @@
             afs = (ArchiveFileSet) rc;
         }
         if (afs != null && afs.size() > 1
-            && afs.getFullpath(this.getProject()).length() > 0) {
-            throw new BuildException("fullpath attribute may only "
-                                     + "be specified for "
-                                     + "filesets that specify a "
-                                     + "single file.");
+            && !afs.getFullpath(this.getProject()).isEmpty()) {
+            throw new BuildException(
+                "fullpath attribute may only be specified for filesets that specify a single file.");
         }
         final TarFileSet tfs = asTarFileSet(afs);
 
         if (isFileFileSet(rc)) {
             final FileSet fs = (FileSet) rc;
-            final String[] files = getFileNames(fs);
-            for (int i = 0; i < files.length; i++) {
-                final File f = new File(fs.getDir(getProject()), files[i]);
-                final String name = files[i].replace(File.separatorChar, '/');
+            for (String file : getFileNames(fs)) {
+                final File f = new File(fs.getDir(getProject()), file);
+                final String name = file.replace(File.separatorChar, '/');
                 tarFile(f, tOut, name, tfs);
             }
         } else if (rc.isFilesystemOnly()) {
@@ -745,7 +728,7 @@
         final DirectoryScanner ds = fs.getDirectoryScanner(fs.getProject());
         final String[] directories = ds.getIncludedDirectories();
         final String[] filesPerSe = ds.getIncludedFiles();
-        final String[] files = new String [directories.length + filesPerSe.length];
+        final String[] files = new String[directories.length + filesPerSe.length];
         System.arraycopy(directories, 0, files, 0, directories.length);
         System.arraycopy(filesPerSe, 0, files, directories.length,
                          filesPerSe.length);
@@ -762,8 +745,8 @@
      * @since Ant 1.7
      */
     protected TarFileSet asTarFileSet(final ArchiveFileSet archiveFileSet) {
-        TarFileSet tfs = null;
-        if (archiveFileSet != null && archiveFileSet instanceof TarFileSet) {
+        TarFileSet tfs;
+        if (archiveFileSet instanceof TarFileSet) {
             tfs = (TarFileSet) archiveFileSet;
         } else {
             tfs = new TarFileSet();
@@ -849,7 +832,6 @@
             if (files == null) {
                 files = getFileNames(this);
             }
-
             return files;
         }
 
@@ -903,7 +885,7 @@
             POSIX = "posix",
             OMIT = "omit";
 
-        private final String[] validModes = {
+        private static final String[] VALID_MODES = {
             WARN, FAIL, TRUNCATE, GNU, POSIX, OMIT
         };
 
@@ -918,7 +900,7 @@
          */
         @Override
         public String[] getValues() {
-            return validModes;
+            return VALID_MODES;
         }
 
         /**
@@ -983,7 +965,11 @@
          *    BZIP2 compression
          */
         private static final String BZIP2 = "bzip2";
-
+        /**
+         *  XZ compression
+         * @since 1.10.1
+         */
+        private static final String XZ = "xz";
 
         /**
          * Default constructor
@@ -999,7 +985,7 @@
          */
         @Override
         public String[] getValues() {
-            return new String[] {NONE, GZIP, BZIP2};
+            return new String[] {NONE, GZIP, BZIP2, XZ};
         }
 
         /**
@@ -1015,14 +1001,39 @@
             final String v = getValue();
             if (GZIP.equals(v)) {
                 return new GZIPOutputStream(ostream);
-            } else {
-                if (BZIP2.equals(v)) {
-                    ostream.write('B');
-                    ostream.write('Z');
-                    return new CBZip2OutputStream(ostream);
-                }
+            }
+            if (XZ.equals(v)) {
+                return newXZOutputStream(ostream);
+            }
+            if (BZIP2.equals(v)) {
+                ostream.write('B');
+                ostream.write('Z');
+                return new CBZip2OutputStream(ostream);
             }
             return ostream;
         }
+
+        private static OutputStream newXZOutputStream(OutputStream ostream)
+            throws BuildException {
+            try {
+                Class<?> fClazz = Class.forName("org.tukaani.xz.FilterOptions");
+                Class<?> oClazz = Class.forName("org.tukaani.xz.LZMA2Options");
+                Class<? extends OutputStream> sClazz =
+                    Class.forName("org.tukaani.xz.XZOutputStream")
+                    .asSubclass(OutputStream.class);
+                Constructor<? extends OutputStream> c =
+                    sClazz.getConstructor(OutputStream.class, fClazz);
+                return c.newInstance(ostream, oClazz.getDeclaredConstructor().newInstance());
+            } catch (ClassNotFoundException ex) {
+                throw new BuildException("xz compression requires the XZ for Java library",
+                                         ex);
+            } catch (NoSuchMethodException
+                     | InstantiationException
+                     | IllegalAccessException
+                     | InvocationTargetException
+                     ex) {
+                throw new BuildException("failed to create XZOutputStream", ex);
+            }
+        }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/TaskOutputStream.java b/src/main/org/apache/tools/ant/taskdefs/TaskOutputStream.java
index 2ba5a61..1ac8e7e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/TaskOutputStream.java
+++ b/src/main/org/apache/tools/ant/taskdefs/TaskOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,8 @@
 import org.apache.tools.ant.Task;
 
 /**
- * Redirects text written to a stream thru the standard
- * ant logging mechanism. This class is useful for integrating
+ * Redirects text written to a stream through the standard
+ * Ant logging mechanism. This class is useful for integrating
  * with tools that write to System.out and System.err. For example,
  * the following will cause all text written to System.out to be
  * logged with "info" priority:
@@ -55,7 +55,7 @@
             + "TaskOutputStream class");
         System.err.println("is considered to be dead code by the Ant "
             + "developers and is unmaintained.");
-        System.err.println("Don\'t use it!");
+        System.err.println("Don't use it!");
 
         this.task = task;
         this.msgOutputLevel = msgOutputLevel;
diff --git a/src/main/org/apache/tools/ant/taskdefs/Taskdef.java b/src/main/org/apache/tools/ant/taskdefs/Taskdef.java
index a7d0b71..2952ea4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Taskdef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Taskdef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,7 +43,6 @@
      * This sets the adapter and the adaptto classes to
      * TaskAdapter and Task.
      */
-
     public Taskdef() {
         setAdapterClass(TaskAdapter.class);
         setAdaptToClass(Task.class);
diff --git a/src/main/org/apache/tools/ant/taskdefs/TempFile.java b/src/main/org/apache/tools/ant/taskdefs/TempFile.java
index 6c36991..7a1570f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/TempFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/TempFile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -80,7 +80,6 @@
         this.property = property;
     }
 
-
     /**
      * Sets the destination directory. If not set,
      * the basedir directory is used instead.
@@ -91,7 +90,6 @@
         this.destDir = destDir;
     }
 
-
     /**
      * Sets the optional prefix string for the temp file.
      *
@@ -101,7 +99,6 @@
         this.prefix = prefix;
     }
 
-
     /**
      * Sets the optional suffix string for the temp file.
      *
@@ -149,8 +146,9 @@
      *
      * @exception  BuildException  if something goes wrong with the build
      */
+    @Override
     public void execute() throws BuildException {
-        if (property == null || property.length() == 0) {
+        if (property == null || property.isEmpty()) {
             throw new BuildException("no property specified");
         }
         if (destDir == null) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/Touch.java b/src/main/org/apache/tools/ant/taskdefs/Touch.java
index 6ade0cd..aa55ea2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Touch.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Touch.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -66,9 +67,11 @@
     public static final DateFormatFactory DEFAULT_DF_FACTORY
         = new DateFormatFactory() {
 
+        @Override
         public DateFormat getPrimaryFormat() {
             return DateUtils.EN_US_DATE_FORMAT_MIN.get();
         }
+        @Override
         public DateFormat getFallbackFormat() {
             return DateUtils.EN_US_DATE_FORMAT_SEC.get();
         }
@@ -78,7 +81,7 @@
     private File file;
     private long millis = -1;
     private String dateTime;
-    private Vector filesets = new Vector();
+    private List<FileSet> filesets = new Vector<>();
     private Union resources;
     private boolean dateTimeConfigured;
     private boolean mkdirs;
@@ -87,12 +90,6 @@
     private DateFormatFactory dfFactory = DEFAULT_DF_FACTORY;
 
     /**
-     * Construct a new <code>Touch</code> task.
-     */
-    public Touch() {
-    }
-
-    /**
      * Sets a single source file to touch.  If the file does not exist
      * an empty file will be created.
      * @param file the <code>File</code> to touch.
@@ -152,9 +149,11 @@
      */
     public void setPattern(final String pattern) {
         dfFactory = new DateFormatFactory() {
+            @Override
             public DateFormat getPrimaryFormat() {
                 return new SimpleDateFormat(pattern);
             }
+            @Override
             public DateFormat getFallbackFormat() {
                 return null;
             }
@@ -178,8 +177,8 @@
      */
     public void add(FileNameMapper fileNameMapper) throws BuildException {
         if (this.fileNameMapper != null) {
-            throw new BuildException("Only one mapper may be added to the "
-                + getTaskName() + " task.");
+            throw new BuildException(
+                "Only one mapper may be added to the %s task.", getTaskName());
         }
         this.fileNameMapper = fileNameMapper;
     }
@@ -218,8 +217,8 @@
      */
     protected synchronized void checkConfiguration() throws BuildException {
         if (file == null && resources == null) {
-            throw new BuildException("Specify at least one source"
-                                   + "--a file or resource collection.");
+            throw new BuildException(
+                "Specify at least one source--a file or resource collection.");
         }
         if (file != null && file.exists() && file.isDirectory()) {
             throw new BuildException("Use a resource collection to touch directories.");
@@ -249,10 +248,9 @@
                     throw new BuildException(pe.getMessage(), pe, getLocation());
                 }
                 if (workmillis < 0) {
-                    throw new BuildException("Date of " + dateTime
-                            + " results in negative " + "milliseconds value "
-                            + "relative to epoch " + "(January 1, 1970, "
-                            + "00:00:00 GMT).");
+                    throw new BuildException(
+                        "Date of %s results in negative milliseconds value relative to epoch (January 1, 1970, 00:00:00 GMT).",
+                        dateTime);
                 }
             }
             log("Setting millis to " + workmillis + " from datetime attribute",
@@ -269,6 +267,7 @@
      * @throws BuildException
      *             if an error occurs.
      */
+    @Override
     public void execute() throws BuildException {
         checkConfiguration();
         touch();
@@ -300,16 +299,12 @@
         // deal with filesets in a special way since the task
         // originally also used the directories and Union won't return
         // them.
-        final int size = filesets.size();
-        for (int i = 0; i < size; i++) {
-            FileSet fs = (FileSet) filesets.elementAt(i);
+        for (FileSet fs : filesets) {
             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
             File fromDir = fs.getDir(getProject());
 
-            String[] srcDirs = ds.getIncludedDirectories();
-
-            for (int j = 0; j < srcDirs.length; j++) {
-                touch(new FileResource(fromDir, srcDirs[j]), defaultTimestamp);
+            for (String srcDir : ds.getIncludedDirectories()) {
+                touch(new FileResource(fromDir, srcDir), defaultTimestamp);
             }
         }
     }
@@ -322,6 +317,7 @@
      * @throws BuildException on error
      * @deprecated since 1.6.x.
      */
+    @Deprecated
     protected void touch(File file) {
         touch(file, getTimestamp());
     }
@@ -365,8 +361,8 @@
             }
         }
         if (!file.canWrite()) {
-            throw new BuildException("Can not change modification date of "
-                                     + "read-only file " + file);
+            throw new BuildException(
+                "Can not change modification date of read-only file %s", file);
         }
         FILE_UTILS.setFileLastModified(file, modTime);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Transform.java b/src/main/org/apache/tools/ant/taskdefs/Transform.java
index 9fd15d1..88818c3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Transform.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Transform.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,7 @@
  * Has been merged into ExecuteOn, empty class for backwards compatibility.
  * We leave that in case that external programs access this class directly,
  * for example via
- *   <tt> Transform tr = (Transform) getProject().createTask("apply") </tt>
+ *   <code> Transform tr = (Transform) getProject().createTask("apply") </code>
  *
  * @ant.task ignore="true"
  */
diff --git a/src/main/org/apache/tools/ant/taskdefs/Truncate.java b/src/main/org/apache/tools/ant/taskdefs/Truncate.java
index cb8fd4a..1c151bc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Truncate.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Truncate.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,7 +40,7 @@
 
     private static final int BUFFER_SIZE = 1024;
 
-    private static final Long ZERO = new Long(0L);
+    private static final Long ZERO = 0L;
 
     private static final String NO_CHILD = "No files specified.";
 
@@ -91,7 +91,7 @@
      */
     public void setLength(Long length) {
         this.length = length;
-        if (length != null && length.longValue() < 0) {
+        if (length != null && length < 0) {
             throw new BuildException(INVALID_LENGTH + length);
         }
     }
@@ -159,7 +159,7 @@
     private void process(File f) {
         long len = f.length();
         long newLength = length == null
-                ? len + adjust.longValue() : length.longValue();
+                ? len + adjust : length;
 
         if (len == newLength) {
             //nothing to do!
diff --git a/src/main/org/apache/tools/ant/taskdefs/Tstamp.java b/src/main/org/apache/tools/ant/taskdefs/Tstamp.java
index aee2607..ca10efe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Tstamp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Tstamp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,16 +19,20 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.text.SimpleDateFormat;
+import java.time.Instant;
 import java.util.Calendar;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Optional;
 import java.util.StringTokenizer;
 import java.util.TimeZone;
 import java.util.Vector;
+import java.util.function.BiFunction;
+import java.util.function.Function;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Location;
@@ -46,7 +50,9 @@
  */
 public class Tstamp extends Task {
 
-    private Vector customFormats = new Vector();
+    private static final String ENV_SOURCE_DATE_EPOCH = "SOURCE_DATE_EPOCH";
+
+    private List<CustomFormat> customFormats = new Vector<>();
     private String prefix = "";
 
     /**
@@ -67,15 +73,25 @@
      * the standard ones, to get their retaliation in early.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
         try {
             Date d = getNow();
-
-            Enumeration i = customFormats.elements();
-            while (i.hasMoreElements()) {
-                CustomFormat cts = (CustomFormat) i.nextElement();
-                cts.execute(getProject(), d, getLocation());
+            // Honour reproducible builds https://reproducible-builds.org/specs/source-date-epoch/#idm55
+            final String epoch = System.getenv(ENV_SOURCE_DATE_EPOCH);
+            try {
+                if (epoch != null) {
+                    // Value of SOURCE_DATE_EPOCH will be an integer, representing seconds.
+                    d = new Date(Long.parseLong(epoch) * 1000L);
+                    log("Honouring environment variable " + ENV_SOURCE_DATE_EPOCH + " which has been set to " + epoch);
+                }
+            } catch(NumberFormatException e) {
+                // ignore
+                log("Ignoring invalid value '" + epoch + "' for " + ENV_SOURCE_DATE_EPOCH
+                        + " environment variable", Project.MSG_DEBUG);
             }
+            final Date date = d;
+            customFormats.forEach(cts -> cts.execute(getProject(), date, getLocation()));
 
             SimpleDateFormat dstamp = new SimpleDateFormat("yyyyMMdd");
             setProperty("DSTAMP", dstamp.format(d));
@@ -98,7 +114,7 @@
      */
     public CustomFormat createFormat() {
         CustomFormat cts = new CustomFormat();
-        customFormats.addElement(cts);
+        customFormats.add(cts);
         return cts;
     }
 
@@ -116,16 +132,41 @@
      * @return Date
      */
     protected Date getNow() {
-        String magicNow = getProject().getProperty(MagicNames.TSTAMP_NOW);
-        if (magicNow != null && magicNow.length() > 0) {
+        Optional<Date> now = getNow(
+            MagicNames.TSTAMP_NOW_ISO,
+            s -> Date.from(Instant.parse(s)),
+            (k, v) -> "magic property " + k + " ignored as '" + v + "' is not in valid ISO pattern"
+        );
+        if (now.isPresent()) {
+            return now.get();
+        }
+
+        now = getNow(
+            MagicNames.TSTAMP_NOW,
+            s -> new Date(1000 * Long.parseLong(s)),
+            (k, v) -> "magic property " + k + " ignored as " + v + " is not a valid number"
+        );
+        return now.orElseGet(Date::new);
+    }
+
+    /**
+     * Checks and returns a Date if the specified property is set.
+     * @param propertyName name of the property to check
+     * @param map conversion of the property value as string to Date
+     * @param log supplier of the log message containing the property name and value if
+     *     the conversion fails
+     * @return Optional containing the Date or null
+     */
+    protected Optional<Date> getNow(String propertyName, Function<String, Date> map, BiFunction<String, String, String> log) {
+        String property = getProject().getProperty(propertyName);
+        if (property != null && !property.isEmpty()) {
             try {
-                return new Date(1000 * Long.parseLong(magicNow));
-            } catch (NumberFormatException ex) {
-                log("magic property " + MagicNames.TSTAMP_NOW + " ignored as "
-                    + magicNow + " is not a valid number");
+                return Optional.ofNullable(map.apply(property));
+            } catch (Exception e) {
+                log(log.apply(propertyName, property));
             }
         }
-        return new Date();
+        return Optional.empty();
     }
 
     /**
@@ -148,12 +189,6 @@
         private int field = Calendar.DATE;
 
         /**
-         * Create a format
-         */
-        public CustomFormat() {
-        }
-
-        /**
          *  The property to receive the date/time string in the given pattern
          * @param propertyName the name of the property.
          */
@@ -228,9 +263,9 @@
          *             encapsulate operations on the unit in its own
          *             class.
          */
+        @Deprecated
         public void setUnit(String unit) {
-            log("DEPRECATED - The setUnit(String) method has been deprecated."
-                + " Use setUnit(Tstamp.Unit) instead.");
+            log("DEPRECATED - The setUnit(String) method has been deprecated. Use setUnit(Tstamp.Unit) instead.");
             Unit u = new Unit();
             u.setValue(unit);
             field = u.getCalendarField();
@@ -317,19 +352,19 @@
                                                 YEAR
                                               };
 
-        private Map calendarFields = new HashMap();
+        private Map<String, Integer> calendarFields = new HashMap<>();
 
         /** Constructor for Unit enumerated type. */
         public Unit() {
             calendarFields.put(MILLISECOND,
-                               new Integer(Calendar.MILLISECOND));
-            calendarFields.put(SECOND, new Integer(Calendar.SECOND));
-            calendarFields.put(MINUTE, new Integer(Calendar.MINUTE));
-            calendarFields.put(HOUR, new Integer(Calendar.HOUR_OF_DAY));
-            calendarFields.put(DAY, new Integer(Calendar.DATE));
-            calendarFields.put(WEEK, new Integer(Calendar.WEEK_OF_YEAR));
-            calendarFields.put(MONTH, new Integer(Calendar.MONTH));
-            calendarFields.put(YEAR, new Integer(Calendar.YEAR));
+                    Calendar.MILLISECOND);
+            calendarFields.put(SECOND, Calendar.SECOND);
+            calendarFields.put(MINUTE, Calendar.MINUTE);
+            calendarFields.put(HOUR, Calendar.HOUR_OF_DAY);
+            calendarFields.put(DAY, Calendar.DATE);
+            calendarFields.put(WEEK, Calendar.WEEK_OF_YEAR);
+            calendarFields.put(MONTH, Calendar.MONTH);
+            calendarFields.put(YEAR, Calendar.YEAR);
         }
 
         /**
@@ -338,14 +373,14 @@
          */
         public int getCalendarField() {
             String key = getValue().toLowerCase(Locale.ENGLISH);
-            Integer i = (Integer) calendarFields.get(key);
-            return i.intValue();
+            return calendarFields.get(key);
         }
 
         /**
          * Get the valid values.
          * @return the value values.
          */
+        @Override
         public String[] getValues() {
             return UNITS;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Typedef.java b/src/main/org/apache/tools/ant/taskdefs/Typedef.java
index 87276e2..cc87a0b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Typedef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Typedef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,6 @@
 
 package org.apache.tools.ant.taskdefs;
 
-
-
 /**
  *
  * Adds a data type definition to the current project.
diff --git a/src/main/org/apache/tools/ant/taskdefs/Unpack.java b/src/main/org/apache/tools/ant/taskdefs/Unpack.java
index ccc4577..bee0bdf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Unpack.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Unpack.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -50,6 +50,7 @@
      * @ant.attribute ignore="true"
      * @param src a <code>String</code> value
      */
+    @Deprecated
     public void setSrc(String src) {
         log("DEPRECATED - The setSrc(String) method has been deprecated."
             + " Use setSrc(File) instead.");
@@ -65,6 +66,7 @@
      * @ant.attribute ignore="true"
      * @param dest a <code>String</code> value
      */
+    @Deprecated
     public void setDest(String dest) {
         log("DEPRECATED - The setDest(String) method has been deprecated."
             + " Use setDest(File) instead.");
@@ -85,22 +87,20 @@
      */
     public void setSrcResource(Resource src) {
         if (!src.isExists()) {
-            throw new BuildException(
-                "the archive " + src.getName() + " doesn't exist");
+            throw new BuildException("the archive %s doesn't exist",
+                src.getName());
         }
         if (src.isDirectory()) {
-            throw new BuildException(
-                "the archive " + src.getName() + " can't be a directory");
+            throw new BuildException("the archive %s can't be a directory",
+                src.getName());
         }
         FileProvider fp = src.as(FileProvider.class);
         if (fp != null) {
             source = fp.getFile();
         } else if (!supportsNonFileResources()) {
             throw new BuildException(
-                "The source " + src.getName()
-                + " is not a FileSystem "
-                + "Only FileSystem resources are"
-                + " supported.");
+                "The source %s is not a FileSystem Only FileSystem resources are supported.",
+                src.getName());
         }
         srcResource = src;
     }
@@ -111,8 +111,8 @@
      */
     public void addConfigured(ResourceCollection a) {
         if (a.size() != 1) {
-            throw new BuildException("only single argument resource collections"
-                                     + " are supported as archives");
+            throw new BuildException(
+                "only single argument resource collections are supported as archives");
         }
         setSrcResource(a.iterator().next());
     }
@@ -163,6 +163,7 @@
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         File savedDest = dest; // may be altered in validate
         try {
@@ -199,7 +200,7 @@
 
     private String getLastNamePart(Resource r) {
         String n = r.getName();
-        int idx = n.lastIndexOf("/");
+        int idx = n.lastIndexOf('/');
         return idx < 0 ? n : n.substring(idx + 1);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/Untar.java b/src/main/org/apache/tools/ant/taskdefs/Untar.java
index 27d2b74..c1bcb30 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Untar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Untar.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,9 +20,11 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Files;
 import java.util.zip.GZIPInputStream;
 
 import org.apache.tools.ant.BuildException;
@@ -35,8 +37,6 @@
 import org.apache.tools.tar.TarEntry;
 import org.apache.tools.tar.TarInputStream;
 
-
-
 /**
  * Untar a file.
  * <p>PatternSets are used to select files to extract
@@ -70,6 +70,7 @@
      *   <li>none - no compression
      *   <li>gzip - Gzip compression
      *   <li>bzip2 - Bzip2 compression
+     *   <li>xz - XZ compression, requires XZ for Java
      * </ul>
      *
      * @param method compression method
@@ -83,33 +84,32 @@
      *
      * @since Ant 1.8.0
      */
+    @Override
     public void setScanForUnicodeExtraFields(boolean b) {
-        throw new BuildException("The " + getTaskName()
-                                 + " task doesn't support the encoding"
-                                 + " attribute", getLocation());
+        throw new BuildException(
+            "The " + getTaskName()
+                + " task doesn't support the encoding attribute",
+            getLocation());
     }
 
     /**
      * @see Expand#expandFile(FileUtils, File, File)
      * {@inheritDoc}
      */
+    @Override
     protected void expandFile(FileUtils fileUtils, File srcF, File dir) {
-        FileInputStream fis = null;
         if (!srcF.exists()) {
             throw new BuildException("Unable to untar "
                     + srcF
                     + " as the file does not exist",
                     getLocation());
         }
-        try {
-            fis = new FileInputStream(srcF);
+        try (InputStream fis = Files.newInputStream(srcF.toPath())) {
             expandStream(srcF.getPath(), fis, dir);
         } catch (IOException ioe) {
             throw new BuildException("Error while expanding " + srcF.getPath()
                                      + "\n" + ioe.toString(),
                                      ioe, getLocation());
-        } finally {
-            FileUtils.close(fis);
         }
     }
 
@@ -120,6 +120,7 @@
      * @param dir       the destination directory
      * @since Ant 1.7
      */
+    @Override
     protected void expandResource(Resource srcR, File dir) {
         if (!srcR.isExists()) {
             throw new BuildException("Unable to untar "
@@ -128,15 +129,11 @@
                                      getLocation());
         }
 
-        InputStream i = null;
-        try {
-            i = srcR.getInputStream();
+        try (InputStream i = srcR.getInputStream()) {
             expandStream(srcR.getName(), i, dir);
         } catch (IOException ioe) {
             throw new BuildException("Error while expanding " + srcR.getName(),
                                      ioe, getLocation());
-        } finally {
-            FileUtils.close(i);
         }
     }
 
@@ -145,16 +142,13 @@
      */
     private void expandStream(String name, InputStream stream, File dir)
         throws IOException {
-        TarInputStream tis = null;
-        try {
-            tis =
-                new TarInputStream(compression.decompress(name,
-                                                          new BufferedInputStream(stream)),
-                                   getEncoding());
+        try (TarInputStream tis = new TarInputStream(
+            compression.decompress(name, new BufferedInputStream(stream)),
+            getEncoding())) {
             log("Expanding: " + name + " into " + dir, Project.MSG_INFO);
-            TarEntry te = null;
             boolean empty = true;
             FileNameMapper mapper = getMapper();
+            TarEntry te;
             while ((te = tis.getNextEntry()) != null) {
                 empty = false;
                 extractFile(FileUtils.getFileUtils(), null, dir, tis,
@@ -162,11 +156,9 @@
                             te.isDirectory(), mapper);
             }
             if (empty && getFailOnEmptyArchive()) {
-                throw new BuildException("archive '" + name + "' is empty");
+                throw new BuildException("archive '%s' is empty", name);
             }
             log("expand complete", Project.MSG_VERBOSE);
-        } finally {
-            FileUtils.close(tis);
         }
     }
 
@@ -190,6 +182,11 @@
          *  BZIP2 compression
          */
         private static final String BZIP2 = "bzip2";
+        /**
+         *  XZ compression
+         * @since 1.10.1
+         */
+        private static final String XZ = "xz";
 
 
         /**
@@ -205,8 +202,9 @@
          *
          * @return valid values
          */
+        @Override
         public String[] getValues() {
-            return new String[] {NONE, GZIP, BZIP2};
+            return new String[] {NONE, GZIP, BZIP2, XZ};
         }
 
         /**
@@ -226,8 +224,12 @@
             if (GZIP.equals(v)) {
                 return new GZIPInputStream(istream);
             }
+            if (XZ.equals(v)) {
+                return newXZInputStream(istream);
+            }
             if (BZIP2.equals(v)) {
-                for (char c : new char[] {'B', 'Z'}) {
+                final char[] magic = new char[] { 'B', 'Z' };
+                for (char c : magic) {
                     if (istream.read() != c) {
                         throw new BuildException("Invalid bz2 file." + name);
                     }
@@ -236,5 +238,26 @@
             }
             return istream;
         }
+
+        private static InputStream newXZInputStream(InputStream istream)
+            throws BuildException {
+            try {
+                Class<? extends InputStream> clazz =
+                    Class.forName("org.tukaani.xz.XZInputStream")
+                    .asSubclass(InputStream.class);
+                Constructor<? extends InputStream> c =
+                    clazz.getConstructor(InputStream.class);
+                return c.newInstance(istream);
+            } catch (ClassNotFoundException ex) {
+                throw new BuildException("xz decompression requires the XZ for Java library",
+                                         ex);
+            } catch (NoSuchMethodException
+                     | InstantiationException
+                     | IllegalAccessException
+                     | InvocationTargetException
+                     ex) {
+                throw new BuildException("failed to create XZInputStream", ex);
+            }
+        }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/UpToDate.java b/src/main/org/apache/tools/ant/taskdefs/UpToDate.java
index e5c85ce..5183c4f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/UpToDate.java
+++ b/src/main/org/apache/tools/ant/taskdefs/UpToDate.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,11 +19,10 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.taskdefs.condition.Condition;
@@ -51,7 +50,7 @@
     private String value;
     private File sourceFile;
     private File targetFile;
-    private Vector sourceFileSets = new Vector();
+    private List<FileSet> sourceFileSets = new Vector<>();
     private Union sourceResources = new Union();
 
     // CheckStyle:VisibilityModifier OFF - bc
@@ -110,7 +109,7 @@
      * @param fs the source files
      */
     public void addSrcfiles(final FileSet fs) {
-        sourceFileSets.addElement(fs);
+        sourceFileSets.add(fs);
     }
 
     /**
@@ -150,24 +149,23 @@
      * see if the target(s) is/are up-to-date.
      * @return true if the target(s) is/are up-to-date
      */
+    @Override
     public boolean eval() {
-        if (sourceFileSets.size() == 0 && sourceResources.size() == 0
+        if (sourceFileSets.isEmpty() && sourceResources.isEmpty()
             && sourceFile == null) {
-            throw new BuildException("At least one srcfile or a nested "
-                                     + "<srcfiles> or <srcresources> element "
-                                     + "must be set.");
+            throw new BuildException(
+                "At least one srcfile or a nested <srcfiles> or <srcresources> element must be set.");
         }
 
-        if ((sourceFileSets.size() > 0 || sourceResources.size() > 0)
+        if ((!sourceFileSets.isEmpty() || !sourceResources.isEmpty())
             && sourceFile != null) {
-            throw new BuildException("Cannot specify both the srcfile "
-                                     + "attribute and a nested <srcfiles> "
-                                     + "or <srcresources> element.");
+            throw new BuildException(
+                "Cannot specify both the srcfile attribute and a nested <srcfiles> or <srcresources> element.");
         }
 
         if (targetFile == null && mapperElement == null) {
-            throw new BuildException("The targetfile attribute or a nested "
-                                     + "mapper element must be set.");
+            throw new BuildException(
+                "The targetfile attribute or a nested mapper element must be set.");
         }
 
         // if the target file is not there, then it can't be up-to-date
@@ -179,8 +177,8 @@
 
         // if the source file isn't there, throw an exception
         if (sourceFile != null && !sourceFile.exists()) {
-            throw new BuildException(sourceFile.getAbsolutePath()
-                                     + " not found.");
+            throw new BuildException("%s not found.",
+                sourceFile.getAbsolutePath());
         }
 
         boolean upToDate = true;
@@ -204,12 +202,13 @@
         // reasons.  If we use the code for union below, we'll always
         // scan all filesets, even if we know the target is out of
         // date after the first test.
-        Enumeration e = sourceFileSets.elements();
-        while (upToDate && e.hasMoreElements()) {
-            FileSet fs = (FileSet) e.nextElement();
-            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
-            upToDate = scanDir(fs.getDir(getProject()),
-                                           ds.getIncludedFiles());
+
+        for (FileSet fs : sourceFileSets) {
+            if (!scanDir(fs.getDir(getProject()),
+                    fs.getDirectoryScanner(getProject()).getIncludedFiles())) {
+                upToDate = false;
+                break;
+            }
         }
 
         if (upToDate) {
@@ -223,12 +222,12 @@
         return upToDate;
     }
 
-
     /**
      * Sets property to true if target file(s) have a more recent timestamp
      * than (each of) the corresponding source file(s).
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         if (property == null) {
             throw new BuildException("property attribute is required.",
@@ -264,14 +263,11 @@
     }
 
     private FileNameMapper getMapper() {
-        FileNameMapper mapper = null;
         if (mapperElement == null) {
             MergingMapper mm = new MergingMapper();
             mm.setTo(targetFile.getAbsolutePath());
-            mapper = mm;
-        } else {
-            mapper = mapperElement.getImplementation();
+            return mm;
         }
-        return mapper;
+        return mapperElement.getImplementation();
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java b/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java
index 77408df..395fcbc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/VerifyJar.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -45,6 +45,9 @@
      */
     public static final String ERROR_NO_FILE = "Not found :";
 
+    /** Error output if there is a failure to verify the jar. */
+    public static final String ERROR_NO_VERIFY = "Failed to verify ";
+
     /**
      * The string we look for in the text to indicate direct verification
      */
@@ -55,8 +58,6 @@
      */
     private boolean certificates = false;
     private BufferingOutputFilter outputCache = new BufferingOutputFilter();
-    /** Error output if there is a failure to verify the jar. */
-    public static final String ERROR_NO_VERIFY = "Failed to verify ";
 
     private String savedStorePass = null;
 
@@ -72,6 +73,7 @@
      * verify our jar files
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
         //validation logic
         final boolean hasJar = jar != null;
@@ -94,15 +96,13 @@
                 FileProvider fr = r.as(FileProvider.class);
                 verifyOneJar(fr.getFile());
             }
-
         } finally {
             endExecution();
         }
-
     }
 
     /**
-     * @since 1.9.11
+     * @since 1.10.3
      */
     @Override
     protected void beginExecution() {
@@ -126,7 +126,7 @@
     }
 
     /**
-     * @since 1.9.11
+     * @since 1.10.3
      */
     @Override
     protected void endExecution() {
@@ -200,11 +200,13 @@
 
         private BufferingOutputFilterReader buffer;
 
+        @Override
         public Reader chain(Reader rdr) {
             buffer = new BufferingOutputFilterReader(rdr);
             return buffer;
         }
 
+        @Override
         public String toString() {
             return buffer.toString();
         }
@@ -229,6 +231,7 @@
             this.next = next;
         }
 
+        @Override
         public int read(char[] cbuf, int off, int len) throws IOException {
             //hand down
             int result = next.read(cbuf, off, len);
@@ -238,10 +241,12 @@
             return result;
         }
 
+        @Override
         public void close() throws IOException {
             next.close();
         }
 
+        @Override
         public String toString() {
             return buffer.toString();
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/WaitFor.java b/src/main/org/apache/tools/ant/taskdefs/WaitFor.java
index 3f94d6f..92ea403 100644
--- a/src/main/org/apache/tools/ant/taskdefs/WaitFor.java
+++ b/src/main/org/apache/tools/ant/taskdefs/WaitFor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -89,7 +89,6 @@
         super("waitfor");
     }
 
-
     /**
      * Constructor that takes the name of the task in the task name.
      *
@@ -108,7 +107,6 @@
         maxWait = time;
     }
 
-
     /**
      * Set the max wait time unit
      * @param unit an enumerated <code>Unit</code> value
@@ -117,8 +115,6 @@
         maxWaitMultiplier = unit.getMultiplier();
     }
 
-
-
     /**
      * Set the time between each check
      * @param time a <code>long</code> value
@@ -150,15 +146,15 @@
      */
     public void execute() throws BuildException {
         if (countConditions() > 1) {
-            throw new BuildException("You must not nest more than one "
-                                     + "condition into "
-                                     + getTaskName());
+            throw new BuildException(
+                "You must not nest more than one condition into %s",
+                getTaskName());
         }
         if (countConditions() < 1) {
-            throw new BuildException("You must nest a condition into "
-                                     + getTaskName());
+            throw new BuildException("You must nest a condition into %s",
+                getTaskName());
         }
-        Condition c = (Condition) getConditions().nextElement();
+        Condition c = getConditions().nextElement();
         try {
             long maxWaitMillis = calculateMaxWaitMillis();
             long checkEveryMillis = calculateCheckEveryMillis();
@@ -244,32 +240,32 @@
             MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK
         };
 
-        private Map timeTable = new HashMap();
+        private Map<String, Long> timeTable = new HashMap<>();
 
         /** Constructor the Unit enumerated type. */
         public Unit() {
-            timeTable.put(MILLISECOND, new Long(1L));
-            timeTable.put(SECOND,      new Long(ONE_SECOND));
-            timeTable.put(MINUTE,      new Long(ONE_MINUTE));
-            timeTable.put(HOUR,        new Long(ONE_HOUR));
-            timeTable.put(DAY,         new Long(ONE_DAY));
-            timeTable.put(WEEK,        new Long(ONE_WEEK));
+            timeTable.put(MILLISECOND, 1L);
+            timeTable.put(SECOND, ONE_SECOND);
+            timeTable.put(MINUTE, ONE_MINUTE);
+            timeTable.put(HOUR, ONE_HOUR);
+            timeTable.put(DAY, ONE_DAY);
+            timeTable.put(WEEK, ONE_WEEK);
         }
 
         /**
-         * Convert the value to a multipler (millisecond to unit).
-         * @return a multipler (a long value)
+         * Convert the value to a multiplier (millisecond to unit).
+         * @return a multiplier (a long value)
          */
         public long getMultiplier() {
             String key = getValue().toLowerCase(Locale.ENGLISH);
-            Long l = (Long) timeTable.get(key);
-            return l.longValue();
+            return timeTable.get(key);
         }
 
         /**
          * @see EnumeratedAttribute#getValues()
          * {@inheritDoc}
          */
+        @Override
         public String[] getValues() {
             return UNITS;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/War.java b/src/main/org/apache/tools/ant/taskdefs/War.java
index 7daf08e..0d559f9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/War.java
+++ b/src/main/org/apache/tools/ant/taskdefs/War.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,7 +27,6 @@
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.zip.ZipOutputStream;
 
-
 /**
  * <p>An extension of &lt;jar&gt; to create a WAR archive.
  * Contains special treatment for files that should end up in the
@@ -49,6 +48,10 @@
  */
 public class War extends Jar {
 
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+    /** path to web.xml file */
+    private static final String XML_DESCRIPTOR_PATH = "WEB-INF/web.xml";
+
     /**
      * our web.xml deployment descriptor
      */
@@ -60,10 +63,6 @@
     private boolean needxmlfile = true;
     private File addedWebXmlFile;
 
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    /** path to web.xml file */
-    private static final String XML_DESCRIPTOR_PATH = "WEB-INF/web.xml";
-
     /** Constructor for the War Task. */
     public War() {
         super();
@@ -73,7 +72,7 @@
 
     /**
      * <i>Deprecated</i> name of the file to create
-     * -use <tt>destfile</tt> instead.
+     * -use <code>destfile</code> instead.
      * @param warFile the destination file
      * @deprecated since 1.5.x.
      *             Use setDestFile(File) instead
@@ -86,15 +85,14 @@
 
     /**
      * set the deployment descriptor to use (WEB-INF/web.xml);
-     * required unless <tt>update=true</tt>
+     * required unless <code>update=true</code>
      * @param descr the deployment descriptor file
      */
     public void setWebxml(File descr) {
         deploymentDescriptor = descr;
         if (!deploymentDescriptor.exists()) {
-            throw new BuildException("Deployment descriptor: "
-                                     + deploymentDescriptor
-                                     + " does not exist.");
+            throw new BuildException("Deployment descriptor:  does not exist.",
+                deploymentDescriptor);
         }
 
         // Create a ZipFileSet for this file, and pass it up.
@@ -104,7 +102,6 @@
         super.addFileset(fs);
     }
 
-
     /**
      * Set the policy on the web.xml file, that is, whether or not it is needed
      * @param needxmlfile whether a web.xml file is needed. Default: true
@@ -117,7 +114,6 @@
      * add files under WEB-INF/lib/
      * @param fs the zip file set to add
      */
-
     public void addLib(ZipFileSet fs) {
         // We just set the prefix for this fileset, and pass it up.
         fs.setPrefix("WEB-INF/lib/");
@@ -190,13 +186,10 @@
                 //check to see if we warn or not
                 if (!FILE_UTILS.fileNameEquals(addedWebXmlFile, file)) {
                     logWhenWriting("Warning: selected " + archiveType
-                                   + " files include a second "
-                                   + XML_DESCRIPTOR_PATH
-                                   + " which will be ignored.\n"
-                                   + "The duplicate entry is at " + file + '\n'
-                                   + "The file that will be used is "
-                                   + addedWebXmlFile,
-                                   Project.MSG_WARN);
+                        + " files include a second " + XML_DESCRIPTOR_PATH
+                        + " which will be ignored.\nThe duplicate entry is at "
+                        + file + "\nThe file that will be used is "
+                        + addedWebXmlFile, Project.MSG_WARN);
                 }
             } else {
                 //no added file, yet
@@ -212,7 +205,6 @@
         }
     }
 
-
     /**
      * Make sure we don't think we already have a web.xml next time this task
      * gets executed.
@@ -224,8 +216,8 @@
             && needxmlfile
             && !isInUpdateMode()
             && hasUpdatedFile()) {
-            throw new BuildException("No WEB-INF/web.xml file was added.\n"
-                    + "If this is your intent, set needxmlfile='false' ");
+            throw new BuildException(
+                "No WEB-INF/web.xml file was added.\nIf this is your intent, set needxmlfile='false' ");
         }
         addedWebXmlFile = null;
         super.cleanUp();
diff --git a/src/main/org/apache/tools/ant/taskdefs/WhichResource.java b/src/main/org/apache/tools/ant/taskdefs/WhichResource.java
index 3f315a8..1010b7b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/WhichResource.java
+++ b/src/main/org/apache/tools/ant/taskdefs/WhichResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -105,14 +105,11 @@
             setcount++;
         }
 
-
         if (setcount == 0) {
-            throw new BuildException("One of classname or resource must"
-                                     + " be specified");
+            throw new BuildException("One of classname or resource must be specified");
         }
         if (setcount > 1) {
-            throw new BuildException("Only one of classname or resource can"
-                                     + " be specified");
+            throw new BuildException("Only one of classname or resource can be specified");
         }
         if (property == null) {
             throw new BuildException("No property defined");
@@ -123,6 +120,7 @@
      * execute it
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         validate();
         if (classpath != null) {
@@ -135,11 +133,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
@@ -155,17 +152,12 @@
             }
 
             log("Searching for " + resource, Project.MSG_VERBOSE);
-            URL url;
-            url = loader.getResource(resource);
+            URL url = loader.getResource(resource);
             if (url != null) {
                 //set the property
                 loc = url.toExternalForm();
                 getProject().setNewProperty(property, loc);
             }
-        } finally {
-            if (loader != null) {
-                loader.cleanup();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison.java b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison.java
index 617790a..c536950 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,7 +31,7 @@
     /**
      * the file protocol prefix for systemid.
      * This file protocol must be appended to an absolute path.
-     * Typically: <tt>FILE_PROTOCOL_PREFIX + file.getAbsolutePath()</tt>
+     * Typically: <code>FILE_PROTOCOL_PREFIX + file.getAbsolutePath()</code>
      * Note that on Windows, an extra '/' must be appended to the
      * protocol prefix so that there is always 3 consecutive slashes.
      * @since Ant 1.4
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison2.java b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison2.java
index 0653b40..bc3bad7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison2.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison2.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison3.java b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison3.java
index 963093f..434efd3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison3.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison3.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison4.java b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison4.java
index 6e16e62..95e14cd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison4.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTLiaison4.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTLogger.java b/src/main/org/apache/tools/ant/taskdefs/XSLTLogger.java
index 4dadebc..411160d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTLogger.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTLoggerAware.java b/src/main/org/apache/tools/ant/taskdefs/XSLTLoggerAware.java
index edf0fce..36d3002 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTLoggerAware.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTLoggerAware.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
index ecd28f5..237f5d8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumMap;
@@ -32,7 +33,6 @@
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
-import javax.xml.xpath.XPathVariableResolver;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -72,6 +72,15 @@
  */
 
 public class XSLTProcess extends MatchingTask implements XSLTLogger {
+    /**
+     * The default processor is trax
+     * @since Ant 1.7
+     */
+    public static final String PROCESSOR_TRAX = "trax";
+
+    /** Utilities used for file operations */
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
     /** destination directory */
     private File destDir = null;
 
@@ -94,7 +103,7 @@
     private String fileDirParameter = null;
 
     /** additional parameters to be passed to the stylesheets */
-    private final List<Param> params = new ArrayList<Param>();
+    private final List<Param> params = new ArrayList<>();
 
     /** Input XML document to be used */
     private File inFile = null;
@@ -120,14 +129,11 @@
     private boolean force = false;
 
     /** XSL output properties to be used */
-    private final Vector<OutputProperty> outputProperties = new Vector<OutputProperty>();
+    private final List<OutputProperty> outputProperties = new Vector<>();
 
     /** for resolving entities such as dtds */
     private final XMLCatalog xmlCatalog = new XMLCatalog();
 
-    /** Utilities used for file operations */
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
     /**
      * Whether to style all files in the included directories as well.
      *
@@ -181,12 +187,6 @@
     private boolean useImplicitFileset = true;
 
     /**
-     * The default processor is trax
-     * @since Ant 1.7
-     */
-    public static final String PROCESSOR_TRAX = "trax";
-
-    /**
      * whether to suppress warnings.
      *
      * @since Ant 1.8.0
@@ -244,12 +244,6 @@
     private TraceConfiguration traceConfiguration;
 
     /**
-     * Creates a new XSLTProcess Task.
-     */
-    public XSLTProcess() {
-    } //-- XSLTProcess
-
-    /**
      * Whether to style all files in the included directories as well;
      * optional, default is true.
      *
@@ -304,8 +298,8 @@
      */
     public void addConfiguredStyle(final Resources rc) {
         if (rc.size() != 1) {
-            handleError("The style element must be specified with exactly one"
-                        + " nested resource.");
+            handleError(
+                "The style element must be specified with exactly one nested resource.");
         } else {
             setXslResource(rc.iterator().next());
         }
@@ -346,13 +340,8 @@
         }
         final File savedBaseDir = baseDir;
 
-        DirectoryScanner scanner;
-        String[]         list;
-        String[]         dirs;
-
         final String baseMessage =
-            "specify the stylesheet either as a filename in style attribute "
-            + "or as a nested resource";
+            "specify the stylesheet either as a filename in style attribute or as a nested resource";
 
         if (xslResource == null && xslFile == null) {
             handleError(baseMessage);
@@ -396,8 +385,7 @@
                      * the wrong version has been used.
                      */
                     if (alternative.exists()) {
-                        log("DEPRECATED - the 'style' attribute should be "
-                            + "relative to the project's");
+                        log("DEPRECATED - the 'style' attribute should be relative to the project's");
                         log("             basedir, not the tasks's basedir.");
                         stylesheet = alternative;
                     }
@@ -428,33 +416,30 @@
             //-- make sure destination directory exists...
             checkDest();
 
+
             if (useImplicitFileset) {
-                scanner = getDirectoryScanner(baseDir);
+                DirectoryScanner scanner = getDirectoryScanner(baseDir);
                 log("Transforming into " + destDir, Project.MSG_INFO);
 
                 // Process all the files marked for styling
-                list = scanner.getIncludedFiles();
-                for (int i = 0; i < list.length; ++i) {
-                    process(baseDir, list[i], destDir, styleResource);
+                for (String element : scanner.getIncludedFiles()) {
+                    process(baseDir, element, destDir, styleResource);
                 }
                 if (performDirectoryScan) {
                     // Process all the directories marked for styling
-                    dirs = scanner.getIncludedDirectories();
-                    for (int j = 0; j < dirs.length; ++j) {
-                        list = new File(baseDir, dirs[j]).list();
-                        for (int i = 0; i < list.length; ++i) {
-                            process(baseDir, dirs[j] + File.separator + list[i], destDir,
+                    for (String dir : scanner.getIncludedDirectories()) {
+                        for (String element : new File(baseDir, dir).list()) {
+                            process(baseDir, dir + File.separator + element, destDir,
                                     styleResource);
                         }
                     }
                 }
-            } else { // only resource collections, there better be some
-                if (resources.size() == 0) {
-                    if (failOnNoResources) {
-                        handleError("no resources specified");
-                    }
-                    return;
+            } else if (resources.isEmpty()) {
+                // only resource collections, there better be some
+                if (failOnNoResources) {
+                    handleError("no resources specified");
                 }
+                return;
             }
             processResources(styleResource);
         } finally {
@@ -495,7 +480,7 @@
     /**
      * Set the destination directory into which the XSL result
      * files should be copied to;
-     * required, unless <tt>in</tt> and <tt>out</tt> are
+     * required, unless <code>in</code> and <code>out</code> are
      * specified.
      * @param dir the name of the destination directory
      **/
@@ -687,8 +672,7 @@
      */
     public TraceConfiguration createTrace() {
         if (traceConfiguration != null) {
-            throw new BuildException("can't have more than one trace"
-                                     + " configuration");
+            throw new BuildException("can't have more than one trace configuration");
         }
         traceConfiguration = new TraceConfiguration();
         return traceConfiguration;
@@ -713,12 +697,12 @@
      * @exception Exception if the processor cannot be loaded.
      */
     private void resolveProcessor(final String proc) throws Exception {
-        if (proc.equals(PROCESSOR_TRAX)) {
+        if (PROCESSOR_TRAX.equals(proc)) {
             liaison = new TraXLiaison();
         } else {
             //anything else is a classname
-            final Class clazz = loadClass(proc);
-            liaison = (XSLTLiaison) clazz.newInstance();
+            final Class<? extends XSLTLiaison> clazz = loadClass(proc).asSubclass(XSLTLiaison.class);
+            liaison = clazz.getDeclaredConstructor().newInstance();
         }
     }
 
@@ -730,7 +714,7 @@
      * @param classname the name of the class to load.
      * @return the requested class.
      */
-    private Class loadClass(final String classname) throws ClassNotFoundException {
+    private Class<?> loadClass(final String classname) throws ClassNotFoundException {
         setupLoader();
         if (loader == null) {
             return Class.forName(classname);
@@ -752,7 +736,7 @@
 
     /**
      * Specifies the output name for the styled result from the
-     * <tt>in</tt> attribute; required if <tt>in</tt> is set
+     * <code>in</code> attribute; required if <code>in</code> is set
      *
      * @param outFile the output File instance.
      */
@@ -762,7 +746,7 @@
 
     /**
      * specifies a single XML document to be styled. Should be used
-     * with the <tt>out</tt> attribute; required if <tt>out</tt> is set
+     * with the <code>out</code> attribute; required if <code>out</code> is set
      *
      * @param inFile the input file
      */
@@ -820,29 +804,25 @@
             throws BuildException {
 
         File   outF = null;
-        File   inF = null;
 
         try {
             final long styleSheetLastModified = stylesheet.getLastModified();
-            inF = new File(baseDir, xmlFile);
+            File inF = new File(baseDir, xmlFile);
 
             if (inF.isDirectory()) {
                 log("Skipping " + inF + " it is a directory.", Project.MSG_VERBOSE);
                 return;
             }
-            FileNameMapper mapper = null;
-            if (mapperElement != null) {
-                mapper = mapperElement.getImplementation();
-            } else {
-                mapper = new StyleMapper();
-            }
+            FileNameMapper mapper = mapperElement == null ? new StyleMapper()
+                : mapperElement.getImplementation();
 
             final String[] outFileName = mapper.mapFileName(xmlFile);
             if (outFileName == null || outFileName.length == 0) {
                 log("Skipping " + inFile + " it cannot get mapped to output.", Project.MSG_VERBOSE);
                 return;
-            } else if (outFileName.length > 1) {
-                log("Skipping " + inFile + " its mapping is ambiguos.", Project.MSG_VERBOSE);
+            }
+            if (outFileName.length > 1) {
+                log("Skipping " + inFile + " its mapping is ambiguous.", Project.MSG_VERBOSE);
                 return;
             }
             outF = new File(destDir, outFileName[0]);
@@ -909,11 +889,9 @@
      */
     private void ensureDirectoryFor(final File targetFile) throws BuildException {
         final File directory = targetFile.getParentFile();
-        if (!directory.exists()) {
-            if (!(directory.mkdirs() || directory.isDirectory())) {
-                handleError("Unable to create directory: "
-                            + directory.getAbsolutePath());
-            }
+        if (!directory.exists() && !directory.mkdirs() && !directory.isDirectory()) {
+            handleError("Unable to create directory: "
+                    + directory.getAbsolutePath());
         }
     }
 
@@ -941,7 +919,7 @@
      * @return the outputproperties
      */
     public Enumeration<OutputProperty> getOutputProperties() {
-        return outputProperties.elements();
+        return Collections.enumeration(outputProperties);
     }
 
     /**
@@ -1169,7 +1147,7 @@
         public static final Map<ParamType, QName> XPATH_TYPES;
 
         static {
-            final Map<ParamType, QName> m = new EnumMap<ParamType, QName>(ParamType.class);
+            final Map<ParamType, QName> m = new EnumMap<>(ParamType.class);
             m.put(XPATH_STRING, XPathConstants.STRING);
             m.put(XPATH_BOOLEAN, XPathConstants.BOOLEAN);
             m.put(XPATH_NUMBER, XPathConstants.NUMBER);
@@ -1186,13 +1164,13 @@
      */
     public OutputProperty createOutputProperty() {
         final OutputProperty p = new OutputProperty();
-        outputProperties.addElement(p);
+        outputProperties.add(p);
         return p;
     }
 
     /**
      * Specify how the result tree should be output as specified
-     * in the <a href="http://www.w3.org/TR/xslt#output">
+     * in the <a href="https://www.w3.org/TR/xslt#output">
      * specification</a>.
      * @since Ant 1.5
      */
@@ -1247,11 +1225,8 @@
 
         xpathFactory = XPathFactory.newInstance();
         xpath = xpathFactory.newXPath();
-        xpath.setXPathVariableResolver(new XPathVariableResolver() {
-            public Object resolveVariable(final QName variableName) {
-                return getProject().getProperty(variableName.toString());
-            }
-        });
+        xpath.setXPathVariableResolver(
+            variableName -> getProject().getProperty(variableName.toString()));
     }
 
     /**
@@ -1311,16 +1286,15 @@
                 if (p.shouldUse()) {
                     final Object evaluatedParam = evaluateParam(p);
                     if (liaison instanceof XSLTLiaison4) {
-                        ((XSLTLiaison4) liaison).addParam(p.getName(), evaluatedParam);
+                        ((XSLTLiaison4) liaison).addParam(p.getName(),
+                            evaluatedParam);
+                    } else if (evaluatedParam == null || evaluatedParam instanceof String) {
+                        liaison.addParam(p.getName(), (String) evaluatedParam);
                     } else {
-                        if (evaluatedParam == null || evaluatedParam instanceof String) {
-                            liaison.addParam(p.getName(), (String) evaluatedParam);
-                        } else {
-                            log("XSLTLiaison '" + liaison.getClass().getName()
-                                    + "' supports only String parameters. Converting parameter '" + p.getName()
-                                    + "' to its String value '" + evaluatedParam, Project.MSG_WARN);
-                            liaison.addParam(p.getName(), String.valueOf(evaluatedParam));
-                        }
+                        log("XSLTLiaison '" + liaison.getClass().getName()
+                                + "' supports only String parameters. Converting parameter '" + p.getName()
+                                + "' to its String value '" + evaluatedParam, Project.MSG_WARN);
+                        liaison.addParam(p.getName(), String.valueOf(evaluatedParam));
                     }
                 }
             }
@@ -1347,7 +1321,7 @@
 
         ParamType type;
 
-        if (typeName == null || "".equals(typeName)) {
+        if (typeName == null || typeName.isEmpty()) {
             type = ParamType.STRING; // String is default
         } else {
             try {
@@ -1372,11 +1346,10 @@
                 final QName xpathType = ParamType.XPATH_TYPES.get(type);
                 if (xpathType == null) {
                     throw new IllegalArgumentException("Invalid XSLT parameter type: " + typeName);
-                } else {
-                    final XPathExpression xpe = xpath.compile(expression);
-                    // null = evaluate XPath on empty XML document
-                    return xpe.evaluate((Object) null, xpathType);
                 }
+                final XPathExpression xpe = xpath.compile(expression);
+                // null = evaluate XPath on empty XML document
+                return xpe.evaluate((Object) null, xpathType);
         }
     }
 
@@ -1445,9 +1418,8 @@
     protected void handleError(final Throwable ex) {
         if (failOnError) {
             throw new BuildException(ex);
-        } else {
-            log("Caught an exception: " + ex, Project.MSG_WARN);
         }
+        log("Caught an exception: " + ex, Project.MSG_WARN);
     }
 
     /**
@@ -1461,10 +1433,9 @@
     protected void handleTransformationError(final Exception ex) {
         if (failOnError && failOnTransformationError) {
             throw new BuildException(ex);
-        } else {
-            log("Caught an error during transformation: " + ex,
-                Project.MSG_WARN);
         }
+        log("Caught an error during transformation: " + ex,
+            Project.MSG_WARN);
     }
 
     /**
@@ -1479,12 +1450,12 @@
         /**
          * the list of factory attributes to use for TraXLiaison
          */
-        private final List<Attribute> attributes = new ArrayList<Attribute>();
+        private final List<Attribute> attributes = new ArrayList<>();
 
         /**
          * the list of factory features to use for TraXLiaison
          */
-        private final List<Feature> features = new ArrayList<Feature>();
+        private final List<Feature> features = new ArrayList<>();
 
         /**
          * @return the name of the factory.
@@ -1544,8 +1515,7 @@
          *  <li>http://xml.apache.org/xalan/features/incremental (true|false) </li>
          * </ul>
          */
-        public static class Attribute
-            extends ProjectComponent
+        public static class Attribute extends ProjectComponent
             implements DynamicConfigurator {
 
             /** attribute name, mostly processor specific */
@@ -1574,6 +1544,7 @@
              * @return null
              * @throws BuildException never
              */
+            @Override
             public Object createDynamicElement(final String name) throws BuildException {
                 return null;
             }
@@ -1585,6 +1556,7 @@
              * @param value the value of the attribute
              * @throws BuildException on error
              */
+            @Override
             public void setDynamicAttribute(final String name, final String value) throws BuildException {
                 // only 'name' and 'value' exist.
                 if ("name".equalsIgnoreCase(name)) {
@@ -1598,7 +1570,7 @@
                         this.value = Boolean.FALSE;
                     } else {
                         try {
-                            this.value = new Integer(value);
+                            this.value = Integer.valueOf(value);
                         } catch (final NumberFormatException e) {
                             this.value = value;
                         }
@@ -1611,7 +1583,7 @@
                                                              new Reference(getProject(),
                                                                            value));
                 } else {
-                    throw new BuildException("Unsupported attribute: " + name);
+                    throw new BuildException("Unsupported attribute: %s", name);
                 }
             }
         } // -- class Attribute
@@ -1624,7 +1596,9 @@
             private String name;
             private boolean value;
 
-            public Feature() { }
+            public Feature() {
+            }
+
             public Feature(String name, boolean value) {
                 this.name = name;
                 this.value = value;
@@ -1670,10 +1644,15 @@
      * @since Ant 1.6.2
      */
     private class StyleMapper implements FileNameMapper {
+        @Override
         public void setFrom(final String from) {
         }
+
+        @Override
         public void setTo(final String to) {
         }
+
+        @Override
         public String[] mapFileName(String xmlFile) {
             final int dotPos = xmlFile.lastIndexOf('.');
             if (dotPos > 0) {
@@ -1796,7 +1775,7 @@
          *
          * @return OutputStream
          */
-        public java.io.OutputStream getOutputStream() {
+        public OutputStream getOutputStream() {
             return new LogOutputStream(XSLTProcess.this);
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/XmlProperty.java b/src/main/org/apache/tools/ant/taskdefs/XmlProperty.java
index 9feb357..4e07c3a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XmlProperty.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XmlProperty.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,9 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Hashtable;
+import java.util.Map;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -176,19 +178,6 @@
  * @ant.task name="xmlproperty" category="xml"
  */
 public class XmlProperty extends Task {
-
-    private Resource src;
-    private String prefix = "";
-    private boolean keepRoot = true;
-    private boolean validate = false;
-    private boolean collapseAttributes = false;
-    private boolean semanticAttributes = false;
-    private boolean includeSemanticAttribute = false;
-    private File rootDirectory = null;
-    private Hashtable addedAttributes = new Hashtable();
-    private XMLCatalog xmlCatalog = new XMLCatalog();
-    private String delimiter = ",";
-
     private static final String ID = "id";
     private static final String REF_ID = "refid";
     private static final String LOCATION = "location";
@@ -201,24 +190,29 @@
 
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-    /**
-     * Constructor.
-     */
-    public XmlProperty() {
-        super();
-    }
+    private Resource src;
+    private String prefix = "";
+    private boolean keepRoot = true;
+    private boolean validate = false;
+    private boolean collapseAttributes = false;
+    private boolean semanticAttributes = false;
+    private boolean includeSemanticAttribute = false;
+    private File rootDirectory = null;
+    private Map<String, String> addedAttributes = new Hashtable<>();
+    private XMLCatalog xmlCatalog = new XMLCatalog();
+    private String delimiter = ",";
 
     /**
      * Initializes the task.
      */
-
+    @Override
     public void init() {
         super.init();
         xmlCatalog.setProject(getProject());
     }
 
     /**
-     * @return the xmlCatalog as the entityresolver.
+     * @return the xmlCatalog as the EntityResolver.
      */
     protected EntityResolver getEntityResolver() {
         return xmlCatalog;
@@ -230,6 +224,7 @@
      * @todo validate the source file is valid before opening, print a better error message
      * @todo add a verbose level log message listing the name of the file being loaded
      */
+    @Override
     public void execute() throws BuildException {
         Resource r = getResource();
 
@@ -246,7 +241,7 @@
               factory.setNamespaceAware(false);
               DocumentBuilder builder = factory.newDocumentBuilder();
               builder.setEntityResolver(getEntityResolver());
-              Document document = null;
+              Document document;
               FileProvider fp = src.as(FileProvider.class);
               if (fp != null) {
                   document = builder.parse(fp.getFile());
@@ -259,7 +254,7 @@
               // This task is allow to override its own properties
               // but not other properties.  So we need to keep track
               // of which properties we've added.
-              addedAttributes = new Hashtable();
+              addedAttributes = new Hashtable<>();
 
               if (keepRoot) {
                   addNodeRecursively(topElement, prefix, null);
@@ -295,7 +290,7 @@
         // Set the prefix for this node to include its tag name.
         String nodePrefix = prefix;
         if (node.getNodeType() != Node.TEXT_NODE) {
-            if (prefix.trim().length() > 0) {
+            if (!prefix.trim().isEmpty()) {
                 nodePrefix += ".";
             }
             nodePrefix += node.getNodeName();
@@ -368,33 +363,31 @@
                     String nodeName = attributeNode.getNodeName();
                     String attributeValue = getAttributeValue(attributeNode);
 
-                    Path containingPath =
-                        ((container != null) && (container instanceof Path))
-                        ? (Path) container
-                        : null;
+                    Path containingPath = container instanceof Path
+                        ? (Path) container : null;
                     /*
                      * The main conditional logic -- if the attribute
                      * is somehow "special" (i.e., it has known
                      * semantic meaning) then deal with it
                      * appropriately.
                      */
-                    if (nodeName.equals(ID)) {
+                    if (ID.equals(nodeName)) {
                         // ID has already been found above.
                         continue;
                     }
-                    if (containingPath != null && nodeName.equals(PATH)) {
+                    if (containingPath != null && PATH.equals(nodeName)) {
                         // A "path" attribute for a node within a Path object.
                         containingPath.setPath(attributeValue);
                     } else if (containingPath != null
-                               && container instanceof Path && nodeName.equals(REF_ID)) {
+                               && container instanceof Path && REF_ID.equals(nodeName)) {
                         // A "refid" attribute for a node within a Path object.
                         containingPath.setPath(attributeValue);
                     } else if (containingPath != null && container instanceof Path
-                               && nodeName.equals(LOCATION)) {
+                               && LOCATION.equals(nodeName)) {
                         // A "location" attribute for a node within a
                         // Path object.
                         containingPath.setLocation(resolveFile(attributeValue));
-                    } else if (nodeName.equals(PATHID)) {
+                    } else if (PATHID.equals(nodeName)) {
                         // A node identifying a new path
                         if (container != null) {
                             throw new BuildException("XmlProperty does not support nested paths");
@@ -411,17 +404,14 @@
         }
         String nodeText = null;
         boolean emptyNode = false;
-        boolean semanticEmptyOverride = false;
-        if (node.getNodeType() == Node.ELEMENT_NODE
+        boolean semanticEmptyOverride = node.getNodeType() == Node.ELEMENT_NODE
                 && semanticAttributes
                 && node.hasAttributes()
                 && (node.getAttributes().getNamedItem(VALUE) != null
                         || node.getAttributes().getNamedItem(LOCATION) != null
                         || node.getAttributes().getNamedItem(REF_ID) != null
                         || node.getAttributes().getNamedItem(PATH) != null || node.getAttributes()
-                        .getNamedItem(PATHID) != null)) {
-            semanticEmptyOverride = true;
-        }
+                        .getNamedItem(PATHID) != null);
         if (node.getNodeType() == Node.TEXT_NODE) {
             // For the text node, add a property.
             nodeText = getAttributeValue(node);
@@ -430,7 +420,7 @@
                 && node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE) {
 
             nodeText = node.getFirstChild().getNodeValue();
-            if ("".equals(nodeText) && !semanticEmptyOverride) {
+            if (nodeText.isEmpty() && !semanticEmptyOverride) {
                 emptyNode = true;
             }
         } else if (node.getNodeType() == Node.ELEMENT_NODE
@@ -441,7 +431,7 @@
         } else if (node.getNodeType() == Node.ELEMENT_NODE
                && node.getChildNodes().getLength() == 1
                && node.getFirstChild().getNodeType() == Node.TEXT_NODE
-               && "".equals(node.getFirstChild().getNodeValue())
+               && node.getFirstChild().getNodeValue().isEmpty()
                && !semanticEmptyOverride) {
             nodeText = "";
             emptyNode = true;
@@ -451,7 +441,7 @@
             if (semanticAttributes && id == null && container instanceof String) {
                 id = (String) container;
             }
-            if (nodeText.trim().length() != 0 || emptyNode) {
+            if (!nodeText.trim().isEmpty() || emptyNode) {
                 addProperty(prefix, nodeText, id);
             }
         }
@@ -459,7 +449,7 @@
         // children to reference if needed.  Path objects are
         // definitely used by child path elements, and ID may be used
         // for a child text node.
-        return (addedPath != null ? addedPath : id);
+        return addedPath != null ? addedPath : id;
     }
 
     /**
@@ -482,7 +472,7 @@
             // when we read them, though (instead of keeping them
             // outside of the project and batch adding them at the end)
             // to allow other properties to reference them.
-            value = (String) addedAttributes.get(name) + getDelimiter() + value;
+            value = addedAttributes.get(name) + getDelimiter() + value;
             getProject().setProperty(name, value);
             addedAttributes.put(name, value);
         } else if (getProject().getProperty(name) == null) {
@@ -509,7 +499,7 @@
         if (semanticAttributes) {
             // Never include the "refid" attribute as part of the
             // attribute name.
-            if (attributeName.equals(REF_ID)) {
+            if (REF_ID.equals(attributeName)) {
                 return "";
             }
             // Otherwise, return it appended unless property to hide it is set.
@@ -525,12 +515,7 @@
      * Return whether the provided attribute name is recognized or not.
      */
     private static boolean isSemanticAttribute(String attributeName) {
-        for (int i = 0; i < ATTRIBUTES.length; i++) {
-            if (attributeName.equals(ATTRIBUTES[i])) {
-                return true;
-            }
-        }
-        return false;
+        return Arrays.asList(ATTRIBUTES).contains(attributeName);
     }
 
     /**
@@ -550,11 +535,11 @@
         if (semanticAttributes) {
             String attributeName = attributeNode.getNodeName();
             nodeValue = getProject().replaceProperties(nodeValue);
-            if (attributeName.equals(LOCATION)) {
+            if (LOCATION.equals(attributeName)) {
                 File f = resolveFile(nodeValue);
                 return f.getPath();
             }
-            if (attributeName.equals(REF_ID)) {
+            if (REF_ID.equals(attributeName)) {
                 Object ref = getProject().getReference(nodeValue);
                 if (ref != null) {
                     return ref.toString();
diff --git a/src/main/org/apache/tools/ant/taskdefs/Zip.java b/src/main/org/apache/tools/ant/taskdefs/Zip.java
index f9e7b11..b694057 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Zip.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Zip.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,22 +19,21 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Comparator;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
 import java.util.Stack;
 import java.util.Vector;
+import java.util.stream.Stream;
 import java.util.zip.CRC32;
 
 import org.apache.tools.ant.BuildException;
@@ -44,7 +43,6 @@
 import org.apache.tools.ant.types.ArchiveFileSet;
 import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.types.PatternSet;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.ZipFileSet;
@@ -86,13 +84,24 @@
     private static final int ROUNDUP_MILLIS = ZIP_FILE_TIMESTAMP_GRANULARITY - 1;
     // CheckStyle:VisibilityModifier OFF - bc
 
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
+    // For directories:
+    private static final long EMPTY_CRC = new CRC32().getValue();
+
+    private static final ResourceSelector MISSING_SELECTOR =
+            target -> !target.isExists();
+
+    private static final ResourceUtils.ResourceSelectorProvider
+        MISSING_DIR_PROVIDER = sr -> MISSING_SELECTOR;
+
     protected File zipFile;
     // use to scan own archive
     private ZipScanner zs;
     private File baseDir;
-    protected Hashtable<String, String> entries = new Hashtable<String, String>();
-    private final Vector<FileSet> groupfilesets = new Vector<FileSet>();
-    private final Vector<ZipFileSet> filesetsFromGroupfilesets = new Vector<ZipFileSet>();
+    protected Hashtable<String, String> entries = new Hashtable<>();
+    private final List<FileSet> groupfilesets = new Vector<>();
+    private final List<ZipFileSet> filesetsFromGroupfilesets = new Vector<>();
     protected String duplicate = "add";
     private boolean doCompress = true;
     private boolean doUpdate = false;
@@ -101,27 +110,10 @@
     private boolean doFilesonly = false;
     protected String archiveType = "zip";
 
-    // For directories:
-    private static final long EMPTY_CRC = new CRC32().getValue();
     protected String emptyBehavior = "skip";
-    private final Vector<ResourceCollection> resources = new Vector<ResourceCollection>();
-    protected Hashtable<String, String> addedDirs = new Hashtable<String, String>();
-    private final Vector<String> addedFiles = new Vector<String>();
-
-    private static final ResourceSelector MISSING_SELECTOR =
-        new ResourceSelector() {
-            public boolean isSelected(final Resource target) {
-                return !target.isExists();
-            }
-        };
-
-    private static final ResourceUtils.ResourceSelectorProvider
-        MISSING_DIR_PROVIDER = new ResourceUtils.ResourceSelectorProvider() {
-                public ResourceSelector
-                    getTargetSelectorForSource(final Resource sr) {
-                    return MISSING_SELECTOR;
-                }
-            };
+    private final List<ResourceCollection> resources = new Vector<>();
+    protected Hashtable<String, String> addedDirs = new Hashtable<>();
+    private final List<String> addedFiles = new Vector<>();
 
     private String fixedModTime = null; // User-provided.
     private long modTimeMillis = 0; // Calculated.
@@ -157,8 +149,6 @@
         return !doubleFilePass || skipWriting;
     }
 
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
     // CheckStyle:VisibilityModifier ON
 
     // This boolean is set if the task detects that the
@@ -368,7 +358,7 @@
      * @param set the group (a fileset) to add
      */
     public void addZipGroupFileset(final FileSet set) {
-        groupfilesets.addElement(set);
+        groupfilesets.add(set);
     }
 
     /**
@@ -418,7 +408,7 @@
      * default encoding.
      *
      * <p>For a list of possible values see <a
-     * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.</p>
+     * href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.</p>
      * @param encoding the encoding name
      */
     public void setEncoding(final String encoding) {
@@ -606,7 +596,7 @@
      *        that you must choose one of a or b, and [c] indicates that you
      *        may use or omit c. &plusmn;ZZZZ is the timezone offset, and may be
      *        literally "Z" to mean GMT.
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public void setModificationtime(String time) {
         fixedModTime = time;
@@ -616,7 +606,7 @@
      * The file modification time previously provided to
      * {@link #setModificationtime(String)} or {@code null} if unset.
      * @return String
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public String getModificationtime() {
         return fixedModTime;
@@ -633,10 +623,8 @@
             skipWriting = true;
             executeMain();
             skipWriting = false;
-            executeMain();
-        } else {
-            executeMain();
         }
+        executeMain();
     }
 
     /**
@@ -666,20 +654,17 @@
         processGroupFilesets();
 
         // collect filesets to pass them to getResourcesToAdd
-        final Vector<ResourceCollection> vfss = new Vector<ResourceCollection>();
+        final List<ResourceCollection> vfss = new ArrayList<>();
         if (baseDir != null) {
             final FileSet fs = (FileSet) getImplicitFileSet().clone();
             fs.setDir(baseDir);
-            vfss.addElement(fs);
+            vfss.add(fs);
         }
-        final int size = resources.size();
-        for (int i = 0; i < size; i++) {
-            final ResourceCollection rc = resources.elementAt(i);
-            vfss.addElement(rc);
-        }
+        vfss.addAll(resources);
 
-        final ResourceCollection[] fss = new ResourceCollection[vfss.size()];
-        vfss.copyInto(fss);
+        final ResourceCollection[] fss =
+            vfss.toArray(new ResourceCollection[0]);
+
         boolean success = false;
         try {
             // can also handle empty archives
@@ -693,8 +678,9 @@
             final File parent = zipFile.getParentFile();
             if (parent != null && !parent.isDirectory()
                 && !(parent.mkdirs() || parent.isDirectory())) {
-                throw new BuildException("Failed to create missing parent"
-                                         + " directory for " + zipFile);
+                throw new BuildException(
+                    "Failed to create missing parent directory for %s",
+                    zipFile);
             }
 
             updatedFile = true;
@@ -745,32 +731,25 @@
                     oldFiles.setSrc(renamedFile);
                     oldFiles.setDefaultexcludes(false);
 
-                    final int addSize = addedFiles.size();
-                    for (int i = 0; i < addSize; i++) {
-                        final PatternSet.NameEntry ne = oldFiles.createExclude();
-                        ne.setName(addedFiles.elementAt(i));
+                    for (String addedFile : addedFiles) {
+                        oldFiles.createExclude().setName(addedFile);
                     }
                     final DirectoryScanner ds =
                         oldFiles.getDirectoryScanner(getProject());
                     ((ZipScanner) ds).setEncoding(encoding);
 
-                    final String[] f = ds.getIncludedFiles();
-                    Resource[] r = new Resource[f.length];
-                    for (int i = 0; i < f.length; i++) {
-                        r[i] = ds.getResource(f[i]);
-                    }
+                    Stream<String> includedResourceNames =
+                        Stream.of(ds.getIncludedFiles());
 
                     if (!doFilesonly) {
-                        final String[] d = ds.getIncludedDirectories();
-                        final Resource[] dr = new Resource[d.length];
-                        for (int i = 0; i < d.length; i++) {
-                            dr[i] = ds.getResource(d[i]);
-                        }
-                        final Resource[] tmp = r;
-                        r = new Resource[tmp.length + dr.length];
-                        System.arraycopy(dr, 0, r, 0, dr.length);
-                        System.arraycopy(tmp, 0, r, dr.length, tmp.length);
+                        includedResourceNames =
+                            Stream.concat(includedResourceNames,
+                                Stream.of(ds.getIncludedDirectories()));
                     }
+
+                    Resource[] r = includedResourceNames.map(ds::getResource)
+                        .toArray(Resource[]::new);
+
                     addResources(oldFiles, r, zOut);
                 }
                 if (zOut != null) {
@@ -822,16 +801,10 @@
             getProject(), "zip", ".tmp", zipFile.getParentFile(), true, false);
         try {
             FILE_UTILS.rename(zipFile, renamedFile);
-        } catch (final SecurityException e) {
+        } catch (final SecurityException | IOException e) {
             throw new BuildException(
-                "Not allowed to rename old file ("
-                + zipFile.getAbsolutePath()
-                + ") to temporary file");
-        } catch (final IOException e) {
-            throw new BuildException(
-                "Unable to rename old file ("
-                + zipFile.getAbsolutePath()
-                + ") to temporary file");
+                "Unable to rename old file (%s) to temporary file",
+                zipFile.getAbsolutePath());
         }
         return renamedFile;
     }
@@ -862,23 +835,22 @@
 
     /** Check the attributes and elements */
     private void checkAttributesAndElements() {
-        if (baseDir == null && resources.size() == 0
-            && groupfilesets.size() == 0 && "zip".equals(archiveType)) {
-            throw new BuildException("basedir attribute must be set, "
-                                     + "or at least one "
-                                     + "resource collection must be given!");
+        if (baseDir == null && resources.isEmpty() && groupfilesets.isEmpty()
+            && "zip".equals(archiveType)) {
+            throw new BuildException(
+                "basedir attribute must be set, or at least one resource collection must be given!");
         }
 
         if (zipFile == null) {
-            throw new BuildException("You must specify the "
-                                     + archiveType + " file to create!");
+            throw new BuildException("You must specify the %s file to create!",
+                archiveType);
         }
 
         if (fixedModTime != null) {
             try {
                 modTimeMillis = DateUtils.parseLenientDateTime(fixedModTime).getTime();
             } catch (ParseException pe) {
-                throw new BuildException("Failed to parse date string " + fixedModTime + ".");
+                throw new BuildException("Failed to parse date string %s.", fixedModTime);
             }
             if (roundUp) {
                 modTimeMillis += ROUNDUP_MILLIS;
@@ -886,11 +858,11 @@
         }
 
         if (zipFile.exists() && !zipFile.isFile()) {
-            throw new BuildException(zipFile + " is not a file.");
+            throw new BuildException("%s is not a file.", zipFile);
         }
 
         if (zipFile.exists() && !zipFile.canWrite()) {
-            throw new BuildException(zipFile + " is read-only.");
+            throw new BuildException("%s is read-only.", zipFile);
         }
     }
 
@@ -908,23 +880,18 @@
     /** Process groupfilesets */
     private void processGroupFilesets() {
         // Add the files found in groupfileset to fileset
-        final int size = groupfilesets.size();
-        for (int i = 0; i < size; i++) {
-
+        for (FileSet fs : groupfilesets) {
             logWhenWriting("Processing groupfileset ", Project.MSG_VERBOSE);
-            final FileSet fs = groupfilesets.elementAt(i);
             final FileScanner scanner = fs.getDirectoryScanner(getProject());
-            final String[] files = scanner.getIncludedFiles();
             final File basedir = scanner.getBasedir();
-            for (int j = 0; j < files.length; j++) {
-
-                logWhenWriting("Adding file " + files[j] + " to fileset",
+            for (String file : scanner.getIncludedFiles()) {
+                logWhenWriting("Adding file " + file + " to fileset",
                                Project.MSG_VERBOSE);
                 final ZipFileSet zf = new ZipFileSet();
                 zf.setProject(getProject());
-                zf.setSrc(new File(basedir, files[j]));
+                zf.setSrc(new File(basedir, file));
                 add(zf);
-                filesetsFromGroupfilesets.addElement(zf);
+                filesetsFromGroupfilesets.add(zf);
             }
         }
     }
@@ -967,18 +934,17 @@
             fileMode = zfs.getFileMode(getProject());
         }
 
-        if (prefix.length() > 0 && fullpath.length() > 0) {
-            throw new BuildException("Both prefix and fullpath attributes must"
-                                     + " not be set on the same fileset.");
+        if (!prefix.isEmpty() && !fullpath.isEmpty()) {
+            throw new BuildException(
+                "Both prefix and fullpath attributes must not be set on the same fileset.");
         }
 
-        if (resources.length != 1 && fullpath.length() > 0) {
-            throw new BuildException("fullpath attribute may only be specified"
-                                     + " for filesets that specify a single"
-                                     + " file.");
+        if (resources.length != 1 && !fullpath.isEmpty()) {
+            throw new BuildException(
+                "fullpath attribute may only be specified for filesets that specify a single file.");
         }
 
-        if (prefix.length() > 0) {
+        if (!prefix.isEmpty()) {
             if (!prefix.endsWith("/") && !prefix.endsWith("\\")) {
                 prefix += "/";
             }
@@ -997,26 +963,26 @@
                 zf = new ZipFile(zfs.getSrc(getProject()), encoding);
             }
 
-            for (int i = 0; i < resources.length; i++) {
-                String name = null;
-                if (fullpath.length() > 0) {
-                    name = fullpath;
+            for (Resource resource : resources) {
+                String name;
+                if (fullpath.isEmpty()) {
+                    name = resource.getName();
                 } else {
-                    name = resources[i].getName();
+                    name = fullpath;
                 }
                 name = name.replace(File.separatorChar, '/');
 
-                if ("".equals(name)) {
+                if (name.isEmpty()) {
                     continue;
                 }
 
-                if (resources[i].isDirectory()) {
+                if (resource.isDirectory()) {
                     if (doFilesonly) {
                         continue;
                     }
                     final int thisDirMode = zfs != null && zfs.hasDirModeBeenSet()
-                        ? dirMode : getUnixMode(resources[i], zf, dirMode);
-                    addDirectoryResource(resources[i], name, prefix,
+                        ? dirMode : getUnixMode(resource, zf, dirMode);
+                    addDirectoryResource(resource, name, prefix,
                                          base, zOut,
                                          dirMode, thisDirMode);
 
@@ -1026,14 +992,14 @@
 
                     if (dealingWithFiles) {
                         final File f = FILE_UTILS.resolveFile(base,
-                                                        resources[i].getName());
+                                                        resource.getName());
                         zipFile(f, zOut, prefix + name, fileMode);
                     } else {
                         final int thisFileMode =
                             zfs != null && zfs.hasFileModeBeenSet()
-                            ? fileMode : getUnixMode(resources[i], zf,
+                            ? fileMode : getUnixMode(resource, zf,
                                                      fileMode);
-                        addResource(resources[i], name, prefix,
+                        addResource(resource, name, prefix,
                                     zOut, thisFileMode, zf,
                                     zfs == null
                                     ? null : zfs.getSrc(getProject()));
@@ -1058,10 +1024,10 @@
         throws IOException {
 
         if (!name.endsWith("/")) {
-            name = name + "/";
+            name += "/";
         }
 
-        final int nextToLastSlash = name.lastIndexOf("/", name.length() - 2);
+        final int nextToLastSlash = name.lastIndexOf('/', name.length() - 2);
         if (nextToLastSlash != -1) {
             addParentDirs(base, name.substring(0, nextToLastSlash + 1),
                           zOut, prefix, defaultDirMode);
@@ -1107,25 +1073,18 @@
                 if (keepCompression) {
                     doCompress = (ze.getMethod() == ZipEntry.DEFLATED);
                 }
-                InputStream is = null;
-                try {
-                    is = new BufferedInputStream(zf.getInputStream(ze));
+                try (final BufferedInputStream is = new BufferedInputStream(zf.getInputStream(ze))) {
                     zipFile(is, zOut, prefix + name, ze.getTime(),
                             fromArchive, mode, ze.getExtraFields(true));
                 } finally {
                     doCompress = oldCompress;
-                    FileUtils.close(is);
                 }
             }
         } else {
-            InputStream is = null;
-            try {
-                is = new BufferedInputStream(r.getInputStream());
+            try (final BufferedInputStream is = new BufferedInputStream(r.getInputStream())) {
                 zipFile(is, zOut, prefix + name, r.getLastModified(),
                         fromArchive, mode, r instanceof ZipResource
                         ? ((ZipResource) r).getExtraFields() : null);
-            } finally {
-                FileUtils.close(is);
             }
         }
     }
@@ -1149,15 +1108,14 @@
             addResources((FileSet) rc, resources, zOut);
             return;
         }
-        for (int i = 0; i < resources.length; i++) {
-            final Resource resource = resources[i];
+        for (final Resource resource : resources) {
             String name = resource.getName();
             if (name == null) {
                 continue;
             }
             name = name.replace(File.separatorChar, '/');
 
-            if ("".equals(name)) {
+            if (name.isEmpty()) {
                 continue;
             }
             if (resource.isDirectory() && doFilesonly) {
@@ -1224,9 +1182,7 @@
             log("Note: creating empty " + archiveType + " archive " + zipFile,
                 Project.MSG_INFO);
         }
-        OutputStream os = null;
-        try {
-            os = new FileOutputStream(zipFile);
+        try (OutputStream os = Files.newOutputStream(zipFile.toPath())) {
             // CheckStyle:MagicNumber OFF
             // Cf. PKZIP specification.
             final byte[] empty = new byte[22];
@@ -1241,8 +1197,6 @@
             throw new BuildException("Could not create empty ZIP archive "
                                      + "(" + ioe.getMessage() + ")", ioe,
                                      getLocation());
-        } finally {
-            FileUtils.close(os);
         }
         return true;
     }
@@ -1291,22 +1245,21 @@
                                              final File zipFile,
                                              final boolean needsUpdate)
         throws BuildException {
-        final ArrayList<ResourceCollection> filesets = new ArrayList<ResourceCollection>();
-        final ArrayList<ResourceCollection> rest = new ArrayList<ResourceCollection>();
-        for (int i = 0; i < rcs.length; i++) {
-            if (rcs[i] instanceof FileSet) {
-                filesets.add(rcs[i]);
+        final List<FileSet> filesets = new ArrayList<>();
+        final List<ResourceCollection> rest = new ArrayList<>();
+        for (ResourceCollection rc : rcs) {
+            if (rc instanceof FileSet) {
+                filesets.add((FileSet) rc);
             } else {
-                rest.add(rcs[i]);
+                rest.add(rc);
             }
         }
         final ResourceCollection[] rc =
-            rest.toArray(new ResourceCollection[rest.size()]);
+            rest.toArray(new ResourceCollection[0]);
         ArchiveState as = getNonFileSetResourcesToAdd(rc, zipFile,
                                                       needsUpdate);
 
-        final FileSet[] fs = filesets.toArray(new FileSet[filesets
-                                                                .size()]);
+        final FileSet[] fs = filesets.toArray(new FileSet[0]);
         final ArchiveState as2 = getResourcesToAdd(fs, zipFile, as.isOutOfDate());
         if (!as.isOutOfDate() && as2.isOutOfDate()) {
             /*
@@ -1340,12 +1293,7 @@
      * to move the withEmpty behavior checks (since either would break
      * subclasses in several ways).
      */
-    private static final ThreadLocal<Boolean> HAVE_NON_FILE_SET_RESOURCES_TO_ADD = new ThreadLocal<Boolean>() {
-            @Override
-            protected Boolean initialValue() {
-                return Boolean.FALSE;
-            }
-        };
+    private static final ThreadLocal<Boolean> HAVE_NON_FILE_SET_RESOURCES_TO_ADD = ThreadLocal.withInitial(() -> Boolean.FALSE);
 
     /**
      * Collect the resources that are newer than the corresponding
@@ -1399,7 +1347,7 @@
                     return new ArchiveState(true, initialResources);
                 }
 
-                if (emptyBehavior.equals("skip")) {
+                if ("skip".equals(emptyBehavior)) {
                     if (doUpdate) {
                         logWhenWriting(archiveType + " archive " + zipFile
                                        + " not updated because no new files were"
@@ -1410,7 +1358,7 @@
                                        + " because no files were included.",
                                        Project.MSG_WARN);
                     }
-                } else if (emptyBehavior.equals("fail")) {
+                } else if ("fail".equals(emptyBehavior)) {
                     throw new BuildException("Cannot create " + archiveType
                                              + " archive " + zipFile
                                              + ": no files were included.",
@@ -1468,7 +1416,7 @@
             if (filesets[i] instanceof ZipFileSet) {
                 final ZipFileSet zfs = (ZipFileSet) filesets[i];
                 if (zfs.getFullpath(getProject()) != null
-                    && !zfs.getFullpath(getProject()).equals("")) {
+                    && !zfs.getFullpath(getProject()).isEmpty()) {
                     // in this case all files from origin map to
                     // the fullPath attribute of the zipfileset at
                     // destination
@@ -1477,7 +1425,7 @@
                     myMapper = fm;
 
                 } else if (zfs.getPrefix(getProject()) != null
-                           && !zfs.getPrefix(getProject()).equals("")) {
+                           && !zfs.getPrefix(getProject()).isEmpty()) {
                     final GlobPatternMapper gm = new GlobPatternMapper();
                     gm.setFrom("*");
                     String prefix = zfs.getPrefix(getProject());
@@ -1541,7 +1489,7 @@
 
         final Resource[][] initialResources = grabNonFileSetResources(rcs);
         final boolean empty = isEmpty(initialResources);
-        HAVE_NON_FILE_SET_RESOURCES_TO_ADD.set(Boolean.valueOf(!empty));
+        HAVE_NON_FILE_SET_RESOURCES_TO_ADD.set(!empty);
         if (empty) {
             // no emptyBehavior handling since the FileSet version
             // will take care of it.
@@ -1571,8 +1519,8 @@
                 final FileProvider fp =
                     initialResources[i][j].as(FileProvider.class);
                 if (fp != null && zipFile.equals(fp.getFile())) {
-                    throw new BuildException("A zip file cannot include "
-                                             + "itself", getLocation());
+                    throw new BuildException("A zip file cannot include itself",
+                        getLocation());
                 }
             }
 
@@ -1609,8 +1557,8 @@
                 ResourceUtils.selectSources(this, u, mapper,
                                             getZipScanner(),
                                             MISSING_DIR_PROVIDER);
-            if (rc.size() > 0) {
-                final ArrayList<Resource> newer = new ArrayList<Resource>();
+            if (!rc.isEmpty()) {
+                final List<Resource> newer = new ArrayList<>();
                 newer.addAll(Arrays.asList(((Union) rc).listResources()));
                 newer.addAll(Arrays.asList(result));
                 result = newer.toArray(result);
@@ -1633,32 +1581,28 @@
             boolean skipEmptyNames = true;
             if (filesets[i] instanceof ZipFileSet) {
                 final ZipFileSet zfs = (ZipFileSet) filesets[i];
-                skipEmptyNames = zfs.getPrefix(getProject()).equals("")
-                    && zfs.getFullpath(getProject()).equals("");
+                skipEmptyNames = zfs.getPrefix(getProject()).isEmpty()
+                    && zfs.getFullpath(getProject()).isEmpty();
             }
             final DirectoryScanner rs =
                 filesets[i].getDirectoryScanner(getProject());
             if (rs instanceof ZipScanner) {
                 ((ZipScanner) rs).setEncoding(encoding);
             }
-            final Vector<Resource> resources = new Vector<Resource>();
+            final List<Resource> resources = new Vector<>();
             if (!doFilesonly) {
-                final String[] directories = rs.getIncludedDirectories();
-                for (int j = 0; j < directories.length; j++) {
-                    if (!"".equals(directories[j]) || !skipEmptyNames) {
-                        resources.addElement(rs.getResource(directories[j]));
+                for (String d : rs.getIncludedDirectories()) {
+                    if (!d.isEmpty() || !skipEmptyNames) {
+                        resources.add(rs.getResource(d));
                     }
                 }
             }
-            final String[] files = rs.getIncludedFiles();
-            for (int j = 0; j < files.length; j++) {
-                if (!"".equals(files[j]) || !skipEmptyNames) {
-                    resources.addElement(rs.getResource(files[j]));
+            for (String f : rs.getIncludedFiles()) {
+                if (!f.isEmpty() || !skipEmptyNames) {
+                    resources.add(rs.getResource(f));
                 }
             }
-
-            result[i] = new Resource[resources.size()];
-            resources.copyInto(result[i]);
+            result[i] = resources.toArray(new Resource[0]);
         }
         return result;
     }
@@ -1674,27 +1618,21 @@
     protected Resource[][] grabNonFileSetResources(final ResourceCollection[] rcs) {
         final Resource[][] result = new Resource[rcs.length][];
         for (int i = 0; i < rcs.length; i++) {
-            final ArrayList<Resource> dirs = new ArrayList<Resource>();
-            final ArrayList<Resource> files = new ArrayList<Resource>();
+            final List<Resource> dirs = new ArrayList<>();
+            final List<Resource> files = new ArrayList<>();
             for (final Resource r : rcs[i]) {
-                if (r.isExists()) {
-                    if (r.isDirectory()) {
-                        dirs.add(r);
-                    } else {
-                        files.add(r);
-                    }
+                if (r.isDirectory()) {
+                    dirs.add(r);
+                } else if (r.isExists()) {
+                    files.add(r);
                 }
             }
             // make sure directories are in alpha-order - this also
             // ensures parents come before their children
-            Collections.sort(dirs, new Comparator<Resource>() {
-                    public int compare(final Resource r1, final Resource r2) {
-                        return r1.getName().compareTo(r2.getName());
-                    }
-                });
-            final ArrayList<Resource> rs = new ArrayList<Resource>(dirs);
+            dirs.sort(Comparator.comparing(Resource::getName));
+            final List<Resource> rs = new ArrayList<>(dirs);
             rs.addAll(files);
-            result[i] = rs.toArray(new Resource[rs.size()]);
+            result[i] = rs.toArray(new Resource[0]);
         }
         return result;
     }
@@ -1727,8 +1665,8 @@
     protected void zipDir(final File dir, final ZipOutputStream zOut, final String vPath,
                           final int mode, final ZipExtraField[] extra)
         throws IOException {
-        zipDir(dir == null ? (Resource) null : new FileResource(dir),
-               zOut, vPath, mode, extra);
+        zipDir(dir == null ? null : new FileResource(dir), zOut, vPath, mode,
+            extra);
     }
 
     /**
@@ -1791,7 +1729,7 @@
      * support a new parameter (extra fields to preserve) without
      * breaking subclasses that override the old method signature.
      */
-    private static final ThreadLocal<ZipExtraField[]> CURRENT_ZIP_EXTRA = new ThreadLocal<ZipExtraField[]>();
+    private static final ThreadLocal<ZipExtraField[]> CURRENT_ZIP_EXTRA = new ThreadLocal<>();
 
     /**
      * Provides the extra fields for the zip entry currently being
@@ -1835,19 +1773,19 @@
 
         if (entries.containsKey(vPath)) {
 
-            if (duplicate.equals("preserve")) {
+            if ("preserve".equals(duplicate)) {
                 logWhenWriting(vPath + " already added, skipping",
                                Project.MSG_INFO);
                 return;
-            } else if (duplicate.equals("fail")) {
-                throw new BuildException("Duplicate file " + vPath
-                                         + " was found and the duplicate "
-                                         + "attribute is 'fail'.");
-            } else {
-                // duplicate equal to add, so we continue
-                logWhenWriting("duplicate file " + vPath
-                               + " found, adding.", Project.MSG_VERBOSE);
             }
+            if ("fail".equals(duplicate)) {
+                throw new BuildException(
+                    "Duplicate file %s was found and the duplicate attribute is 'fail'.",
+                    vPath);
+            }
+            // duplicate equal to add, so we continue
+            logWhenWriting("duplicate file " + vPath
+                           + " found, adding.", Project.MSG_VERBOSE);
         } else {
             logWhenWriting("adding entry " + vPath, Project.MSG_VERBOSE);
         }
@@ -1904,7 +1842,7 @@
                 count = markableInputStream.read(buffer, 0, buffer.length);
             } while (count != -1);
         }
-        addedFiles.addElement(vPath);
+        addedFiles.add(vPath);
     }
 
     /**
@@ -1957,14 +1895,11 @@
                                      getLocation());
         }
 
-        final BufferedInputStream bIn = new BufferedInputStream(new FileInputStream(file));
-        try {
+        try (final BufferedInputStream bIn = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
             // ZIPs store time with a granularity of 2 seconds, round up
             zipFile(bIn, zOut, vPath,
                     file.lastModified() + (roundUp ? ROUNDUP_MILLIS : 0),
                     null, mode);
-        } finally {
-            bIn.close();
         }
     }
 
@@ -1983,7 +1918,7 @@
                                        final int dirMode)
         throws IOException {
         if (!doFilesonly) {
-            final Stack<String> directories = new Stack<String>();
+            final Stack<String> directories = new Stack<>();
             int slashPos = entry.length();
 
             while ((slashPos = entry.lastIndexOf('/', slashPos - 1)) != -1) {
@@ -1996,7 +1931,7 @@
 
             while (!directories.isEmpty()) {
                 final String dir = directories.pop();
-                File f = null;
+                File f;
                 if (baseDir != null) {
                     f = new File(baseDir, dir);
                 } else {
@@ -2023,16 +1958,12 @@
      */
     protected void cleanUp() {
         addedDirs.clear();
-        addedFiles.removeAllElements();
+        addedFiles.clear();
         entries.clear();
         addingNewFiles = false;
         doUpdate = savedDoUpdate;
-        final Enumeration<ZipFileSet> e = filesetsFromGroupfilesets.elements();
-        while (e.hasMoreElements()) {
-            final ZipFileSet zf = e.nextElement();
-            resources.removeElement(zf);
-        }
-        filesetsFromGroupfilesets.removeAllElements();
+        resources.removeAll(filesetsFromGroupfilesets);
+        filesetsFromGroupfilesets.clear();
         HAVE_NON_FILE_SET_RESOURCES_TO_ADD.set(Boolean.FALSE);
     }
 
@@ -2045,10 +1976,10 @@
      * @see #cleanUp
      */
     public void reset() {
-        resources.removeAllElements();
+        resources.clear();
         zipFile = null;
         baseDir = null;
-        groupfilesets.removeAllElements();
+        groupfilesets.clear();
         duplicate = "add";
         archiveType = "zip";
         doCompress = true;
@@ -2066,8 +1997,8 @@
      * @since Ant 1.5.2
      */
     protected static final boolean isEmpty(final Resource[][] r) {
-        for (int i = 0; i < r.length; i++) {
-            if (r[i].length > 0) {
+        for (Resource[] element : r) {
+            if (element.length > 0) {
                 return false;
             }
         }
@@ -2082,19 +2013,18 @@
      */
     protected Resource[] selectFileResources(final Resource[] orig) {
         return selectResources(orig,
-                               new ResourceSelector() {
-                                   public boolean isSelected(final Resource r) {
-                                       if (!r.isDirectory()) {
-                                           return true;
-                                       } else if (doFilesonly) {
-                                           logWhenWriting("Ignoring directory "
-                                                          + r.getName()
-                                                          + " as only files will"
-                                                          + " be added.",
-                                                          Project.MSG_VERBOSE);
-                                       }
-                                       return false;
+                               r -> {
+                                   if (!r.isDirectory()) {
+                                       return true;
                                    }
+                                   if (doFilesonly) {
+                                       logWhenWriting("Ignoring directory "
+                                                      + r.getName()
+                                                      + " as only files will"
+                                                      + " be added.",
+                                                      Project.MSG_VERBOSE);
+                                   }
+                                   return false;
                                });
     }
 
@@ -2105,12 +2035,7 @@
      * @since Ant 1.8.0
      */
     protected Resource[] selectDirectoryResources(final Resource[] orig) {
-        return selectResources(orig,
-                               new ResourceSelector() {
-                                   public boolean isSelected(final Resource r) {
-                                       return r.isDirectory();
-                                   }
-                               });
+        return selectResources(orig, Resource::isDirectory);
     }
 
     /**
@@ -2125,18 +2050,9 @@
         if (orig.length == 0) {
             return orig;
         }
-
-        final ArrayList<Resource> v = new ArrayList<Resource>(orig.length);
-        for (int i = 0; i < orig.length; i++) {
-            if (selector.isSelected(orig[i])) {
-                v.add(orig[i]);
-            }
-        }
-
-        if (v.size() != orig.length) {
-            return v.toArray(new Resource[v.size()]);
-        }
-        return orig;
+        Resource[] result = Stream.of(orig).filter(selector::isSelected)
+            .toArray(Resource[]::new);
+        return result.length == orig.length ? orig : result;
     }
 
     /**
@@ -2207,11 +2123,9 @@
             if (resourcesToAdd == null)  {
                 return true;
             }
-            for (int counter = 0; counter < resourcesToAdd.length; counter++) {
-                if (resourcesToAdd[counter] != null) {
-                    if (resourcesToAdd[counter].length > 0) {
-                        return false;
-                    }
+            for (Resource[] element : resourcesToAdd) {
+                if (element != null && element.length > 0) {
+                    return false;
                 }
             }
             return true;
@@ -2225,7 +2139,7 @@
      * @since Ant 1.8.0
      */
     public static final class UnicodeExtraField extends EnumeratedAttribute {
-        private static final Map<String, UnicodeExtraFieldPolicy> POLICIES = new HashMap<String, UnicodeExtraFieldPolicy>();
+        private static final Map<String, UnicodeExtraFieldPolicy> POLICIES = new HashMap<>();
         private static final String NEVER_KEY = "never";
         private static final String ALWAYS_KEY = "always";
         private static final String N_E_KEY = "not-encodeable";
@@ -2259,7 +2173,6 @@
         }
     }
 
-
     /**
      * The choices for Zip64 extensions.
      *
@@ -2281,13 +2194,13 @@
      * central directory - which is what <em>as-needed</em> may result
      * in.  Java5 and Microsoft Visual Studio's Extension loader are
      * known to fconsider the archive broken in such cases.  If you
-     * are targeting such an archiver uset the value <em>never</em>
+     * are targeting such an archiver use the value <em>never</em>
      * unless you know you need Zip64 extensions.</p>
      *
      * @since Ant 1.9.1
      */
     public static final class Zip64ModeAttribute extends EnumeratedAttribute {
-        private static final Map<String, Zip64Mode> MODES = new HashMap<String, Zip64Mode>();
+        private static final Map<String, Zip64Mode> MODES = new HashMap<>();
 
         private static final String NEVER_KEY = "never";
         private static final String ALWAYS_KEY = "always";
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/compilers/CompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapter.java
index 5a275b8..93107db 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterExtension.java b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterExtension.java
index 038b9cb..62599a5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterExtension.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterExtension.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java
index 3fc60f7..a7087bf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -176,59 +176,49 @@
      * @since Ant 1.8.0
      */
     public static CompilerAdapter getCompiler(String compilerType, Task task,
-                                              Path classpath)
-        throws BuildException {
-            if (compilerType.equalsIgnoreCase(COMPILER_JIKES)) {
-                return new Jikes();
-            }
-            if (isForkedJavac(compilerType)) {
-                return new JavacExternal();
-            }
-            if (compilerType.equalsIgnoreCase(COMPILER_CLASSIC)
-                || isClassicJdkCompiler(compilerType)) {
-                task.log("This version of java does "
-                                         + "not support the classic "
-                                         + "compiler; upgrading to modern",
-                                         Project.MSG_WARN);
-                compilerType = COMPILER_MODERN;
-            }
-            if (compilerType.equalsIgnoreCase(COMPILER_MODERN)
-                || isModernJdkCompiler(compilerType)) {
-                // does the modern compiler exist?
-                if (doesModernCompilerExist()) {
-                    return new Javac13();
-                } else {
-                    throw new BuildException("Unable to find a javac "
-                                             + "compiler;\n"
-                                             + MODERN_COMPILER
-                                             + " is not on the "
-                                             + "classpath.\n"
-                                             + "Perhaps JAVA_HOME does not"
-                                             + " point to the JDK.\n"
-                            + "It is currently set to \""
-                            + JavaEnvUtils.getJavaHome()
-                            + "\"");
-                }
-            }
-
-            if (compilerType.equalsIgnoreCase(COMPILER_JVC)
-                || compilerType.equalsIgnoreCase(COMPILER_JVC_ALIAS)) {
-                return new Jvc();
-            }
-            if (compilerType.equalsIgnoreCase(COMPILER_KJC)) {
-                return new Kjc();
-            }
-            if (compilerType.equalsIgnoreCase(COMPILER_GCJ)) {
-                return new Gcj();
-            }
-            if (compilerType.equalsIgnoreCase(COMPILER_SYMANTEC_ALIAS)
-                || compilerType.equalsIgnoreCase(COMPILER_SYMANTEC)) {
-                return new Sj();
-            }
-            return resolveClassName(compilerType,
-                                    // Memory-Leak in line below
-                                task.getProject().createClassLoader(classpath));
+        Path classpath) throws BuildException {
+        if (COMPILER_JIKES.equalsIgnoreCase(compilerType)) {
+            return new Jikes();
         }
+        if (isForkedJavac(compilerType)) {
+            return new JavacExternal();
+        }
+        if (COMPILER_CLASSIC.equalsIgnoreCase(compilerType)
+            || isClassicJdkCompiler(compilerType)) {
+            task.log(
+                "This version of java does not support the classic compiler; upgrading to modern",
+                Project.MSG_WARN);
+            compilerType = COMPILER_MODERN;
+        }
+        if (COMPILER_MODERN.equalsIgnoreCase(compilerType)
+            || isModernJdkCompiler(compilerType)) {
+            // does the modern compiler exist?
+            if (doesModernCompilerExist()) {
+                return new Javac13();
+            }
+            throw new BuildException(
+                "Unable to find a javac compiler;\n%s is not on the classpath.\nPerhaps JAVA_HOME does not point to the JDK.\nIt is currently set to \"%s\"",
+                MODERN_COMPILER, JavaEnvUtils.getJavaHome());
+        }
+
+        if (COMPILER_JVC.equalsIgnoreCase(compilerType)
+            || COMPILER_JVC_ALIAS.equalsIgnoreCase(compilerType)) {
+            return new Jvc();
+        }
+        if (COMPILER_KJC.equalsIgnoreCase(compilerType)) {
+            return new Kjc();
+        }
+        if (COMPILER_GCJ.equalsIgnoreCase(compilerType)) {
+            return new Gcj();
+        }
+        if (COMPILER_SYMANTEC_ALIAS.equalsIgnoreCase(compilerType)
+            || COMPILER_SYMANTEC.equalsIgnoreCase(compilerType)) {
+            return new Sj();
+        }
+        return resolveClassName(compilerType,
+            // Memory-Leak in line below
+            task.getProject().createClassLoader(classpath));
+    }
 
     /**
      * query for the Modern compiler existing
@@ -264,7 +254,7 @@
     private static CompilerAdapter resolveClassName(String className,
                                                     ClassLoader loader)
         throws BuildException {
-        return (CompilerAdapter) ClasspathUtils.newInstance(className,
+        return ClasspathUtils.newInstance(className,
                 loader != null ? loader :
                 CompilerAdapterFactory.class.getClassLoader(),
                 CompilerAdapter.class);
@@ -274,7 +264,7 @@
      * Is the compiler implementation a forked jdk compiler?
      *
      * @param compilerImpl the name of the compiler implementation
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public static boolean isForkedJavac(final String compilerName) {
         return containsIgnoreCase(FORKED_JDK_COMPILERS, compilerName);
@@ -284,7 +274,7 @@
      * Is the compiler implementation a jdk compiler?
      *
      * @param compilerImpl the name of the compiler implementation
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public static boolean isJdkCompiler(final String compilerName) {
         return containsIgnoreCase(JDK_COMPILERS, compilerName);
@@ -294,7 +284,7 @@
      * Is the compiler implementation a jdk compiler without specified version?
      *
      * @param compilerImpl the name of the compiler implementation
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public static boolean isJdkCompilerNickname(final String compilerName) {
         return containsIgnoreCase(JDK_COMPILER_NICKNAMES, compilerName);
@@ -304,7 +294,7 @@
      * Does the compiler correspond to "classic"?
      *
      * @param compilerImpl the name of the compiler implementation
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public static boolean isClassicJdkCompiler(final String compilerName) {
         return containsIgnoreCase(CLASSIC_JDK_COMPILERS, compilerName);
@@ -314,18 +304,13 @@
      * Does the compiler correspond to "modern"?
      *
      * @param compilerImpl the name of the compiler implementation
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public static boolean isModernJdkCompiler(final String compilerName) {
         return containsIgnoreCase(MODERN_JDK_COMPILERS, compilerName);
     }
 
     private static boolean containsIgnoreCase(final List<String> compilers, final String compilerName) {
-        for (String compiler : compilers) {
-            if (compiler.equalsIgnoreCase(compilerName)) {
-                return true;
-            }
-        }
-        return false;
+        return compilerName != null && compilers.stream().anyMatch(compilerName::equalsIgnoreCase);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
index 9046e24..cf3ec45 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,14 @@
 
 package org.apache.tools.ant.taskdefs.compilers;
 
-//Java5 style
-//import static org.apache.tools.ant.util.StringUtils.LINE_SEP;
-
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Location;
@@ -61,6 +62,14 @@
 
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
+    //must keep for subclass BC, though unused:
+    // CheckStyle:ConstantNameCheck OFF - bc
+    @Deprecated
+    protected static final String lSep = StringUtils.LINE_SEP;
+    // CheckStyle:ConstantNameCheck ON
+
+    private static final Pattern JAVAC_ARG_FILE_CHARS_TO_QUOTE = Pattern.compile("[ #]"); // space or # character
+
     protected Path src;
     protected File destDir;
     protected String encoding;
@@ -88,11 +97,6 @@
     protected File[] compileList;
     protected Javac attributes;
 
-    //must keep for subclass BC, though unused:
-    // CheckStyle:ConstantNameCheck OFF - bc
-    protected static final String lSep = StringUtils.LINE_SEP;
-
-    // CheckStyle:ConstantNameCheck ON
     // CheckStyle:VisibilityModifier ON
 
     /**
@@ -101,6 +105,7 @@
      *
      * @param attributes a configured Javac task.
      */
+    @Override
     public void setJavac(final Javac attributes) {
         this.attributes = attributes;
         src = attributes.getSrcdir();
@@ -147,6 +152,7 @@
      * but specialized compilers can recognize multiple kinds
      * of files.
      */
+    @Override
     public String[] getSupportedFileExtensions() {
         return new String[] {"java"};
     }
@@ -254,19 +260,20 @@
         final Path classpath = getCompileClasspath();
         // For -sourcepath, use the "sourcepath" value if present.
         // Otherwise default to the "srcdir" value.
-        Path sourcepath = null;
+        Path sourcepath;
         if (compileSourcepath != null) {
             sourcepath = compileSourcepath;
         } else {
             sourcepath = src;
         }
 
-        final String memoryParameterPrefix = assumeJava11() ? "-J-" : "-J-X";
+        final String memoryParameterPrefix = assumeJava1_2Plus() ? "-J-X" : "-J-";
+
         if (memoryInitialSize != null) {
             if (!attributes.isForkedJavac()) {
-                attributes.log("Since fork is false, ignoring "
-                               + "memoryInitialSize setting.",
-                               Project.MSG_WARN);
+                attributes.log(
+                    "Since fork is false, ignoring memoryInitialSize setting.",
+                    Project.MSG_WARN);
             } else {
                 cmd.createArgument().setValue(memoryParameterPrefix
                                               + "ms" + memoryInitialSize);
@@ -275,9 +282,9 @@
 
         if (memoryMaximumSize != null) {
             if (!attributes.isForkedJavac()) {
-                attributes.log("Since fork is false, ignoring "
-                               + "memoryMaximumSize setting.",
-                               Project.MSG_WARN);
+                attributes.log(
+                    "Since fork is false, ignoring memoryMaximumSize setting.",
+                    Project.MSG_WARN);
             } else {
                 cmd.createArgument().setValue(memoryParameterPrefix
                                               + "mx" + memoryMaximumSize);
@@ -301,13 +308,9 @@
 
         // Just add "sourcepath" to classpath (for JDK1.1)
         // as well as "bootclasspath" and "extdirs"
-        if (assumeJava11()) {
+        if (!assumeJava1_2Plus()) {
             final Path cp = new Path(project);
-
-            final Path bp = getBootClassPath();
-            if (bp.size() > 0) {
-                cp.append(bp);
-            }
+            Optional.ofNullable(getBootClassPath()).ifPresent(cp::append);
 
             if (extdirs != null) {
                 cp.addExtdirs(extdirs);
@@ -330,13 +333,13 @@
                 }
 
                 final Path bp = getBootClassPath();
-                if (bp.size() > 0) {
+                if (!bp.isEmpty()) {
                     cmd.createArgument().setValue("-bootclasspath");
                     cmd.createArgument().setPath(bp);
                 }
             }
 
-            if (extdirs != null && extdirs.size() > 0) {
+            if (extdirs != null && !extdirs.isEmpty()) {
                 cmd.createArgument().setValue("-extdirs");
                 cmd.createArgument().setPath(extdirs);
             }
@@ -347,7 +350,7 @@
             cmd.createArgument().setValue(encoding);
         }
         if (debug) {
-            if (useDebugLevel && !assumeJava11()) {
+            if (useDebugLevel && assumeJava1_2Plus()) {
                 final String debugLevel = attributes.getDebugLevel();
                 if (debugLevel != null) {
                     cmd.createArgument().setValue("-g:" + debugLevel);
@@ -365,13 +368,14 @@
         }
 
         if (depend) {
-            if (assumeJava11()) {
+        	if (assumeJava1_3Plus()) {
+        		attributes.log(
+                        "depend attribute is not supported by the modern compiler",
+                        Project.MSG_WARN);
+        	} else if (assumeJava1_2Plus()) {
+        		cmd.createArgument().setValue("-Xdepend");
+        	} else { //java 1.1
                 cmd.createArgument().setValue("-depend");
-            } else if (assumeJava12()) {
-                cmd.createArgument().setValue("-Xdepend");
-            } else {
-                attributes.log("depend attribute is not supported by the "
-                               + "modern compiler", Project.MSG_WARN);
             }
         }
 
@@ -392,13 +396,13 @@
      */
     protected Commandline setupModernJavacCommandlineSwitches(final Commandline cmd) {
         setupJavacCommandlineSwitches(cmd, true);
-        if (!assumeJava13()) { // -source added with JDK 1.4
+        if (assumeJava1_4Plus()) { // -source added with JDK 1.4
             final String t = attributes.getTarget();
             final String s = attributes.getSource();
             if (release == null || !assumeJava9Plus()) {
                 if (release != null) {
-                    attributes.log("Support for javac --release has been added"
-                                   + " in Java9 ignoring it");
+                    attributes.log(
+                        "Support for javac --release has been added in Java9 ignoring it");
                 }
                 if (s != null) {
                     cmd.createArgument().setValue("-source");
@@ -409,34 +413,33 @@
                 }
             } else { // Java 9+ and release has been set
                 if (t != null || s != null || getBootClassPath().size() > 0) {
-                    attributes.log("Ignoring source, target and bootclasspath"
-                                   + " as release has been set",
-                                   Project.MSG_WARN);
+                    attributes.log(
+                        "Ignoring source, target and bootclasspath as release has been set",
+                        Project.MSG_WARN);
                 }
                 cmd.createArgument().setValue("--release");
                 cmd.createArgument().setValue(release);
             }
         }
         final Path msp = getModulesourcepath();
-        if (msp.size() > 0) {
+        if (!msp.isEmpty()) {
             cmd.createArgument().setValue("--module-source-path");
             cmd.createArgument().setPath(msp);
         }
         final Path mp = getModulepath();
-        if (mp.size() > 0) {
+        if (!mp.isEmpty()) {
             cmd.createArgument().setValue("--module-path");
             cmd.createArgument().setPath(mp);
         }
         final Path ump = getUpgrademodulepath();
-        if (ump.size() > 0) {
+        if (!ump.isEmpty()) {
             cmd.createArgument().setValue("--upgrade-module-path");
             cmd.createArgument().setPath(ump);
         }
         if (attributes.getNativeHeaderDir() != null) {
-            if (assumeJava13() || assumeJava14() || assumeJava15() || assumeJava16()
-                    || assumeJava17()) {
-                attributes.log("Support for javac -h has been added in Java8,"
-                               + " ignoring it");
+            if (!assumeJava1_8Plus()) {
+                attributes.log(
+                    "Support for javac -h has been added in Java8, ignoring it");
             } else {
                 cmd.createArgument().setValue("-h");
                 cmd.createArgument().setFile(attributes.getNativeHeaderDir());
@@ -487,23 +490,13 @@
     protected void logAndAddFilesToCompile(final Commandline cmd) {
         attributes.log("Compilation " + cmd.describeArguments(), Project.MSG_VERBOSE);
 
-        final StringBuffer niceSourceList = new StringBuffer("File");
-        if (compileList.length != 1) {
-            niceSourceList.append("s");
-        }
-        niceSourceList.append(" to be compiled:");
+        attributes.log(String.format("%s to be compiled:",
+                compileList.length == 1 ? "File" : "Files"), Project.MSG_VERBOSE);
 
-        niceSourceList.append(StringUtils.LINE_SEP);
-
-        for (int i = 0; i < compileList.length; i++) {
-            final String arg = compileList[i].getAbsolutePath();
-            cmd.createArgument().setValue(arg);
-            niceSourceList.append("    ");
-            niceSourceList.append(arg);
-            niceSourceList.append(StringUtils.LINE_SEP);
-        }
-
-        attributes.log(niceSourceList.toString(), Project.MSG_VERBOSE);
+        attributes.log(Stream.of(compileList).map(File::getAbsolutePath)
+                        .peek(arg -> cmd.createArgument().setValue(arg))
+                        .map(arg -> String.format("    %s%n", arg))
+                        .collect(Collectors.joining("")), Project.MSG_VERBOSE);
     }
 
     /**
@@ -553,29 +546,30 @@
              */
             if (Commandline.toString(args).length() > COMMAND_LINE_LIMIT
                 && firstFileName >= 0) {
-                BufferedWriter out = null;
                 try {
                     tmpFile = FILE_UTILS.createTempFile(
                         getProject(), "files", "", getJavac().getTempdir(), true, true);
-                    out = new BufferedWriter(new FileWriter(tmpFile));
-                    for (int i = firstFileName; i < args.length; i++) {
-                        if (quoteFiles && args[i].contains(" ")) {
-                            args[i] = args[i].replace(File.separatorChar, '/');
-                            out.write("\"" + args[i] + "\"");
-                        } else {
-                            out.write(args[i]);
+                    try (BufferedWriter out =
+                        new BufferedWriter(new FileWriter(tmpFile))) {
+                        for (int i = firstFileName; i < args.length; i++) {
+                            if (quoteFiles && JAVAC_ARG_FILE_CHARS_TO_QUOTE.matcher(args[i]).find()) {
+                                args[i] =
+                                    args[i].replace(File.separatorChar, '/');
+                                out.write("\"" + args[i] + "\"");
+                            } else {
+                                out.write(args[i]);
+                            }
+                            out.newLine();
                         }
-                        out.newLine();
+                        out.flush();
+                        commandArray = new String[firstFileName + 1];
+                        System.arraycopy(args, 0, commandArray, 0,
+                            firstFileName);
+                        commandArray[firstFileName] = "@" + tmpFile;
                     }
-                    out.flush();
-                    commandArray = new String[firstFileName + 1];
-                    System.arraycopy(args, 0, commandArray, 0, firstFileName);
-                    commandArray[firstFileName] = "@" + tmpFile;
                 } catch (final IOException e) {
                     throw new BuildException("Error creating temporary file",
                                              e, location);
-                } finally {
-                    FileUtils.close(out);
                 }
             } else {
                 commandArray = args;
@@ -630,118 +624,226 @@
      * Shall we assume JDK 1.1 command line switches?
      * @return true if jdk 1.1
      * @since Ant 1.5
+     * @deprecated since Ant 1.10.7, use assumeJava1_1Plus, if necessary combined with !assumeJava1_2Plus
      */
+    @Deprecated
     protected boolean assumeJava11() {
-        return CompilerAdapterFactory.COMPILER_JAVAC_1_1
-            .equalsIgnoreCase(attributes.getCompilerVersion());
+        return assumeJava1_1Plus() && !assumeJava1_2Plus();
     }
-
+    
+    /**
+     * Shall we assume JDK 1.1+ command line switches?
+     * @return true if jdk 1.1 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_1Plus() {
+        return CompilerAdapterFactory.COMPILER_JAVAC_1_1
+            .equalsIgnoreCase(attributes.getCompilerVersion())
+            || assumeJava1_2Plus();
+    }
+    
     /**
      * Shall we assume JDK 1.2 command line switches?
      * @return true if jdk 1.2
      * @since Ant 1.5
+     * @deprecated since Ant 1.10.7, use assumeJava1_2Plus, if necessary combined with !assumeJava1_3Plus
      */
+    @Deprecated
     protected boolean assumeJava12() {
-        return CompilerAdapterFactory.COMPILER_JAVAC_1_2
-            .equalsIgnoreCase(attributes.getCompilerVersion());
+    	return assumeJava1_2Plus() && !assumeJava1_3Plus();
     }
 
     /**
+     * Shall we assume JDK 1.2+ command line switches?
+     * @return true if jdk 1.2 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_2Plus() {
+        return CompilerAdapterFactory.COMPILER_JAVAC_1_2
+            .equalsIgnoreCase(attributes.getCompilerVersion())
+            || assumeJava1_3Plus();
+    }
+    
+    /**
      * Shall we assume JDK 1.3 command line switches?
      * @return true if jdk 1.3
      * @since Ant 1.5
+     * @deprecated since Ant 1.10.7, use assumeJava1_3Plus, if necessary combined with !assumeJava1_4Plus
      */
+    @Deprecated
     protected boolean assumeJava13() {
-        return CompilerAdapterFactory.COMPILER_JAVAC_1_3
-            .equalsIgnoreCase(attributes.getCompilerVersion());
+    	return assumeJava1_3Plus() && !assumeJava1_4Plus();
     }
 
     /**
+     * Shall we assume JDK 1.3+ command line switches?
+     * @return true if jdk 1.3 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_3Plus() {
+        return CompilerAdapterFactory.COMPILER_JAVAC_1_3
+            .equalsIgnoreCase(attributes.getCompilerVersion())
+            || assumeJava1_4Plus();
+    }
+    
+    /**
      * Shall we assume JDK 1.4 command line switches?
      * @return true if jdk 1.4
      * @since Ant 1.6.3
+     * @deprecated since Ant 1.10.7, use assumeJava1_4Plus, if necessary combined with !assumeJava1_5Plus
      */
+    @Deprecated
     protected boolean assumeJava14() {
-        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_4, JavaEnvUtils.JAVA_1_4);
+    	return assumeJava1_4Plus() && !assumeJava1_5Plus();
+    }
+    
+    /**
+     * Shall we assume JDK 1.4+ command line switches?
+     * @return true if jdk 1.4 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_4Plus() {
+        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_4, JavaEnvUtils.JAVA_1_4)
+             || assumeJava1_5Plus();
     }
 
     /**
      * Shall we assume JDK 1.5 command line switches?
      * @return true if JDK 1.5
      * @since Ant 1.6.3
+     * @deprecated since Ant 1.10.7, use assumeJava1_5Plus, if necessary combined with !assumeJava1_6Plus
      */
+    @Deprecated
     protected boolean assumeJava15() {
-        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_5, JavaEnvUtils.JAVA_1_5);
+    	return assumeJava1_5Plus() && !assumeJava1_6Plus();
+    }
+    
+    /**
+     * Shall we assume JDK 1.5+ command line switches?
+     * @return true if jdk 1.5 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_5Plus() {
+        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_5, JavaEnvUtils.JAVA_1_5)
+            || assumeJava1_6Plus();
     }
 
     /**
      * Shall we assume JDK 1.6 command line switches?
      * @return true if JDK 1.6
      * @since Ant 1.7
+     * @deprecated since Ant 1.10.7, use assumeJava1_6Plus, if necessary combined with !assumeJava1_7Plus
      */
+    @Deprecated
     protected boolean assumeJava16() {
-        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_6, JavaEnvUtils.JAVA_1_6);
+    	return assumeJava1_6Plus() && !assumeJava1_7Plus();
     }
 
     /**
+     * Shall we assume JDK 1.6+ command line switches?
+     * @return true if jdk 1.6 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_6Plus() {
+        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_6, JavaEnvUtils.JAVA_1_6)
+            || assumeJava1_7Plus() ;
+    }
+    
+    /**
      * Shall we assume JDK 1.7 command line switches?
      * @return true if JDK 1.7
      * @since Ant 1.8.2
+     * @deprecated since Ant 1.10.7, use assumeJava1_7Plus, if necessary combined with !assumeJava1_8Plus
      */
+    @Deprecated
     protected boolean assumeJava17() {
-        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_7, JavaEnvUtils.JAVA_1_7);
+    	return assumeJava1_7Plus() && !assumeJava1_8Plus();
+    }
+    
+    /**
+     * Shall we assume JDK 1.7+ command line switches?
+     * @return true if jdk 1.7 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_7Plus() {
+        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_7, JavaEnvUtils.JAVA_1_7)
+             || assumeJava1_8Plus();
     }
 
     /**
      * Shall we assume JDK 1.8 command line switches?
      * @return true if JDK 1.8
      * @since Ant 1.8.3
+     * @deprecated since Ant 1.10.7, use assumeJava1_8Plus, if necessary combined with !assumeJava9Plus
      */
+    @Deprecated
     protected boolean assumeJava18() {
-        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_8, JavaEnvUtils.JAVA_1_8);
+    	return assumeJava1_8Plus() && !assumeJava9Plus();
     }
 
     /**
+     * Shall we assume JDK 1.8+ command line switches?
+     * @return true if jdk 1.8 and above
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava1_8Plus() {
+        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_1_8, JavaEnvUtils.JAVA_1_8)
+            || assumeJava9Plus();
+    }
+    
+    /**
      * Shall we assume JDK 9 command line switches?
      * @return true if JDK 9
      * @since Ant 1.9.4
      * @deprecated use #assumeJava9 instead
      */
+    @Deprecated
     protected boolean assumeJava19() {
-        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_9, JavaEnvUtils.JAVA_9)
-            || assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_9_ALIAS, JavaEnvUtils.JAVA_9);
+    	return assumeJava9();
     }
 
     /**
      * Shall we assume JDK 9 command line switches?
      * @return true if JDK 9
      * @since Ant 1.9.8
+     * @deprecated since Ant 1.10.7, use assumeJava9Plus, in the future if necessary combined with !assumeJava10Plus
      */
+    @Deprecated
     protected boolean assumeJava9() {
-        return assumeJava19();
+        return assumeJava9Plus() && !assumeJava10Plus();
     }
 
     /**
      * Shall we assume JDK 9+ command line switches?
      * @return true if JDK 9+
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     protected boolean assumeJava9Plus() {
-        return CompilerAdapterFactory.COMPILER_JAVAC_9.equalsIgnoreCase(attributes.getCompilerVersion())
-            || CompilerAdapterFactory.COMPILER_JAVAC_9_ALIAS.equalsIgnoreCase(attributes.getCompilerVersion())
-            || CompilerAdapterFactory.COMPILER_JAVAC_10_PLUS.equalsIgnoreCase(attributes.getCompilerVersion())
-            || (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)
-                && CompilerAdapterFactory.isJdkCompilerNickname(attributes.getCompilerVersion()));
+        return assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_9, JavaEnvUtils.JAVA_9)
+            || assumeJavaXY(CompilerAdapterFactory.COMPILER_JAVAC_9_ALIAS, JavaEnvUtils.JAVA_9)
+            || assumeJava10Plus();
     }
 
     /**
+     * Shall we assume JDK 10+ command line switches?
+     * @return true if JDK 10+
+     * @since Ant 1.10.7
+     */
+    protected boolean assumeJava10Plus() {
+        return CompilerAdapterFactory.COMPILER_JAVAC_10_PLUS.equalsIgnoreCase(attributes.getCompilerVersion())
+                || (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_10)
+                    && CompilerAdapterFactory.isJdkCompilerNickname(attributes.getCompilerVersion()));
+    }
+    
+    /**
      * Shall we assume command line switches for the given version of Java?
      * @since Ant 1.8.3
      */
     private boolean assumeJavaXY(final String javacXY, final String javaEnvVersionXY) {
-        return javacXY.equalsIgnoreCase(attributes.getCompilerVersion())
-            || (JavaEnvUtils.isJavaVersion(javaEnvVersionXY)
-                && CompilerAdapterFactory.isJdkCompilerNickname(attributes.getCompilerVersion()));
+        String compilerVersion = attributes.getCompilerVersion();
+        return javacXY.equalsIgnoreCase(compilerVersion) ||
+                (JavaEnvUtils.isJavaVersion(javaEnvVersionXY)
+                 && CompilerAdapterFactory.isJdkCompilerNickname(attributes.getCompilerVersion()));
     }
 
     /**
@@ -770,7 +872,7 @@
      * @since Ant 1.6.3
      */
     protected String getNoDebugArgument() {
-        return assumeJava11() ? null : "-g:none";
+    	return assumeJava1_2Plus() ? "-g:none" : null;
     }
 
     private void setImplicitSourceSwitch(final Commandline cmd,
@@ -796,18 +898,18 @@
      * selected JDK's javac.
      */
     private String getDefaultSource() {
-        if (assumeJava15() || assumeJava16()) {
-            return "1.5 in JDK 1.5 and 1.6";
-        }
-        if (assumeJava17()) {
-            return "1.7 in JDK 1.7";
-        }
-        if (assumeJava18()) {
-            return "1.8 in JDK 1.8";
-        }
         if (assumeJava9Plus()) {
             return "9 in JDK 9";
         }
+        if (assumeJava1_8Plus()) {
+            return "1.8 in JDK 1.8";
+        }
+        if (assumeJava1_7Plus()) {
+            return "1.7 in JDK 1.7";
+        }
+        if (assumeJava1_5Plus()) {
+            return "1.5 in JDK 1.5 and 1.6";
+        }
         return "";
     }
 
@@ -821,29 +923,27 @@
      * @param t the -target value, must not be null
      */
     private boolean mustSetSourceForTarget(String t) {
-        if (assumeJava14()) {
+        if (!assumeJava1_5Plus()) {
             return false;
         }
         if (t.startsWith("1.")) {
             t = t.substring(2);
         }
-        return t.equals("1") || t.equals("2") || t.equals("3") || t.equals("4")
-            || ((t.equals("5") || t.equals("6")) && !assumeJava15() && !assumeJava16())
-            || (t.equals("7") && !assumeJava17())
-            || (t.equals("8") && !assumeJava18())
-            || (t.equals("9") && !assumeJava9Plus());
+        return "1".equals(t) || "2".equals(t) || "3".equals(t) || "4".equals(t)
+                || (("5".equals(t) || "6".equals(t)) && assumeJava1_7Plus())
+                || ("7".equals(t) && assumeJava1_8Plus())
+                || ("8".equals(t) && assumeJava9Plus())
+                || ("9".equals(t) && assumeJava10Plus());
     }
 
-
     /**
-     * Turn the task's attribute for -source into soemthing that is
+     * Turn the task's attribute for -source into something that is
      * understood by all javac's after 1.4.
      *
      * <p>support for -source 1.1 and -source 1.2 has been added with
      * JDK 1.4.2 but isn't present in 1.5.0+</p>
      */
     private String adjustSourceValue(final String source) {
-        return (source.equals("1.1") || source.equals("1.2")) ? "1.3" : source;
+        return "1.1".equals(source) || "1.2".equals(source) ? "1.3" : source;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Gcj.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Gcj.java
index a665e47..0d48286 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Gcj.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Gcj.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,16 +31,17 @@
  * @since Ant 1.4
  */
 public class Gcj extends DefaultCompilerAdapter {
+    private static final String[] CONFLICT_WITH_DASH_C = {"-o", "--main=", "-D", "-fjni", "-L"};
 
     /**
      * Performs a compile using the gcj compiler.
      * @return true if the compilation succeeded
      * @throws BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
-        Commandline cmd;
         attributes.log("Using gcj compiler", Project.MSG_VERBOSE);
-        cmd = setupGCJCommand();
+        Commandline cmd = setupGCJCommand();
 
         int firstFileName = cmd.size();
         logAndAddFilesToCompile(cmd);
@@ -60,7 +61,7 @@
         // gcj doesn't support bootclasspath dir (-bootclasspath)
         // so we'll emulate it for compatibility and convenience.
         Path p = getBootClassPath();
-        if (p.size() > 0) {
+        if (!p.isEmpty()) {
             classpath.append(p);
         }
 
@@ -89,8 +90,8 @@
 
             if (!destDir.exists()
                 && !(destDir.mkdirs() || destDir.isDirectory())) {
-                throw new BuildException("Can't make output directories. "
-                                         + "Maybe permission is wrong. ");
+                throw new BuildException(
+                    "Can't make output directories. Maybe permission is wrong.");
             }
         }
 
@@ -152,6 +153,4 @@
         return nativeBuild;
     }
 
-    private static final String[] CONFLICT_WITH_DASH_C = {"-o", "--main=", "-D", "-fjni", "-L"};
-
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac12.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac12.java
index 637ce0e..fb041a9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac12.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac12.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,7 +26,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.LogOutputStream;
 import org.apache.tools.ant.types.Commandline;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
 
 /**
@@ -50,21 +49,16 @@
         attributes.log("Using classic compiler", Project.MSG_VERBOSE);
         Commandline cmd = setupJavacCommand(true);
 
-        OutputStream logstr = new LogOutputStream(attributes, Project.MSG_WARN);
-        try {
+        try (OutputStream logstr = new LogOutputStream(attributes, Project.MSG_WARN)) {
             // Create an instance of the compiler, redirecting output to
             // the project log
             Class<?> c = Class.forName(CLASSIC_COMPILER_CLASSNAME);
-            Constructor cons =
-                c.getConstructor(OutputStream.class, String.class);
-            Object compiler
-                = cons.newInstance(logstr, "javac");
+            Constructor<?> cons = c.getConstructor(OutputStream.class, String.class);
+            Object compiler = cons.newInstance(logstr, "javac");
 
             // Call the compile() method
             Method compile = c.getMethod("compile", String[].class);
-            Boolean ok = (Boolean) compile.invoke(compiler,
-                    new Object[] {cmd.getArguments()});
-            return ok.booleanValue();
+            return (Boolean) compile.invoke(compiler, new Object[] {cmd.getArguments()});
         } catch (ClassNotFoundException ex) {
             throw new BuildException("Cannot use classic compiler, as it is "
                                         + "not available. \n"
@@ -82,8 +76,6 @@
                 throw new BuildException("Error starting classic compiler: ",
                                          ex, location);
             }
-        } finally {
-            FileUtils.close(logstr);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java
index 6ca04c5..1d79ab8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,27 +44,25 @@
      * @return true if the compiler ran with a zero exit result (ok)
      * @exception BuildException if the compilation has problems.
      */
+    @Override
     public boolean execute() throws BuildException {
         attributes.log("Using modern compiler", Project.MSG_VERBOSE);
         Commandline cmd = setupModernJavacCommand();
 
         // Use reflection to be able to build on all JDKs >= 1.1:
         try {
-            Class c = Class.forName("com.sun.tools.javac.Main");
-            Object compiler = c.newInstance ();
-            Method compile = c.getMethod ("compile",
-                new Class [] {(new String [] {}).getClass ()});
-            int result = ((Integer) compile.invoke
-                          (compiler, new Object[] {cmd.getArguments()}))
-                .intValue ();
-            return (result == MODERN_COMPILER_SUCCESS);
+            Class<?> c = Class.forName("com.sun.tools.javac.Main");
+            Object compiler = c.getDeclaredConstructor().newInstance();
+            Method compile = c.getMethod("compile", String[].class);
+            int result = (Integer) compile.invoke(compiler,
+                    (Object) cmd.getArguments());
+            return result == MODERN_COMPILER_SUCCESS;
         } catch (Exception ex) {
             if (ex instanceof BuildException) {
                 throw (BuildException) ex;
-            } else {
-                throw new BuildException("Error starting modern compiler",
-                                         ex, location);
             }
+            throw new BuildException("Error starting modern compiler",
+                                     ex, location);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/JavacExternal.java b/src/main/org/apache/tools/ant/taskdefs/compilers/JavacExternal.java
index e227ecf..8ce8059 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/JavacExternal.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/JavacExternal.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,31 +40,76 @@
      * @return true if the compilation succeeded
      * @throws BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
         attributes.log("Using external javac compiler", Project.MSG_VERBOSE);
 
         Commandline cmd = new Commandline();
         cmd.setExecutable(getJavac().getJavacExecutable());
-        if (!assumeJava11() && !assumeJava12()) {
+        if (assumeJava1_3Plus()) {
             setupModernJavacCommandlineSwitches(cmd);
         } else {
             setupJavacCommandlineSwitches(cmd, true);
         }
-        int firstFileName = assumeJava11() ? -1 : cmd.size();
+
+        int openVmsFirstFileName = assumeJava1_2Plus() ? cmd.size() : -1;
+
         logAndAddFilesToCompile(cmd);
         //On VMS platform, we need to create a special java options file
         //containing the arguments and classpath for the javac command.
         //The special file is supported by the "-V" switch on the VMS JVM.
         if (Os.isFamily("openvms")) {
-            return execOnVMS(cmd, firstFileName);
+            return execOnVMS(cmd, openVmsFirstFileName);
         }
-        return
-                executeExternalCompile(cmd.getCommandline(), firstFileName,
-                        true)
+
+        String[] commandLine = cmd.getCommandline();
+        int firstFileName;
+
+        if (assumeJava1_2Plus()) {
+            firstFileName = moveArgFileEligibleOptionsToEnd(commandLine);
+        } else {
+            firstFileName = -1;
+        }
+
+        return executeExternalCompile(commandLine, firstFileName,
+                true)
                 == 0;
     }
 
     /**
+     * Moves all -J and @argfiles arguments to the beginning
+     * So that all command line arguments could be written to file, but -J and @argfile
+     * As per javac documentation:
+     *      you can specify one or more files that contain arguments to the javac command (except -J options)
+     * @param commandLine command line to process
+     * @return int index of first argument that could be put into argfile
+     */
+    private int moveArgFileEligibleOptionsToEnd(String[] commandLine) {
+        int nonArgFileOptionIdx = 1; // 0 for javac executable
+        while(nonArgFileOptionIdx < commandLine.length &&
+                !isArgFileEligible(commandLine[nonArgFileOptionIdx])) {
+            nonArgFileOptionIdx++;
+        }
+
+        for(int i = nonArgFileOptionIdx + 1; i < commandLine.length; i++) {
+            if (!isArgFileEligible(commandLine[i])) {
+                String option = commandLine[i];
+                if (i - nonArgFileOptionIdx >= 0) {
+                    System.arraycopy( commandLine, nonArgFileOptionIdx, commandLine, nonArgFileOptionIdx + 1, i - nonArgFileOptionIdx );
+                }
+                commandLine[nonArgFileOptionIdx] = option;
+                nonArgFileOptionIdx++;
+            }
+        }
+
+        return nonArgFileOptionIdx;
+    }
+
+    private static boolean isArgFileEligible(String option) {
+        return !(option.startsWith("-J") || option.startsWith("@"));
+    }
+
+    /**
      * helper method to execute our command on VMS.
      * @param cmd Commandline
      * @param firstFileName int
@@ -82,7 +127,8 @@
                             true);
 
         } catch (IOException e) {
-            throw new BuildException("Failed to create a temporary file for \"-V\" switch");
+            throw new BuildException(
+                "Failed to create a temporary file for \"-V\" switch");
         } finally {
             FileUtils.delete(vmsFile);
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java
index eac1bcf..e6b5c37 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,6 +43,7 @@
      * @return true if the compilation succeeded
      * @throws BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
         attributes.log("Using jikes compiler", Project.MSG_VERBOSE);
 
@@ -50,7 +51,7 @@
 
         // For -sourcepath, use the "sourcepath" value if present.
         // Otherwise default to the "srcdir" value.
-        Path sourcepath = null;
+        Path sourcepath;
         if (compileSourcepath != null) {
             sourcepath = compileSourcepath;
         } else {
@@ -58,14 +59,14 @@
         }
         // If the buildfile specifies sourcepath="", then don't
         // output any sourcepath.
-        if (sourcepath.size() > 0) {
+        if (!sourcepath.isEmpty()) {
             cmd.createArgument().setValue("-sourcepath");
             cmd.createArgument().setPath(sourcepath);
         }
 
         Path classpath = new Path(project);
 
-        if (bootclasspath == null || bootclasspath.size() == 0) {
+        if (bootclasspath == null || bootclasspath.isEmpty()) {
             // no bootclasspath, therefore, get one from the java runtime
             includeJavaRuntime = true;
         } else {
@@ -82,7 +83,7 @@
             classpath.append(new Path(project, jikesPath));
         }
 
-        if (extdirs != null && extdirs.size() > 0) {
+        if (extdirs != null && !extdirs.isEmpty()) {
             cmd.createArgument().setValue("-extdirs");
             cmd.createArgument().setPath(extdirs);
         }
@@ -136,7 +137,7 @@
         if (attributes.getSource() != null) {
             cmd.createArgument().setValue("-source");
             String source = attributes.getSource();
-            if (source.equals("1.1") || source.equals("1.2")) {
+            if ("1.1".equals(source) || "1.2".equals(source)) {
                 // support for -source 1.1 and -source 1.2 has been
                 // added with JDK 1.4.2, Jikes doesn't like it
                 attributes.log("Jikes doesn't support '-source " + source
@@ -151,7 +152,7 @@
         int firstFileName = cmd.size();
 
         Path boot = getBootClassPath();
-        if (boot.size() > 0) {
+        if (!boot.isEmpty()) {
             cmd.createArgument().setValue("-bootclasspath");
             cmd.createArgument().setPath(boot);
         }
@@ -161,7 +162,7 @@
     }
 
     private void addPropertyParams(Commandline cmd) {
-        /**
+        /*
          * TODO
          * Perhaps we shouldn't use properties for these
          * three options (emacs mode, warnings and pedantic),
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java
index 85ec479..fb659fe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,6 +37,7 @@
      * @return true if the compiler ran with a zero exit result (ok)
      * @exception BuildException if the compilation has problems.
      */
+    @Override
     public boolean execute() throws BuildException {
         attributes.log("Using jvc compiler", Project.MSG_VERBOSE);
 
@@ -45,7 +46,7 @@
         // jvc doesn't support bootclasspath dir (-bootclasspath)
         // so we'll emulate it for compatibility and convenience.
         Path p = getBootClassPath();
-        if (p.size() > 0) {
+        if (!p.isEmpty()) {
             classpath.append(p);
         }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Kjc.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Kjc.java
index 68b5ba1..eaaddaf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Kjc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Kjc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,6 +38,7 @@
      * @return true if the compilation succeeded
      * @exception BuildException if the compilation has problems.
      */
+    @Override
     public boolean execute() throws BuildException {
         attributes.log("Using kjc compiler", Project.MSG_VERBOSE);
         Commandline cmd = setupKjcCommand();
@@ -66,14 +67,14 @@
             cmd.createArgument().setFile(destDir);
         }
 
-        // generate the clsspath
+        // generate the classpath
         cmd.createArgument().setValue("-classpath");
 
         Path cp = new Path(project);
 
         // kjc don't have bootclasspath option.
         Path p = getBootClassPath();
-        if (p.size() > 0) {
+        if (!p.isEmpty()) {
             cp.append(p);
         }
 
@@ -115,5 +116,3 @@
         return cmd;
     }
 }
-
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Sj.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Sj.java
index 0dcc0e4..2720d15 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/Sj.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Sj.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,6 +35,7 @@
      * @return true if the compilation succeeded
      * @throws BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
         attributes.log("Using symantec java compiler", Project.MSG_VERBOSE);
 
@@ -54,8 +55,8 @@
      * @return null.
      * @since Ant 1.6.3
      */
+    @Override
     protected String getNoDebugArgument() {
         return null;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/And.java b/src/main/org/apache/tools/ant/taskdefs/condition/And.java
index 91b34c8..6b50ff3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/And.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/And.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,8 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
-import java.util.Enumeration;
-
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * &lt;and&gt; condition container.
@@ -36,15 +35,9 @@
      * @return true if all the contained conditions evaluates to true
      * @exception BuildException if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
-        Enumeration e = getConditions();
-        while (e.hasMoreElements()) {
-            Condition c = (Condition) e.nextElement();
-            if (!c.eval()) {
-                return false;
-            }
-        }
-        return true;
+        return StreamUtils.enumerationAsStream(getConditions()).allMatch(Condition::eval);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/AntVersion.java b/src/main/org/apache/tools/ant/taskdefs/condition/AntVersion.java
index 24a6bd8..4669cc8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/AntVersion.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/AntVersion.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 package org.apache.tools.ant.taskdefs.condition;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.util.DeweyDecimal;
@@ -36,6 +37,7 @@
      * Run as a task.
      * @throws BuildException if an error occurs.
      */
+    @Override
     public void execute() throws BuildException {
         if (propertyname == null) {
             throw new BuildException("'property' must be set.");
@@ -56,6 +58,7 @@
      * @return true if the condition is true.
      * @throws BuildException if an error occurs.
      */
+    @Override
     public boolean eval() throws BuildException {
         validate();
         DeweyDecimal actual = getVersion();
@@ -82,8 +85,8 @@
                 new DeweyDecimal(atLeast); //NOSONAR
             } catch (NumberFormatException e) {
                 throw new BuildException(
-                    "The 'atleast' attribute is not a Dewey Decimal eg 1.1.0 : "
-                    + atLeast);
+                    "The 'atleast' attribute is not a Dewey Decimal eg 1.1.0 : %s",
+                    atLeast);
             }
         } else {
             try {
@@ -91,8 +94,8 @@
                 new DeweyDecimal(exactly); //NOSONAR
             } catch (NumberFormatException e) {
                 throw new BuildException(
-                    "The 'exactly' attribute is not a Dewey Decimal eg 1.1.0 : "
-                    + exactly);
+                    "The 'exactly' attribute is not a Dewey Decimal eg 1.1.0 : %s",
+                    exactly);
             }
         }
     }
@@ -102,7 +105,7 @@
         p.init();
         StringBuilder sb = new StringBuilder();
         boolean foundFirstDigit = false;
-        for (char versionChar : p.getProperty("ant.version").toCharArray()) {
+        for (char versionChar : p.getProperty(MagicNames.ANT_VERSION).toCharArray()) {
             if (Character.isDigit(versionChar)) {
                 sb.append(versionChar);
                 foundFirstDigit = true;
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Condition.java b/src/main/org/apache/tools/ant/taskdefs/condition/Condition.java
index 62adbf3..5ff59c2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Condition.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Condition.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,4 +32,3 @@
      */
     boolean eval() throws BuildException;
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java b/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
index d057b46..0d24f49 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,9 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.ProjectComponent;
@@ -43,7 +45,7 @@
     /**
      *
      */
-    private Vector conditions = new Vector();
+    private List<Condition> conditions = new Vector<>();
 
     /**
      * Simple constructor.
@@ -77,8 +79,8 @@
      * @return an enumeration to use for iteration
      * @since 1.1
      */
-    protected final Enumeration getConditions() {
-        return conditions.elements();
+    protected final Enumeration<Condition> getConditions() {
+        return Collections.enumeration(conditions);
     }
 
     /**
@@ -108,7 +110,7 @@
      * @since 1.1
      */
     public void addAvailable(Available a) {
-        conditions.addElement(a);
+        conditions.add(a);
     }
 
     /**
@@ -118,7 +120,7 @@
      * @since 1.4, Ant 1.5
      */
     public void addChecksum(Checksum c) {
-        conditions.addElement(c);
+        conditions.add(c);
     }
 
     /**
@@ -128,7 +130,7 @@
      * @since 1.1
      */
     public void addUptodate(UpToDate u) {
-        conditions.addElement(u);
+        conditions.add(u);
     }
 
     /**
@@ -138,7 +140,7 @@
      * @since 1.1
      */
     public void addNot(Not n) {
-        conditions.addElement(n);
+        conditions.add(n);
     }
 
     /**
@@ -148,7 +150,7 @@
      * @since 1.1
      */
     public void addAnd(And a) {
-        conditions.addElement(a);
+        conditions.add(a);
     }
 
     /**
@@ -158,7 +160,7 @@
      * @since 1.1
      */
     public void addOr(Or o) {
-        conditions.addElement(o);
+        conditions.add(o);
     }
 
     /**
@@ -168,7 +170,7 @@
      * @since 1.1
      */
     public void addEquals(Equals e) {
-        conditions.addElement(e);
+        conditions.add(e);
     }
 
     /**
@@ -178,7 +180,7 @@
      * @since 1.1
      */
     public void addOs(Os o) {
-        conditions.addElement(o);
+        conditions.add(o);
     }
 
     /**
@@ -188,7 +190,7 @@
      * @since Ant 1.5
      */
     public void addIsSet(IsSet i) {
-        conditions.addElement(i);
+        conditions.add(i);
     }
 
     /**
@@ -198,7 +200,7 @@
      * @since Ant 1.5
      */
     public void addHttp(Http h) {
-        conditions.addElement(h);
+        conditions.add(h);
     }
 
     /**
@@ -208,7 +210,7 @@
      * @since Ant 1.5
      */
     public void addSocket(Socket s) {
-        conditions.addElement(s);
+        conditions.add(s);
     }
 
     /**
@@ -218,7 +220,7 @@
      * @since Ant 1.5
      */
     public void addFilesMatch(FilesMatch test) {
-        conditions.addElement(test);
+        conditions.add(test);
     }
 
     /**
@@ -228,7 +230,7 @@
      * @since Ant 1.5
      */
     public void addContains(Contains test) {
-        conditions.addElement(test);
+        conditions.add(test);
     }
 
     /**
@@ -238,7 +240,7 @@
      * @since Ant 1.5
      */
     public void addIsTrue(IsTrue test) {
-        conditions.addElement(test);
+        conditions.add(test);
     }
 
     /**
@@ -248,7 +250,7 @@
      * @since Ant 1.5
      */
     public void addIsFalse(IsFalse test) {
-        conditions.addElement(test);
+        conditions.add(test);
     }
 
     /**
@@ -258,7 +260,7 @@
      * @since Ant 1.6
      */
     public void addIsReference(IsReference i) {
-        conditions.addElement(i);
+        conditions.add(i);
     }
 
     /**
@@ -266,7 +268,7 @@
      * @param test the condition
      */
     public void addIsFileSelected(IsFileSelected test) {
-        conditions.addElement(test);
+        conditions.add(test);
     }
 
     /**
@@ -275,7 +277,7 @@
      * @since Ant 1.6
      */
     public void add(Condition c) {
-        conditions.addElement(c);
+        conditions.add(c);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Contains.java b/src/main/org/apache/tools/ant/taskdefs/condition/Contains.java
index 347c474..98bc5c4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Contains.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Contains.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -63,10 +63,11 @@
      * @return true if the substring is within the string
      * @exception BuildException if the attributes are not set correctly
      */
+    @Override
     public boolean eval() throws BuildException {
         if (string == null || subString == null) {
-            throw new BuildException("both string and substring are required "
-                                     + "in contains");
+            throw new BuildException(
+                "both string and substring are required in contains");
         }
 
         return caseSensitive
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Equals.java b/src/main/org/apache/tools/ant/taskdefs/condition/Equals.java
index 2d930f9..44e3561 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Equals.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Equals.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -50,10 +50,10 @@
     /**
      * Set the first string
      *
-     * @param a1 the first string
+     * @param arg1 the first string
      */
-    public void setArg1(String a1) {
-        setArg1Internal(a1);
+    public void setArg1(String arg1) {
+        setArg1Internal(arg1);
     }
 
     private void setArg1Internal(Object arg1) {
@@ -77,10 +77,10 @@
     /**
      * Set the second string
      *
-     * @param a2 the second string
+     * @param arg2 the second string
      */
-    public void setArg2(String a2) {
-        setArg2Internal(a2);
+    public void setArg2(String arg2) {
+        setArg2Internal(arg2);
     }
 
     private void setArg2Internal(Object arg2) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/FilesMatch.java b/src/main/org/apache/tools/ant/taskdefs/condition/FilesMatch.java
index 5e99398..45a235d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/FilesMatch.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/FilesMatch.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,7 +44,6 @@
 
     private boolean textfile = false;
 
-
     /**
      * Sets the File1 attribute
      *
@@ -54,7 +53,6 @@
         this.file1 = file1;
     }
 
-
     /**
      * Sets the File2 attribute
      *
@@ -78,13 +76,14 @@
      * @return true if the files are equal
      * @exception BuildException if it all went pear-shaped
      */
+    @Override
     public boolean eval()
         throws BuildException {
 
         //validate
         if (file1 == null || file2 == null) {
-            throw new BuildException("both file1 and file2 are required in "
-                                     + "filesmatch");
+            throw new BuildException(
+                "both file1 and file2 are required in filesmatch");
         }
 
         //#now match the files
@@ -98,4 +97,3 @@
         return matches;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/HasFreeSpace.java b/src/main/org/apache/tools/ant/taskdefs/condition/HasFreeSpace.java
index 420c189..7b9434a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/HasFreeSpace.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/HasFreeSpace.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,6 +41,7 @@
      * @return true if there enough free space.
      * @throws BuildException if there is a problem.
      */
+    @Override
     public boolean eval() throws BuildException {
         validate();
         try {
@@ -48,11 +49,11 @@
                 //reflection to avoid bootstrap/build problems
                 File fs = new File(partition);
                 ReflectWrapper w = new ReflectWrapper(fs);
-                long free = ((Long) w.invoke("getFreeSpace")).longValue();
+                long free = w.<Long>invoke("getFreeSpace");
                 return free >= StringUtils.parseHumanSizes(needed);
-            } else {
-                throw new BuildException("HasFreeSpace condition not supported on Java5 or less.");
             }
+            throw new BuildException(
+                "HasFreeSpace condition not supported on Java5 or less.");
         } catch (Exception e) {
             throw new BuildException(e);
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/HasMethod.java b/src/main/org/apache/tools/ant/taskdefs/condition/HasMethod.java
index 6b8d85f..1043eef 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/HasMethod.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/HasMethod.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,7 +37,6 @@
     private AntClassLoader loader;
     private boolean ignoreSystemClasses = false;
 
-
     /**
      * Set the classpath to be used when searching for classes and resources.
      *
@@ -104,7 +103,7 @@
     /**
      * Check if a given class can be loaded.
      */
-    private Class loadClass(String classname) {
+    private Class<?> loadClass(String classname) {
         try {
             if (ignoreSystemClasses) {
                 loader = getProject().createClassLoader(classpath);
@@ -114,25 +113,23 @@
                     return loader.findClass(classname);
                 } catch (SecurityException se) {
                     // class found but restricted name
-                    throw new BuildException("class \"" + classname
-                                             + "\" was found but a"
-                                             + " SecurityException has been"
-                                             + " raised while loading it",
-                                             se);
-                }
-            } else if (loader != null) {
-                // How do we ever get here?
-                return loader.loadClass(classname);
-            } else {
-                ClassLoader l = this.getClass().getClassLoader();
-                // Can return null to represent the bootstrap class loader.
-                // see API docs of Class.getClassLoader.
-                if (l != null) {
-                    return Class.forName(classname, true, l);
-                } else {
-                    return Class.forName(classname);
+                    throw new BuildException(
+                        "class \"" + classname
+                            + "\" was found but a SecurityException has been raised while loading it",
+                        se);
                 }
             }
+            if (loader != null) {
+                // How do we ever get here?
+                return loader.loadClass(classname);
+            }
+            ClassLoader l = this.getClass().getClassLoader();
+            // Can return null to represent the bootstrap class loader.
+            // see API docs of Class.getClassLoader.
+            if (l != null) {
+                return Class.forName(classname, true, l);
+            }
+            return Class.forName(classname);
         } catch (ClassNotFoundException e) {
             throw new BuildException("class \"" + classname
                                      + "\" was not found");
@@ -143,15 +140,15 @@
         }
     }
 
-
     /** {@inheritDoc}. */
+    @Override
     public boolean eval() throws BuildException {
         if (classname == null) {
             throw new BuildException("No classname defined");
         }
         ClassLoader preLoadClass = loader;
         try {
-            Class clazz = loadClass(classname);
+            Class<?> clazz = loadClass(classname);
             if (method != null) {
                 return isMethodFound(clazz);
             }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Http.java b/src/main/org/apache/tools/ant/taskdefs/condition/Http.java
index c163ad7..b811e8d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Http.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Http.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
+import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.ProtocolException;
@@ -28,22 +29,29 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.taskdefs.Get;
 
 /**
  * Condition to wait for a HTTP request to succeed. Its attribute(s) are:
  *   url - the URL of the request.
  *   errorsBeginAt - number at which errors begin at; default=400.
  *   requestMethod - HTTP request method to use; GET, HEAD, etc. default=GET
+ *   readTimeout - The read timeout in ms. default=0
  * @since Ant 1.5
  */
 public class Http extends ProjectComponent implements Condition {
     private static final int ERROR_BEGINS = 400;
     private static final String DEFAULT_REQUEST_METHOD = "GET";
+    private static final String HTTP = "http";
+    private static final String HTTPS = "https";
 
     private String spec = null;
     private String requestMethod = DEFAULT_REQUEST_METHOD;
     private boolean followRedirects = true;
 
+    private int errorsBeginAt = ERROR_BEGINS;
+    private int readTimeout = 0;
+
     /**
      * Set the url attribute
      * @param url the url of the request
@@ -52,8 +60,6 @@
         spec = url;
     }
 
-    private int errorsBeginAt = ERROR_BEGINS;
-
     /**
      * Set the errorsBeginAt attribute
      * @param errorsBeginAt number at which errors begin at, default is
@@ -92,9 +98,24 @@
     }
 
     /**
+     * Sets the read timeout. Any value &lt; 0 will be ignored
+     *
+     * @param t the timeout value in milli seconds
+     *
+     * @see java.net.HttpURLConnection#setReadTimeout
+     * @since Ant 1.10.6
+     */
+    public void setReadTimeout(int t) {
+        if(t >= 0) {
+            this.readTimeout = t;
+        }
+    }
+
+    /**
      * @return true if the HTTP request succeeds
      * @exception BuildException if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
         if (spec == null) {
             throw new BuildException("No url specified in http condition");
@@ -105,21 +126,15 @@
             try {
                 URLConnection conn = url.openConnection();
                 if (conn instanceof HttpURLConnection) {
-                    HttpURLConnection http = (HttpURLConnection) conn;
-                    http.setRequestMethod(requestMethod);
-                    http.setInstanceFollowRedirects(followRedirects);
-                    int code = http.getResponseCode();
+                    int code = request((HttpURLConnection) conn, url);
                     log("Result code for " + spec + " was " + code,
                         Project.MSG_VERBOSE);
-                    if (code > 0 && code < errorsBeginAt) {
-                        return true;
-                    }
-                    return false;
+                    return code > 0 && code < errorsBeginAt;
                 }
             } catch (ProtocolException pe) {
                 throw new BuildException("Invalid HTTP protocol: "
                                          + requestMethod, pe);
-            } catch (java.io.IOException e) {
+            } catch (IOException e) {
                 return false;
             }
         } catch (MalformedURLException e) {
@@ -127,4 +142,39 @@
         }
         return true;
     }
+
+    private int request(final HttpURLConnection http, final URL url) throws IOException {
+        http.setRequestMethod(requestMethod);
+        http.setInstanceFollowRedirects(followRedirects);
+        http.setReadTimeout(readTimeout);
+        final int firstStatusCode = http.getResponseCode();
+        if (this.followRedirects && Get.isMoved(firstStatusCode)) {
+            final String newLocation = http.getHeaderField("Location");
+            final URL newURL = new URL(newLocation);
+            if (redirectionAllowed(url, newURL)) {
+                final URLConnection newConn = newURL.openConnection();
+                if (newConn instanceof HttpURLConnection) {
+                    log("Following redirect from " + url + " to " + newURL);
+                    return request((HttpURLConnection) newConn, newURL);
+                }
+            }
+        }
+        return firstStatusCode;
+    }
+
+    private boolean redirectionAllowed(final URL from, final URL to) {
+        if (from.equals(to)) {
+            // most simple case of an infinite redirect loop
+            return false;
+        }
+        if (!(from.getProtocol().equals(to.getProtocol())
+              || (HTTP.equals(from.getProtocol())
+                  && HTTPS.equals(to.getProtocol())))) {
+            log("Redirection detected from "
+                + from.getProtocol() + " to " + to.getProtocol()
+                + ". Protocol switch unsafe, not allowed.");
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsFailure.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsFailure.java
index b0ffb9e..8388283 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsFailure.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsFailure.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsFalse.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsFalse.java
index 0b3e69b..2361b0f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsFalse.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsFalse.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -48,7 +48,7 @@
         if (value == null) {
             throw new BuildException("Nothing to test for falsehood");
         }
-        return !value.booleanValue();
+        return !value;
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsFileSelected.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsFileSelected.java
index efdb664..e7cd9d6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsFileSelected.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsFileSelected.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsLastModified.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsLastModified.java
index ac05478..08e80db 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsLastModified.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsLastModified.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -69,9 +69,11 @@
      */
     public void setPattern(final String pattern) {
         dfFactory = new Touch.DateFormatFactory() {
+            @Override
             public DateFormat getPrimaryFormat() {
                 return new SimpleDateFormat(pattern);
             }
+            @Override
             public DateFormat getFallbackFormat() {
                 return null;
             }
@@ -104,8 +106,8 @@
      */
     protected void validate() throws BuildException {
         if (millis >= 0 && dateTime != null) {
-            throw new BuildException("Only one of dateTime and millis can be"
-                                     + " set");
+            throw new BuildException(
+                "Only one of dateTime and millis can be set");
         }
         if (millis < 0 && dateTime == null) {
             throw new BuildException("millis or dateTime is required");
@@ -129,7 +131,7 @@
             return System.currentTimeMillis();
         }
         DateFormat df = dfFactory.getPrimaryFormat();
-        ParseException pe = null;
+        ParseException pe;
         try {
             return df.parse(dateTime).getTime();
         } catch (ParseException peOne) {
@@ -144,11 +146,7 @@
                 }
             }
         }
-        if (pe != null) {
-            throw new BuildException(pe.getMessage(), pe, getLocation());
-        }
-        /* NOTREACHED */
-        return 0;
+        throw new BuildException(pe.getMessage(), pe, getLocation());
     }
 
     /**
@@ -156,6 +154,7 @@
      * @return true or false depending on the comparison mode and the time of the resource
      * @throws BuildException if something goes wrong
      */
+    @Override
     public boolean eval() throws BuildException {
         validate();
         long expected = getMillis();
@@ -209,6 +208,8 @@
             setValue(s);
         }
 
+        /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
             return new String[] {
                 EQUALS_TEXT, BEFORE_TEXT, AFTER_TEXT, NOT_BEFORE_TEXT,
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java
index d83fcbe..c0d46ee 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,8 +19,6 @@
 package org.apache.tools.ant.taskdefs.condition;
 
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -50,16 +48,13 @@
  * @since Ant 1.7
  */
 public class IsReachable extends ProjectComponent implements Condition {
-
-    private static final int SECOND = 1000; // millis per second
-    private String host;
-    private String url;
-
     /**
      * The default timeout.
      */
     public static final int DEFAULT_TIMEOUT = 30;
-    private int timeout = DEFAULT_TIMEOUT;
+
+    private static final int SECOND = 1000; // millis per second
+
     /**
      * Error when no hostname is defined
      */
@@ -88,11 +83,16 @@
     public static final String ERROR_NO_HOST_IN_URL = "No hostname in URL ";
     /**
      * The method name to look for in InetAddress
-     * @deprecated Since 1.9.14
+     * @deprecated Since 1.10.6
      */
     @Deprecated
     public static final String METHOD_NAME = "isReachable";
 
+    private String host;
+    private String url;
+
+    private int timeout = DEFAULT_TIMEOUT;
+
     /**
      * Set the host to ping.
      *
@@ -125,10 +125,10 @@
      *
      * @param string param to check
      *
-     * @return true if it is empty
+     * @return true if it is isNullOrEmpty
      */
-    private boolean empty(final String string) {
-        return string == null || string.length() == 0;
+    private boolean isNullOrEmpty(final String string) {
+        return string == null || string.isEmpty();
     }
 
     /**
@@ -139,23 +139,24 @@
      * @throws BuildException
      *          if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
-        if (empty(host) && empty(url)) {
+        if (isNullOrEmpty(host) && isNullOrEmpty(url)) {
             throw new BuildException(ERROR_NO_HOSTNAME);
         }
         if (timeout < 0) {
             throw new BuildException(ERROR_BAD_TIMEOUT);
         }
         String target = host;
-        if (!empty(url)) {
-            if (!empty(host)) {
+        if (!isNullOrEmpty(url)) {
+            if (!isNullOrEmpty(host)) {
                 throw new BuildException(ERROR_BOTH_TARGETS);
             }
             try {
                 //get the host of a url
                 final URL realURL = new URL(url);
                 target = realURL.getHost();
-                if (empty(target)) {
+                if (isNullOrEmpty(target)) {
                     throw new BuildException(ERROR_NO_HOST_IN_URL + url);
                 }
             } catch (final MalformedURLException e) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsReference.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsReference.java
index f172849..760d868 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsReference.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsReference.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -56,34 +56,30 @@
      *              the reference is the same type
      * @exception BuildException if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
         if (ref == null) {
-            throw new BuildException("No reference specified for isreference "
-                                     + "condition");
+            throw new BuildException(
+                    "No reference specified for isreference condition");
         }
 
         String key = ref.getRefId();
         if (!getProject().hasReference(key)) {
             return false;
-        } else if (type == null) {
-            return true;
-        } else {
-            Object o = getProject().getReference(key);
-            Class typeClass =
-                (Class) getProject().getDataTypeDefinitions().get(type);
-
-            if (typeClass == null) {
-                typeClass =
-                    (Class) getProject().getTaskDefinitions().get(type);
-            }
-
-            if (typeClass == null) {
-                // don't know the type, should throw exception instead?
-                return false;
-            }
-
-            return typeClass.isAssignableFrom(o.getClass());
         }
+
+        if (type == null) {
+            return true;
+        }
+        Class<?> typeClass = getProject().getDataTypeDefinitions().get(type);
+        if (typeClass == null) {
+            typeClass = getProject().getTaskDefinitions().get(type);
+        }
+
+        // if the type is unknown, throw exception instead?
+        return typeClass != null
+                && typeClass.isAssignableFrom(getProject().getReference(key).getClass());
+
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsSet.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsSet.java
index d4a5914..7d8b0c0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsSet.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,9 +41,11 @@
      * @return true if the property exists
      * @exception BuildException if the property attribute is not set
      */
+    @Override
     public boolean eval() throws BuildException {
         if (property == null) {
-            throw new BuildException("No property specified for isset " + "condition");
+            throw new BuildException(
+                "No property specified for isset condition");
         }
         return getProject().getProperty(property) != null;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsSigned.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsSigned.java
index 277a921..54857cb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsSigned.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsSigned.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,12 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.ManifestTask;
 import org.apache.tools.ant.types.DataType;
-import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.ant.util.StreamUtils;
 import org.apache.tools.zip.ZipFile;
 
 /**
@@ -71,19 +70,10 @@
      */
     public static boolean isSigned(File zipFile, String name)
         throws IOException {
-        ZipFile jarFile = null;
-        try {
-            jarFile = new ZipFile(zipFile);
+        try (ZipFile jarFile = new ZipFile(zipFile)) {
             if (null == name) {
-                Enumeration entries = jarFile.getEntries();
-                while (entries.hasMoreElements()) {
-                    String eName = ((ZipEntry) entries.nextElement()).getName();
-                    if (eName.startsWith(SIG_START)
-                        && eName.endsWith(SIG_END)) {
-                        return true;
-                    }
-                }
-                return false;
+                return StreamUtils.enumerationAsStream(jarFile.getEntries())
+                        .anyMatch(e -> e.getName().startsWith(SIG_START) && e.getName().endsWith(SIG_END));
             }
             name = replaceInvalidChars(name);
             boolean shortSig = jarFile.getEntry(SIG_START
@@ -98,8 +88,6 @@
             }
 
             return shortSig || longSig;
-        } finally {
-            ZipFile.closeQuietly(jarFile);
         }
     }
 
@@ -109,6 +97,7 @@
      * specified, if the file contains a signature.
      * @return true if the file is signed.
      */
+    @Override
     public boolean eval() {
         if (file == null) {
             throw new BuildException("The file attribute must be set.");
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/IsTrue.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsTrue.java
index 753b441..732e226 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/IsTrue.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsTrue.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,12 +44,12 @@
      * @return the value
      * @throws BuildException if someone forgot to spec a value
      */
+    @Override
     public boolean eval() throws BuildException {
         if (value == null) {
             throw new BuildException("Nothing to test for truth");
         }
-        return value.booleanValue();
+        return value;
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/JavaVersion.java b/src/main/org/apache/tools/ant/taskdefs/condition/JavaVersion.java
index 69a9290..a221495 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/JavaVersion.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/JavaVersion.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,10 +23,11 @@
 
 /**
  * An Java version condition.
- * @since Java 1.9.10
+ * @since Ant 1.10.2
  */
 public class JavaVersion implements Condition {
 
+    private String atMost = null;
     private String atLeast = null;
     private String exactly = null;
 
@@ -44,16 +45,19 @@
         if (null != exactly) {
             return actual.isEqual(new DeweyDecimal(exactly));
         }
+        if (atMost != null) {
+            return actual.isLessThanOrEqual(new DeweyDecimal(atMost));
+        }
         //default
         return false;
     }
 
     private void validate() throws BuildException {
-        if (atLeast != null && exactly != null) {
-            throw new BuildException("Only one of atleast or exactly may be set.");
+        if (atLeast != null && exactly != null && atMost != null) {
+            throw new BuildException("Only one of atleast or atmost or exactly may be set.");
         }
-        if (null == atLeast && null == exactly) {
-            throw new BuildException("One of atleast or exactly must be set.");
+        if (null == atLeast && null == exactly && atMost == null) {
+            throw new BuildException("One of atleast or atmost or exactly must be set.");
         }
         if (atLeast != null) {
             try {
@@ -64,6 +68,14 @@
                     "The 'atleast' attribute is not a Dewey Decimal eg 1.1.0 : "
                     + atLeast);
             }
+        } else if (atMost != null) {
+            try {
+                new DeweyDecimal(atMost); //NOSONAR
+            } catch (NumberFormatException e) {
+                throw new BuildException(
+                        "The 'atmost' attribute is not a Dewey Decimal eg 1.1.0 : "
+                                + atMost);
+            }
         } else {
             try {
                 // only created for side effect
@@ -88,13 +100,33 @@
      * Set the atleast attribute.
      * This is of the form major.minor.point.
      * For example 1.7.0.
-     * @param atLeast the version to check against.
+     * @param atLeast the version to set
      */
     public void setAtLeast(String atLeast) {
         this.atLeast = atLeast;
     }
 
     /**
+     * Get the atmost attribute.
+     * @return the atmost attribute.
+     * @since Ant 1.10.10
+     */
+    public String getAtMost() {
+        return atMost;
+    }
+
+    /**
+     * Set the atmost attribute.
+     * This is of the form major.minor.point.
+     * For example 11.0.2
+     * @param atMost the version to set
+     * @since Ant 1.10.10
+     */
+    public void setAtMost(String atMost) {
+        this.atMost = atMost;
+    }
+
+    /**
      * Get the exactly attribute.
      * @return the exactly attribute.
      */
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Matches.java b/src/main/org/apache/tools/ant/taskdefs/condition/Matches.java
index ac37f8f..4966955 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Matches.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Matches.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Not.java b/src/main/org/apache/tools/ant/taskdefs/condition/Not.java
index a39dcbb..71250c4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Not.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Not.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,15 +36,16 @@
      * @return true if the condition is true.
      * @throws BuildException if the condition is not configured correctly.
      */
+    @Override
     public boolean eval() throws BuildException {
         if (countConditions() > 1) {
-            throw new BuildException("You must not nest more than one "
-                + "condition into <not>");
+            throw new BuildException(
+                "You must not nest more than one condition into <not>");
         }
         if (countConditions() < 1) {
             throw new BuildException("You must nest a condition into <not>");
         }
-        return !((Condition) getConditions().nextElement()).eval();
+        return !getConditions().nextElement().eval();
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Or.java b/src/main/org/apache/tools/ant/taskdefs/condition/Or.java
index aedfe74..dddddab 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Or.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Or.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,8 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
-import java.util.Enumeration;
-
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
  * &lt;or&gt; condition container.
@@ -36,15 +35,9 @@
      * @return true if any of the contained conditions evaluate to true
      * @exception BuildException if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
-        Enumeration e = getConditions();
-        while (e.hasMoreElements()) {
-            Condition c = (Condition) e.nextElement();
-            if (c.eval()) {
-                return true;
-            }
-        }
-        return false;
+        return StreamUtils.enumerationAsStream(getConditions()).anyMatch(Condition::eval);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Os.java b/src/main/org/apache/tools/ant/taskdefs/condition/Os.java
index ace0c66..03bb15c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Os.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Os.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
+import java.io.File;
 import java.util.Locale;
 
 import org.apache.tools.ant.BuildException;
@@ -34,26 +35,9 @@
         System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
     private static final String OS_VERSION =
         System.getProperty("os.version").toLowerCase(Locale.ENGLISH);
-    private static final String PATH_SEP =
-        System.getProperty("path.separator");
+    private static final String PATH_SEP = File.pathSeparator;
 
     /**
-     * OS family to look for
-     */
-    private String family;
-    /**
-     * Name of OS
-     */
-    private String name;
-    /**
-     * version of OS
-     */
-    private String version;
-    /**
-     * OS architecture
-     */
-    private String arch;
-    /**
      * OS family that can be tested for. {@value}
      */
     public static final String FAMILY_WINDOWS = "windows";
@@ -108,6 +92,23 @@
     private static final String DARWIN = "darwin";
 
     /**
+     * OS family to look for
+     */
+    private String family;
+    /**
+     * Name of OS
+     */
+    private String name;
+    /**
+     * version of OS
+     */
+    private String version;
+    /**
+     * OS architecture
+     */
+    private String arch;
+
+    /**
      * Default constructor
      *
      */
@@ -179,6 +180,7 @@
      * @throws BuildException if there is an error.
      * @see Os#setFamily(String)
      */
+    @Override
     public boolean eval() throws BuildException {
         return isOs(family, name, arch, version);
     }
@@ -270,39 +272,52 @@
                             || OS_NAME.contains("ce"));
                     isNT = !is9x;
                 }
-                if (family.equals(FAMILY_WINDOWS)) {
-                    isFamily = isWindows;
-                } else if (family.equals(FAMILY_9X)) {
-                    isFamily = isWindows && is9x;
-                } else if (family.equals(FAMILY_NT)) {
-                    isFamily = isWindows && isNT;
-                } else if (family.equals(FAMILY_OS2)) {
-                    isFamily = OS_NAME.contains(FAMILY_OS2);
-                } else if (family.equals(FAMILY_NETWARE)) {
-                    isFamily = OS_NAME.contains(FAMILY_NETWARE);
-                } else if (family.equals(FAMILY_DOS)) {
-                    isFamily = PATH_SEP.equals(";") && !isFamily(FAMILY_NETWARE);
-                } else if (family.equals(FAMILY_MAC)) {
-                    isFamily = OS_NAME.contains(FAMILY_MAC)
-                        || OS_NAME.contains(DARWIN);
-                } else if (family.equals(FAMILY_TANDEM)) {
-                    isFamily = OS_NAME.contains("nonstop_kernel");
-                } else if (family.equals(FAMILY_UNIX)) {
-                    isFamily = PATH_SEP.equals(":")
-                        && !isFamily(FAMILY_VMS)
-                        && (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x")
-                            || OS_NAME.contains(DARWIN));
-                } else if (family.equals(FAMILY_ZOS)) {
-                    isFamily = OS_NAME.contains(FAMILY_ZOS)
-                        || OS_NAME.contains("os/390");
-                } else if (family.equals(FAMILY_OS400)) {
-                    isFamily = OS_NAME.contains(FAMILY_OS400);
-                } else if (family.equals(FAMILY_VMS)) {
-                    isFamily = OS_NAME.contains(FAMILY_VMS);
-                } else {
-                    throw new BuildException(
-                        "Don\'t know how to detect os family \""
-                        + family + "\"");
+                switch (family) {
+                    case FAMILY_WINDOWS:
+                        isFamily = isWindows;
+                        break;
+                    case FAMILY_9X:
+                        isFamily = isWindows && is9x;
+                        break;
+                    case FAMILY_NT:
+                        isFamily = isWindows && isNT;
+                        break;
+                    case FAMILY_OS2:
+                        isFamily = OS_NAME.contains(FAMILY_OS2);
+                        break;
+                    case FAMILY_NETWARE:
+                        isFamily = OS_NAME.contains(FAMILY_NETWARE);
+                        break;
+                    case FAMILY_DOS:
+                        isFamily = PATH_SEP.equals(";") && !isFamily(FAMILY_NETWARE);
+                        break;
+                    case FAMILY_MAC:
+                        isFamily = OS_NAME.contains(FAMILY_MAC)
+                                || OS_NAME.contains(DARWIN);
+                        break;
+                    case FAMILY_TANDEM:
+                        isFamily = OS_NAME.contains("nonstop_kernel");
+                        break;
+                    case FAMILY_UNIX:
+                        isFamily = PATH_SEP.equals(":")
+                                && !isFamily(FAMILY_VMS)
+                                && (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x")
+                                || OS_NAME.contains(DARWIN));
+                        break;
+                    case FAMILY_ZOS:
+                        isFamily = OS_NAME.contains(FAMILY_ZOS)
+                                || OS_NAME.contains("os/390");
+                        break;
+                    case FAMILY_OS400:
+                        isFamily = OS_NAME.contains(FAMILY_OS400);
+                        break;
+                    case FAMILY_VMS:
+                        isFamily = OS_NAME.contains(FAMILY_VMS);
+                        break;
+                    default:
+                        throw new BuildException(
+                                "Don't know how to detect os family \""
+                                        + family + "\"");
                 }
             }
             if (name != null) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/ParserSupports.java b/src/main/org/apache/tools/ant/taskdefs/condition/ParserSupports.java
index d283401..6f86a4a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/ParserSupports.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/ParserSupports.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,9 +31,6 @@
  */
 public class ParserSupports extends ProjectComponent implements Condition {
 
-    private String feature;
-    private String property;
-    private String value;
     // Error messages
     /** error - combined attributes not allowed */
     public static final String ERROR_BOTH_ATTRIBUTES =
@@ -56,6 +53,10 @@
     public static final String ERROR_NO_VALUE =
         "A value is needed when testing for property support";
 
+    private String feature;
+    private String property;
+    private String value;
+
     /**
      * Feature to probe for.
      * @param feature the feature to probe for.
@@ -82,6 +83,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public boolean eval() throws BuildException {
         if (feature != null && property != null) {
             throw new BuildException(ERROR_BOTH_ATTRIBUTES);
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/ResourceContains.java b/src/main/org/apache/tools/ant/taskdefs/condition/ResourceContains.java
index aed4c43..6056cb0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/ResourceContains.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/ResourceContains.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -88,8 +88,7 @@
                         o = rc.iterator().next();
                     }
                 } else {
-                    throw new BuildException(
-                        "Illegal value at '" + refid + "': " + String.valueOf(o));
+                    throw new BuildException("Illegal value at '%s': %s", refid, o);
                 }
             }
             this.resource = (Resource) o;
@@ -122,8 +121,8 @@
             resolveRefid();
         }
         if (resource == null || substring == null) {
-            throw new BuildException("both resource and substring are required "
-                                     + "in <resourcecontains>");
+            throw new BuildException(
+                "both resource and substring are required in <resourcecontains>");
         }
     }
 
@@ -132,10 +131,11 @@
      * @return true if the substring is contained in the resource
      * @throws BuildException if there is a problem.
      */
+    @Override
     public synchronized boolean eval() throws BuildException {
         validate();
 
-        if (substring.length() == 0) {
+        if (substring.isEmpty()) {
             if (getProject() != null) {
                 getProject().log("Substring is empty; returning true",
                                  Project.MSG_VERBOSE);
@@ -146,9 +146,8 @@
             return false;
         }
 
-        BufferedReader reader = null;
-        try {
-            reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
+        try (BufferedReader reader = new BufferedReader(
+            new InputStreamReader(resource.getInputStream()))) {
             String contents = FileUtils.safeReadFully(reader);
             String sub = substring;
             if (!casesensitive) {
@@ -158,8 +157,6 @@
             return contents.contains(sub);
         } catch (IOException e) {
             throw new BuildException("There was a problem accessing resource : " + resource);
-        } finally {
-            FileUtils.close(reader);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/ResourceExists.java b/src/main/org/apache/tools/ant/taskdefs/condition/ResourceExists.java
index 0e4de58..daf684f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/ResourceExists.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/ResourceExists.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/ResourcesMatch.java b/src/main/org/apache/tools/ant/taskdefs/condition/ResourcesMatch.java
index 29e3e80..c4ab33b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/ResourcesMatch.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/ResourcesMatch.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -65,6 +65,7 @@
      * @return true if all resources are equal.
      * @exception BuildException if there is an error.
      */
+    @Override
     public boolean eval() throws BuildException {
         if (resources == null) {
             throw new BuildException(
@@ -72,11 +73,11 @@
         }
         if (resources.size() > 1) {
             Iterator<Resource> i = resources.iterator();
-            Resource r1 = (Resource) i.next();
-            Resource r2 = null;
+            Resource r1 = i.next();
+            Resource r2;
 
             while (i.hasNext()) {
-                r2 = (Resource) i.next();
+                r2 = i.next();
                 try {
                     if (!ResourceUtils.contentEquals(r1, r2, asText)) {
                         return false;
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..df436a4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Socket.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Socket.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -57,31 +57,21 @@
      * @return true if a socket can be created
      * @exception BuildException if the attributes are not set
      */
+    @Override
     public boolean eval() throws BuildException {
         if (server == null) {
-            throw new BuildException("No server specified in socket "
-                                     + "condition");
+            throw new BuildException("No server specified in socket condition");
         }
         if (port == 0) {
             throw new BuildException("No port specified in socket condition");
         }
         log("Checking for listener at " + server + ":" + port,
             Project.MSG_VERBOSE);
-        java.net.Socket s = null;
-        try {
-            s = new java.net.Socket(server, port);
+        try (java.net.Socket s = new java.net.Socket(server, port)) {
+            return true;
         } catch (IOException e) {
             return false;
-        } finally {
-          if (s != null) {
-            try {
-              s.close();
-            } catch (IOException ioe) {
-              // Intentionally left blank
-            }
-          }
         }
-        return true;
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/TypeFound.java b/src/main/org/apache/tools/ant/taskdefs/condition/TypeFound.java
index f97c7f4..af8625a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/TypeFound.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/TypeFound.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,7 +58,6 @@
      * @return true if the typename exists
      */
     protected boolean doesTypeExist(String typename) {
-
         ComponentHelper helper =
             ComponentHelper.getComponentHelper(getProject());
         String componentName = ProjectHelper.genComponentName(uri, typename);
@@ -81,6 +80,7 @@
      * @return true if the condition is true
      * @exception BuildException if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
         if (name == null) {
             throw new BuildException("No type specified");
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Xor.java b/src/main/org/apache/tools/ant/taskdefs/condition/Xor.java
index 2cc8e4c..05dc51e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Xor.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Xor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,12 +17,11 @@
  */
 package org.apache.tools.ant.taskdefs.condition;
 
-import java.util.Enumeration;
-
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.StreamUtils;
 
 /**
- * The <tt>Xor</tt> condition type to exclusive or operations.
+ * The <code>Xor</code> condition type to exclusive or operations.
  * This does not shortcut stuff.
  * @since Ant 1.7
  */
@@ -34,16 +33,11 @@
      * @throws BuildException
      *          if an error occurs.
      */
+    @Override
     public boolean eval() throws BuildException {
-        Enumeration e = getConditions();
-        //initial state is false.
-        boolean state = false;
-        while (e.hasMoreElements()) {
-            Condition c = (Condition) e.nextElement();
-            //every condition is xored against the previous one
-            state ^= c.eval();
-        }
-        return state;
+        // initial state is false
+        return StreamUtils.enumerationAsStream(getConditions()).map(Condition::eval)
+                .reduce((a, b) -> a ^ b).orElse(Boolean.FALSE);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java
index b1a9a12..195b78b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,7 +28,7 @@
     private Date date;
     private String author;
     private final String comment;
-    private final Vector files = new Vector();
+    private final Vector<RCSFile> files = new Vector<>();
 
     /**
      * Creates a new instance of a CVSEntry
@@ -48,7 +48,7 @@
      * @param revision the revision
      */
     public void addFile(final String file, final String revision) {
-        files.addElement(new RCSFile(file, revision));
+        files.add(new RCSFile(file, revision));
     }
 
     /**
@@ -58,7 +58,7 @@
      * @param previousRevision the previous revision
      */
     public void addFile(final String file, final String revision, final String previousRevision) {
-        files.addElement(new RCSFile(file, revision, previousRevision));
+        files.add(new RCSFile(file, revision, previousRevision));
     }
 
     /**
@@ -97,7 +97,7 @@
      * Gets the files in this CVSEntry
      * @return the files
      */
-    public Vector getFiles() {
+    public Vector<RCSFile> getFiles() {
         return files;
     }
 
@@ -105,6 +105,7 @@
      * Gets a String containing author, date, files and comment
      * @return a string representation of this CVSEntry
      */
+    @Override
     public String toString() {
         return getAuthor() + "\n" + getDate() + "\n" + getFiles() + "\n"
             + getComment();
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java
index b088107..7c862e9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,24 +20,23 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.TimeZone;
 
 import org.apache.tools.ant.taskdefs.AbstractCvsTask;
-import org.apache.tools.ant.util.CollectionUtils;
+import org.apache.tools.ant.taskdefs.AbstractCvsTask.Module;
 
 /**
  * A class used to parse the output of the CVS log command.
  *
  */
 class ChangeLogParser {
-    //private static final int GET_ENTRY = 0;
     private static final int GET_FILE = 1;
     private static final int GET_DATE = 2;
     private static final int GET_COMMENT = 3;
@@ -53,9 +52,6 @@
     private final SimpleDateFormat cvs1129InputDate =
         new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.US);
 
-    static {
-    }
-
     //The following is data used while processing stdout of CVS command
     private String file;
     private String date;
@@ -67,32 +63,29 @@
     private int status = GET_FILE;
 
     /** rcs entries */
-    private final Hashtable entries = new Hashtable();
+    private final Map<String, CVSEntry> entries = new Hashtable<>();
 
     private final boolean remote;
     private final String[] moduleNames;
     private final int[] moduleNameLengths;
 
     public ChangeLogParser() {
-        this(false, "", CollectionUtils.EMPTY_LIST);
+        this(false, "", Collections.emptyList());
     }
 
-    public ChangeLogParser(boolean remote, String packageName, List modules) {
+    public ChangeLogParser(boolean remote, String packageName, List<AbstractCvsTask.Module> modules) {
         this.remote = remote;
 
-        ArrayList names = new ArrayList();
+        List<String> names = new ArrayList<>();
         if (packageName != null) {
             for (StringTokenizer tok = new StringTokenizer(packageName);
                  tok.hasMoreTokens();) {
                 names.add(tok.nextToken());
             }
         }
-        for (Iterator iter = modules.iterator(); iter.hasNext();) {
-            AbstractCvsTask.Module m = (AbstractCvsTask.Module) iter.next();
-            names.add(m.getName());
-        }
+        modules.stream().map(Module::getName).forEach(names::add);
 
-        moduleNames = (String[]) names.toArray(new String[names.size()]);
+        moduleNames = names.toArray(new String[0]);
         moduleNameLengths = new int[moduleNames.length];
         for (int i = 0; i < moduleNames.length; i++) {
             moduleNameLengths[i] = moduleNames[i].length();
@@ -109,12 +102,7 @@
      * @return a list of rcs entries as an array
      */
     public CVSEntry[] getEntrySetAsArray() {
-        final CVSEntry[] array = new CVSEntry[ entries.size() ];
-        int i = 0;
-        for (Enumeration e = entries.elements(); e.hasMoreElements();) {
-            array[i++] = (CVSEntry) e.nextElement();
-        }
-        return array;
+        return entries.values().toArray(new CVSEntry[0]);
     }
 
     /**
@@ -123,7 +111,7 @@
      * @param line the line to process
      */
     public void stdout(final String line) {
-        switch(status) {
+        switch (status) {
             case GET_FILE:
                 // make sure attributes are reset when
                 // working on a 'new' file.
@@ -158,23 +146,20 @@
      * @param line the line
      */
     private void processComment(final String line) {
-        final String lineSeparator = System.getProperty("line.separator");
-        if (line.equals(
-                "=============================================================================")) {
+        if ("============================================================================="
+            .equals(line)) {
             //We have ended changelog for that particular file
             //so we can save it
-            final int end
-                = comment.length() - lineSeparator.length(); //was -1
+            final int end = comment.length() - System.lineSeparator().length(); //was -1
             comment = comment.substring(0, end);
             saveEntry();
             status = GET_FILE;
-        } else if (line.equals("----------------------------")) {
-            final int end
-                = comment.length() - lineSeparator.length(); //was -1
+        } else if ("----------------------------".equals(line)) {
+            final int end = comment.length() - System.lineSeparator().length(); //was -1
             comment = comment.substring(0, end);
             status = GET_PREVIOUS_REV;
         } else {
-            comment += line + lineSeparator;
+            comment += line + System.lineSeparator();
         }
     }
 
@@ -186,7 +171,7 @@
     private void processFile(final String line) {
         if (!remote && line.startsWith("Working file:")) {
             // CheckStyle:MagicNumber OFF
-            file = line.substring(14, line.length());
+            file = line.substring(14);
             // CheckStyle:MagicNumber ON
             status = GET_REVISION;
         } else if (remote && line.startsWith("RCS file:")) {
@@ -275,17 +260,8 @@
      * Utility method that saves the current entry.
      */
     private void saveEntry() {
-        final String entryKey = date + author + comment;
-        CVSEntry entry;
-        if (!entries.containsKey(entryKey)) {
-            Date dateObject = parseDate(date);
-            entry = new CVSEntry(dateObject, author, comment);
-            entries.put(entryKey, entry);
-        } else {
-            entry = (CVSEntry) entries.get(entryKey);
-        }
-
-        entry.addFile(file, revision, previousRevision);
+        entries.computeIfAbsent(date + author + comment,
+                k -> new CVSEntry(parseDate(date), author, comment)).addFile(file, revision, previousRevision);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java
index 81dadfd..c84f610 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,16 @@
 package org.apache.tools.ant.taskdefs.cvslib;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Properties;
 import java.util.Vector;
 
@@ -35,7 +36,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.AbstractCvsTask;
 import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Examines the output of cvs log and group related changes together.
@@ -70,7 +70,7 @@
     private File usersFile;
 
     /** User list */
-    private Vector cvsUsers = new Vector();
+    private List<CvsUser> cvsUsers = new Vector<>();
 
     /** Input dir */
     private File inputDir;
@@ -98,8 +98,7 @@
      * performed. If empty then all files in the working directory will
      * be checked.
      */
-    private final Vector filesets = new Vector();
-
+    private final List<FileSet> filesets = new Vector<>();
 
     /**
      * Set the base dir for cvs.
@@ -110,7 +109,6 @@
         this.inputDir = inputDir;
     }
 
-
     /**
      * Set the output file for the log.
      *
@@ -120,7 +118,6 @@
         this.destFile = destFile;
     }
 
-
     /**
      * Set a lookup list of user names &amp; addresses
      *
@@ -130,17 +127,15 @@
         this.usersFile = usersFile;
     }
 
-
     /**
      * Add a user to list changelog knows about.
      *
      * @param user the user
      */
     public void addUser(final CvsUser user) {
-        cvsUsers.addElement(user);
+        cvsUsers.add(user);
     }
 
-
     /**
      * Set the date at which the changelog should start.
      *
@@ -150,7 +145,6 @@
         this.startDate = start;
     }
 
-
     /**
      * Set the date at which the changelog should stop.
      *
@@ -160,7 +154,6 @@
         this.endDate = endDate;
     }
 
-
     /**
      * Set the number of days worth of log entries to process.
      *
@@ -195,7 +188,6 @@
         this.startTag = start;
     }
 
-
     /**
      * Set the tag at which the changelog should stop.
      *
@@ -211,29 +203,26 @@
      * @param fileSet a set of files about which cvs logs will be generated.
      */
     public void addFileset(final FileSet fileSet) {
-        filesets.addElement(fileSet);
+        filesets.add(fileSet);
     }
 
-
     /**
      * Execute task
      *
      * @exception BuildException if something goes wrong executing the
      *            cvs command
      */
+    @Override
     public void execute() throws BuildException {
         File savedDir = inputDir; // may be altered in validate
 
         try {
-
             validate();
             final Properties userList = new Properties();
 
             loadUserlist(userList);
 
-            final int size = cvsUsers.size();
-            for (int i = 0; i < size; i++) {
-                final CvsUser user = (CvsUser) cvsUsers.get(i);
+            for (CvsUser user : cvsUsers) {
                 user.validate();
                 userList.put(user.getUserID(), user.getDisplayname());
             }
@@ -283,18 +272,11 @@
             }
 
             // Check if list of files to check has been specified
-            if (!filesets.isEmpty()) {
-                final Enumeration e = filesets.elements();
-
-                while (e.hasMoreElements()) {
-                    final FileSet fileSet = (FileSet) e.nextElement();
-                    final DirectoryScanner scanner =
-                        fileSet.getDirectoryScanner(getProject());
-                    final String[] files = scanner.getIncludedFiles();
-
-                    for (int i = 0; i < files.length; i++) {
-                        addCommandArgument(files[i]);
-                    }
+            for (FileSet fileSet : filesets) {
+                final DirectoryScanner scanner =
+                    fileSet.getDirectoryScanner(getProject());
+                for (String file : scanner.getIncludedFiles()) {
+                    addCommandArgument(file);
                 }
             }
 
@@ -340,27 +322,20 @@
             inputDir = getProject().getBaseDir();
         }
         if (null == destFile) {
-            final String message = "Destfile must be set.";
-
-            throw new BuildException(message);
+            throw new BuildException("Destfile must be set.");
         }
         if (!inputDir.exists()) {
-            final String message = "Cannot find base dir "
-                 + inputDir.getAbsolutePath();
-
-            throw new BuildException(message);
+            throw new BuildException("Cannot find base dir %s",
+                inputDir.getAbsolutePath());
         }
         if (null != usersFile && !usersFile.exists()) {
-            final String message = "Cannot find user lookup list "
-                 + usersFile.getAbsolutePath();
-
-            throw new BuildException(message);
+            throw new BuildException("Cannot find user lookup list %s",
+                usersFile.getAbsolutePath());
         }
         if ((null != startTag || null != endTag)
             && (null != startDate || null != endDate)) {
-            final String message = "Specify either a tag or date range,"
-                + " not both";
-            throw new BuildException(message);
+            throw new BuildException(
+                "Specify either a tag or date range, not both");
         }
     }
 
@@ -375,7 +350,7 @@
          throws BuildException {
         if (null != usersFile) {
             try {
-                userList.load(new FileInputStream(usersFile));
+                userList.load(Files.newInputStream(usersFile.toPath()));
             } catch (final IOException ioe) {
                 throw new BuildException(ioe.toString(), ioe);
             }
@@ -389,23 +364,16 @@
      * @return the filtered entry set
      */
     private CVSEntry[] filterEntrySet(final CVSEntry[] entrySet) {
-        final Vector results = new Vector();
+        final List<CVSEntry> results = new ArrayList<>();
 
-        for (int i = 0; i < entrySet.length; i++) {
-            final CVSEntry cvsEntry = entrySet[i];
+        for (CVSEntry cvsEntry : entrySet) {
             final Date date = cvsEntry.getDate();
 
             //bug#30471
             //this is caused by Date.after throwing a NullPointerException
             //for some reason there's no date set in the CVSEntry
-            //Java 1.3.1 API
-            //http://java.sun.com/j2se/1.3/docs/api/java/util/Date.html#after(java.util.Date)
-            //doesn't throw NullPointerException
-            //Java 1.4.2 + 1.5 API
-            //http://java.sun.com/j2se/1.4.2/docs/api/java/util/Date.html#after(java.util.Date)
-            //according to the docs it doesn't throw, according to the bug report it does
-            //http://java.sun.com/j2se/1.5.0/docs/api/java/util/Date.html#after(java.util.Date)
-            //according to the docs it does throw
+            //https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Date.html#after(java.util.Date)
+            //according to the docs as of 1.5 it does throw
 
             //for now skip entries which are missing a date
             if (null == date) {
@@ -420,13 +388,10 @@
                 //Skip dates that are too late
                 continue;
             }
-            results.addElement(cvsEntry);
+            results.add(cvsEntry);
         }
 
-        final CVSEntry[] resultArray = new CVSEntry[results.size()];
-
-        results.copyInto(resultArray);
-        return resultArray;
+        return results.toArray(new CVSEntry[0]);
     }
 
     /**
@@ -434,9 +399,7 @@
      */
     private void replaceAuthorIdWithName(final Properties userList,
                                          final CVSEntry[] entrySet) {
-        for (int i = 0; i < entrySet.length; i++) {
-
-            final CVSEntry entry = entrySet[ i ];
+        for (final CVSEntry entry : entrySet) {
             if (userList.containsKey(entry.getAuthor())) {
                 entry.setAuthor(userList.getProperty(entry.getAuthor()));
             }
@@ -451,17 +414,11 @@
      */
     private void writeChangeLog(final CVSEntry[] entrySet)
          throws BuildException {
-        FileOutputStream output = null;
 
-        try {
-            output = new FileOutputStream(destFile);
+        try (final PrintWriter writer = new PrintWriter(
+            new OutputStreamWriter(Files.newOutputStream(destFile.toPath()), StandardCharsets.UTF_8))) {
 
-            final PrintWriter writer =
-                new PrintWriter(new OutputStreamWriter(output, "UTF-8"));
-
-            final ChangeLogWriter serializer = new ChangeLogWriter();
-
-            serializer.printChangeLog(writer, entrySet);
+            new ChangeLogWriter().printChangeLog(writer, entrySet);
 
             if (writer.checkError()) {
                 throw new IOException("Encountered an error writing changelog");
@@ -470,9 +427,6 @@
             getProject().log(uee.toString(), Project.MSG_ERR);
         } catch (final IOException ioe) {
             throw new BuildException(ioe.toString(), ioe);
-        } finally {
-            FileUtils.close(output);
         }
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java
index ce92327..c65261d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,9 +20,9 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
-import java.util.Enumeration;
 import java.util.TimeZone;
 
+import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.DOMElementWriter;
 import org.apache.tools.ant.util.DOMUtils;
 import org.w3c.dom.Document;
@@ -36,9 +36,11 @@
     /** output format for dates written to xml file */
     private final SimpleDateFormat outputDate
         = new SimpleDateFormat("yyyy-MM-dd");
+
     /** output format for times written to xml file */
     private SimpleDateFormat outputTime
         = new SimpleDateFormat("HH:mm");
+
     /** stateless helper for writing the XML document */
     private static final DOMElementWriter DOM_WRITER = new DOMElementWriter();
 
@@ -62,20 +64,17 @@
             Element root = doc.createElement("changelog");
             DOM_WRITER.openElement(root, output, 0, "\t");
             output.println();
-            for (int i = 0; i < entries.length; i++) {
-                final CVSEntry entry = entries[i];
-
+            for (final CVSEntry entry : entries) {
                 printEntry(doc, output, entry);
             }
             DOM_WRITER.closeElement(root, output, 0, "\t", true);
             output.flush();
             output.close();
         } catch (IOException e) {
-            throw new org.apache.tools.ant.BuildException(e);
+            throw new BuildException(e);
         }
     }
 
-
     /**
      * Print out an individual entry in changelog.
      *
@@ -92,11 +91,7 @@
                                    outputTime.format(entry.getDate()));
         DOMUtils.appendCDATAElement(ent, "author", entry.getAuthor());
 
-        final Enumeration enumeration = entry.getFiles().elements();
-
-        while (enumeration.hasMoreElements()) {
-            final RCSFile file = (RCSFile) enumeration.nextElement();
-
+        for (RCSFile file : entry.getFiles()) {
             Element f = DOMUtils.createChildElement(ent, "file");
             DOMUtils.appendCDATAElement(f, "name", file.getName());
             DOMUtils.appendTextElement(f, "revision", file.getRevision());
@@ -111,4 +106,3 @@
         DOM_WRITER.write(ent, output, 1, "\t");
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java
index 3941304..bc50afa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,22 +19,20 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;
-import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.AbstractCvsTask;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.apache.tools.ant.util.DOMElementWriter;
 import org.apache.tools.ant.util.DOMUtils;
 import org.apache.tools.ant.util.FileUtils;
@@ -151,7 +149,7 @@
     /**
      * temporary list of package names.
      */
-    private List packageNames = new ArrayList();
+    private List<String> packageNames = new ArrayList<>();
 
     /**
      * temporary list of "File:" + package name + "/" for all packages.
@@ -228,7 +226,6 @@
         ignoreRemoved = b;
     }
 
-
     /**
      * Execute task.
      *
@@ -296,10 +293,9 @@
      */
     private CvsTagEntry[] parseRDiff(File tmpFile) throws BuildException {
         // parse the output of the command
-        BufferedReader reader = null;
 
-        try {
-            reader = new BufferedReader(new FileReader(tmpFile)); //NOSONAR
+        try (BufferedReader reader =
+            new BufferedReader(new FileReader(tmpFile))) {
 
             // entries are of the form:
             //CVS 1.11
@@ -315,7 +311,7 @@
             // File testantoine/antoine.bat is removed; TESTANTOINE_1 revision 1.1.1.1
             //
             // get rid of 'File module/"
-            Vector entries = new Vector();
+            List<CvsTagEntry> entries = new ArrayList<>();
 
             String line = reader.readLine();
 
@@ -324,6 +320,7 @@
                                          packageNamePrefixLengths);
                 if (line != null) {
                     // use || in a perl like fashion
+                    @SuppressWarnings("unused")
                     boolean processed
                         =  doFileIsNew(entries, line)
                         || doFileHasChanged(entries, line)
@@ -332,24 +329,13 @@
                 line = reader.readLine();
             }
 
-            CvsTagEntry[] array = new CvsTagEntry[entries.size()];
-            entries.copyInto(array);
-
-            return array;
+            return entries.toArray(new CvsTagEntry[0]);
         } catch (IOException e) {
             throw new BuildException("Error in parsing", e);
-        } finally {
-            if (reader != null) {
-                try {
-                    reader.close();
-                } catch (IOException e) {
-                    log(e.toString(), Project.MSG_ERR);
-                }
-            }
         }
     }
 
-    private boolean doFileIsNew(Vector entries, String line) {
+    private boolean doFileIsNew(List<CvsTagEntry> entries, String line) {
         int index = line.indexOf(FILE_IS_NEW);
         if (index == -1) {
             return false;
@@ -363,12 +349,12 @@
             rev = line.substring(indexrev + REVISION.length());
         }
         CvsTagEntry entry = new CvsTagEntry(filename, rev);
-        entries.addElement(entry);
+        entries.add(entry);
         log(entry.toString(), Project.MSG_VERBOSE);
         return true;
     }
 
-    private boolean doFileHasChanged(Vector entries, String line) {
+    private boolean doFileHasChanged(List<CvsTagEntry> entries, String line) {
         int index = line.indexOf(FILE_HAS_CHANGED);
         if (index == -1) {
             return false;
@@ -384,12 +370,12 @@
         CvsTagEntry entry = new CvsTagEntry(filename,
                                             revision,
                                             prevRevision);
-        entries.addElement(entry);
+        entries.add(entry);
         log(entry.toString(), Project.MSG_VERBOSE);
         return true;
     }
 
-    private boolean doFileWasRemoved(Vector entries, String line) {
+    private boolean doFileWasRemoved(List<CvsTagEntry> entries, String line) {
         if (ignoreRemoved) {
             return false;
         }
@@ -405,7 +391,7 @@
             rev = line.substring(indexrev + REVISION.length());
         }
         CvsTagEntry entry = new CvsTagEntry(filename, null, rev);
-        entries.addElement(entry);
+        entries.add(entry);
         log(entry.toString(), Project.MSG_VERBOSE);
         return true;
     }
@@ -417,11 +403,8 @@
      * @exception BuildException if an error occurs
      */
     private void writeTagDiff(CvsTagEntry[] entries) throws BuildException {
-        FileOutputStream output = null;
-        try {
-            output = new FileOutputStream(mydestfile);
-            PrintWriter writer = new PrintWriter(
-                                     new OutputStreamWriter(output, "UTF-8"));
+        try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(
+            Files.newOutputStream(mydestfile.toPath()), StandardCharsets.UTF_8))) {
             writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
             Document doc = DOMUtils.newDocument();
             Element root = doc.createElement("tagdiff");
@@ -438,7 +421,7 @@
 
             root.setAttribute("cvsroot", getCvsRoot());
             root.setAttribute("package",
-                              CollectionUtils.flattenToString(packageNames));
+                    String.join(",", packageNames));
             DOM_WRITER.openElement(root, writer, 0, "\t");
             writer.println();
             for (CvsTagEntry entry : entries) {
@@ -449,19 +432,10 @@
             if (writer.checkError()) {
                 throw new IOException("Encountered an error writing tagdiff");
             }
-            writer.close();
         } catch (UnsupportedEncodingException uee) {
             log(uee.toString(), Project.MSG_ERR);
         } catch (IOException ioe) {
             throw new BuildException(ioe.toString(), ioe);
-        } finally {
-            if (null != output) {
-                try {
-                    output.close();
-                } catch (IOException ioe) {
-                    log(ioe.toString(), Project.MSG_ERR);
-                }
-            }
         }
     }
 
@@ -494,7 +468,7 @@
      * @exception BuildException if a parameter is not correctly set
      */
     private void validate() throws BuildException {
-        if (null == mypackage && getModules().size() == 0) {
+        if (null == mypackage && getModules().isEmpty()) {
             throw new BuildException("Package/module must be set.");
         }
 
@@ -507,8 +481,8 @@
         }
 
         if (null != mystartTag && null != mystartDate) {
-            throw new BuildException("Only one of start tag and start date "
-                                     + "must be set.");
+            throw new BuildException(
+                "Only one of start tag and start date must be set.");
         }
 
         if (null == myendTag && null == myendDate) {
@@ -516,8 +490,8 @@
         }
 
         if (null != myendTag && null != myendDate) {
-            throw new BuildException("Only one of end tag and end date must "
-                                     + "be set.");
+            throw new BuildException(
+                "Only one of end tag and end date must be set.");
         }
     }
 
@@ -535,8 +509,7 @@
                 addCommandArgument(pack);
             }
         }
-        for (Iterator iter = getModules().iterator(); iter.hasNext();) {
-            AbstractCvsTask.Module m = (AbstractCvsTask.Module) iter.next();
+        for (Module m : getModules()) {
             packageNames.add(m.getName());
             // will be added to command line in super.execute()
         }
@@ -548,7 +521,6 @@
         }
     }
 
-
     /**
      * removes a "File: module/" prefix if present.
      *
@@ -560,17 +532,11 @@
         if (line.length() < FILE_STRING_LENGTH) {
             return null;
         }
-        boolean matched = false;
         for (int i = 0; i < packagePrefixes.length; i++) {
             if (line.startsWith(packagePrefixes[i])) {
-                matched = true;
-                line = line.substring(prefixLengths[i]);
-                break;
+                return line.substring(prefixLengths[i]);
             }
         }
-        if (!matched) {
-            line = line.substring(FILE_STRING_LENGTH);
-        }
-        return line;
+        return line.substring(FILE_STRING_LENGTH);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagEntry.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagEntry.java
index 6e349c7..d1e5d7a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagEntry.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagEntry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -89,8 +89,9 @@
      * Gets a String containing filename and difference from previous version
      * @return a string representation of this CVSTagEntry
      */
+    @Override
     public String toString() {
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         buffer.append(filename);
         if (revision == null) {
             buffer.append(" was removed");
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java
index 85a2fc6..85edc91 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,10 +26,10 @@
 public class CvsUser {
     /** The user's Id */
     private String userID;
+
     /** The user's full name */
     private String displayName;
 
-
     /**
      * Set the user's fullname
      *
@@ -39,7 +39,6 @@
         this.displayName = displayName;
     }
 
-
     /**
      * Set the user's id
      *
@@ -49,7 +48,6 @@
         this.userID = userID;
     }
 
-
     /**
      * Get the user's id.
      *
@@ -59,7 +57,6 @@
         return userID;
     }
 
-
     /**
      * Get the user's full name
      *
@@ -69,7 +66,6 @@
         return displayName;
     }
 
-
     /**
      * Validate that this object is configured.
      *
@@ -78,16 +74,11 @@
      */
     public void validate() throws BuildException {
         if (null == userID) {
-            final String message = "Username attribute must be set.";
-
-            throw new BuildException(message);
+            throw new BuildException("Username attribute must be set.");
         }
         if (null == displayName) {
-            final String message =
-                "Displayname attribute must be set for userID " + userID;
-
-            throw new BuildException(message);
+            throw new BuildException(
+                "Displayname attribute must be set for userID %s", userID);
         }
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsVersion.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsVersion.java
index 618da4e..bad68b7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsVersion.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsVersion.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,6 +43,7 @@
 public class CvsVersion extends AbstractCvsTask {
     static final long VERSION_1_11_2 = 11102;
     static final long MULTIPLY = 100;
+
     private String clientVersion;
     private String serverVersion;
     private String clientVersionProperty;
@@ -55,6 +56,7 @@
     public String getClientVersion() {
         return clientVersion;
     }
+
     /**
      * Get the CVS server version
      * @return CVS server version
@@ -62,6 +64,7 @@
     public String getServerVersion() {
         return serverVersion;
     }
+
     /**
      * Set a property where to store the CVS client version
      * @param clientVersionProperty  property for CVS client version
@@ -77,6 +80,7 @@
     public void setServerVersionProperty(String serverVersionProperty) {
         this.serverVersionProperty = serverVersionProperty;
     }
+
     /**
      * Find out if the server version supports log with S option
      * @return  boolean indicating if the server version supports log with S option
@@ -90,24 +94,26 @@
         long version = 0;
         while (tokenizer.hasMoreTokens()) {
             String s = tokenizer.nextToken();
-            int i = 0;
+            int i;
             for (i = 0; i < s.length(); i++) {
                 if (!Character.isDigit(s.charAt(i))) {
                     break;
                 }
             }
             String s2 = s.substring(0, i);
-            version = version + counter * Long.parseLong(s2);
+            version += counter * Long.parseLong(s2);
             if (counter == 1) {
                 break;
             }
-            counter = counter / MULTIPLY;
+            counter /= MULTIPLY;
         }
-        return (version >= VERSION_1_11_2);
+        return version >= VERSION_1_11_2;
     }
+
     /**
      * the execute method running CvsVersion
      */
+    @Override
     public void execute() {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         this.setOutputStream(bos);
@@ -127,9 +133,9 @@
         while (haveReadAhead || st.hasMoreTokens()) {
             String currentToken = haveReadAhead ? cachedVersion : st.nextToken();
             haveReadAhead = false;
-            if (currentToken.equals("Client:")) {
+            if ("Client:".equals(currentToken)) {
                 client = true;
-            } else if (currentToken.equals("Server:")) {
+            } else if ("Server:".equals(currentToken)) {
                 server = true;
             } else if (currentToken.startsWith("(CVS")
                        && currentToken.endsWith(")")) {
@@ -151,7 +157,7 @@
                 }
                 server = false;
                 cvs = null;
-            } else if (currentToken.equals("(client/server)")
+            } else if ("(client/server)".equals(currentToken)
                        && cvs != null && cachedVersion != null
                        && !client && !server) {
                 client = server = true;
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java
index 70a8cf3..2aa42cd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,12 +26,10 @@
     private String revision;
     private String previousRevision;
 
-
-    RCSFile(final String name, final String rev) {
-        this(name, rev, null);
+    RCSFile(final String name, final String revision) {
+        this(name, revision, null);
     }
 
-
     RCSFile(final String name,
                   final String revision,
                   final String previousRevision) {
@@ -66,4 +64,3 @@
         return previousRevision;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingOutputStream.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingOutputStream.java
index f2b61cf..2f4cdf5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingOutputStream.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,8 +39,8 @@
      *
      * @param line the line to log.
      */
+    @Override
     protected void processLine(final String line) {
         parser.stdout(line);
     }
 }
-
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..021eb5a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,9 @@
 package org.apache.tools.ant.taskdefs.cvslib;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 
-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.
@@ -34,7 +33,6 @@
             new ByteArrayOutputStream());
     }
 
-
     String getErrors() {
         try {
             final ByteArrayOutputStream error
@@ -46,16 +44,10 @@
         }
     }
 
-
+    @Override
     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..791d8d9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
@@ -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
@@ -67,6 +66,8 @@
 java=org.apache.tools.ant.taskdefs.Java
 javac=org.apache.tools.ant.taskdefs.Javac
 javadoc=org.apache.tools.ant.taskdefs.Javadoc
+jmod=org.apache.tools.ant.taskdefs.modules.Jmod
+link=org.apache.tools.ant.taskdefs.modules.Link
 length=org.apache.tools.ant.taskdefs.Length
 loadfile=org.apache.tools.ant.taskdefs.LoadFile
 loadproperties=org.apache.tools.ant.taskdefs.LoadProperties
@@ -92,6 +93,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
@@ -108,6 +110,7 @@
 unjar=org.apache.tools.ant.taskdefs.Expand
 untar=org.apache.tools.ant.taskdefs.Untar
 unwar=org.apache.tools.ant.taskdefs.Expand
+unxz=org.apache.tools.ant.taskdefs.optional.xz.Unxz
 unzip=org.apache.tools.ant.taskdefs.Expand
 uptodate=org.apache.tools.ant.taskdefs.UpToDate
 waitfor=org.apache.tools.ant.taskdefs.WaitFor
@@ -115,6 +118,7 @@
 whichresource=org.apache.tools.ant.taskdefs.WhichResource
 xmlproperty=org.apache.tools.ant.taskdefs.XmlProperty
 xslt=org.apache.tools.ant.taskdefs.XSLTProcess
+xz=org.apache.tools.ant.taskdefs.optional.xz.Xz
 zip=org.apache.tools.ant.taskdefs.Zip
 
 # optional tasks
@@ -146,6 +150,7 @@
 ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar
 ftp=org.apache.tools.ant.taskdefs.optional.net.FTP
 image=org.apache.tools.ant.taskdefs.optional.image.Image
+imageio=org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
 iplanet-ejbc=org.apache.tools.ant.taskdefs.optional.ejb.IPlanetEjbcTask
 jarlib-available=org.apache.tools.ant.taskdefs.optional.extension.JarLibAvailableTask
 jarlib-display=org.apache.tools.ant.taskdefs.optional.extension.JarLibDisplayTask
@@ -158,6 +163,7 @@
 jjtree=org.apache.tools.ant.taskdefs.optional.javacc.JJTree
 junit=org.apache.tools.ant.taskdefs.optional.junit.JUnitTask
 junitreport=org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator
+junitlauncher=org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask
 native2ascii=org.apache.tools.ant.taskdefs.optional.Native2Ascii
 netrexxc=org.apache.tools.ant.taskdefs.optional.NetRexxC
 propertyfile=org.apache.tools.ant.taskdefs.optional.PropertyFile
@@ -194,7 +200,6 @@
 wljspc=org.apache.tools.ant.taskdefs.optional.jsp.WLJspc
 xmlvalidate=org.apache.tools.ant.taskdefs.optional.XMLValidateTask
 
-
 # deprecated ant tasks (kept for back compatibility)
 copydir=org.apache.tools.ant.taskdefs.Copydir
 copyfile=org.apache.tools.ant.taskdefs.Copyfile
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java
index 25e3555..359cbc2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailAddress.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -119,7 +119,7 @@
     private String trim(String t, boolean trimAngleBrackets) {
         int start = 0;
         int end = t.length();
-        boolean trim = false;
+        boolean trim;
         do {
             trim = false;
             if (t.charAt(end - 1) == ')'
@@ -140,7 +140,6 @@
         return t.substring(start, end);
     }
 
-
     /**
      * Sets the personal / display name of the address.
      *
@@ -150,7 +149,6 @@
         this.name = name;
     }
 
-
     /**
      * Sets the email address.
      *
@@ -160,21 +158,19 @@
         this.address = address;
     }
 
-
     /**
      * Constructs a string "name &lt;address&gt;" or "address"
      *
      * @return a string representation of the address
      */
+    @Override
     public String toString() {
         if (name == null) {
             return address;
-        } else {
-            return name + " <" + address + ">";
         }
+        return name + " <" + address + ">";
     }
 
-
     /**
      * Returns the address
      *
@@ -184,7 +180,6 @@
         return address;
     }
 
-
     /**
      * Returns the display name
      *
@@ -194,4 +189,3 @@
         return name;
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java
index 9715c12..5336d06 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,6 @@
 import java.io.File;
 import java.util.StringTokenizer;
 import java.util.Vector;
-
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
@@ -60,6 +59,7 @@
          *
          * @return a list of valid entries
          */
+        @Override
         public String[] getValues() {
             return new String[] {AUTO, MIME, UU, PLAIN};
         }
@@ -82,16 +82,16 @@
     /** sender  */
     private EmailAddress from = null;
     /** replyto */
-    private Vector replyToList = new Vector();
+    private Vector<EmailAddress> replyToList = new Vector<>();
     /** TO recipients  */
-    private Vector toList = new Vector();
+    private Vector<EmailAddress> toList = new Vector<>();
     /** CC (Carbon Copy) recipients  */
-    private Vector ccList = new Vector();
+    private Vector<EmailAddress> ccList = new Vector<>();
     /** BCC (Blind Carbon Copy) recipients  */
-    private Vector bccList = new Vector();
+    private Vector<EmailAddress> bccList = new Vector<>();
 
     /** generic headers */
-    private Vector headers = new Vector();
+    private Vector<Header> headers = new Vector<>();
 
     /** file list  */
     private Path attachments = null;
@@ -165,7 +165,7 @@
      * @param port The port to use.
      */
     public void setMailport(int port) {
-        this.port = Integer.valueOf(port);
+        this.port = port;
     }
 
     /**
@@ -193,8 +193,8 @@
      */
     public void setMessage(String message) {
         if (this.message != null) {
-            throw new BuildException("Only one message can be sent in an "
-                 + "email");
+            throw new BuildException(
+                "Only one message can be sent in an email");
         }
         this.message = new Message(message);
         this.message.setProject(getProject());
@@ -207,8 +207,8 @@
      */
     public void setMessageFile(File file) {
         if (this.message != null) {
-            throw new BuildException("Only one message can be sent in an "
-                 + "email");
+            throw new BuildException(
+                "Only one message can be sent in an email");
         }
         this.message = new Message(file);
         this.message.setProject(getProject());
@@ -288,7 +288,7 @@
      * @param address An email address.
      */
     public void addTo(EmailAddress address) {
-        toList.addElement(address);
+        toList.add(address);
     }
 
     /**
@@ -300,7 +300,7 @@
         StringTokenizer tokens = new StringTokenizer(list, ",");
 
         while (tokens.hasMoreTokens()) {
-            toList.addElement(new EmailAddress(tokens.nextToken()));
+            toList.add(new EmailAddress(tokens.nextToken()));
         }
     }
 
@@ -310,7 +310,7 @@
      * @param address The email address.
      */
     public void addCc(EmailAddress address) {
-        ccList.addElement(address);
+        ccList.add(address);
     }
 
     /**
@@ -322,7 +322,7 @@
         StringTokenizer tokens = new StringTokenizer(list, ",");
 
         while (tokens.hasMoreTokens()) {
-            ccList.addElement(new EmailAddress(tokens.nextToken()));
+            ccList.add(new EmailAddress(tokens.nextToken()));
         }
     }
 
@@ -332,7 +332,7 @@
      * @param address The email address.
      */
     public void addBcc(EmailAddress address) {
-        bccList.addElement(address);
+        bccList.add(address);
     }
 
     /**
@@ -344,7 +344,7 @@
         StringTokenizer tokens = new StringTokenizer(list, ",");
 
         while (tokens.hasMoreTokens()) {
-            bccList.addElement(new EmailAddress(tokens.nextToken()));
+            bccList.add(new EmailAddress(tokens.nextToken()));
         }
     }
 
@@ -439,6 +439,7 @@
     /**
      * Send an email.
      */
+    @Override
     public void execute() {
         Message savedMessage = message;
 
@@ -448,16 +449,9 @@
             // prepare for the auto select mechanism
             boolean autoFound = false;
             // try MIME format
-            if (encoding.equals(MIME)
-                 || (encoding.equals(AUTO) && !autoFound)) {
+            if (MIME.equals(encoding) || AUTO.equals(encoding)) {
                 try {
-                    //check to make sure that activation.jar
-                    //and mail.jar are available - see bug 31969
-                    Class.forName("javax.activation.DataHandler");
-                    Class.forName("javax.mail.internet.MimeMessage");
-
-                    mailer = (Mailer) ClasspathUtils.newInstance(
-                            "org.apache.tools.ant.taskdefs.email.MimeMailer",
+                    mailer = ClasspathUtils.newInstance(getMailerImplementation(),
                             EmailTask.class.getClassLoader(), Mailer.class);
                     autoFound = true;
 
@@ -468,20 +462,20 @@
             }
             // SMTP auth only allowed with MIME mail
             if (!autoFound && ((user != null) || (password != null))
-                && (encoding.equals(UU) || encoding.equals(PLAIN))) {
+                && (UU.equals(encoding) || PLAIN.equals(encoding))) {
                 throw new BuildException("SMTP auth only possible with MIME mail");
             }
             // SSL only allowed with MIME mail
             if (!autoFound  && (ssl || starttls)
-                && (encoding.equals(UU) || encoding.equals(PLAIN))) {
-                throw new BuildException("SSL and STARTTLS only possible with"
-                                         + " MIME mail");
+                && (UU.equals(encoding) || PLAIN.equals(encoding))) {
+                throw new BuildException(
+                    "SSL and STARTTLS only possible with MIME mail");
             }
             // try UU format
-            if (encoding.equals(UU)
-                 || (encoding.equals(AUTO) && !autoFound)) {
+            if (UU.equals(encoding)
+                 || (AUTO.equals(encoding) && !autoFound)) {
                 try {
-                    mailer = (Mailer) ClasspathUtils.newInstance(
+                    mailer = ClasspathUtils.newInstance(
                             "org.apache.tools.ant.taskdefs.email.UUMailer",
                             EmailTask.class.getClassLoader(), Mailer.class);
                     autoFound = true;
@@ -491,16 +485,16 @@
                 }
             }
             // try plain format
-            if (encoding.equals(PLAIN)
-                 || (encoding.equals(AUTO) && !autoFound)) {
+            if (PLAIN.equals(encoding)
+                 || (AUTO.equals(encoding) && !autoFound)) {
                 mailer = new PlainMailer();
                 autoFound = true;
                 log("Using plain mail", Project.MSG_VERBOSE);
             }
             // a valid mailer must be present by now
             if (mailer == null) {
-                throw new BuildException("Failed to initialise encoding: "
-                     + encoding);
+                throw new BuildException("Failed to initialise encoding: %s",
+                    encoding);
             }
             // a valid message is required
             if (message == null) {
@@ -513,33 +507,33 @@
             }
             // at least one address to send to/cc/bcc is required
             if (toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty()) {
-                throw new BuildException("At least one of to, cc or bcc must "
-                     + "be supplied");
+                throw new BuildException(
+                    "At least one of to, cc or bcc must be supplied");
             }
             // set the mimetype if not done already (and required)
             if (messageMimeType != null) {
                 if (message.isMimeTypeSpecified()) {
-                    throw new BuildException("The mime type can only be "
-                         + "specified in one location");
+                    throw new BuildException(
+                        "The mime type can only be specified in one location");
                 }
                 message.setMimeType(messageMimeType);
             }
             // set the character set if not done already (and required)
             if (charset != null) {
                 if (message.getCharset() != null) {
-                    throw new BuildException("The charset can only be "
-                         + "specified in one location");
+                    throw new BuildException(
+                        "The charset can only be specified in one location");
                 }
                 message.setCharset(charset);
             }
             message.setInputEncoding(messageFileInputEncoding);
 
             // identify which files should be attached
-            Vector<File> files = new Vector<File>();
+            Vector<File> files = new Vector<>();
+
             if (attachments != null) {
                 for (Resource r : attachments) {
-                    files.addElement(r.as(FileProvider.class)
-                                     .getFile());
+                    files.add(r.as(FileProvider.class).getFile());
                 }
             }
             // let the user know what's going to happen
@@ -553,7 +547,7 @@
             // pass the params to the mailer
             mailer.setHost(host);
             if (port != null) {
-                mailer.setPort(port.intValue());
+                mailer.setPort(port);
                 mailer.setPortExplicitlySpecified(true);
             } else {
                 mailer.setPort(SMTP_PORT);
@@ -599,6 +593,32 @@
         }
     }
 
+    private String getMailerImplementation() {
+        //check to make sure that activation.jar
+        //and mail.jar are available - see bug 31969
+        try {
+            Class.forName("jakarta.activation.DataHandler");
+            Class.forName("jakarta.mail.internet.MimeMessage");
+
+            return "org.apache.tools.ant.taskdefs.email.JakartaMimeMailer";
+        } catch (ClassNotFoundException cnfe) {
+            logBuildException("Could not find Jakarta MIME mail: ",
+                    new BuildException(cnfe));
+        }
+
+        try {
+            Class.forName("javax.activation.DataHandler");
+            Class.forName("javax.mail.internet.MimeMessage");
+
+            return "org.apache.tools.ant.taskdefs.email.MimeMailer";
+        } catch (ClassNotFoundException cnfe) {
+            logBuildException("Could not find MIME mail: ",
+                    new BuildException(cnfe));
+        }
+
+        return "org.apache.tools.ant.taskdefs.email.Mailer";
+    }
+
     private void logBuildException(String reason, BuildException e) {
         Throwable t = e.getCause() == null ? e : e.getCause();
         log(reason + t.getMessage(), Project.MSG_WARN);
@@ -636,4 +656,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/Header.java b/src/main/org/apache/tools/ant/taskdefs/email/Header.java
index 6bcfb66..36bc8ec 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/Header.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/Header.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,9 @@
 package org.apache.tools.ant.taskdefs.email;
 
 /**
- * Class representing a generic e-mail header.
+ * Class representing a generic key-value header.
+ * TODO: This should be moved out of the email package
+ *
  * @since Ant 1.7
  */
 public class Header {
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java
new file mode 100644
index 0000000..a1ebb98
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java
@@ -0,0 +1,340 @@
+/*
+ *  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
+ *
+ *      https://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.email;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import jakarta.activation.DataHandler;
+import jakarta.activation.DataSource;
+import jakarta.activation.FileDataSource;
+import jakarta.mail.Address;
+import jakarta.mail.Authenticator;
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
+import jakarta.mail.PasswordAuthentication;
+import jakarta.mail.SendFailedException;
+import jakarta.mail.Session;
+import jakarta.mail.Transport;
+import jakarta.mail.internet.AddressException;
+import jakarta.mail.internet.InternetAddress;
+import jakarta.mail.internet.MimeBodyPart;
+import jakarta.mail.internet.MimeMessage;
+import jakarta.mail.internet.MimeMultipart;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+
+/**
+ * Uses the JakartaMail classes to send Mime format email.
+ *
+ * @since Ant 1.10.13
+ */
+public class JakartaMimeMailer extends Mailer {
+    private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
+
+    private static final String GENERIC_ERROR =
+        "Problem while sending mime mail:";
+
+    /** Default character set */
+    private static final String DEFAULT_CHARSET
+        = System.getProperty("file.encoding");
+
+    // To work properly with national charsets we have to use
+    // implementation of interface jakarta.activation.DataSource
+    /**
+     * String data source implementation.
+     */
+    class StringDataSource implements DataSource {
+        private String data = null;
+        private String type = null;
+        private String charset = null;
+        private ByteArrayOutputStream out;
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            if (data == null && out == null) {
+                throw new IOException("No data");
+            }
+            if (out != null) {
+                final String encodedOut = out.toString(charset);
+                data = (data != null) ? data.concat(encodedOut) : encodedOut;
+                out = null;
+            }
+            return new ByteArrayInputStream(data.getBytes(charset));
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            out = (out == null) ? new ByteArrayOutputStream() : out;
+            return out;
+        }
+
+        public void setContentType(final String type) {
+            this.type = type.toLowerCase(Locale.ENGLISH);
+        }
+
+        @Override
+        public String getContentType() {
+            if (type != null && type.indexOf("charset") > 0
+                && type.startsWith("text/")) {
+                return type;
+            }
+            // Must be like "text/plain; charset=windows-1251"
+            return (type != null ? type : "text/plain") +
+                    "; charset=" + charset;
+        }
+
+        @Override
+        public String getName() {
+            return "StringDataSource";
+        }
+
+        public void setCharset(final String charset) {
+            this.charset = charset;
+        }
+
+        public String getCharset() {
+            return charset;
+        }
+    }
+
+    /**
+     * Send the email.
+     *
+     * @throws BuildException if the email can't be sent.
+     */
+    @Override
+    public void send() {
+        try {
+            final Properties props = new Properties();
+
+            props.put("mail.smtp.host", host);
+            props.put("mail.smtp.port", String.valueOf(port));
+
+            // Aside, the JDK is clearly unaware of the Scottish
+            // 'session', which involves excessive quantities of
+            // alcohol :-)
+            Session sesh;
+            Authenticator auth = null;
+            if (SSL) {
+                try {
+                    final Provider p =
+                        Class.forName("com.sun.net.ssl.internal.ssl.Provider")
+                            .asSubclass(Provider.class).getDeclaredConstructor().newInstance();
+                    Security.addProvider(p);
+                } catch (final Exception e) {
+                    throw new BuildException(
+                        "could not instantiate ssl security provider, check that you have JSSE in your classpath");
+                }
+                // SMTP provider
+                props.put("mail.smtp.socketFactory.class", SSL_FACTORY);
+                props.put("mail.smtp.socketFactory.fallback", "false");
+                props.put("mail.smtps.host", host);
+                if (isPortExplicitlySpecified()) {
+                    props.put("mail.smtps.port", String.valueOf(port));
+                    props.put("mail.smtp.socketFactory.port",
+                              String.valueOf(port));
+                }
+            }
+            if (user != null || password != null) {
+                props.put("mail.smtp.auth", "true");
+                auth = new SimpleAuthenticator(user, password);
+            }
+            if (isStartTLSEnabled()) {
+                props.put("mail.smtp.starttls.enable", "true");
+            }
+            sesh = Session.getInstance(props, auth);
+
+            //create the message
+            final MimeMessage msg = new MimeMessage(sesh);
+            final MimeMultipart attachments = new MimeMultipart();
+
+            //set the sender
+            if (from.getName() == null) {
+                msg.setFrom(new InternetAddress(from.getAddress()));
+            } else {
+                msg.setFrom(new InternetAddress(from.getAddress(),
+                    from.getName()));
+            }
+            // set the reply to addresses
+            msg.setReplyTo(internetAddresses(replyToList));
+            msg.setRecipients(Message.RecipientType.TO,
+                internetAddresses(toList));
+            msg.setRecipients(Message.RecipientType.CC,
+                internetAddresses(ccList));
+            msg.setRecipients(Message.RecipientType.BCC,
+                internetAddresses(bccList));
+
+            // Choosing character set of the mail message
+            // First: looking it from MimeType
+            String charset = parseCharSetFromMimeType(message.getMimeType());
+            if (charset != null) {
+                // Assign/reassign message charset from MimeType
+                message.setCharset(charset);
+            } else {
+                // Next: looking if charset having explicit definition
+                charset = message.getCharset();
+                if (charset == null) {
+                    // Using default
+                    charset = DEFAULT_CHARSET;
+                    message.setCharset(charset);
+                }
+            }
+            // Using jakarta.activation.DataSource paradigm
+            final StringDataSource sds = new StringDataSource();
+            sds.setContentType(message.getMimeType());
+            sds.setCharset(charset);
+
+            if (subject != null) {
+                msg.setSubject(subject, charset);
+            }
+            msg.addHeader("Date", getDate());
+
+            if (headers != null) {
+                for (Header h : headers) {
+                    msg.addHeader(h.getName(), h.getValue());
+                }
+            }
+            final PrintStream out = new PrintStream(sds.getOutputStream());
+            message.print(out);
+            out.close();
+
+            final MimeBodyPart textbody = new MimeBodyPart();
+            textbody.setDataHandler(new DataHandler(sds));
+            attachments.addBodyPart(textbody);
+
+            for (File file : files) {
+                MimeBodyPart body = new MimeBodyPart();
+                if (!file.exists() || !file.canRead()) {
+                    throw new BuildException(
+                        "File \"%s\" does not exist or is not readable.",
+                        file.getAbsolutePath());
+                }
+                final FileDataSource fileData = new FileDataSource(file);
+                final DataHandler fileDataHandler = new DataHandler(fileData);
+
+                body.setDataHandler(fileDataHandler);
+                body.setFileName(file.getName());
+                attachments.addBodyPart(body);
+            }
+            msg.setContent(attachments);
+            try {
+                // Send the message using SMTP, or SMTPS if the host uses SSL
+                final Transport transport = sesh.getTransport(SSL ? "smtps" : "smtp");
+                transport.connect(host, user, password);
+                transport.sendMessage(msg, msg.getAllRecipients());
+            } catch (final SendFailedException sfe) {
+                if (!shouldIgnoreInvalidRecipients()) {
+                    throw new BuildException(GENERIC_ERROR, sfe);
+                }
+                if (sfe.getValidSentAddresses() == null
+                           || sfe.getValidSentAddresses().length == 0) {
+                    throw new BuildException("Couldn't reach any recipient",
+                                             sfe);
+                }
+                Address[] invalid = sfe.getInvalidAddresses();
+                if (invalid == null) {
+                    invalid = new Address[0];
+                }
+                for (Address address : invalid) {
+                    didntReach(address, "invalid", sfe);
+                }
+                Address[] validUnsent = sfe.getValidUnsentAddresses();
+                if (validUnsent == null) {
+                    validUnsent = new Address[0];
+                }
+                for (Address address : validUnsent) {
+                    didntReach(address, "valid", sfe);
+                }
+            }
+        } catch (MessagingException | IOException e) {
+            throw new BuildException(GENERIC_ERROR, e);
+        }
+    }
+
+    private static InternetAddress[] internetAddresses(final Vector<EmailAddress> list)
+        throws AddressException, UnsupportedEncodingException {
+
+        final List<InternetAddress> addrs = new ArrayList<>();
+
+        for (final EmailAddress addr : list) {
+            final String name = addr.getName();
+            addrs.add((name == null)
+                ? new InternetAddress(addr.getAddress())
+                : new InternetAddress(addr.getAddress(), name));
+        }
+        return addrs.toArray(new InternetAddress[addrs.size()]);
+    }
+
+    private String parseCharSetFromMimeType(final String type) {
+        if (type == null) {
+            return null;
+        }
+        final int pos = type.indexOf("charset");
+        if (pos < 0) {
+            return null;
+        }
+        // Assuming mime type in form "text/XXXX; charset=XXXXXX"
+        final StringTokenizer token = new StringTokenizer(type.substring(pos), "=; ");
+        token.nextToken(); // Skip 'charset='
+        return token.nextToken();
+    }
+
+    private void didntReach(final Address addr, final String category,
+                            final MessagingException ex) {
+        final String msg = "Failed to send mail to " + category + " address "
+            + addr + " because of " + ex.getMessage();
+        if (task != null) {
+            task.log(msg, Project.MSG_WARN);
+        } else {
+            System.err.println(msg);
+        }
+    }
+
+    static class SimpleAuthenticator extends Authenticator {
+        private String user = null;
+        private String password = null;
+
+        public SimpleAuthenticator(final String user, final String password) {
+            this.user = user;
+            this.password = password;
+        }
+
+        @Override
+        public PasswordAuthentication getPasswordAuthentication() {
+            return new PasswordAuthentication(user, password);
+        }
+    }
+}
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java b/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java
index 352ae0b..7c00038 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -279,4 +279,3 @@
         return DateUtils.getDateForHeader();
     }
 }
-
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 8869ef1..477c736 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/Message.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/Message.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,13 +20,14 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.Reader;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.ProjectComponent;
 
@@ -47,7 +48,6 @@
     public Message() {
     }
 
-
     /**
      * Creates a new message based on the given string
      *
@@ -57,7 +57,6 @@
         addText(text);
     }
 
-
     /**
      * Creates a new message using the contents of the given file.
      *
@@ -67,7 +66,6 @@
         messageSource = file;
     }
 
-
     /**
      * Adds a textual part of the message
      *
@@ -77,7 +75,6 @@
         buffer.append(text);
     }
 
-
     /**
      * Sets the source file of the message
      *
@@ -87,7 +84,6 @@
         this.messageSource = src;
     }
 
-
     /**
      * Sets the content type for the message
      *
@@ -98,7 +94,6 @@
         specified = true;
     }
 
-
     /**
      * Returns the content type
      *
@@ -108,35 +103,28 @@
         return mimeType;
     }
 
-
     /**
      * Prints the message onto an output stream
      *
      * @param ps The print stream to write to
      * @throws IOException if an error occurs
      */
-    public void print(PrintStream ps)
-         throws IOException {
+    @SuppressWarnings("resource")
+    public void print(PrintStream ps) throws IOException {
         // We need character encoding aware printing here.
         // So, using BufferedWriter over OutputStreamWriter instead of PrintStream
         BufferedWriter out = null;
         try {
-            out
-                = charset != null ? new BufferedWriter(new OutputStreamWriter(ps, charset))
-                : new BufferedWriter(new OutputStreamWriter(ps));
+            out = charset == null ? new BufferedWriter(new OutputStreamWriter(ps))
+                    : new BufferedWriter(new OutputStreamWriter(ps, charset));
             if (messageSource != null) {
                 // Read message from a file
-                Reader freader = getReader(messageSource);
-
-                try {
-                    BufferedReader in = new BufferedReader(freader);
-                    String line = null;
+                try (BufferedReader in = new BufferedReader(getReader(messageSource))) {
+                    String line;
                     while ((line = in.readLine()) != null) {
                         out.write(getProject().replaceProperties(line));
                         out.newLine();
                     }
-                } finally {
-                    freader.close();
                 }
             } else {
                 out.write(getProject().replaceProperties(buffer.substring(0)));
@@ -148,7 +136,6 @@
         }
     }
 
-
     /**
      * Returns true if the mimeType has been set.
      *
@@ -167,6 +154,7 @@
     public void setCharset(String charset) {
         this.charset = charset;
     }
+
     /**
      * Returns the charset of mail message.
      *
@@ -189,7 +177,7 @@
 
     private Reader getReader(File f) throws IOException {
         if (inputEncoding != null) {
-            FileInputStream fis = new FileInputStream(f);
+            InputStream fis = Files.newInputStream(f.toPath());
             try {
                 return new InputStreamReader(fis, inputEncoding);
             } catch (IOException ex) {
@@ -200,4 +188,3 @@
         return new FileReader(f);
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java
index 1b2a72d..387078b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,8 +28,6 @@
 import java.security.Provider;
 import java.security.Security;
 import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Properties;
@@ -60,7 +58,9 @@
  * Uses the JavaMail classes to send Mime format email.
  *
  * @since Ant 1.5
+ * @deprecated see org.apache.tools.ant.taskdefs.email.JakartaMimeMailer
  */
+@Deprecated
 public class MimeMailer extends Mailer {
     private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
 
@@ -83,6 +83,7 @@
         private String charset = null;
         private ByteArrayOutputStream out;
 
+        @Override
         public InputStream getInputStream() throws IOException {
             if (data == null && out == null) {
                 throw new IOException("No data");
@@ -95,6 +96,7 @@
             return new ByteArrayInputStream(data.getBytes(charset));
         }
 
+        @Override
         public OutputStream getOutputStream() throws IOException {
             out = (out == null) ? new ByteArrayOutputStream() : out;
             return out;
@@ -104,16 +106,18 @@
             this.type = type.toLowerCase(Locale.ENGLISH);
         }
 
+        @Override
         public String getContentType() {
             if (type != null && type.indexOf("charset") > 0
                 && type.startsWith("text/")) {
                 return type;
             }
             // Must be like "text/plain; charset=windows-1251"
-            return new StringBuffer(type != null ? type : "text/plain").append(
-                "; charset=").append(charset).toString();
+            return (type != null ? type : "text/plain") +
+                    "; charset=" + charset;
         }
 
+        @Override
         public String getName() {
             return "StringDataSource";
         }
@@ -132,6 +136,7 @@
      *
      * @throws BuildException if the email can't be sent.
      */
+    @Override
     public void send() {
         try {
             final Properties props = new Properties();
@@ -146,13 +151,13 @@
             Authenticator auth = null;
             if (SSL) {
                 try {
-                    final Provider p = (Provider) Class.forName(
-                        "com.sun.net.ssl.internal.ssl.Provider").newInstance();
+                    final Provider p =
+                        Class.forName("com.sun.net.ssl.internal.ssl.Provider")
+                            .asSubclass(Provider.class).getDeclaredConstructor().newInstance();
                     Security.addProvider(p);
                 } catch (final Exception e) {
-                    throw new BuildException("could not instantiate ssl "
-                        + "security provider, check that you have JSSE in "
-                        + "your classpath");
+                    throw new BuildException(
+                        "could not instantiate ssl security provider, check that you have JSSE in your classpath");
                 }
                 // SMTP provider
                 props.put("mail.smtp.socketFactory.class", SSL_FACTORY);
@@ -219,8 +224,7 @@
             msg.addHeader("Date", getDate());
 
             if (headers != null) {
-                for (final Iterator iter = headers.iterator(); iter.hasNext();) {
-                    final Header h = (Header) iter.next();
+                for (Header h : headers) {
                     msg.addHeader(h.getName(), h.getValue());
                 }
             }
@@ -232,18 +236,12 @@
             textbody.setDataHandler(new DataHandler(sds));
             attachments.addBodyPart(textbody);
 
-            final Enumeration e = files.elements();
-
-            while (e.hasMoreElements()) {
-                final File file = (File) e.nextElement();
-
-                MimeBodyPart body;
-
-                body = new MimeBodyPart();
+            for (File file : files) {
+                MimeBodyPart body = new MimeBodyPart();
                 if (!file.exists() || !file.canRead()) {
-                    throw new BuildException("File \"" + file.getAbsolutePath()
-                         + "\" does not exist or is not "
-                         + "readable.");
+                    throw new BuildException(
+                        "File \"%s\" does not exist or is not readable.",
+                        file.getAbsolutePath());
                 }
                 final FileDataSource fileData = new FileDataSource(file);
                 final DataHandler fileDataHandler = new DataHandler(fileData);
@@ -261,7 +259,8 @@
             } catch (final SendFailedException sfe) {
                 if (!shouldIgnoreInvalidRecipients()) {
                     throw new BuildException(GENERIC_ERROR, sfe);
-                } else if (sfe.getValidSentAddresses() == null
+                }
+                if (sfe.getValidSentAddresses() == null
                            || sfe.getValidSentAddresses().length == 0) {
                     throw new BuildException("Couldn't reach any recipient",
                                              sfe);
@@ -281,16 +280,15 @@
                     didntReach(address, "valid", sfe);
                 }
             }
-        } catch (final MessagingException e) {
-            throw new BuildException(GENERIC_ERROR, e);
-        } catch (final IOException e) {
+        } catch (MessagingException | IOException e) {
             throw new BuildException(GENERIC_ERROR, e);
         }
     }
 
     private static InternetAddress[] internetAddresses(final Vector<EmailAddress> list)
         throws AddressException, UnsupportedEncodingException {
-        final List<InternetAddress> addrs = new ArrayList<InternetAddress>();
+
+        final List<InternetAddress> addrs = new ArrayList<>();
 
         for (final EmailAddress addr : list) {
             final String name = addr.getName();
@@ -307,7 +305,7 @@
         }
         final int pos = type.indexOf("charset");
         if (pos < 0) {
-          return null;
+            return null;
         }
         // Assuming mime type in form "text/XXXX; charset=XXXXXX"
         final StringTokenizer token = new StringTokenizer(type.substring(pos), "=; ");
@@ -329,10 +327,13 @@
     static class SimpleAuthenticator extends Authenticator {
         private String user = null;
         private String password = null;
+
         public SimpleAuthenticator(final String user, final String password) {
             this.user = user;
             this.password = password;
         }
+
+        @Override
         public PasswordAuthentication getPasswordAuthentication() {
             return new PasswordAuthentication(user, password);
         }
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..806102c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,11 +19,10 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintStream;
-import java.util.Enumeration;
-
+import java.nio.file.Files;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.mail.MailMessage;
@@ -39,49 +38,44 @@
      *
      * @see org.apache.tools.mail.MailMessage
      */
+    @Override
     public void send() {
         try {
             MailMessage mailMessage = new MailMessage(host, port);
 
             mailMessage.from(from.toString());
 
-            Enumeration e;
             boolean atLeastOneRcptReached = false;
 
-            e = replyToList.elements();
-            while (e.hasMoreElements()) {
-                mailMessage.replyto(e.nextElement().toString());
-            }
-            e = toList.elements();
-            while (e.hasMoreElements()) {
-                String to = e.nextElement().toString();
+            replyToList.stream().map(Object::toString).forEach(mailMessage::replyto);
+
+            for (EmailAddress to : toList) {
                 try {
-                    mailMessage.to(to);
+                    mailMessage.to(to.toString());
                     atLeastOneRcptReached = true;
                 } catch (IOException ex) {
                     badRecipient(to, ex);
                 }
             }
-            e = ccList.elements();
-            while (e.hasMoreElements()) {
-                String to = e.nextElement().toString();
+
+            for (EmailAddress cc : ccList) {
                 try {
-                    mailMessage.cc(to);
+                    mailMessage.cc(cc.toString());
                     atLeastOneRcptReached = true;
                 } catch (IOException ex) {
-                    badRecipient(to, ex);
+                    badRecipient(cc, ex);
                 }
             }
-            e = bccList.elements();
-            while (e.hasMoreElements()) {
-                String to = e.nextElement().toString();
+
+            for (EmailAddress bcc : bccList) {
                 try {
-                    mailMessage.bcc(to);
+                    mailMessage.bcc(bcc.toString());
                     atLeastOneRcptReached = true;
                 } catch (IOException ex) {
-                    badRecipient(to, ex);
+                    badRecipient(bcc, ex);
                 }
             }
+
             if (!atLeastOneRcptReached) {
                 throw new BuildException("Couldn't reach any recipient");
             }
@@ -96,18 +90,17 @@
                 mailMessage.setHeader("Content-Type", message.getMimeType());
             }
             if (headers != null) {
-                e = headers.elements();
-                while (e.hasMoreElements()) {
-                    Header h = (Header) e.nextElement();
+                for (Header h : headers) {
                     mailMessage.setHeader(h.getName(), h.getValue());
                 }
             }
             PrintStream out = mailMessage.getPrintStream();
             message.print(out);
 
-            e = files.elements();
-            while (e.hasMoreElements()) {
-                attach((File) e.nextElement(), out);
+            if (files != null) {
+                for (File f : files) {
+                    attach(f, out);
+                }
             }
             mailMessage.sendAndClose();
         } catch (IOException ioe) {
@@ -126,9 +119,9 @@
     protected void attach(File file, PrintStream out)
          throws IOException {
         if (!file.exists() || !file.canRead()) {
-            throw new BuildException("File \"" + file.getName()
-                 + "\" does not exist or is not "
-                 + "readable.");
+            throw new BuildException(
+                "File \"%s\" does not exist or is not readable.",
+                file.getAbsolutePath());
         }
 
         if (includeFileNames) {
@@ -144,23 +137,20 @@
             out.println();
         }
 
-        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 (InputStream finstr = Files.newInputStream(file.toPath());
+             BufferedInputStream in = new BufferedInputStream(finstr, buf.length)) {
 
+            int length;
             while ((length = in.read(buf)) != -1) {
                 out.write(buf, 0, length);
             }
-        } finally {
-            finstr.close();
         }
     }
 
-    private void badRecipient(String rcpt, IOException reason) {
+    private void badRecipient(EmailAddress rcpt, IOException reason) {
         String msg = "Failed to send mail to " + rcpt;
         if (shouldIgnoreInvalidRecipients()) {
             msg += " because of :" + reason.getMessage();
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..c0e47e7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/UUMailer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/UUMailer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,9 +19,10 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintStream;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.UUEncoder;
@@ -32,24 +33,18 @@
  * @since Ant 1.5
  */
 class UUMailer extends PlainMailer {
+    @Override
     protected void attach(File file, PrintStream out)
          throws IOException {
         if (!file.exists() || !file.canRead()) {
-            throw new BuildException("File \"" + file.getName()
-                 + "\" does not exist or is not "
-                 + "readable.");
+            throw new BuildException(
+                "File \"%s" + "\" does not exist or is not " + "readable.",
+                file.getAbsolutePath());
         }
 
-        FileInputStream finstr = new FileInputStream(file);
-
-        try {
-            BufferedInputStream in = new BufferedInputStream(finstr);
-            UUEncoder encoder = new UUEncoder(file.getName());
-
-            encoder.encode(in, out);
-
-        } finally {
-            finstr.close();
+        try (InputStream in =
+            new BufferedInputStream(Files.newInputStream(file.toPath()))) {
+            new UUEncoder(file.getName()).encode(in, out);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncher.java
index cc9fb88..095ef39 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,6 +22,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Optional;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.condition.Os;
@@ -41,7 +43,7 @@
     private static CommandLauncher shellLauncher = null;
 
     static {
-        if(!Os.isFamily("os/2")) {
+        if (!Os.isFamily("os/2")) {
             vmLauncher = new Java13CommandLauncher();
         }
 
@@ -94,7 +96,7 @@
      */
     public Process exec(Project project, String[] cmd, String[] env)
         throws IOException {
-        if(project != null) {
+        if (project != null) {
             project.log("Execute:CommandLauncher: "
                 + Commandline.describeCommand(cmd), Project.MSG_DEBUG);
         }
@@ -124,8 +126,8 @@
         if (workingDir == null) {
             return exec(project, cmd, env);
         }
-        throw new IOException("Cannot execute a process in different "
-            + "directory under this JVM");
+        throw new IOException(
+            "Cannot execute a process in different directory under this JVM");
     }
 
     /**
@@ -163,37 +165,25 @@
 
     private static CommandLauncher extractLauncher(String referenceName,
                                                    Project project) {
-        CommandLauncher launcher = null;
-        if (project != null) {
-            launcher = (CommandLauncher) project.getReference(referenceName);
-        }
-
-        if (launcher == null) {
-            launcher = getSystemLauncher(referenceName);
-        }
-        return launcher;
+        return Optional.ofNullable(project)
+            .map(p -> p.<CommandLauncher> getReference(referenceName))
+            .orElseGet(() -> getSystemLauncher(referenceName));
     }
 
     private static CommandLauncher getSystemLauncher(String launcherRefId) {
-        CommandLauncher launcher = null;
         String launcherClass = System.getProperty(launcherRefId);
         if (launcherClass != null) {
             try {
-                launcher = (CommandLauncher) Class.forName(launcherClass)
-                    .newInstance();
-            } catch(InstantiationException e) {
+                return Class.forName(launcherClass).asSubclass(CommandLauncher.class)
+                        .getDeclaredConstructor().newInstance();
+            } catch (InstantiationException | IllegalAccessException
+                    | ClassNotFoundException
+                    | NoSuchMethodException | InvocationTargetException e) {
                 System.err.println("Could not instantiate launcher class "
-                                   + launcherClass + ": " + e.getMessage());
-            } catch(IllegalAccessException e) {
-                System.err.println("Could not instantiate launcher class "
-                                   + launcherClass + ": " + e.getMessage());
-            } catch(ClassNotFoundException e) {
-                System.err.println("Could not instantiate launcher class "
-                                   + launcherClass + ": " + e.getMessage());
+                    + launcherClass + ": " + e.getMessage());
             }
         }
-
-        return launcher;
+        return null;
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncherProxy.java b/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncherProxy.java
index 7a1c877..021e4c1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncherProxy.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/CommandLauncherProxy.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/Java13CommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/Java13CommandLauncher.java
index 12ec7d9..02fbede 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/Java13CommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/Java13CommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/MacCommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/MacCommandLauncher.java
index 02a8e78..ec41a9c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/MacCommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/MacCommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/OS2CommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/OS2CommandLauncher.java
index 75ecaa3..baadc13 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/OS2CommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/OS2CommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/PerlScriptCommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/PerlScriptCommandLauncher.java
index d5b06f7..58c0e09 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/PerlScriptCommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/PerlScriptCommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,15 +58,14 @@
             if (workingDir == null) {
                 return exec(project, cmd, env);
             }
-            throw new IOException("Cannot locate antRun script: "
-                                  + "No project provided");
+            throw new IOException(
+                "Cannot locate antRun script: No project provided");
         }
         // Locate the auxiliary script
         String antHome = project.getProperty(MagicNames.ANT_HOME);
         if (antHome == null) {
-            throw new IOException("Cannot locate antRun script: "
-                                  + "Property '" + MagicNames.ANT_HOME
-                                  + "' not found");
+            throw new IOException("Cannot locate antRun script: Property '"
+                + MagicNames.ANT_HOME + "' not found");
         }
         String antRun = FILE_UTILS.resolveFile(project.getBaseDir(),
                                                antHome + File.separator
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/ScriptCommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/ScriptCommandLauncher.java
index 936f948..0aacbb3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/ScriptCommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/ScriptCommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,15 +58,14 @@
             if (workingDir == null) {
                 return exec(project, cmd, env);
             }
-            throw new IOException("Cannot locate antRun script: "
-                                  + "No project provided");
+            throw new IOException(
+                "Cannot locate antRun script: No project provided");
         }
         // Locate the auxiliary script
         String antHome = project.getProperty(MagicNames.ANT_HOME);
         if (antHome == null) {
-            throw new IOException("Cannot locate antRun script: "
-                                  + "Property '" + MagicNames.ANT_HOME
-                                  + "' not found");
+            throw new IOException("Cannot locate antRun script: Property '"
+                + MagicNames.ANT_HOME + "' not found");
         }
         String antRun = FILE_UTILS.resolveFile(project.getBaseDir(),
                                                antHome + File.separator
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java
index 97f27c6..be5c44d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/VmsCommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,10 +32,6 @@
  */
 public class VmsCommandLauncher extends Java13CommandLauncher {
 
-    public VmsCommandLauncher() {
-        super();
-    }
-
     /**
      * Launches the given command in a new process.
      *
@@ -53,7 +49,8 @@
     public Process exec(Project project, String[] cmd, String[] env)
         throws IOException {
         File cmdFile = createCommandFile(project, cmd, env);
-        Process p = super.exec(project, new String[] {cmdFile.getPath()}, env);
+        Process p =
+            super.exec(project, new String[] {cmdFile.getPath()}, env);
         deleteAfter(cmdFile, p);
         return p;
     }
@@ -80,7 +77,8 @@
     public Process exec(Project project, String[] cmd, String[] env,
                         File workingDir) throws IOException {
         File cmdFile = createCommandFile(project, cmd, env);
-        Process p = super.exec(project, new String[] {cmdFile.getPath()}, env, workingDir);
+        Process p = super.exec(project, new String[] {cmdFile.getPath()}, env,
+            workingDir);
         deleteAfter(cmdFile, p);
         return p;
     }
@@ -96,9 +94,7 @@
     private File createCommandFile(final Project project, String[] cmd, String[] env)
         throws IOException {
         File script = FILE_UTILS.createTempFile(project, "ANT", ".COM", null, true, true);
-        BufferedWriter out = null;
-        try {
-            out = new BufferedWriter(new FileWriter(script));
+        try (BufferedWriter out = new BufferedWriter(new FileWriter(script))) {
 
             // add the environment as logicals to the DCL script
             if (env != null) {
@@ -121,23 +117,18 @@
                 out.newLine();
                 out.write(cmd[i]);
             }
-        } finally {
-            FileUtils.close(out);
         }
         return script;
     }
 
     private void deleteAfter(final File f, final Process p) {
-        new Thread() {
-            @Override
-            public void run() {
-                try {
-                    p.waitFor();
-                } catch(InterruptedException e) {
-                    // ignore
-                }
-                FileUtils.delete(f);
+        new Thread(() -> {
+            try {
+                p.waitFor();
+            } catch (InterruptedException e) {
+                // ignore
             }
-        }.start();
+            FileUtils.delete(f);
+        }).start();
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/launcher/WinNTCommandLauncher.java b/src/main/org/apache/tools/ant/taskdefs/launcher/WinNTCommandLauncher.java
index 65abafc..bd225ce 100644
--- a/src/main/org/apache/tools/ant/taskdefs/launcher/WinNTCommandLauncher.java
+++ b/src/main/org/apache/tools/ant/taskdefs/launcher/WinNTCommandLauncher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/modules/Jmod.java b/src/main/org/apache/tools/ant/taskdefs/modules/Jmod.java
new file mode 100644
index 0000000..47f0ef2
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/modules/Jmod.java
@@ -0,0 +1,1284 @@
+/*
+ *  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
+ *
+ *      https://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.modules;
+
+import java.io.File;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.IOException;
+
+import java.nio.file.Files;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+
+import java.util.Map;
+import java.util.LinkedHashMap;
+
+import java.util.Collections;
+
+import java.util.spi.ToolProvider;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+
+import org.apache.tools.ant.util.MergingMapper;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.ResourceUtils;
+
+import org.apache.tools.ant.types.EnumeratedAttribute;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.ModuleVersion;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+
+import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.types.resources.Union;
+
+/**
+ * Creates a linkable .jmod file from a modular jar file, and optionally from
+ * other resource files such as native libraries and documents.  Equivalent
+ * to the JDK's
+ * <a href="https://docs.oracle.com/en/java/javase/11/tools/jmod.html">jmod</a>
+ * tool.
+ * <p>
+ * Supported attributes:
+ * <dl>
+ * <dt>{@code destFile}
+ * <dd>Required, jmod file to create.
+ * <dt>{@code classpath}
+ * <dt>{@code classpathref}
+ * <dd>Where to locate files to be placed in the jmod file.
+ * <dt>{@code modulepath}
+ * <dt>{@code modulepathref}
+ * <dd>Where to locate dependencies.
+ * <dt>{@code commandpath}
+ * <dt>{@code commandpathref}
+ * <dd>Directories containing native commands to include in jmod.
+ * <dt>{@code headerpath}
+ * <dt>{@code headerpathref}
+ * <dd>Directories containing header files to include in jmod.
+ * <dt>{@code configpath}
+ * <dt>{@code configpathref}
+ * <dd>Directories containing user-editable configuration files
+ *     to include in jmod.
+ * <dt>{@code legalpath}
+ * <dt>{@code legalpathref}
+ * <dd>Directories containing legal licenses and notices to include in jmod.
+ * <dt>{@code nativelibpath}
+ * <dt>{@code nativelibpathref}
+ * <dd>Directories containing native libraries to include in jmod.
+ * <dt>{@code manpath}
+ * <dt>{@code manpathref}
+ * <dd>Directories containing man pages to include in jmod.
+ * <dt>{@code version}
+ * <dd>Module <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">version</a>.
+ * <dt>{@code mainclass}
+ * <dd>Main class of module.
+ * <dt>{@code platform}
+ * <dd>The target platform for the jmod.  A particular JDK's platform
+ * can be seen by running
+ * <code>jmod describe $JDK_HOME/jmods/java.base.jmod | grep -i platform</code>.
+ * <dt>{@code hashModulesPattern}
+ * <dd>Regular expression for names of modules in the module path
+ *     which depend on the jmod being created, and which should have
+ *     hashes generated for them and included in the new jmod.
+ * <dt>{@code resolveByDefault}
+ * <dd>Boolean indicating whether the jmod should be one of
+ *     the default resolved modules in an application.  Default is true.
+ * <dt>{@code moduleWarnings}
+ * <dd>Whether to emit warnings when resolving modules which are
+ *     not recommended for use.  Comma-separated list of one of more of
+ *     the following:
+ *     <dl>
+ *     <dt>{@code deprecated}
+ *     <dd>Warn if module is deprecated
+ *     <dt>{@code leaving}
+ *     <dd>Warn if module is deprecated for removal
+ *     <dt>{@code incubating}
+ *     <dd>Warn if module is an incubating (not yet official) module
+ *     </dl>
+ * </dl>
+ *
+ * <p>
+ * Supported nested elements:
+ * <dl>
+ * <dt>{@code <classpath>}
+ * <dd>Path indicating where to locate files to be placed in the jmod file.
+ * <dt>{@code <modulepath>}
+ * <dd>Path indicating where to locate dependencies.
+ * <dt>{@code <commandpath>}
+ * <dd>Path of directories containing native commands to include in jmod.
+ * <dt>{@code <headerpath>}
+ * <dd>Path of directories containing header files to include in jmod.
+ * <dt>{@code <configpath>}
+ * <dd>Path of directories containing user-editable configuration files
+ *     to include in jmod.
+ * <dt>{@code <legalpath>}
+ * <dd>Path of directories containing legal notices to include in jmod.
+ * <dt>{@code <nativelibpath>}
+ * <dd>Path of directories containing native libraries to include in jmod.
+ * <dt>{@code <manpath>}
+ * <dd>Path of directories containing man pages to include in jmod.
+ * <dt>{@code <version>}
+ * <dd><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">Module version</a> of jmod.
+ *     Must have a required {@code number} attribute.  May also have optional
+ *     {@code preRelease} and {@code build} attributes.
+ * <dt>{@code <moduleWarning>}
+ * <dd>Has one required attribute, {@code reason}.  See {@code moduleWarnings}
+ *     attribute above.  This element may be specified multiple times.
+ * </dl>
+ * <p>
+ * destFile and classpath are required data.
+ *
+ * @since 1.10.6
+ */
+public class Jmod
+extends Task {
+    /** Location of jmod file to be created. */
+    private File jmodFile;
+
+    /**
+     * Path of files (usually jar files or directories containing
+     * compiled classes) from which to create jmod.
+     */
+    private Path classpath;
+
+    /**
+     * Path of directories containing modules on which the modules
+     * in the classpath depend.
+     */
+    private Path modulePath;
+
+    /**
+     * Path of directories containing executable files to bundle in the
+     * created jmod.
+     */
+    private Path commandPath;
+
+    /**
+     * Path of directories containing configuration files to bundle in the
+     * created jmod.
+     */
+    private Path configPath;
+
+    /**
+     * Path of directories containing includable header files (such as for
+     * other languages) to bundle in the created jmod.
+     */
+    private Path headerPath;
+
+    /**
+     * Path of directories containing legal license files to bundle
+     * in the created jmod.
+     */
+    private Path legalPath;
+
+    /**
+     * Path of directories containing native libraries needed by classes
+     * in the modules comprising the created jmod.
+     */
+    private Path nativeLibPath;
+
+    /**
+     * Path of directories containing manual pages to bundle
+     * in the created jmod.
+     */
+    private Path manPath;
+
+    /**
+     * Module version of jmod.  Either this or {@link #moduleVersion}
+     * may be set.
+     */
+    private String version;
+
+    /** Module version of jmod.  Either this or {@link #version} may be set. */
+    private ModuleVersion moduleVersion;
+
+    /**
+     * Main class to execute, if Java attempts to execute jmod's module
+     * without specifying a main class explicitly.
+     */
+    private String mainClass;
+
+    /**
+     * Target platform of created jmod.  Examples are {@code windows-amd64}
+     * and {@code linux-amd64}.  Target platform is an attribute
+     * of each JDK, which can be seen by executing
+     * <code>jmod describe $JDK_HOME/jmods/java.base.jmod</code> and
+     * searching the output for a line starting with {@code platform}.
+     */
+    private String platform;
+
+    /**
+     * Regular expression matching names of modules which depend on the
+     * the created jmod's module, for which hashes should be added to the
+     * created jmod.
+     */
+    private String hashModulesPattern;
+
+    /**
+     * Whether the created jmod should be seen by Java when present in a
+     * module path, even if not explicitly named.  Normally true.
+     */
+    private boolean resolveByDefault = true;
+
+    /**
+     * Reasons why module resolution during jmod creation may emit warnings.
+     */
+    private final List<ResolutionWarningSpec> moduleWarnings =
+        new ArrayList<>();
+
+    /**
+     * Attribute containing the location of the jmod file to create.
+     *
+     * @return location of jmod file
+     *
+     * @see #setDestFile(File)
+     */
+    public File getDestFile() {
+        return jmodFile;
+    }
+
+    /**
+     * Sets attribute containing the location of the jmod file to create.
+     * This value is required.
+     *
+     * @param file location where jmod file will be created.
+     */
+    public void setDestFile(final File file) {
+        this.jmodFile = file;
+    }
+
+    /**
+     * Adds an unconfigured {@code <classpath>} child element which can
+     * specify the files which will comprise the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setClasspath(Path)
+     */
+    public Path createClasspath() {
+        if (classpath == null) {
+            classpath = new Path(getProject());
+        }
+        return classpath.createPath();
+    }
+
+    /**
+     * Attribute which specifies the files (usually modular .jar files)
+     * which will comprise the created jmod file.
+     *
+     * @return path of constituent files
+     *
+     * @see #setClasspath(Path)
+     */
+    public Path getClasspath() {
+        return classpath;
+    }
+
+    /**
+     * Sets attribute specifying the files that will comprise the created jmod
+     * file.  Usually this contains a single modular .jar file.
+     * <p>
+     * The classpath is required and must not be empty.
+     *
+     * @param path path of files that will comprise jmod
+     *
+     * @see #createClasspath()
+     */
+    public void setClasspath(final Path path) {
+        if (classpath == null) {
+            this.classpath = path;
+        } else {
+            classpath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setClasspath(Path) classpath attribute} from a
+     * path reference.
+     *
+     * @param ref reference to path which will act as classpath
+     */
+    public void setClasspathRef(final Reference ref) {
+        createClasspath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child {@code <modulePath>} element which can contain a
+     * path of directories containing modules upon which modules in the
+     * {@linkplain #setClasspath(Path) classpath} depend.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setModulePath(Path)
+     */
+    public Path createModulePath() {
+        if (modulePath == null) {
+            modulePath = new Path(getProject());
+        }
+        return modulePath.createPath();
+    }
+
+    /**
+     * Attribute containing path of directories which contain modules on which
+     * the created jmod's {@linkplain #setClasspath(Path) constituent modules}
+     * depend.
+     *
+     * @return path of directories containing modules needed by
+     *         classpath modules
+     *
+     * @see #setModulePath(Path)
+     */
+    public Path getModulePath() {
+        return modulePath;
+    }
+
+    /**
+     * Sets attribute containing path of directories which contain modules
+     * on which the created jmod's
+     * {@linkplain #setClasspath(Path) constituent modules} depend.
+     *
+     * @param path path of directories containing modules needed by
+     *             classpath modules
+     *
+     * @see #createModulePath()
+     */
+    public void setModulePath(final Path path) {
+        if (modulePath == null) {
+            this.modulePath = path;
+        } else {
+            modulePath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setModulePath(Path) module path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as module path
+     */
+    public void setModulePathRef(final Reference ref) {
+        createModulePath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child element which can contain a list of directories
+     * containing native executable files to include in the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setCommandPath(Path)
+     */
+    public Path createCommandPath() {
+        if (commandPath == null) {
+            commandPath = new Path(getProject());
+        }
+        return commandPath.createPath();
+    }
+
+    /**
+     * Attribute containing path of directories which contain native
+     * executable files to include in the created jmod.
+     *
+     * @return list of directories containing native executables
+     *
+     * @see #setCommandPath(Path)
+     */
+    public Path getCommandPath() {
+        return commandPath;
+    }
+
+    /**
+     * Sets attribute containing path of directories which contain native
+     * executable files to include in the created jmod.
+     *
+     * @param path list of directories containing native executables
+     *
+     * @see #createCommandPath()
+     */
+    public void setCommandPath(final Path path) {
+        if (commandPath == null) {
+            this.commandPath = path;
+        } else {
+            commandPath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setCommandPath(Path) command path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as command path
+     */
+    public void setCommandPathRef(final Reference ref) {
+        createCommandPath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child element which can contain a list of directories
+     * containing user configuration files to include in the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setConfigPath(Path)
+     */
+    public Path createConfigPath() {
+        if (configPath == null) {
+            configPath = new Path(getProject());
+        }
+        return configPath.createPath();
+    }
+
+    /**
+     * Attribute containing list of directories which contain
+     * user configuration files.
+     *
+     * @return list of directories containing user configuration files
+     *
+     * @see #setConfigPath(Path)
+     */
+    public Path getConfigPath() {
+        return configPath;
+    }
+
+    /**
+     * Sets attribute containing list of directories which contain
+     * user configuration files.
+     *
+     * @param path list of directories containing user configuration files
+     *
+     * @see #createConfigPath()
+     */
+    public void setConfigPath(final Path path) {
+        if (configPath == null) {
+            this.configPath = path;
+        } else {
+            configPath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setConfigPath(Path) configuration file path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as configuration file path
+     */
+    public void setConfigPathRef(final Reference ref) {
+        createConfigPath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child element which can contain a list of directories
+     * containing compile-time header files for third party use, to include
+     * in the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setHeaderPath(Path)
+     */
+    public Path createHeaderPath() {
+        if (headerPath == null) {
+            headerPath = new Path(getProject());
+        }
+        return headerPath.createPath();
+    }
+
+    /**
+     * Attribute containing a path of directories which hold compile-time
+     * header files for third party use, all of which will be included in the
+     * created jmod.
+     *
+     * @return path of directories containing header files
+     */
+    public Path getHeaderPath() {
+        return headerPath;
+    }
+
+    /**
+     * Sets attribute containing a path of directories which hold compile-time
+     * header files for third party use, all of which will be included in the
+     * created jmod.
+     *
+     * @param path path of directories containing header files
+     *
+     * @see #createHeaderPath()
+     */
+    public void setHeaderPath(final Path path) {
+        if (headerPath == null) {
+            this.headerPath = path;
+        } else {
+            headerPath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setHeaderPath(Path) header path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as header path
+     */
+    public void setHeaderPathRef(final Reference ref) {
+        createHeaderPath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child element which can contain a list of directories
+     * containing license files to include in the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setLegalPath(Path)
+     */
+    public Path createLegalPath() {
+        if (legalPath == null) {
+            legalPath = new Path(getProject());
+        }
+        return legalPath.createPath();
+    }
+
+    /**
+     * Attribute containing list of directories which hold license files
+     * to include in the created jmod.
+     *
+     * @return path containing directories which hold license files
+     */
+    public Path getLegalPath() {
+        return legalPath;
+    }
+
+    /**
+     * Sets attribute containing list of directories which hold license files
+     * to include in the created jmod.
+     *
+     * @param path path containing directories which hold license files
+     *
+     * @see #createLegalPath()
+     */
+    public void setLegalPath(final Path path) {
+        if (legalPath == null) {
+            this.legalPath = path;
+        } else {
+            legalPath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setLegalPath(Path) legal licenses path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as legal path
+     */
+    public void setLegalPathRef(final Reference ref) {
+        createLegalPath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child element which can contain a list of directories
+     * containing native libraries to include in the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setNativeLibPath(Path)
+     */
+    public Path createNativeLibPath() {
+        if (nativeLibPath == null) {
+            nativeLibPath = new Path(getProject());
+        }
+        return nativeLibPath.createPath();
+    }
+
+    /**
+     * Attribute containing list of directories which hold native libraries
+     * to include in the created jmod.
+     *
+     * @return path of directories containing native libraries
+     */
+    public Path getNativeLibPath() {
+        return nativeLibPath;
+    }
+
+    /**
+     * Sets attribute containing list of directories which hold native libraries
+     * to include in the created jmod.
+     *
+     * @param path path of directories containing native libraries
+     *
+     * @see #createNativeLibPath()
+     */
+    public void setNativeLibPath(final Path path) {
+        if (nativeLibPath == null) {
+            this.nativeLibPath = path;
+        } else {
+            nativeLibPath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setNativeLibPath(Path) native library path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as native library path
+     */
+    public void setNativeLibPathRef(final Reference ref) {
+        createNativeLibPath().setRefid(ref);
+    }
+
+    /**
+     * Creates a child element which can contain a list of directories
+     * containing man pages (program manuals, typically in troff format)
+     * to include in the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setManPath(Path)
+     */
+    public Path createManPath() {
+        if (manPath == null) {
+            manPath = new Path(getProject());
+        }
+        return manPath.createPath();
+    }
+
+    /**
+     * Attribute containing list of directories containing man pages
+     * to include in created jmod.  Man pages are textual program manuals,
+     * typically in troff format.
+     *
+     * @return path containing directories which hold man pages to include
+     *         in jmod
+     */
+    public Path getManPath() {
+        return manPath;
+    }
+
+    /**
+     * Sets attribute containing list of directories containing man pages
+     * to include in created jmod.  Man pages are textual program manuals,
+     * typically in troff format.
+     *
+     * @param path path containing directories which hold man pages to include
+     *             in jmod
+     *
+     * @see #createManPath()
+     */
+    public void setManPath(final Path path) {
+        if (manPath == null) {
+            this.manPath = path;
+        } else {
+            manPath.append(path);
+        }
+    }
+
+    /**
+     * Sets {@linkplain #setManPath(Path) man pages path}
+     * from a path reference.
+     *
+     * @param ref reference to path which will act as module path
+     */
+    public void setManPathRef(final Reference ref) {
+        createManPath().setRefid(ref);
+    }
+
+    /**
+     * Creates an uninitialized child element representing the version of
+     * the module represented by the created jmod.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setVersion(String)
+     */
+    public ModuleVersion createVersion() {
+        if (moduleVersion != null) {
+            throw new BuildException(
+                "No more than one <moduleVersion> element is allowed.",
+                getLocation());
+        }
+        moduleVersion = new ModuleVersion();
+        return moduleVersion;
+    }
+
+    /**
+     * Attribute which specifies
+     * a <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">module version</a>
+     * for created jmod.
+     *
+     * @return module version for created jmod
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Sets the <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">module version</a>
+     * for the created jmod.
+     *
+     * @param version module version of created jmod
+     *
+     * @see #createVersion()
+     */
+    public void setVersion(final String version) {
+        this.version = version;
+    }
+
+    /**
+     * Attribute containing the class that acts as the executable entry point
+     * of the created jmod.
+     *
+     * @return fully-qualified name of jmod's main class
+     */
+    public String getMainClass() {
+        return mainClass;
+    }
+
+    /**
+     * Sets attribute containing the class that acts as the
+     * executable entry point of the created jmod.
+     *
+     * @param className fully-qualified name of jmod's main class
+     */
+    public void setMainClass(final String className) {
+        this.mainClass = className;
+    }
+
+    /**
+     * Attribute containing the platform for which the jmod
+     * will be built.  Platform values are defined in the
+     * {@code java.base.jmod} of JDKs, and usually take the form
+     * <var>OS</var>{@code -}<var>architecture</var>.  If unset,
+     * current platform is used.
+     *
+     * @return OS and architecture for which jmod will be built, or {@code null}
+     */
+    public String getPlatform() {
+        return platform;
+    }
+
+    /**
+     * Sets attribute containing the platform for which the jmod
+     * will be built.  Platform values are defined in the
+     * {@code java.base.jmod} of JDKs, and usually take the form
+     * <var>OS</var>{@code -}<var>architecture</var>.  If unset,
+     * current platform is used.
+     * <p>
+     * A JDK's platform can be viewed with a command like:
+     * <code>jmod describe $JDK_HOME/jmods/java.base.jmod | grep -i platform</code>.
+o    *
+     * @param platform platform for which jmod will be created, or {@code null}
+     */
+    public void setPlatform(final String platform) {
+        this.platform = platform;
+    }
+
+    /**
+     * Attribute containing a regular expression which specifies which
+     * of the modules that depend on the jmod being created should have
+     * hashes generated and added to the jmod.
+     *
+     * @return regex specifying which dependent modules should have
+     *         their generated hashes included
+     */
+    public String getHashModulesPattern() {
+        return hashModulesPattern;
+    }
+
+    /**
+     * Sets attribute containing a regular expression which specifies which
+     * of the modules that depend on the jmod being created should have
+     * hashes generated and added to the jmod.
+     *
+     * @param pattern regex specifying which dependent modules should have
+     *         their generated hashes included
+     */
+    public void setHashModulesPattern(final String pattern) {
+        this.hashModulesPattern = pattern;
+    }
+
+    /**
+     * Attribute indicating whether the created jmod should be visible
+     * in a module path, even when not specified explicitly.  True by default.
+     *
+     * @return whether jmod should be visible in module paths
+     */
+    public boolean getResolveByDefault() {
+        return resolveByDefault;
+    }
+
+    /**
+     * Sets attribute indicating whether the created jmod should be visible
+     * in a module path, even when not specified explicitly.  True by default.
+     *
+     * @param resolve whether jmod should be visible in module paths
+     */
+    public void setResolveByDefault(final boolean resolve) {
+        this.resolveByDefault = resolve;
+    }
+
+    /**
+     * Creates a child element which can specify the circumstances
+     * under which jmod creation emits warnings.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setModuleWarnings(String)
+     */
+    public ResolutionWarningSpec createModuleWarning() {
+        ResolutionWarningSpec warningSpec = new ResolutionWarningSpec();
+        moduleWarnings.add(warningSpec);
+        return warningSpec;
+    }
+
+    /**
+     * Sets attribute containing a comma-separated list of reasons for
+     * jmod creation to emit warnings.  Valid values in list are:
+     * {@code deprecated}, {@code leaving}, {@code incubating}.
+     *
+     * @param warningList list containing one or more of the above values,
+     *                    separated by commas
+     *
+     * @see #createModuleWarning()
+     * @see Jmod.ResolutionWarningReason
+     */
+    public void setModuleWarnings(final String warningList) {
+        for (String warning : warningList.split(",")) {
+            moduleWarnings.add(new ResolutionWarningSpec(warning));
+        }
+    }
+
+    /**
+     * Permissible reasons for jmod creation to emit warnings.
+     */
+    public static class ResolutionWarningReason
+    extends EnumeratedAttribute {
+        /**
+         * String value indicating warnings are emitted for modules
+         * marked as deprecated (but not deprecated for removal).
+         */
+        public static final String DEPRECATED = "deprecated";
+
+        /**
+         * String value indicating warnings are emitted for modules
+         * marked as deprecated for removal.
+         */
+        public static final String LEAVING = "leaving";
+
+        /**
+         * String value indicating warnings are emitted for modules
+         * designated as "incubating" in the JDK.
+         */
+        public static final String INCUBATING = "incubating";
+
+        /** Maps Ant task values to jmod option values. */
+        private static final Map<String, String> VALUES_TO_OPTIONS;
+
+        static {
+            Map<String, String> map = new LinkedHashMap<>();
+            map.put(DEPRECATED, "deprecated");
+            map.put(LEAVING,    "deprecated-for-removal");
+            map.put(INCUBATING, "incubating");
+
+            VALUES_TO_OPTIONS = Collections.unmodifiableMap(map);
+        }
+
+        @Override
+        public String[] getValues() {
+            return VALUES_TO_OPTIONS.keySet().toArray(new String[0]);
+        }
+
+        /**
+         * Converts this object's current value to a jmod tool
+         * option value.
+         *
+         * @return jmod option value
+         */
+        String toCommandLineOption() {
+            return VALUES_TO_OPTIONS.get(getValue());
+        }
+
+        /**
+         * Converts a string to a {@code ResolutionWarningReason} instance.
+         *
+         * @param s string to convert
+         *
+         * @return {@code ResolutionWarningReason} instance corresponding to
+         *         string argument
+         *
+         * @throws BuildException if argument is not a valid
+         *                        {@code ResolutionWarningReason} value
+         */
+        public static ResolutionWarningReason valueOf(String s) {
+            return (ResolutionWarningReason)
+                getInstance(ResolutionWarningReason.class, s);
+        }
+    }
+
+    /**
+     * Child element which enables jmod tool warnings.  'reason' attribute
+     * is required.
+     */
+    public class ResolutionWarningSpec {
+        /** Condition which should trigger jmod warning output. */
+        private ResolutionWarningReason reason;
+
+        /**
+         * Creates an uninitialized element.
+         */
+        public ResolutionWarningSpec() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates an element with the given reason attribute.
+         *
+         * @param reason non{@code null} {@link Jmod.ResolutionWarningReason}
+         *               value
+         *
+         * @throws BuildException if argument is not a valid
+         *                        {@code ResolutionWarningReason}
+         */
+        public ResolutionWarningSpec(String reason) {
+            setReason(ResolutionWarningReason.valueOf(reason));
+        }
+
+        /**
+         * Required attribute containing reason for emitting jmod warnings.
+         *
+         * @return condition which triggers jmod warnings
+         */
+        public ResolutionWarningReason getReason() {
+            return reason;
+        }
+
+        /**
+         * Sets attribute containing reason for emitting jmod warnings.
+         *
+         * @param reason condition which triggers jmod warnings
+         */
+        public void setReason(ResolutionWarningReason reason) {
+            this.reason = reason;
+        }
+
+        /**
+         * Verifies this object's state.
+         *
+         * @throws BuildException if this object's reason is {@code null}
+         */
+        public void validate() {
+            if (reason == null) {
+                throw new BuildException("reason attribute is required",
+                    getLocation());
+            }
+        }
+    }
+
+    /**
+     * Checks whether a resource is a directory.  Used for checking validity
+     * of jmod path arguments which have to be directories.
+     *
+     * @param resource resource to check
+     *
+     * @return true if resource exists and is not a directory,
+     *         false if it is a directory or does not exist
+     */
+    private static boolean isRegularFile(Resource resource) {
+        return resource.isExists() && !resource.isDirectory();
+    }
+
+    /**
+     * Checks that all paths which are required to be directories only,
+     * refer only to directories.
+     *
+     * @throws BuildException if any path has an existing file
+     *                        which is a non-directory
+     */
+    private void checkDirPaths() {
+        if (modulePath != null
+            && modulePath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "ModulePath must contain only directories.", getLocation());
+        }
+        if (commandPath != null
+            && commandPath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "CommandPath must contain only directories.", getLocation());
+        }
+        if (configPath != null
+            && configPath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "ConfigPath must contain only directories.", getLocation());
+        }
+        if (headerPath != null
+            && headerPath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "HeaderPath must contain only directories.", getLocation());
+        }
+        if (legalPath != null
+            && legalPath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "LegalPath must contain only directories.", getLocation());
+        }
+        if (nativeLibPath != null
+            && nativeLibPath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "NativeLibPath must contain only directories.", getLocation());
+        }
+        if (manPath != null
+            && manPath.stream().anyMatch(Jmod::isRegularFile)) {
+
+            throw new BuildException(
+                "ManPath must contain only directories.", getLocation());
+        }
+    }
+
+    /**
+     * Creates a jmod file according to this task's properties
+     * and child elements.
+     *
+     * @throws BuildException if destFile is not set
+     * @throws BuildException if classpath is not set or is empty
+     * @throws BuildException if any path other than classpath refers to an
+     *                        existing file which is not a directory
+     * @throws BuildException if both {@code version} attribute and
+     *                        {@code <version>} child element are present
+     * @throws BuildException if {@code hashModulesPattern} is set, but
+     *                        module path is not defined
+     */
+    @Override
+    public void execute()
+    throws BuildException {
+
+        if (jmodFile == null) {
+            throw new BuildException("Destination file is required.",
+                getLocation());
+        }
+
+        if (classpath == null) {
+            throw new BuildException("Classpath is required.",
+                getLocation());
+        }
+
+        if (classpath.stream().noneMatch(Resource::isExists)) {
+            throw new BuildException(
+                "Classpath must contain at least one entry which exists.",
+                getLocation());
+        }
+
+        if (version != null && moduleVersion != null) {
+            throw new BuildException(
+                "version attribute and nested <version> element "
+                + "cannot both be present.",
+                getLocation());
+        }
+
+        if (hashModulesPattern != null && !hashModulesPattern.isEmpty()
+            && modulePath == null) {
+
+            throw new BuildException(
+                "hashModulesPattern requires a module path, since "
+                + "it will generate hashes of the other modules which depend "
+                + "on the module being created.",
+                getLocation());
+        }
+
+        checkDirPaths();
+
+        Path[] dependentPaths = {
+            classpath,
+            modulePath,
+            commandPath,
+            configPath,
+            headerPath,
+            legalPath,
+            nativeLibPath,
+            manPath,
+        };
+        Union allResources = new Union(getProject());
+        for (Path path : dependentPaths) {
+            if (path != null) {
+                for (String entry : path.list()) {
+                    File entryFile = new File(entry);
+                    if (entryFile.isDirectory()) {
+                        log("Will compare timestamp of all files in "
+                            + "\"" + entryFile + "\" with timestamp of "
+                            + jmodFile, Project.MSG_VERBOSE);
+                        FileSet fileSet = new FileSet();
+                        fileSet.setDir(entryFile);
+                        allResources.add(fileSet);
+                    } else {
+                        log("Will compare timestamp of \"" + entryFile + "\" "
+                            + "with timestamp of " + jmodFile,
+                            Project.MSG_VERBOSE);
+                        allResources.add(new FileResource(entryFile));
+                    }
+                }
+            }
+        }
+
+        ResourceCollection outOfDate =
+            ResourceUtils.selectOutOfDateSources(this, allResources,
+                new MergingMapper(jmodFile.toString()),
+                getProject(),
+                FileUtils.getFileUtils().getFileTimestampGranularity());
+
+        if (outOfDate.isEmpty()) {
+            log("Skipping jmod creation, since \"" + jmodFile + "\" "
+                + "is already newer than all files in paths.",
+                Project.MSG_VERBOSE);
+            return;
+        }
+
+        Collection<String> args = buildJmodArgs();
+
+        try {
+            log("Deleting " + jmodFile + " if it exists.", Project.MSG_VERBOSE);
+            Files.deleteIfExists(jmodFile.toPath());
+        } catch (IOException e) {
+            throw new BuildException(
+                "Could not remove old file \"" + jmodFile + "\": " + e, e,
+                getLocation());
+        }
+
+        ToolProvider jmod = ToolProvider.findFirst("jmod").orElseThrow(
+            () -> new BuildException("jmod tool not found in JDK.",
+                getLocation()));
+
+        log("Executing: jmod " + String.join(" ", args), Project.MSG_VERBOSE);
+
+        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+
+        int exitCode;
+        try (PrintStream out = new PrintStream(stdout);
+             PrintStream err = new PrintStream(stderr)) {
+
+            exitCode = jmod.run(out, err, args.toArray(new String[0]));
+        }
+
+        if (exitCode != 0) {
+            StringBuilder message = new StringBuilder();
+            message.append("jmod failed (exit code ").append(exitCode).append(")");
+            if (stdout.size() > 0) {
+                message.append(", output is: ").append(stdout);
+            }
+            if (stderr.size() > 0) {
+                message.append(", error output is: ").append(stderr);
+            }
+
+            throw new BuildException(message.toString(), getLocation());
+        }
+
+        log("Created " + jmodFile.getAbsolutePath(), Project.MSG_INFO);
+    }
+
+    /**
+     * Creates list of arguments to <code>jmod</code> tool, based on this
+     * instance's current state.
+     *
+     * @return new list of <code>jmod</code> arguments
+     */
+    private Collection<String> buildJmodArgs() {
+        Collection<String> args = new ArrayList<>();
+
+        args.add("create");
+
+        args.add("--class-path");
+        args.add(classpath.toString());
+
+        // Paths
+
+        if (modulePath != null && !modulePath.isEmpty()) {
+            args.add("--module-path");
+            args.add(modulePath.toString());
+        }
+        if (commandPath != null && !commandPath.isEmpty()) {
+            args.add("--cmds");
+            args.add(commandPath.toString());
+        }
+        if (configPath != null && !configPath.isEmpty()) {
+            args.add("--config");
+            args.add(configPath.toString());
+        }
+        if (headerPath != null && !headerPath.isEmpty()) {
+            args.add("--header-files");
+            args.add(headerPath.toString());
+        }
+        if (legalPath != null && !legalPath.isEmpty()) {
+            args.add("--legal-notices");
+            args.add(legalPath.toString());
+        }
+        if (nativeLibPath != null && !nativeLibPath.isEmpty()) {
+            args.add("--libs");
+            args.add(nativeLibPath.toString());
+        }
+        if (manPath != null && !manPath.isEmpty()) {
+            args.add("--man-pages");
+            args.add(manPath.toString());
+        }
+
+        // Strings
+
+        String versionStr =
+            (moduleVersion != null ? moduleVersion.toModuleVersionString() : version);
+        if (versionStr != null && !versionStr.isEmpty()) {
+            args.add("--module-version");
+            args.add(versionStr);
+        }
+
+        if (mainClass != null && !mainClass.isEmpty()) {
+            args.add("--main-class");
+            args.add(mainClass);
+        }
+        if (platform != null && !platform.isEmpty()) {
+            args.add("--target-platform");
+            args.add(platform);
+        }
+        if (hashModulesPattern != null && !hashModulesPattern.isEmpty()) {
+            args.add("--hash-modules");
+            args.add(hashModulesPattern);
+        }
+
+        // booleans
+
+        if (!resolveByDefault) {
+            args.add("--do-not-resolve-by-default");
+        }
+        for (ResolutionWarningSpec moduleWarning : moduleWarnings) {
+            moduleWarning.validate();
+            args.add("--warn-if-resolved");
+            args.add(moduleWarning.getReason().toCommandLineOption());
+        }
+
+        // Destination file
+
+        args.add(jmodFile.toString());
+
+        return args;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/modules/Link.java b/src/main/org/apache/tools/ant/taskdefs/modules/Link.java
new file mode 100644
index 0000000..b25d4c2
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/modules/Link.java
@@ -0,0 +1,2122 @@
+/*
+ *  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
+ *
+ *      https://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.modules;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Reader;
+import java.io.IOException;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+import java.nio.file.Files;
+import java.nio.file.FileVisitResult;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.Properties;
+
+import java.util.Collections;
+import java.util.Objects;
+
+import java.util.spi.ToolProvider;
+
+import java.util.stream.Stream;
+import java.util.stream.Collectors;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+
+import org.apache.tools.ant.types.EnumeratedAttribute;
+import org.apache.tools.ant.types.LogLevel;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.ResourceCollection;
+
+import org.apache.tools.ant.util.CompositeMapper;
+import org.apache.tools.ant.util.MergingMapper;
+
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.ResourceUtils;
+
+/**
+ * Assembles jmod files into an executable image.  Equivalent to the
+ * JDK {@code jlink} command.
+ * <p>
+ * Supported attributes:
+ * <dl>
+ * <dt>{@code destDir}
+ * <dd>Root directory of created image. (required)
+ * <dt>{@code modulePath}
+ * <dd>Path of modules.  Should be a list of .jmod files.  Required, unless
+ *     nested module path or modulepathref is present.
+ * <dt>{@code modulePathRef}
+ * <dd>Reference to path of modules.  Referenced path should be
+ *     a list of .jmod files.
+ * <dt>{@code modules}
+ * <dd>Comma-separated list of modules to assemble.  Required, unless
+ *     one or more nested {@code <module>} elements are present.
+ * <dt>{@code observableModules}
+ * <dd>Comma-separated list of explicit modules that comprise
+ *     "universe" visible to tool while linking.
+ * <dt>{@code launchers}
+ * <dd>Comma-separated list of commands, each of the form
+ *     <var>name</var>{@code =}<var>module</var> or
+ *     <var>name</var>{@code =}<var>module</var>{@code /}<var>mainclass</var>
+ * <dt>{@code excludeFiles}
+ * <dd>Comma-separated list of patterns specifying files to exclude from
+ *     linked image.
+ *     Each is either a <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+ *     or {@code @}<var>filename</var>.
+ * <dt>{@code excludeResources}
+ * <dd>Comma-separated list of patterns specifying resources to exclude from jmods.
+ *     Each is either a <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+ *     or {@code @}<var>filename</var>.
+ * <dt>{@code locales}
+ * <dd>Comma-separated list of extra locales to include,
+ *     requires {@code jdk.localedata} module
+ * <dt>{@code resourceOrder}
+ * <dt>Comma-separated list of patterns specifying resource search order.
+ *     Each is either a <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+ *     or {@code @}<var>filename</var>.
+ * <dt>{@code bindServices}
+ * <dd>boolean, whether to link service providers; default is false
+ * <dt>{@code ignoreSigning}
+ * <dd>boolean, whether to allow signed jar files; default is false
+ * <dt>{@code includeHeaders}
+ * <dd>boolean, whether to include header files; default is true
+ * <dt>{@code includeManPages}
+ * <dd>boolean, whether to include man pages; default is true
+ * <dt>{@code includeNativeCommands}
+ * <dd>boolean, whether to include native executables normally generated
+ *     for image; default is true
+ * <dt>{@code debug}
+ * <dd>boolean, whether to include debug information; default is true
+ * <dt>{@code verboseLevel}
+ * <dd>If set, jlink will produce verbose output, which will be logged at
+ *     the specified Ant log level ({@code DEBUG}, {@code VERBOSE},
+ *     {@code INFO}}, {@code WARN}, or {@code ERR}).
+ * <dt>{@code compress}
+ * <dd>compression level, one of:
+ *     <dl>
+ *     <dt>{@code 0}
+ *     <dt>{@code none}
+ *     <dd>no compression (default)
+ *     <dt>{@code 1}
+ *     <dt>{@code strings}
+ *     <dd>constant string sharing
+ *     <dt>{@code 2}
+ *     <dt>{@code zip}
+ *     <dd>zip compression
+ *     </dl>
+ * <dt>{@code endianness}
+ * <dd>Must be {@code little} or {@code big}, default is native endianness
+ * <dt>{@code checkDuplicateLegal}
+ * <dd>Boolean.  When merging legal notices from different modules
+ *     because they have the same name, verify that their contents
+ *     are identical.  Default is false, which means any license files
+ *     with the same name are assumed to have the same content, and no
+ *     checking is done.
+ * <dt>{@code vmType}
+ * <dd>Hotspot VM in image, one of:
+ *     <ul>
+ *     <li>{@code client}
+ *     <li>{@code server}
+ *     <li>{@code minimal}
+ *     <li>{@code all} (default)
+ *     </ul>
+ * </dl>
+ *
+ * <p>
+ * Supported nested elements
+ * <dl>
+ * <dt>{@code <modulepath>}
+ * <dd>path element
+ * <dt>{@code <module>}
+ * <dd>May be specified multiple times.
+ *     Only attribute is required {@code name} attribute.
+ * <dt>{@code <observableModule>}
+ * <dd>May be specified multiple times.
+ *     Only attribute is required {@code name} attribute.
+ * <dt>{@code <launcher>}
+ * <dd>May be specified multiple times.  Attributes:
+ *     <ul>
+ *     <li>{@code name} (required)
+ *     <li>{@code module} (required)
+ *     <li>{@code mainClass} (optional)
+ *     </ul>
+ * <dt>{@code <locale>}
+ * <dd>May be specified multiple times.
+ *     Only attribute is required {@code name} attribute.
+ * <dt>{@code <resourceOrder>}
+ * <dd>Explicit resource search order in image.  May be specified multiple
+ *     times.  Exactly one of these attributes must be specified:
+ *     <dl>
+ *     <dt>{@code pattern}
+ *     <dd>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+ *     <dt>{@code listFile}
+ *     <dd>Text file containing list of resource names (not patterns),
+ *         one per line
+ *     </dl>
+ *     If the {@code resourceOrder} attribute is also present on the task, its
+ *     patterns are treated as if they occur before patterns in nested
+ *     {@code <resourceOrder>} elements.
+ * <dt>{@code <excludeFiles>}
+ * <dd>Excludes files from linked image tree.  May be specified multiple times.
+ *     Exactly one of these attributes is required:
+ *     <dl>
+ *     <dt>{@code pattern}
+ *     <dd>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+ *     <dt>{@code listFile}
+ *     <dd>Text file containing list of file names (not patterns),
+ *         one per line
+ *     </dl>
+ * <dt>{@code <excludeResources>}
+ * <dd>Excludes resources from jmods.  May be specified multiple times.
+ *     Exactly one of these attributes is required:
+ *     <dl>
+ *     <dt>{@code pattern}
+ *     <dd>A <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">standard PathMatcher pattern</a>
+ *     <dt>{@code listFile}
+ *     <dd>Text file containing list of resource names (not patterns),
+ *         one per line
+ *     </dl>
+ * <dt>{@code <compress>}
+ * <dd>Must have {@code level} attribute, whose permitted values are the same
+ *     as the {@code compress} task attribute described above.
+ *     May also have a {@code files} attribute, which is a comma-separated
+ *     list of patterns, and/or nested {@code <files>} elements, each with
+ *     either a {@code pattern} attribute or {@code listFile} attribute.
+ * <dt>{@code <releaseInfo>}
+ * <dd>Replaces, augments, or trims the image's release info properties.
+ *     This may specify any of the following:
+ *     <ul>
+ *     <li>A {@code file} attribute, pointing to a Java properties file
+ *         containing new release info properties that will entirely replace
+ *         the current ones.
+ *     <li>A {@code delete} attribute, containing comma-separated property keys
+ *         to remove from application's release info, and/or any number of
+ *         nested {@code <delete>} elements, each with a required {@code key}
+ *         attribute.
+ *     <li>One or more nested {@code <add>} elements, containing either
+ *         {@code key} and {@code value} attributes, or a {@code file}
+ *         attribute and an optional {@code charset} attribute.
+ *     </ul>
+ * </dl>
+ *
+ * @see <a href="https://docs.oracle.com/en/java/javase/11/tools/jlink.html"><code>jlink</code> tool reference</a>
+ *
+ * @since 1.10.6
+ */
+public class Link
+extends Task {
+    /**
+     * Error message for improperly formatted launcher attribute.
+     */
+    private static final String INVALID_LAUNCHER_STRING =
+        "Launcher command must take the form name=module "
+        + "or name=module/mainclass";
+
+    /** Path of directories containing linkable modules. */
+    private Path modulePath;
+
+    /** Modules to include in linked image. */
+    private final List<ModuleSpec> modules = new ArrayList<>();
+
+    /** If non-empty, list of all modules linker is permitted to know about. */
+    private final List<ModuleSpec> observableModules = new ArrayList<>();
+
+    /**
+     * Additional runnable programs which linker will place in image's
+     * <code>bin</code> directory.
+     */
+    private final List<Launcher> launchers = new ArrayList<>();
+
+    /**
+     * Locales to explicitly include from {@code jdk.localdata} module.
+     * If empty, all locales are included.
+     */
+    private final List<LocaleSpec> locales = new ArrayList<>();
+
+    /** Resource ordering. */
+    private final List<PatternListEntry> ordering = new ArrayList<>();
+
+    /** Files to exclude from linked image. */
+    private final List<PatternListEntry> excludedFiles = new ArrayList<>();
+
+    /**
+     * Resources in linked modules which should be excluded from linked image.
+     */
+    private final List<PatternListEntry> excludedResources = new ArrayList<>();
+
+    /**
+     * Whether to include all service provides in linked image which are
+     * present in the module path and which are needed by modules explicitly
+     * linked.
+     */
+    private boolean bindServices;
+
+    /**
+     * Whether to ignore signed jars (and jmods based on signed jars) when
+     * linking, instead of emitting an error.
+     */
+    private boolean ignoreSigning;
+
+    /** Whether to include header files from linked modules in image. */
+    private boolean includeHeaders = true;
+
+    /** Whether to include man pages from linked modules in image. */
+    private boolean includeManPages = true;
+
+    /** Whether to include native commands from linked modules in image. */
+    private boolean includeNativeCommands = true;
+
+    /** Whether to include classes' debug information or strip it. */
+    private boolean debug = true;
+
+    /**
+     * The Ant logging level at which verbose output of linked should be
+     * emitted.  If null, verbose output is disabled.
+     */
+    private LogLevel verboseLevel;
+
+    /** Directory into which linked image will be placed. */
+    private File outputDir;
+
+    /** Endianness of some files (?) in linked image. */
+    private Endianness endianness;
+
+    /**
+     * Simple compression level applied to linked image.
+     * This or {@link #compression} may be set, but not both.
+     */
+    private CompressionLevel compressionLevel;
+
+    /**
+     * Describes which files in image to compress, and how to compress them.
+     * This or {@link #compressionLevel} may be set, but not both.
+     */
+    private Compression compression;
+
+    /**
+     * Whether to check duplicate legal notices from different modules
+     * actually have identical content, not just indentical names,
+     * before merging them.
+     * <a href="https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java#L80">Forced to true as of Java 11.</a>
+     */
+    private boolean checkDuplicateLegal;
+
+    /** Type of VM in linked image. */
+    private VMType vmType;
+
+    /** Changes to linked image's default release info. */
+    private final List<ReleaseInfo> releaseInfo = new ArrayList<>();
+
+    /**
+     * Adds child {@code <modulePath>} element.
+     *
+     * @return new, empty child element
+     *
+     * @see #setModulePath(Path)
+     */
+    public Path createModulePath() {
+        if (modulePath == null) {
+            modulePath = new Path(getProject());
+        }
+        return modulePath.createPath();
+    }
+
+    /**
+     * Attribute containing path of directories containing linkable modules.
+     *
+     * @return current module path, possibly {@code null}
+     *
+     * @see #setModulePath(Path)
+     * @see #createModulePath()
+     */
+    public Path getModulePath() {
+        return modulePath;
+    }
+
+    /**
+     * Sets attribute containing path of directories containing
+     * linkable modules.
+     *
+     * @param path new module path
+     *
+     * @see #getModulePath()
+     * @see #setModulePathRef(Reference)
+     * @see #createModulePath()
+     */
+    public void setModulePath(final Path path) {
+        if (modulePath == null) {
+            this.modulePath = path;
+        } else {
+            modulePath.append(path);
+        }
+    }
+
+    /**
+     * Sets module path as a reference.
+     *
+     * @param ref path reference
+     *
+     * @see #setModulePath(Path)
+     * @see #createModulePath()
+     */
+    public void setModulePathRef(final Reference ref) {
+        createModulePath().setRefid(ref);
+    }
+
+    /**
+     * Adds child {@code <module>} element, specifying a module to link.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setModules(String)
+     */
+    public ModuleSpec createModule() {
+        ModuleSpec module = new ModuleSpec();
+        modules.add(module);
+        return module;
+    }
+
+    /**
+     * Sets attribute containing list of modules to link.
+     *
+     * @param moduleList comma-separated list of module names
+     */
+    public void setModules(final String moduleList) {
+        for (String moduleName : moduleList.split(",")) {
+            modules.add(new ModuleSpec(moduleName));
+        }
+    }
+
+    /**
+     * Creates child {@code <observableModule>} element that represents
+     * one of the modules the linker is permitted to know about.
+     *
+     * @return new, unconfigured child element
+     */
+    public ModuleSpec createObservableModule() {
+        ModuleSpec module = new ModuleSpec();
+        observableModules.add(module);
+        return module;
+    }
+
+    /**
+     * Sets attribute containing modules linker is permitted to know about.
+     *
+     * @param moduleList comma-separated list of module names
+     */
+    public void setObservableModules(final String moduleList) {
+        for (String moduleName : moduleList.split(",")) {
+            observableModules.add(new ModuleSpec(moduleName));
+        }
+    }
+
+    /**
+     * Creates child {@code <launcher>} element that can contain information
+     * on additional executable in the linked image.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setLaunchers(String)
+     */
+    public Launcher createLauncher() {
+        Launcher command = new Launcher();
+        launchers.add(command);
+        return command;
+    }
+
+    /**
+     * Sets attribute containing comma-separated list of information needed for
+     * additional executables in the linked image.  Each item must be of the
+     * form * <var>name</var>{@code =}<var>module</var> or
+     * <var>name</var>{@code =}<var>module</var>{@code /}<var>mainclass</var>.
+     *
+     * @param launcherList comma-separated list of launcher data
+     */
+    public void setLaunchers(final String launcherList) {
+        for (String launcherSpec : launcherList.split(",")) {
+            launchers.add(new Launcher(launcherSpec));
+        }
+    }
+
+    /**
+     * Creates child {@code <locale>} element that specifies a Java locale,
+     * or set of locales, to include from the {@code jdk.localedata} module
+     * in the linked image.
+     *
+     * @return new, unconfigured child element
+     */
+    public LocaleSpec createLocale() {
+        LocaleSpec locale = new LocaleSpec();
+        locales.add(locale);
+        return locale;
+    }
+
+    /**
+     * Sets attribute containing a list of locale patterns, to specify
+     * Java locales to include from {@code jdk.localedata} module in
+     * linked image.  Asterisks ({@code *}) are permitted for wildcard
+     * matches.
+     *
+     * @param localeList comma-separated list of locale patterns
+     */
+    public void setLocales(final String localeList) {
+        for (String localeName : localeList.split(",")) {
+            locales.add(new LocaleSpec(localeName));
+        }
+    }
+
+    /**
+     * Creates child {@code <excludeFiles>} element that specifies
+     * files to exclude from linked modules when assembling linked image.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setExcludeFiles(String)
+     */
+    public PatternListEntry createExcludeFiles() {
+        PatternListEntry entry = new PatternListEntry();
+        excludedFiles.add(entry);
+        return entry;
+    }
+
+    /**
+     * Sets attribute containing a list of patterns denoting files
+     * to exclude from linked modules when assembling linked image.
+     *
+     * @param patternList comman-separated list of patterns
+     *
+     * @see Link.PatternListEntry
+     */
+    public void setExcludeFiles(String patternList) {
+        for (String pattern : patternList.split(",")) {
+            excludedFiles.add(new PatternListEntry(pattern));
+        }
+    }
+
+    /**
+     * Creates child {@code <excludeResources>} element that specifies
+     * resources in linked modules that will be excluded from linked image.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setExcludeResources(String)
+     */
+    public PatternListEntry createExcludeResources() {
+        PatternListEntry entry = new PatternListEntry();
+        excludedResources.add(entry);
+        return entry;
+    }
+
+    /**
+     * Sets attribute containing a list of patterns denoting resources
+     * to exclude from linked modules in linked image.
+     *
+     * @param patternList comma-separated list of patterns
+     *
+     * @see #createExcludeResources()
+     * @see Link.PatternListEntry
+     */
+    public void setExcludeResources(String patternList) {
+        for (String pattern : patternList.split(",")) {
+            excludedResources.add(new PatternListEntry(pattern));
+        }
+    }
+
+    /**
+     * Creates child {@code <resourceOrder} element that specifies
+     * explicit ordering of resources in linked image.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setResourceOrder(String)
+     */
+    public PatternListEntry createResourceOrder() {
+        PatternListEntry order = new PatternListEntry();
+        ordering.add(order);
+        return order;
+    }
+
+    /**
+     * Sets attribute containing a list of patterns that explicitly
+     * order resources in the linked image.  Any patterns specified here
+     * will be placed before any patterns specified as
+     * {@linkplain #createResourceOrder() child elements}.
+     *
+     * @param patternList comma-separated list of patterns
+     *
+     * @see #createResourceOrder()
+     * @see Link.PatternListEntry
+     */
+    public void setResourceOrder(final String patternList) {
+        List<PatternListEntry> orderList = new ArrayList<>();
+
+        for (String pattern : patternList.split(",")) {
+            orderList.add(new PatternListEntry(pattern));
+        }
+
+        // Attribute value comes before nested elements.
+        ordering.addAll(0, orderList);
+    }
+
+    /**
+     * Attribute indicating whether linked image should pull in providers
+     * in the module path of services used by explicitly linked modules.
+     *
+     * @return true if linked will pull in service provides, false if not
+     *
+     * @see #setBindServices(boolean)
+     */
+    public boolean getBindServices() {
+        return bindServices;
+    }
+
+    /**
+     * Sets attribute indicating whether linked image should pull in providers
+     * in the module path of services used by explicitly linked modules.
+     *
+     * @param bind whether to include service providers
+     *
+     * @see #getBindServices()
+     */
+    public void setBindServices(final boolean bind) {
+        this.bindServices = bind;
+    }
+
+    /**
+     * Attribute indicating whether linker should allow modules made from
+     * signed jars.
+     *
+     * @return true if signed jars are allowed, false if modules based on
+     *         signed jars cause an error
+     *
+     * @see #setIgnoreSigning(boolean)
+     */
+    public boolean getIgnoreSigning() {
+        return ignoreSigning;
+    }
+
+    /**
+     * Sets attribute indicating whether linker should allow modules made from
+     * signed jars.
+     * <p>
+     * Note: As of Java 11, this attribute is internally forced to true.  See
+     * <a href="https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java#L80">the source</a>.
+     *
+     * @param ignore true to have linker allow signed jars,
+     *               false to have linker emit an error for signed jars
+     *
+     *
+     * @see #getIgnoreSigning()
+     */
+    public void setIgnoreSigning(final boolean ignore) {
+        this.ignoreSigning = ignore;
+    }
+
+    /**
+     * Attribute indicating whether to include header files from linked modules
+     * in image.
+     *
+     * @return true if header files should be included, false to exclude them
+     *
+     * @see #setIncludeHeaders(boolean)
+     */
+    public boolean getIncludeHeaders() {
+        return includeHeaders;
+    }
+
+    /**
+     * Sets attribute indicating whether to include header files from
+     * linked modules in image.
+     *
+     * @param include true if header files should be included,
+     *                false to exclude them
+     *
+     * @see #getIncludeHeaders()
+     */
+    public void setIncludeHeaders(final boolean include) {
+        this.includeHeaders = include;
+    }
+
+    /**
+     * Attribute indicating whether to include man pages from linked modules
+     * in image.
+     *
+     * @return true if man pages should be included, false to exclude them
+     *
+     * @see #setIncludeManPages(boolean)
+     */
+    public boolean getIncludeManPages() {
+        return includeManPages;
+    }
+
+    /**
+     * Sets attribute indicating whether to include man pages from
+     * linked modules in image.
+     *
+     * @param include true if man pages should be included,
+     *                false to exclude them
+     *
+     * @see #getIncludeManPages()
+     */
+    public void setIncludeManPages(final boolean include) {
+        this.includeManPages = include;
+    }
+
+    /**
+     * Attribute indicating whether to include generated native commands,
+     * and native commands from linked modules, in image.
+     *
+     * @return true if native commands should be included, false to exclude them
+     *
+     * @see #setIncludeNativeCommands(boolean)
+     */
+    public boolean getIncludeNativeCommands() {
+        return includeNativeCommands;
+    }
+
+    /**
+     * Sets attribute indicating whether to include generated native commands,
+     * and native commands from linked modules, in image.
+     *
+     * @param include true if native commands should be included,
+     *                false to exclude them
+     *
+     * @see #getIncludeNativeCommands()
+     */
+    public void setIncludeNativeCommands(final boolean include) {
+        this.includeNativeCommands = include;
+    }
+
+    /**
+     * Attribute indicating whether linker should keep or strip
+     * debug information in classes.
+     *
+     * @return true if debug information will be retained,
+     *         false if it will be stripped
+     *
+     * @see #setDebug(boolean)
+     */
+    public boolean getDebug() {
+        return debug;
+    }
+
+    /**
+     * Sets attribute indicating whether linker should keep or strip
+     * debug information in classes.
+     *
+     * @param debug true if debug information should be retained,
+     *              false if it should be stripped
+     *
+     * @see #getDebug()
+     */
+    public void setDebug(final boolean debug) {
+        this.debug = debug;
+    }
+
+    /**
+     * Attribute indicating whether linker should produce verbose output,
+     * and at what logging level that output should be shown.
+     *
+     * @return logging level at which to show linker's verbose output,
+     *         or {@code null} to disable verbose output
+     *
+     * @see #setVerboseLevel(LogLevel)
+     */
+    public LogLevel getVerboseLevel() {
+        return verboseLevel;
+    }
+
+    /**
+     * Sets attribute indicating whether linker should produce verbose output,
+     * and at what logging level that output should be shown.
+     *
+     * @param level level logging level at which to show linker's
+     *              verbose output, or {@code null} to disable verbose output
+     *
+     * @see #getVerboseLevel()
+     */
+    public void setVerboseLevel(final LogLevel level) {
+        this.verboseLevel = level;
+    }
+
+    /**
+     * Required attribute containing directory where linked image will be
+     * created.
+     *
+     * @return directory where linked image will reside
+     *
+     * @see #setDestDir(File)
+     */
+    public File getDestDir() {
+        return outputDir;
+    }
+
+    /**
+     * Sets attribute indicating directory where linked image will be created.
+     *
+     * @param dir directory in which image will be created by linker
+     *
+     * @see #getDestDir()
+     */
+    public void setDestDir(final File dir) {
+        this.outputDir = dir;
+    }
+
+    /**
+     * Attribute indicating level of compression linker will apply to image.
+     * This is exclusive with regard to {@link #createCompress()}:  only one
+     * of the two may be specified.
+     *
+     * @return compression level to apply, or {@code null} for none
+     *
+     * @see #setCompress(Link.CompressionLevel)
+     * @see #createCompress()
+     */
+    public CompressionLevel getCompress() {
+        return compressionLevel;
+    }
+
+    /**
+     * Sets attribute indicating level of compression linker will apply
+     * to image. This is exclusive with regard to {@link #createCompress()}:
+     * only one of the two may be specified.
+     *
+     * @param level compression level to apply, or {@code null} for none
+     *
+     * @see #getCompress()
+     * @see #createCompress()
+     */
+    public void setCompress(final CompressionLevel level) {
+        this.compressionLevel = level;
+    }
+
+    /**
+     * Creates child {@code <compress>} element that specifies the level of
+     * compression the linker will apply, and optionally, which files in the
+     * image will be compressed.  This is exclusive with regard to the
+     * {@link #setCompress compress} attribute:  only one of the two may be
+     * specified.
+     *
+     * @return new, unconfigured child element
+     *
+     * @see #setCompress(Link.CompressionLevel)
+     */
+    public Compression createCompress() {
+        if (compression != null) {
+            throw new BuildException(
+                "Only one nested compression element is permitted.",
+                getLocation());
+        }
+        compression = new Compression();
+        return compression;
+    }
+
+    /**
+     * Attribute which indicates whether certain files in the linked image
+     * will be big-endian or little-endian.  If {@code null}, the underlying
+     * platform's endianness is used.
+     *
+     * @return endianness to apply, or {@code null} to platform default
+     *
+     * @see #setEndianness(Link.Endianness)
+     */
+    public Endianness getEndianness() {
+        return endianness;
+    }
+
+    /**
+     * Sets attribute which indicates whether certain files in the linked image
+     * will be big-endian or little-endian.  If {@code null}, the underlying
+     * platform's endianness is used.
+     *
+     * @param endianness endianness to apply, or {@code null} to use
+     *                   platform default
+     *
+     * @see #getEndianness()
+     */
+    public void setEndianness(final Endianness endianness) {
+        this.endianness = endianness;
+    }
+
+    /**
+     * Attribute indicating whether linker should check legal notices with
+     * duplicate names, and refuse to merge them (usually using symbolic links)
+     * if their respective content is not identical.
+     *
+     * @return true if legal notice files with same name should be checked
+     *         for identical content, false to suppress check
+     *
+     * @see #setCheckDuplicateLegal(boolean)
+     */
+    public boolean getCheckDuplicateLegal() {
+        return checkDuplicateLegal;
+    }
+
+    /**
+     * Sets attribute indicating whether linker should check legal notices with
+     * duplicate names, and refuse to merge them (usually using symbolic links)
+     * if their respective content is not identical.
+     *
+     * @param check true if legal notice files with same name should be checked
+     *         for identical content, false to suppress check
+     *
+     * @see #getCheckDuplicateLegal()
+     */
+    public void setCheckDuplicateLegal(final boolean check) {
+        this.checkDuplicateLegal = check;
+    }
+
+    /**
+     * Attribute indicating what type of JVM the linked image should have.
+     * If {@code null}, all JVM types are included.
+     *
+     * @return type of JVM linked image will have
+     *
+     * @see #setVmType(Link.VMType)
+     */
+    public VMType getVmType() {
+        return vmType;
+    }
+
+    /**
+     * Set attribute indicating what type of JVM the linked image should have.
+     * If {@code null}, all JVM types are included.
+     *
+     * @param type type of JVM linked image will have
+     *
+     * @see #getVmType()
+     */
+    public void setVmType(final VMType type) {
+        this.vmType = type;
+    }
+
+    /**
+     * Creates child {@code <releaseInfo>} element that modifies the default
+     * release properties of the linked image.
+     *
+     * @return new, unconfigured child element
+     */
+    public ReleaseInfo createReleaseInfo() {
+        ReleaseInfo info = new ReleaseInfo();
+        releaseInfo.add(info);
+        return info;
+    }
+
+    /**
+     * Child element that explicitly names a Java module.
+     */
+    public class ModuleSpec {
+        /** Module's name.  Required. */
+        private String name;
+
+        /** Creates an unconfigured element. */
+        public ModuleSpec() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates an element with the given module name.
+         *
+         * @param name module's name
+         */
+        public ModuleSpec(final String name) {
+            setName(name);
+        }
+
+        /**
+         * Attribute containing name of module this element represents.
+         *
+         * @return name of module
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * Sets attribute representing the name of this module this element
+         * represents.
+         *
+         * @param name module's name
+         */
+        public void setName(final String name) {
+            this.name = name;
+        }
+
+        /**
+         * Verifies this element's state.
+         *
+         * @throws BuildException if name is not set
+         */
+        public void validate() {
+            if (name == null) {
+                throw new BuildException("name is required for module.",
+                    getLocation());
+            }
+        }
+    }
+
+    /**
+     * Child element that contains a pattern matching Java locales.
+     */
+    public class LocaleSpec {
+        /** Pattern of locale names to match. */
+        private String name;
+
+        /** Creates an unconfigured element. */
+        public LocaleSpec() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates an element with the given name pattern.
+         *
+         * @param name pattern of locale names to match
+         */
+        public LocaleSpec(final String name) {
+            setName(name);
+        }
+
+        /**
+         * Attribute containing a pattern which matches Java locale names.
+         * May be an explicit Java locale, or may contain an asterisk
+         * ({@code *)} for wildcard matching.
+         *
+         * @return this element's locale name pattern
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * Sets attribute containing a pattern which matches Java locale names.
+         * May be an explicit Java locale, or may contain an asterisk
+         * ({@code *)} for wildcard matching.
+         *
+         * @param name new locale name or pattern matching locale names
+         */
+        public void setName(final String name) {
+            this.name = name;
+        }
+
+        /**
+         * Verifies this element's state.
+         *
+         * @throws BuildException if name is not set
+         */
+        public void validate() {
+            if (name == null) {
+                throw new BuildException("name is required for locale.",
+                    getLocation());
+            }
+        }
+    }
+
+    /**
+     * Child element type which specifies a jlink files pattern.  Each
+     * instance may specify a string
+     * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">PathMatcher pattern</a>
+     * or a text file containing a list of such patterns, one per line.
+     */
+    public class PatternListEntry {
+        /** PathMatcher pattern of files to match. */
+        private String pattern;
+
+        /** Plain text list file with one PathMatcher pattern per line. */
+        private File file;
+
+        /** Creates an unconfigured element. */
+        public PatternListEntry() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates a new element from either a pattern or listing file.
+         * If the argument starts with "{@code @}", the remainder of it
+         * is assumed to be a listing file;  otherwise, it is treated as
+         * a PathMatcher pattern.
+         *
+         * @param pattern a PathMatcher pattern or {@code @}-filename
+         */
+        public PatternListEntry(final String pattern) {
+            if (pattern.startsWith("@")) {
+                setListFile(new File(pattern.substring(1)));
+            } else {
+                setPattern(pattern);
+            }
+        }
+
+        /**
+         * Returns this element's PathMatcher pattern attribute, if set.
+         *
+         * @return this element's files pattern
+         */
+        public String getPattern() {
+            return pattern;
+        }
+
+        /**
+         * Sets this element's
+         * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29">PathMatcher pattern</a>
+         * attribute for matching files.
+         *
+         * @param pattern new files pattern
+         */
+        public void setPattern(final String pattern) {
+            this.pattern = pattern;
+        }
+
+        /**
+         * Returns this element's list file attribute, if set.
+         *
+         * @return this element's list file
+         *
+         * @see #setListFile(File)
+         */
+        public File getListFile() {
+            return file;
+        }
+
+        /**
+         * Sets this element's list file attribute.  The file must be a
+         * plain text file with one PathMatcher pattern per line.
+         *
+         * @param file list file containing patterns
+         *
+         * @see #getListFile()
+         */
+        public void setListFile(final File file) {
+            this.file = file;
+        }
+
+        /**
+         * Verifies this element's state.
+         *
+         * @throws BuildException if both pattern and file are set
+         * @throws BuildException if neither pattern nor file is set
+         */
+        public void validate() {
+            if ((pattern == null && file == null)
+                || (pattern != null && file != null)) {
+
+                throw new BuildException(
+                    "Each entry in a pattern list must specify "
+                    + "exactly one of pattern or file.", getLocation());
+            }
+        }
+
+        /**
+         * Converts this element to a jlink command line attribute,
+         * either this element's bare pattern, or its list file
+         * preceded by "{@code @}".
+         *
+         * @return this element's information converted to a command line value
+         */
+        public String toOptionValue() {
+            return pattern != null ? pattern : ("@" + file);
+        }
+    }
+
+    /**
+     * Child element representing a custom launcher command in a linked image.
+     * A launcher has a name, which is typically used as a file name for an
+     * executable file, a Java module name, and optionally a class within
+     * that module which can act as a standard Java main class.
+     */
+    public class Launcher {
+        /** This launcher's name, usually used to create an executable file. */
+        private String name;
+
+        /** The name of the Java module this launcher launches. */
+        private String module;
+
+        /**
+         * The class within this element's {@link #module} to run.
+         * Optional if the Java module specifies its own main class.
+         */
+        private String mainClass;
+
+        /** Creates a new, unconfigured element. */
+        public Launcher() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates a new element from a {@code jlink}-compatible string
+         * specifier, which must take the form
+         * <var>name</var>{@code =}<var>module</var> or
+         * <var>name</var>{@code =}<var>module</var>{@code /}<var>mainclass</var>.
+         *
+         * @param textSpec name, module, and optional main class, as described
+         *                 above
+         *
+         * @throws NullPointerException if argument is {@code null}
+         * @throws BuildException if argument does not conform to above
+         *                        requirements
+         */
+        public Launcher(final String textSpec) {
+            Objects.requireNonNull(textSpec, "Text cannot be null");
+
+            int equals = textSpec.lastIndexOf('=');
+            if (equals < 1) {
+                throw new BuildException(INVALID_LAUNCHER_STRING);
+            }
+
+            setName(textSpec.substring(0, equals));
+
+            int slash = textSpec.indexOf('/', equals);
+            if (slash < 0) {
+                setModule(textSpec.substring(equals + 1));
+            } else if (slash > equals + 1 && slash < textSpec.length() - 1) {
+                setModule(textSpec.substring(equals + 1, slash));
+                setMainClass(textSpec.substring(slash + 1));
+            } else {
+                throw new BuildException(INVALID_LAUNCHER_STRING);
+            }
+        }
+
+        /**
+         * Returns this element's name attribute, typically used as the basis
+         * of an executable file name.
+         *
+         * @return this element's name
+         *
+         * @see #setName(String)
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * Sets this element's name attribute, which is typically used by the
+         * linker to create an executable file with a similar name.  Thus,
+         * the name should contain only characters safe for file names.
+         *
+         * @param name name of launcher
+         */
+        public void setName(final String name) {
+            this.name = name;
+        }
+
+        /**
+         * Returns the attribute of this element which contains the
+         * name of the Java module to execute.
+         *
+         * @return this element's module name
+         */
+        public String getModule() {
+            return module;
+        }
+
+        /**
+         * Sets the attribute of this element which contains the name of
+         * a Java module to execute.
+         *
+         * @param module name of module to execute
+         */
+        public void setModule(final String module) {
+            this.module = module;
+        }
+
+        /**
+         * Returns the attribute of this element which contains the main class
+         * to execute in this element's {@linkplain #getModule() module}, if
+         * that module doesn't define its main class.
+         *
+         * @return name of main class to execute
+         */
+        public String getMainClass() {
+            return mainClass;
+        }
+
+        /**
+         * Sets the attribute which contains the main class to execute in
+         * this element's {@linkplain #getModule() module}, if that module
+         * doesn't define its main class.
+         *
+         * @param className name of class to execute
+         */
+        public void setMainClass(final String className) {
+            this.mainClass = className;
+        }
+
+        /**
+         * Verifies this element's state.
+         *
+         * @throws BuildException if name or module is not set
+         */
+        public void validate() {
+            if (name == null || name.isEmpty()) {
+                throw new BuildException("Launcher must have a name",
+                    getLocation());
+            }
+            if (module == null || module.isEmpty()) {
+                throw new BuildException("Launcher must have specify a module",
+                    getLocation());
+            }
+        }
+
+        /**
+         * Returns this element's information in jlink launcher format:
+         * <var>name</var>{@code =}<var>module</var> or
+         * <var>name</var>{@code =}<var>module</var>{@code /}<var>mainclass</var>.
+         *
+         * @return name, module and optional main class in jlink format
+         */
+        @Override
+        public String toString() {
+            if (mainClass != null) {
+                return name + "=" + module + "/" + mainClass;
+            } else {
+                return name + "=" + module;
+            }
+        }
+    }
+
+    /**
+     * Possible values for linked image endianness:
+     * {@code little} and {@code big}.
+     */
+    public static class Endianness
+    extends EnumeratedAttribute {
+        @Override
+        public String[] getValues() {
+            return new String[] {
+                "little", "big"
+            };
+        }
+    }
+
+    /**
+     * Possible values for JVM type in linked image:
+     * {@code client}, {@code server}, {@code minimal}, or {@code all}.
+     */
+    public static class VMType
+    extends EnumeratedAttribute {
+        @Override
+        public String[] getValues() {
+            return new String[] {
+                "client", "server", "minimal", "all"
+            };
+        }
+    }
+
+    /**
+     * Possible attribute values for compression level of a linked image:
+     * <dl>
+     * <dt>{@code 0}
+     * <dt>{@code none}
+     * <dd>no compression (default)
+     * <dt>{@code 1}
+     * <dt>{@code strings}
+     * <dd>constant string sharing
+     * <dt>{@code 2}
+     * <dt>{@code zip}
+     * <dd>zip compression
+     * </dl>
+     */
+    public static class CompressionLevel
+    extends EnumeratedAttribute {
+        private static final Map<String, String> KEYWORDS;
+
+        static {
+            Map<String, String> map = new LinkedHashMap<>();
+            map.put("0", "0");
+            map.put("1", "1");
+            map.put("2", "2");
+            map.put("none", "0");
+            map.put("strings", "1");
+            map.put("zip", "2");
+
+            KEYWORDS = Collections.unmodifiableMap(map);
+        }
+
+        @Override
+        public String[] getValues() {
+            return KEYWORDS.keySet().toArray(new String[0]);
+        }
+
+        /**
+         * Converts this value to a string suitable for use in a
+         * jlink command.
+         *
+         * @return jlink keyword corresponding to this value
+         */
+        String toCommandLineOption() {
+            return KEYWORDS.get(getValue());
+        }
+    }
+
+    /**
+     * Child element fully describing compression of a linked image.
+     * This includes the level, and optionally, the names of files to compress.
+     */
+    public class Compression {
+        /** Compression level.  Required attribute. */
+        private CompressionLevel level;
+
+        /**
+         * Patterns specifying files to compress.  If empty, all files are
+         * compressed.
+         */
+        private final List<PatternListEntry> patterns = new ArrayList<>();
+
+        /**
+         * Required attribute containing level of compression.
+         *
+         * @return compression level
+         */
+        public CompressionLevel getLevel() {
+            return level;
+        }
+
+        /**
+         * Sets attribute indicating level of compression.
+         *
+         * @param level type of compression to apply to linked image
+         */
+        public void setLevel(final CompressionLevel level) {
+            this.level = level;
+        }
+
+        /**
+         * Creates a nested element which can specify a pattern of files
+         * to compress.
+         *
+         * @return new, unconfigured child element
+         */
+        public PatternListEntry createFiles() {
+            PatternListEntry pattern = new PatternListEntry();
+            patterns.add(pattern);
+            return pattern;
+        }
+
+        /**
+         * Sets an attribute that represents a list of file patterns to
+         * compress in the linked image, as a comma-separated list of
+         * PathMatcher patterns or pattern list files.
+         *
+         * @param patternList comma-separated list of patterns and/or file names
+         *
+         * @see Link.PatternListEntry
+         */
+        public void setFiles(final String patternList) {
+            patterns.clear();
+            for (String pattern : patternList.split(",")) {
+                patterns.add(new PatternListEntry(pattern));
+            }
+        }
+
+        /**
+         * Verifies this element's state.
+         *
+         * @throws BuildException if compression level is not set
+         * @throws BuildException if any nested patterns are invalid
+         */
+        public void validate() {
+            if (level == null) {
+                throw new BuildException("Compression level must be specified.",
+                     getLocation());
+            }
+            patterns.forEach(PatternListEntry::validate);
+        }
+
+        /**
+         * Converts this element to a single jlink option value.
+         *
+         * @return command line option representing this element's state
+         */
+        public String toCommandLineOption() {
+            StringBuilder option =
+                new StringBuilder(level.toCommandLineOption());
+
+            if (!patterns.isEmpty()) {
+                String separator = ":filter=";
+                for (PatternListEntry entry : patterns) {
+                    option.append(separator).append(entry.toOptionValue());
+                    separator = ",";
+                }
+            }
+
+            return option.toString();
+        }
+    }
+
+    /**
+     * Grandchild element representing deletable key in a linked image's
+     * release properties.
+     */
+    public class ReleaseInfoKey {
+        /** Required attribute holding property key to delete. */
+        private String key;
+
+        /** Creates a new, unconfigured element. */
+        public ReleaseInfoKey() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates a new element with the specified key.
+         *
+         * @param key property key to delete from release info
+         */
+        public ReleaseInfoKey(final String key) {
+            setKey(key);
+        }
+
+        /**
+         * Attribute holding the release info property key to delete.
+         *
+         * @return property key to be deleted
+         */
+        public String getKey() {
+            return key;
+        }
+
+        /**
+         * Sets attribute containing property key to delete from
+         * linked image's release info.
+         *
+         * @param key propert key to be deleted
+         */
+        public void setKey(final String key) {
+            this.key = key;
+        }
+
+        /**
+         * Verifies this element's state is valid.
+         *
+         * @throws BuildException if key is not set
+         */
+        public void validate() {
+            if (key == null) {
+                throw new BuildException(
+                    "Release info key must define a 'key' attribute.",
+                    getLocation());
+            }
+        }
+    }
+
+    /**
+     * Grandchild element describing additional release info properties for a
+     * linked image.  To be valid, an instance must have either a non-null
+     * key and value, or a non-null file.
+     */
+    public class ReleaseInfoEntry {
+        /** New release property's key. */
+        private String key;
+
+        /** New release property's value. */
+        private String value;
+
+        /** File containing additional release properties. */
+        private File file;
+
+        /** Charset of {@link #file}. */
+        private String charset = StandardCharsets.ISO_8859_1.name();
+
+        /** Creates a new, unconfigured element. */
+        public ReleaseInfoEntry() {
+            // Deliberately empty.
+        }
+
+        /**
+         * Creates a new element which specifies a single additional property.
+         *
+         * @param key new property's key
+         * @param value new property's value
+         */
+        public ReleaseInfoEntry(final String key,
+                                final String value) {
+            setKey(key);
+            setValue(value);
+        }
+
+        /**
+         * Attribute containing the key of this element's additional property.
+         *
+         * @return additional property's key
+         *
+         * @see #getValue()
+         */
+        public String getKey() {
+            return key;
+        }
+
+        /**
+         * Sets attribute containing the key of this element's
+         * additional property.
+         *
+         * @param key additional property's key
+         *
+         * @see #setValue(String)
+         */
+        public void setKey(final String key) {
+            this.key = key;
+        }
+
+        /**
+         * Attribute containing the value of this element's additional property.
+         *
+         * @return additional property's value
+         *
+         * @see #getKey()
+         */
+        public String getValue() {
+            return value;
+        }
+
+        /**
+         * Sets attributes containing the value of this element's
+         * additional property.
+         *
+         * @param value additional property's value
+         *
+         * @see #setKey(String)
+         */
+        public void setValue(final String value) {
+            this.value = value;
+        }
+
+        /**
+         * Attribute containing a Java properties file which contains
+         * additional release info properties.  This is exclusive with
+         * respect to the {@linkplain #getKey() key} and
+         * {@linkplain #getValue() value} of this instance:  either the
+         * file must be set, or the key and value must be set.
+         *
+         * @return this element's properties file
+         */
+        public File getFile() {
+            return file;
+        }
+
+        /**
+         * Sets attribute containing a Java properties file which contains
+         * additional release info properties.  This is exclusive with
+         * respect to the {@linkplain #setKey(String) key} and
+         * {@linkplain #setValue(String) value} of this instance:  either the
+         * file must be set, or the key and value must be set.
+         *
+         * @param file this element's properties file
+         */
+        public void setFile(final File file) {
+            this.file = file;
+        }
+
+        /**
+         * Attribute containing the character set of this object's
+         * {@linkplain #getFile() file}.  This is {@code ISO_8859_1}
+         * by default, in accordance with the java.util.Properties default.
+         *
+         * @return character set of this element's file
+         */
+        public String getCharset() {
+            return charset;
+        }
+
+        /**
+         * Sets attribute containing the character set of this object's
+         * {@linkplain #setFile(File) file}.  If not set, this is
+         * {@code ISO_8859_1} by default, in accordance with the
+         * java.util.Properties default.
+         *
+         * @param charset character set of this element's file
+         */
+        public void setCharset(final String charset) {
+            this.charset = charset;
+        }
+
+        /**
+         * Verifies the state of this element.
+         *
+         * @throws BuildException if file is set, and key and/or value are set
+         * @throws BuildException if file is not set, and key and value are not both set
+         * @throws BuildException if charset is not a valid Java Charset name
+         */
+        public void validate() {
+            if (file == null && (key == null || value == null)) {
+                throw new BuildException(
+                    "Release info must define 'key' and 'value' attributes, "
+                    + "or a 'file' attribute.", getLocation());
+            }
+            if (file != null && (key != null || value != null)) {
+                throw new BuildException(
+                    "Release info cannot define both a file attribute and "
+                    + "key/value attributes.", getLocation());
+            }
+
+            // This can't happen from a build file, but can theoretically
+            // happen if called from Java code.
+            if (charset == null) {
+                throw new BuildException("Charset cannot be null.",
+                    getLocation());
+            }
+
+            try {
+                Charset.forName(charset);
+            } catch (IllegalArgumentException e) {
+                throw new BuildException(e, getLocation());
+            }
+        }
+
+        /**
+         * Converts this element to a Java properties object containing
+         * the additional properties this element represents.  If this
+         * element's file is set, it is read;  otherwise, a Properties
+         * object containing just one property, consisting of this element's
+         * key and value, is returned.
+         *
+         * @return new Properties object obtained from this element's file or
+         *         its key and value
+         *
+         * @throws BuildException if file is set, but cannot be read
+         */
+        public Properties toProperties() {
+            Properties props = new Properties();
+            if (file != null) {
+                try (Reader reader = Files.newBufferedReader(
+                    file.toPath(), Charset.forName(charset))) {
+
+                    props.load(reader);
+                } catch (IOException e) {
+                    throw new BuildException(
+                        "Cannot read release info file \"" + file + "\": " + e,
+                        e, getLocation());
+                }
+            } else {
+                props.setProperty(key, value);
+            }
+
+            return props;
+        }
+    }
+
+    /**
+     * Child element describing changes to the default release properties
+     * of a linked image.
+     */
+    public class ReleaseInfo {
+        /**
+         * File that contains replacement release properties for linked image.
+         */
+        private File file;
+
+        /**
+         * Properties to add to default release properties of linked image.
+         */
+        private final List<ReleaseInfoEntry> propertiesToAdd = new ArrayList<>();
+
+        /**
+         * Property keys to remove from release properties of linked image.
+         */
+        private final List<ReleaseInfoKey> propertiesToDelete = new ArrayList<>();
+
+        /**
+         * Attribute specifying Java properties file which will replace the
+         * default release info properties for the linked image.
+         *
+         * @return release properties file
+         */
+        public File getFile() {
+            return file;
+        }
+
+        /**
+         * Sets attribute specifying Java properties file which will replace
+         * the default release info properties for the linked image.
+         *
+         * @param file replacement release properties file
+         */
+        public void setFile(final File file) {
+            this.file = file;
+        }
+
+        /**
+         * Creates an uninitialized child element which can represent properties
+         * to add to the default release properties of a linked image.
+         *
+         * @return new, unconfigured child element
+         */
+        public ReleaseInfoEntry createAdd() {
+            ReleaseInfoEntry property = new ReleaseInfoEntry();
+            propertiesToAdd.add(property);
+            return property;
+        }
+
+        /**
+         * Creates an uninitialized child element which can represent
+         * a property key to delete from the release properties of
+         * a linked image.
+         *
+         * @return new, unconfigured child element
+         */
+        public ReleaseInfoKey createDelete() {
+            ReleaseInfoKey key = new ReleaseInfoKey();
+            propertiesToDelete.add(key);
+            return key;
+        }
+
+        /**
+         * Sets attribute which contains a comma-separated list of
+         * property keys to delete from the release properties of
+         * a linked image.
+         *
+         * @param keyList comma-separated list of property keys
+         *
+         * @see #createDelete()
+         */
+        public void setDelete(final String keyList) {
+            for (String key : keyList.split(",")) {
+                propertiesToDelete.add(new ReleaseInfoKey(key));
+            }
+        }
+
+        /**
+         * Verifies the state of this element.
+         *
+         * @throws BuildException if any child element is invalid
+         *
+         * @see Link.ReleaseInfoEntry#validate()
+         * @see Link.ReleaseInfoKey#validate()
+         */
+        public void validate() {
+            propertiesToAdd.forEach(ReleaseInfoEntry::validate);
+            propertiesToDelete.forEach(ReleaseInfoKey::validate);
+        }
+
+        /**
+         * Converts all of this element's state to a series of
+         * <code>jlink</code> options.
+         *
+         * @return new collection of jlink options based on this element's
+         *         attributes and child elements
+         */
+        public Collection<String> toCommandLineOptions() {
+            Collection<String> options = new ArrayList<>();
+
+            if (file != null) {
+                options.add("--release-info=" + file);
+            }
+            if (!propertiesToAdd.isEmpty()) {
+                StringBuilder option = new StringBuilder("--release-info=add");
+
+                for (ReleaseInfoEntry entry : propertiesToAdd) {
+                    Properties props = entry.toProperties();
+                    for (String key : props.stringPropertyNames()) {
+                        option.append(":").append(key).append("=");
+                        option.append(props.getProperty(key));
+                    }
+                }
+
+                options.add(option.toString());
+            }
+            if (!propertiesToDelete.isEmpty()) {
+                StringBuilder option =
+                    new StringBuilder("--release-info=del:keys=");
+
+                String separator = "";
+                for (ReleaseInfoKey key : propertiesToDelete) {
+                    option.append(separator).append(key.getKey());
+                    // jlink docs aren't clear on whether property keys
+                    // to delete should be separated by commas or colons.
+                    separator = ",";
+                }
+
+                options.add(option.toString());
+            }
+
+            return options;
+        }
+    }
+
+    /**
+     * Invokes the jlink tool to create a new linked image, unless the
+     * output directory exists and all of its files are files are newer
+     * than all files in the module path.
+     *
+     * @throws BuildException if destDir is not set
+     * @throws BuildException if module path is unset or empty
+     * @throws BuildException if module list is empty
+     * @throws BuildException if compressionLevel attribute and compression
+     *                        child element are both specified
+     */
+    @Override
+    public void execute()
+    throws BuildException {
+        if (outputDir == null) {
+            throw new BuildException("Destination directory is required.",
+                getLocation());
+        }
+
+        if (modulePath == null || modulePath.isEmpty()) {
+            throw new BuildException("Module path is required.", getLocation());
+        }
+
+        if (modules.isEmpty()) {
+            throw new BuildException("At least one module must be specified.",
+                getLocation());
+        }
+
+        if (outputDir.exists()) {
+            CompositeMapper imageMapper = new CompositeMapper();
+            try (Stream<java.nio.file.Path> imageTree =
+                Files.walk(outputDir.toPath())) {
+
+                /*
+                 * Is this sufficient?  What if part of the image tree was
+                 * deleted or altered?  Should we check for standard
+                 * files and directories, like 'bin', 'lib', 'conf', 'legal',
+                 * and 'release'?  (Some, like 'include', may not be present,
+                 * if the image was previously built with options that
+                 * omitted them.)
+                 */
+                imageTree.forEach(
+                    p -> imageMapper.add(new MergingMapper(p.toString())));
+
+                ResourceCollection outOfDate =
+                    ResourceUtils.selectOutOfDateSources(this, modulePath,
+                        imageMapper, getProject(),
+                        FileUtils.getFileUtils().getFileTimestampGranularity());
+                if (outOfDate.isEmpty()) {
+                    log("Skipping image creation, since "
+                        + "\"" + outputDir + "\" is already newer than "
+                        + "all constituent modules.", Project.MSG_VERBOSE);
+                    return;
+                }
+            } catch (IOException e) {
+                throw new BuildException(
+                    "Could not scan \"" + outputDir + "\" "
+                    + "for being up-to-date: " + e, e, getLocation());
+            }
+        }
+
+        modules.forEach(ModuleSpec::validate);
+        observableModules.forEach(ModuleSpec::validate);
+        launchers.forEach(Launcher::validate);
+        locales.forEach(LocaleSpec::validate);
+        ordering.forEach(PatternListEntry::validate);
+        excludedFiles.forEach(PatternListEntry::validate);
+        excludedResources.forEach(PatternListEntry::validate);
+
+        Collection<String> args = buildJlinkArgs();
+
+        ToolProvider jlink = ToolProvider.findFirst("jlink").orElseThrow(
+            () -> new BuildException("jlink tool not found in JDK.",
+                getLocation()));
+
+        if (outputDir.exists()) {
+            log("Deleting existing " + outputDir, Project.MSG_VERBOSE);
+            deleteTree(outputDir.toPath());
+        }
+
+        log("Executing: jlink " + String.join(" ", args), Project.MSG_VERBOSE);
+
+        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+
+        int exitCode;
+        try (PrintStream out = new PrintStream(stdout);
+             PrintStream err = new PrintStream(stderr)) {
+
+            exitCode = jlink.run(out, err, args.toArray(new String[0]));
+        }
+
+        if (exitCode != 0) {
+            StringBuilder message = new StringBuilder();
+            message.append("jlink failed (exit code ").append(exitCode).append(")");
+            if (stdout.size() > 0) {
+                message.append(", output is: ").append(stdout);
+            }
+            if (stderr.size() > 0) {
+                message.append(", error output is: ").append(stderr);
+            }
+
+            throw new BuildException(message.toString(), getLocation());
+        }
+
+        if (verboseLevel != null) {
+            int level = verboseLevel.getLevel();
+
+            if (stdout.size() > 0) {
+                log(stdout.toString(), level);
+            }
+            if (stderr.size() > 0) {
+                log(stderr.toString(), level);
+            }
+        }
+
+        log("Created " + outputDir.getAbsolutePath(), Project.MSG_INFO);
+    }
+
+    /**
+     * Recursively deletes a file tree.
+     *
+     * @param dir root of tree to delete
+     *
+     * @throws BuildException if deletion fails
+     */
+    private void deleteTree(java.nio.file.Path dir) {
+        try {
+            Files.walkFileTree(dir, new SimpleFileVisitor<java.nio.file.Path>() {
+                @Override
+                public FileVisitResult visitFile(final java.nio.file.Path file,
+                                                 final BasicFileAttributes attr)
+                throws IOException {
+                    Files.delete(file);
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(final java.nio.file.Path dir,
+                                                          IOException e)
+                throws IOException {
+                    if (e == null) {
+                        Files.delete(dir);
+                    }
+                    return super.postVisitDirectory(dir, e);
+                }
+            });
+        } catch (IOException e) {
+            throw new BuildException(
+                "Could not delete \"" + dir + "\": " + e, e, getLocation());
+        }
+    }
+
+    /**
+     * Creates list of arguments to <code>jlink</code> tool, based on this
+     * instance's current state.
+     *
+     * @return new list of <code>jlink</code> arguments
+     *
+     * @throws BuildException if any inconsistencies attributes/elements
+     *                        is found
+     */
+    private Collection<String> buildJlinkArgs() {
+        Collection<String> args = new ArrayList<>();
+
+        args.add("--output");
+        args.add(outputDir.toString());
+
+        args.add("--module-path");
+        args.add(modulePath.toString());
+
+        args.add("--add-modules");
+        args.add(modules.stream().map(ModuleSpec::getName).collect(
+            Collectors.joining(",")));
+
+        if (!observableModules.isEmpty()) {
+            args.add("--limit-modules");
+            args.add(observableModules.stream().map(ModuleSpec::getName).collect(
+                Collectors.joining(",")));
+        }
+
+        if (!locales.isEmpty()) {
+            args.add("--include-locales="
+                + locales.stream().map(LocaleSpec::getName).collect(
+                    Collectors.joining(",")));
+        }
+
+        for (Launcher launcher : launchers) {
+            args.add("--launcher");
+            args.add(launcher.toString());
+        }
+
+        if (!ordering.isEmpty()) {
+            args.add("--order-resources="
+                + ordering.stream().map(PatternListEntry::toOptionValue).collect(
+                    Collectors.joining(",")));
+        }
+        if (!excludedFiles.isEmpty()) {
+            args.add("--exclude-files="
+                + excludedFiles.stream().map(PatternListEntry::toOptionValue).collect(
+                    Collectors.joining(",")));
+        }
+        if (!excludedResources.isEmpty()) {
+            args.add("--exclude-resources="
+                + excludedResources.stream().map(PatternListEntry::toOptionValue).collect(
+                    Collectors.joining(",")));
+        }
+
+        if (bindServices) {
+            args.add("--bind-services");
+        }
+        if (ignoreSigning) {
+            args.add("--ignore-signing-information");
+        }
+        if (!includeHeaders) {
+            args.add("--no-header-files");
+        }
+        if (!includeManPages) {
+            args.add("--no-man-pages");
+        }
+        if (!includeNativeCommands) {
+            args.add("--strip-native-commands");
+        }
+        if (!debug) {
+            args.add("--strip-debug");
+        }
+        if (verboseLevel != null) {
+            args.add("--verbose");
+        }
+
+        if (endianness != null) {
+            args.add("--endian");
+            args.add(endianness.getValue());
+        }
+
+        if (compressionLevel != null) {
+            if (compression != null) {
+                throw new BuildException("compressionLevel attribute "
+                    + "and <compression> child element cannot both be present.",
+                    getLocation());
+            }
+            args.add("--compress=" + compressionLevel.toCommandLineOption());
+        }
+        if (compression != null) {
+            compression.validate();
+            args.add("--compress=" + compression.toCommandLineOption());
+        }
+        if (vmType != null) {
+            args.add("--vm=" + vmType.getValue());
+        }
+        if (checkDuplicateLegal) {
+            args.add("--dedup-legal-notices=error-if-not-same-content");
+        }
+        for (ReleaseInfo info : releaseInfo) {
+            info.validate();
+            args.addAll(info.toCommandLineOptions());
+        }
+
+        return args;
+    }
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/main/org/apache/tools/ant/taskdefs/modules/package-info.java
similarity index 78%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/main/org/apache/tools/ant/taskdefs/modules/package-info.java
index 9d6fcba..b3aec4c 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/main/org/apache/tools/ant/taskdefs/modules/package-info.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,11 @@
  *  limitations under the License.
  *
  */
+
 /**
+ * Tasks for dealing with Java modules, which are supported starting with
+ * Java 9.
+ *
+ * @since 1.10.6
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
-}
+package org.apache.tools.ant.taskdefs.modules;
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 2f73c3f..8ce2a17 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -118,8 +118,9 @@
      * @param superGrammar the super grammar filename
      * @deprecated  since ant 1.6
      */
+    @Deprecated
     public void setGlib(String superGrammar) {
-        String sg = null;
+        String sg;
         if (Os.isFamily("dos")) {
             sg = superGrammar.replace('\\', '/');
         } else {
@@ -127,6 +128,7 @@
         }
         setGlib(FILE_UTILS.resolveFile(getProject().getBaseDir(), sg));
     }
+
     /**
      * Sets an optional super grammar file
      * @param superGrammar the super grammar file
@@ -135,6 +137,7 @@
     public void setGlib(File superGrammar) {
         this.superGrammar = superGrammar;
     }
+
     /**
      * Sets a flag to enable ParseView debugging
      * @param enable a <code>boolean</code> value
@@ -200,7 +203,6 @@
      * @param s a <code>boolean</code> value
      */
     public void setFork(boolean s) {
-        //this.fork = s;
     }
 
     /**
@@ -235,6 +237,7 @@
      * specify it directly.
      * @throws BuildException on error
      */
+    @Override
     public void init() throws BuildException {
         addClasspathEntry("/antlr/ANTLRGrammarParseBehavior.class");
     }
@@ -270,7 +273,7 @@
             log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG);
             createClasspath().setLocation(f);
         } else {
-            log("Couldn\'t find " + resource, Project.MSG_VERBOSE);
+            log("Couldn't find " + resource, Project.MSG_VERBOSE);
         }
     }
 
@@ -278,6 +281,7 @@
      * Execute the task.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         validateAttributes();
 
@@ -356,7 +360,6 @@
         if (targetFile == null || !targetFile.isFile()) {
             throw new BuildException("Invalid target: " + targetFile);
         }
-
         // if no output directory is specified, used the target's directory
         if (outputDirectory == null) {
             setOutputdirectory(new File(targetFile.getParent()));
@@ -368,8 +371,8 @@
 
     private File getGeneratedFile() throws BuildException {
         String generatedFileName = null;
-        try {
-            BufferedReader in = new BufferedReader(new FileReader(targetFile));
+        try (BufferedReader in =
+            new BufferedReader(new FileReader(targetFile))) {
             String line;
             while ((line = in.readLine()) != null) {
                 int extendsIndex = line.indexOf(" extends ");
@@ -379,7 +382,6 @@
                     break;
                 }
             }
-            in.close();
         } catch (Exception e) {
             throw new BuildException("Unable to determine generated class", e);
         }
@@ -421,17 +423,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/Cab.java b/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
index 270b5d4..7be3b28 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -46,12 +46,13 @@
 
 public class Cab extends MatchingTask {
     private static final int DEFAULT_RESULT = -99;
+
     private File cabFile;
     private File baseDir;
-    private Vector filesets = new Vector();
     private boolean doCompress = true;
     private boolean doVerbose = false;
     private String cmdOptions;
+    private boolean filesetAdded = false;
 
     // CheckStyle:VisibilityModifier OFF - bc
     protected String archiveType = "cab";
@@ -101,13 +102,14 @@
 
     /**
      * Adds a set of files to archive.
-     * @param set a set of files to archive.
+     * @param fileset a set of files to archive.
      */
-    public void addFileset(FileSet set) {
-        if (filesets.size() > 0) {
+    public void addFileset(FileSet fileset) {
+        if (filesetAdded) {
             throw new BuildException("Only one nested fileset allowed");
         }
-        filesets.addElement(set);
+        filesetAdded = true;
+        this.fileset = fileset;
     }
 
     /*
@@ -120,15 +122,15 @@
      * @throws BuildException on error.
      */
     protected void checkConfiguration() throws BuildException {
-        if (baseDir == null && filesets.size() == 0) {
-            throw new BuildException("basedir attribute or one "
-                                     + "nested fileset is required!",
-                                     getLocation());
+        if (baseDir == null && !filesetAdded) {
+            throw new BuildException(
+                "basedir attribute or one nested fileset is required!",
+                getLocation());
         }
         if (baseDir != null && !baseDir.exists()) {
             throw new BuildException("basedir does not exist!", getLocation());
         }
-        if (baseDir != null && filesets.size() > 0) {
+        if (baseDir != null && filesetAdded) {
             throw new BuildException(
                 "Both basedir attribute and a nested fileset is not allowed");
         }
@@ -145,8 +147,7 @@
      * @throws BuildException on error.
      */
     protected ExecTask createExec() throws BuildException {
-        ExecTask exec = new ExecTask(this);
-        return exec;
+        return new ExecTask(this);
     }
 
     /**
@@ -154,17 +155,10 @@
      * @param files the list of files to check.
      * @return true if the cab file is newer than its dependents.
      */
-    protected boolean isUpToDate(Vector files) {
-        boolean upToDate = true;
-        final int size = files.size();
-        for (int i = 0; i < size && upToDate; i++) {
-            String file = files.elementAt(i).toString();
-            if (FILE_UTILS.resolveFile(baseDir, file).lastModified()
-                    > cabFile.lastModified()) {
-                upToDate = false;
-            }
-        }
-        return upToDate;
+    protected boolean isUpToDate(Vector<String> files) {
+        final long cabModified = cabFile.lastModified();
+        return files.stream().map(f -> FILE_UTILS.resolveFile(baseDir, f))
+            .mapToLong(File::lastModified).allMatch(t -> t < cabModified);
     }
 
     /**
@@ -177,23 +171,18 @@
      * @return the list file created.
      * @throws IOException if there is an error.
      */
-    protected File createListFile(Vector files)
+    protected File createListFile(Vector<String> files)
         throws IOException {
         File listFile = FILE_UTILS.createTempFile(getProject(), "ant", "", null, true, true);
 
-        BufferedWriter writer = null;
-        try {
-            writer = new BufferedWriter(new FileWriter(listFile));
-
-            final int size = files.size();
-            for (int i = 0; i < size; i++) {
-                writer.write('\"' + files.elementAt(i).toString() + '\"');
+        try (BufferedWriter writer =
+            new BufferedWriter(new FileWriter(listFile))) {
+            for (String f : files) {
+                String s = String.format("\"%s\"", f);
+                writer.write(s);
                 writer.newLine();
             }
-        } finally {
-            FileUtils.close(writer);
         }
-
         return listFile;
     }
 
@@ -202,12 +191,8 @@
      * @param files the vector to append the files to.
      * @param ds the scanner to get the files from.
      */
-    protected void appendFiles(Vector files, DirectoryScanner ds) {
-        String[] dsfiles = ds.getIncludedFiles();
-
-        for (int i = 0; i < dsfiles.length; i++) {
-            files.addElement(dsfiles[i]);
-        }
+    protected void appendFiles(Vector<String> files, DirectoryScanner ds) {
+        Collections.addAll(files, ds.getIncludedFiles());
     }
 
     /**
@@ -217,18 +202,16 @@
      * @return the list of files.
      * @throws BuildException if there is an error.
      */
-    protected Vector getFileList() throws BuildException {
-        Vector files = new Vector();
+    protected Vector<String> getFileList() throws BuildException {
+        Vector<String> files = new Vector<>();
 
         if (baseDir != null) {
             // get files from old methods - includes and nested include
             appendFiles(files, super.getDirectoryScanner(baseDir));
         } else {
-            FileSet fs = (FileSet) filesets.elementAt(0);
-            baseDir = fs.getDir();
-            appendFiles(files, fs.getDirectoryScanner(getProject()));
+            baseDir = fileset.getDir();
+            appendFiles(files, fileset.getDirectoryScanner(getProject()));
         }
-
         return files;
     }
 
@@ -236,11 +219,12 @@
      * execute this task.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
 
         checkConfiguration();
 
-        Vector files = getFileList();
+        Vector<String> files = getFileList();
 
         // quick exit if the target is up to date
         if (isUpToDate(files)) {
@@ -252,20 +236,17 @@
         if (!Os.isFamily("windows")) {
             log("Using listcab/libcabinet", Project.MSG_VERBOSE);
 
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
 
-            Enumeration fileEnum = files.elements();
+            files.forEach(f -> sb.append(f).append("\n"));
 
-            while (fileEnum.hasMoreElements()) {
-                sb.append(fileEnum.nextElement()).append("\n");
-            }
             sb.append("\n").append(cabFile.getAbsolutePath()).append("\n");
 
             try {
                 Process p = Execute.launch(getProject(),
-                                           new String[] {"listcab"}, null,
-                                           baseDir != null ? baseDir : getProject().getBaseDir(),
-                                           true);
+                    new String[] {"listcab"}, null,
+                    baseDir != null ? baseDir : getProject().getBaseDir(),
+                    true);
                 OutputStream out = p.getOutputStream();
 
                 // Create the stream pumpers to forward listcab's stdout and stderr to the log
@@ -277,8 +258,8 @@
                 StreamPumper    errPump = new StreamPumper(p.getErrorStream(), errLog);
 
                 // Pump streams asynchronously
-                (new Thread(outPump)).start();
-                (new Thread(errPump)).start();
+                new Thread(outPump).start();
+                new Thread(errPump).start();
 
                 out.write(sb.toString().getBytes());
                 out.flush();
@@ -305,8 +286,9 @@
                     log("Error executing listcab; error code: " + result);
                 }
             } catch (IOException ex) {
-                String msg = "Problem creating " + cabFile + " " + ex.getMessage();
-                throw new BuildException(msg, getLocation());
+                throw new BuildException(
+                    "Problem creating " + cabFile + " " + ex.getMessage(),
+                    getLocation());
             }
         } else {
             try {
@@ -348,8 +330,9 @@
 
                 listFile.delete();
             } catch (IOException ioe) {
-                String msg = "Problem creating " + cabFile + " " + ioe.getMessage();
-                throw new BuildException(msg, getLocation());
+                throw new BuildException(
+                    "Problem creating " + cabFile + " " + ioe.getMessage(),
+                    getLocation());
             }
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java b/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
index 8a0a9e1..7404bdc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/EchoProperties.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,39 +17,39 @@
  */
 package org.apache.tools.ant.taskdefs.optional;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.Vector;
-
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.LogOutputStream;
 import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.types.PropertySet;
-import org.apache.tools.ant.util.CollectionUtils;
 import org.apache.tools.ant.util.DOMElementWriter;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -130,7 +130,7 @@
      */
     private boolean failonerror = true;
 
-    private Vector propertySets = new Vector();
+    private List<PropertySet> propertySets = new Vector<>();
 
     private String format = "text";
 
@@ -160,23 +160,21 @@
         this.destfile = destfile;
     }
 
-
     /**
      * If true, the task will fail if an error occurs writing the properties
      * file, otherwise errors are just logged.
      *
-     * @param failonerror  <tt>true</tt> if IO exceptions are reported as build
-     *      exceptions, or <tt>false</tt> if IO exceptions are ignored.
+     * @param failonerror  <code>true</code> if IO exceptions are reported as build
+     *      exceptions, or <code>false</code> if IO exceptions are ignored.
      */
     public void setFailOnError(boolean failonerror) {
         this.failonerror = failonerror;
     }
 
-
     /**
      * If the prefix is set, then only properties which start with this
      * prefix string will be recorded. If regex is not set and  if this
-     * is never set, or it is set to an empty string or <tt>null</tt>,
+     * is never set, or it is set to an empty string or <code>null</code>,
      * then all properties will be recorded.
      *
      * <p>For example, if the attribute is set as:</p>
@@ -187,7 +185,7 @@
      * @param  prefix  The new prefix value
      */
     public void setPrefix(String prefix) {
-        if (prefix != null && prefix.length() != 0) {
+        if (prefix != null && !prefix.isEmpty()) {
             this.prefix = prefix;
             PropertySet ps = new PropertySet();
             ps.setProject(getProject());
@@ -199,7 +197,7 @@
     /**
      * If the regex is set, then only properties whose names match it
      * will be recorded.  If prefix is not set and if this is never set,
-     * or it is set to an empty string or <tt>null</tt>, then all
+     * or it is set to an empty string or <code>null</code>, then all
      * properties will be recorded.
      *
      * <p>For example, if the attribute is set as:</p>
@@ -212,7 +210,7 @@
      * @since Ant 1.7
      */
     public void setRegex(String regex) {
-        if (regex != null && regex.length() != 0) {
+        if (regex != null && !regex.isEmpty()) {
             this.regex = regex;
             PropertySet ps = new PropertySet();
             ps.setProject(getProject());
@@ -227,7 +225,7 @@
      * @since Ant 1.6
      */
     public void addPropertyset(PropertySet ps) {
-        propertySets.addElement(ps);
+        propertySets.add(ps);
     }
 
     /**
@@ -249,6 +247,7 @@
          * @see EnumeratedAttribute#getValues()
          * @return accepted values
          */
+        @Override
         public String[] getValues() {
             return formats;
         }
@@ -259,27 +258,28 @@
      *
      * @exception BuildException  trouble, probably file IO
      */
+    @Override
     public void execute() throws BuildException {
         if (prefix != null && regex != null) {
-            throw new BuildException("Please specify either prefix"
-                    + " or regex, but not both", getLocation());
+            throw new BuildException(
+                "Please specify either prefix or regex, but not both",
+                getLocation());
         }
         //copy the properties file
-        Hashtable allProps = new Hashtable();
+        Hashtable<Object, Object> allProps = new Hashtable<>();
 
         /* load properties from file if specified, otherwise
         use Ant's properties */
-        if (inFile == null && propertySets.size() == 0) {
+        if (inFile == null && propertySets.isEmpty()) {
             // add ant properties
             allProps.putAll(getProject().getProperties());
         } else if (inFile != null) {
-            if (inFile.exists() && inFile.isDirectory()) {
+            if (inFile.isDirectory()) {
                 String message = "srcfile is a directory!";
                 if (failonerror) {
                     throw new BuildException(message, getLocation());
-                } else {
-                    log(message, Project.MSG_ERR);
                 }
+                log(message, Project.MSG_ERR);
                 return;
             }
 
@@ -293,9 +293,7 @@
                 return;
             }
 
-            FileInputStream in = null;
-            try {
-                in = new FileInputStream(inFile);
+            try (InputStream in = Files.newInputStream(inFile.toPath())) {
                 Properties props = new Properties();
                 props.load(in);
                 allProps.putAll(props);
@@ -304,75 +302,38 @@
                     "Could not find file " + inFile.getAbsolutePath();
                 if (failonerror) {
                     throw new BuildException(message, fnfe, getLocation());
-                } else {
-                    log(message, Project.MSG_WARN);
                 }
+                log(message, Project.MSG_WARN);
                 return;
             } catch (IOException ioe) {
                 String message =
                     "Could not read file " + inFile.getAbsolutePath();
                 if (failonerror) {
                     throw new BuildException(message, ioe, getLocation());
-                } else {
-                    log(message, Project.MSG_WARN);
                 }
+                log(message, Project.MSG_WARN);
                 return;
-            } finally {
-                FileUtils.close(in);
             }
         }
 
-        Enumeration e = propertySets.elements();
-        while (e.hasMoreElements()) {
-            PropertySet ps = (PropertySet) e.nextElement();
-            allProps.putAll(ps.getProperties());
-        }
+        propertySets.stream().map(PropertySet::getProperties)
+            .forEach(allProps::putAll);
 
-        OutputStream os = null;
-        try {
-            if (destfile == null) {
-                os = new ByteArrayOutputStream();
-                saveProperties(allProps, os);
-                log(os.toString(), Project.MSG_INFO);
-            } else {
-                if (destfile.exists() && destfile.isDirectory()) {
-                    String message = "destfile is a directory!";
-                    if (failonerror) {
-                        throw new BuildException(message, getLocation());
-                    } else {
-                        log(message, Project.MSG_ERR);
-                    }
-                    return;
-                }
-
-                if (destfile.exists() && !destfile.canWrite()) {
-                    String message =
-                        "Can not write to the specified destfile!";
-                    if (failonerror) {
-                        throw new BuildException(message, getLocation());
-                    } else {
-                        log(message, Project.MSG_ERR);
-                    }
-                    return;
-                }
-                os = new FileOutputStream(this.destfile);
+        try (OutputStream os = createOutputStream()) {
+            if (os != null) {
                 saveProperties(allProps, os);
             }
         } catch (IOException ioe) {
             if (failonerror) {
                 throw new BuildException(ioe, getLocation());
-            } else {
-                log(ioe.getMessage(), Project.MSG_INFO);
             }
-        } finally {
-            FileUtils.close(os);
+            log(ioe.getMessage(), Project.MSG_INFO);
         }
     }
 
-
     /**
      * Send the key/value pairs in the hashtable to the given output stream.
-     * Only those properties matching the <tt>prefix</tt> constraint will be
+     * Only those properties matching the <code>prefix</code> constraint will be
      * sent to the output stream.
      * The output stream will be closed when this method returns.
      *
@@ -381,37 +342,37 @@
      * @throws IOException      on output errors
      * @throws BuildException   on other errors
      */
-    protected void saveProperties(Hashtable allProps, OutputStream os)
+    protected void saveProperties(Hashtable<Object, Object> allProps, OutputStream os)
         throws IOException, BuildException {
-        final List keyList = new ArrayList(allProps.keySet());
-        Collections.sort(keyList);
+        final List<Object> keyList = new ArrayList<>(allProps.keySet());
+
         Properties props = new Properties() {
             private static final long serialVersionUID = 5090936442309201654L;
-            public Enumeration keys() {
-                return CollectionUtils.asEnumeration(keyList.iterator());
+
+            @Override
+            public Enumeration<Object> keys() {
+                return keyList.stream()
+                    .sorted(Comparator.comparing(Object::toString))
+                    .collect(Collectors.collectingAndThen(Collectors.toList(),
+                        Collections::enumeration));
             }
-            public Set entrySet() {
-                Set result = super.entrySet();
+
+            @Override
+            public Set<Map.Entry<Object, Object>> entrySet() {
+                Set<Map.Entry<Object, Object>> result = super.entrySet();
                 if (JavaEnvUtils.isKaffe()) {
-                    TreeSet t = new TreeSet(new Comparator() {
-                        public int compare(Object o1, Object o2) {
-                            String key1 = (String) ((Map.Entry) o1).getKey();
-                            String key2 = (String) ((Map.Entry) o2).getKey();
-                            return key1.compareTo(key2);
-                        }
-                    });
+                    Set<Map.Entry<Object, Object>> t =
+                        new TreeSet<>(Comparator.comparing(
+                            ((Function<Map.Entry<Object, Object>, Object>) Map.Entry::getKey)
+                                .andThen(Object::toString)));
                     t.addAll(result);
-                    result = t;
+                    return t;
                 }
                 return result;
             }
         };
-        final int size = keyList.size();
-        for (int i = 0; i < size; i++) {
-            String name = keyList.get(i).toString();
-            String value = allProps.get(name).toString();
-            props.setProperty(name, value);
-        }
+        allProps.forEach((k, v) -> props.put(String.valueOf(k), String.valueOf(v)));
+
         if ("text".equals(format)) {
             jdkSaveProperties(props, os, "Ant properties");
         } else if ("xml".equals(format)) {
@@ -422,7 +383,7 @@
     /**
      * a tuple for the sort list.
      */
-    private static final class Tuple implements Comparable {
+    private static final class Tuple implements Comparable<Tuple> {
         private String key;
         private String value;
 
@@ -439,9 +400,9 @@
          * @throws ClassCastException if the specified object's type prevents it
          *                            from being compared to this Object.
          */
-        public int compareTo(Object o) {
-            Tuple that = (Tuple) o;
-            return key.compareTo(that.key);
+        @Override
+        public int compareTo(Tuple o) {
+            return Comparator.<String> naturalOrder().compare(key, o.key);
         }
 
         @Override
@@ -453,26 +414,21 @@
                 return false;
             }
             Tuple that = (Tuple) o;
-            return (key == null ? that.key == null : key.equals(that.key))
-                && (value == null ? that.value == null : value.equals(that.value));
+            return Objects.equals(key, that.key)
+                && Objects.equals(value, that.value);
         }
 
         @Override
         public int hashCode() {
-            return key != null ? key.hashCode() : 0;
+            return Objects.hash(key);
         }
     }
 
-    private List sortProperties(Properties props) {
+    private List<Tuple> sortProperties(Properties props) {
         // sort the list. Makes SCM and manual diffs easier.
-        List sorted = new ArrayList(props.size());
-        Enumeration e = props.propertyNames();
-        while (e.hasMoreElements()) {
-            String name = (String) e.nextElement();
-            sorted.add(new Tuple(name, props.getProperty(name)));
-        }
-        Collections.sort(sorted);
-        return sorted;
+        return props.stringPropertyNames().stream()
+            .map(k -> new Tuple(k, props.getProperty(k))).sorted()
+            .collect(Collectors.toList());
     }
 
     /**
@@ -487,36 +443,29 @@
         Document doc = getDocumentBuilder().newDocument();
         Element rootElement = doc.createElement(PROPERTIES);
 
-        List sorted = sortProperties(props);
-
+        List<Tuple> sorted = sortProperties(props);
 
         // output properties
-        Iterator iten = sorted.iterator();
-        while (iten.hasNext()) {
-            Tuple tuple = (Tuple) iten.next();
+        for (Tuple tuple : sorted) {
             Element propElement = doc.createElement(PROPERTY);
             propElement.setAttribute(ATTR_NAME, tuple.key);
             propElement.setAttribute(ATTR_VALUE, tuple.value);
             rootElement.appendChild(propElement);
         }
 
-        Writer wri = null;
-        try {
-            wri = new OutputStreamWriter(os, "UTF8");
+        try (Writer wri = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
             wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-            (new DOMElementWriter()).write(rootElement, wri, 0, "\t");
+            new DOMElementWriter().write(rootElement, wri, 0, "\t");
             wri.flush();
         } catch (IOException ioe) {
             throw new BuildException("Unable to write XML file", ioe);
-        } finally {
-            FileUtils.close(wri);
         }
     }
 
     /**
      * JDK 1.2 allows for the safer method
-     * <tt>Properties.store(OutputStream, String)</tt>, which throws an
-     * <tt>IOException</tt> on an output error.
+     * <code>Properties.store(OutputStream, String)</code>, which throws an
+     * <code>IOException</code> on an output error.
      *
      * @param props the properties to record
      * @param os record the properties to this output stream
@@ -527,7 +476,6 @@
                                      String header) throws IOException {
        try {
            props.store(os, header);
-
        } catch (IOException ioe) {
            throw new BuildException(ioe, getLocation());
        } finally {
@@ -541,6 +489,29 @@
        }
     }
 
+    private OutputStream createOutputStream() throws IOException {
+        if (destfile == null) {
+            return new LogOutputStream(this);
+        }
+        if (destfile.exists() && destfile.isDirectory()) {
+            String message = "destfile is a directory!";
+            if (failonerror) {
+                throw new BuildException(message, getLocation());
+            }
+            log(message, Project.MSG_ERR);
+            return null;
+        }
+        if (destfile.exists() && !destfile.canWrite()) {
+            String message =
+                "Can not write to the specified destfile!";
+            if (failonerror) {
+                throw new BuildException(message, getLocation());
+            }
+            log(message, Project.MSG_ERR);
+            return null;
+        }
+        return Files.newOutputStream(this.destfile.toPath());
+    }
 
     /**
      * Uses the DocumentBuilderFactory to get a DocumentBuilder instance.
@@ -555,4 +526,3 @@
         }
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java
index e9753df..c4e3159 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Javah.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,11 @@
 package org.apache.tools.ant.taskdefs.optional;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
 import java.util.Vector;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -33,7 +34,6 @@
 import org.apache.tools.ant.types.FileSet;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
-import org.apache.tools.ant.util.StringUtils;
 import org.apache.tools.ant.util.facade.FacadeTaskHelper;
 import org.apache.tools.ant.util.facade.ImplementationSpecificArgument;
 
@@ -70,7 +70,7 @@
 
 public class Javah extends Task {
 
-    private Vector classes = new Vector(2);
+    private List<ClassArgument> classes = new Vector<>(2);
     private String cls;
     private File destDir;
     private Path classpath = null;
@@ -80,9 +80,8 @@
     private boolean old     = false;
     private boolean stubs   = false;
     private Path bootclasspath;
-    //private Path extdirs;
     private FacadeTaskHelper facade = null;
-    private Vector files = new Vector();
+    private Vector<FileSet> files = new Vector<>();
     private JavahAdapter nestedAdapter = null;
 
     /**
@@ -106,7 +105,7 @@
      */
     public ClassArgument createClass() {
         ClassArgument ga = new ClassArgument();
-        classes.addElement(ga);
+        classes.add(ga);
         return ga;
     }
 
@@ -117,10 +116,6 @@
     public class ClassArgument {
         private String name;
 
-        /** Constructor for ClassArgument. */
-        public ClassArgument() {
-        }
-
         /**
          * Set the name attribute.
          * @param name the name attribute.
@@ -152,33 +147,20 @@
      * @since Ant 1.6.3
      */
     public String[] getClasses() {
-        ArrayList al = new ArrayList();
+        Stream<String> stream = Stream.concat(
+            files.stream()
+                .map(fs -> fs.getDirectoryScanner(getProject()).getIncludedFiles())
+                .flatMap(Stream::of)
+                .map(s -> s.replace('\\', '.').replace('/', '.')
+                    .replaceFirst("\\.class$", "")),
+            classes.stream().map(ClassArgument::getName));
+
         if (cls != null) {
-            StringTokenizer tok = new StringTokenizer(cls, ",", false);
-            while (tok.hasMoreTokens()) {
-                al.add(tok.nextToken().trim());
-            }
+            stream = Stream.concat(Stream.of(cls.split(",")).map(String::trim),
+                stream);
         }
 
-        if (files.size() > 0) {
-            for (Enumeration e = files.elements(); e.hasMoreElements();) {
-                FileSet fs = (FileSet) e.nextElement();
-                String[] includedClasses = fs.getDirectoryScanner(
-                    getProject()).getIncludedFiles();
-                for (int i = 0; i < includedClasses.length; i++) {
-                    String className =
-                        includedClasses[i].replace('\\', '.').replace('/', '.')
-                        .substring(0, includedClasses[i].length() - 6);
-                    al.add(className);
-                }
-            }
-        }
-        Enumeration e = classes.elements();
-        while (e.hasMoreElements()) {
-            ClassArgument arg = (ClassArgument) e.nextElement();
-            al.add(arg.getName());
-        }
-        return (String[]) al.toArray(new String[al.size()]);
+        return stream.toArray(String[]::new);
     }
 
     /**
@@ -391,8 +373,7 @@
      * @since Ant 1.6.3
      */
     public ImplementationSpecificArgument createArg() {
-        ImplementationSpecificArgument arg =
-            new ImplementationSpecificArgument();
+        ImplementationSpecificArgument arg = new ImplementationSpecificArgument();
         facade.addImplementationArgument(arg);
         return arg;
     }
@@ -426,8 +407,7 @@
      */
     public void add(JavahAdapter adapter) {
         if (nestedAdapter != null) {
-            throw new BuildException("Can't have more than one javah"
-                                     + " adapter");
+            throw new BuildException("Can't have more than one javah adapter");
         }
         nestedAdapter = adapter;
     }
@@ -437,17 +417,23 @@
      *
      * @throws BuildException is there is a problem in the task execution.
      */
+    @Override
     public void execute() throws BuildException {
         // first off, make sure that we've got a srcdir
+        final Set<Settings> settings = EnumSet.noneOf(Settings.class);
 
-        if ((cls == null) && (classes.size() == 0) && (files.size() == 0)) {
-            throw new BuildException("class attribute must be set!",
-                getLocation());
+        if (cls != null) {
+            settings.add(Settings.cls);
         }
-
-        if ((cls != null) && (classes.size() > 0) && (files.size() > 0)) {
-            throw new BuildException("set class attribute OR class element OR fileset, "
-                + "not 2 or more of them.", getLocation());
+        if (!classes.isEmpty()) {
+            settings.add(Settings.classes);
+        }
+        if (!files.isEmpty()) {
+            settings.add(Settings.files);
+        }
+        if (settings.size() > 1) {
+            throw new BuildException("Exactly one of " + Settings.values()
+                    + " attributes is required", getLocation());
         }
 
         if (destDir != null) {
@@ -456,13 +442,13 @@
                     + "\" does not exist or is not a directory", getLocation());
             }
             if (outputFile != null) {
-                throw new BuildException("destdir and outputFile are mutually "
-                    + "exclusive", getLocation());
+                throw new BuildException("destdir and outputFile are mutually exclusive",
+                        getLocation());
             }
         }
 
         if (classpath == null) {
-            classpath = (new Path(getProject())).concatSystemClasspath("last");
+            classpath = new Path(getProject()).concatSystemClasspath("last");
         } else {
             classpath = classpath.concatSystemClasspath("ignore");
         }
@@ -493,22 +479,20 @@
         log("Compilation " + cmd.describeArguments(),
             Project.MSG_VERBOSE);
 
-        StringBuffer niceClassList = new StringBuffer();
         String[] c = getClasses();
-        for (int i = 0; i < c.length; i++) {
-            cmd.createArgument().setValue(c[i]);
-            niceClassList.append("    ");
-            niceClassList.append(c[i]);
-            niceClassList.append(StringUtils.LINE_SEP);
-        }
-
-        StringBuffer prefix = new StringBuffer("Class");
+        StringBuilder message = new StringBuilder("Class");
         if (c.length > 1) {
-            prefix.append("es");
+            message.append("es");
         }
-        prefix.append(" to be compiled:");
-        prefix.append(StringUtils.LINE_SEP);
+        message.append(String.format(" to be compiled:%n"));
+        for (String element : c) {
+            cmd.createArgument().setValue(element);
+            message.append(String.format("    %s%n", element));
+        }
+        log(message.toString(), Project.MSG_VERBOSE);
+    }
 
-        log(prefix.toString() + niceClassList.toString(), Project.MSG_VERBOSE);
+    private enum Settings {
+        cls, files, classes
     }
 }
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java
index acbee87..ad7b1bf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Native2Ascii.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -198,8 +198,8 @@
      */
     public void add(Native2AsciiAdapter adapter) {
         if (nestedAdapter != null) {
-            throw new BuildException("Can't have more than one native2ascii"
-                                     + " adapter");
+            throw new BuildException(
+                "Can't have more than one native2ascii adapter");
         }
         nestedAdapter = adapter;
     }
@@ -209,6 +209,7 @@
      *
      * @throws BuildException is there is a problem in the task execution.
      */
+    @Override
     public void execute() throws BuildException {
 
         DirectoryScanner scanner = null; // Scanner to find our inputs
@@ -228,11 +229,11 @@
         // to be set, so we don't stomp every file.  One could still
         // include a file with the same extension, but ....
         if (srcDir.equals(destDir) && extension == null && mapper == null) {
-            throw new BuildException("The ext attribute or a mapper must be set if"
-                                     + " src and dest dirs are the same.");
+            throw new BuildException(
+                "The ext attribute or a mapper must be set if src and dest dirs are the same.");
         }
 
-        FileNameMapper m = null;
+        FileNameMapper m;
         if (mapper == null) {
             if (extension == null) {
                 m = new IdentityMapper();
@@ -279,8 +280,7 @@
 
         // Make sure we're not about to clobber something
         if (srcFile.equals(destFile)) {
-            throw new BuildException("file " + srcFile
-                                     + " would overwrite its self");
+            throw new BuildException("file %s would overwrite itself", srcFile);
         }
 
         // Make intermediate directories if needed
@@ -291,8 +291,8 @@
 
             if (!parentFile.exists()
                 && !(parentFile.mkdirs() || parentFile.isDirectory())) {
-                throw new BuildException("cannot create parent directory "
-                                         + parentName);
+                throw new BuildException("cannot create parent directory %s",
+                    parentName);
             }
         }
 
@@ -317,18 +317,21 @@
 
     private class ExtMapper implements FileNameMapper {
 
+        @Override
         public void setFrom(String s) {
         }
+
+        @Override
         public void setTo(String s) {
         }
 
+        @Override
         public String[] mapFileName(String fileName) {
             int lastDot = fileName.lastIndexOf('.');
             if (lastDot >= 0) {
                 return new String[] {fileName.substring(0, lastDot) + extension};
-            } else {
-                return new String[] {fileName + extension};
             }
+            return new String[] {fileName + extension};
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/NetRexxC.java b/src/main/org/apache/tools/ant/taskdefs/optional/NetRexxC.java
index 5d7b8b2..083aeed 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/NetRexxC.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/NetRexxC.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,11 +23,14 @@
 import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
-import java.util.Enumeration;
+import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Properties;
 import java.util.StringTokenizer;
 import java.util.Vector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import netrexx.lang.Rexx;
 
@@ -142,8 +145,8 @@
     static final String MSG_DEPRECATION = "has been deprecated";
 
     // other implementation variables
-    private Vector compileList = new Vector();
-    private Hashtable filecopyList = new Hashtable();
+    private Vector<String> compileList = new Vector<>();
+    private Hashtable<String, String> filecopyList = new Hashtable<>();
 
     /**
      * Set whether literals are treated as binary, rather than NetRexx types.
@@ -155,7 +158,6 @@
         this.binary = binary;
     }
 
-
     /**
      * Set the classpath used for NetRexx compilation.
      * @param classpath the classpath to use.
@@ -164,7 +166,6 @@
         this.classpath = classpath;
     }
 
-
     /**
      * Set whether comments are passed through to the generated java source.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -175,7 +176,6 @@
         this.comments = comments;
     }
 
-
     /**
      * Set whether error messages come out in compact or verbose format.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -186,7 +186,6 @@
         this.compact = compact;
     }
 
-
     /**
      * Set whether the NetRexx compiler should compile the generated java code.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -201,7 +200,6 @@
         }
     }
 
-
     /**
      * Set whether or not compiler messages should be displayed on the 'console'.
      * Note that this task will rely on the default value for filtering compile messages.
@@ -213,7 +211,6 @@
         this.console = console;
     }
 
-
     /**
      * Whether variable cross references are generated.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -224,7 +221,6 @@
         this.crossref = crossref;
     }
 
-
     /**
      * Set whether decimal arithmetic should be used for the netrexx code.
      * Setting this to off will report decimal arithmetic as an error, for
@@ -237,7 +233,6 @@
         this.decimal = decimal;
     }
 
-
     /**
      * Set the destination directory into which the NetRexx source files
      * should be copied and then compiled.
@@ -247,7 +242,6 @@
         destDir = destDirName;
     }
 
-
     /**
      * Whether diagnostic information about the compile is generated
      * @param diag a <code>boolean</code> value.
@@ -256,7 +250,6 @@
         this.diag = diag;
     }
 
-
     /**
      * Sets whether variables must be declared explicitly before use.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -267,7 +260,6 @@
         this.explicit = explicit;
     }
 
-
     /**
      * Whether the generated java code is formatted nicely or left to match
      * NetRexx line numbers for call stack debugging.
@@ -279,7 +271,6 @@
         this.format = format;
     }
 
-
     /**
      * Whether the generated java code is produced.
      * This is not implemented yet.
@@ -289,7 +280,6 @@
         log("The attribute java is currently unused.", Project.MSG_WARN);
     }
 
-
     /**
      * Sets whether the generated java source file should be kept after
      * compilation. The generated files will have an extension of .java.keep,
@@ -303,7 +293,6 @@
         this.keep = keep;
     }
 
-
     /**
      * Whether the compiler text logo is displayed when compiling.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -314,7 +303,6 @@
         this.logo = logo;
     }
 
-
     /**
      * Whether the generated .java file should be replaced when compiling.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -325,7 +313,6 @@
         this.replace = replace;
     }
 
-
     /**
      * Sets whether the compiler messages will be written to NetRexxC.log as
      * well as to the console.
@@ -337,7 +324,6 @@
         this.savelog = savelog;
     }
 
-
     /**
      * Tells the NetRexx compiler to store the class files in the same
      * directory as the source files. The alternative is the working directory.
@@ -349,7 +335,6 @@
         this.sourcedir = sourcedir;
     }
 
-
     /**
      * Set the source dir to find the source Java files.
      * @param srcDirName the source directory.
@@ -358,7 +343,6 @@
         srcDir = srcDirName;
     }
 
-
     /**
      * Tells the NetRexx compiler that method calls always need parentheses,
      * even if no arguments are needed, e.g. <code>aStringVar.getBytes</code>
@@ -371,7 +355,6 @@
         this.strictargs = strictargs;
     }
 
-
     /**
      * Tells the NetRexx compile that assignments must match exactly on type.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -382,7 +365,6 @@
         this.strictassign = strictassign;
     }
 
-
     /**
      * Specifies whether the NetRexx compiler should be case sensitive or not.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -393,7 +375,6 @@
         this.strictcase = strictcase;
     }
 
-
     /**
      * Sets whether classes need to be imported explicitly using an <code>import</code>
      * statement. By default the NetRexx compiler will import certain packages
@@ -406,7 +387,6 @@
         this.strictimport = strictimport;
     }
 
-
     /**
      * Sets whether local properties need to be qualified explicitly using
      * <code>this</code>.
@@ -418,7 +398,6 @@
         this.strictprops = strictprops;
     }
 
-
     /**
      * Whether the compiler should force catching of exceptions by explicitly
      * named types.
@@ -430,7 +409,6 @@
         this.strictsignal = strictsignal;
     }
 
-
     /**
      * Sets whether debug symbols should be generated into the class file.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -441,7 +419,6 @@
         this.symbols = symbols;
     }
 
-
     /**
      * Asks the NetRexx compiler to print compilation times to the console
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -470,12 +447,10 @@
      */
     public void setTrace(String trace) {
         TraceAttr t = new TraceAttr();
-
         t.setValue(trace);
         setTrace(t);
     }
 
-
     /**
      * Tells the NetRexx compiler that the source is in UTF8.
      * Valid true values are "yes", "on" or "true". Anything else sets the flag to false.
@@ -486,7 +461,6 @@
         this.utf8 = utf8;
     }
 
-
     /**
      * Whether lots of warnings and error messages should be generated
      * @param verbose the value to set - verbose&lt;level&gt; or noverbose.
@@ -495,14 +469,12 @@
         this.verbose = verbose.getValue();
     }
 
-
     /**
      * Whether lots of warnings and error messages should be generated
      * @param verbose the value to set - verbose&lt;level&gt; or noverbose.
      */
     public void setVerbose(String verbose) {
         VerboseAttr v = new VerboseAttr();
-
         v.setValue(verbose);
         setVerbose(v);
     }
@@ -517,7 +489,6 @@
         this.suppressMethodArgumentNotUsed = suppressMethodArgumentNotUsed;
     }
 
-
     /**
      * Whether the task should suppress the "Private property is defined but
      * not used" in strictargs-Mode, which can be quite annoying while
@@ -528,7 +499,6 @@
         this.suppressPrivatePropertyNotUsed = suppressPrivatePropertyNotUsed;
     }
 
-
     /**
      * Whether the task should suppress the "Variable is set but not used" in
      * strictargs-Mode. Be careful with this one! The warning is logged as
@@ -539,7 +509,6 @@
         this.suppressVariableNotUsed = suppressVariableNotUsed;
     }
 
-
     /**
      * Whether the task should suppress the "FooException is in SIGNALS list
      * but is not signalled within the method", which is sometimes rather
@@ -550,7 +519,6 @@
         this.suppressExceptionNotSignalled = suppressExceptionNotSignalled;
     }
 
-
     /**
      * Tells whether we should filter out any deprecation-messages
      * of the compiler out.
@@ -560,7 +528,6 @@
         this.suppressDeprecation = suppressDeprecation;
     }
 
-
     /**
      * Tells whether the trailing .keep in nocompile-mode should be removed
      * so that the resulting java source really ends on .java.
@@ -571,12 +538,12 @@
         this.removeKeepExtension = removeKeepExtension;
     }
 
-
     /**
      * init-Method sets defaults from Properties. That way, when ant is called
      * with arguments like -Dant.netrexxc.verbose=verbose5 one can easily take
      * control of all netrexxc-tasks.
      */
+    @Override
     public void init() {
         String p;
 
@@ -681,11 +648,11 @@
         }
     }
 
-
     /**
      * Executes the task - performs the actual compiler call.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
 
         // first off, make sure that we've got a srcdir and destdir
@@ -695,18 +662,15 @@
 
         // scan source and dest dirs to build up both copy lists and
         // compile lists
-        //        scanDir(srcDir, destDir);
         DirectoryScanner ds = getDirectoryScanner(srcDir);
 
-        String[] files = ds.getIncludedFiles();
-
-        scanDir(srcDir, destDir, files);
+        scanDir(srcDir, destDir, ds.getIncludedFiles());
 
         // copy the source and support files
         copyFilesToDestination();
 
         // compile the source files
-        if (compileList.size() > 0) {
+        if (!compileList.isEmpty()) {
             log("Compiling " + compileList.size() + " source file"
                  + (compileList.size() == 1 ? "" : "s")
                  + " to " + destDir);
@@ -717,16 +681,14 @@
         }
     }
 
-
     /**
      * Scans the directory looking for source files to be compiled and support
      * files to be copied.
      */
     private void scanDir(File srcDir, File destDir, String[] files) {
-        for (int i = 0; i < files.length; i++) {
-            File srcFile = new File(srcDir, files[i]);
-            File destFile = new File(destDir, files[i]);
-            String filename = files[i];
+        for (String filename : files) {
+            File srcFile = new File(srcDir, filename);
+            File destFile = new File(destDir, filename);
             // if it's a non source file, copy it if a later date than the
             // dest
             // if it's a source file, see if the destination class file
@@ -749,112 +711,77 @@
                     filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
                     compileList.addElement(destFile.getAbsolutePath());
                 }
-            } else {
-                if (srcFile.lastModified() > destFile.lastModified()) {
-                    filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
-                }
+            } else if (srcFile.lastModified() > destFile.lastModified()) {
+                filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
             }
         }
     }
 
-
     /** Copy eligible files from the srcDir to destDir  */
     private void copyFilesToDestination() {
-        if (filecopyList.size() > 0) {
+        if (!filecopyList.isEmpty()) {
             log("Copying " + filecopyList.size() + " file"
                  + (filecopyList.size() == 1 ? "" : "s")
                  + " to " + destDir.getAbsolutePath());
 
-            Enumeration e = filecopyList.keys();
-
-            while (e.hasMoreElements()) {
-                String fromFile = (String) e.nextElement();
-                String toFile = (String) filecopyList.get(fromFile);
-
+            filecopyList.forEach((fromFile, toFile) -> {
                 try {
                     FileUtils.getFileUtils().copyFile(fromFile, toFile);
                 } catch (IOException ioe) {
-                    String msg = "Failed to copy " + fromFile + " to " + toFile
-                         + " due to " + ioe.getMessage();
-
-                    throw new BuildException(msg, ioe);
+                    throw new BuildException("Failed to copy " + fromFile
+                        + " to " + toFile + " due to " + ioe.getMessage(), ioe);
                 }
-            }
+            });
         }
     }
 
-
     /**
      * Rename .java.keep files (back) to .java. The netrexxc renames all
      * .java files to .java.keep if either -keep or -nocompile option is set.
      */
     private void removeKeepExtensions() {
-        if (compileList.size() > 0) {
+        if (!compileList.isEmpty()) {
             log("Removing .keep extension on " + compileList.size() + " file"
                  + (compileList.size() == 1 ? "" : "s"));
-            Enumeration e = compileList.elements();
-            while (e.hasMoreElements()) {
-                String nrxName = (String) e.nextElement();
-                String baseName = nrxName.substring(0, nrxName.lastIndexOf('.'));
+            compileList.forEach(nrxName -> {
+                String baseName =
+                    nrxName.substring(0, nrxName.lastIndexOf('.'));
                 File fromFile = new File(baseName + ".java.keep");
                 File toFile = new File(baseName + ".java");
                 if (fromFile.renameTo(toFile)) {
-                    log("Successfully renamed " + fromFile + " to " + toFile, Project.MSG_VERBOSE);
+                    log("Successfully renamed " + fromFile + " to " + toFile,
+                        Project.MSG_VERBOSE);
                 } else {
                     log("Failed to rename " + fromFile + " to " + toFile);
                 }
-            }
+            });
         }
     }
 
-
     /** Performs a compile using the NetRexx 1.1.x compiler  */
     private void doNetRexxCompile() throws BuildException {
         log("Using NetRexx compiler", Project.MSG_VERBOSE);
 
         String classpath = getCompileClasspath();
-        StringBuffer compileOptions = new StringBuffer();
 
         // create an array of strings for input to the compiler: one array
         // comes from the compile options, the other from the compileList
         String[] compileOptionsArray = getCompileOptionsAsArray();
-        String[] fileListArray = new String[compileList.size()];
-        Enumeration e = compileList.elements();
-        int j = 0;
-
-        while (e.hasMoreElements()) {
-            fileListArray[j] = (String) e.nextElement();
-            j++;
-        }
-        // create a single array of arguments for the compiler
-        String[] compileArgs = new String[compileOptionsArray.length + fileListArray.length];
-
-        for (int i = 0; i < compileOptionsArray.length; i++) {
-            compileArgs[i] = compileOptionsArray[i];
-        }
-        for (int i = 0; i < fileListArray.length; i++) {
-            compileArgs[i + compileOptionsArray.length] = fileListArray[i];
-        }
 
         // print nice output about what we are doing for the log
-        compileOptions.append("Compilation args: ");
-        for (int i = 0; i < compileOptionsArray.length; i++) {
-            compileOptions.append(compileOptionsArray[i]);
-            compileOptions.append(" ");
-        }
-        log(compileOptions.toString(), Project.MSG_VERBOSE);
+        log(Stream.of(compileOptionsArray)
+            .collect(Collectors.joining(" ", "Compilation args: ", "")),
+            Project.MSG_VERBOSE);
 
-        String eol = System.getProperty("line.separator");
-        StringBuffer niceSourceList = new StringBuffer("Files to be compiled:" + eol);
+        log("Files to be compiled:", Project.MSG_VERBOSE);
 
-        final int size = compileList.size();
-        for (int i = 0; i < size; i++) {
-            niceSourceList.append("    ");
-            niceSourceList.append(compileList.elementAt(i).toString());
-            niceSourceList.append(eol);
-        }
+        log(compileList.stream().map(s -> String.format("    %s%n", s))
+                        .collect(Collectors.joining("")), Project.MSG_VERBOSE);
 
-        log(niceSourceList.toString(), Project.MSG_VERBOSE);
+        // create a single array of arguments for the compiler
+        String[] compileArgs =
+                Stream.concat(Stream.of(compileOptionsArray), compileList.stream())
+                .toArray(String[]::new);
 
         // need to set java.class.path property and restore it later
         // since the NetRexx compiler has no option for the classpath
@@ -865,7 +792,7 @@
 
         try {
             StringWriter out = new StringWriter();
-            PrintWriter w = null;
+            PrintWriter w;
             int rc =
                 COM.ibm.netrexx.process.NetRexxC.main(new Rexx(compileArgs),
                                                       w = new PrintWriter(out)); //NOSONAR
@@ -873,17 +800,18 @@
             String ddir = destDir.getAbsolutePath();
             boolean doReplace = !(sdir.equals(ddir));
             int dlen = ddir.length();
-            String l;
             BufferedReader in = new BufferedReader(new StringReader(out.toString()));
 
             log("replacing destdir '" + ddir + "' through sourcedir '"
                 + sdir + "'", Project.MSG_VERBOSE);
+
+            String l;
             while ((l = in.readLine()) != null) {
                 int idx;
 
                 while (doReplace && ((idx = l.indexOf(ddir)) != -1)) {
                     // path is mentioned in the message
-                    l = (new StringBuffer(l)).replace(idx, idx + dlen, sdir).toString();
+                    l = new StringBuilder(l).replace(idx, idx + dlen, sdir).toString();
                 }
                 // verbose level logging for suppressed messages
                 if (suppressMethodArgumentNotUsed
@@ -912,28 +840,26 @@
                 }
             }
             if (rc > 1) {
-                throw new BuildException("Compile failed, messages should "
-                    + "have been provided.");
+                throw new BuildException(
+                    "Compile failed, messages should have been provided.");
             }
             if (w.checkError()) {
                 throw new IOException("Encountered an error");
             }
         } catch (IOException ioe) {
-            throw new BuildException("Unexpected IOException while "
-                + "playing with Strings", ioe);
+            throw new BuildException(
+                "Unexpected IOException while playing with Strings", ioe);
         } finally {
             // need to reset java.class.path property
             // since the NetRexx compiler has no option for the classpath
             currentProperties = System.getProperties();
             currentProperties.put("java.class.path", currentClassPath);
         }
-
     }
 
-
     /** Builds the compilation classpath.  */
     private String getCompileClasspath() {
-        StringBuffer classpath = new StringBuffer();
+        StringBuilder classpath = new StringBuilder();
 
         // add dest dir to classpath so that previously compiled and
         // untouched classes are on classpath
@@ -945,49 +871,43 @@
         }
 
         // add the system classpath
-        // addExistingToClasspath(classpath,System.getProperty("java.class.path"));
         return classpath.toString();
     }
 
-
     /** This  */
     private String[] getCompileOptionsAsArray() {
-        Vector options = new Vector();
+        List<String> options = new ArrayList<>();
 
-        options.addElement(binary ? "-binary" : "-nobinary");
-        options.addElement(comments ? "-comments" : "-nocomments");
-        options.addElement(compile ? "-compile" : "-nocompile");
-        options.addElement(compact ? "-compact" : "-nocompact");
-        options.addElement(console ? "-console" : "-noconsole");
-        options.addElement(crossref ? "-crossref" : "-nocrossref");
-        options.addElement(decimal ? "-decimal" : "-nodecimal");
-        options.addElement(diag ? "-diag" : "-nodiag");
-        options.addElement(explicit ? "-explicit" : "-noexplicit");
-        options.addElement(format ? "-format" : "-noformat");
-        options.addElement(keep ? "-keep" : "-nokeep");
-        options.addElement(logo ? "-logo" : "-nologo");
-        options.addElement(replace ? "-replace" : "-noreplace");
-        options.addElement(savelog ? "-savelog" : "-nosavelog");
-        options.addElement(sourcedir ? "-sourcedir" : "-nosourcedir");
-        options.addElement(strictargs ? "-strictargs" : "-nostrictargs");
-        options.addElement(strictassign ? "-strictassign" : "-nostrictassign");
-        options.addElement(strictcase ? "-strictcase" : "-nostrictcase");
-        options.addElement(strictimport ? "-strictimport" : "-nostrictimport");
-        options.addElement(strictprops ? "-strictprops" : "-nostrictprops");
-        options.addElement(strictsignal ? "-strictsignal" : "-nostrictsignal");
-        options.addElement(symbols ? "-symbols" : "-nosymbols");
-        options.addElement(time ? "-time" : "-notime");
-        options.addElement("-" + trace);
-        options.addElement(utf8 ? "-utf8" : "-noutf8");
-        options.addElement("-" + verbose);
+        options.add(binary ? "-binary" : "-nobinary");
+        options.add(comments ? "-comments" : "-nocomments");
+        options.add(compile ? "-compile" : "-nocompile");
+        options.add(compact ? "-compact" : "-nocompact");
+        options.add(console ? "-console" : "-noconsole");
+        options.add(crossref ? "-crossref" : "-nocrossref");
+        options.add(decimal ? "-decimal" : "-nodecimal");
+        options.add(diag ? "-diag" : "-nodiag");
+        options.add(explicit ? "-explicit" : "-noexplicit");
+        options.add(format ? "-format" : "-noformat");
+        options.add(keep ? "-keep" : "-nokeep");
+        options.add(logo ? "-logo" : "-nologo");
+        options.add(replace ? "-replace" : "-noreplace");
+        options.add(savelog ? "-savelog" : "-nosavelog");
+        options.add(sourcedir ? "-sourcedir" : "-nosourcedir");
+        options.add(strictargs ? "-strictargs" : "-nostrictargs");
+        options.add(strictassign ? "-strictassign" : "-nostrictassign");
+        options.add(strictcase ? "-strictcase" : "-nostrictcase");
+        options.add(strictimport ? "-strictimport" : "-nostrictimport");
+        options.add(strictprops ? "-strictprops" : "-nostrictprops");
+        options.add(strictsignal ? "-strictsignal" : "-nostrictsignal");
+        options.add(symbols ? "-symbols" : "-nosymbols");
+        options.add(time ? "-time" : "-notime");
+        options.add("-" + trace);
+        options.add(utf8 ? "-utf8" : "-noutf8");
+        options.add("-" + verbose);
 
-        String[] results = new String[options.size()];
-
-        options.copyInto(results);
-        return results;
+        return options.toArray(new String[0]);
     }
 
-
     /**
      * Takes a classpath-like string, and adds each element of this string to
      * a new classpath, if the components exist. Components that don't exist,
@@ -998,9 +918,9 @@
      * @param target - target classpath
      * @param source - source classpath to get file objects.
      */
-    private void addExistingToClasspath(StringBuffer target, String source) {
+    private void addExistingToClasspath(StringBuilder target, String source) {
         StringTokenizer tok = new StringTokenizer(source,
-            System.getProperty("path.separator"), false);
+            File.pathSeparator, false);
 
         while (tok.hasMoreTokens()) {
             File f = getProject().resolveFile(tok.nextToken());
@@ -1013,15 +933,14 @@
                     + f.getAbsolutePath(), Project.MSG_VERBOSE);
             }
         }
-
     }
 
-
     /**
      * Enumerated class corresponding to the trace attribute.
      */
     public static class TraceAttr extends EnumeratedAttribute {
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
             return new String[] {"trace", "trace1", "trace2", "notrace"};
         }
@@ -1032,9 +951,10 @@
      */
     public static class VerboseAttr extends EnumeratedAttribute {
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
             return new String[] {"verbose", "verbose0", "verbose1", "verbose2",
-                    "verbose3", "verbose4", "verbose5", "noverbose"};
+                "verbose3", "verbose4", "verbose5", "noverbose"};
         }
     }
 }
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 71f2841..7c24c94 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,17 +21,16 @@
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 import java.text.DateFormat;
 import java.text.DecimalFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
@@ -147,7 +146,7 @@
     private File                propertyfile;
     private boolean             useJDKProperties;
 
-    private Vector entries = new Vector();
+    private Vector<Entry> entries = new Vector<>();
 
     /* ========================================================================
      *
@@ -182,10 +181,7 @@
     }
 
     private void executeOperation() throws BuildException {
-        for (Enumeration e = entries.elements(); e.hasMoreElements();) {
-            Entry entry = (Entry) e.nextElement();
-            entry.executeOn(properties);
-        }
+        entries.forEach(e -> e.executeOn(properties));
     }
 
     private void readFile() throws BuildException {
@@ -200,27 +196,16 @@
             if (propertyfile.exists()) {
                 log("Updating property file: "
                     + propertyfile.getAbsolutePath());
-                FileInputStream fis = null;
-                try {
-                    fis = new FileInputStream(propertyfile);
-                    BufferedInputStream bis = new BufferedInputStream(fis);
+                try (InputStream fis = Files.newInputStream(propertyfile.toPath());
+                     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 (OutputStream out =
+                     Files.newOutputStream(propertyfile.toPath())) {
                     out.flush();
-                } finally {
-                    if (out != null) {
-                        out.close();
-                    }
                 }
             }
         } catch (IOException ioe) {
@@ -269,13 +254,8 @@
             throw new BuildException(x, getLocation());
         }
         try {
-            OutputStream os = new FileOutputStream(propertyfile); //NOSONAR
-            try {
-                try {
-                    os.write(baos.toByteArray());
-                } finally {
-                    os.close();
-                }
+            try (OutputStream os = Files.newOutputStream(propertyfile.toPath())) {
+                os.write(baos.toByteArray());
             } catch (IOException x) { // possibly corrupt
                 FileUtils.getFileUtils().tryHardToDelete(propertyfile);
                 throw x;
@@ -286,7 +266,7 @@
     }
 
     private boolean checkParam(File param) {
-        return !(param == null);
+        return param != null;
     }
 
     /**
@@ -404,7 +384,7 @@
                 } else if (type == Type.STRING_TYPE) {
                     executeString(oldValue);
                 } else {
-                    throw new BuildException("Unknown operation type: " + type);
+                    throw new BuildException("Unknown operation type: %d", type);
                 }
             } catch (NullPointerException npe) {
                 // Default to string type
@@ -466,7 +446,6 @@
             newValue = fmt.format(currentValue.getTime());
         }
 
-
         /**
          * Handle operations for type <code>int</code>.
          *
@@ -478,7 +457,6 @@
             int currentValue = DEFAULT_INT_VALUE;
             int newV  = DEFAULT_INT_VALUE;
 
-
             DecimalFormat fmt = (pattern != null) ? new DecimalFormat(pattern)
                 : new DecimalFormat();
             try {
@@ -488,9 +466,7 @@
                 } else {
                     currentValue = 0;
                 }
-            } catch (NumberFormatException nfe) {
-                // swallow
-            } catch (ParseException pe)  {
+            } catch (NumberFormatException | ParseException nfe) {
                 // swallow
             }
 
@@ -501,9 +477,7 @@
                 if (value != null) {
                     try {
                         operationValue = fmt.parse(value).intValue();
-                    } catch (NumberFormatException nfe) {
-                        // swallow
-                    } catch (ParseException pe)  {
+                    } catch (NumberFormatException | ParseException nfe) {
                         // swallow
                     }
                 }
@@ -554,15 +528,17 @@
                                          + "properties (key:" + key + ")");
             }
             if (value == null && defaultValue == null  && operation != Operation.DELETE_OPER) {
-                throw new BuildException("\"value\" and/or \"default\" "
-                                         + "attribute must be specified (key:" + key + ")");
+                throw new BuildException(
+                    "\"value\" and/or \"default\" attribute must be specified (key: %s)",
+                    key);
             }
             if (key == null) {
                 throw new BuildException("key is mandatory");
             }
             if (type == Type.STRING_TYPE && pattern != null) {
-                throw new BuildException("pattern is not supported for string "
-                                         + "properties (key:" + key + ")");
+                throw new BuildException(
+                    "pattern is not supported for string properties (key: %s)",
+                    key);
             }
         }
 
@@ -601,7 +577,7 @@
                     ret = defaultValue;
                 }
             } else {
-                ret = (oldValue == null) ? defaultValue : oldValue;
+                ret = oldValue == null ? defaultValue : oldValue;
             }
 
             return ret;
@@ -636,9 +612,11 @@
             public static int toOperation(String oper) {
                 if ("+".equals(oper)) {
                     return INCREMENT_OPER;
-                } else if ("-".equals(oper)) {
+                }
+                if ("-".equals(oper)) {
                     return DECREMENT_OPER;
-                } else if ("del".equals(oper)) {
+                }
+                if ("del".equals(oper)) {
                     return DELETE_OPER;
                 }
                 return EQUALS_OPER;
@@ -672,7 +650,8 @@
             public static int toType(String type) {
                 if ("int".equals(type)) {
                     return INTEGER_TYPE;
-                } else if ("date".equals(type)) {
+                }
+                if ("date".equals(type)) {
                     return DATE_TYPE;
                 }
                 return STRING_TYPE;
@@ -699,19 +678,19 @@
         private static final String[] UNITS = {MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH,
                 YEAR};
 
-        private Map calendarFields = new HashMap();
+        private Map<String, Integer> calendarFields = new HashMap<>();
 
         /** no arg constructor */
         public Unit() {
             calendarFields.put(MILLISECOND,
-                               new Integer(Calendar.MILLISECOND));
-            calendarFields.put(SECOND, new Integer(Calendar.SECOND));
-            calendarFields.put(MINUTE, new Integer(Calendar.MINUTE));
-            calendarFields.put(HOUR, new Integer(Calendar.HOUR_OF_DAY));
-            calendarFields.put(DAY, new Integer(Calendar.DATE));
-            calendarFields.put(WEEK, new Integer(Calendar.WEEK_OF_YEAR));
-            calendarFields.put(MONTH, new Integer(Calendar.MONTH));
-            calendarFields.put(YEAR, new Integer(Calendar.YEAR));
+                    Calendar.MILLISECOND);
+            calendarFields.put(SECOND, Calendar.SECOND);
+            calendarFields.put(MINUTE, Calendar.MINUTE);
+            calendarFields.put(HOUR, Calendar.HOUR_OF_DAY);
+            calendarFields.put(DAY, Calendar.DATE);
+            calendarFields.put(WEEK, Calendar.WEEK_OF_YEAR);
+            calendarFields.put(MONTH, Calendar.MONTH);
+            calendarFields.put(YEAR, Calendar.YEAR);
         }
 
         /**
@@ -719,9 +698,7 @@
          * @return the calendar value.
          */
         public int getCalendarField() {
-            String key = getValue().toLowerCase();
-            Integer i = (Integer) calendarFields.get(key);
-            return i.intValue();
+            return calendarFields.get(getValue().toLowerCase());
         }
 
         /** {@inheritDoc}. */
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java b/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java
index c4acadb..34a4f38 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/RenameExtensions.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,6 +43,7 @@
  * @deprecated since 1.5.x.
  *             Use &lt;move&gt; instead
  */
+@Deprecated
 public class RenameExtensions extends MatchingTask {
 
     private String fromExtension = "";
@@ -121,7 +122,7 @@
         log("          from=\"*" + fromExtension + "\"", Project.MSG_INFO);
         log("          to=\"*" + toExtension + "\" />", Project.MSG_INFO);
         log("</move>", Project.MSG_INFO);
-        log("using the same patterns on <fileset> as you\'ve used here",
+        log("using the same patterns on <fileset> as you've used here",
             Project.MSG_INFO);
 
         Move move = new Move();
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 5ec9cd2..5b7e3e6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,8 +20,6 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -29,6 +27,8 @@
 import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -144,7 +144,6 @@
         this.subs = null;
     }
 
-
     /**
      * file for which the regular expression should be replaced;
      * required unless a nested fileset is supplied.
@@ -155,7 +154,6 @@
         this.file = file;
     }
 
-
     /**
      * the regular expression pattern to match in the file(s);
      * required if no nested &lt;regexp&gt; is used
@@ -171,7 +169,6 @@
         regex.setPattern(match);
     }
 
-
     /**
      * The substitution pattern to place in the file(s) in place
      * of the regular expression.
@@ -182,8 +179,8 @@
 
     public void setReplace(String replace) {
         if (subs != null) {
-            throw new BuildException("Only one substitution expression is "
-                                     + "allowed");
+            throw new BuildException(
+                "Only one substitution expression is allowed");
         }
 
         subs = new Substitution();
@@ -210,7 +207,6 @@
         this.flags = flags;
     }
 
-
     /**
      * Process the file(s) one line at a time, executing the replacement
      * on one line at a time.  This is useful if you
@@ -224,12 +220,7 @@
      */
     @Deprecated
     public void setByLine(String byline) {
-        Boolean res = Boolean.valueOf(byline);
-
-        if (res == null) {
-            res = Boolean.FALSE;
-        }
-        this.byline = res.booleanValue();
+        this.byline = Boolean.parseBoolean(byline);
     }
 
     /**
@@ -305,8 +296,8 @@
      */
     public Substitution createSubstitution() {
         if (subs != null) {
-            throw new BuildException("Only one substitution expression is "
-                                     + "allowed");
+            throw new BuildException(
+                "Only one substitution expression is allowed");
         }
 
         subs = new Substitution();
@@ -350,7 +341,6 @@
         return res;
     }
 
-
     /**
      * Perform the replacement on a file
      *
@@ -364,24 +354,25 @@
         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);
+            final Charset charset = encoding == null ? Charset.defaultCharset() : Charset.forName(encoding);
+            try (InputStream is = Files.newInputStream(f.toPath());
+                 OutputStream os = Files.newOutputStream(temp.toPath())) {
+                Reader r = null;
+                Writer w = null;
                 try {
-                    Writer w = encoding != null ? new OutputStreamWriter(os, encoding) : new OutputStreamWriter(os);
-
+                    r = new InputStreamReader(is, charset);
+                    w = new OutputStreamWriter(os, charset);
                     log("Replacing pattern '" + regex.getPattern(getProject())
                         + "' with '" + subs.getExpression(getProject())
                         + "' in '" + f.getPath() + "'" + (byline ? " by line" : "")
-                        + (flags.length() > 0 ? " with flags: '" + flags + "'" : "")
+                        + (flags.isEmpty() ? "" : " with flags: '" + flags + "'")
                         + ".", Project.MSG_VERBOSE);
 
                     if (byline) {
                         r = new BufferedReader(r);
                         w = new BufferedWriter(w);
 
-                        StringBuffer linebuf = new StringBuffer();
+                        StringBuilder linebuf = new StringBuilder();
                         int c;
                         boolean hasCR = false;
 
@@ -395,7 +386,7 @@
                                                                w, options);
                                     w.write('\r');
 
-                                    linebuf = new StringBuffer();
+                                    linebuf = new StringBuilder();
                                     // hasCR is still true (for the second one)
                                 } else {
                                     // first CR in this line
@@ -411,9 +402,9 @@
                                 }
                                 w.write('\n');
 
-                                linebuf = new StringBuffer();
+                                linebuf = new StringBuilder();
                             } else { // any other char
-                                if ((hasCR) || (c < 0)) {
+                                if (hasCR || c < 0) {
                                     // Mac-style linebreak or EOF (or both)
                                     changes |= replaceAndWrite(linebuf.toString(),
                                                                w, options);
@@ -422,7 +413,7 @@
                                         hasCR = false;
                                     }
 
-                                    linebuf = new StringBuffer();
+                                    linebuf = new StringBuilder();
                                 }
 
                                 if (c >= 0) {
@@ -434,15 +425,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);
@@ -467,7 +453,6 @@
         }
     }
 
-
     /**
      * Execute the task
      *
@@ -483,9 +468,8 @@
         }
 
         if (file != null && resources != null) {
-            throw new BuildException("You cannot supply the 'file' attribute "
-                                     + "and resource collections at the same "
-                                     + "time.");
+            throw new BuildException(
+                "You cannot supply the 'file' attribute and resource collections at the same time.");
         }
 
         int options = RegexpUtil.asOptions(flags);
@@ -505,9 +489,7 @@
 
         if (resources != null) {
             for (Resource r : resources) {
-                FileProvider fp =
-                    r.as(FileProvider.class);
-                File f = fp.getFile();
+                File f = r.as(FileProvider.class).getFile();
 
                 if (f.exists()) {
                     try {
@@ -537,5 +519,3 @@
         return !res.equals(s);
     }
 }
-
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java b/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java
index a816f6e..addc4d6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Rpm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,10 @@
 
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.nio.file.Files;
 import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
@@ -110,6 +110,7 @@
      *
      * @throws BuildException is there is a problem in the task execution.
      */
+    @Override
     public void execute() throws BuildException {
 
         Commandline toExecute = new Commandline();
@@ -148,9 +149,9 @@
             }
         } else {
             if (output != null) {
-                FileOutputStream fos = null;
+                OutputStream fos = null;
                 try {
-                    fos = new FileOutputStream(output); //NOSONAR
+                    fos = Files.newOutputStream(output.toPath()); //NOSONAR
                     BufferedOutputStream bos = new BufferedOutputStream(fos);
                     outputstream = new PrintStream(bos);
                 } catch (IOException e) {
@@ -163,9 +164,9 @@
                 outputstream = new LogOutputStream(this, Project.MSG_DEBUG);
             }
             if (error != null) {
-                FileOutputStream fos = null;
+                OutputStream fos = null;
                 try {
-                    fos = new FileOutputStream(error);
+                    fos = Files.newOutputStream(error.toPath());
                     BufferedOutputStream bos = new BufferedOutputStream(fos);
                     errorstream = new PrintStream(bos);
                 } catch (IOException e) {
@@ -204,7 +205,7 @@
      * The directory which will have the expected
      * subdirectories, SPECS, SOURCES, BUILD, SRPMS; optional.
      * If this isn't specified,
-     * the <tt>baseDir</tt> value is used
+     * the <code>baseDir</code> value is used
      *
      * @param td the directory containing the normal RPM directories.
      */
@@ -226,7 +227,7 @@
      * @param sf the spec file name to use.
      */
     public void setSpecFile(String sf) {
-        if ((sf == null) || (sf.trim().length() == 0)) {
+        if (sf == null || sf.trim().isEmpty()) {
             throw new BuildException("You must specify a spec file", getLocation());
         }
         this.specFile = sf;
@@ -252,7 +253,7 @@
     /**
      * Flag (optional, default=false)
      * to remove the sources after the build.
-     * See the <tt>--rmsource</tt>  option of rpmbuild.
+     * See the <code>--rmsource</code>  option of rpmbuild.
      * @param rs a <code>boolean</code> value.
      */
     public void setRemoveSource(boolean rs) {
@@ -319,20 +320,20 @@
      * @since 1.6
      */
     protected String guessRpmBuildCommand() {
-        Map/*<String, String>*/ env = Execute.getEnvironmentVariables();
-        String path = (String) env.get(PATH1);
+        Map<String, String> env = Execute.getEnvironmentVariables();
+        String path = env.get(PATH1);
         if (path == null) {
-            path = (String) env.get(PATH2);
+            path = env.get(PATH2);
             if (path == null) {
-                path = (String) env.get(PATH3);
+                path = env.get(PATH3);
             }
         }
 
         if (path != null) {
             Path p = new Path(getProject(), path);
             String[] pElements = p.list();
-            for (int i = 0; i < pElements.length; i++) {
-                File f = new File(pElements[i],
+            for (String pElement : pElements) {
+                File f = new File(pElement,
                                   "rpmbuild"
                                   + (Os.isFamily("dos") ? ".exe" : ""));
                 if (f.canRead()) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/SchemaValidate.java b/src/main/org/apache/tools/ant/taskdefs/optional/SchemaValidate.java
index 30801de..354dcab 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/SchemaValidate.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/SchemaValidate.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,8 @@
 import java.io.File;
 import java.net.MalformedURLException;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
@@ -40,7 +41,7 @@
  * This task validates XML schema documents. It requires an XML parser
  * that handles the relevant SAX, Xerces or JAXP options.
  *
- * To resolve remote referencies, Ant may need its proxy set up, using the
+ * To resolve remote references, Ant may need its proxy set up, using the
  * setproxy task.
  *
  * Hands off most of the work to its parent, {@link XMLValidateTask}
@@ -48,23 +49,6 @@
  */
 
 public class SchemaValidate extends XMLValidateTask {
-
-    /** map of all declared schemas; we catch and complain about redefinitions */
-    private HashMap schemaLocations = new HashMap();
-
-    /** full checking of a schema */
-    private boolean fullChecking = true;
-
-    /**
-     * flag to disable DTD support. Best left enabled.
-     */
-    private boolean disableDTD = false;
-
-    /**
-     * default URL for nonamespace schemas
-     */
-    private SchemaLocation anonymousSchema;
-
     // Error strings
     /** SAX1 not supported */
     public static final String ERROR_SAX_1 = "SAX1 parsers are not supported";
@@ -88,12 +72,29 @@
     public static final String ERROR_DUPLICATE_SCHEMA
         = "Duplicate declaration of schema ";
 
+    /** map of all declared schemas; we catch and complain about redefinitions */
+    private Map<String, SchemaLocation> schemaLocations = new HashMap<>();
+
+    /** full checking of a schema */
+    private boolean fullChecking = true;
+
+    /**
+     * flag to disable DTD support. Best left enabled.
+     */
+    private boolean disableDTD = false;
+
+    /**
+     * default URL for nonamespace schemas
+     */
+    private SchemaLocation anonymousSchema;
+
     /**
      * Called by the project to let the task initialize properly. The default
      * implementation is a no-op.
      *
      * @throws BuildException if something goes wrong with the build
      */
+    @Override
     public void init() throws BuildException {
         super.init();
         //validating
@@ -129,7 +130,7 @@
 
     /**
      * Set schema attributes in a JAXP 1.2 engine.
-     * @see <A href="http://java.sun.com/xml/jaxp/change-requests-11.html">
+     * @see <A href="https://java.sun.com/xml/jaxp/change-requests-11.html">
      * JAXP 1.2 Approved CHANGES</A>
      * @return true on success, false on failure
      */
@@ -155,7 +156,7 @@
     public void addConfiguredSchema(SchemaLocation location) {
         log("adding schema " + location, Project.MSG_DEBUG);
         location.validateNamespace();
-        SchemaLocation old = (SchemaLocation) schemaLocations.get(location.getNamespace());
+        SchemaLocation old = schemaLocations.get(location.getNamespace());
         if (old != null && !old.equals(location)) {
             throw new BuildException(ERROR_DUPLICATE_SCHEMA + location);
         }
@@ -213,6 +214,7 @@
      *
      * @throws BuildException if something went wrong
      */
+    @Override
     protected void initValidator() {
         super.initValidator();
         //validate the parser type
@@ -221,7 +223,6 @@
         }
 
         //enable schema
-        //setFeature(XmlConstants.FEATURE_VALIDATION, false);
         setFeature(XmlConstants.FEATURE_NAMESPACES, true);
         if (!enableXercesSchemaValidation() && !enableJAXP12SchemaValidation()) {
             //could not use xerces or jaxp calls
@@ -244,6 +245,7 @@
      * create our own factory with our own options.
      * @return a default XML parser
      */
+    @Override
     protected XMLReader createDefaultReader() {
         SAXParserFactory factory = SAXParserFactory.newInstance();
         factory.setValidating(true);
@@ -252,9 +254,7 @@
         try {
             SAXParser saxParser = factory.newSAXParser();
             reader = saxParser.getXMLReader();
-        } catch (ParserConfigurationException e) {
-            throw new BuildException(ERROR_PARSER_CREATION_FAILURE, e);
-        } catch (SAXException e) {
+        } catch (ParserConfigurationException | SAXException e) {
             throw new BuildException(ERROR_PARSER_CREATION_FAILURE, e);
         }
         return reader;
@@ -265,23 +265,14 @@
      * property.
      */
     protected void addSchemaLocations() {
-        Iterator it = schemaLocations.values().iterator();
-        StringBuffer buffer = new StringBuffer();
-        int count = 0;
-        while (it.hasNext()) {
-            if (count > 0) {
-                buffer.append(' ');
-            }
-            SchemaLocation schemaLocation = (SchemaLocation) it.next();
-            String tuple = schemaLocation.getURIandLocation();
-            buffer.append(tuple);
-            log("Adding schema " + tuple, Project.MSG_VERBOSE);
-            count++;
-        }
-        if (count > 0) {
-            setProperty(XmlConstants.PROPERTY_SCHEMA_LOCATION, buffer.toString());
-        }
+        if (!schemaLocations.isEmpty()) {
+            String joinedValue = schemaLocations.values().stream()
+                .map(SchemaLocation::getURIandLocation)
+                .peek(tuple -> log("Adding schema " + tuple, Project.MSG_VERBOSE))
+                .collect(Collectors.joining(" "));
 
+            setProperty(XmlConstants.PROPERTY_SCHEMA_LOCATION, joinedValue);
+        }
     }
 
     /**
@@ -289,11 +280,8 @@
      * @return the schema URL
      */
     protected String getNoNamespaceSchemaURL() {
-        if (anonymousSchema == null) {
-            return null;
-        } else {
-            return anonymousSchema.getSchemaLocationURL();
-        }
+        return anonymousSchema == null ? null
+            : anonymousSchema.getSchemaLocationURL();
     }
 
     /**
@@ -317,6 +305,7 @@
      *
      * @param fileProcessed number of files processed.
      */
+    @Override
     protected void onSuccessfulValidation(int fileProcessed) {
         log(fileProcessed + MESSAGE_FILES_VALIDATED, Project.MSG_VERBOSE);
     }
@@ -350,10 +339,6 @@
         public static final String ERROR_NO_LOCATION
             = "No file or URL supplied for the schema ";
 
-        /** No arg constructor */
-        public SchemaLocation() {
-        }
-
         /**
          * Get the namespace.
          * @return the namespace.
@@ -442,11 +427,7 @@
          */
         public String getURIandLocation() throws BuildException {
             validateNamespace();
-            StringBuffer buffer = new StringBuffer();
-            buffer.append(namespace);
-            buffer.append(' ');
-            buffer.append(getSchemaLocationURL());
-            return new String(buffer);
+            return namespace + ' ' + getSchemaLocationURL();
         }
 
         /**
@@ -465,7 +446,7 @@
          * @return true if it is not null or empty
          */
         private boolean isSet(String property) {
-            return property != null && property.length() != 0;
+            return property != null && !property.isEmpty();
         }
 
         /**
@@ -474,6 +455,7 @@
          * @return true iff the objects are considered equal in value
          */
 
+        @Override
         public boolean equals(Object o) {
             if (this == o) {
                 return true;
@@ -484,30 +466,22 @@
 
             final SchemaLocation schemaLocation = (SchemaLocation) o;
 
-            if (file != null ? !file.equals(schemaLocation.file) : schemaLocation.file != null) {
-                return false;
-            }
-            if (namespace != null ? !namespace.equals(schemaLocation.namespace)
-                    : schemaLocation.namespace != null) {
-                return false;
-            }
-            if (url != null ? !url.equals(schemaLocation.url) : schemaLocation.url != null) {
-                return false;
-            }
-
-            return true;
+            return (file == null ? schemaLocation.file == null : file.equals(schemaLocation.file))
+                    && (namespace == null ? schemaLocation.namespace == null : namespace.equals(schemaLocation.namespace))
+                    && (url == null ? schemaLocation.url == null : url.equals(schemaLocation.url));
         }
 
         /**
          * Generate a hashcode depending on the namespace, url and file name.
          * @return the hashcode.
          */
+        @Override
         public int hashCode() {
             int result;
             // CheckStyle:MagicNumber OFF
-            result = (namespace != null ? namespace.hashCode() : 0);
-            result = 29 * result + (file != null ? file.hashCode() : 0);
-            result = 29 * result + (url != null ? url.hashCode() : 0);
+            result = (namespace == null ? 0 : namespace.hashCode());
+            result = 29 * result + (file == null ? 0 : file.hashCode());
+            result = 29 * result + (url == null ? 0 : url.hashCode());
             // CheckStyle:MagicNumber OFF
             return result;
         }
@@ -517,13 +491,11 @@
          * and the like
          * @return a string representation of the object.
          */
+        @Override
         public String toString() {
-            StringBuffer buffer = new StringBuffer();
-            buffer.append(namespace != null ? namespace : "(anonymous)");
-            buffer.append(' ');
-            buffer.append(url != null ? (url + " ") : "");
-            buffer.append(file != null ? file.getAbsolutePath() : "");
-            return buffer.toString();
+            return (namespace == null ? "(anonymous)" : namespace)
+                    + (url == null ? "" : " " + url)
+                    + (file == null ? "" : " " + file.getAbsolutePath());
         }
-    } //SchemaLocation
+    }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Script.java b/src/main/org/apache/tools/ant/taskdefs/optional/Script.java
index a29347f..cb322f0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Script.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Script.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,6 +24,7 @@
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.util.ScriptManager;
 import org.apache.tools.ant.util.ScriptRunnerHelper;
 
 /**
@@ -58,11 +59,20 @@
      *
      * @param manager the scripting manager.
      */
+    @Deprecated
     public void setManager(String manager) {
         helper.setManager(manager);
     }
 
     /**
+     * Set the script manager.
+     * @param manager
+     */
+    public void setManager(ScriptManager manager) {
+        helper.setManager(manager);
+    }
+
+    /**
      * Defines the language (required).
      *
      * @param language the scripting language name for the script.
@@ -130,4 +140,15 @@
     public void setSetBeans(boolean setBeans) {
         helper.setSetBeans(setBeans);
     }
+
+    /**
+     * Set the encoding of the script from an external file; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public void setEncoding(String encoding) {
+        helper.setEncoding(encoding);
+    }
+
 }
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 e527131..1be941c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,15 +21,13 @@
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
@@ -65,6 +63,7 @@
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JAXPUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
+import org.apache.tools.ant.util.StreamUtils;
 import org.xml.sax.EntityResolver;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -122,16 +121,16 @@
     private URIResolver uriResolver;
 
     /** transformer output properties */
-    private final Vector<String[]> outputProperties = new Vector<String[]>();
+    private final Vector<String[]> outputProperties = new Vector<>();
 
     /** stylesheet parameters */
-    private final Hashtable<String, Object> params = new Hashtable<String, Object>();
+    private final Hashtable<String, Object> params = new Hashtable<>();
 
     /** factory attributes */
-    private final List<Object[]> attributes = new ArrayList<Object[]>();
+    private final List<Object[]> attributes = new ArrayList<>();
 
     /** factory features */
-    private final Map<String, Boolean> features = new HashMap<String, Boolean>();
+    private final Map<String, Boolean> features = new HashMap<>();
 
     /** whether to suppress warnings */
     private boolean suppressWarnings = false;
@@ -188,27 +187,18 @@
             createTransformer();
         }
 
-        InputStream fis = null;
-        OutputStream fos = null;
-        try {
-            fis = new BufferedInputStream(new FileInputStream(infile));
-            fos = new BufferedOutputStream(new FileOutputStream(outfile));
+        // autoclose all handles, otherwise the garbage collector will close them...
+        // and Windows may complain about not being able to delete files.
+        try (InputStream fis = new BufferedInputStream(Files.newInputStream(infile.toPath()));
+             OutputStream fos = new BufferedOutputStream(Files.newOutputStream(outfile.toPath()))) {
             final StreamResult res = new StreamResult(fos);
             // not sure what could be the need of this...
             res.setSystemId(JAXPUtils.getSystemId(outfile));
-            final Source src = getSource(fis, infile);
-
             // set parameters on each transformation, maybe something has changed
             //(e.g. value of file name parameter)
             setTransformationParameters();
 
-            transformer.transform(src, res);
-        } finally {
-            // make sure to close all handles, otherwise the garbage
-            // collector will close them...whenever possible and
-            // Windows may complain about not being able to delete files.
-            FileUtils.close(fis);
-            FileUtils.close(fos);
+            transformer.transform(getSource(fis, infile), res);
         }
     }
 
@@ -301,17 +291,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();
-            }
         }
     }
 
@@ -334,7 +318,7 @@
         if (uriResolver != null) {
             transformer.setURIResolver(uriResolver);
         }
-        for (String[] pair : outputProperties) {
+        for (final String[] pair : outputProperties) {
             transformer.setOutputProperty(pair[0], pair[1]);
         }
 
@@ -342,13 +326,13 @@
             if ("org.apache.xalan.transformer.TransformerImpl" //NOSONAR
                 .equals(transformer.getClass().getName())) {
                 try {
-                    final Class traceSupport =
+                    final Class<?> traceSupport =
                         Class.forName("org.apache.tools.ant.taskdefs.optional."
                                       + "Xalan2TraceSupport", true,
                                       Thread.currentThread()
                                       .getContextClassLoader());
                     final XSLTTraceSupport ts =
-                        (XSLTTraceSupport) traceSupport.newInstance();
+                        (XSLTTraceSupport) traceSupport.getDeclaredConstructor().newInstance();
                     ts.configureTrace(transformer, traceConfiguration);
                 } catch (final Exception e) {
                     final String msg = "Failed to enable tracing because of " + e;
@@ -374,9 +358,7 @@
      * Sets the parameters for the transformer.
      */
     private void setTransformationParameters() {
-        for (Map.Entry<String, Object> entry : params.entrySet()) {
-            transformer.setParameter(entry.getKey(), entry.getValue());
-        }
+        params.forEach((key, value) -> transformer.setParameter(key, value));
     }
 
     /**
@@ -396,7 +378,7 @@
             tfactory = TransformerFactory.newInstance();
         } else {
             try {
-                Class clazz = null;
+                Class<?> clazz = null;
                 try {
                     clazz =
                         Class.forName(factoryName, true,
@@ -418,7 +400,7 @@
                 if (clazz == null) {
                     clazz = Class.forName(factoryName);
                 }
-                tfactory = (TransformerFactory) clazz.newInstance();
+                tfactory = (TransformerFactory) clazz.getDeclaredConstructor().newInstance();
             } catch (final Exception e) {
                 throw new BuildException(e);
             }
@@ -429,7 +411,6 @@
         tfactory.setErrorListener(this);
 
         // specific attributes for the transformer
-        final int size = attributes.size();
         for (final Object[] pair : attributes) {
             tfactory.setAttribute((String) pair[0], pair[1]);
         }
@@ -569,7 +550,7 @@
             return;
         }
 
-        final StringBuffer msg = new StringBuffer();
+        final StringBuilder msg = new StringBuilder();
         final SourceLocator locator = e.getLocator();
         if (locator != null) {
             final String systemid = locator.getSystemId();
@@ -628,16 +609,11 @@
         final XSLTProcess.Factory factory = xsltTask.getFactory();
         if (factory != null) {
             setFactory(factory.getName());
-
             // configure factory attributes
-            for (final XSLTProcess.Factory.Attribute attr
-                    : Collections.list(factory.getAttributes())) {
-                setAttribute(attr.getName(), attr.getValue());
-            }
-            for (final XSLTProcess.Factory.Feature feature
-                     : factory.getFeatures()) {
-                setFeature(feature.getName(), feature.getValue());
-            }
+            StreamUtils.enumerationAsStream(factory.getAttributes())
+                    .forEach(attr -> setAttribute(attr.getName(), attr.getValue()));
+            factory.getFeatures()
+                    .forEach(feature -> setFeature(feature.getName(), feature.getValue()));
         }
 
         final XMLCatalog xmlCatalog = xsltTask.getXMLCatalog();
@@ -647,12 +623,9 @@
             setURIResolver(xmlCatalog);
         }
 
-
         // configure output properties
-        for (final XSLTProcess.OutputProperty prop
-                : Collections.list(xsltTask.getOutputProperties())) {
-            setOutputProperty(prop.getName(), prop.getValue());
-        }
+        StreamUtils.enumerationAsStream(xsltTask.getOutputProperties())
+                .forEach(prop -> setOutputProperty(prop.getName(), prop.getValue()));
 
         suppressWarnings = xsltTask.getSuppressWarnings();
 
@@ -661,8 +634,7 @@
 
     private void applyReflectionHackForExtensionMethods() {
         // Jigsaw doesn't allow reflection to work, so we can stop trying
-        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_7)
-            && !JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
+        if (!JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
             try { // #51668, #52382
                 final Field _isNotSecureProcessing = tfactory.getClass().getDeclaredField("_isNotSecureProcessing");
                 _isNotSecureProcessing.setAccessible(true);
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 f47ec57..0358bdc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,9 @@
 package org.apache.tools.ant.taskdefs.optional;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Files;
 import java.util.Vector;
 
 import org.apache.tools.ant.AntClassLoader;
@@ -74,7 +75,7 @@
     /** file to be validated */
     protected File file = null;
     /** sets of file to be validated */
-    protected Vector<FileSet> filesets = new Vector<FileSet>();
+    protected Vector<FileSet> filesets = new Vector<>();
     protected Path classpath;
 
     /**
@@ -90,12 +91,12 @@
     // CheckStyle:VisibilityModifier ON
 
     /** The vector to store all attributes (features) to be set on the parser. **/
-    private Vector<Attribute> attributeList = new Vector<Attribute>();
+    private Vector<Attribute> attributeList = new Vector<>();
 
     /**
      * List of properties.
      */
-    private final Vector<Property> propertyList = new Vector<Property>();
+    private final Vector<Property> propertyList = new Vector<>();
 
     private XMLCatalog xmlCatalog = new XMLCatalog();
     /** Message for successful validation */
@@ -288,7 +289,7 @@
     public void execute() throws BuildException {
         try {
             int fileProcessed = 0;
-            if (file == null && (filesets.size() == 0)) {
+            if (file == null && filesets.isEmpty()) {
                 throw new BuildException(
                     "Specify at least one source - " + "a file or a fileset.");
             }
@@ -307,12 +308,12 @@
                 }
             }
 
-            for (FileSet fs : filesets) {
+            for (final FileSet fs : filesets) {
                 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
                 for (String fileName : ds.getIncludedFiles()) {
                     File srcFile = new File(fs.getDir(getProject()), fileName);
                     doValidate(srcFile);
-                  fileProcessed++;
+                    fileProcessed++;
                 }
             }
             onSuccessfulValidation(fileProcessed);
@@ -348,12 +349,12 @@
                 setFeature(XmlConstants.FEATURE_VALIDATION, true);
             }
             // set the feature from the attribute list
-            for (Attribute feature : attributeList) {
+            for (final Attribute feature : attributeList) {
                 setFeature(feature.getName(), feature.getValue());
 
             }
             // Sets properties
-            for (Property prop : propertyList) {
+            for (final Property prop : propertyList) {
                 setProperty(prop.getName(), prop.getValue());
             }
         }
@@ -381,7 +382,7 @@
             reader = createDefaultReaderOrParser();
         } else {
 
-            Class readerClass = null;
+            Class<?> readerClass = null;
             try {
                 // load the parser class
                 if (classpath != null) {
@@ -392,12 +393,9 @@
                     readerClass = Class.forName(readerClassName);
                 }
 
-                reader = readerClass.newInstance();
-            } catch (ClassNotFoundException e) {
-                throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
-            } catch (InstantiationException e) {
-                throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
-            } catch (IllegalAccessException e) {
+                reader = readerClass.getDeclaredConstructor().newInstance();
+            } catch (ClassNotFoundException | IllegalAccessException | InstantiationException
+                    | NoSuchMethodException | InvocationTargetException e) {
                 throw new BuildException(INIT_FAILED_MSG + readerClassName, e);
             }
         }
@@ -541,7 +539,7 @@
         try {
             log("Validating " + afile.getName() + "... ", Project.MSG_VERBOSE);
             errorHandler.init(afile);
-            InputSource is = new InputSource(new FileInputStream(afile));
+            InputSource is = new InputSource(Files.newInputStream(afile.toPath()));
             String uri = FILE_UTILS.toURI(afile.getAbsolutePath());
             is.setSystemId(uri);
             xmlReader.parse(is);
@@ -645,7 +643,7 @@
                 }
                 int line = e.getLineNumber();
                 int col = e.getColumnNumber();
-                return  name
+                return name
                     + (line == -1
                        ? ""
                        : (":" + line + (col == -1 ? "" : (":" + col))))
@@ -661,11 +659,10 @@
      * @since ant1.6
      */
     public static class Attribute {
-        /** The name of the attribute to set.
+        /**
+         * The name of the attribute to set.
          *
-         * Valid attributes <a href=
-         * "http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
-         * >include.</a>
+         * Valid attributes <a href="http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description">include</a>
          */
         private String attributeName = null;
 
@@ -708,7 +705,7 @@
 
     /**
      * A Parser property.
-     * See <a href="http://xml.apache.org/xerces-j/properties.html">
+     * See <a href="https://xml.apache.org/xerces-j/properties.html">
      * XML parser properties</a> for usable properties
      * @since ant 1.6.2
      */
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/XSLTTraceSupport.java b/src/main/org/apache/tools/ant/taskdefs/optional/XSLTTraceSupport.java
index 8b684d8..41386bb 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/XSLTTraceSupport.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/XSLTTraceSupport.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport.java b/src/main/org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport.java
index e5da018..cb064d4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheck.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheck.java
index f6a94b5..8b2b3f3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheck.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheck.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,12 +29,20 @@
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.types.FileSet;
 
-
 /**
  * Class common to all check commands (checkout, checkin,checkin default task);
  * @ant.task ignore="true"
  */
 public class CCMCheck extends Continuus {
+    /**
+     * -comment flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "/comment";
+
+    /**
+     *  -task flag -- associate checkout task with task
+     */
+    public static final String FLAG_TASK = "/task";
 
     private File file = null;
     private String comment = null;
@@ -42,15 +50,10 @@
 
     // CheckStyle:VisibilityModifier OFF - bc
 
-    protected Vector filesets = new Vector();
+    protected Vector<FileSet> filesets = new Vector<>();
 
     // CheckStyle:VisibilityModifier ON
 
-    /** Constructor for CCMCheck. */
-    public CCMCheck() {
-        super();
-    }
-
     /**
      * Get the value of file.
      * @return value of file.
@@ -84,7 +87,6 @@
         this.comment = v;
     }
 
-
     /**
      * Get the value of task.
      * @return value of task.
@@ -102,7 +104,6 @@
         this.task = v;
     }
 
-
     /**
      * Adds a set of files to copy.
      * @param set the set of files
@@ -120,9 +121,10 @@
      * </p>
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
 
-        if (file == null && filesets.size() == 0) {
+        if (file == null && filesets.isEmpty()) {
             throw new BuildException(
                 "Specify at least one source - a file or a fileset.");
         }
@@ -131,7 +133,7 @@
             throw new BuildException("CCMCheck cannot be generated for directories");
         }
 
-        if (file != null  && filesets.size() > 0) {
+        if (file != null && !filesets.isEmpty()) {
             throw new BuildException("Choose between file and fileset !");
         }
 
@@ -140,14 +142,11 @@
             return;
         }
 
-        int sizeofFileSet = filesets.size();
-        for (int i = 0; i < sizeofFileSet; i++) {
-            FileSet fs = (FileSet) filesets.elementAt(i);
+        for (FileSet fs : filesets) {
+            final File basedir = fs.getDir(getProject());
             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
-            String[] srcFiles = ds.getIncludedFiles();
-            for (int j = 0; j < srcFiles.length; j++) {
-                File src = new File(fs.getDir(getProject()), srcFiles[j]);
-                setFile(src);
+            for (String srcFile : ds.getIncludedFiles()) {
+                setFile(new File(basedir, srcFile));
                 doit();
             }
         }
@@ -170,12 +169,11 @@
 
         int result = run(commandLine);
         if (Execute.isFailure(result)) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -195,14 +193,4 @@
         }
     }
 
-    /**
-     * -comment flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "/comment";
-
-    /**
-     *  -task flag -- associate checkout task with task
-     */
-    public static final String FLAG_TASK = "/task";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckin.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckin.java
index ff7472c..e4dc2c2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckin.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckin.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,4 +36,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckinDefault.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckinDefault.java
index 2fe2a2a..729abe1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckinDefault.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckinDefault.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,14 +25,13 @@
  */
 public class CCMCheckinDefault extends CCMCheck {
 
+    /** The default task */
+    public static final String DEFAULT_TASK = "default";
+
     /** Constructor for CCMCheckinDefault. */
     public CCMCheckinDefault() {
         super();
         setCcmAction(COMMAND_CHECKIN);
         setTask(DEFAULT_TASK);
     }
-
-    /** The default task */
-    public static final String DEFAULT_TASK = "default";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckout.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckout.java
index 44bbc6b..39d6045 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckout.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCheckout.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,4 +32,3 @@
         setCcmAction(COMMAND_CHECKOUT);
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCreateTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCreateTask.java
index 7777718..4c6fb14 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCreateTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMCreateTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,6 +38,35 @@
  * @ant.task name="ccmcreatetask" category="scm"
  */
 public class CCMCreateTask extends Continuus implements ExecuteStreamHandler {
+    /**
+     * /comment -- comments associated to the task
+     */
+    public static final String FLAG_COMMENT = "/synopsis";
+
+    /**
+     *  /platform flag -- target platform
+     */
+    public static final String FLAG_PLATFORM = "/plat";
+
+    /**
+     * /resolver flag
+     */
+    public static final String FLAG_RESOLVER = "/resolver";
+
+    /**
+     * /release flag
+     */
+    public static final String FLAG_RELEASE = "/release";
+
+    /**
+     * /release flag
+     */
+    public static final String FLAG_SUBSYSTEM = "/subsystem";
+
+    /**
+     *  -task flag -- associate checkout task with task
+     */
+    public static final String FLAG_TASK = "/task";
 
     private String comment = null;
     private String platform = null;
@@ -63,9 +92,9 @@
      * </p>
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
-        int result = 0;
 
         // build the command line from what we got the format
         // as specified in the CCM.EXE help
@@ -74,10 +103,9 @@
 
         checkOptions(commandLine);
 
-        result = run(commandLine, this);
-        if (Execute.isFailure(result)) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+        if (Execute.isFailure(run(commandLine, this))) {
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
 
         //create task ok, set this task as the default one
@@ -88,15 +116,12 @@
 
         log(commandLine.describeCommand(), Project.MSG_DEBUG);
 
-        result = run(commandLine2);
-        if (result != 0) {
-            String msg = "Failed executing: " + commandLine2.toString();
-            throw new BuildException(msg, getLocation());
+        if (run(commandLine2) != 0) {
+            throw new BuildException("Failed executing: " + commandLine2,
+                getLocation());
         }
-
     }
 
-
     /**
      * Check the command line options.
      */
@@ -127,7 +152,6 @@
         }
     }
 
-
     /**
      * Get the value of comment.
      * @return value of comment.
@@ -145,7 +169,6 @@
         this.comment = v;
     }
 
-
     /**
      * Get the value of platform.
      * @return value of platform.
@@ -163,7 +186,6 @@
         this.platform = v;
     }
 
-
     /**
      * Get the value of resolver.
      * @return value of resolver.
@@ -181,7 +203,6 @@
         this.resolver = v;
     }
 
-
     /**
      * Get the value of release.
      * @return value of release.
@@ -216,7 +237,6 @@
         this.subSystem = v;
     }
 
-
     /**
      * Get the value of task.
      * @return value of task.
@@ -235,71 +255,45 @@
         this.task = v;
     }
 
-    /**
-     * /comment -- comments associated to the task
-     */
-    public static final String FLAG_COMMENT = "/synopsis";
-
-    /**
-     *  /platform flag -- target platform
-     */
-    public static final String FLAG_PLATFORM = "/plat";
-
-    /**
-     * /resolver flag
-     */
-    public static final String FLAG_RESOLVER = "/resolver";
-
-    /**
-     * /release flag
-     */
-    public static final String FLAG_RELEASE = "/release";
-
-    /**
-     * /release flag
-     */
-    public static final String FLAG_SUBSYSTEM = "/subsystem";
-
-    /**
-     *  -task flag -- associate checkout task with task
-     */
-    public static final String FLAG_TASK = "/task";
-
-
     // implementation of org.apache.tools.ant.taskdefs.ExecuteStreamHandler interface
 
     /**
      *
      * @throws IOException on error
      */
+    @Override
     public void start() throws IOException {
     }
 
     /**
      *
      */
+    @Override
     public void stop() {
     }
 
     /**
      *
      * @param param1 the output stream
-     * @exception java.io.IOException on error
+     * @exception IOException on error
      */
+    @Override
     public void setProcessInputStream(OutputStream param1) throws IOException {
     }
 
     /**
      *
      * @param is the input stream
-     * @exception java.io.IOException on error
+     * @exception IOException on error
      */
+    @Override
     public void setProcessErrorStream(InputStream is) throws IOException {
-        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
-        String s = reader.readLine();
-        if (s != null) {
-            log("err " + s, Project.MSG_DEBUG);
-        } // end of if ()
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
+            String s = reader.readLine();
+            if (s != null) {
+                log("err " + s, Project.MSG_DEBUG);
+            }
+        }
     }
 
     /**
@@ -307,12 +301,11 @@
      * @param is InputStream
      * @throws IOException on error
      */
+    @Override
     public void setProcessOutputStream(InputStream is) throws IOException {
-
-        String buffer = "";
-        try {
-            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
-            buffer = reader.readLine();
+        try (BufferedReader reader =
+            new BufferedReader(new InputStreamReader(is))) {
+            String buffer = reader.readLine();
             if (buffer != null) {
                 log("buffer:" + buffer, Project.MSG_DEBUG);
                 String taskstring = buffer.substring(buffer.indexOf(' ')).trim();
@@ -323,7 +316,7 @@
         } catch (NullPointerException npe) {
             log("error procession stream, null pointer exception", Project.MSG_ERR);
             log(StringUtils.getStackTrace(npe), Project.MSG_ERR);
-            throw new BuildException(npe.getClass().getName());
+            throw new BuildException(npe);
         } catch (Exception e) {
             log("error procession stream " + e.getMessage(), Project.MSG_ERR);
             throw new BuildException(e.getMessage());
@@ -332,4 +325,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMReconfigure.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMReconfigure.java
index 35a0834..9e6cc13 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMReconfigure.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/CCMReconfigure.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,6 +28,21 @@
  * Task allows to reconfigure a project, recursively or not
  */
 public class CCMReconfigure extends Continuus {
+    /**
+     * /recurse --
+     */
+    public static final String FLAG_RECURSE = "/recurse";
+
+    /**
+     * /recurse --
+     */
+    public static final String FLAG_VERBOSE = "/verbose";
+
+
+    /**
+     *  /project flag -- target project
+     */
+    public static final String FLAG_PROJECT = "/project";
 
     private String ccmProject = null;
     private boolean recurse = false;
@@ -39,7 +54,6 @@
         setCcmAction(COMMAND_RECONFIGURE);
     }
 
-
     /**
      * Executes the task.
      * <p>
@@ -48,9 +62,9 @@
      * </p>
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
-        int result = 0;
 
         // build the command line from what we got the format
         // as specified in the CCM.EXE help
@@ -59,14 +73,13 @@
 
         checkOptions(commandLine);
 
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result)) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -103,7 +116,6 @@
         this.ccmProject = v;
     }
 
-
     /**
      * Get the value of recurse.
      * @return value of recurse.
@@ -121,7 +133,6 @@
         this.recurse = v;
     }
 
-
     /**
      * Get the value of verbose.
      * @return value of verbose.
@@ -138,22 +149,4 @@
         this.verbose = v;
     }
 
-
-    /**
-     * /recurse --
-     */
-    public static final String FLAG_RECURSE = "/recurse";
-
-    /**
-     * /recurse --
-     */
-    public static final String FLAG_VERBOSE = "/verbose";
-
-
-    /**
-     *  /project flag -- target project
-     */
-    public static final String FLAG_PROJECT = "/project";
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/Continuus.java b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/Continuus.java
index 5618dd6..66d835e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ccm/Continuus.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ccm/Continuus.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,8 @@
 
 package org.apache.tools.ant.taskdefs.optional.ccm;
 
+import java.io.IOException;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
@@ -39,80 +41,6 @@
  *
  */
 public abstract class Continuus extends Task {
-
-    private String ccmDir = "";
-    private String ccmAction = "";
-
-    /**
-     * Get the value of ccmAction.
-     * @return value of ccmAction.
-     */
-    public String getCcmAction() {
-        return ccmAction;
-    }
-
-    /**
-     * Set the value of ccmAction.
-     * @param v  Value to assign to ccmAction.
-     * @ant.attribute ignore="true"
-     */
-    public void setCcmAction(String v) {
-        this.ccmAction = v;
-    }
-
-
-    /**
-     * Set the directory where the ccm executable is located.
-     *
-     * @param dir the directory containing the ccm executable
-     */
-    public final void setCcmDir(String dir) {
-        ccmDir = FileUtils.translatePath(dir);
-    }
-
-    /**
-     * Builds and returns the command string to execute ccm
-     * @return String containing path to the executable
-     */
-    protected final String getCcmCommand() {
-        String toReturn = ccmDir;
-        if (!toReturn.equals("") && !toReturn.endsWith("/")) {
-            toReturn += "/";
-        }
-
-        toReturn += CCM_EXE;
-
-        return toReturn;
-    }
-
-
-    /**
-     * Run the command.
-     * @param cmd the command line
-     * @param handler an execute stream handler
-     * @return the exit status of the command
-     */
-    protected int run(Commandline cmd, ExecuteStreamHandler handler) {
-        try {
-            Execute exe = new Execute(handler);
-            exe.setAntRun(getProject());
-            exe.setWorkingDirectory(getProject().getBaseDir());
-            exe.setCommandline(cmd.getCommandline());
-            return exe.execute();
-        } catch (java.io.IOException e) {
-            throw new BuildException(e, getLocation());
-        }
-    }
-
-    /**
-     * Run the command.
-     * @param cmd the command line
-     * @return the exit status of the command
-     */
-    protected int run(Commandline cmd) {
-        return run(cmd, new LogStreamHandler(this, Project.MSG_VERBOSE, Project.MSG_WARN));
-    }
-
     /**
      * Constant for the thing to execute
      */
@@ -140,5 +68,75 @@
      */
     public static final String COMMAND_DEFAULT_TASK = "default_task";
 
+    private String ccmDir = "";
+    private String ccmAction = "";
+
+    /**
+     * Get the value of ccmAction.
+     * @return value of ccmAction.
+     */
+    public String getCcmAction() {
+        return ccmAction;
+    }
+
+    /**
+     * Set the value of ccmAction.
+     * @param v  Value to assign to ccmAction.
+     * @ant.attribute ignore="true"
+     */
+    public void setCcmAction(String v) {
+        this.ccmAction = v;
+    }
+
+    /**
+     * Set the directory where the ccm executable is located.
+     *
+     * @param dir the directory containing the ccm executable
+     */
+    public final void setCcmDir(String dir) {
+        ccmDir = FileUtils.translatePath(dir);
+    }
+
+    /**
+     * Builds and returns the command string to execute ccm
+     * @return String containing path to the executable
+     */
+    protected final String getCcmCommand() {
+        String toReturn = ccmDir;
+        if (!toReturn.isEmpty() && !toReturn.endsWith("/")) {
+            toReturn += "/";
+        }
+
+        toReturn += CCM_EXE;
+
+        return toReturn;
+    }
+
+    /**
+     * Run the command.
+     * @param cmd the command line
+     * @param handler an execute stream handler
+     * @return the exit status of the command
+     */
+    protected int run(Commandline cmd, ExecuteStreamHandler handler) {
+        try {
+            Execute exe = new Execute(handler);
+            exe.setAntRun(getProject());
+            exe.setWorkingDirectory(getProject().getBaseDir());
+            exe.setCommandline(cmd.getCommandline());
+            return exe.execute();
+        } catch (IOException e) {
+            throw new BuildException(e, getLocation());
+        }
+    }
+
+    /**
+     * Run the command.
+     * @param cmd the command line
+     * @return the exit status of the command
+     */
+    protected int run(Commandline cmd) {
+        return run(cmd, new LogStreamHandler(this, Project.MSG_VERBOSE, Project.MSG_WARN));
+    }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckin.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckin.java
index f7c4a5f..a3b5ea4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckin.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckin.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -79,6 +79,41 @@
  *
  */
 public class CCCheckin extends ClearCase {
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+
+    /**
+     * -nwarn flag -- suppresses warning messages
+     */
+    public static final String FLAG_NOWARN = "-nwarn";
+
+    /**
+     * -ptime flag -- preserves the modification time
+     */
+    public static final String FLAG_PRESERVETIME = "-ptime";
+
+    /**
+     * -keep flag -- keeps a copy of the file with a .keep extension
+     */
+    public static final String FLAG_KEEPCOPY = "-keep";
+
+    /**
+     * -identical flag -- allows the file to be checked in even if it is identical to the original
+     */
+    public static final String FLAG_IDENTICAL = "-identical";
+
     private String mComment = null;
     private String mCfile = null;
     private boolean mNwarn = false;
@@ -93,10 +128,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -115,14 +150,12 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine, getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -273,7 +306,6 @@
         return mIdentical;
     }
 
-
     /**
      * Get the 'comment' command
      *
@@ -310,35 +342,5 @@
         }
     }
 
-
-        /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-        /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-        /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-        /**
-     * -nwarn flag -- suppresses warning messages
-     */
-    public static final String FLAG_NOWARN = "-nwarn";
-        /**
-     * -ptime flag -- preserves the modification time
-     */
-    public static final String FLAG_PRESERVETIME = "-ptime";
-        /**
-     * -keep flag -- keeps a copy of the file with a .keep extension
-     */
-    public static final String FLAG_KEEPCOPY = "-keep";
-        /**
-     * -identical flag -- allows the file to be checked in even if it is identical to the original
-     */
-    public static final String FLAG_IDENTICAL = "-identical";
-
 }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckout.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckout.java
index 4489b7b..aee78ab 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckout.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCCheckout.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -95,6 +95,56 @@
  *
  */
 public class CCCheckout extends ClearCase {
+    /**
+     *  -reserved flag -- check out the file as reserved
+     */
+    public static final String FLAG_RESERVED = "-reserved";
+
+    /**
+     *  -reserved flag -- check out the file as unreserved
+     */
+    public static final String FLAG_UNRESERVED = "-unreserved";
+
+    /**
+     * -out flag -- create a writable file under a different filename
+     */
+    public static final String FLAG_OUT = "-out";
+
+    /**
+     * -ndata flag -- checks out the file but does not create an editable file containing its data
+     */
+    public static final String FLAG_NODATA = "-ndata";
+
+    /**
+     * -branch flag -- checks out the file on a specified branch
+     */
+    public static final String FLAG_BRANCH = "-branch";
+
+    /**
+     * -version flag -- allows checkout of a version that is not main latest
+     */
+    public static final String FLAG_VERSION = "-version";
+
+    /**
+     * -nwarn flag -- suppresses warning messages
+     */
+    public static final String FLAG_NOWARN = "-nwarn";
+
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+
     private boolean mReserved = true;
     private String mOut = null;
     private boolean mNdata = false;
@@ -112,10 +162,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -143,10 +193,10 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
@@ -155,7 +205,6 @@
      */
     private boolean lsCheckout() {
         Commandline cmdl = new Commandline();
-        String result;
 
         // build the command line from what we got the format is
         // cleartool lsco [options...] [viewpath ...]
@@ -168,12 +217,11 @@
         // viewpath
         cmdl.createArgument().setValue(getViewPath());
 
-        result = runS(cmdl, getFailOnErr());
+        String result = runS(cmdl, getFailOnErr());
 
-        // System.out.println( "lsCheckout: " + result );
-
-        return (result != null && result.length() > 0) ? true : false;
+        return result != null && !result.isEmpty();
     }
+
     /**
      * Check the command line options.
      */
@@ -190,23 +238,17 @@
         if (getOut() != null) {
             // -out
             getOutCommand(cmd);
-        } else {
-            if (getNoData()) {
-                // -ndata
-                cmd.createArgument().setValue(FLAG_NODATA);
-            }
-
+        } else if (getNoData()) {
+            // -ndata
+            cmd.createArgument().setValue(FLAG_NODATA);
         }
 
         if (getBranch() != null) {
             // -branch
             getBranchCommand(cmd);
-        } else {
-            if (getVersion()) {
-                // -version
-                cmd.createArgument().setValue(FLAG_VERSION);
-            }
-
+        } else if (getVersion()) {
+            // -version
+            cmd.createArgument().setValue(FLAG_VERSION);
         }
 
         if (getNoWarn()) {
@@ -217,20 +259,15 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         // viewpath
         cmd.createArgument().setValue(getViewPath());
-
-        // Print out info about the notco option
-        // System.out.println( "Notco: " + (getNotco() ? "yes" : "no") );
     }
 
     /**
@@ -271,7 +308,6 @@
         return mNotco;
     }
 
-
     /**
      * Creates a writable file under a different filename.
      *
@@ -435,7 +471,6 @@
         }
     }
 
-
     /**
      * Get the 'comment' command
      *
@@ -472,46 +507,5 @@
         }
     }
 
-        /**
-     *  -reserved flag -- check out the file as reserved
-     */
-    public static final String FLAG_RESERVED = "-reserved";
-        /**
-     *  -reserved flag -- check out the file as unreserved
-     */
-    public static final String FLAG_UNRESERVED = "-unreserved";
-        /**
-     * -out flag -- create a writable file under a different filename
-     */
-    public static final String FLAG_OUT = "-out";
-        /**
-     * -ndata flag -- checks out the file but does not create an editable file containing its data
-     */
-    public static final String FLAG_NODATA = "-ndata";
-        /**
-     * -branch flag -- checks out the file on a specified branch
-     */
-    public static final String FLAG_BRANCH = "-branch";
-        /**
-     * -version flag -- allows checkout of a version that is not main latest
-     */
-    public static final String FLAG_VERSION = "-version";
-        /**
-     * -nwarn flag -- suppresses warning messages
-     */
-    public static final String FLAG_NOWARN = "-nwarn";
-        /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-        /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-        /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-
 }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCLock.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCLock.java
index ba7def7..7968cc3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCLock.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCLock.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,19 +18,19 @@
 
 package org.apache.tools.ant.taskdefs.optional.clearcase;
 
+import java.util.Optional;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Execute;
 import org.apache.tools.ant.types.Commandline;
 
 
-/**
+/*
  * TODO:
  * comment field doesn't include all options yet
  */
 
-
-
 /**
  * Performs a ClearCase Lock command.
  *
@@ -86,6 +86,31 @@
  *
  */
 public class CCLock extends ClearCase {
+    /**
+     *  -replace flag -- replace existing lock on object(s)
+     */
+    public static final String FLAG_REPLACE = "-replace";
+
+    /**
+     * -nusers flag -- list of users to exclude from lock
+     */
+    public static final String FLAG_NUSERS = "-nusers";
+
+    /**
+     * -obsolete flag -- mark locked object as obsolete
+     */
+    public static final String FLAG_OBSOLETE = "-obsolete";
+
+    /**
+     * -comment flag -- method to use for commenting events
+     */
+    public static final String FLAG_COMMENT = "-comment";
+
+    /**
+     * -pname flag -- pathname to lock
+     */
+    public static final String FLAG_PNAME = "-pname";
+
     private boolean mReplace = false;
     private boolean mObsolete = false;
     private String mComment = null;
@@ -100,10 +125,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -126,17 +151,17 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getOpType(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
     /**
      * Check the command line options.
      */
-private void checkOptions(Commandline cmd) {
+    private void checkOptions(Commandline cmd) {
         // ClearCase items
         if (getReplace()) {
             // -replace
@@ -151,15 +176,15 @@
         getCommentCommand(cmd);
 
         if (getObjselect() == null && getPname() == null) {
-            throw new BuildException("Should select either an element "
-            + "(pname) or an object (objselect)");
+            throw new BuildException(
+                "Should select either an element (pname) or an object (objselect)");
         }
         getPnameCommand(cmd);
         // object selector
         if (getObjselect() != null) {
             cmd.createArgument().setValue(getObjselect());
         }
-}
+    }
 
     /**
      * If true, replace an existing lock.
@@ -290,15 +315,14 @@
     private void getNusersCommand(Commandline cmd) {
         if (getNusers() == null) {
             return;
-        } else {
-            /* Had to make two separate commands here because if a space is
-               inserted between the flag and the value, it is treated as a
-               Windows filename with a space and it is enclosed in double
-               quotes ("). This breaks clearcase.
-            */
-            cmd.createArgument().setValue(FLAG_NUSERS);
-            cmd.createArgument().setValue(getNusers());
         }
+        /* Had to make two separate commands here because if a space is
+           inserted between the flag and the value, it is treated as a
+           Windows filename with a space and it is enclosed in double
+           quotes ("). This breaks clearcase.
+        */
+        cmd.createArgument().setValue(FLAG_NUSERS);
+        cmd.createArgument().setValue(getNusers());
     }
 
     /**
@@ -310,15 +334,14 @@
     private void getCommentCommand(Commandline cmd) {
         if (getComment() == null) {
             return;
-        } else {
-            /* Had to make two separate commands here because if a space is
-               inserted between the flag and the value, it is treated as a
-               Windows filename with a space and it is enclosed in double
-               quotes ("). This breaks clearcase.
-            */
-            cmd.createArgument().setValue(FLAG_COMMENT);
-            cmd.createArgument().setValue(getComment());
         }
+        /* Had to make two separate commands here because if a space is
+           inserted between the flag and the value, it is treated as a
+           Windows filename with a space and it is enclosed in double
+           quotes ("). This breaks clearcase.
+        */
+        cmd.createArgument().setValue(FLAG_COMMENT);
+        cmd.createArgument().setValue(getComment());
     }
 
     /**
@@ -330,15 +353,14 @@
     private void getPnameCommand(Commandline cmd) {
         if (getPname() == null) {
             return;
-        } else {
-            /* Had to make two separate commands here because if a space is
-               inserted between the flag and the value, it is treated as a
-               Windows filename with a space and it is enclosed in double
-               quotes ("). This breaks clearcase.
-            */
-            cmd.createArgument().setValue(FLAG_PNAME);
-            cmd.createArgument().setValue(getPname());
         }
+        /* Had to make two separate commands here because if a space is
+           inserted between the flag and the value, it is treated as a
+           Windows filename with a space and it is enclosed in double
+           quotes ("). This breaks clearcase.
+        */
+        cmd.createArgument().setValue(FLAG_PNAME);
+        cmd.createArgument().setValue(getPname());
     }
 
     /**
@@ -347,33 +369,7 @@
      * @return String containing the object/pname being worked on
      */
     private String getOpType() {
-
-        if (getPname() != null) {
-            return getPname();
-        } else {
-            return getObjselect();
-        }
+        return Optional.ofNullable(getPname()).orElseGet(this::getObjselect);
     }
 
-    /**
-     *  -replace flag -- replace existing lock on object(s)
-     */
-    public static final String FLAG_REPLACE = "-replace";
-    /**
-     * -nusers flag -- list of users to exclude from lock
-     */
-    public static final String FLAG_NUSERS = "-nusers";
-    /**
-     * -obsolete flag -- mark locked object as obsolete
-     */
-    public static final String FLAG_OBSOLETE = "-obsolete";
-    /**
-     * -comment flag -- method to use for commenting events
-     */
-    public static final String FLAG_COMMENT = "-comment";
-    /**
-     * -pname flag -- pathname to lock
-     */
-    public static final String FLAG_PNAME = "-pname";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkattr.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkattr.java
index 89b55f9..0418b9c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkattr.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkattr.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -84,6 +84,31 @@
  *
  */
 public class CCMkattr extends ClearCase {
+    /**
+     * -replace flag -- replace the existing value of the attribute
+     */
+    public static final String FLAG_REPLACE = "-replace";
+    /**
+     * -recurse flag -- process all subdirectories
+     */
+    public static final String FLAG_RECURSE = "-recurse";
+    /**
+     * -version flag -- attach attribute to specified version
+     */
+    public static final String FLAG_VERSION = "-version";
+    /**
+     * -c flag -- comment to attach to the element
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+
     private boolean mReplace = false;
     private boolean mRecurse = false;
     private String mVersion = null;
@@ -99,10 +124,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Check for required attributes
         if (getTypeName() == null) {
@@ -132,10 +157,10 @@
         // For debugging
         // System.out.println(commandLine.toString());
 
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
@@ -162,13 +187,11 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         if (getTypeName() != null) {
@@ -183,7 +206,6 @@
         cmd.createArgument().setValue(getViewPath());
     }
 
-
     /**
      * Set the replace flag
      *
@@ -310,7 +332,6 @@
         return mTypeValue;
     }
 
-
     /**
      * Get the 'version' command
      *
@@ -398,29 +419,4 @@
         }
     }
 
-    /**
-     * -replace flag -- replace the existing value of the attribute
-     */
-    public static final String FLAG_REPLACE = "-replace";
-    /**
-     * -recurse flag -- process all subdirectories
-     */
-    public static final String FLAG_RECURSE = "-recurse";
-    /**
-     * -version flag -- attach attribute to specified version
-     */
-    public static final String FLAG_VERSION = "-version";
-    /**
-     * -c flag -- comment to attach to the element
-     */
-    public static final String FLAG_COMMENT = "-c";
-    /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-    /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkbl.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkbl.java
index ac0f42b..ea7c8ab 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkbl.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkbl.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -81,6 +81,36 @@
  *
  */
 public class CCMkbl extends ClearCase {
+
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+    /**
+     * -identical flag -- allows the file to be checked in even if it is identical to the original
+     */
+    public static final String FLAG_IDENTICAL = "-identical";
+    /**
+     * -incremental flag -- baseline to be created is incremental
+     */
+    public static final String FLAG_INCREMENTAL = "-incremental";
+    /**
+     * -full flag -- baseline to be created is full
+     */
+    public static final String FLAG_FULL = "-full";
+    /**
+     * -nlabel -- baseline to be created without a label
+     */
+    public static final String FLAG_NLABEL = "-nlabel";
+
     private String mComment = null;
     private String mCfile = null;
     private String mBaselineRootName = null;
@@ -89,7 +119,6 @@
     private boolean mFull = false;
     private boolean mNlabel = false;
 
-
     /**
      * Executes the task.
      * <p>
@@ -97,10 +126,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -119,14 +148,13 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getBaselineRootName(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -134,13 +162,11 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         if (getIdentical()) {
@@ -163,10 +189,8 @@
 
        // baseline_root_name
         cmd.createArgument().setValue(getBaselineRootName());
-
     }
 
-
     /**
      * Set comment string
      *
@@ -222,8 +246,6 @@
     }
 
     /**
-
-    /**
      * Set the nowarn flag
      *
      * @param nwarn the status to set the flag to
@@ -295,7 +317,6 @@
         return mNlabel;
     }
 
-
     /**
      * Get the 'comment' command
      *
@@ -332,35 +353,4 @@
         }
     }
 
-
-        /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-        /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-        /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-        /**
-     * -identical flag -- allows the file to be checked in even if it is identical to the original
-     */
-    public static final String FLAG_IDENTICAL = "-identical";
-       /**
-     * -incremental flag -- baseline to be created is incremental
-     */
-    public static final String FLAG_INCREMENTAL = "-incremental";
-       /**
-     * -full flag -- baseline to be created is full
-     */
-    public static final String FLAG_FULL = "-full";
-       /**
-     * -nlabel -- baseline to be created without a label
-     */
-    public static final String FLAG_NLABEL = "-nlabel";
-
-
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkdir.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkdir.java
index 441ff52..cbb3dde 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkdir.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkdir.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -64,6 +64,23 @@
  *
  */
 public class CCMkdir extends ClearCase {
+    /**
+     * -c flag -- comment to attach to the directory
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the directory
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+    /**
+     * -nco flag -- do not checkout element after creation
+     */
+    public static final String FLAG_NOCHECKOUT = "-nco";
+
     private String  mComment = null;
     private String  mCfile   = null;
     private boolean mNoco    = false;
@@ -75,10 +92,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -97,10 +114,10 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
@@ -111,13 +128,11 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
         if (getNoCheckout()) {
             // -nco
@@ -181,7 +196,6 @@
         return mNoco;
     }
 
-
     /**
      * Get the 'comment' command
      *
@@ -218,21 +232,4 @@
         }
     }
 
-    /**
-     * -c flag -- comment to attach to the directory
-     */
-    public static final String FLAG_COMMENT = "-c";
-    /**
-     * -cfile flag -- file containing a comment to attach to the directory
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-    /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-    /**
-     * -nco flag -- do not checkout element after creation
-     */
-    public static final String FLAG_NOCHECKOUT = "-nco";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkelem.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkelem.java
index 53d2f0b..d5feadd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkelem.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMkelem.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -89,6 +89,43 @@
  *
  */
 public class CCMkelem extends ClearCase {
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+    /**
+     * -nwarn flag -- suppresses warning messages
+     */
+    public static final String FLAG_NOWARN = "-nwarn";
+    /**
+     * -ptime flag -- preserves the modification time on checkin
+     */
+    public static final String FLAG_PRESERVETIME = "-ptime";
+    /**
+     * -nco flag -- do not checkout element after creation
+     */
+    public static final String FLAG_NOCHECKOUT = "-nco";
+    /**
+     * -ci flag -- checkin element after creation
+     */
+    public static final String FLAG_CHECKIN = "-ci";
+    /**
+     * -master flag -- change mastership of main branch to current site
+     */
+    public static final String FLAG_MASTER = "-master";
+    /**
+     * -eltype flag -- element type to use during creation
+     */
+    public static final String FLAG_ELTYPE = "-eltype";
+
     private String  mComment = null;
     private String  mCfile   = null;
     private boolean mNwarn   = false;
@@ -105,10 +142,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -127,14 +164,13 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -142,13 +178,11 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         if (getNoWarn()) {
@@ -330,7 +364,6 @@
         return mEltype;
     }
 
-
     /**
      * Get the 'comment' command
      *
@@ -385,41 +418,4 @@
         }
     }
 
-    /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-    /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-    /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-    /**
-     * -nwarn flag -- suppresses warning messages
-     */
-    public static final String FLAG_NOWARN = "-nwarn";
-    /**
-     * -ptime flag -- preserves the modification time on checkin
-     */
-    public static final String FLAG_PRESERVETIME = "-ptime";
-    /**
-     * -nco flag -- do not checkout element after creation
-     */
-    public static final String FLAG_NOCHECKOUT = "-nco";
-    /**
-     * -ci flag -- checkin element after creation
-     */
-    public static final String FLAG_CHECKIN = "-ci";
-    /**
-     * -master flag -- change mastership of main branch to current site
-     */
-    public static final String FLAG_MASTER = "-master";
-    /**
-     * -eltype flag -- element type to use during creation
-     */
-    public static final String FLAG_ELTYPE = "-eltype";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklabel.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklabel.java
index b1a9686..15f1d09 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklabel.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklabel.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -83,6 +83,31 @@
  *
  */
 public class CCMklabel extends ClearCase {
+    /**
+     * -replace flag -- replace another label of the same type
+     */
+    public static final String FLAG_REPLACE = "-replace";
+    /**
+     * -recurse flag -- process all subdirectories
+     */
+    public static final String FLAG_RECURSE = "-recurse";
+    /**
+     * -version flag -- attach label to specified version
+     */
+    public static final String FLAG_VERSION = "-version";
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+
     private boolean mReplace = false;
     private boolean mRecurse = false;
     private String mVersion = null;
@@ -98,10 +123,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Check for required attributes
         if (getTypeName() == null) {
@@ -125,10 +150,10 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
@@ -155,13 +180,11 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         if (getTypeName() != null) {
@@ -173,7 +196,6 @@
         cmd.createArgument().setValue(getViewPath());
     }
 
-
     /**
      * Set the replace flag
      *
@@ -300,7 +322,6 @@
         return mVOB;
     }
 
-
     /**
      * Get the 'version' command
      *
@@ -362,10 +383,9 @@
      *        without the type-name
      */
     private void getTypeCommand(Commandline cmd) {
-        String typenm = null;
 
         if (getTypeName() != null) {
-            typenm = getTypeName();
+            String typenm = getTypeName();
             if (getVOB() != null) {
                 typenm += "@" + getVOB();
             }
@@ -373,31 +393,4 @@
         }
     }
 
-
-    /**
-     * -replace flag -- replace another label of the same type
-     */
-    public static final String FLAG_REPLACE = "-replace";
-    /**
-     * -recurse flag -- process all subdirectories
-     */
-    public static final String FLAG_RECURSE = "-recurse";
-    /**
-     * -version flag -- attach label to specified version
-     */
-    public static final String FLAG_VERSION = "-version";
-    /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-    /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-    /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklbtype.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklbtype.java
index 04db9cd..2724ec8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklbtype.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCMklbtype.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -95,6 +95,39 @@
  *
  */
 public class CCMklbtype extends ClearCase {
+    /**
+     * -replace flag -- replace existing label definition of the same type
+     */
+    public static final String FLAG_REPLACE = "-replace";
+    /**
+     * -global flag -- creates a label type that is global to the VOB or to VOBs that use this VOB
+     */
+    public static final String FLAG_GLOBAL = "-global";
+    /**
+     * -ordinary flag -- creates a label type that can be used only in the current VOB
+     */
+    public static final String FLAG_ORDINARY = "-ordinary";
+    /**
+     * -pbranch flag -- allows label type to be used once per branch
+     */
+    public static final String FLAG_PBRANCH = "-pbranch";
+    /**
+     * -shared flag -- sets the way mastership is checked by ClearCase
+     */
+    public static final String FLAG_SHARED = "-shared";
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+
     private String mTypeName = null;
     private String mVOB = null;
     private String mComment = null;
@@ -112,9 +145,9 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
-        int result = 0;
 
         // Check for required attributes
         if (getTypeName() == null) {
@@ -133,14 +166,13 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getTypeSpecifier(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -153,11 +185,9 @@
         if (getOrdinary()) {
             // -ordinary
             cmd.createArgument().setValue(FLAG_ORDINARY);
-        } else {
-            if (getGlobal()) {
-                // -global
-                cmd.createArgument().setValue(FLAG_GLOBAL);
-            }
+        } else if (getGlobal()) {
+            // -global
+            cmd.createArgument().setValue(FLAG_GLOBAL);
         }
 
         if (getPbranch()) {
@@ -173,20 +203,17 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         // type-name@vob
         cmd.createArgument().setValue(getTypeSpecifier());
     }
 
-
     /**
      * Set type-name string
      *
@@ -349,7 +376,6 @@
         return mCfile;
     }
 
-
     /**
      * Get the 'comment' command
      *
@@ -393,49 +419,11 @@
      *         specified, otherwise an empty string
      */
     private String getTypeSpecifier() {
-        String typenm = null;
-
-        typenm = getTypeName();
+        String typenm = getTypeName();
         if (getVOB() != null) {
             typenm += "@" + getVOB();
         }
-
         return typenm;
     }
 
-
-    /**
-     * -replace flag -- replace existing label definition of the same type
-     */
-    public static final String FLAG_REPLACE = "-replace";
-    /**
-     * -global flag -- creates a label type that is global to the VOB or to VOBs that use this VOB
-     */
-    public static final String FLAG_GLOBAL = "-global";
-    /**
-     * -ordinary flag -- creates a label type that can be used only in the current VOB
-     */
-    public static final String FLAG_ORDINARY = "-ordinary";
-    /**
-     * -pbranch flag -- allows label type to be used once per branch
-     */
-    public static final String FLAG_PBRANCH = "-pbranch";
-    /**
-     * -shared flag -- sets the way mastership is checked by ClearCase
-     */
-    public static final String FLAG_SHARED = "-shared";
-    /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-    /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-    /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCRmtype.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCRmtype.java
index 82a9e63..d3beadf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCRmtype.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCRmtype.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -87,6 +87,31 @@
  *
  */
 public class CCRmtype extends ClearCase {
+    /**
+     * -ignore flag -- ignore pre-trigger operations when removing a trigger type
+     */
+    public static final String FLAG_IGNORE = "-ignore";
+    /**
+     * -rmall flag -- removes all instances of a type and the type object itself
+     */
+    public static final String FLAG_RMALL = "-rmall";
+    /**
+     * -force flag -- suppresses confirmation prompts
+     */
+    public static final String FLAG_FORCE = "-force";
+    /**
+     * -c flag -- comment to attach to the file
+     */
+    public static final String FLAG_COMMENT = "-c";
+    /**
+     * -cfile flag -- file containing a comment to attach to the file
+     */
+    public static final String FLAG_COMMENTFILE = "-cfile";
+    /**
+     * -nc flag -- no comment is specified
+     */
+    public static final String FLAG_NOCOMMENT = "-nc";
+
     private String mTypeKind = null;
     private String mTypeName = null;
     private String mVOB = null;
@@ -102,9 +127,9 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
-        int result = 0;
 
         // Check for required attributes
         if (getTypeKind() == null) {
@@ -126,14 +151,13 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getTypeSpecifier(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -150,13 +174,11 @@
         if (getComment() != null) {
             // -c
             getCommentCommand(cmd);
+        } else if (getCommentFile() != null) {
+            // -cfile
+            getCommentFileCommand(cmd);
         } else {
-            if (getCommentFile() != null) {
-                // -cfile
-                getCommentFileCommand(cmd);
-            } else {
-                cmd.createArgument().setValue(FLAG_NOCOMMENT);
-            }
+            cmd.createArgument().setValue(FLAG_NOCOMMENT);
         }
 
         // type-kind:type-name
@@ -298,10 +320,9 @@
     private String getTypeSpecifier() {
         String tkind = getTypeKind();
         String tname = getTypeName();
-        String typeSpec = null;
 
         // Return the type-selector
-        typeSpec = tkind + ":" + tname;
+        String typeSpec = tkind + ":" + tname;
         if (getVOB() != null) {
             typeSpec += "@" + getVOB();
         }
@@ -344,31 +365,4 @@
         }
     }
 
-
-    /**
-     * -ignore flag -- ignore pre-trigger operations when removing a trigger type
-     */
-    public static final String FLAG_IGNORE = "-ignore";
-    /**
-     * -rmall flag -- removes all instances of a type and the type object itself
-     */
-    public static final String FLAG_RMALL = "-rmall";
-    /**
-     * -force flag -- suppresses confirmation prompts
-     */
-    public static final String FLAG_FORCE = "-force";
-    /**
-     * -c flag -- comment to attach to the file
-     */
-    public static final String FLAG_COMMENT = "-c";
-    /**
-     * -cfile flag -- file containing a comment to attach to the file
-     */
-    public static final String FLAG_COMMENTFILE = "-cfile";
-    /**
-     * -nc flag -- no comment is specified
-     */
-    public static final String FLAG_NOCOMMENT = "-nc";
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnCheckout.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnCheckout.java
index 6d7e488..c8bcb60 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnCheckout.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnCheckout.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -54,6 +54,15 @@
  *
  */
 public class CCUnCheckout extends ClearCase {
+    /**
+     *  -keep flag -- keep a copy of the file with .keep extension
+     */
+    public static final String FLAG_KEEPCOPY = "-keep";
+    /**
+     *  -rm flag -- remove the copy of the file
+     */
+    public static final String FLAG_RM = "-rm";
+
     private boolean mKeep = false;
 
     /**
@@ -63,10 +72,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -85,14 +94,13 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
-
     /**
      * Check the command line options.
      */
@@ -128,15 +136,4 @@
         return mKeep;
     }
 
-
-    /**
-     *  -keep flag -- keep a copy of the file with .keep extension
-     */
-    public static final String FLAG_KEEPCOPY = "-keep";
-    /**
-     *  -rm flag -- remove the copy of the file
-     */
-    public static final String FLAG_RM = "-rm";
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnlock.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnlock.java
index 7d72726..4493d1e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnlock.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUnlock.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,14 @@
 
 package org.apache.tools.ant.taskdefs.optional.clearcase;
 
+import java.util.Optional;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Execute;
 import org.apache.tools.ant.types.Commandline;
 
-/**
+/*
  * TODO:
  * comment field doesn't include all options yet
  */
@@ -69,6 +71,15 @@
  *
  */
 public class CCUnlock extends ClearCase {
+    /**
+     * -comment flag -- method to use for commenting events
+     */
+    public static final String FLAG_COMMENT = "-comment";
+    /**
+     * -pname flag -- pathname to lock
+     */
+    public static final String FLAG_PNAME = "-pname";
+
     private String mComment = null;
     private String mPname = null;
 
@@ -79,10 +90,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -105,10 +116,10 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getOpType(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
@@ -120,8 +131,8 @@
         getCommentCommand(cmd);
 
         if (getObjSelect() == null && getPname() == null) {
-            throw new BuildException("Should select either an element "
-            + "(pname) or an object (objselect)");
+            throw new BuildException(
+                "Should select either an element (pname) or an object (objselect)");
         }
         getPnameCommand(cmd);
         // object selector
@@ -204,15 +215,14 @@
     private void getCommentCommand(Commandline cmd) {
         if (getComment() == null) {
             return;
-        } else {
-            /* Had to make two separate commands here because if a space is
-               inserted between the flag and the value, it is treated as a
-               Windows filename with a space and it is enclosed in double
-               quotes ("). This breaks clearcase.
-            */
-            cmd.createArgument().setValue(FLAG_COMMENT);
-            cmd.createArgument().setValue(getComment());
         }
+        /* Had to make two separate commands here because if a space is
+           inserted between the flag and the value, it is treated as a
+           Windows filename with a space and it is enclosed in double
+           quotes ("). This breaks clearcase.
+        */
+        cmd.createArgument().setValue(FLAG_COMMENT);
+        cmd.createArgument().setValue(getComment());
     }
 
     /**
@@ -224,15 +234,14 @@
     private void getPnameCommand(Commandline cmd) {
         if (getPname() == null) {
             return;
-        } else {
-            /* Had to make two separate commands here because if a space is
-               inserted between the flag and the value, it is treated as a
-               Windows filename with a space and it is enclosed in double
-               quotes ("). This breaks clearcase.
-            */
-            cmd.createArgument().setValue(FLAG_PNAME);
-            cmd.createArgument().setValue(getPname());
         }
+        /* Had to make two separate commands here because if a space is
+           inserted between the flag and the value, it is treated as a
+           Windows filename with a space and it is enclosed in double
+           quotes ("). This breaks clearcase.
+        */
+        cmd.createArgument().setValue(FLAG_PNAME);
+        cmd.createArgument().setValue(getPname());
     }
 
     /**
@@ -241,21 +250,7 @@
      * @return String containing the object/pname being worked on
      */
     private String getOpType() {
-
-        if (getPname() != null) {
-            return getPname();
-        } else {
-            return getObjSelect();
-        }
+        return Optional.ofNullable(getPname()).orElseGet(this::getObjSelect);
     }
 
-    /**
-     * -comment flag -- method to use for commenting events
-     */
-    public static final String FLAG_COMMENT = "-comment";
-    /**
-     * -pname flag -- pathname to lock
-     */
-    public static final String FLAG_PNAME = "-pname";
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUpdate.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUpdate.java
index a8ee850..457d68f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUpdate.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCUpdate.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -81,6 +81,35 @@
  *
  */
 public class CCUpdate extends ClearCase {
+    /**
+     *  -graphical flag -- display graphical dialog during update operation
+     */
+    public static final String FLAG_GRAPHICAL = "-graphical";
+    /**
+     * -log flag -- file to log status to
+     */
+    public static final String FLAG_LOG = "-log";
+    /**
+     * -overwrite flag -- overwrite hijacked files
+     */
+    public static final String FLAG_OVERWRITE = "-overwrite";
+    /**
+     * -noverwrite flag -- do not overwrite hijacked files
+     */
+    public static final String FLAG_NOVERWRITE = "-noverwrite";
+    /**
+     * -rename flag -- rename hijacked files with .keep extension
+     */
+    public static final String FLAG_RENAME = "-rename";
+    /**
+     * -ctime flag -- modified time is written as the current time
+     */
+    public static final String FLAG_CURRENTTIME = "-ctime";
+    /**
+     * -ptime flag -- modified time is written as the VOB time
+     */
+    public static final String FLAG_PRESERVETIME = "-ptime";
+
     private boolean mGraphical = false;
     private boolean mOverwrite = false;
     private boolean mRename = false;
@@ -95,10 +124,10 @@
      * to execute the command line.
      * @throws BuildException if the command fails and failonerr is set to true
      */
+    @Override
     public void execute() throws BuildException {
         Commandline commandLine = new Commandline();
         Project aProj = getProject();
-        int result = 0;
 
         // Default the viewpath to basedir if it is not specified
         if (getViewPath() == null) {
@@ -121,10 +150,10 @@
             getProject().log("Ignoring any errors that occur for: "
                     + getViewPathBasename(), Project.MSG_VERBOSE);
         }
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnErr()) {
-            String msg = "Failed executing: " + commandLine.toString();
-            throw new BuildException(msg, getLocation());
+            throw new BuildException("Failed executing: " + commandLine,
+                getLocation());
         }
     }
 
@@ -140,24 +169,20 @@
             if (getOverwrite()) {
                 // -overwrite
                 cmd.createArgument().setValue(FLAG_OVERWRITE);
+            } else if (getRename()) {
+                // -rename
+                cmd.createArgument().setValue(FLAG_RENAME);
             } else {
-                if (getRename()) {
-                    // -rename
-                    cmd.createArgument().setValue(FLAG_RENAME);
-                } else {
-                    // -noverwrite
-                    cmd.createArgument().setValue(FLAG_NOVERWRITE);
-                }
+                // -noverwrite
+                cmd.createArgument().setValue(FLAG_NOVERWRITE);
             }
 
             if (getCurrentTime()) {
                 // -ctime
                 cmd.createArgument().setValue(FLAG_CURRENTTIME);
-            } else {
-                if (getPreserveTime()) {
-                    // -ptime
-                    cmd.createArgument().setValue(FLAG_PRESERVETIME);
-                }
+            } else if (getPreserveTime()) {
+                // -ptime
+                cmd.createArgument().setValue(FLAG_PRESERVETIME);
             }
 
             // -log logname
@@ -279,7 +304,6 @@
         return mLog;
     }
 
-
     /**
      * Get the 'log' command
      *
@@ -288,45 +312,14 @@
     private void getLogCommand(Commandline cmd) {
         if (getLog() == null) {
             return;
-        } else {
-            /* Had to make two separate commands here because if a space is
-               inserted between the flag and the value, it is treated as a
-               Windows filename with a space and it is enclosed in double
-               quotes ("). This breaks clearcase.
-            */
-            cmd.createArgument().setValue(FLAG_LOG);
-            cmd.createArgument().setValue(getLog());
         }
+        /* Had to make two separate commands here because if a space is
+           inserted between the flag and the value, it is treated as a
+           Windows filename with a space and it is enclosed in double
+           quotes ("). This breaks clearcase.
+        */
+        cmd.createArgument().setValue(FLAG_LOG);
+        cmd.createArgument().setValue(getLog());
     }
 
-    /**
-     *  -graphical flag -- display graphical dialog during update operation
-     */
-    public static final String FLAG_GRAPHICAL = "-graphical";
-    /**
-     * -log flag -- file to log status to
-     */
-    public static final String FLAG_LOG = "-log";
-    /**
-     * -overwrite flag -- overwrite hijacked files
-     */
-    public static final String FLAG_OVERWRITE = "-overwrite";
-    /**
-     * -noverwrite flag -- do not overwrite hijacked files
-     */
-    public static final String FLAG_NOVERWRITE = "-noverwrite";
-    /**
-     * -rename flag -- rename hijacked files with .keep extension
-     */
-    public static final String FLAG_RENAME = "-rename";
-    /**
-     * -ctime flag -- modified time is written as the current time
-     */
-    public static final String FLAG_CURRENTTIME = "-ctime";
-    /**
-     * -ptime flag -- modified time is written as the VOB time
-     */
-    public static final String FLAG_PRESERVETIME = "-ptime";
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/ClearCase.java b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/ClearCase.java
index 6eecc8a..8311426 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/ClearCase.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/ClearCase.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 package org.apache.tools.ant.taskdefs.optional.clearcase;
 
 import java.io.File;
+import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -29,8 +30,6 @@
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.util.FileUtils;
 
-
-
 /**
  * A base class for creating tasks for executing commands on ClearCase.
  * <p>
@@ -46,151 +45,6 @@
  *
  */
 public abstract class ClearCase extends Task {
-    private String mClearToolDir = "";
-    private String mviewPath = null;
-    private String mobjSelect = null;
-    private int pcnt = 0;
-    private boolean mFailonerr = true;
-    /**
-     * Set the directory where the cleartool executable is located.
-     *
-     * @param dir the directory containing the cleartool executable
-     */
-    public final void setClearToolDir(String dir) {
-        mClearToolDir = FileUtils.translatePath(dir);
-    }
-
-    /**
-     * Builds and returns the command string to execute cleartool
-     *
-     * @return String containing path to the executable
-     */
-    protected final String getClearToolCommand() {
-        String toReturn = mClearToolDir;
-        if (!toReturn.equals("") && !toReturn.endsWith("/")) {
-            toReturn += "/";
-        }
-
-        toReturn += CLEARTOOL_EXE;
-
-        return toReturn;
-    }
-
-    /**
-     * Set the path to the item in a ClearCase view to operate on.
-     *
-     * @param viewPath Path to the view directory or file
-     */
-    public final void setViewPath(String viewPath) {
-        mviewPath = viewPath;
-    }
-
-    /**
-     * Get the path to the item in a clearcase view
-     *
-     * @return mviewPath
-     */
-    public String getViewPath() {
-        return mviewPath;
-    }
-
-    /**
-     * Get the basename path of the item in a clearcase view
-     *
-     * @return basename
-     */
-    public String getViewPathBasename() {
-        return (new File(mviewPath)).getName();
-    }
-
-    /**
-     * Set the object to operate on.
-     *
-     * @param objSelect object to operate on
-     */
-    public final void setObjSelect(String objSelect) {
-        mobjSelect = objSelect;
-    }
-
-    /**
-     * Get the object to operate on
-     *
-     * @return mobjSelect
-     */
-    public String getObjSelect() {
-        return mobjSelect;
-    }
-
-    /**
-     * Execute the given command are return success or failure
-     * @param cmd command line to execute
-     * @return the exit status of the subprocess or <code>INVALID</code>
-     */
-    protected int run(Commandline cmd) {
-        try {
-            Project aProj = getProject();
-            Execute exe
-                = new Execute(new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN));
-            exe.setAntRun(aProj);
-            exe.setWorkingDirectory(aProj.getBaseDir());
-            exe.setCommandline(cmd.getCommandline());
-            return exe.execute();
-        } catch (java.io.IOException e) {
-            throw new BuildException(e, getLocation());
-        }
-    }
-
-    /**
-     * Execute the given command, and return it's output
-     * @param cmdline command line to execute
-     * @return output of the command line
-     * @deprecated use the two arg version instead
-     */
-    @Deprecated
-    protected String runS(Commandline cmdline) {
-        return runS(cmdline, false);
-    }
-
-    /**
-     * Execute the given command, and return it's output
-     * @param cmdline command line to execute
-     * @param failOnError whether to fail the build if the command fails
-     * @return output of the command line
-     * @since Ant 1.9.14
-     */
-    protected String runS(Commandline cmdline, boolean failOnError) {
-        String   outV  = "opts.cc.runS.output" + pcnt++;
-        ExecTask exe   = new ExecTask(this);
-        Commandline.Argument arg = exe.createArg();
-
-        exe.setExecutable(cmdline.getExecutable());
-        arg.setLine(Commandline.toString(cmdline.getArguments()));
-        exe.setOutputproperty(outV);
-        exe.setFailonerror(failOnError);
-        exe.execute();
-
-        return getProject().getProperty(outV);
-    }
-    /**
-     * If true, command will throw an exception on failure.
-     *
-     * @param failonerr the status to set the flag to
-     * @since ant 1.6.1
-     */
-    public void setFailOnErr(boolean failonerr) {
-        mFailonerr = failonerr;
-    }
-
-    /**
-     * Get failonerr flag status
-     *
-     * @return boolean containing status of failonerr flag
-     * @since ant 1.6.1
-     */
-    public boolean getFailOnErr() {
-        return mFailonerr;
-    }
-
     /**
      * Constant for the thing to execute
      */
@@ -252,5 +106,151 @@
      */
     public static final String COMMAND_MKDIR = "mkdir";
 
-}
+    private String mClearToolDir = "";
+    private String mviewPath = null;
+    private String mobjSelect = null;
+    private int pcnt = 0;
+    private boolean mFailonerr = true;
 
+    /**
+     * Set the directory where the cleartool executable is located.
+     *
+     * @param dir the directory containing the cleartool executable
+     */
+    public final void setClearToolDir(String dir) {
+        mClearToolDir = FileUtils.translatePath(dir);
+    }
+
+    /**
+     * Builds and returns the command string to execute cleartool
+     *
+     * @return String containing path to the executable
+     */
+    protected final String getClearToolCommand() {
+        String toReturn = mClearToolDir;
+        if (!toReturn.isEmpty() && !toReturn.endsWith("/")) {
+            toReturn += "/";
+        }
+
+        toReturn += CLEARTOOL_EXE;
+
+        return toReturn;
+    }
+
+    /**
+     * Set the path to the item in a ClearCase view to operate on.
+     *
+     * @param viewPath Path to the view directory or file
+     */
+    public final void setViewPath(String viewPath) {
+        mviewPath = viewPath;
+    }
+
+    /**
+     * Get the path to the item in a clearcase view
+     *
+     * @return mviewPath
+     */
+    public String getViewPath() {
+        return mviewPath;
+    }
+
+    /**
+     * Get the basename path of the item in a clearcase view
+     *
+     * @return basename
+     */
+    public String getViewPathBasename() {
+        return (new File(mviewPath)).getName();
+    }
+
+    /**
+     * Set the object to operate on.
+     *
+     * @param objSelect object to operate on
+     */
+    public final void setObjSelect(String objSelect) {
+        mobjSelect = objSelect;
+    }
+
+    /**
+     * Get the object to operate on
+     *
+     * @return mobjSelect
+     */
+    public String getObjSelect() {
+        return mobjSelect;
+    }
+
+    /**
+     * Execute the given command are return success or failure
+     * @param cmd command line to execute
+     * @return the exit status of the subprocess or <code>INVALID</code>
+     */
+    protected int run(Commandline cmd) {
+        try {
+            Project aProj = getProject();
+            Execute exe = new Execute(
+                new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN));
+            exe.setAntRun(aProj);
+            exe.setWorkingDirectory(aProj.getBaseDir());
+            exe.setCommandline(cmd.getCommandline());
+            return exe.execute();
+        } catch (IOException e) {
+            throw new BuildException(e, getLocation());
+        }
+    }
+
+    /**
+     * Execute the given command, and return it's output
+     * @param cmdline command line to execute
+     * @return output of the command line
+     * @deprecated use the two arg version instead
+     */
+    @Deprecated
+    protected String runS(Commandline cmdline) {
+        return runS(cmdline, false);
+    }
+
+    /**
+     * Execute the given command, and return it's output
+     * @param cmdline command line to execute
+     * @param failOnError whether to fail the build if the command fails
+     * @return output of the command line
+     * @since Ant 1.10.6
+     */
+    protected String runS(Commandline cmdline, boolean failOnError) {
+        String   outV  = "opts.cc.runS.output" + pcnt++;
+        ExecTask exe   = new ExecTask(this);
+        Commandline.Argument arg = exe.createArg();
+
+        exe.setExecutable(cmdline.getExecutable());
+        arg.setLine(Commandline.toString(cmdline.getArguments()));
+        exe.setOutputproperty(outV);
+        exe.setFailonerror(failOnError);
+        exe.execute();
+
+        return getProject().getProperty(outV);
+    }
+
+    /**
+     * If true, command will throw an exception on failure.
+     *
+     * @param failonerr the status to set the flag to
+     * @since ant 1.6.1
+     */
+    public void setFailOnErr(boolean failonerr) {
+        mFailonerr = failonerr;
+    }
+
+    /**
+     * Get failonerr flag status
+     *
+     * @return boolean containing status of failonerr flag
+     * @since ant 1.6.1
+     */
+    public boolean getFailOnErr() {
+        return mFailonerr;
+    }
+
+}
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..46c4596 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,17 +18,18 @@
 package org.apache.tools.ant.taskdefs.optional.depend;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.Vector;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
 
-import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.types.resources.ZipResource;
 import org.apache.tools.ant.util.depend.AbstractAnalyzer;
+import org.apache.tools.zip.ZipFile;
 
 /**
  * An analyzer which uses the depend task's bytecode classes to analyze
@@ -36,11 +37,6 @@
  *
  */
 public class AntAnalyzer extends AbstractAnalyzer {
-    /**
-     * Default constructor
-     */
-    public AntAnalyzer() {
-    }
 
     /**
      * Determine the dependencies of the configured root classes.
@@ -50,85 +46,56 @@
      * @param classes a vector to be populated with the names of the
      *      dependency classes.
      */
+    @Override
     protected void determineDependencies(Vector<File> files, Vector<String> classes) {
         // we get the root classes and build up a set of
         // classes upon which they depend
-        Hashtable<String, String> dependencies = new Hashtable<String, String>();
-        Hashtable<File, File> containers = new Hashtable<File, File>();
-        Hashtable<String, String> toAnalyze = new Hashtable<String, String>();
-        for (Enumeration<String> e = getRootClasses(); e.hasMoreElements();) {
-            String classname = e.nextElement();
-            toAnalyze.put(classname, classname);
-        }
+        Set<String> dependencies = new HashSet<>();
+        Set<File> containers = new HashSet<>();
+        Set<String> toAnalyze = new HashSet<>(Collections.list(getRootClasses()));
+        Set<String> analyzedDeps = new HashSet<>();
 
         int count = 0;
         int maxCount = isClosureRequired() ? MAX_LOOPS : 1;
-        Hashtable<String, String> analyzedDeps = null;
-        while (toAnalyze.size() != 0 && count++ < maxCount) {
-            analyzedDeps = new Hashtable<String, String>();
-            for (Enumeration<String> e = toAnalyze.keys(); e.hasMoreElements();) {
-                String classname = e.nextElement();
-                dependencies.put(classname, classname);
+        while (!toAnalyze.isEmpty() && count++ < maxCount) {
+            analyzedDeps.clear();
+            for (String classname : toAnalyze) {
+                dependencies.add(classname);
+                File container = null;
                 try {
-                    File container = getClassContainer(classname);
-                    if (container == null) {
-                        continue;
-                    }
-                    containers.put(container, container);
-
-                    ZipFile zipFile = null;
-                    InputStream inStream = null;
-                    try {
-                        if (container.getName().endsWith(".class")) {
-                            inStream = new FileInputStream(container.getPath());
-                        } else {
-                            zipFile = new ZipFile(container.getPath());
-                            String entryName
-                                = classname.replace('.', '/') + ".class";
-                            ZipEntry entry = new ZipEntry(entryName);
-                            inStream
-                                = zipFile.getInputStream(entry);
-                        }
-                        ClassFile classFile = new ClassFile();
-                        classFile.read(inStream);
-                        for (String dependency : classFile.getClassRefs()) {
-                            analyzedDeps.put(dependency, dependency);
-                        }
-                    } finally {
-                        FileUtils.close(inStream);
-                        if (zipFile != null) {
-                            zipFile.close();
-                        }
-                    }
+                    container = getClassContainer(classname);
                 } catch (IOException ioe) {
                     // ignore
                 }
+                if (container != null) {
+                    containers.add(container);
+
+                    try (InputStream inStream = container.getName().endsWith(".class")
+                            ? Files.newInputStream(Paths.get(container.getPath()))
+                            : ZipResource.getZipEntryStream(new ZipFile(container.getPath(), "UTF-8"),
+                            classname.replace('.', '/') + ".class")) {
+                        ClassFile classFile = new ClassFile();
+                        classFile.read(inStream);
+                        analyzedDeps.addAll(classFile.getClassRefs());
+                    } catch (IOException ioe) {
+                        // ignore
+                    }
+                }
             }
 
             toAnalyze.clear();
-
             // now recover all the dependencies collected and add to the list.
-            for (String className : analyzedDeps.values()) {
-                if (!dependencies.containsKey(className)) {
-                    toAnalyze.put(className, className);
-                }
-            }
+            analyzedDeps.stream().filter(className -> !dependencies.contains(className))
+                    .forEach(toAnalyze::add);
         }
 
         // pick up the last round of dependencies that were determined
-        for (String className : analyzedDeps.values()) {
-            dependencies.put(className, className);
-        }
+        dependencies.addAll(analyzedDeps);
 
         files.removeAllElements();
-        for (File f : containers.keySet()) {
-            files.add(f);
-        }
-
+        files.addAll(containers);
         classes.removeAllElements();
-        for (String dependency :dependencies.keySet()) {
-            classes.add(dependency);
-        }
+        classes.addAll(dependencies);
     }
 
     /**
@@ -136,9 +103,9 @@
      *
      * @return true if the analyzer provides dependency file information.
      */
+    @Override
     protected boolean supportsFileDependencies() {
         return true;
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFile.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFile.java
index 858ce03..4a90744 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -59,8 +59,8 @@
         DataInputStream classStream = new DataInputStream(stream);
 
         if (classStream.readInt() != CLASS_MAGIC) {
-            throw new ClassFormatError("No Magic Code Found "
-                + "- probably not a Java class file.");
+            throw new ClassFormatError(
+                "No Magic Code Found - probably not a Java class file.");
         }
 
         // right we have a good looking class file.
@@ -81,7 +81,6 @@
         className  = classInfo.getClassName();
     }
 
-
     /**
      * Get the classes which this class references.
      *
@@ -89,7 +88,7 @@
      */
     public Vector<String> getClassRefs() {
 
-        Vector<String> classRefs = new Vector<String>();
+        Vector<String> classRefs = new Vector<>();
 
         final int size = constantPool.size();
         for (int i = 0; i < size; ++i) {
@@ -118,4 +117,3 @@
         return ClassFileUtils.convertSlashName(className);
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileIterator.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileIterator.java
index 92fc191..0199dd1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileIterator.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileIterator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,11 +17,14 @@
  */
 package org.apache.tools.ant.taskdefs.optional.depend;
 
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
 /**
  * Iterator interface for iterating over a set of class files
  *
  */
-public interface ClassFileIterator {
+public interface ClassFileIterator extends Iterable<ClassFile> {
 
     /**
      * Get the next class file in the iteration
@@ -29,5 +32,33 @@
      * @return the next class file in the iteration
      */
     ClassFile getNextClassFile();
-}
 
+    @Override
+    default Iterator<ClassFile> iterator() {
+
+        return new Iterator<ClassFile>() {
+            ClassFile next;
+            {
+                next = getNextClassFile();
+            }
+
+            @Override
+            public boolean hasNext() {
+                return next != null;
+            }
+
+            @Override
+            public ClassFile next() {
+                if (next == null) {
+                    throw new NoSuchElementException();
+                }
+                try {
+                    return next;
+                } finally {
+                    next = getNextClassFile();
+                }
+            }
+
+        };
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileUtils.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileUtils.java
index c6eec6c..245b790 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileUtils.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/ClassFileUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -49,4 +49,3 @@
         return dotName.replace('.', '/');
     }
 }
-
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 99a49c4..beb2d6f 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,9 +24,17 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.net.URL;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -37,6 +45,9 @@
 import org.apache.tools.ant.taskdefs.rmic.WLRmic;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.FileProvider;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.depend.DependencyAnalyzer;
 
@@ -74,26 +85,23 @@
     /** The directory which contains the dependency cache. */
     private File cache;
 
-    /** The list of source paths derived from the srcPath field. */
-    private String[] srcPathList;
-
     /**
      * A map which gives for every class a list of the class which it
      * affects.
      */
-    private Hashtable affectedClassMap;
+    private Map<String, Map<String, ClassFileInfo>> affectedClassMap;
 
     /** A map which gives information about a class */
-    private Hashtable classFileInfoMap;
+    private Map<String, ClassFileInfo> classFileInfoMap;
 
     /**
      * A map which gives the list of jars and classes from the classpath
      * that a class depends upon
      */
-    private Hashtable classpathDependencies;
+    private Map<String, Set<File>> classpathDependencies;
 
     /** The list of classes which are out of date. */
-    private Hashtable outOfDateClasses;
+    private Map<String, String> outOfDateClasses;
 
     /**
      * indicates that the dependency relationships should be extended beyond
@@ -182,29 +190,24 @@
      * @return a collection of class dependencies
      * @exception IOException if the dependency file cannot be read
      */
-    private Hashtable readCachedDependencies(File depFile) throws IOException {
-        Hashtable dependencyMap = new Hashtable();
+    private Map<String, List<String>> readCachedDependencies(File depFile) throws IOException {
+        Map<String, List<String>> dependencyMap = new HashMap<>();
 
-        BufferedReader in = null;
-        try {
-            in = new BufferedReader(new FileReader(depFile));
-            String line = null;
-            Vector dependencyList = null;
-            String className = null;
-            int prependLength = CLASSNAME_PREPEND.length();
+        int prependLength = CLASSNAME_PREPEND.length();
+
+        try (BufferedReader in = new BufferedReader(new FileReader(depFile))) {
+            List<String> dependencyList = null;
+            String line;
             while ((line = in.readLine()) != null) {
                 if (line.startsWith(CLASSNAME_PREPEND)) {
-                    dependencyList = new Vector();
-                    className = line.substring(prependLength);
-                    dependencyMap.put(className, dependencyList);
+                    String className = line.substring(prependLength);
+                    dependencyList = dependencyMap.computeIfAbsent(className,
+                        k -> new ArrayList<>());
                 } else if (dependencyList != null) {
-                    dependencyList.addElement(line);
+                    dependencyList.add(line);
                 }
             }
-        } finally {
-            FileUtils.close(in);
         }
-
         return dependencyMap;
     }
 
@@ -214,32 +217,21 @@
      * @param dependencyMap the map of dependencies to be written out.
      * @exception IOException if the dependency file cannot be written out.
      */
-    private void writeCachedDependencies(Hashtable dependencyMap)
+    private void writeCachedDependencies(Map<String, List<String>> dependencyMap)
         throws IOException {
         if (cache != null) {
-            BufferedWriter pw = null;
-            try {
-                cache.mkdirs();
-                File depFile = new File(cache, CACHE_FILE_NAME);
-
-                pw = new BufferedWriter(new FileWriter(depFile));
-                Enumeration e = dependencyMap.keys();
-                while (e.hasMoreElements()) {
-                    String className = (String) e.nextElement();
-
-                    pw.write(CLASSNAME_PREPEND + className);
-                    pw.newLine();
-
-                    Vector dependencyList
-                        = (Vector) dependencyMap.get(className);
-                    int size = dependencyList.size();
-                    for (int x = 0; x < size; x++) {
-                        pw.write(String.valueOf(dependencyList.elementAt(x)));
+            cache.mkdirs();
+            File depFile = new File(cache, CACHE_FILE_NAME);
+            try (BufferedWriter pw =
+                new BufferedWriter(new FileWriter(depFile))) {
+                for (Map.Entry<String, List<String>> e : dependencyMap
+                    .entrySet()) {
+                    pw.write(String.format("%s%s%n", CLASSNAME_PREPEND, e.getKey()));
+                    for (String s : e.getValue()) {
+                        pw.write(s);
                         pw.newLine();
                     }
                 }
-            } finally {
-                FileUtils.close(pw);
             }
         }
     }
@@ -254,27 +246,16 @@
             return null;
         }
 
-        String[] destPathElements = destPath.list();
-        String[] classpathElements = dependClasspath.list();
-        String checkPath = "";
-        for (int i = 0; i < classpathElements.length; ++i) {
-            String element = classpathElements[i];
-            boolean inDestPath = false;
-            for (int j = 0; j < destPathElements.length && !inDestPath; ++j) {
-                inDestPath = destPathElements[j].equals(element);
-            }
-            if (!inDestPath) {
-                if (checkPath.length() == 0) {
-                    checkPath = element;
-                } else {
-                    checkPath += ":" + element;
-                }
-            }
-        }
+        Set<Resource> dependNotInDest = new LinkedHashSet<>();
+        dependClasspath.forEach(dependNotInDest::add);
+        destPath.forEach(dependNotInDest::remove);
 
-        Path p = null;
-        if (checkPath.length() > 0) {
-            p = new Path(getProject(), checkPath);
+        Path p;
+        if (dependNotInDest.isEmpty()) {
+            p = null;
+        } else {
+            p = new Path(getProject());
+            dependNotInDest.forEach(p::add);
         }
 
         log("Classpath without dest dir is " + p, Project.MSG_DEBUG);
@@ -300,11 +281,11 @@
      *      files cannot be read or written
      */
     private void determineDependencies() throws IOException {
-        affectedClassMap = new Hashtable();
-        classFileInfoMap = new Hashtable();
+        affectedClassMap = new HashMap<>();
+        classFileInfoMap = new HashMap<>();
         boolean cacheDirty = false;
 
-        Hashtable dependencyMap = new Hashtable();
+        Map<String, List<String>> dependencyMap = new HashMap<>();
         File cacheFile = null;
         boolean cacheFileExists = true;
         long cacheLastModified = Long.MAX_VALUE;
@@ -318,13 +299,11 @@
                 dependencyMap = readCachedDependencies(cacheFile);
             }
         }
-        Enumeration classfileEnum = getClassFiles(destPath).elements();
-        while (classfileEnum.hasMoreElements()) {
-            ClassFileInfo info = (ClassFileInfo) classfileEnum.nextElement();
+        for (ClassFileInfo info : getClassFiles()) {
             log("Adding class info for " + info.className, Project.MSG_DEBUG);
             classFileInfoMap.put(info.className, info);
 
-            Vector dependencyList = null;
+            List<String> dependencyList = null;
 
             if (cache != null) {
                 // try to read the dependency info from the map if it is
@@ -333,7 +312,7 @@
                     && cacheLastModified > info.absoluteFile.lastModified()) {
                     // depFile exists and is newer than the class file
                     // need to get dependency list from the map.
-                    dependencyList = (Vector) dependencyMap.get(info.className);
+                    dependencyList = dependencyMap.get(info.className);
                 }
             }
 
@@ -343,32 +322,19 @@
                 analyzer.addRootClass(info.className);
                 analyzer.addClassPath(destPath);
                 analyzer.setClosure(false);
-                dependencyList = new Vector();
-                Enumeration depEnum = analyzer.getClassDependencies();
-                while (depEnum.hasMoreElements()) {
-                    Object o = depEnum.nextElement();
-                    dependencyList.addElement(o);
-                    log("Class " + info.className + " depends on " + o,
-                        Project.MSG_DEBUG);
-                }
+                dependencyList = Collections.list(analyzer.getClassDependencies());
+                dependencyList.forEach(o -> log("Class " + info.className + " depends on " + o,
+                        Project.MSG_DEBUG));
                 cacheDirty = true;
                 dependencyMap.put(info.className, dependencyList);
             }
 
             // This class depends on each class in the dependency list. For each
             // one of those, add this class into their affected classes list
-            Enumeration depEnum = dependencyList.elements();
-            while (depEnum.hasMoreElements()) {
-                String dependentClass = (String) depEnum.nextElement();
-
-                Hashtable affectedClasses
-                    = (Hashtable) affectedClassMap.get(dependentClass);
-                if (affectedClasses == null) {
-                    affectedClasses = new Hashtable();
-                    affectedClassMap.put(dependentClass, affectedClasses);
-                }
-
-                affectedClasses.put(info.className, info);
+            for (String dependentClass : dependencyList) {
+                affectedClassMap
+                    .computeIfAbsent(dependentClass, k -> new HashMap<>())
+                    .put(info.className, info);
                 log(dependentClass + " affects " + info.className,
                     Project.MSG_DEBUG);
             }
@@ -378,23 +344,19 @@
         Path checkPath = getCheckClassPath();
         if (checkPath != null) {
             // now determine which jars each class depends upon
-            classpathDependencies = new Hashtable();
-            AntClassLoader loader = null;
-            try {
-                loader = getProject().createClassLoader(checkPath);
+            classpathDependencies = new HashMap<>();
+            try (AntClassLoader loader = getProject().createClassLoader(checkPath)) {
 
-                Hashtable classpathFileCache = new Hashtable();
+                Map<String, Object> classpathFileCache = new HashMap<>();
                 Object nullFileMarker = new Object();
-                for (Enumeration e = dependencyMap.keys(); e.hasMoreElements();) {
-                    String className = (String) e.nextElement();
+                for (Map.Entry<String, List<String>> e : dependencyMap.entrySet()) {
+                    String className = e.getKey();
                     log("Determining classpath dependencies for " + className,
                         Project.MSG_DEBUG);
-                    Vector dependencyList = (Vector) dependencyMap.get(className);
-                    Hashtable dependencies = new Hashtable();
+                    List<String> dependencyList = e.getValue();
+                    Set<File> dependencies = new HashSet<>();
                     classpathDependencies.put(className, dependencies);
-                    Enumeration e2 = dependencyList.elements();
-                    while (e2.hasMoreElements()) {
-                        String dependency = (String) e2.nextElement();
+                    for (String dependency : dependencyList) {
                         log("Looking for " + dependency, Project.MSG_DEBUG);
                         Object classpathFileObject
                             = classpathFileCache.get(dependency);
@@ -407,22 +369,23 @@
                                     = loader.getResource(dependency.replace('.', '/') + ".class");
                                 log("URL is " + classURL, Project.MSG_DEBUG);
                                 if (classURL != null) {
-                                    if (classURL.getProtocol().equals("jar")) {
+                                    if ("jar".equals(classURL.getProtocol())) {
                                         String jarFilePath = classURL.getFile();
                                         int classMarker = jarFilePath.indexOf('!');
                                         jarFilePath = jarFilePath.substring(0, classMarker);
                                         if (jarFilePath.startsWith("file:")) {
                                             classpathFileObject = new File(
-                                                                           FileUtils.getFileUtils().fromURI(jarFilePath));
+                                                FileUtils.getFileUtils()
+                                                    .fromURI(jarFilePath));
                                         } else {
                                             throw new IOException(
-                                                                  "Bizarre nested path in jar: protocol: "
-                                                                  + jarFilePath);
+                                                "Bizarre nested path in jar: protocol: "
+                                                    + jarFilePath);
                                         }
-                                    } else if (classURL.getProtocol().equals("file")) {
+                                    } else if ("file".equals(classURL.getProtocol())) {
                                         classpathFileObject = new File(
-                                                                       FileUtils.getFileUtils()
-                                                                       .fromURI(classURL.toExternalForm()));
+                                            FileUtils.getFileUtils().fromURI(
+                                                classURL.toExternalForm()));
                                     }
                                     log("Class " + className
                                         + " depends on " + classpathFileObject
@@ -439,14 +402,10 @@
                             File jarFile = (File) classpathFileObject;
                             log("Adding a classpath dependency on " + jarFile,
                                 Project.MSG_DEBUG);
-                            dependencies.put(jarFile, jarFile);
+                            dependencies.add(jarFile);
                         }
                     }
                 }
-            } finally {
-                if (loader != null) {
-                    loader.cleanup();
-                }
             }
         } else {
             log("No classpath to check", Project.MSG_DEBUG);
@@ -466,11 +425,9 @@
      */
     private int deleteAllAffectedFiles() {
         int count = 0;
-        for (Enumeration e = outOfDateClasses.elements(); e.hasMoreElements();) {
-            String className = (String) e.nextElement();
+        for (String className : outOfDateClasses.keySet()) {
             count += deleteAffectedFiles(className);
-            ClassFileInfo classInfo
-                = (ClassFileInfo) classFileInfoMap.get(className);
+            ClassFileInfo classInfo = classFileInfoMap.get(className);
             if (classInfo != null && classInfo.absoluteFile.exists()) {
                 if (classInfo.sourceFile == null) {
                     warnOutOfDateButNotDeleted(classInfo, className, className);
@@ -493,14 +450,13 @@
     private int deleteAffectedFiles(String className) {
         int count = 0;
 
-        Hashtable affectedClasses = (Hashtable) affectedClassMap.get(className);
+        Map<String, ClassFileInfo> affectedClasses = affectedClassMap.get(className);
         if (affectedClasses == null) {
             return count;
         }
-        for (Enumeration e = affectedClasses.keys(); e.hasMoreElements();) {
-            String affectedClass = (String) e.nextElement();
-            ClassFileInfo affectedClassInfo
-                = (ClassFileInfo) affectedClasses.get(affectedClass);
+        for (Map.Entry<String, ClassFileInfo> e : affectedClasses.entrySet()) {
+            String affectedClass = e.getKey();
+            ClassFileInfo affectedClassInfo = e.getValue();
 
             if (!affectedClassInfo.absoluteFile.exists()) {
                 continue;
@@ -526,12 +482,11 @@
                     continue;
                 }
                 // need to delete the main class
-                String topLevelClassName
-                    = affectedClass.substring(0, affectedClass.indexOf("$"));
+                String topLevelClassName = affectedClass.substring(0, affectedClass.indexOf("$"));
                 log("Top level class = " + topLevelClassName,
                     Project.MSG_VERBOSE);
                 ClassFileInfo topLevelClassInfo
-                    = (ClassFileInfo) classFileInfoMap.get(topLevelClassName);
+                    = classFileInfoMap.get(topLevelClassName);
                 if (topLevelClassInfo != null
                     && topLevelClassInfo.absoluteFile.exists()) {
                     log("Deleting file "
@@ -575,8 +530,8 @@
         log("The class " + affectedClass + " in file "
             + affectedClassInfo.absoluteFile.getPath()
             + " is out of date due to " + className
-            + " but has not been deleted because its source file"
-            + " could not be determined", level);
+            + " but has not been deleted because its source file could not be determined",
+            level);
         affectedClassInfo.isUserWarned = true;
     }
 
@@ -604,75 +559,48 @@
         log("Reverse Dependency Dump for " + affectedClassMap.size()
             + " classes:", Project.MSG_DEBUG);
 
-        Enumeration classEnum = affectedClassMap.keys();
-        while (classEnum.hasMoreElements()) {
-            String className = (String) classEnum.nextElement();
+        affectedClassMap.forEach((className, affectedClasses) -> {
             log(" Class " + className + " affects:", Project.MSG_DEBUG);
-            Hashtable affectedClasses
-                = (Hashtable) affectedClassMap.get(className);
-            Enumeration affectedClassEnum = affectedClasses.keys();
-            while (affectedClassEnum.hasMoreElements()) {
-                String affectedClass = (String) affectedClassEnum.nextElement();
-                ClassFileInfo info
-                    = (ClassFileInfo) affectedClasses.get(affectedClass);
-                log("    " + affectedClass + " in "
-                    + info.absoluteFile.getPath(), Project.MSG_DEBUG);
-            }
-        }
+            affectedClasses.forEach((affectedClass, info) -> log(
+                "    " + affectedClass + " in " + info.absoluteFile.getPath(),
+                Project.MSG_DEBUG));
+        });
 
         if (classpathDependencies != null) {
             log("Classpath file dependencies (Forward):", Project.MSG_DEBUG);
 
-            Enumeration classpathEnum = classpathDependencies.keys();
-            while (classpathEnum.hasMoreElements()) {
-                String className = (String) classpathEnum.nextElement();
+            classpathDependencies.forEach((className, dependencies) -> {
                 log(" Class " + className + " depends on:", Project.MSG_DEBUG);
-                Hashtable dependencies
-                    = (Hashtable) classpathDependencies.get(className);
-
-                Enumeration classpathFileEnum = dependencies.elements();
-                while (classpathFileEnum.hasMoreElements()) {
-                    File classpathFile = (File) classpathFileEnum.nextElement();
-                    log("    " + classpathFile.getPath(), Project.MSG_DEBUG);
-                }
-            }
+                dependencies.forEach(f -> log("    " + f.getPath(), Project.MSG_DEBUG));
+            });
         }
     }
 
     private void determineOutOfDateClasses() {
-        outOfDateClasses = new Hashtable();
-        for (int i = 0; i < srcPathList.length; i++) {
-            File srcDir = getProject().resolveFile(srcPathList[i]);
-            if (srcDir.exists()) {
-                DirectoryScanner ds = this.getDirectoryScanner(srcDir);
-                String[] files = ds.getIncludedFiles();
-                scanDir(srcDir, files);
-            }
-        }
+        outOfDateClasses = new HashMap<>();
+        directories(srcPath).forEach(srcDir -> {
+            DirectoryScanner ds = this.getDirectoryScanner(srcDir);
+            scanDir(srcDir, ds.getIncludedFiles());
+        });
 
         // now check classpath file dependencies
         if (classpathDependencies == null) {
             return;
         }
 
-        Enumeration classpathDepsEnum = classpathDependencies.keys();
-        while (classpathDepsEnum.hasMoreElements()) {
-            String className = (String) classpathDepsEnum.nextElement();
+        for (Map.Entry<String, Set<File>> e : classpathDependencies.entrySet()) {
+            String className = e.getKey();
             if (outOfDateClasses.containsKey(className)) {
                 continue;
             }
-            ClassFileInfo info
-                = (ClassFileInfo) classFileInfoMap.get(className);
+            ClassFileInfo info = classFileInfoMap.get(className);
 
             // if we have no info about the class - it may have been deleted already and we
             // are using cached info.
             if (info != null) {
-                Hashtable dependencies
-                    = (Hashtable) classpathDependencies.get(className);
-                for (Enumeration e2 = dependencies.elements(); e2.hasMoreElements();) {
-                    File classpathFile = (File) e2.nextElement();
-                    if (classpathFile.lastModified()
-                        > info.absoluteFile.lastModified()) {
+                for (File classpathFile : e.getValue()) {
+                    if (classpathFile.lastModified() > info.absoluteFile
+                        .lastModified()) {
                         log("Class " + className
                             + " is out of date with respect to "
                             + classpathFile, Project.MSG_DEBUG);
@@ -689,6 +617,7 @@
      *
      * @exception BuildException Thrown in case of an unrecoverable error.
      */
+    @Override
     public void execute() throws BuildException {
         try {
             long start = System.currentTimeMillis();
@@ -697,8 +626,7 @@
                                          getLocation());
             }
 
-            srcPathList = srcPath.list();
-            if (srcPathList.length == 0) {
+            if (!directories(srcPath).findAny().isPresent()) {
                 throw new BuildException("srcdir attribute must be non-empty",
                                          getLocation());
             }
@@ -708,8 +636,8 @@
             }
 
             if (cache != null && cache.exists() && !cache.isDirectory()) {
-                throw new BuildException("The cache, if specified, must "
-                                         + "point to a directory");
+                throw new BuildException(
+                    "The cache, if specified, must point to a directory");
             }
 
             if (cache != null && !cache.exists()) {
@@ -749,50 +677,38 @@
      *      checked.
      */
     protected void scanDir(File srcDir, String[] files) {
-
-        for (int i = 0; i < files.length; i++) {
-            File srcFile = new File(srcDir, files[i]);
-            if (files[i].endsWith(".java")) {
+        for (String f : files) {
+            File srcFile = new File(srcDir, f);
+            if (f.endsWith(".java")) {
                 String filePath = srcFile.getPath();
                 String className
                     = filePath.substring(srcDir.getPath().length() + 1,
                                          filePath.length() - ".java".length());
                 className = ClassFileUtils.convertSlashName(className);
                 ClassFileInfo info
-                    = (ClassFileInfo) classFileInfoMap.get(className);
+                    = classFileInfoMap.get(className);
                 if (info == null) {
                     // there was no class file. add this class to the list
                     outOfDateClasses.put(className, className);
-                } else {
-                    if (srcFile.lastModified()
-                        > info.absoluteFile.lastModified()) {
-                        outOfDateClasses.put(className, className);
-                    }
+                } else if (srcFile.lastModified() > info.absoluteFile
+                    .lastModified()) {
+                    outOfDateClasses.put(className, className);
                 }
             }
         }
     }
 
-
     /**
      * Get the list of class files we are going to analyse.
      *
-     * @param classLocations a path structure containing all the directories
-     *      where classes can be found.
      * @return a vector containing the classes to analyse.
      */
-    private Vector getClassFiles(Path classLocations) {
+    private List<ClassFileInfo> getClassFiles() {
         // break the classLocations into its components.
-        String[] classLocationsList = classLocations.list();
+        List<ClassFileInfo> classFileList = new ArrayList<>();
 
-        Vector classFileList = new Vector();
-
-        for (int i = 0; i < classLocationsList.length; ++i) {
-            File dir = new File(classLocationsList[i]);
-            if (dir.isDirectory()) {
-                addClassFiles(classFileList, dir, dir);
-            }
-        }
+        directories(destPath)
+            .forEach(dir -> addClassFiles(classFileList, dir, dir));
 
         return classFileList;
     }
@@ -806,21 +722,17 @@
      */
     private File findSourceFile(String classname, File sourceFileKnownToExist) {
         String sourceFilename;
-        int innerIndex = classname.indexOf("$");
+        int innerIndex = classname.indexOf('$');
         if (innerIndex != -1) {
             sourceFilename = classname.substring(0, innerIndex) + ".java";
         } else {
             sourceFilename = classname + ".java";
         }
-
         // search the various source path entries
-        for (int i = 0; i < srcPathList.length; ++i) {
-            File sourceFile = new File(srcPathList[i], sourceFilename);
-            if (sourceFile.equals(sourceFileKnownToExist) || sourceFile.exists()) {
-                return sourceFile;
-            }
-        }
-        return null;
+        return directories(srcPath)
+            .map(d -> new File(d, sourceFilename)).filter(Predicate
+                .<File> isEqual(sourceFileKnownToExist).or(File::exists))
+            .findFirst().orElse(null);
     }
 
     /**
@@ -835,36 +747,34 @@
      *      the absolute class name from the relative position in the
      *      source tree
      */
-    private void addClassFiles(Vector classFileList, File dir, File root) {
-        String[] filesInDir = dir.list();
+    private void addClassFiles(List<ClassFileInfo> classFileList, File dir, File root) {
+        File[] children = dir.listFiles();
 
-        if (filesInDir == null) {
+        if (children == null) {
             return;
         }
-        int length = filesInDir.length;
 
         int rootLength = root.getPath().length();
         File sourceFileKnownToExist = null; // speed optimization
-        for (int i = 0; i < length; ++i) {
-            File file = new File(dir, filesInDir[i]);
-            if (filesInDir[i].endsWith(".class")) {
+        for (File file : children) {
+            if (file.getName().endsWith(".class")) {
                 ClassFileInfo info = new ClassFileInfo();
                 info.absoluteFile = file;
-                String relativeName = file.getPath().substring(
-                                                               rootLength + 1,
-                                                               file.getPath().length() - ".class".length());
+
+                String relativeName = file.getPath().substring(rootLength + 1,
+                    file.getPath().length() - ".class".length());
+
                 info.className
                     = ClassFileUtils.convertSlashName(relativeName);
-                info.sourceFile = sourceFileKnownToExist = findSourceFile(
-                                                                          relativeName, sourceFileKnownToExist);
-                classFileList.addElement(info);
+                info.sourceFile = sourceFileKnownToExist =
+                    findSourceFile(relativeName, sourceFileKnownToExist);
+                classFileList.add(info);
             } else {
                 addClassFiles(classFileList, file, root);
             }
         }
     }
 
-
     /**
      * Set the directories path to find the Java source files.
      *
@@ -913,5 +823,10 @@
     public void setDump(boolean dump) {
         this.dump = dump;
     }
-}
 
+    private Stream<File> directories(ResourceCollection rc) {
+        return rc.stream().map(r -> r.as(FileProvider.class))
+            .filter(Objects::nonNull).map(FileProvider::getFile)
+            .filter(File::isDirectory);
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/DirectoryIterator.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/DirectoryIterator.java
index af28c96..2cf71aa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/DirectoryIterator.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/DirectoryIterator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,11 +18,15 @@
 package org.apache.tools.ant.taskdefs.optional.depend;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Stack;
-import java.util.Vector;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
 
 /**
  * An iterator which iterates through the contents of a java directory. The
@@ -36,7 +40,7 @@
      * This is a stack of current iterators supporting the depth first
      * traversal of the directory tree.
      */
-    private Stack enumStack;
+    private Deque<Iterator<File>> enumStack;
 
     /**
      * The current directory iterator. As directories encounter lower level
@@ -45,7 +49,7 @@
      * directory. This implements a depth first traversal of the directory
      * namespace.
      */
-    private Enumeration currentEnum;
+    private Iterator<File> currentIterator;
 
     /**
      * Creates a directory iterator. The directory iterator is created to
@@ -63,12 +67,8 @@
     public DirectoryIterator(File rootDirectory, boolean changeInto)
          throws IOException {
         super();
-
-        enumStack = new Stack();
-
-        Vector filesInRoot = getDirectoryEntries(rootDirectory);
-
-        currentEnum = filesInRoot.elements();
+        enumStack = new ArrayDeque<>();
+        currentIterator = getDirectoryEntries(rootDirectory).iterator();
     }
 
     /**
@@ -79,21 +79,12 @@
      * @return a vector containing File objects for each entry in the
      *      directory.
      */
-    private Vector getDirectoryEntries(File directory) {
-        Vector files = new Vector();
-
-        // File[] filesInDir = directory.listFiles();
-        String[] filesInDir = directory.list();
-
-        if (filesInDir != null) {
-            int length = filesInDir.length;
-
-            for (int i = 0; i < length; ++i) {
-                files.addElement(new File(directory, filesInDir[i]));
-            }
+    private List<File> getDirectoryEntries(File directory) {
+        File[] filesInDir = directory.listFiles();
+        if (filesInDir == null) {
+            return Collections.emptyList();
         }
-
-        return files;
+        return Arrays.asList(filesInDir);
     }
 
     /**
@@ -110,30 +101,28 @@
      *
      * @return the next ClassFile in the iteration.
      */
+    @Override
     public ClassFile getNextClassFile() {
         ClassFile nextElement = null;
 
         try {
             while (nextElement == null) {
-                if (currentEnum.hasMoreElements()) {
-                    File element = (File) currentEnum.nextElement();
+                if (currentIterator.hasNext()) {
+                    File element = currentIterator.next();
 
                     if (element.isDirectory()) {
 
                         // push the current iterator onto the stack and then
                         // iterate through this directory.
-                        enumStack.push(currentEnum);
+                        enumStack.push(currentIterator);
 
-                        Vector files = getDirectoryEntries(element);
+                        List<File> files = getDirectoryEntries(element);
 
-                        currentEnum = files.elements();
+                        currentIterator = files.iterator();
                     } else {
-
                         // we have a file. create a stream for it
-                        FileInputStream inFileStream
-                            = new FileInputStream(element);
-
-                        try {
+                        try (InputStream inFileStream
+                             = Files.newInputStream(element.toPath())) {
                             if (element.getName().endsWith(".class")) {
 
                                 // create a data input stream from the jar
@@ -144,17 +133,13 @@
 
                                 nextElement = javaClass;
                             }
-                        } finally {
-                            inFileStream.close();
                         }
                     }
+                } else // this iterator is exhausted. Can we pop one off the stack
+                if (enumStack.isEmpty()) {
+                    break;
                 } else {
-                    // this iterator is exhausted. Can we pop one off the stack
-                    if (enumStack.empty()) {
-                        break;
-                    } else {
-                        currentEnum = (Enumeration) enumStack.pop();
-                    }
+                    currentIterator = enumStack.pop();
                 }
             }
         } catch (IOException e) {
@@ -165,4 +150,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/JarFileIterator.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/JarFileIterator.java
index c468b95..f55cfd5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/JarFileIterator.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/JarFileIterator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,7 +41,6 @@
      */
     public JarFileIterator(InputStream stream) throws IOException {
         super();
-
         jarStream = new ZipInputStream(stream);
     }
 
@@ -50,6 +49,7 @@
      *
      * @return a ClassFile object describing the class from the jar
      */
+    @Override
     public ClassFile getNextClassFile() {
         ZipEntry jarEntry;
         ClassFile nextElement = null;
@@ -69,7 +69,6 @@
 
                     nextElement = javaClass;
                 } else {
-
                     jarEntry = jarStream.getNextEntry();
                 }
             }
@@ -83,9 +82,7 @@
 
             throw new BuildException("Problem reading JAR file: " + text);
         }
-
         return nextElement;
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ClassCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ClassCPInfo.java
index 8abbfc8..edbc6e0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ClassCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ClassCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -54,6 +54,7 @@
      * @exception IOException thrown if there is a problem reading the entry
      *      from the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         index = cpStream.readUnsignedShort();
         className = "unresolved";
@@ -64,6 +65,7 @@
      *
      * @return string representation of this constant pool entry
      */
+    @Override
     public String toString() {
         return "Class Constant Pool Entry for " + className + "[" + index + "]";
     }
@@ -74,6 +76,7 @@
      * @param constantPool the constant pool with which to resolve the
      *      class.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         className = ((Utf8CPInfo) constantPool.getEntry(index)).getValue();
 
@@ -90,4 +93,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantCPInfo.java
index 6103422..e381417 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -60,4 +60,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPool.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPool.java
index fe35a4f..d781769 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,25 +23,27 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * The constant pool of a Java class. The constant pool is a collection of
  * constants used in a Java class file. It stores strings, constant values,
  * class names, method names, field names etc.
  *
- * @see <a href="http://java.sun.com/docs/books/vmspec/">The Java Virtual
+ * @see <a href="https://docs.oracle.com/javase/specs/index.html">The Java Virtual
  *      Machine Specification</a>
  */
 public class ConstantPool {
 
     /** The entries in the constant pool. */
-    private final List<ConstantPoolEntry> entries = new ArrayList<ConstantPoolEntry>();
+    private final List<ConstantPoolEntry> entries = new ArrayList<>();
 
     /**
      * A Hashtable of UTF8 entries - used to get constant pool indexes of
      * the UTF8 values quickly
      */
-    private final Map<String, Integer> utf8Indexes = new HashMap<String, Integer>();
+    private final Map<String, Integer> utf8Indexes = new HashMap<>();
 
     /** Initialise the constant pool. */
     public ConstantPool() {
@@ -101,7 +103,7 @@
         if (entry instanceof Utf8CPInfo) {
             Utf8CPInfo utf8Info = (Utf8CPInfo) entry;
 
-            utf8Indexes.put(utf8Info.getValue(), Integer.valueOf(index));
+            utf8Indexes.put(utf8Info.getValue(), index);
         }
 
         return index;
@@ -143,7 +145,7 @@
         Integer indexInteger = utf8Indexes.get(value);
 
         if (indexInteger != null) {
-            index = indexInteger.intValue();
+            index = indexInteger;
         }
 
         return index;
@@ -343,16 +345,11 @@
      *
      * @return the constant pool entries as strings
      */
+    @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder("\n");
-        final int size = entries.size();
-
-        for (int i = 0; i < size; ++i) {
-            sb.append('[').append(i).append("] = ").append(getEntry(i)).append('\n');
-        }
-
-        return sb.toString();
+        return IntStream.range(0, entries.size())
+            .mapToObj(i -> String.format("[%d] = %s", i, getEntry(i)))
+            .collect(Collectors.joining("\n", "\n", "\n"));
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPoolEntry.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPoolEntry.java
index 26a0d09..5b0bb02 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPoolEntry.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ConstantPoolEntry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -71,6 +71,13 @@
     /** Tag value for InvokeDynamic entries*/
     public static final int CONSTANT_INVOKEDYNAMIC = 18;
 
+    /** Tag value for CONSTANT_Module_info entry */
+    public static final int CONSTANT_MODULEINFO = 19;
+
+    /** Tag value for CONSTANT_Package_info entry (within a module) */
+    public static final int CONSTANT_PACKAGEINFO = 20;
+
+
     /**
      * This entry's tag which identifies the type of this constant pool
      * entry.
@@ -115,72 +122,63 @@
      */
     public static ConstantPoolEntry readEntry(DataInputStream cpStream)
          throws IOException {
-        ConstantPoolEntry cpInfo = null;
         int cpTag = cpStream.readUnsignedByte();
 
+        ConstantPoolEntry cpInfo;
         switch (cpTag) {
 
             case CONSTANT_UTF8:
                 cpInfo = new Utf8CPInfo();
-
                 break;
             case CONSTANT_INTEGER:
                 cpInfo = new IntegerCPInfo();
-
                 break;
             case CONSTANT_FLOAT:
                 cpInfo = new FloatCPInfo();
-
                 break;
             case CONSTANT_LONG:
                 cpInfo = new LongCPInfo();
-
                 break;
             case CONSTANT_DOUBLE:
                 cpInfo = new DoubleCPInfo();
-
                 break;
             case CONSTANT_CLASS:
                 cpInfo = new ClassCPInfo();
-
                 break;
             case CONSTANT_STRING:
                 cpInfo = new StringCPInfo();
-
                 break;
             case CONSTANT_FIELDREF:
                 cpInfo = new FieldRefCPInfo();
-
                 break;
             case CONSTANT_METHODREF:
                 cpInfo = new MethodRefCPInfo();
-
                 break;
             case CONSTANT_INTERFACEMETHODREF:
                 cpInfo = new InterfaceMethodRefCPInfo();
-
                 break;
             case CONSTANT_NAMEANDTYPE:
                 cpInfo = new NameAndTypeCPInfo();
-
                 break;
             case CONSTANT_METHODHANDLE:
                 cpInfo = new MethodHandleCPInfo();
-
                 break;
             case CONSTANT_METHODTYPE:
                 cpInfo = new MethodTypeCPInfo();
-
                 break;
             case CONSTANT_INVOKEDYNAMIC:
                 cpInfo = new InvokeDynamicCPInfo();
-
+                break;
+            case CONSTANT_MODULEINFO:
+                cpInfo = new ModuleCPInfo();
+                break;
+            case CONSTANT_PACKAGEINFO:
+                cpInfo = new PackageCPInfo();
                 break;
             default:
                 throw new ClassFormatError("Invalid Constant Pool entry Type "
                      + cpTag);
         }
-
         cpInfo.read(cpStream);
 
         return cpInfo;
@@ -239,4 +237,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/DoubleCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/DoubleCPInfo.java
index a21c0d6..a26bb65 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/DoubleCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/DoubleCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,8 +41,9 @@
      * @exception IOException if there is a problem reading the entry from the
      *      stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
-        setValue(new Double(cpStream.readDouble()));
+        setValue(cpStream.readDouble());
     }
 
     /**
@@ -50,9 +51,9 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
         return "Double Constant Pool Entry: " + getValue();
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FieldRefCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FieldRefCPInfo.java
index 06c0925..eb36244 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FieldRefCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FieldRefCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -49,6 +49,7 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         classIndex = cpStream.readUnsignedShort();
         nameAndTypeIndex = cpStream.readUnsignedShort();
@@ -61,6 +62,7 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         ClassCPInfo fieldClass
             = (ClassCPInfo) constantPool.getEntry(classIndex);
@@ -85,18 +87,14 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
-        String value;
-
         if (isResolved()) {
-            value = "Field : Class = " + fieldClassName + ", name = "
-                + fieldName + ", type = " + fieldType;
-        } else {
-            value = "Field : Class index = " + classIndex
-                + ", name and type index = " + nameAndTypeIndex;
+            return "Field : Class = " + fieldClassName + ", name = " + fieldName
+                + ", type = " + fieldType;
         }
-
-        return value;
+        return "Field : Class index = " + classIndex
+            + ", name and type index = " + nameAndTypeIndex;
     }
 
     /**
@@ -127,4 +125,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FloatCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FloatCPInfo.java
index 532b672..7bf997e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FloatCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/FloatCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,8 +39,9 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
-        setValue(new Float(cpStream.readFloat()));
+        setValue(cpStream.readFloat());
     }
 
     /**
@@ -48,9 +49,9 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
         return "Float Constant Pool Entry: " + getValue();
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/IntegerCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/IntegerCPInfo.java
index 3beaa8c..1699868 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/IntegerCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/IntegerCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,8 +39,9 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
-        setValue(new Integer(cpStream.readInt()));
+        setValue(cpStream.readInt());
     }
 
     /**
@@ -48,9 +49,9 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
         return "Integer Constant Pool Entry: " + getValue();
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InterfaceMethodRefCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InterfaceMethodRefCPInfo.java
index fbc23c1..6430599 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InterfaceMethodRefCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InterfaceMethodRefCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,6 +55,7 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         classIndex = cpStream.readUnsignedShort();
         nameAndTypeIndex = cpStream.readUnsignedShort();
@@ -67,6 +68,7 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         ClassCPInfo interfaceMethodClass
              = (ClassCPInfo) constantPool.getEntry(classIndex);
@@ -91,19 +93,16 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
-        String value;
-
         if (isResolved()) {
-            value = "InterfaceMethod : Class = " + interfaceMethodClassName
+            return "InterfaceMethod : Class = " + interfaceMethodClassName
                  + ", name = " + interfaceMethodName + ", type = "
                  + interfaceMethodType;
-        } else {
-            value = "InterfaceMethod : Class index = " + classIndex
-                 + ", name and type index = " + nameAndTypeIndex;
         }
+        return "InterfaceMethod : Class index = " + classIndex
+             + ", name and type index = " + nameAndTypeIndex;
 
-        return value;
     }
 
     /**
@@ -134,4 +133,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InvokeDynamicCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InvokeDynamicCPInfo.java
index 3795db7..7f14dee 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InvokeDynamicCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/InvokeDynamicCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,7 +32,7 @@
     private int nameAndTypeIndex;
     /** the name and type CP info pointed to */
     private NameAndTypeCPInfo nameAndTypeCPInfo;
-    /** */
+
     /** Constructor.  */
     public InvokeDynamicCPInfo() {
         super(CONSTANT_INVOKEDYNAMIC, 1);
@@ -43,9 +43,10 @@
      *
      * @param cpStream the DataInputStream which contains the constant pool
      *      entry to be read.
-     * @exception java.io.IOException if there is a problem reading the entry from
+     * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         bootstrapMethodAttrIndex = cpStream.readUnsignedShort();
         nameAndTypeIndex = cpStream.readUnsignedShort();
@@ -56,16 +57,14 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
-        String value;
         if (isResolved()) {
-            value = "Name = " + nameAndTypeCPInfo.getName() + ", type = " + nameAndTypeCPInfo.getType();
-        } else {
-            value = "BootstrapMethodAttrIndex inx = " + bootstrapMethodAttrIndex
-            + "NameAndType index = " + nameAndTypeIndex;
+            return "Name = " + nameAndTypeCPInfo.getName() + ", type = "
+                + nameAndTypeCPInfo.getType();
         }
-
-        return value;
+        return "BootstrapMethodAttrIndex inx = " + bootstrapMethodAttrIndex
+            + "NameAndType index = " + nameAndTypeIndex;
     }
     /**
      * Resolve this constant pool entry with respect to its dependents in
@@ -74,6 +73,7 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         nameAndTypeCPInfo
                 = (NameAndTypeCPInfo) constantPool.getEntry(nameAndTypeIndex);
@@ -82,4 +82,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/LongCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/LongCPInfo.java
index e854f04..d073351 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/LongCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/LongCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,8 +39,9 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
-        setValue(new Long(cpStream.readLong()));
+        setValue(cpStream.readLong());
     }
 
     /**
@@ -48,9 +49,9 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
         return "Long Constant Pool Entry: " + getValue();
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodHandleCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodHandleCPInfo.java
index a5906c7..2c8bf85 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodHandleCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodHandleCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,27 +31,23 @@
     private ReferenceKind referenceKind;
     /** Must be a valid index into the constant pool table. */
     private int referenceIndex;
-    /**
-     * the index into the constant pool which defined the name and type
-     * signature of the method
-     */
-    private int nameAndTypeIndex;
-    public enum ReferenceKind {
-        REF_getField(1),
-        REF_getStatic(2),
-        REF_putField(3),
-        REF_putStatic(4),
-        REF_invokeVirtual(5),
-        REF_invokeStatic(6),
-        REF_invokeSpecial(7),
-        REF_newInvokeSpecial(8),
-        REF_invokeInterface(9);
-        private final int referenceKind;
-        ReferenceKind(int referenceKind) {
-            this.referenceKind = referenceKind;
-        }
 
+    public enum ReferenceKind {
+        REF_getField,
+        REF_getStatic,
+        REF_putField,
+        REF_putStatic,
+        REF_invokeVirtual,
+        REF_invokeStatic,
+        REF_invokeSpecial,
+        REF_newInvokeSpecial,
+        REF_invokeInterface;
+
+        public int value() {
+            return ordinal() + 1;
+        }
     }
+
     /** Constructor. */
     public MethodHandleCPInfo() {
         super(CONSTANT_METHODHANDLE, 1);
@@ -62,12 +58,12 @@
      *
      * @param cpStream the DataInputStream which contains the constant pool
      *      entry to be read.
-     * @exception java.io.IOException if there is a problem reading the entry from
+     * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         referenceKind = ReferenceKind.values()[cpStream.readUnsignedByte() - 1];
-
         referenceIndex = cpStream.readUnsignedShort();
     }
 
@@ -76,17 +72,13 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
-        String value;
-
         if (isResolved()) {
-            value = "MethodHandle : " + reference.toString();
-        } else {
-            value = "MethodHandle : Reference kind = " + referenceKind
-                 +  "Reference index = " + referenceIndex;
+            return "MethodHandle : " + reference.toString();
         }
-
-        return value;
+        return "MethodHandle : Reference kind = " + referenceKind
+            + "Reference index = " + referenceIndex;
     }
 
     /**
@@ -96,12 +88,11 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         reference = constantPool.getEntry(referenceIndex);
         reference.resolve(constantPool);
         super.resolve(constantPool);
     }
 
-
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodRefCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodRefCPInfo.java
index 6b33521..dd73031 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodRefCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodRefCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -52,6 +52,7 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         classIndex = cpStream.readUnsignedShort();
         nameAndTypeIndex = cpStream.readUnsignedShort();
@@ -62,18 +63,14 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
-        String value;
-
         if (isResolved()) {
-            value = "Method : Class = " + methodClassName + ", name = "
-                 + methodName + ", type = " + methodType;
-        } else {
-            value = "Method : Class index = " + classIndex
-                 + ", name and type index = " + nameAndTypeIndex;
+            return "Method : Class = " + methodClassName + ", name = "
+                + methodName + ", type = " + methodType;
         }
-
-        return value;
+        return "Method : Class index = " + classIndex
+            + ", name and type index = " + nameAndTypeIndex;
     }
 
     /**
@@ -83,6 +80,7 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         ClassCPInfo methodClass
              = (ClassCPInfo) constantPool.getEntry(classIndex);
@@ -130,4 +128,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodTypeCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodTypeCPInfo.java
index d3c35ce..6e90933 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodTypeCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/MethodTypeCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,6 +30,7 @@
     private int methodDescriptorIndex;
     /** the value of the method descriptor pointed to */
     private String methodDescriptor;
+
     /** Constructor.  */
     public MethodTypeCPInfo() {
         super(CONSTANT_METHODTYPE, 1);
@@ -40,7 +41,7 @@
      *
      * @param cpStream the DataInputStream which contains the constant pool
      *      entry to be read.
-     * @exception java.io.IOException if there is a problem reading the entry from
+     * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
     @Override
@@ -63,6 +64,7 @@
         methodDescriptor = methodClass.getValue();
         super.resolve(constantPool);
     }
+
     /**
      * Print a readable version of the constant pool entry.
      *
@@ -70,13 +72,10 @@
      */
     @Override
     public String toString() {
-        if (!isResolved()) {
-            return "MethodDescriptorIndex: " + methodDescriptorIndex;
-        } else {
+        if (isResolved()) {
             return "MethodDescriptor: " + methodDescriptor;
-
         }
+        return "MethodDescriptorIndex: " + methodDescriptorIndex;
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ModuleCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ModuleCPInfo.java
new file mode 100644
index 0000000..8e56f55
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/ModuleCPInfo.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
+ *
+ *      https://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.depend.constantpool;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Represents the module info constant pool entry
+ */
+public class ModuleCPInfo extends ConstantCPInfo {
+
+    private int moduleNameIndex;
+    private String moduleName;
+
+    public ModuleCPInfo() {
+        super(CONSTANT_MODULEINFO, 1);
+    }
+
+    @Override
+    public void read(final DataInputStream cpStream) throws IOException {
+        this.moduleNameIndex = cpStream.readUnsignedShort();
+    }
+
+    @Override
+    public void resolve(final ConstantPool constantPool) {
+        this.moduleName = ((Utf8CPInfo) constantPool.getEntry(this.moduleNameIndex)).getValue();
+
+        super.resolve(constantPool);
+    }
+
+    @Override
+    public String toString() {
+        return "Module info Constant Pool Entry for " + this.moduleName + "[" + this.moduleNameIndex + "]";
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/NameAndTypeCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/NameAndTypeCPInfo.java
index 47f454d..04986d0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/NameAndTypeCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/NameAndTypeCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,6 +25,20 @@
  *
  */
 public class NameAndTypeCPInfo extends ConstantPoolEntry {
+    /** the name component of this entry */
+    private String name;
+    /** the type component of this entry */
+    private String type;
+    /**
+     * the index into the constant pool at which the name component's string
+     * value is stored
+     */
+    private int nameIndex;
+    /**
+     * the index into the constant pool where the type descriptor string is
+     * stored.
+     */
+    private int descriptorIndex;
 
     /** Constructor. */
     public NameAndTypeCPInfo() {
@@ -39,6 +53,7 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         nameIndex = cpStream.readUnsignedShort();
         descriptorIndex = cpStream.readUnsignedShort();
@@ -49,17 +64,13 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
-        String value;
-
         if (isResolved()) {
-            value = "Name = " + name + ", type = " + type;
-        } else {
-            value = "Name index = " + nameIndex
-                 + ", descriptor index = " + descriptorIndex;
+            return "Name = " + name + ", type = " + type;
         }
-
-        return value;
+        return "Name index = " + nameIndex + ", descriptor index = "
+            + descriptorIndex;
     }
 
     /**
@@ -69,6 +80,7 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         name = ((Utf8CPInfo) constantPool.getEntry(nameIndex)).getValue();
         type = ((Utf8CPInfo) constantPool.getEntry(descriptorIndex)).getValue();
@@ -94,19 +106,4 @@
         return type;
     }
 
-    /** the name component of this entry */
-    private String name;
-    /** the type component of this entry */
-    private String type;
-    /**
-     * the index into the constant pool at which the name component's string
-     * value is stored
-     */
-    private int nameIndex;
-    /**
-     * the index into the constant pool where the type descriptor string is
-     * stored.
-     */
-    private int descriptorIndex;
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/PackageCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/PackageCPInfo.java
new file mode 100644
index 0000000..c5bfaa6
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/PackageCPInfo.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
+ *
+ *      https://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.depend.constantpool;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Represents the package info (within a module) constant pool entry
+ */
+public class PackageCPInfo extends ConstantCPInfo {
+
+    private int packageNameIndex;
+    private String packageName;
+
+    public PackageCPInfo() {
+        super(CONSTANT_PACKAGEINFO, 1);
+    }
+
+    @Override
+    public void read(final DataInputStream cpStream) throws IOException {
+        this.packageNameIndex = cpStream.readUnsignedShort();
+    }
+
+    @Override
+    public void resolve(final ConstantPool constantPool) {
+        this.packageName = ((Utf8CPInfo) constantPool.getEntry(this.packageNameIndex)).getValue();
+
+        super.resolve(constantPool);
+    }
+
+    @Override
+    public String toString() {
+        return "Package info Constant Pool Entry for " + this.packageName + "[" + this.packageNameIndex + "]";
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/StringCPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/StringCPInfo.java
index bc9ee24..2ed0b8e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/StringCPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/StringCPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,6 +26,8 @@
  *
  */
 public class StringCPInfo extends ConstantCPInfo {
+    /** the index into the constant pool containing the string's content */
+    private int index;
 
     /** Constructor.  */
     public StringCPInfo() {
@@ -40,9 +42,9 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         index = cpStream.readUnsignedShort();
-
         setValue("unresolved");
     }
 
@@ -51,6 +53,7 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
         return "String Constant Pool Entry for "
             + getValue() + "[" + index + "]";
@@ -63,12 +66,11 @@
      * @param constantPool the constant pool of which this entry is a member
      *      and against which this entry is to be resolved.
      */
+    @Override
     public void resolve(ConstantPool constantPool) {
         setValue(((Utf8CPInfo) constantPool.getEntry(index)).getValue());
         super.resolve(constantPool);
     }
 
-    /** the index into the constant pool containing the string's content */
-    private int index;
 }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/Utf8CPInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/Utf8CPInfo.java
index 5471ccd..28c4c63 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/Utf8CPInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/constantpool/Utf8CPInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,6 +41,7 @@
      * @exception IOException if there is a problem reading the entry from
      *      the stream.
      */
+    @Override
     public void read(DataInputStream cpStream) throws IOException {
         value = cpStream.readUTF();
     }
@@ -50,6 +51,7 @@
      *
      * @return the string representation of this constant pool entry.
      */
+    @Override
     public String toString() {
         return "UTF8 Value = " + value;
     }
@@ -64,4 +66,3 @@
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandDeploymentTool.java
index 0c9e632..76bcbde 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -16,19 +16,19 @@
  *
  */
 
-
 package org.apache.tools.ant.taskdefs.optional.ejb;
 
-
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Vector;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -36,10 +36,10 @@
 import org.apache.tools.ant.taskdefs.Execute;
 import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
 import org.apache.tools.ant.taskdefs.Java;
+import org.apache.tools.ant.taskdefs.optional.ejb.EjbJar.DTDLocation;
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.types.Path;
 
-
 /**
  * BorlandDeploymentTool is dedicated to the Borland Application Server 4.5 and 4.5.1
  * This task generates and compiles the stubs and skeletons for all ejb described into the
@@ -58,7 +58,7 @@
  * <li>version (int)       : tell what is the Borland appserver version 4 or 5 </li>
  * </ul>
  *
- *<PRE>
+ *<pre>
  *
  *      &lt;ejbjar srcdir=&quot;${build.classes}&quot;
  *               basejarname=&quot;vsmp&quot;
@@ -72,25 +72,24 @@
  *          &lt;include name=&quot;demo\helper\*.class&quot;/&gt;
  *         &lt;/support&gt;
  *     &lt;/ejbjar&gt;
- *</PRE>
+ *</pre>
  *
  */
 public class BorlandDeploymentTool extends GenericDeploymentTool
                                    implements ExecuteStreamHandler {
     /** Borland 1.1 ejb id */
-    public static final String PUBLICID_BORLAND_EJB
-    = "-//Inprise Corporation//DTD Enterprise JavaBeans 1.1//EN";
+    public static final String PUBLICID_BORLAND_EJB =
+        "-//Inprise Corporation//DTD Enterprise JavaBeans 1.1//EN";
 
-    protected static final String DEFAULT_BAS45_EJB11_DTD_LOCATION
-    = "/com/inprise/j2ee/xml/dtds/ejb-jar.dtd";
+    protected static final String DEFAULT_BAS45_EJB11_DTD_LOCATION =
+        "/com/inprise/j2ee/xml/dtds/ejb-jar.dtd";
 
-    protected static final String DEFAULT_BAS_DTD_LOCATION
-    = "/com/inprise/j2ee/xml/dtds/ejb-inprise.dtd";
+    protected static final String DEFAULT_BAS_DTD_LOCATION =
+        "/com/inprise/j2ee/xml/dtds/ejb-inprise.dtd";
 
     protected static final String BAS_DD = "ejb-inprise.xml";
     protected static final String BES_DD = "ejb-borland.xml";
 
-
     /** Java2iiop executable **/
     protected static final String JAVA2IIOP = "java2iiop";
 
@@ -114,13 +113,13 @@
 
     /** Borland Enterprise Server = version 5 */
     static final int    BES       = 5;
+
     /** Borland Application Server or Inprise Application Server  = version 4 */
     static final int    BAS       = 4;
 
     /** borland appserver version 4 or 5 */
     private int version = BAS;
 
-
     /**
      * Instance variable that determines whether it is necessary to verify the
      * produced jar
@@ -128,7 +127,7 @@
     private boolean verify     = true;
     private String  verifyArgs = "";
 
-    private Hashtable genfiles = new Hashtable();
+    private Map<String, File> genfiles = new Hashtable<>();
 
     /**
      * set the debug mode for java2iiop (default false)
@@ -146,7 +145,6 @@
         this.verify = verify;
     }
 
-
     /**
      * Setter used to store the suffix for the generated borland jar file.
      * @param inString the string to use as the suffix.
@@ -155,7 +153,6 @@
         this.jarSuffix = inString;
     }
 
-
     /**
      * sets some additional args to send to verify command
      * @param args additional command line parameters
@@ -173,7 +170,6 @@
         this.borlandDTD = inString;
     }
 
-
     /**
      * setter used to store whether the task will include the generate client task.
      * (see : BorlandGenerateClient task)
@@ -200,34 +196,27 @@
         this.java2iioparams = params;
     }
 
-
     /**
      * Get the borland descriptor handler.
      * @param srcDir the source directory.
      * @return the descriptor.
      */
     protected DescriptorHandler getBorlandDescriptorHandler(final File srcDir) {
-        DescriptorHandler handler =
-            new DescriptorHandler(getTask(), srcDir) {
-                    protected void processElement() {
-                        if (currentElement.equals("type-storage")) {
-                            // Get the filename of vendor specific descriptor
-                            String fileNameWithMETA = currentText;
-                            //trim the META_INF\ off of the file name
-                            String fileName
-                                = fileNameWithMETA.substring(META_DIR.length(),
-                                    fileNameWithMETA.length());
-                            File descriptorFile = new File(srcDir, fileName);
-
-                            ejbFiles.put(fileNameWithMETA, descriptorFile);
-                        }
-                    }
-                };
+        DescriptorHandler handler = new DescriptorHandler(getTask(), srcDir) {
+            @Override
+            protected void processElement() {
+                if ("type-storage".equals(currentElement)) {
+                    // Get the filename of vendor specific descriptor
+                    // trim the META_INF\ off of the file name
+                    ejbFiles.put(currentText, new File(srcDir,
+                            currentText.substring(META_DIR.length())));
+                }
+            }
+        };
         handler.registerDTD(PUBLICID_BORLAND_EJB,
                             borlandDTD == null ? DEFAULT_BAS_DTD_LOCATION : borlandDTD);
 
-        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
-            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
+        for (DTDLocation dtdLocation : getConfig().dtdLocations) {
             handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
         }
         return handler;
@@ -239,14 +228,15 @@
      * @param ejbFiles the map to add the files to.
      * @param ddPrefix the prefix to use.
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    @Override
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
 
         //choose the right vendor DD
-        if (!(version == BES || version == BAS)) {
+        if (version != BES && version != BAS) {
             throw new BuildException("version " + version + " is not supported");
         }
 
-        String dd = (version == BES ? BES_DD : BAS_DD);
+        String dd = (version == BES) ? BES_DD : BAS_DD;
 
         log("vendor file : " + ddPrefix + dd, Project.MSG_DEBUG);
 
@@ -265,6 +255,7 @@
      * Get the vendor specific name of the Jar that will be output. The modification date
      * of this jar will be checked against the dependent bean classes.
      */
+    @Override
     File getVendorOutputJarFile(String baseName) {
         return new File(getDestDir(), baseName +  jarSuffix);
     }
@@ -293,8 +284,7 @@
     private void verifyBorlandJarV5(File sourceJar) {
         log("verify BES " + sourceJar, Project.MSG_INFO);
         try {
-            ExecTask execTask = null;
-            execTask = new ExecTask(getTask());
+            ExecTask execTask = new ExecTask(getTask());
             execTask.setDir(new File("."));
             execTask.setExecutable("iastool");
             //classpath
@@ -314,9 +304,7 @@
             execTask.execute();
         } catch (Exception e) {
             // Have to catch this because of the semantics of calling main()
-            String msg = "Exception while calling generateclient Details: "
-                + e.toString();
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while calling generateclient Details: ", e);
         }
     }
 
@@ -353,7 +341,6 @@
         }
     }
 
-
     /**
      * Generate the client jar corresponding to the jar file passed as parameter
      * the method uses the BorlandGenerateClient task.
@@ -363,7 +350,7 @@
         getTask().getProject().addTaskDefinition("internal_bas_generateclient",
             org.apache.tools.ant.taskdefs.optional.ejb.BorlandGenerateClient.class);
 
-        org.apache.tools.ant.taskdefs.optional.ejb.BorlandGenerateClient gentask = null;
+        BorlandGenerateClient gentask;
         log("generate client for " + sourceJar, Project.MSG_INFO);
         try {
             Project project = getTask().getProject();
@@ -380,9 +367,7 @@
             gentask.execute();
         } catch (Exception e) {
             //TO DO : delete the file if it is not a valid file.
-            String msg = "Exception while calling " + VERIFY + " Details: "
-                + e.toString();
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while calling " + VERIFY, e);
         }
     }
 
@@ -391,10 +376,8 @@
      * Add all the generate class file into the ejb files
      * @param ithomes : iterator on home class
      */
-    private void buildBorlandStubs(Iterator ithomes) {
-        Execute execTask = null;
-
-        execTask = new Execute(this);
+    private void buildBorlandStubs(Collection<String> ithomes) {
+        Execute execTask = new Execute(this);
         Project project = getTask().getProject();
         execTask.setAntRun(project);
         execTask.setWorkingDirectory(project.getBaseDir());
@@ -418,16 +401,14 @@
             commandline.createArgument().setLine(java2iioparams);
         }
 
-
         //root dir
         commandline.createArgument().setValue("-root_dir");
         commandline.createArgument().setValue(getConfig().srcDir.getAbsolutePath());
         //compiling order
         commandline.createArgument().setValue("-compile");
         //add the home class
-        while (ithomes.hasNext()) {
-            commandline.createArgument().setValue(ithomes.next().toString());
-        }
+        ithomes.stream().map(Object::toString)
+            .forEach(v -> commandline.createArgument().setValue(v));
 
         try {
             log("Calling java2iiop", Project.MSG_VERBOSE);
@@ -435,11 +416,11 @@
             execTask.setCommandline(commandline.getCommandline());
             int result = execTask.execute();
             if (Execute.isFailure(result)) {
-                String msg = "Failed executing java2iiop (ret code is "
-                    + result + ")";
-                throw new BuildException(msg, getTask().getLocation());
+                throw new BuildException(
+                    "Failed executing java2iiop (ret code is " + result + ")",
+                    getTask().getLocation());
             }
-        } catch (java.io.IOException e) {
+        } catch (IOException e) {
             log("java2iiop exception :" + e.getMessage(), Project.MSG_ERR);
             throw new BuildException(e, getTask().getLocation());
         }
@@ -455,13 +436,13 @@
      * @param publicId the id to use.
      * @throws BuildException if there is an error.
      */
-    protected void writeJar(String baseName, File jarFile, Hashtable files, String publicId)
+    @Override
+    protected void writeJar(String baseName, File jarFile, Hashtable<String, File> files, String publicId)
         throws BuildException {
         //build the home classes list.
-        Vector homes = new Vector();
-        Iterator it = files.keySet().iterator();
-        while (it.hasNext()) {
-            String clazz = (String) it.next();
+        List<String> homes = new ArrayList<>();
+
+        for (String clazz : files.keySet()) {
             if (clazz.endsWith("Home.class")) {
                 //remove .class extension
                 String home = toClass(clazz);
@@ -470,7 +451,7 @@
             }
         }
 
-        buildBorlandStubs(homes.iterator());
+        buildBorlandStubs(homes);
 
         //add the gen files to the collection
         files.putAll(genfiles);
@@ -493,9 +474,8 @@
      */
     private String toClass(String filename) {
         //remove the .class
-        String classname = filename.substring(0, filename.lastIndexOf(".class"));
-        classname = classname.replace('\\', '.');
-        return classname;
+        return filename.substring(0, filename.lastIndexOf(".class"))
+            .replace('\\', '.').replace('/', '.');
     }
 
     /**
@@ -504,28 +484,35 @@
      */
     private  String toClassFile(String filename) {
         //remove the .class
-        String classfile = filename.substring(0, filename.lastIndexOf(".java"));
-        classfile = classfile + ".class";
-        return classfile;
+        return filename.replaceFirst("\\.java$", ".class");
     }
 
     // implementation of org.apache.tools.ant.taskdefs.ExecuteStreamHandler interface
 
     /** {@inheritDoc}. */
-    public void start() throws IOException  { }
+    @Override
+    public void start() throws IOException {
+    }
+
     /** {@inheritDoc}. */
-    public void stop()  {  }
+    @Override
+    public void stop() {
+    }
+
     /** {@inheritDoc}. */
-    public void setProcessInputStream(OutputStream param1) throws IOException   { }
+    @Override
+    public void setProcessInputStream(OutputStream param1) throws IOException {
+    }
 
     /**
      * Set the output stream of the process.
      * @param is the input stream.
      * @throws IOException if there is an error.
      */
+    @Override
     public void setProcessOutputStream(InputStream is) throws IOException {
-        try {
-            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+        try (BufferedReader reader =
+            new BufferedReader(new InputStreamReader(is))) {
             String javafile;
             while ((javafile = reader.readLine()) != null) {
                 if (javafile.endsWith(".java")) {
@@ -535,10 +522,8 @@
                     genfiles.put(key, new File(classfile));
                 }
             }
-            reader.close();
         } catch (Exception e) {
-            String msg = "Exception while parsing  java2iiop output. Details: " + e.toString();
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while parsing java2iiop output.", e);
         }
     }
 
@@ -547,6 +532,7 @@
      * @param is the input stream.
      * @throws IOException if there is an error.
      */
+    @Override
     public void setProcessErrorStream(InputStream is) throws IOException {
         BufferedReader reader = new BufferedReader(new InputStreamReader(is));
         String s = reader.readLine();
@@ -555,4 +541,3 @@
         }
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandGenerateClient.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandGenerateClient.java
index dd46269..8ca3b53 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandGenerateClient.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/BorlandGenerateClient.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -133,7 +133,6 @@
         createClasspath().setRefid(r);
     }
 
-
     /**
      * Do the work.
      *
@@ -141,6 +140,7 @@
      *
      * @exception BuildException if something goes wrong with the build
      */
+    @Override
     public void execute() throws BuildException {
         if (ejbjarfile == null || ejbjarfile.isDirectory()) {
             throw new BuildException("invalid ejb jar file.");
@@ -151,7 +151,7 @@
             String ejbjarname = ejbjarfile.getAbsolutePath();
             //clientname = ejbjarfile+client.jar
             String clientname = ejbjarname.substring(0, ejbjarname.lastIndexOf("."));
-            clientname = clientname + "client.jar";
+            clientname += "client.jar";
             clientjarfile = new File(clientname);
         }
 
@@ -160,15 +160,13 @@
             setMode(JAVA_MODE);
         }
 
-        if (!(version == BorlandDeploymentTool.BES
-            || version == BorlandDeploymentTool.BAS)) {
-            throw new BuildException("version " + version
-                                      + " is not supported");
+        if (version != BorlandDeploymentTool.BES && version != BorlandDeploymentTool.BAS) {
+            throw new BuildException("version %d is not supported", version);
         }
 
         log("client jar file is " + clientjarfile);
 
-        if (mode.equalsIgnoreCase(FORK_MODE)) {
+        if (FORK_MODE.equalsIgnoreCase(mode)) {
             executeFork();
         } else {
             executeJava();
@@ -182,15 +180,14 @@
     protected void executeJava() throws BuildException {
         try {
             if (version == BorlandDeploymentTool.BES)  {
-                throw new BuildException("java mode is supported only for "
-                    + "previous version <=" + BorlandDeploymentTool.BAS);
+                throw new BuildException(
+                    "java mode is supported only for previous version <= %d",
+                    BorlandDeploymentTool.BAS);
             }
 
             log("mode : java");
 
-            Java execTask = null;
-            execTask = new Java(this);
-
+            Java execTask = new Java(this);
             execTask.setDir(new File("."));
             execTask.setClassname("com.inprise.server.commandline.EJBUtilities");
             //classpath
@@ -218,8 +215,7 @@
 
         } catch (Exception e) {
             // Have to catch this because of the semantics of calling main()
-            String msg = "Exception while calling generateclient Details: " + e.toString();
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while calling generateclient", e);
         }
     }
 
@@ -227,7 +223,7 @@
      * launch the generate client using system api.
      * @throws BuildException if there is an error.
      */
-    protected  void executeFork() throws BuildException {
+    protected void executeFork() throws BuildException {
         if (version == BorlandDeploymentTool.BAS) {
             executeForkV4();
         }
@@ -240,13 +236,11 @@
      * launch the generate client using system api.
      * @throws BuildException if there is an error.
      */
-    protected  void executeForkV4() throws BuildException {
+    protected void executeForkV4() throws BuildException {
         try {
-
             log("mode : fork " + BorlandDeploymentTool.BAS, Project.MSG_DEBUG);
 
             ExecTask execTask = new ExecTask(this);
-
             execTask.setDir(new File("."));
             execTask.setExecutable("iastool");
             execTask.createArg().setValue("generateclient");
@@ -267,24 +261,19 @@
             execTask.execute();
         } catch (Exception e) {
             // Have to catch this because of the semantics of calling main()
-            String msg = "Exception while calling generateclient Details: "
-                + e.toString();
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while calling generateclient", e);
         }
-
     }
 
     /**
      * launch the generate client using system api.
      * @throws BuildException if there is an error.
      */
-    protected  void executeForkV5() throws BuildException {
+    protected void executeForkV5() throws BuildException {
         try {
             log("mode : fork " + BorlandDeploymentTool.BES, Project.MSG_DEBUG);
             ExecTask execTask = new ExecTask(this);
-
             execTask.setDir(new File("."));
-
             execTask.setExecutable("iastool");
             if (debug) {
                 execTask.createArg().setValue("-debug");
@@ -303,11 +292,8 @@
             execTask.execute();
         } catch (Exception e) {
             // Have to catch this because of the semantics of calling main()
-            String msg = "Exception while calling generateclient Details: "
-                + e.toString();
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while calling generateclient", e);
         }
-
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/DescriptorHandler.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/DescriptorHandler.java
index af15945..47c8158 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/DescriptorHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/DescriptorHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,14 @@
 package org.apache.tools.ant.taskdefs.optional.ejb;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.file.Files;
+import java.util.Collections;
 import java.util.Hashtable;
+import java.util.Map;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
@@ -97,20 +98,20 @@
      * put into the jar file, mapped to File objects  Accessed by the SAX
      * parser call-back method characters().
      */
-    protected Hashtable ejbFiles = null;
+    protected Hashtable<String, File> ejbFiles = null;
 
     /**
      * Instance variable that stores the value found in the &lt;ejb-name&gt; element
      */
     protected String ejbName = null;
 
-    private Hashtable fileDTDs = new Hashtable();
+    private Map<String, File> fileDTDs = new Hashtable<>();
 
-    private Hashtable resourceDTDs = new Hashtable();
+    private Map<String, String> resourceDTDs = new Hashtable<>();
 
     private boolean inEJBRef = false;
 
-    private Hashtable urlDTDs = new Hashtable();
+    private Map<String, URL> urlDTDs = new Hashtable<>();
     // CheckStyle:VisibilityModifier OFF - bc
 
     /**
@@ -185,22 +186,23 @@
      * @return an inputsource for this identifier
      * @throws SAXException if there is a problem.
      */
+    @Override
     public InputSource resolveEntity(String publicId, String systemId)
         throws SAXException {
         this.publicId = publicId;
 
-        File dtdFile = (File) fileDTDs.get(publicId);
+        File dtdFile = fileDTDs.get(publicId);
         if (dtdFile != null) {
             try {
                 owningTask.log("Resolved " + publicId + " to local file "
                     + dtdFile, Project.MSG_VERBOSE);
-                return new InputSource(new FileInputStream(dtdFile));
-            } catch (FileNotFoundException ex) {
+                return new InputSource(Files.newInputStream(dtdFile.toPath()));
+            } catch (IOException ex) {
                 // ignore
             }
         }
 
-        String dtdResourceName = (String) resourceDTDs.get(publicId);
+        String dtdResourceName = resourceDTDs.get(publicId);
         if (dtdResourceName != null) {
             InputStream is = this.getClass().getResourceAsStream(dtdResourceName);
             if (is != null) {
@@ -210,7 +212,7 @@
             }
         }
 
-        URL dtdUrl = (URL) urlDTDs.get(publicId);
+        URL dtdUrl = urlDTDs.get(publicId);
         if (dtdUrl != null) {
             try {
                 InputStream is = dtdUrl.openStream();
@@ -232,8 +234,8 @@
      * Getter method that returns the set of files to include in the EJB jar.
      * @return the map of files
      */
-    public Hashtable getFiles() {
-        return (ejbFiles == null) ? new Hashtable() : ejbFiles;
+    public Hashtable<String, File> getFiles() {
+        return ejbFiles == null ? new Hashtable<>(Collections.emptyMap()) : ejbFiles;
     }
 
     /**
@@ -257,8 +259,9 @@
      * instance variables to ensure safe operation.
      * @throws SAXException on error
      */
+    @Override
     public void startDocument() throws SAXException {
-        this.ejbFiles = new Hashtable(DEFAULT_HASH_TABLE_SIZE, 1);
+        this.ejbFiles = new Hashtable<>(DEFAULT_HASH_TABLE_SIZE, 1);
         this.currentElement = null;
         inEJBRef = false;
     }
@@ -271,21 +274,22 @@
      * @param attrs Attributes associated to the element.
      * @throws SAXException on error
      */
+    @Override
     public void startElement(String name, AttributeList attrs)
         throws SAXException {
         this.currentElement = name;
         currentText = "";
-        if (name.equals(EJB_REF) || name.equals(EJB_LOCAL_REF)) {
+        if (EJB_REF.equals(name) || EJB_LOCAL_REF.equals(name)) {
             inEJBRef = true;
-        } else if (parseState == STATE_LOOKING_EJBJAR && name.equals(EJB_JAR)) {
+        } else if (parseState == STATE_LOOKING_EJBJAR && EJB_JAR.equals(name)) {
             parseState = STATE_IN_EJBJAR;
-        } else if (parseState == STATE_IN_EJBJAR && name.equals(ENTERPRISE_BEANS)) {
+        } else if (parseState == STATE_IN_EJBJAR && ENTERPRISE_BEANS.equals(name)) {
             parseState = STATE_IN_BEANS;
-        } else if (parseState == STATE_IN_BEANS && name.equals(SESSION_BEAN)) {
+        } else if (parseState == STATE_IN_BEANS && SESSION_BEAN.equals(name)) {
             parseState = STATE_IN_SESSION;
-        } else if (parseState == STATE_IN_BEANS && name.equals(ENTITY_BEAN)) {
+        } else if (parseState == STATE_IN_BEANS && ENTITY_BEAN.equals(name)) {
             parseState = STATE_IN_ENTITY;
-        } else if (parseState == STATE_IN_BEANS && name.equals(MESSAGE_BEAN)) {
+        } else if (parseState == STATE_IN_BEANS && MESSAGE_BEAN.equals(name)) {
             parseState = STATE_IN_MESSAGE;
         }
     }
@@ -300,6 +304,7 @@
      *        in this implementation.
      * @throws SAXException on error
      */
+    @Override
     public void endElement(String name) throws SAXException {
         processElement();
         currentText = "";
@@ -335,6 +340,7 @@
      *        char array where the current data terminates.
      * @throws SAXException on error
      */
+    @Override
     public void characters(char[] ch, int start, int length)
         throws SAXException {
         currentText += new String(ch, start, length);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EJBDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EJBDeploymentTool.java
index 6ed8e34..6a7852a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EJBDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EJBDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,14 +18,11 @@
 
 package org.apache.tools.ant.taskdefs.optional.ejb;
 
-
-
 import javax.xml.parsers.SAXParser;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
 
-
 /**
  * The interface to implement for deployment tools.
  */
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java
index 0728b75..483d34c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,6 @@
 // Standard java imports
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 import javax.xml.parsers.ParserConfigurationException;
@@ -103,12 +102,12 @@
         /**
          * A Fileset of support classes
          */
-        public List supportFileSets = new ArrayList();
+        public List<FileSet> supportFileSets = new ArrayList<>();
 
         /**
          * The list of configured DTD locations
          */
-        public ArrayList dtdLocations = new ArrayList();
+        public ArrayList<DTDLocation> dtdLocations = new ArrayList<>();
 
         /**
          * The naming scheme used to determine the generated jar name
@@ -162,6 +161,7 @@
          *
          * @return an array of the values of this attribute class.
          */
+        @Override
         public String[] getValues() {
             return new String[] {EJB_NAME, DIRECTORY, DESCRIPTOR, BASEJARNAME};
         }
@@ -178,20 +178,21 @@
         /** 2.0 value */
         public static final String CMP2_0 = "2.0";
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
-            return new String[]{
+            return new String[] {
                 CMP1_0,
                 CMP2_0,
             };
         }
     }
+
     /**
      * The config which is built by this task and used by the various deployment
      * tools to access the configuration of the ejbjar task
      */
     private Config config = new Config();
 
-
     /**
      * Stores a handle to the directory to put the Jar files in. This is
      * only used by the generic deployment descriptor tool which is created
@@ -203,11 +204,11 @@
     /** Instance variable that stores the suffix for the generated jarfile. */
     private String genericJarSuffix = "-generic.jar";
 
-    /** Instance variable that stores the CMP version for the jboss jarfile. */
+    /** Instance variable that stores the CMP version for the JBoss jarfile. */
     private String cmpVersion = CMPVersion.CMP1_0;
 
     /** The list of deployment tools we are going to run. */
-    private ArrayList deploymentTools = new ArrayList();
+    private List<EJBDeploymentTool> deploymentTools = new ArrayList<>();
 
     /**
      * Add a deployment tool to the list of deployment tools that will be
@@ -226,7 +227,7 @@
      * deployment tool for Orion server.
      *
      * @return the deployment tool instance to be configured.
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public OrionDeploymentTool createOrion() {
         OrionDeploymentTool tool = new OrionDeploymentTool();
@@ -235,7 +236,7 @@
     }
 
     /**
-     * Adds a deployment tool for Weblogic server.
+     * Adds a deployment tool for WebLogic server.
      *
      * @return the deployment tool instance to be configured.
      */
@@ -246,7 +247,7 @@
     }
 
     /**
-     * Adds a deployment tool for Websphere 4.0 server.
+     * Adds a deployment tool for WebSphere 4.0 server.
      *
      * @return the deployment tool instance to be configured.
      */
@@ -308,7 +309,7 @@
     }
 
     /**
-     * Adds a deployment tool for Weblogic when using the Toplink
+     * Adds a deployment tool for WebLogic when using the TOPLink
      * Object-Relational mapping.
      *
      * @return the deployment tool instance to be configured.
@@ -361,7 +362,6 @@
         return supportFileSet;
     }
 
-
     /**
      * Set the Manifest file to use when jarring. As of EJB 1.1, manifest
      * files are no longer used to configure the EJB. However, they still
@@ -422,10 +422,10 @@
         if (config.namingScheme == null) {
             config.namingScheme = new NamingScheme();
             config.namingScheme.setValue(NamingScheme.BASEJARNAME);
-        } else if (!config.namingScheme.getValue().equals(NamingScheme.BASEJARNAME)) {
-            throw new BuildException("The basejarname attribute is not "
-                + "compatible with the "
-                + config.namingScheme.getValue() + " naming scheme");
+        } else if (!NamingScheme.BASEJARNAME.equals(config.namingScheme.getValue())) {
+            throw new BuildException(
+                "The basejarname attribute is not compatible with the %s naming scheme",
+                config.namingScheme.getValue());
         }
     }
 
@@ -437,11 +437,11 @@
      */
     public void setNaming(NamingScheme namingScheme) {
         config.namingScheme = namingScheme;
-        if (!config.namingScheme.getValue().equals(NamingScheme.BASEJARNAME)
+        if (!NamingScheme.BASEJARNAME.equals(config.namingScheme.getValue())
             && config.baseJarName != null) {
-            throw new BuildException("The basejarname attribute is not "
-                + "compatible with the "
-                + config.namingScheme.getValue() + " naming scheme");
+            throw new BuildException(
+                "The basejarname attribute is not compatible with the %s naming scheme",
+                config.namingScheme.getValue());
         }
     }
 
@@ -559,10 +559,10 @@
         if (config.namingScheme == null) {
             config.namingScheme = new NamingScheme();
             config.namingScheme.setValue(NamingScheme.DESCRIPTOR);
-        } else if (config.namingScheme.getValue().equals(NamingScheme.BASEJARNAME)
+        } else if (NamingScheme.BASEJARNAME.equals(config.namingScheme.getValue())
                     && config.baseJarName == null) {
-            throw new BuildException("The basejarname attribute must "
-                + "be specified with the basejarname naming scheme");
+            throw new BuildException(
+                "The basejarname attribute must be specified with the basejarname naming scheme");
         }
     }
 
@@ -581,10 +581,11 @@
      *            encountered that cannot be recovered from, to signal to ant
      *            that a major problem occurred within this task.
      */
+    @Override
     public void execute() throws BuildException {
         validateConfig();
 
-        if (deploymentTools.size() == 0) {
+        if (deploymentTools.isEmpty()) {
             GenericDeploymentTool genericTool = new GenericDeploymentTool();
             genericTool.setTask(this);
             genericTool.setDestdir(destDir);
@@ -592,8 +593,7 @@
             deploymentTools.add(genericTool);
         }
 
-        for (Iterator i = deploymentTools.iterator(); i.hasNext();) {
-            EJBDeploymentTool tool = (EJBDeploymentTool) i.next();
+        for (EJBDeploymentTool tool : deploymentTools) {
             tool.configure(config);
             tool.validateConfigured();
         }
@@ -604,7 +604,6 @@
             saxParserFactory.setValidating(true);
             SAXParser saxParser = saxParserFactory.newSAXParser();
 
-
             DirectoryScanner ds = getDirectoryScanner(config.descriptorDir);
             ds.scan();
             String[] files = ds.getIncludedFiles();
@@ -614,30 +613,18 @@
 
             // Loop through the files. Each file represents one deployment
             // descriptor, and hence one bean in our model.
-            for (int index = 0; index < files.length; ++index) {
+            for (String file : files) {
                 // process the deployment descriptor in each tool
-                for (Iterator i = deploymentTools.iterator(); i.hasNext();) {
-                    EJBDeploymentTool tool = (EJBDeploymentTool) i.next();
-                    tool.processDescriptor(files[index], saxParser);
+                for (EJBDeploymentTool tool : deploymentTools) {
+                    tool.processDescriptor(file, saxParser);
                 }
             }
         } catch (SAXException se) {
-            String msg = "SAXException while creating parser."
-                + "  Details: "
-                + se.getMessage();
-            throw new BuildException(msg, se);
+            throw new BuildException("SAXException while creating parser.", se);
         } catch (ParserConfigurationException pce) {
-            String msg = "ParserConfigurationException while creating parser. "
-                       + "Details: " + pce.getMessage();
-            throw new BuildException(msg, pce);
+            throw new BuildException(
+                "ParserConfigurationException while creating parser. ", pce);
         }
     } // end of execute()
 
 }
-
-
-
-
-
-
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java
index 3329a8b..228fbc9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,14 +18,13 @@
 package org.apache.tools.ant.taskdefs.optional.ejb;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Enumeration;
+import java.nio.file.Files;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
@@ -38,9 +37,9 @@
 import org.apache.tools.ant.Location;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.optional.ejb.EjbJar.DTDLocation;
 import org.apache.tools.ant.types.FileSet;
 import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.depend.DependencyAnalyzer;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -119,7 +118,7 @@
      /**
      * Set of files have been loaded into the EJB jar
      */
-    private Set addedfiles;
+    private Set<String> addedfiles;
 
     /**
      * Handler used to parse the EJB XML descriptor
@@ -131,11 +130,6 @@
      */
     private DependencyAnalyzer dependencyAnalyzer;
 
-    /** No arg constructor */
-    public GenericDeploymentTool() {
-    }
-
-
     /**
      * Set the destination directory; required.
      * @param inDir the destination directory.
@@ -153,12 +147,12 @@
         return destDir;
     }
 
-
     /**
      * Set the task which owns this tool
      *
      * @param task the Task to which this deployment tool is associated.
      */
+    @Override
     public void setTask(Task task) {
         this.task = task;
     }
@@ -235,7 +229,6 @@
                 combinedPath.append(config.classpath);
             }
         }
-
         return combinedPath;
     }
 
@@ -269,18 +262,22 @@
         }
 
         String analyzerClassName = null;
-        if (analyzer.equals(ANALYZER_SUPER)) {
-            analyzerClassName = ANALYZER_CLASS_SUPER;
-        } else if (analyzer.equals(ANALYZER_FULL)) {
-            analyzerClassName = ANALYZER_CLASS_FULL;
-        } else {
-            analyzerClassName = analyzer;
+        switch (analyzer) {
+            case ANALYZER_SUPER:
+                analyzerClassName = ANALYZER_CLASS_SUPER;
+                break;
+            case ANALYZER_FULL:
+                analyzerClassName = ANALYZER_CLASS_FULL;
+                break;
+            default:
+                analyzerClassName = analyzer;
+                break;
         }
 
         try {
-            Class analyzerClass = Class.forName(analyzerClassName);
-            dependencyAnalyzer
-                = (DependencyAnalyzer) analyzerClass.newInstance();
+            Class<? extends DependencyAnalyzer> analyzerClass =
+                Class.forName(analyzerClassName).asSubclass(DependencyAnalyzer.class);
+            dependencyAnalyzer = analyzerClass.getDeclaredConstructor().newInstance();
             dependencyAnalyzer.addClassPath(new Path(task.getProject(),
                 config.srcDir.getPath()));
             dependencyAnalyzer.addClassPath(config.classpath);
@@ -297,12 +294,12 @@
         }
     }
 
-
     /**
      * Configure this tool for use in the ejbjar task.
      *
      * @param config the configuration from the surrounding ejbjar task.
      */
+    @Override
     public void configure(EjbJar.Config config) {
         this.config = config;
 
@@ -327,12 +324,11 @@
                                 File inputFile,
                                 String logicalFilename)
         throws BuildException {
-        FileInputStream iStream = null;
-        try {
-            if (!addedfiles.contains(logicalFilename)) {
-                iStream = new FileInputStream(inputFile);
+        if (!addedfiles.contains(logicalFilename)) {
+            try (InputStream iStream = Files.newInputStream(inputFile.toPath())) {
                 // Create the zip entry and add it to the jar file
-                ZipEntry zipEntry = new ZipEntry(logicalFilename.replace('\\', '/'));
+                ZipEntry zipEntry =
+                    new ZipEntry(logicalFilename.replace('\\', '/'));
                 jStream.putNextEntry(zipEntry);
 
                 // Create the file input stream, and buffer everything over
@@ -346,15 +342,12 @@
 
                 //add it to list of files in jar
                 addedfiles.add(logicalFilename);
-           }
-        } catch (IOException ioe) {
-            log("WARNING: IOException while adding entry "
-                + logicalFilename + " to jarfile from "
-                + inputFile.getPath() + " "  + ioe.getClass().getName()
-                + "-" + ioe.getMessage(), Project.MSG_WARN);
-        } finally {
-            // Close up the file input stream for the class file
-            FileUtils.close(iStream);
+            } catch (IOException ioe) {
+                log("WARNING: IOException while adding entry " + logicalFilename
+                    + " to jarfile from " + inputFile.getPath() + " "
+                    + ioe.getClass().getName() + "-" + ioe.getMessage(),
+                    Project.MSG_WARN);
+            }
         }
     }
 
@@ -369,8 +362,7 @@
         registerKnownDTDs(h);
 
         // register any DTDs supplied by the user
-        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
-            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
+        for (DTDLocation dtdLocation : getConfig().dtdLocations) {
             h.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
         }
         return h;
@@ -388,6 +380,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void processDescriptor(String descriptorFileName, SAXParser saxParser) {
 
         checkConfiguration(descriptorFileName, saxParser);
@@ -396,7 +389,7 @@
             handler = getDescriptorHandler(config.srcDir);
 
             // Retreive the files to be added to JAR from EJB descriptor
-            Hashtable ejbFiles = parseEjbFiles(descriptorFileName, saxParser);
+            Hashtable<String, File> ejbFiles = parseEjbFiles(descriptorFileName, saxParser);
 
             // Add any support classes specified in the build file
             addSupportClasses(ejbFiles);
@@ -411,8 +404,6 @@
                 ejbFiles.put(MANIFEST, manifestFile);
             }
 
-
-
             // First the regular deployment descriptor
             ejbFiles.put(META_DIR + EJB_DD,
                          new File(config.descriptorDir, descriptorFileName));
@@ -425,7 +416,7 @@
 
             // Lastly create File object for the Jar files. If we are using
             // a flat destination dir, then we need to redefine baseName!
-            if (config.flatDestDir && baseName.length() != 0) {
+            if (config.flatDestDir && !baseName.isEmpty()) {
                 int startName = baseName.lastIndexOf(File.separator);
                 if (startName == -1) {
                     startName = 0;
@@ -437,41 +428,36 @@
 
             File jarFile = getVendorOutputJarFile(baseName);
 
-
             // Check to see if we need a build and start doing the work!
             if (needToRebuild(ejbFiles, jarFile)) {
                 // Log that we are going to build...
                 log("building "
                               + jarFile.getName()
                               + " with "
-                              + String.valueOf(ejbFiles.size())
+                              + ejbFiles.size()
                               + " files",
                               Project.MSG_INFO);
 
                 // Use helper method to write the jarfile
                 String publicId = getPublicId();
                 writeJar(baseName, jarFile, ejbFiles, publicId);
-
             } else {
                 // Log that the file is up to date...
                 log(jarFile.toString() + " is up to date.",
                               Project.MSG_VERBOSE);
             }
-
         } catch (SAXException se) {
-            String msg = "SAXException while parsing '"
-                + descriptorFileName
-                + "'. This probably indicates badly-formed XML."
-                + "  Details: "
-                + se.getMessage();
-            throw new BuildException(msg, se);
+            throw new BuildException(
+                "SAXException while parsing '" + descriptorFileName
+                    + "'. This probably indicates badly-formed XML."
+                    + "  Details: " + se.getMessage(),
+                se);
         } catch (IOException ioe) {
-            String msg = "IOException while parsing'"
-                + descriptorFileName
-                + "'.  This probably indicates that the descriptor"
-                + " doesn't exist. Details: "
-                + ioe.getMessage();
-            throw new BuildException(msg, ioe);
+            throw new BuildException(
+                "IOException while parsing'" + descriptorFileName
+                    + "'.  This probably indicates that the descriptor"
+                    + " doesn't exist. Details: " + ioe.getMessage(),
+                ioe);
         }
     }
 
@@ -489,7 +475,6 @@
      */
     protected void checkConfiguration(String descriptorFileName,
                                     SAXParser saxParser) throws BuildException {
-
         /*
          * For the GenericDeploymentTool, do nothing.  Vendor specific
          * subclasses should throw a BuildException if the configuration is
@@ -512,28 +497,17 @@
      * @throws IOException       An IOException from the parser, possibly from a
      *                           the byte stream or character stream
      */
-    protected Hashtable parseEjbFiles(String descriptorFileName, SAXParser saxParser)
+    protected Hashtable<String, File> parseEjbFiles(String descriptorFileName, SAXParser saxParser)
                             throws IOException, SAXException {
-        FileInputStream descriptorStream = null;
-        Hashtable ejbFiles = null;
-
-        try {
-
-            /* Parse the ejb deployment descriptor.  While it may not
-             * look like much, we use a SAXParser and an inner class to
-             * get hold of all the classfile names for the descriptor.
-             */
-            descriptorStream
-                = new FileInputStream(new File(config.descriptorDir, descriptorFileName));
+        /* Parse the ejb deployment descriptor.  While it may not
+         * look like much, we use a SAXParser and an inner class to
+         * get hold of all the classfile names for the descriptor.
+         */
+        try (InputStream descriptorStream = Files.newInputStream(
+            new File(config.descriptorDir, descriptorFileName).toPath())) {
             saxParser.parse(new InputSource(descriptorStream), handler);
-
-            ejbFiles = handler.getFiles();
-
-        } finally {
-            FileUtils.close(descriptorStream);
+            return handler.getFiles();
         }
-
-        return ejbFiles;
     }
 
     /**
@@ -543,22 +517,18 @@
      * @param ejbFiles Hashtable of EJB classes (and other) files that will be
      *                 added to the completed JAR file
      */
-    protected void addSupportClasses(Hashtable ejbFiles) {
+    protected void addSupportClasses(Hashtable<String, File> ejbFiles) {
         // add in support classes if any
         Project project = task.getProject();
-        for (Iterator i = config.supportFileSets.iterator(); i.hasNext();) {
-            FileSet supportFileSet = (FileSet) i.next();
+        for (FileSet supportFileSet : config.supportFileSets) {
             File supportBaseDir = supportFileSet.getDir(project);
             DirectoryScanner supportScanner = supportFileSet.getDirectoryScanner(project);
-            supportScanner.scan();
-            String[] supportFiles = supportScanner.getIncludedFiles();
-            for (int j = 0; j < supportFiles.length; ++j) {
-                ejbFiles.put(supportFiles[j], new File(supportBaseDir, supportFiles[j]));
+            for (String supportFile : supportScanner.getIncludedFiles()) {
+                ejbFiles.put(supportFile, new File(supportBaseDir, supportFile));
             }
         }
     }
 
-
     /**
      * Using the EJB descriptor file name passed from the <code>ejbjar</code>
      * task, this method returns the "basename" which will be used to name the
@@ -574,14 +544,14 @@
         String baseName = "";
 
         // Work out what the base name is
-        if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.BASEJARNAME)) {
+        if (EjbJar.NamingScheme.BASEJARNAME.equals(config.namingScheme.getValue())) {
             String canonicalDescriptor = descriptorFileName.replace('\\', '/');
             int index = canonicalDescriptor.lastIndexOf('/');
             if (index != -1) {
                 baseName = descriptorFileName.substring(0, index + 1);
             }
             baseName += config.baseJarName;
-        } else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.DESCRIPTOR)) {
+        } else if (EjbJar.NamingScheme.DESCRIPTOR.equals(config.namingScheme.getValue())) {
             int lastSeparatorIndex = descriptorFileName.lastIndexOf(File.separator);
             int endBaseName = -1;
             if (lastSeparatorIndex != -1) {
@@ -594,10 +564,11 @@
             if (endBaseName != -1) {
                 baseName = descriptorFileName.substring(0, endBaseName);
             } else {
-                throw new BuildException("Unable to determine jar name "
-                    + "from descriptor \"" + descriptorFileName + "\"");
+                throw new BuildException(
+                    "Unable to determine jar name from descriptor \"%s\"",
+                    descriptorFileName);
             }
-        } else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.DIRECTORY)) {
+        } else if (EjbJar.NamingScheme.DIRECTORY.equals(config.namingScheme.getValue())) {
             File descriptorFile = new File(config.descriptorDir, descriptorFileName);
             String path = descriptorFile.getAbsolutePath();
             int lastSeparatorIndex
@@ -610,9 +581,8 @@
             if (dirSeparatorIndex != -1) {
                 dirName = dirName.substring(dirSeparatorIndex + 1);
             }
-
             baseName = dirName;
-        } else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.EJB_NAME)) {
+        } else if (EjbJar.NamingScheme.EJB_NAME.equals(config.namingScheme.getValue())) {
             baseName = handler.getEjbName();
         }
         return baseName;
@@ -652,11 +622,10 @@
      * @param ejbFiles a hashtable entryname -&gt; file.
      * @param ddPrefix a prefix to use.
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
         // nothing to add for generic tool.
     }
 
-
     /**
      * Get the vendor specific name of the Jar that will be output. The modification date
      * of this jar will be checked against the dependent bean classes.
@@ -683,16 +652,13 @@
      * @return         boolean indicating whether or not the <code>jarFile</code>
      *                 is up to date
      */
-    protected boolean needToRebuild(Hashtable ejbFiles, File jarFile) {
+    protected boolean needToRebuild(Hashtable<String, File> ejbFiles, File jarFile) {
         if (jarFile.exists()) {
             long lastBuild = jarFile.lastModified();
 
-            Iterator fileIter = ejbFiles.values().iterator();
-
             // Loop through the files seeing if any has been touched
             // more recently than the destination jar.
-            while (fileIter.hasNext()) {
-                File currentFile = (File) fileIter.next();
+            for (File currentFile : ejbFiles.values()) {
                 if (lastBuild < currentFile.lastModified()) {
                     log("Build needed because " + currentFile.getPath() + " is out of date",
                         Project.MSG_VERBOSE);
@@ -701,7 +667,6 @@
             }
             return false;
         }
-
         return true;
     }
 
@@ -733,7 +698,6 @@
         if (manifestFile.exists()) {
             return manifestFile;
         }
-
         if (config.manifest != null) {
             return config.manifest;
         }
@@ -750,17 +714,15 @@
      * @param publicId the id to use.
      * @throws BuildException if there is a problem.
      */
-    protected void writeJar(String baseName, File jarfile, Hashtable files,
+    protected void writeJar(String baseName, File jarfile, Hashtable<String, File> files,
                             String publicId) throws BuildException {
-
-        JarOutputStream jarStream = null;
+        // clean the addedfiles set
+        if (addedfiles == null) {
+            addedfiles = new HashSet<>();
+        } else {
+            addedfiles.clear();
+        }
         try {
-            // clean the addedfiles set
-            if (addedfiles == null) {
-                addedfiles = new HashSet();
-            } else {
-                addedfiles.clear();
-            }
 
             /* If the jarfile already exists then whack it and recreate it.
              * Should probably think of a more elegant way to handle this
@@ -776,18 +738,18 @@
             InputStream in = null;
             Manifest manifest = null;
             try {
-                File manifestFile = (File) files.get(MANIFEST);
+                File manifestFile = files.get(MANIFEST);
                 if (manifestFile != null && manifestFile.exists()) {
-                    in = new FileInputStream(manifestFile);
+                    in = Files.newInputStream(manifestFile.toPath());
                 } else {
                     String defaultManifest = "/org/apache/tools/ant/defaultManifest.mf";
                     in = this.getClass().getResourceAsStream(defaultManifest);
                     if (in == null) {
-                        throw new BuildException("Could not find "
-                            + "default manifest: " + defaultManifest);
+                        throw new BuildException(
+                            "Could not find default manifest: %s",
+                            defaultManifest);
                     }
                 }
-
                 manifest = new Manifest(in);
             } catch (IOException e) {
                 throw new BuildException("Unable to read manifest", e, getLocation());
@@ -799,46 +761,44 @@
 
             // Create the streams necessary to write the jarfile
 
-            jarStream = new JarOutputStream(new FileOutputStream(jarfile), manifest);
-            jarStream.setMethod(JarOutputStream.DEFLATED);
+            try (JarOutputStream jarStream = new JarOutputStream(
+                Files.newOutputStream(jarfile.toPath()), manifest)) {
+                jarStream.setMethod(JarOutputStream.DEFLATED);
 
-            // Loop through all the class files found and add them to the jar
-            for (Iterator entryIterator = files.keySet().iterator(); entryIterator.hasNext();) {
-                String entryName = (String) entryIterator.next();
-                if (entryName.equals(MANIFEST)) {
-                    continue;
-                }
+                // Loop through all the class files found and add them to the jar
+                for (Map.Entry<String, File> entryFiles : files.entrySet()) {
+                    String entryName = entryFiles.getKey();
+                    if (entryName.equals(MANIFEST)) {
+                        continue;
+                    }
+                    File entryFile = entryFiles.getValue();
+                    log("adding file '" + entryName + "'", Project.MSG_VERBOSE);
+                    addFileToJar(jarStream, entryFile, entryName);
 
-                File entryFile = (File) files.get(entryName);
+                    // See if there are any inner classes for this class and add them in if there are
+                    InnerClassFilenameFilter flt =
+                        new InnerClassFilenameFilter(entryFile.getName());
+                    File entryDir = entryFile.getParentFile();
+                    String[] innerfiles = entryDir.list(flt);
+                    if (innerfiles != null) {
+                        for (String innerfile : innerfiles) {
+                            //get and clean up innerclass name
+                            int entryIndex =
+                                entryName.lastIndexOf(entryFile.getName()) - 1;
+                            if (entryIndex < 0) {
+                                entryName = innerfile;
+                            } else {
+                                entryName = entryName.substring(0, entryIndex)
+                                    + File.separatorChar + innerfile;
+                            }
+                            // link the file
+                            entryFile = new File(config.srcDir, entryName);
 
-                log("adding file '" + entryName + "'",
-                              Project.MSG_VERBOSE);
-
-                addFileToJar(jarStream, entryFile, entryName);
-
-                // See if there are any inner classes for this class and add them in if there are
-                InnerClassFilenameFilter flt = new InnerClassFilenameFilter(entryFile.getName());
-                File entryDir = entryFile.getParentFile();
-                String[] innerfiles = entryDir.list(flt);
-                if (innerfiles != null) {
-                    for (int i = 0, n = innerfiles.length; i < n; i++) {
-
-                        //get and clean up innerclass name
-                        int entryIndex = entryName.lastIndexOf(entryFile.getName()) - 1;
-                        if (entryIndex < 0) {
-                            entryName = innerfiles[i];
-                        } else {
-                            entryName = entryName.substring(0, entryIndex)
-                                + File.separatorChar + innerfiles[i];
-                        }
-                        // link the file
-                        entryFile = new File(config.srcDir, entryName);
-
-                        log("adding innerclass file '" + entryName + "'",
+                            log("adding innerclass file '" + entryName + "'",
                                 Project.MSG_VERBOSE);
 
-                        addFileToJar(jarStream, entryFile, entryName);
-
+                            addFileToJar(jarStream, entryFile, entryName);
+                        }
                     }
                 }
             }
@@ -848,8 +808,6 @@
                 + "'. Details: "
                 + ioe.getMessage();
             throw new BuildException(msg, ioe);
-        } finally {
-            FileUtils.close(jarStream);
         }
     } // end of writeJar
 
@@ -859,7 +817,7 @@
      * @param checkEntries files, that are extracted from the deployment descriptor
      * @throws BuildException if there is a problem.
      */
-    protected void checkAndAddDependants(Hashtable checkEntries)
+    protected void checkAndAddDependants(Hashtable<String, File> checkEntries)
         throws BuildException {
 
         if (dependencyAnalyzer == null) {
@@ -868,9 +826,7 @@
 
         dependencyAnalyzer.reset();
 
-        Iterator i = checkEntries.keySet().iterator();
-        while (i.hasNext()) {
-            String entryName = (String) i.next();
+        for (String entryName : checkEntries.keySet()) {
             if (entryName.endsWith(".class")) {
                 String className = entryName.substring(0,
                     entryName.length() - ".class".length());
@@ -881,12 +837,8 @@
             }
         }
 
-        Enumeration e = dependencyAnalyzer.getClassDependencies();
-
-        while (e.hasMoreElements()) {
-            String classname = (String) e.nextElement();
-            String location
-                = classname.replace('.', File.separatorChar) + ".class";
+        for (String classname : Collections.list(dependencyAnalyzer.getClassDependencies())) {
+            String location = classname.replace('.', File.separatorChar) + ".class";
             File classFile = new File(config.srcDir, location);
             if (classFile.exists()) {
                 checkEntries.put(location, classFile);
@@ -896,7 +848,6 @@
         }
     }
 
-
     /**
      * Returns a Classloader object which parses the passed in generic EjbJar classpath.
      * The loader is used to dynamically load classes from javax.ejb.* and the classes
@@ -907,7 +858,6 @@
         if (classpathLoader != null) {
             return classpathLoader;
         }
-
         Path combinedClasspath = getCombinedClasspath();
 
         // only generate a new ClassLoader if we have a classpath
@@ -918,7 +868,6 @@
             classpathLoader
                 = getTask().getProject().createClassLoader(combinedClasspath);
         }
-
         return classpathLoader;
     }
 
@@ -928,11 +877,12 @@
      * @throws BuildException If the Deployment Tool's configuration isn't
      *                        valid
      */
+    @Override
     public void validateConfigured() throws BuildException {
-        if ((destDir == null) || (!destDir.isDirectory())) {
-            String msg = "A valid destination directory must be specified "
-                            + "using the \"destdir\" attribute.";
-            throw new BuildException(msg, getLocation());
+        if (destDir == null || !destDir.isDirectory()) {
+            throw new BuildException(
+                "A valid destination directory must be specified using the \"destdir\" attribute.",
+                getLocation());
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetDeploymentTool.java
index d39fb9e..5a013f4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,12 +21,12 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Hashtable;
-import java.util.Iterator;
 
 import javax.xml.parsers.SAXParser;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.ejb.EjbJar.DTDLocation;
 import org.xml.sax.SAXException;
 
 /**
@@ -105,7 +105,8 @@
      * we may determine the name of the EJB JAR file using this display-name,
      * but this has not be implemented yet.
      */
-    private String  displayName;
+    @SuppressWarnings("unused")
+    private String displayName;
 
     /*
      * Regardless of the name of the iAS-specific EJB descriptor file, it will
@@ -200,25 +201,26 @@
         int startOfName = descriptorFileName.lastIndexOf(File.separatorChar) + 1;
         String stdXml = descriptorFileName.substring(startOfName);
         if (stdXml.equals(EJB_DD) && (getConfig().baseJarName == null)) {
-            String msg = "No name specified for the completed JAR file.  The EJB"
-                            + " descriptor should be prepended with the JAR "
-                            + "name or it should be specified using the "
-                            + "attribute \"basejarname\" in the \"ejbjar\" task.";
-            throw new BuildException(msg, getLocation());
+            throw new BuildException(
+                "No name specified for the completed JAR file.  The EJB"
+                    + " descriptor should be prepended with the JAR "
+                    + "name or it should be specified using the "
+                    + "attribute \"basejarname\" in the \"ejbjar\" task.",
+                getLocation());
         }
 
         File iasDescriptor = new File(getConfig().descriptorDir,
                                         getIasDescriptorName());
-        if ((!iasDescriptor.exists()) || (!iasDescriptor.isFile())) {
-            String msg = "The iAS-specific EJB descriptor ("
-                            + iasDescriptor + ") was not found.";
-            throw new BuildException(msg, getLocation());
+        if (!iasDescriptor.exists() || !iasDescriptor.isFile()) {
+            throw new BuildException("The iAS-specific EJB descriptor ("
+                + iasDescriptor + ") was not found.", getLocation());
         }
 
-        if ((iashome != null) && (!iashome.isDirectory())) {
-            String msg = "If \"iashome\" is specified, it must be a valid "
-                            + "directory (it was set to " + iashome + ").";
-            throw new BuildException(msg, getLocation());
+        if (iashome != null && !iashome.isDirectory()) {
+            throw new BuildException(
+                "If \"iashome\" is specified, it must be a valid directory (it was set to "
+                    + iashome + ").",
+                getLocation());
         }
     }
 
@@ -238,10 +240,10 @@
      *                           exception
      */
     @Override
-    protected Hashtable parseEjbFiles(String descriptorFileName,
+    protected Hashtable<String, File> parseEjbFiles(String descriptorFileName,
                          SAXParser saxParser) throws IOException, SAXException {
 
-        Hashtable files;
+        Hashtable<String, File> files;
 
         /* Build and populate an instance of the ejbc utility */
         IPlanetEjbc ejbc = new IPlanetEjbc(
@@ -258,12 +260,9 @@
             ejbc.setIasHomeDir(iashome);
         }
         if (getConfig().dtdLocations != null) {
-            for (Iterator i = getConfig().dtdLocations.iterator();
-                 i.hasNext();) {
-                EjbJar.DTDLocation dtdLocation =
-                    (EjbJar.DTDLocation) i.next();
+            for (DTDLocation dtdLocation : getConfig().dtdLocations) {
                 ejbc.registerDTD(dtdLocation.getPublicId(),
-                                 dtdLocation.getLocation());
+                    dtdLocation.getLocation());
             }
         }
 
@@ -290,7 +289,7 @@
                 int endOfCmp = descriptor.lastIndexOf('/');
                 String cmpDescriptor = descriptor.substring(endOfCmp + 1);
 
-                File   cmpFile = new File(baseDir, relativePath + cmpDescriptor);
+                File cmpFile = new File(baseDir, relativePath + cmpDescriptor);
                 if (!cmpFile.exists()) {
                     throw new BuildException("The CMP descriptor file ("
                             + cmpFile + ") could not be found.", getLocation());
@@ -298,7 +297,6 @@
                 files.put(descriptor, cmpFile);
             }
         }
-
         return files;
     }
 
@@ -311,7 +309,7 @@
      * @param ddPrefix not used
      */
     @Override
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
         ejbFiles.put(META_DIR + IAS_DD, new File(getConfig().descriptorDir,
                      getIasDescriptorName()));
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java
index 23116d3..7e5d8cc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,30 +20,32 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Date;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.StringTokenizer;
+import java.util.stream.Stream;
 
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 
+import org.apache.tools.ant.util.StringUtils;
 import org.xml.sax.AttributeList;
 import org.xml.sax.HandlerBase;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
-import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
-
 /**
  * Compiles EJB stubs and skeletons for the iPlanet Application
  * Server (iAS).  The class will read a standard EJB descriptor (as well as an
@@ -90,6 +92,7 @@
 
     /* Classpath used when the iAS ejbc is called */
     private String      classpath;
+    @SuppressWarnings("unused")
     private String[]    classpathElements;
 
     /* Options passed to the iAS ejbc */
@@ -110,7 +113,7 @@
      * (relative to the destination directory).  The value for the Hashtable is
      * a File object which reference the actual class file.
      */
-    private Hashtable   ejbFiles     = new Hashtable();
+    private Hashtable<String, File>   ejbFiles     = new Hashtable<>();
 
     /* Value of the display-name element read from the standard EJB descriptor */
     private String      displayName;
@@ -146,15 +149,11 @@
          * Parse the classpath into it's individual elements and store the
          * results in the "classpathElements" instance variable.
          */
-        List elements = new ArrayList();
         if (classpath != null) {
             StringTokenizer st = new StringTokenizer(classpath,
                                                         File.pathSeparator);
-            while (st.hasMoreTokens()) {
-                elements.add(st.nextToken());
-            }
-            classpathElements
-                    = (String[]) elements.toArray(new String[elements.size()]);
+            final int count = st.countTokens();
+            classpathElements = Collections.list(st).toArray(new String[count]);
         }
     }
 
@@ -213,7 +212,7 @@
      *
      * @return The list of EJB files processed by the ejbc utility.
      */
-    public Hashtable getEjbFiles() {
+    public Hashtable<String, File> getEjbFiles() {
         return ejbFiles;
     }
 
@@ -232,16 +231,8 @@
      * @return An array of CMP descriptors.
      */
     public String[] getCmpDescriptors() {
-        List returnList = new ArrayList();
-
-        EjbInfo[] ejbs = handler.getEjbs();
-
-        for (int i = 0; i < ejbs.length; i++) {
-            List descriptors = (List) ejbs[i].getCmpDescriptors();
-            returnList.addAll(descriptors);
-        }
-
-        return (String[]) returnList.toArray(new String[returnList.size()]);
+        return Stream.of(handler.getEjbs()).map(EjbInfo::getCmpDescriptors)
+            .flatMap(Collection::stream).toArray(String[]::new);
     }
 
     /**
@@ -261,7 +252,7 @@
         boolean     retainSource  = false;
         IPlanetEjbc ejbc;
 
-        if ((args.length < MIN_NUM_ARGS) || (args.length > MAX_NUM_ARGS)) {
+        if (args.length < MIN_NUM_ARGS || args.length > MAX_NUM_ARGS) {
             usage();
             return;
         }
@@ -270,13 +261,13 @@
         iasDescriptor = new File(args[args.length - 1]);
 
         for (int i = 0; i < args.length - 2; i++) {
-            if (args[i].equals("-classpath")) {
+            if ("-classpath".equals(args[i])) {
                 classpath = args[++i];
-            } else if (args[i].equals("-d")) {
+            } else if ("-d".equals(args[i])) {
                 destDirectory = new File(args[++i]);
-            } else if (args[i].equals("-debug")) {
+            } else if ("-debug".equals(args[i])) {
                 debug = true;
-            } else if (args[i].equals("-keepsource")) {
+            } else if ("-keepsource".equals(args[i])) {
                 retainSource = true;
             } else {
                 usage();
@@ -339,19 +330,19 @@
     private static void usage() {
         System.out.println("java org.apache.tools.ant.taskdefs.optional.ejb.IPlanetEjbc \\");
         System.out.println("  [OPTIONS] [EJB 1.1 descriptor] [iAS EJB descriptor]");
-        System.out.println("");
+        System.out.println();
         System.out.println("Where OPTIONS are:");
         System.out.println("  -debug -- for additional debugging output");
         System.out.println("  -keepsource -- to retain Java source files generated");
         System.out.println("  -classpath [classpath] -- classpath used for compilation");
         System.out.println("  -d [destination directory] -- directory for compiled classes");
-        System.out.println("");
+        System.out.println();
         System.out.println("If a classpath is not specified, the system classpath");
         System.out.println("will be used.  If a destination directory is not specified,");
         System.out.println("the current working directory will be used (classes will");
         System.out.println("still be placed in subfolders which correspond to their");
         System.out.println("package name).");
-        System.out.println("");
+        System.out.println();
         System.out.println("The EJB home interface, remote interface, and implementation");
         System.out.println("class must be found in the destination directory.  In");
         System.out.println("addition, the destination will look for the stubs and skeletons");
@@ -376,22 +367,17 @@
 
         EjbInfo[] ejbs = getEjbs(); // Returns list of EJBs for processing
 
-        for (int i = 0; i < ejbs.length; i++) {
+        for (EjbInfo ejb : ejbs) {
             log("EJBInfo...");
-            log(ejbs[i].toString());
+            log(ejb.toString());
         }
 
-        for (int i = 0; i < ejbs.length; i++) {
-            EjbInfo ejb = ejbs[i];
-
+        for (EjbInfo ejb : ejbs) {
             ejb.checkConfiguration(destDirectory);  // Throws EjbcException
 
             if (ejb.mustBeRecompiled(destDirectory)) {
                 log(ejb.getName() + " must be recompiled using ejbc.");
-
-                String[] arguments = buildArgumentList(ejb);
-                callEjbc(arguments);
-
+                callEjbc(buildArgumentList(ejb));
             } else {
                 log(ejb.getName() + " is up to date.");
             }
@@ -405,11 +391,6 @@
      */
     private void callEjbc(String[] arguments) {
 
-        /* Concatenate all of the command line arguments into a single String */
-        StringBuffer args = new StringBuffer();
-        for (int i = 0; i < arguments.length; i++) {
-            args.append(arguments[i]).append(" ");
-        }
 
         /* If an iAS home directory is specified, prepend it to the command */
         String command;
@@ -421,6 +402,9 @@
         }
         command += "ejbc ";
 
+        /* Concatenate all of the command line arguments into a single String */
+        String args = String.join(" ", arguments);
+
         log(command + args);
 
         /*
@@ -451,31 +435,31 @@
      */
     protected void checkConfiguration() throws EjbcException {
 
-        String msg = "";
+        StringBuilder msg = new StringBuilder();
 
         if (stdDescriptor == null) {
-            msg += "A standard XML descriptor file must be specified.  ";
+            msg.append("A standard XML descriptor file must be specified.  ");
         }
         if (iasDescriptor == null) {
-            msg += "An iAS-specific XML descriptor file must be specified.  ";
+            msg.append("An iAS-specific XML descriptor file must be specified.  ");
         }
         if (classpath == null) {
-            msg += "A classpath must be specified.    ";
+            msg.append("A classpath must be specified.    ");
         }
         if (parser == null) {
-            msg += "An XML parser must be specified.    ";
+            msg.append("An XML parser must be specified.    ");
         }
 
         if (destDirectory == null) {
-            msg += "A destination directory must be specified.  ";
+            msg.append("A destination directory must be specified.  ");
         } else if (!destDirectory.exists()) {
-            msg += "The destination directory specified does not exist.  ";
+            msg.append("The destination directory specified does not exist.  ");
         } else if (!destDirectory.isDirectory()) {
-            msg += "The destination specified is not a directory.  ";
+            msg.append("The destination specified is not a directory.  ");
         }
 
         if (msg.length() > 0) {
-            throw new EjbcException(msg);
+            throw new EjbcException(msg.toString());
         }
     }
 
@@ -491,18 +475,14 @@
      *                       XML descriptor (it may wrap another exception)
      */
     private EjbInfo[] getEjbs() throws IOException, SAXException {
-        EjbInfo[] ejbs = null;
 
         /*
          * The EJB information is gathered from the standard XML EJB descriptor
          * and the iAS-specific XML EJB descriptor using a SAX parser.
          */
-
         parser.parse(stdDescriptor, handler);
         parser.parse(iasDescriptor, handler);
-        ejbs = handler.getEjbs();
-
-        return ejbs;
+        return handler.getEjbs();
     }
 
     /**
@@ -515,7 +495,7 @@
      */
     private String[] buildArgumentList(EjbInfo ejb) {
 
-        List arguments = new ArrayList();
+        List<String> arguments = new ArrayList<>();
 
         /* OPTIONAL COMMAND LINE PARAMETERS */
 
@@ -559,7 +539,7 @@
         arguments.add(ejb.getImplementation().getQualifiedClassName());
 
         /* Convert the List into an Array and return it */
-        return (String[]) arguments.toArray(new String[arguments.size()]);
+        return arguments.toArray(new String[0]);
     }
 
     /**
@@ -584,6 +564,7 @@
      *
      */
     public class EjbcException extends Exception {
+        private static final long serialVersionUID = 1L;
 
         /**
          * Constructs an exception with the given descriptive message.
@@ -624,10 +605,10 @@
          * remote copies of these DTDs cannot be accessed.  The key for the Map
          * is the DTDs public ID and the value is the local location for the DTD
          */
-        private Map       resourceDtds = new HashMap();
-        private Map       fileDtds = new HashMap();
+        private Map<String, String>       resourceDtds = new HashMap<>();
+        private Map<String, String>       fileDtds = new HashMap<>();
 
-        private Map       ejbs = new HashMap();      // List of EJBs found in XML
+        private Map<String, EjbInfo>       ejbs = new HashMap<>();      // List of EJBs found in XML
         private EjbInfo   currentEjb;             // One item within the Map
         private boolean   iasDescriptor = false;  // Is doc iAS or EJB descriptor
 
@@ -653,7 +634,7 @@
          *         parsing.
          */
         public EjbInfo[] getEjbs() {
-            return (EjbInfo[]) ejbs.values().toArray(new EjbInfo[ejbs.size()]);
+            return ejbs.values().toArray(new EjbInfo[0]);
         }
 
         /**
@@ -662,6 +643,7 @@
          *
          * @return String display-name value.
          */
+        @SuppressWarnings("unused")
         public String getDisplayName() {
             return displayName;
         }
@@ -680,7 +662,7 @@
          */
         public void registerDTD(String publicID, String location) {
             log("Registering: " + location);
-            if ((publicID == null) || (location == null)) {
+            if (publicID == null || location == null) {
                 return;
             }
 
@@ -706,35 +688,30 @@
          * @param publicId The DTD's public identifier.
          * @param systemId The location of the DTD, as found in the XML document.
          */
+        @Override
         public InputSource resolveEntity(String publicId, String systemId)
                 throws SAXException {
             InputStream inputStream = null;
 
-
             try {
-
                 /* Search the resource Map and (if not found) file Map */
-
-                String location = (String) resourceDtds.get(publicId);
+                String location = resourceDtds.get(publicId);
                 if (location != null) {
                     inputStream
                         = ClassLoader.getSystemResource(location).openStream();
                 } else {
-                    location = (String) fileDtds.get(publicId);
+                    location = fileDtds.get(publicId);
                     if (location != null) {
                         // closed when the InputSource is closed
-                        inputStream = new FileInputStream(location); //NOSONAR
+                        inputStream = Files.newInputStream(Paths.get(location)); //NOSONAR
                     }
                 }
-            } catch (IOException e) {
-                return super.resolveEntity(publicId, systemId);
+            } catch (IOException ignored) {
             }
-
             if (inputStream == null) {
                 return super.resolveEntity(publicId, systemId);
-            } else {
-                return new InputSource(inputStream);
             }
+            return new InputSource(inputStream);
         }
 
         /**
@@ -745,6 +722,7 @@
          *             (if any).
          * @throws SAXException If the parser cannot process the document.
          */
+        @Override
         public void startElement(String name, AttributeList atts)
                 throws SAXException {
 
@@ -757,13 +735,13 @@
             /* A new element has started, so reset the text being captured */
             currentText = "";
 
-            if (currentLoc.equals("\\ejb-jar")) {
+            if ("\\ejb-jar".equals(currentLoc)) {
                 iasDescriptor = false;
-            } else if (currentLoc.equals("\\ias-ejb-jar")) {
+            } else if ("\\ias-ejb-jar".equals(currentLoc)) {
                 iasDescriptor = true;
             }
 
-            if ((name.equals("session")) || (name.equals("entity"))) {
+            if ("session".equals(name) || "entity".equals(name)) {
                 ejbType = name;
             }
         }
@@ -777,9 +755,9 @@
          * @param len The number of characters found in the document.
          * @throws SAXException If the parser cannot process the document.
          */
+        @Override
         public void characters(char[] ch, int start, int len)
                 throws SAXException {
-
             currentText += new String(ch).substring(start, start + len);
         }
 
@@ -789,6 +767,7 @@
          * @param name String name of the element.
          * @throws SAXException If the parser cannot process the document.
          */
+        @Override
         public void endElement(String name) throws SAXException {
 
             /*
@@ -824,30 +803,26 @@
          */
         private void stdCharacters(String value) {
 
-            if (currentLoc.equals("\\ejb-jar\\display-name")) {
+            if ("\\ejb-jar\\display-name".equals(currentLoc)) {
                 displayName = value;
                 return;
             }
 
             String base = "\\ejb-jar\\enterprise-beans\\" + ejbType;
 
-            if (currentLoc.equals(base + "\\ejb-name")) {
-                currentEjb = (EjbInfo) ejbs.get(value);
-                if (currentEjb == null) {
-                    currentEjb = new EjbInfo(value);
-                    ejbs.put(value, currentEjb);
-                }
-            } else if (currentLoc.equals(base + "\\home")) {
+            if ((base + "\\ejb-name").equals(currentLoc)) {
+                currentEjb = ejbs.computeIfAbsent(value, EjbInfo::new);
+            } else if ((base + "\\home").equals(currentLoc)) {
                 currentEjb.setHome(value);
-            } else if (currentLoc.equals(base + "\\remote")) {
+            } else if ((base + "\\remote").equals(currentLoc)) {
                 currentEjb.setRemote(value);
-            } else if (currentLoc.equals(base + "\\ejb-class")) {
+            } else if ((base + "\\ejb-class").equals(currentLoc)) {
                 currentEjb.setImplementation(value);
-            } else if (currentLoc.equals(base + "\\prim-key-class")) {
+            } else if ((base + "\\prim-key-class").equals(currentLoc)) {
                 currentEjb.setPrimaryKey(value);
-            } else if (currentLoc.equals(base + "\\session-type")) {
+            } else if ((base + "\\session-type").equals(currentLoc)) {
                 currentEjb.setBeantype(value);
-            } else if (currentLoc.equals(base + "\\persistence-type")) {
+            } else if ((base + "\\persistence-type").equals(currentLoc)) {
                 currentEjb.setCmp(value);
             }
         }
@@ -865,18 +840,14 @@
         private void iasCharacters(String value) {
             String base = "\\ias-ejb-jar\\enterprise-beans\\" + ejbType;
 
-            if (currentLoc.equals(base + "\\ejb-name")) {
-                currentEjb = (EjbInfo) ejbs.get(value);
-                if (currentEjb == null) {
-                    currentEjb = new EjbInfo(value);
-                    ejbs.put(value, currentEjb);
-                }
-            } else if (currentLoc.equals(base + "\\iiop")) {
+            if ((base + "\\ejb-name").equals(currentLoc)) {
+                currentEjb = ejbs.computeIfAbsent(value, EjbInfo::new);
+            } else if ((base + "\\iiop").equals(currentLoc)) {
                 currentEjb.setIiop(value);
-            } else if (currentLoc.equals(base + "\\failover-required")) {
+            } else if ((base + "\\failover-required").equals(currentLoc)) {
                 currentEjb.setHasession(value);
-            } else if (currentLoc.equals(base + "\\persistence-manager"
-                                              + "\\properties-file-location")) {
+            } else if ((base
+                + "\\persistence-manager\\properties-file-location").equals(currentLoc)) {
                 currentEjb.addCmpDescriptor(value);
             }
         }
@@ -888,16 +859,16 @@
      *
      */
     private class EjbInfo {
-        private String     name;              // EJB's display name
-        private Classname  home;              // EJB's home interface name
-        private Classname  remote;            // EJB's remote interface name
-        private Classname  implementation;      // EJB's implementation class
-        private Classname  primaryKey;        // EJB's primary key class
-        private String  beantype = "entity";  // or "stateful" or "stateless"
-        private boolean cmp       = false;      // Does this EJB support CMP?
-        private boolean iiop      = false;      // Does this EJB support IIOP?
-        private boolean hasession = false;      // Does this EJB require failover?
-        private List<String> cmpDescriptors = new ArrayList<String>();  // CMP descriptor list
+        private String    name;              // EJB's display name
+        private Classname home;              // EJB's home interface name
+        private Classname remote;            // EJB's remote interface name
+        private Classname implementation;    // EJB's implementation class
+        private Classname primaryKey;        // EJB's primary key class
+        private String  beantype = "entity"; // or "stateful" or "stateless"
+        private boolean cmp       = false;   // Does this EJB support CMP?
+        private boolean iiop      = false;   // Does this EJB support IIOP?
+        private boolean hasession = false;   // Does this EJB require failover?
+        private List<String> cmpDescriptors = new ArrayList<>();  // CMP descriptor list
 
         /**
          * Construct a new EJBInfo object with the given name.
@@ -919,9 +890,8 @@
             if (name == null) {
                 if (implementation == null) {
                     return "[unnamed]";
-                } else {
-                    return implementation.getClassName();
                 }
+                return implementation.getClassName();
             }
             return name;
         }
@@ -978,6 +948,7 @@
             this.primaryKey = primaryKey;
         }
 
+        @SuppressWarnings("unused")
         public Classname getPrimaryKey() {
             return primaryKey;
         }
@@ -995,7 +966,7 @@
         }
 
         public void setCmp(String cmp) {
-            setCmp(cmp.equals("Container"));
+            setCmp("Container".equals(cmp));
         }
 
         public boolean getCmp() {
@@ -1007,7 +978,7 @@
         }
 
         public void setIiop(String iiop) {
-            setIiop(iiop.equals("true"));
+            setIiop(Boolean.parseBoolean(iiop));
         }
 
         public boolean getIiop() {
@@ -1019,7 +990,7 @@
         }
 
         public void setHasession(String hasession) {
-            setHasession(hasession.equals("true"));
+            setHasession(Boolean.parseBoolean(hasession));
         }
 
         public boolean getHasession() {
@@ -1030,7 +1001,7 @@
             cmpDescriptors.add(descriptor);
         }
 
-        public List getCmpDescriptors() {
+        public List<String> getCmpDescriptors() {
             return cmpDescriptors;
         }
 
@@ -1047,53 +1018,53 @@
 
             /* Check that the specified instance variables are valid */
             if (home == null) {
-                throw new EjbcException("A home interface was not found "
-                            + "for the " + name + " EJB.");
+                throw new EjbcException(
+                    "A home interface was not found for the " + name + " EJB.");
             }
             if (remote == null) {
-                throw new EjbcException("A remote interface was not found "
-                            + "for the " + name + " EJB.");
+                throw new EjbcException(
+                    "A remote interface was not found for the " + name
+                        + " EJB.");
             }
             if (implementation == null) {
-                throw new EjbcException("An EJB implementation class was not "
-                            + "found for the " + name + " EJB.");
+                throw new EjbcException(
+                    "An EJB implementation class was not found for the " + name
+                        + " EJB.");
             }
 
-            if ((!beantype.equals(ENTITY_BEAN))
-                        && (!beantype.equals(STATELESS_SESSION))
-                        && (!beantype.equals(STATEFUL_SESSION))) {
-                throw new EjbcException("The beantype found (" + beantype + ") "
-                            + "isn't valid in the " + name + " EJB.");
+            if (!beantype.equals(ENTITY_BEAN)
+                && !beantype.equals(STATELESS_SESSION)
+                && !beantype.equals(STATEFUL_SESSION)) {
+                throw new EjbcException("The beantype found (" + beantype
+                    + ") isn't valid in the " + name + " EJB.");
             }
 
-            if (cmp && (!beantype.equals(ENTITY_BEAN))) {
-                System.out.println("CMP stubs and skeletons may not be generated"
-                    + " for a Session Bean -- the \"cmp\" attribute will be"
-                    + " ignoredfor the " + name + " EJB.");
+            if (cmp && !beantype.equals(ENTITY_BEAN)) {
+                System.out.println(
+                    "CMP stubs and skeletons may not be generated for a Session Bean -- the \"cmp\" attribute will be ignoredfor the "
+                        + name + " EJB.");
             }
 
-            if (hasession && (!beantype.equals(STATEFUL_SESSION))) {
-                System.out.println("Highly available stubs and skeletons may "
-                    + "only be generated for a Stateful Session Bean -- the "
-                    + "\"hasession\" attribute will be ignored for the "
-                    + name + " EJB.");
+            if (hasession && !beantype.equals(STATEFUL_SESSION)) {
+                System.out.println(
+                    "Highly available stubs and skeletons may only be generated for a Stateful Session Bean"
+                        + "-- the \"hasession\" attribute will be ignored for the "
+                        + name + " EJB.");
             }
 
             /* Check that the EJB "source" classes all exist */
             if (!remote.getClassFile(buildDir).exists()) {
                 throw new EjbcException("The remote interface "
-                            + remote.getQualifiedClassName() + " could not be "
-                            + "found.");
+                    + remote.getQualifiedClassName() + " could not be found.");
             }
             if (!home.getClassFile(buildDir).exists()) {
                 throw new EjbcException("The home interface "
-                            + home.getQualifiedClassName() + " could not be "
-                            + "found.");
+                    + home.getQualifiedClassName() + " could not be found.");
             }
             if (!implementation.getClassFile(buildDir).exists()) {
                 throw new EjbcException("The EJB implementation class "
-                            + implementation.getQualifiedClassName() + " could "
-                            + "not be found.");
+                    + implementation.getQualifiedClassName()
+                    + " could not be found.");
             }
         }
 
@@ -1139,9 +1110,8 @@
             remoteFile = remote.getClassFile(buildDir);
             modified = remoteFile.lastModified();
             if (modified == -1) {
-                System.out.println("The class "
-                                + remote.getQualifiedClassName() + " couldn't "
-                                + "be found on the classpath");
+                System.out.println("The class " + remote.getQualifiedClassName()
+                    + " couldn't be found on the classpath");
                 return -1;
             }
             latestModified = modified;
@@ -1150,9 +1120,8 @@
             homeFile = home.getClassFile(buildDir);
             modified = homeFile.lastModified();
             if (modified == -1) {
-                System.out.println("The class "
-                                + home.getQualifiedClassName() + " couldn't be "
-                                + "found on the classpath");
+                System.out.println("The class " + home.getQualifiedClassName()
+                    + " couldn't be found on the classpath");
                 return -1;
             }
             latestModified = Math.max(latestModified, modified);
@@ -1162,9 +1131,9 @@
                 pkFile = primaryKey.getClassFile(buildDir);
                 modified = pkFile.lastModified();
                 if (modified == -1) {
-                    System.out.println("The class "
-                                    + primaryKey.getQualifiedClassName() + "couldn't be "
-                                    + "found on the classpath");
+                    System.out.println(
+                        "The class " + primaryKey.getQualifiedClassName()
+                            + "couldn't be found on the classpath");
                     return -1;
                 }
                 latestModified = Math.max(latestModified, modified);
@@ -1225,7 +1194,7 @@
          */
         private long destClassesModified(File destDir) {
             String[] classnames = classesToGenerate(); // List of all stubs & skels
-            long destClassesModified = new Date().getTime(); // Earliest mod time
+            long destClassesModified = Instant.now().toEpochMilli(); // Earliest mod time
             boolean allClassesFound  = true;           // Has each been found?
 
             /*
@@ -1233,7 +1202,8 @@
              * determine (if all exist) which file has the most recent timestamp
              */
             for (String classname : classnames) {
-                String pathToClass = classname.replace('.', File.separatorChar) + ".class";
+                String pathToClass =
+                        classname.replace('.', File.separatorChar) + ".class";
                 File classFile = new File(destDir, pathToClass);
 
                 /*
@@ -1252,7 +1222,7 @@
                 }
             }
 
-            return (allClassesFound) ? destClassesModified : -1;
+            return allClassesFound ? destClassesModified : -1;
         }
 
         /**
@@ -1316,22 +1286,23 @@
          *
          * @return A String representing the EjbInfo instance.
          */
+        @Override
         public String toString() {
-            String s = "EJB name: " + name
-                        + "\n\r              home:      " + home
-                        + "\n\r              remote:    " + remote
-                        + "\n\r              impl:      " + implementation
-                        + "\n\r              primaryKey: " + primaryKey
-                        + "\n\r              beantype:  " + beantype
-                        + "\n\r              cmp:       " + cmp
-                        + "\n\r              iiop:      " + iiop
-                        + "\n\r              hasession: " + hasession;
+            StringBuilder s = new StringBuilder("EJB name: " + name
+                    + "\n\r              home:      " + home
+                    + "\n\r              remote:    " + remote
+                    + "\n\r              impl:      " + implementation
+                    + "\n\r              primaryKey: " + primaryKey
+                    + "\n\r              beantype:  " + beantype
+                    + "\n\r              cmp:       " + cmp
+                    + "\n\r              iiop:      " + iiop
+                    + "\n\r              hasession: " + hasession);
 
             for (String cmpDescriptor : cmpDescriptors) {
-                s += "\n\r              CMP Descriptor: " + cmpDescriptor;
+                s.append("\n\r              CMP Descriptor: ").append(cmpDescriptor);
             }
 
-            return s;
+            return s.toString();
         }
 
     } // End of EjbInfo inner class
@@ -1431,6 +1402,7 @@
          *
          * @return String representing the fully qualified class name.
          */
+        @Override
         public String toString() {
             return getQualifiedClassName();
         }
@@ -1462,18 +1434,16 @@
          * Reads text from the input stream and redirects it to standard output
          * using a separate thread.
          */
+        @Override
         public void run() {
-            BufferedReader reader = new BufferedReader(
-                                            new InputStreamReader(stream));
-            String text;
-            try {
+            try (BufferedReader reader =
+                new BufferedReader(new InputStreamReader(stream))) {
+                String text;
                 while ((text = reader.readLine()) != null) {
                     System.out.println(text);
                 }
             } catch (IOException e) {
                 e.printStackTrace(); //NOSONAR
-            } finally {
-                FileUtils.close(reader);
             }
         }
     }  // End of RedirectOutput inner class
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbcTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbcTask.java
index 9aca1cb..1d57561 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbcTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbcTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -188,6 +188,7 @@
      * Does the work.
      * @throws BuildException if there is a problem.
      */
+    @Override
     public void execute() throws BuildException {
         checkConfiguration();
 
@@ -202,41 +203,42 @@
     private void checkConfiguration() throws BuildException {
 
         if (ejbdescriptor == null) {
-            String msg = "The standard EJB descriptor must be specified using "
-                            + "the \"ejbdescriptor\" attribute.";
+            String msg =
+                "The standard EJB descriptor must be specified using the \"ejbdescriptor\" attribute.";
             throw new BuildException(msg, getLocation());
         }
-        if ((!ejbdescriptor.exists()) || (!ejbdescriptor.isFile())) {
+        if (!ejbdescriptor.exists() || !ejbdescriptor.isFile()) {
             String msg = "The standard EJB descriptor (" + ejbdescriptor
-                            + ") was not found or isn't a file.";
+                + ") was not found or isn't a file.";
             throw new BuildException(msg, getLocation());
         }
 
         if (iasdescriptor == null) {
-            String msg = "The iAS-speific XML descriptor must be specified using"
-                            + " the \"iasdescriptor\" attribute.";
+            String msg =
+                "The iAS-speific XML descriptor must be specified using the \"iasdescriptor\" attribute.";
             throw new BuildException(msg, getLocation());
         }
-        if ((!iasdescriptor.exists()) || (!iasdescriptor.isFile())) {
+        if (!iasdescriptor.exists() || !iasdescriptor.isFile()) {
             String msg = "The iAS-specific XML descriptor (" + iasdescriptor
-                            + ") was not found or isn't a file.";
+                + ") was not found or isn't a file.";
             throw new BuildException(msg, getLocation());
         }
 
         if (dest == null) {
-            String msg = "The destination directory must be specified using "
-                            + "the \"dest\" attribute.";
+            String msg =
+                "The destination directory must be specified using the \"dest\" attribute.";
             throw new BuildException(msg, getLocation());
         }
-        if ((!dest.exists()) || (!dest.isDirectory())) {
-            String msg = "The destination directory (" + dest + ") was not "
-                            + "found or isn't a directory.";
+        if (!dest.exists() || !dest.isDirectory()) {
+            String msg = "The destination directory (" + dest
+                + ") was not found or isn't a directory.";
             throw new BuildException(msg, getLocation());
         }
 
-        if ((iashome != null) && (!iashome.isDirectory())) {
-            String msg = "If \"iashome\" is specified, it must be a valid "
-                            + "directory (it was set to " + iashome + ").";
+        if (iashome != null && !iashome.isDirectory()) {
+            String msg =
+                "If \"iashome\" is specified, it must be a valid directory (it was set to "
+                    + iashome + ").";
             throw new BuildException(msg, getLocation());
         }
     }
@@ -248,21 +250,13 @@
      * @throws BuildException If the parser cannot be created or configured.
      */
     private SAXParser getParser() throws BuildException {
-
-        SAXParser saxParser = null;
         try {
             SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
             saxParserFactory.setValidating(true);
-            saxParser = saxParserFactory.newSAXParser();
-        } catch (SAXException e) {
-            String msg = "Unable to create a SAXParser: " + e.getMessage();
-            throw new BuildException(msg, e, getLocation());
-        } catch (ParserConfigurationException e) {
-            String msg = "Unable to create a SAXParser: " + e.getMessage();
-            throw new BuildException(msg, e, getLocation());
+            return saxParserFactory.newSAXParser();
+        } catch (SAXException | ParserConfigurationException e) {
+            throw new BuildException("Unable to create a SAXParser: " + e.getMessage(), e, getLocation());
         }
-
-        return saxParser;
     }
 
     /**
@@ -284,21 +278,23 @@
         if (iashome != null) {
             ejbc.setIasHomeDir(iashome);
         }
-
         try {
             ejbc.execute();
         } catch (IOException e) {
-            String msg = "An IOException occurred while trying to read the XML "
-                            + "descriptor file: " + e.getMessage();
-            throw new BuildException(msg, e, getLocation());
+            throw new BuildException(
+                "An IOException occurred while trying to read the XML descriptor file: "
+                    + e.getMessage(),
+                e, getLocation());
         } catch (SAXException e) {
-            String msg = "A SAXException occurred while trying to read the XML "
-                            + "descriptor file: " + e.getMessage();
-            throw new BuildException(msg, e, getLocation());
+            throw new BuildException(
+                "A SAXException occurred while trying to read the XML descriptor file: "
+                    + e.getMessage(),
+                e, getLocation());
         } catch (IPlanetEjbc.EjbcException e) {
-            String msg = "An exception occurred while trying to run the ejbc "
-                            + "utility: " + e.getMessage();
-            throw new BuildException(msg, e, getLocation());
+            throw new BuildException(
+                "An exception occurred while trying to run the ejbc utility: "
+                    + e.getMessage(),
+                e, getLocation());
         }
     }
 
@@ -309,13 +305,9 @@
      * @return Path The classpath to be used for EJBc.
      */
     private Path getClasspath() {
-        Path cp = null;
         if (classpath == null) {
-            cp = (new Path(getProject())).concatSystemClasspath("last");
-        } else {
-            cp = classpath.concatSystemClasspath("ignore");
+            return new Path(getProject()).concatSystemClasspath("last");
         }
-
-        return cp;
+        return classpath.concatSystemClasspath("ignore");
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/InnerClassFilenameFilter.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/InnerClassFilenameFilter.java
index e92d9879..c9ab8c6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/InnerClassFilenameFilter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/InnerClassFilenameFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,11 +44,9 @@
      * @param filename the filename to filter on.
      * @return true if the filename is an inner class of the base class.
      */
+    @Override
     public boolean accept(File dir, String filename) {
-        if ((filename.lastIndexOf(".") != filename.lastIndexOf(".class"))
-            || (filename.indexOf(baseClassName + "$") != 0)) {
-            return false;
-        }
-        return true;
+        return filename.lastIndexOf('.') == filename.lastIndexOf(".class")
+            && filename.indexOf(baseClassName + "$") == 0;
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JbossDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JbossDeploymentTool.java
index e6f8192..21a0f2f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JbossDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JbossDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -53,14 +53,14 @@
      * @param ejbFiles the hashtable of files to populate.
      * @param ddPrefix the prefix to use.
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    @Override
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
         File jbossDD = new File(getConfig().descriptorDir, ddPrefix + JBOSS_DD);
         if (jbossDD.exists()) {
             ejbFiles.put(META_DIR + JBOSS_DD, jbossDD);
         } else {
-            log("Unable to locate jboss deployment descriptor. "
-                + "It was expected to be in " + jbossDD.getPath(),
-                Project.MSG_WARN);
+            log("Unable to locate jboss deployment descriptor. It was expected to be in "
+                + jbossDD.getPath(), Project.MSG_WARN);
             return;
         }
         String descriptorFileName = JBOSS_CMP10D;
@@ -73,8 +73,7 @@
         if (jbossCMPD.exists()) {
             ejbFiles.put(META_DIR + descriptorFileName, jbossCMPD);
         } else {
-            log("Unable to locate jboss cmp descriptor. "
-                + "It was expected to be in "
+            log("Unable to locate jboss cmp descriptor. It was expected to be in "
                 + jbossCMPD.getPath(), Project.MSG_VERBOSE);
         }
     }
@@ -83,15 +82,15 @@
      * Get the vendor specific name of the Jar that will be output. The modification date
      * of this jar will be checked against the dependent bean classes.
      */
+    @Override
     File getVendorOutputJarFile(String baseName) {
         if (getDestDir() == null && getParent().getDestdir() == null) {
             throw new BuildException("DestDir not specified");
         }
         if (getDestDir() == null) {
             return new File(getParent().getDestdir(), baseName + jarSuffix);
-        } else {
-            return new File(getDestDir(), baseName + jarSuffix);
         }
+        return new File(getDestDir(), baseName + jarSuffix);
     }
 
     /**
@@ -101,6 +100,7 @@
      *                        valid
      * @since ant 1.6
      */
+    @Override
     public void validateConfigured() throws BuildException {
     }
 
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 07ca610..768e9cb 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,9 +19,10 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
+import java.nio.file.Files;
+import java.util.Arrays;
 import java.util.Hashtable;
-
+import java.util.List;
 import javax.xml.parsers.SAXParser;
 
 import org.apache.tools.ant.AntClassLoader;
@@ -329,6 +330,7 @@
     /* ------------- */
 
     /** {@inheritDoc}. */
+    @Override
     public void processDescriptor(String aDescriptorName, SAXParser saxParser) {
 
         descriptorName = aDescriptorName;
@@ -346,7 +348,8 @@
     }
 
     /** {@inheritDoc}. */
-    protected void writeJar(String baseName, File jarfile, Hashtable ejbFiles, String publicId)
+    @Override
+    protected void writeJar(String baseName, File jarfile, Hashtable<String, File> ejbFiles, String publicId)
     throws BuildException {
 
         // create the generic jar first
@@ -366,10 +369,11 @@
     }
 
     /** {@inheritDoc}. */
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    @Override
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
 
-    // JOnAS-specific descriptor deployment
-    jonasDescriptorName = getJonasDescriptorName();
+        // JOnAS-specific descriptor deployment
+        jonasDescriptorName = getJonasDescriptorName();
         File jonasDD = new File(getConfig().descriptorDir, jonasDescriptorName);
 
         if (jonasDD.exists()) {
@@ -381,6 +385,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     protected File getVendorOutputJarFile(String baseName) {
         return new File(getDestDir(), baseName + suffix);
     }
@@ -458,6 +463,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     protected String getJarBaseName(String descriptorFileName) {
 
         String baseName = null;
@@ -499,6 +505,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     protected void registerKnownDTDs(DescriptorHandler handler) {
         handler.registerDTD(EJB_JAR_1_1_PUBLIC_ID,
                     jonasroot + File.separator + "xml" + File.separator + EJB_JAR_1_1_DTD);
@@ -518,15 +525,12 @@
      * @param ejbFiles the hashtable.
      */
     private void addGenICGeneratedFiles(
-        File genericJarFile, Hashtable ejbFiles) {
-        Java genicTask = null;    // GenIC task
-        String genicClass = null; // GenIC class (3 are supported for various
-                                  // versions
+        File genericJarFile, Hashtable<String, File> ejbFiles) {
         if (nogenic) {
             return;
         }
 
-        genicTask = new Java(getTask());
+        Java genicTask = new Java(getTask()); // GenIC task
         genicTask.setTaskName("genic");
         genicTask.setFork(true);
 
@@ -553,13 +557,8 @@
         genicTask.createArg().setValue("-d");
         genicTask.createArg().setFile(outputdir);
 
-        // work around a bug of GenIC 2.5
-        String key;
-        File f;
-        Enumeration keys = ejbFiles.keys();
-        while (keys.hasMoreElements()) {
-            key = (String) keys.nextElement();
-            f = new File(outputdir + File.separator + key);
+        for (String key : ejbFiles.keySet()) {
+            File f = new File(outputdir + File.separator + key);
             f.getParentFile().mkdirs();
         }
         log("Worked around a bug of GenIC 2.5.", Project.MSG_VERBOSE);
@@ -581,15 +580,18 @@
         log("Using classpath: " + classpath.toString(), Project.MSG_VERBOSE);
         genicTask.setClasspath(classpath);
 
+        String genicClass; // GenIC class (3 are supported for various
+        // versions
+        // work around a bug of GenIC 2.5
+
         // class name (search in the classpath provided for the ejbjar element)
         genicClass = getGenicClassName(classpath);
         if (genicClass == null) {
             log("Cannot find GenIC class in classpath.", Project.MSG_ERR);
             throw new BuildException("GenIC class not found, please check the classpath.");
-        } else {
-            log("Using '" + genicClass + "' GenIC class.", Project.MSG_VERBOSE);
-            genicTask.setClassname(genicClass);
         }
+        log("Using '" + genicClass + "' GenIC class.", Project.MSG_VERBOSE);
+        genicTask.setClassname(genicClass);
 
         // keepgenerated
         if (keepgenerated) {
@@ -613,13 +615,13 @@
         }
 
         // javacopts
-        if (javacopts != null && !javacopts.equals("")) {
+        if (javacopts != null && !javacopts.isEmpty()) {
             genicTask.createArg().setValue("-javacopts");
             genicTask.createArg().setLine(javacopts);
         }
 
         // rmicopts
-        if (rmicopts != null && !rmicopts.equals("")) {
+        if (rmicopts != null && !rmicopts.isEmpty()) {
             genicTask.createArg().setValue("-rmicopts");
             genicTask.createArg().setLine(rmicopts);
         }
@@ -681,10 +683,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 +722,6 @@
                     + "' not found in classpath.",
                     Project.MSG_VERBOSE);
             }
-        } finally {
-            if (cl != null) {
-                cl.cleanup();
-            }
         }
         return null;
     }
@@ -737,33 +732,38 @@
      * @param saxParser          not used.
      * @throws BuildException if there is an error.
      */
+    @Override
     protected void checkConfiguration(String descriptorFileName,
                       SAXParser saxParser) throws BuildException {
 
         // jonasroot
         if (jonasroot == null) {
-            throw new BuildException("The jonasroot attribut is not set.");
-        } else if (!jonasroot.isDirectory()) {
-            throw new BuildException("The jonasroot attribut '" + jonasroot
-                + "' is not a valid directory.");
+            throw new BuildException("The jonasroot attribute is not set.");
+        }
+        if (!jonasroot.isDirectory()) {
+            throw new BuildException(
+                "The jonasroot attribute '%s' is not a valid directory.",
+                jonasroot);
         }
 
         // orb
-        if (orb != null && !orb.equals(RMI_ORB) && !orb.equals(JEREMIE_ORB)
-            && !orb.equals(DAVID_ORB)) {
-            throw new BuildException("The orb attribut '" + orb
-                + "' is not valid (must be either "
-                + RMI_ORB + ", " + JEREMIE_ORB + " or " + DAVID_ORB + ").");
+        final List<String> validOrbs =
+            Arrays.asList(RMI_ORB, JEREMIE_ORB, DAVID_ORB);
+
+        if (orb != null && !validOrbs.contains(orb)) {
+            throw new BuildException(
+                "The orb attribute '%s' is not valid (must be one of %s.", orb,
+                validOrbs);
         }
 
         // additionalargs
-        if (additionalargs != null && additionalargs.equals("")) {
-            throw new BuildException("Empty additionalargs attribut.");
+        if (additionalargs != null && additionalargs.isEmpty()) {
+            throw new BuildException("Empty additionalargs attribute.");
         }
 
         // javac
-        if (javac != null && javac.equals("")) {
-            throw new BuildException("Empty javac attribut.");
+        if (javac != null && javac.isEmpty()) {
+            throw new BuildException("Empty javac attribute.");
         }
     }
 
@@ -778,26 +778,19 @@
      * @throws BuildException if a temp directory cannot be created.
      */
     private File createTempDir() throws IOException {
-        File tmpDir = File.createTempFile("genic", null, null);
-        tmpDir.delete();
-        if (!tmpDir.mkdir()) {
-            throw new IOException("Cannot create the temporary directory '" + tmpDir + "'.");
-        }
-        return tmpDir;
+        return Files.createTempDirectory("genic").toFile();
     }
 
     /**
-     * Delete a file. If the file is a directory, delete recursivly all the
+     * Delete a file. If the file is a directory, delete recursively all the
      * files inside.
      *
      * @param aFile file to delete.
      */
     private void deleteAllFiles(File aFile) {
         if (aFile.isDirectory()) {
-            File[] someFiles = aFile.listFiles();
-
-            for (int i = 0; i < someFiles.length; i++) {
-                deleteAllFiles(someFiles[i]);
+            for (File child : aFile.listFiles()) {
+                deleteAllFiles(child);
             }
         }
         aFile.delete();
@@ -811,22 +804,19 @@
      * @param rootDir the current sub-directory to scan.
      * @param hashtable the hashtable where to add the files.
      */
-    private void addAllFiles(File file, String rootDir, Hashtable hashtable) {
-
+    private void addAllFiles(File file, String rootDir, Hashtable<String, File> hashtable) {
         if (!file.exists()) {
             throw new IllegalArgumentException();
         }
-
         String newRootDir;
         if (file.isDirectory()) {
-            File[] files = file.listFiles();
-            for (int i = 0; i < files.length; i++) {
-                if (rootDir.length() > 0) {
-                    newRootDir = rootDir + File.separator + files[i].getName();
+            for (File child : file.listFiles()) {
+                if (rootDir.isEmpty()) {
+                    newRootDir = child.getName();
                 } else {
-                    newRootDir = files[i].getName();
+                    newRootDir = rootDir + File.separator + child.getName();
                 }
-                addAllFiles(files[i], newRootDir, hashtable);
+                addAllFiles(child, newRootDir, hashtable);
             }
         } else {
             hashtable.put(rootDir, file);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/OrionDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/OrionDeploymentTool.java
index a737803..340d434 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/OrionDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/OrionDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,7 +27,7 @@
  * ejb jar file. Orion only requires one additional file orion-ejb-jar.xml
  * and does not require any additional compilation.
  *
- * @since Ant 1.9.10
+ * @since Ant 1.10.2
  * @see EjbJar#createOrion
  */
 
@@ -35,7 +35,7 @@
 
     protected static final String ORION_DD = "orion-ejb-jar.xml";
 
-    /** Instance variable that stores the suffix for the jboss jarfile. */
+    /** Instance variable that stores the suffix for the JBoss jarfile. */
     private String jarSuffix = ".jar";
 
     /**
@@ -45,7 +45,7 @@
      * @param ejbFiles Hashtable&lt;String, File&gt;
      * @param baseName String
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String baseName) {
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String baseName) {
         String ddPrefix = usingBaseJarName() ? "" : baseName;
         File orionDD = new File(getConfig().descriptorDir, ddPrefix + ORION_DD);
 
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..018156b 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,17 +18,19 @@
 package org.apache.tools.ant.taskdefs.optional.ejb;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Enumeration;
+import java.nio.file.Files;
 import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
 
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -38,17 +40,18 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Java;
 import org.apache.tools.ant.types.Environment;
+import org.apache.tools.ant.types.Environment.Variable;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.FileUtils;
 import org.xml.sax.InputSource;
 
 /**
     The weblogic element is used to control the weblogic.ejbc compiler for
-    generating weblogic EJB jars. Prior to Ant 1.3, the method of locating CMP
+    generating WebLogic EJB jars. Prior to Ant 1.3, the method of locating CMP
     descriptors was to use the ejbjar naming convention. So if your ejb-jar was
-    called, Customer-ejb-jar.xml, your weblogic descriptor was called Customer-
+    called, Customer-ejb-jar.xml, your WebLogic descriptor was called Customer-
     weblogic-ejb-jar.xml and your CMP descriptor had to be Customer-weblogic-cmp-
-    rdbms-jar.xml. In addition, the &lt;type-storage&gt; element in the weblogic
+    rdbms-jar.xml. In addition, the &lt;type-storage&gt; element in the WebLogic
     descriptor had to be set to the standard name META-INF/weblogic-cmp-rdbms-
     jar.xml, as that is where the CMP descriptor was mapped to in the generated
     jar.
@@ -60,23 +63,23 @@
     /** EJB20 id */
     public static final String PUBLICID_EJB20
          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
-    /** Weblogic 5.1.0 id */
+    /** WebLogic 5.1.0 id */
     public static final String PUBLICID_WEBLOGIC_EJB510
          = "-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN";
-    /** Weblogic 6.0.0 id */
+    /** WebLogic 6.0.0 id */
     public static final String PUBLICID_WEBLOGIC_EJB600
          = "-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN";
-    /** Weblogic 7.0.0 id */
+    /** WebLogic 7.0.0 id */
     public static final String PUBLICID_WEBLOGIC_EJB700
          = "-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN";
 
-    /** Weblogic 5.1 dtd location */
+    /** WebLogic 5.1 dtd location */
     protected static final String DEFAULT_WL51_EJB11_DTD_LOCATION
          = "/weblogic/ejb/deployment/xml/ejb-jar.dtd";
-    /** Weblogic 6.0 ejb 1.1 dtd location */
+    /** WebLogic 6.0 ejb 1.1 dtd location */
     protected static final String DEFAULT_WL60_EJB11_DTD_LOCATION
          = "/weblogic/ejb20/dd/xml/ejb11-jar.dtd";
-    /** Weblogic 6.0 ejb 2.0 dtd location */
+    /** WebLogic 6.0 ejb 2.0 dtd location */
     protected static final String DEFAULT_WL60_EJB20_DTD_LOCATION
          = "/weblogic/ejb20/dd/xml/ejb20-jar.dtd";
 
@@ -100,13 +103,13 @@
     /** File utilities instance for copying jars */
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-    /** Instance variable that stores the suffix for the weblogic jarfile. */
+    /** Instance variable that stores the suffix for the WebLogic jarfile. */
     private String jarSuffix = ".jar";
 
-    /** Instance variable that stores the location of the weblogic DTD file. */
+    /** Instance variable that stores the location of the WebLogic DTD file. */
     private String weblogicDTD;
 
-    /** Instance variable that stores the location of the ejb 1.1 DTD file. */
+    /** Instance variable that stores the location of the EJB 1.1 DTD file. */
     private String ejb11DTD;
 
     /** Instance variable that determines whether generic ejb jars are kept. */
@@ -114,7 +117,7 @@
 
     /**
      * Instance variable that stores the fully qualified classname of the
-     * weblogic EJBC compiler
+     * WebLogic EJBC compiler
      */
     private String ejbcClass = null;
 
@@ -137,11 +140,11 @@
     /** Indicates if the old CMP location convention is to be used.  */
     private boolean newCMP = false;
 
-    /** The classpath to the weblogic classes. */
+    /** The classpath to the WebLogic classes. */
     private Path wlClasspath = null;
 
     /** System properties for the JVM. */
-    private Vector sysprops = new Vector();
+    private List<Variable> sysprops = new Vector<>();
 
     /**
      * The weblogic.StdoutSeverityLevel to use when running the JVM that
@@ -160,9 +163,8 @@
         sysprops.add(sysp);
     }
 
-
     /**
-     * Get the classpath to the weblogic classpaths.
+     * Get the classpath to the WebLogic classpaths.
      * @return the classpath to configure.
      */
     public Path createWLClasspath() {
@@ -182,12 +184,11 @@
         this.outputDir = outputDir;
     }
 
-
     /**
      * Optional classpath to WL6.0.
-     * Weblogic 6.0 will give a warning if the home and remote interfaces
+     * WebLogic 6.0 will give a warning if the home and remote interfaces
      * of a bean are on the system classpath used to run weblogic.ejbc.
-     * In that case, the standard weblogic classes should be set with
+     * In that case, the standard WebLogic classes should be set with
      * this attribute (or equivalent nested element) and the
      * home and remote interfaces located with the standard classpath
      * attribute.
@@ -197,7 +198,6 @@
         this.wlClasspath = wlClasspath;
     }
 
-
     /**
      * The compiler (switch <code>-compiler</code>) to use; optional.
      * This allows for the selection of a different compiler
@@ -214,7 +214,6 @@
         this.compiler = compiler;
     }
 
-
     /**
      * Set the rebuild flag to false to only update changes in the jar rather
      * than rerunning ejbc; optional, default true.
@@ -230,7 +229,6 @@
         this.alwaysRebuild = rebuild;
     }
 
-
     /**
      * Sets the weblogic.StdoutSeverityLevel to use when running the JVM that
      * executes ejbc; optional. Set to 16 to avoid the warnings about EJB Home and
@@ -241,7 +239,6 @@
         this.jvmDebugLevel = jvmDebugLevel;
     }
 
-
     /**
      * Get the debug level.
      * @return the jvm debug level (may be null).
@@ -250,10 +247,8 @@
         return jvmDebugLevel;
     }
 
-
-
     /**
-     * Setter used to store the suffix for the generated weblogic jar file.
+     * Setter used to store the suffix for the generated WebLogic jar file.
      *
      * @param inString the string to use as the suffix.
      */
@@ -261,7 +256,6 @@
         this.jarSuffix = inString;
     }
 
-
     /**
      * controls whether the generic file used as input to
      * ejbc is retained; defaults to false
@@ -272,19 +266,17 @@
         this.keepGeneric = inValue;
     }
 
-
     /**
-     * Controls whether weblogic will keep the generated Java
+     * Controls whether WebLogic will keep the generated Java
      * files used to build the class files added to the
      * jar. This can be useful when debugging; default is false.
      *
      * @param inValue either 'true' or 'false'
      */
     public void setKeepgenerated(String inValue) {
-        this.keepgenerated = Boolean.valueOf(inValue).booleanValue();
+        this.keepgenerated = Boolean.parseBoolean(inValue);
     }
 
-
     /**
      * Any optional extra arguments pass to the weblogic.ejbc
      * tool.
@@ -294,9 +286,8 @@
         this.additionalArgs = args;
     }
 
-
     /**
-     * Set any additional arguments to pass to the weblogic JVM; optional.
+     * Set any additional arguments to pass to the WebLogic JVM; optional.
      * @param args the arguments to be passed to the JVM
      */
     public void setJvmargs(String args) {
@@ -307,7 +298,7 @@
      * Set the classname of the ejbc compiler;  optional
      * Normally ejbjar determines
      * the appropriate class based on the DTD used for the EJB. The EJB 2.0 compiler
-     * featured in weblogic 6 has, however, been deprecated in version 7. When
+     * featured in WebLogic 6 has, however, been deprecated in version 7. When
      * using with version 7 this attribute should be set to
      * &quot;weblogic.ejbc&quot; to avoid the deprecation warning.
      * @param ejbcClass the name of the class to use.
@@ -316,7 +307,6 @@
         this.ejbcClass = ejbcClass;
     }
 
-
     /**
      * Get the ejbc compiler class.
      * @return the name of the ejbc compiler class.
@@ -325,10 +315,9 @@
         return ejbcClass;
     }
 
-
     /**
      * <b>Deprecated</b>. Defines the location of the ejb-jar DTD in
-     *  the weblogic class hierarchy. Should not be needed, and the
+     *  the WebLogic class hierarchy. Should not be needed, and the
      * nested &lt;dtd&gt; element is recommended when it is.
      *
      * @param inString the string to use as the DTD location.
@@ -337,10 +326,9 @@
         setEJBdtd(inString);
     }
 
-
     /**
-     * <b>Deprecated</b>. Defines the location of weblogic DTD in
-     *  the weblogic class hierarchy. Should not be needed, and the
+     * <b>Deprecated</b>. Defines the location of WebLogic DTD in
+     *  the WebLogic class hierarchy. Should not be needed, and the
      * nested &lt;dtd&gt; element is recommended when it is.
      *
      * @param inString the string to use as the DTD location.
@@ -349,10 +337,9 @@
         this.weblogicDTD = inString;
     }
 
-
     /**
      * <b>Deprecated</b>. Defines the location of Sun's EJB DTD in
-     *  the weblogic class hierarchy. Should not be needed, and the
+     *  the WebLogic class hierarchy. Should not be needed, and the
      * nested &lt;dtd&gt; element is recommended when it is.
      *
      * @param inString the string to use as the DTD location.
@@ -361,7 +348,6 @@
         this.ejb11DTD = inString;
     }
 
-
     /**
      * Set the value of the oldCMP scheme. This is an antonym for newCMP
      * @ant.attribute ignore="true'
@@ -371,16 +357,15 @@
         this.newCMP = !oldCMP;
     }
 
-
     /**
      * If this is set to true, the new method for locating
      * CMP descriptors will be used; optional, default false.
      * <P>
      * The old CMP scheme locates the
-     * weblogic CMP descriptor based on the naming convention where the
-     * weblogic CMP file is expected to be named with the bean name as the
+     * WebLogic CMP descriptor based on the naming convention where the
+     * WebLogic CMP file is expected to be named with the bean name as the
      * prefix. Under this scheme the name of the CMP descriptor does not match
-     * the name actually used in the main weblogic EJB descriptor. Also,
+     * the name actually used in the main WebLogic EJB descriptor. Also,
      * descriptors which contain multiple CMP references could not be used.
      * @param newCMP a <code>boolean</code> value.
      */
@@ -388,7 +373,6 @@
         this.newCMP = newCMP;
     }
 
-
     /**
      * Do not EJBC the jar after it has been put together;
      * optional, default false
@@ -398,11 +382,11 @@
         this.noEJBC = noEJBC;
     }
 
-
     /**
      * Register the DTDs.
      * @param handler the handler to use.
      */
+    @Override
     protected void registerKnownDTDs(DescriptorHandler handler) {
         // register all the known DTDs
         handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL51_EJB11_DTD_LOCATION);
@@ -411,29 +395,23 @@
         handler.registerDTD(PUBLICID_EJB20, DEFAULT_WL60_EJB20_DTD_LOCATION);
     }
 
-
     /**
-     * Get the weblogic descriptor handler.
+     * Get the WebLogic descriptor handler.
      * @param srcDir the source directory.
      * @return the descriptor.
      */
     protected DescriptorHandler getWeblogicDescriptorHandler(final File srcDir) {
-        DescriptorHandler handler =
-            new DescriptorHandler(getTask(), srcDir) {
-                protected void processElement() {
-                    if (currentElement.equals("type-storage")) {
-                        // Get the filename of vendor specific descriptor
-                        String fileNameWithMETA = currentText;
-                        //trim the META_INF\ off of the file name
-                        String fileName
-                             = fileNameWithMETA.substring(META_DIR.length(),
-                            fileNameWithMETA.length());
-                        File descriptorFile = new File(srcDir, fileName);
-
-                        ejbFiles.put(fileNameWithMETA, descriptorFile);
-                    }
+        DescriptorHandler handler = new DescriptorHandler(getTask(), srcDir) {
+            @Override
+            protected void processElement() {
+                if ("type-storage".equals(currentElement)) {
+                    // Get the filename of vendor specific descriptor
+                    // trim the META_INF\ off of the file name
+                    ejbFiles.put(currentText, new File(srcDir,
+                            currentText.substring(META_DIR.length())));
                 }
-            };
+            }
+        };
 
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL51_DTD_LOCATION);
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL60_51_DTD_LOCATION);
@@ -442,52 +420,45 @@
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, weblogicDTD);
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, weblogicDTD);
 
-        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
-            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
-
-            handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
-        }
+        getConfig().dtdLocations.forEach(l -> handler.registerDTD(l.getPublicId(), l.getLocation()));
         return handler;
     }
 
-
     /**
      * Add any vendor specific files which should be included in the EJB Jar.
      * @param ejbFiles the hash table to be populated.
      * @param ddPrefix the prefix to use.
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    @Override
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
         File weblogicDD = new File(getConfig().descriptorDir, ddPrefix + WL_DD);
 
         if (weblogicDD.exists()) {
             ejbFiles.put(META_DIR + WL_DD,
                 weblogicDD);
         } else {
-            log("Unable to locate weblogic deployment descriptor. "
-                + "It was expected to be in "
+            log("Unable to locate weblogic deployment descriptor. It was expected to be in "
                 + weblogicDD.getPath(), Project.MSG_WARN);
             return;
         }
 
         if (!newCMP) {
             log("The old method for locating CMP files has been DEPRECATED.", Project.MSG_VERBOSE);
-            log("Please adjust your weblogic descriptor and set "
-                + "newCMP=\"true\" to use the new CMP descriptor "
-                + "inclusion mechanism. ", Project.MSG_VERBOSE);
-            // The the weblogic cmp deployment descriptor
+            log("Please adjust your weblogic descriptor and set newCMP=\"true\" to use the new CMP descriptor inclusion mechanism. ",
+                Project.MSG_VERBOSE);
+            // The the WebLogic CMP deployment descriptor
             File weblogicCMPDD = new File(getConfig().descriptorDir, ddPrefix + WL_CMP_DD);
 
             if (weblogicCMPDD.exists()) {
-                ejbFiles.put(META_DIR + WL_CMP_DD,
-                    weblogicCMPDD);
+                ejbFiles.put(META_DIR + WL_CMP_DD, weblogicCMPDD);
             }
         } else {
-            // now that we have the weblogic descriptor, we parse the file
+            // now that we have the WebLogic descriptor, we parse the file
             // to find other descriptors needed to deploy the bean.
             // this could be the weblogic-cmp-rdbms.xml or any other O/R
             // mapping tool descriptors.
             try {
-                File ejbDescriptor = (File) ejbFiles.get(META_DIR + EJB_DD);
+                File ejbDescriptor = ejbFiles.get(META_DIR + EJB_DD);
                 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
 
                 saxParserFactory.setValidating(true);
@@ -496,37 +467,29 @@
                 DescriptorHandler handler
                     = getWeblogicDescriptorHandler(ejbDescriptor.getParentFile());
 
-                saxParser.parse(new InputSource
-                    (new FileInputStream(weblogicDD)),
-                        handler);
-
-                Hashtable ht = handler.getFiles();
-                Enumeration e = ht.keys();
-
-                while (e.hasMoreElements()) {
-                    String key = (String) e.nextElement();
-
-                    ejbFiles.put(key, ht.get(key));
+                try (InputStream in = Files.newInputStream(weblogicDD.toPath())) {
+                    saxParser.parse(new InputSource(in), handler);
                 }
+                ejbFiles.putAll(handler.getFiles());
             } catch (Exception e) {
-                String msg = "Exception while adding Vendor specific files: " + e.toString();
-
-                throw new BuildException(msg, e);
+                throw new BuildException(
+                    "Exception while adding Vendor specific files: "
+                        + e.toString(),
+                    e);
             }
         }
     }
 
-
     /**
      * Get the vendor specific name of the Jar that will be output. The
      * modification date of this jar will be checked against the dependent
      * bean classes.
      */
+    @Override
     File getVendorOutputJarFile(String baseName) {
         return new File(getDestDir(), baseName + jarSuffix);
     }
 
-
     /**
      * Helper method invoked by execute() for each WebLogic jar to be built.
      * Encapsulates the logic of constructing a java task for calling
@@ -537,7 +500,6 @@
      *      jarfile.
      */
     private void buildWeblogicJar(File sourceJar, File destJar, String publicId) {
-        Java javaTask = null;
 
         if (noEJBC) {
             try {
@@ -554,17 +516,11 @@
         String ejbcClassName = ejbcClass;
 
         try {
-            javaTask = new Java(getTask());
+            Java javaTask = new Java(getTask());
             javaTask.setTaskName("ejbc");
 
             javaTask.createJvmarg().setLine(additionalJvmArgs);
-            if (!(sysprops.isEmpty())) {
-                for (Enumeration en = sysprops.elements(); en.hasMoreElements();) {
-                    Environment.Variable entry
-                        = (Environment.Variable) en.nextElement();
-                    javaTask.addSysproperty(entry);
-                }
-            }
+            sysprops.forEach(javaTask::addSysproperty);
 
             if (getJvmDebugLevel() != null) {
                 javaTask.createJvmarg().setLine(" -Dweblogic.StdoutSeverityLevel=" + jvmDebugLevel);
@@ -594,20 +550,18 @@
                 String buildCompiler
                     = getTask().getProject().getProperty("build.compiler");
 
-                if (buildCompiler != null && buildCompiler.equals("jikes")) {
+                if ("jikes".equals(buildCompiler)) {
                     javaTask.createArg().setValue("-compiler");
                     javaTask.createArg().setValue("jikes");
                 }
-            } else {
-                if (!compiler.equals(DEFAULT_COMPILER)) {
-                    javaTask.createArg().setValue("-compiler");
-                    javaTask.createArg().setLine(compiler);
-                }
+            } else if (!DEFAULT_COMPILER.equals(compiler)) {
+                javaTask.createArg().setValue("-compiler");
+                javaTask.createArg().setLine(compiler);
             }
 
             Path combinedClasspath = getCombinedClasspath();
             if (wlClasspath != null && combinedClasspath != null
-                 && combinedClasspath.toString().trim().length() > 0) {
+                    && !combinedClasspath.toString().trim().isEmpty()) {
                 javaTask.createArg().setValue("-classpath");
                 javaTask.createArg().setPath(combinedClasspath);
             }
@@ -638,14 +592,11 @@
             }
         } catch (Exception e) {
             // Have to catch this because of the semantics of calling main()
-            String msg = "Exception while calling " + ejbcClassName
-                + ". Details: " + e.toString();
-
-            throw new BuildException(msg, e);
+            throw new BuildException("Exception while calling " + ejbcClassName
+                + ". Details: " + e.toString(), e);
         }
     }
 
-
     /**
      * Method used to encapsulate the writing of the JAR file. Iterates over
      * the filenames/java.io.Files in the Hashtable stored on the instance
@@ -656,7 +607,8 @@
      * @param publicId the id to use.
      * @throws BuildException if there is a problem.
      */
-    protected void writeJar(String baseName, File jarFile, Hashtable files,
+    @Override
+    protected void writeJar(String baseName, File jarFile, Hashtable<String, File> files,
                             String publicId) throws BuildException {
         // need to create a generic jar first.
         File genericJarFile = super.getVendorOutputJarFile(baseName);
@@ -673,38 +625,37 @@
         }
     }
 
-
     /**
      * Called to validate that the tool parameters have been configured.
      * @throws BuildException if there is an error.
      */
+    @Override
     public void validateConfigured() throws BuildException {
         super.validateConfigured();
     }
 
-
     /**
-     * Helper method to check to see if a weblogic EBJ1.1 jar needs to be
+     * Helper method to check to see if a WebLogic EJB 1.1 jar needs to be
      * rebuilt using ejbc. Called from writeJar it sees if the "Bean" classes
      * are the only thing that needs to be updated and either updates the Jar
-     * with the Bean classfile or returns true, saying that the whole weblogic
-     * jar needs to be regened with ejbc. This allows faster build times for
+     * with the Bean classfile or returns true, saying that the whole WebLogic
+     * jar needs to be regenerated with ejbc. This allows faster build times for
      * working developers. <p>
      *
-     * The way weblogic ejbc works is it creates wrappers for the publicly
+     * The way WebLogic ejbc works is it creates wrappers for the publicly
      * defined methods as they are exposed in the remote interface. If the
      * actual bean changes without changing the the method signatures then
      * only the bean classfile needs to be updated and the rest of the
-     * weblogic jar file can remain the same. If the Interfaces, ie. the
+     * WebLogic jar file can remain the same. If the Interfaces, ie. the
      * method signatures change or if the xml deployment descriptors changed,
      * the whole jar needs to be rebuilt with ejbc. This is not strictly true
      * for the xml files. If the JNDI name changes then the jar doesn't have to
      * be rebuild, but if the resources references change then it does. At
-     * this point the weblogic jar gets rebuilt if the xml files change at
+     * this point the WebLogic jar gets rebuilt if the xml files change at
      * all.
      *
      * @param genericJarFile java.io.File The generic jar file.
-     * @param weblogicJarFile java.io.File The weblogic jar file to check to
+     * @param weblogicJarFile java.io.File The WebLogic jar file to check to
      *      see if it needs to be rebuilt.
      * @return true if the jar needs to be rebuilt.
      */
@@ -721,86 +672,70 @@
         try {
             log("Checking if weblogic Jar needs to be rebuilt for jar " + weblogicJarFile.getName(),
                 Project.MSG_VERBOSE);
-            // Only go forward if the generic and the weblogic file both exist
+            // Only go forward if the generic and the WebLogic file both exist
             if (genericJarFile.exists() && genericJarFile.isFile()
                  && weblogicJarFile.exists() && weblogicJarFile.isFile()) {
                 //open jar files
                 genericJar = new JarFile(genericJarFile);
                 wlJar = new JarFile(weblogicJarFile);
 
-                Hashtable genericEntries = new Hashtable();
-                Hashtable wlEntries = new Hashtable();
-                Hashtable replaceEntries = new Hashtable();
+                Map<String, JarEntry> replaceEntries = new HashMap<>();
 
                 //get the list of generic jar entries
-                for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
-                    JarEntry je = (JarEntry) e.nextElement();
+                Map<String, JarEntry> genericEntries = genericJar.stream()
+                        .collect(Collectors.toMap(je -> je.getName().replace('\\', '/'),
+                                je -> je, (a, b) -> b));
+                // get the list of WebLogic jar entries
+                Map<String, JarEntry> wlEntries = wlJar.stream().collect(Collectors.toMap(ZipEntry::getName,
+                        je -> je, (a, b) -> b));
 
-                    genericEntries.put(je.getName().replace('\\', '/'), je);
-                }
-                //get the list of weblogic jar entries
-                for (Enumeration e = wlJar.entries(); e.hasMoreElements();) {
-                    JarEntry je = (JarEntry) e.nextElement();
-
-                    wlEntries.put(je.getName(), je);
-                }
-
-                //Cycle Through generic and make sure its in weblogic
+                // Cycle through generic and make sure its in WebLogic
                 genericLoader = getClassLoaderFromJar(genericJarFile);
 
-                for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
-                    String filepath = (String) e.nextElement();
-
-                    if (wlEntries.containsKey(filepath)) {
-                        // File name/path match
-
-                        // Check files see if same
-                        JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
-                        JarEntry wlEntry = (JarEntry) wlEntries.get(filepath);
-
-                        if ((genericEntry.getCrc() != wlEntry.getCrc())
-                            || (genericEntry.getSize() != wlEntry.getSize())) {
-
-                            if (genericEntry.getName().endsWith(".class")) {
-                                //File are different see if its an object or an interface
-                                String classname
-                                    = genericEntry.getName()
-                                    .replace(File.separatorChar, '.')
-                                    .replace('/', '.');
-
-                                classname = classname.substring(0, classname.lastIndexOf(".class"));
-
-                                Class genclass = genericLoader.loadClass(classname);
-
-                                if (genclass.isInterface()) {
-                                    //Interface changed   rebuild jar.
-                                    log("Interface " + genclass.getName()
-                                        + " has changed", Project.MSG_VERBOSE);
-                                    rebuild = true;
-                                    break;
-                                } else {
-                                    //Object class Changed   update it.
-                                    replaceEntries.put(filepath, genericEntry);
-                                }
-                            } else {
-                                // is it the manifest. If so ignore it
-                                if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
-                                    //File other then class changed   rebuild
-                                    log("Non class file " + genericEntry.getName()
-                                        + " has changed", Project.MSG_VERBOSE);
-                                    rebuild = true;
-                                    break;
-                                }
-                            }
-                        }
-                    } else {
+                for (String filepath : genericEntries.keySet()) {
+                    if (!wlEntries.containsKey(filepath)) {
                         // a file doesn't exist rebuild
-
                         log("File " + filepath + " not present in weblogic jar",
                             Project.MSG_VERBOSE);
                         rebuild = true;
                         break;
                     }
+                    // File name/path match
+                    // Check files see if same
+                    JarEntry genericEntry = genericEntries.get(filepath);
+                    JarEntry wlEntry = wlEntries.get(filepath);
+
+                    if (genericEntry.getCrc() != wlEntry.getCrc()
+                        || genericEntry.getSize() != wlEntry.getSize()) {
+
+                        if (genericEntry.getName().endsWith(".class")) {
+                            //File are different see if its an object or an interface
+                            String classname = genericEntry.getName()
+                                    .replace(File.separatorChar, '.')
+                                    .replace('/', '.');
+
+                            classname = classname.substring(0, classname.lastIndexOf(".class"));
+
+                            Class<?> genclass = genericLoader.loadClass(classname);
+
+                            if (genclass.isInterface()) {
+                                //Interface changed   rebuild jar.
+                                log("Interface " + genclass.getName()
+                                    + " has changed", Project.MSG_VERBOSE);
+                                rebuild = true;
+                                break;
+                            }
+                            //Object class Changed   update it.
+                            replaceEntries.put(filepath, genericEntry);
+                        } else if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
+                            // it is not the manifest, otherwise we'd ignore it
+                            // File other then class changed   rebuild
+                            log("Non class file " + genericEntry.getName()
+                                + " has changed", Project.MSG_VERBOSE);
+                            rebuild = true;
+                            break;
+                        }
+                    }
                 }
 
                 if (!rebuild) {
@@ -810,16 +745,11 @@
                         newWLJarFile.delete();
                     }
 
-                    newJarStream = new JarOutputStream(new FileOutputStream(newWLJarFile));
+                    newJarStream = new JarOutputStream(Files.newOutputStream(newWLJarFile.toPath()));
                     newJarStream.setLevel(0);
 
-                    //Copy files from old weblogic jar
-                    for (Enumeration e = wlEntries.elements(); e.hasMoreElements();) {
-                        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
-                        int bytesRead;
-                        InputStream is;
-                        JarEntry je = (JarEntry) e.nextElement();
-
+                    // Copy files from old WebLogic jar
+                    for (JarEntry je : wlEntries.values()) {
                         if (je.getCompressedSize() == -1
                             || je.getCompressedSize() == je.getSize()) {
                             newJarStream.setLevel(0);
@@ -827,20 +757,23 @@
                             newJarStream.setLevel(JAR_COMPRESS_LEVEL);
                         }
 
+                        InputStream is;
                         // Update with changed Bean class
                         if (replaceEntries.containsKey(je.getName())) {
                             log("Updating Bean class from generic Jar "
                                 + je.getName(), Project.MSG_VERBOSE);
                             // Use the entry from the generic jar
-                            je = (JarEntry) replaceEntries.get(je.getName());
+                            je = replaceEntries.get(je.getName());
                             is = genericJar.getInputStream(je);
                         } else {
-                            //use fle from original weblogic jar
+                            //use file from original WebLogic jar
 
                             is = wlJar.getInputStream(je);
                         }
                         newJarStream.putNextEntry(new JarEntry(je.getName()));
 
+                        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+                        int bytesRead;
                         while ((bytesRead = is.read(buffer)) != -1) {
                             newJarStream.write(buffer, 0, bytesRead);
                         }
@@ -866,24 +799,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);
@@ -892,13 +811,12 @@
                     rebuild = true;
                 }
             }
-            if (genericLoader != null
-                && genericLoader instanceof AntClassLoader) {
+            if (genericLoader instanceof AntClassLoader) {
+                @SuppressWarnings("resource")
                 AntClassLoader loader = (AntClassLoader) genericLoader;
                 loader.cleanup();
             }
         }
-
         return rebuild;
     }
 
@@ -921,7 +839,6 @@
         if (classpath != null) {
             lookupPath.append(classpath);
         }
-
         return getTask().getProject().createClassLoader(lookupPath);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicTOPLinkDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicTOPLinkDeploymentTool.java
index 0752bbe..0571f84 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicTOPLinkDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicTOPLinkDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,7 @@
 import org.apache.tools.ant.Project;
 
 /**
- * Deployment tool for Weblogic TOPLink.
+ * Deployment tool for WebLogic TOPLink.
  */
 public class WeblogicTOPLinkDeploymentTool extends WeblogicDeploymentTool {
 
@@ -62,14 +62,17 @@
      * @param srcDir the source file.
      * @return the descriptor handler.
      */
+    @Override
     protected DescriptorHandler getDescriptorHandler(File srcDir) {
         DescriptorHandler handler = super.getDescriptorHandler(srcDir);
         if (toplinkDTD != null) {
-            handler.registerDTD("-//The Object People, Inc.//"
-                + "DTD TOPLink for WebLogic CMP 2.5.1//EN", toplinkDTD);
+            handler.registerDTD(
+                "-//The Object People, Inc.//DTD TOPLink for WebLogic CMP 2.5.1//EN",
+                toplinkDTD);
         } else {
-            handler.registerDTD("-//The Object People, Inc.//"
-                + "DTD TOPLink for WebLogic CMP 2.5.1//EN", TL_DTD_LOC);
+            handler.registerDTD(
+                "-//The Object People, Inc.//DTD TOPLink for WebLogic CMP 2.5.1//EN",
+                TL_DTD_LOC);
         }
         return handler;
     }
@@ -80,21 +83,20 @@
      * @param ejbFiles the hashtable to add files to.
      * @param ddPrefix the prefix to use.
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
+    @Override
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
         super.addVendorFiles(ejbFiles, ddPrefix);
         // Then the toplink deployment descriptor
 
         // Setup a naming standard here?.
 
-
         File toplinkDD = new File(getConfig().descriptorDir, ddPrefix + toplinkDescriptor);
 
         if (toplinkDD.exists()) {
             ejbFiles.put(META_DIR + toplinkDescriptor,
                          toplinkDD);
         } else {
-            log("Unable to locate toplink deployment descriptor. "
-                + "It was expected to be in "
+            log("Unable to locate toplink deployment descriptor. It was expected to be in "
                 + toplinkDD.getPath(), Project.MSG_WARN);
         }
     }
@@ -103,11 +105,12 @@
      * Called to validate that the tool parameters have been configured.
      * @throws BuildException if there is an error.
      */
+    @Override
     public void validateConfigured() throws BuildException {
         super.validateConfigured();
         if (toplinkDescriptor == null) {
-            throw new BuildException("The toplinkdescriptor attribute must "
-                + "be specified");
+            throw new BuildException(
+                "The toplinkdescriptor attribute must be specified");
         }
     }
 }
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 52668bd..8200601 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,17 @@
 package org.apache.tools.ant.taskdefs.optional.ejb;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Enumeration;
+import java.nio.file.Files;
 import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -37,9 +39,9 @@
 import org.apache.tools.ant.util.FileUtils;
 
 /**
- * Websphere deployment tool that augments the ejbjar task.
- * Searches for the websphere specific deployment descriptors and
- * adds them to the final ejb jar file. Websphere has two specific descriptors for session
+ * WebSphere deployment tool that augments the ejbjar task.
+ * Searches for the WebSphere specific deployment descriptors and
+ * adds them to the final ejb jar file. WebSphere has two specific descriptors for session
  * beans:
  * <ul>
  *    <li>ibm-ejb-jar-bnd.xmi</li>
@@ -53,7 +55,7 @@
  * In terms of WebSphere, the generation of container code and stubs is
  * called <code>deployment</code>. This step can be performed by the websphere
  * element as part of the jar generation process. If the switch
- * <code>ejbdeploy</code> is on, the ejbdeploy tool from the websphere toolset
+ * <code>ejbdeploy</code> is on, the ejbdeploy tool from the WebSphere toolset
  * is called for every ejb-jar. Unfortunately, this step only works, if you
  * use the ibm jdk. Otherwise, the rmic (called by ejbdeploy) throws a
  * ClassFormatError. Be sure to switch ejbdeploy off, if run ant with
@@ -78,7 +80,7 @@
 
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-    /** Instance variable that stores the suffix for the websphere jarfile. */
+    /** Instance variable that stores the suffix for the WebSphere jarfile. */
     private String jarSuffix = ".jar";
 
     /** Instance variable that stores the location of the ejb 1.1 DTD file. */
@@ -95,7 +97,7 @@
     /** Indicates if the old CMP location convention is to be used. */
     private boolean newCMP = false;
 
-    /** The classpath to the websphere classes. */
+    /** The classpath to the WebSphere classes. */
     private Path wasClasspath = null;
 
     /** The DB Vendor name, the EJB is persisted against */
@@ -134,12 +136,12 @@
     /** the scratchdir for the ejbdeploy operation */
     private String tempdir = "_ejbdeploy_temp";
 
-    /** the home directory for websphere */
+    /** the home directory for WebSphere */
     private File websphereHome;
 
     /**
-     * Get the classpath to the websphere classpaths.
-     * @return the websphere classpath.
+     * Get the classpath to the WebSphere classpaths.
+     * @return the WebSphere classpath.
      */
     public Path createWASClasspath() {
         if (wasClasspath == null) {
@@ -148,16 +150,14 @@
         return wasClasspath.createPath();
     }
 
-
     /**
-     * Set the websphere classpath.
-     * @param wasClasspath the websphere classpath.
+     * Set the WebSphere classpath.
+     * @param wasClasspath the WebSphere classpath.
      */
     public void setWASClasspath(Path wasClasspath) {
         this.wasClasspath = wasClasspath;
     }
 
-
     /** Sets the DB Vendor for the Entity Bean mapping; optional.
      * <p>
      * Valid options can be obtained by running the following command:
@@ -177,7 +177,6 @@
         this.dbVendor = dbvendor;
     }
 
-
     /**
      * Sets the name of the Database to create; optional.
      *
@@ -187,7 +186,6 @@
         this.dbName = dbName;
     }
 
-
     /**
      * Sets the name of the schema to create; optional.
      *
@@ -197,7 +195,6 @@
         this.dbSchema = dbSchema;
     }
 
-
     /**
      * Flag, default false, to only generate the deployment
      * code, do not run RMIC or Javac
@@ -208,7 +205,6 @@
         this.codegen = codegen;
     }
 
-
     /**
      * Flag, default true, to only output error messages.
      *
@@ -218,7 +214,6 @@
         this.quiet = quiet;
     }
 
-
     /**
      * Flag to disable the validation steps; optional, default false.
      *
@@ -228,7 +223,6 @@
         this.novalidate = novalidate;
     }
 
-
     /**
      * Flag to disable warning and informational messages; optional, default false.
      *
@@ -238,7 +232,6 @@
         this.nowarn = nowarn;
     }
 
-
     /**
      * Flag to disable informational messages; optional, default false.
      *
@@ -248,7 +241,6 @@
         this.noinform = noinform;
     }
 
-
     /**
      * Flag to enable internal tracing when set, optional, default false.
      *
@@ -276,7 +268,6 @@
         use35MappingRules = attr;
     }
 
-
     /**
      * Set the rebuild flag to false to only update changes in the jar rather
      * than rerunning ejbdeploy; optional, default true.
@@ -286,7 +277,6 @@
         this.alwaysRebuild = rebuild;
     }
 
-
     /**
      * String value appended to the basename of the deployment
      * descriptor to create the filename of the WebLogic EJB
@@ -297,7 +287,6 @@
         this.jarSuffix = inString;
     }
 
-
     /**
      * This controls whether the generic file used as input to
      * ejbdeploy is retained; optional, default false.
@@ -307,7 +296,6 @@
         this.keepGeneric = inValue;
     }
 
-
     /**
      * Decide, whether ejbdeploy should be called or not;
      * optional, default true.
@@ -318,7 +306,6 @@
         this.ejbdeploy = ejbdeploy;
     }
 
-
     /**
      * Setter used to store the location of the Sun's Generic EJB DTD. This
      * can be a file on the system or a resource on the classpath.
@@ -329,7 +316,6 @@
         this.ejb11DTD = inString;
     }
 
-
     /**
      * Set the value of the oldCMP scheme. This is an antonym for newCMP
      * @ant.attribute ignore="true"
@@ -339,13 +325,12 @@
         this.newCMP = !oldCMP;
     }
 
-
     /**
      * Set the value of the newCMP scheme. The old CMP scheme locates the
-     * websphere CMP descriptor based on the naming convention where the
-     * websphere CMP file is expected to be named with the bean name as the
+     * WebSphere CMP descriptor based on the naming convention where the
+     * WebSphere CMP file is expected to be named with the bean name as the
      * prefix. Under this scheme the name of the CMP descriptor does not match
-     * the name actually used in the main websphere EJB descriptor. Also,
+     * the name actually used in the main WebSphere EJB descriptor. Also,
      * descriptors which contain multiple CMP references could not be used.
      * @param newCMP a <code>boolean</code> value.
      */
@@ -353,7 +338,6 @@
         this.newCMP = newCMP;
     }
 
-
     /**
      * The directory, where ejbdeploy will write temporary files;
      * optional, defaults to '_ejbdeploy_temp'.
@@ -363,24 +347,18 @@
         this.tempdir = tempdir;
     }
 
-
     /** {@inheritDoc}. */
+    @Override
     protected DescriptorHandler getDescriptorHandler(File srcDir) {
         DescriptorHandler handler = new DescriptorHandler(getTask(), srcDir);
         // register all the DTDs, both the ones that are known and
         // any supplied by the user
         handler.registerDTD(PUBLICID_EJB11, ejb11DTD);
 
-        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
-            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
-
-            handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
-        }
-
+        getConfig().dtdLocations.forEach(l -> handler.registerDTD(l.getPublicId(), l.getLocation()));
         return handler;
     }
 
-
     /**
      * Get a description handler.
      * @param srcDir the source directory.
@@ -389,15 +367,12 @@
     protected DescriptorHandler getWebsphereDescriptorHandler(final File srcDir) {
         DescriptorHandler handler =
             new DescriptorHandler(getTask(), srcDir) {
+                @Override
                 protected void processElement() {
                 }
             };
 
-        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
-            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
-
-            handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
-        }
+        getConfig().dtdLocations.forEach(l -> handler.registerDTD(l.getPublicId(), l.getLocation()));
         return handler;
     }
 
@@ -407,9 +382,10 @@
      * @param ejbFiles a hashtable entryname -&gt; file.
      * @param baseName a prefix to use.
      */
-    protected void addVendorFiles(Hashtable ejbFiles, String baseName) {
+    @Override
+    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String baseName) {
 
-        String ddPrefix = (usingBaseJarName() ? "" : baseName);
+        String ddPrefix = usingBaseJarName() ? "" : baseName;
         String dbPrefix = (dbVendor == null) ? "" : dbVendor + "-";
 
         // Get the Extensions document
@@ -419,8 +395,7 @@
             ejbFiles.put(META_DIR + WAS_EXT,
                 websphereEXT);
         } else {
-            log("Unable to locate websphere extensions. "
-                + "It was expected to be in "
+            log("Unable to locate websphere extensions. It was expected to be in "
                 + websphereEXT.getPath(), Project.MSG_VERBOSE);
         }
 
@@ -430,17 +405,15 @@
             ejbFiles.put(META_DIR + WAS_BND,
                 websphereBND);
         } else {
-            log("Unable to locate websphere bindings. "
-                + "It was expected to be in "
+            log("Unable to locate websphere bindings. It was expected to be in "
                 + websphereBND.getPath(), Project.MSG_VERBOSE);
         }
 
         if (!newCMP) {
             log("The old method for locating CMP files has been DEPRECATED.",
                 Project.MSG_VERBOSE);
-            log("Please adjust your websphere descriptor and set "
-                + "newCMP=\"true\" to use the new CMP descriptor "
-                + "inclusion mechanism. ", Project.MSG_VERBOSE);
+            log("Please adjust your websphere descriptor and set newCMP=\"true\" to use the new CMP descriptor inclusion mechanism. ",
+                Project.MSG_VERBOSE);
         } else {
             // We attempt to put in the MAP and Schema files of CMP beans
             try {
@@ -468,25 +441,24 @@
                 }
                 // There is nothing else to see here...keep moving sonny
             } catch (Exception e) {
-                String msg = "Exception while adding Vendor specific files: "
-                    + e.toString();
-
-                throw new BuildException(msg, e);
+                throw new BuildException(
+                    "Exception while adding Vendor specific files: "
+                        + e.toString(),
+                    e);
             }
         }
     }
 
-
     /**
      * Get the vendor specific name of the Jar that will be output. The
      * modification date of this jar will be checked against the dependent
      * bean classes.
      */
+    @Override
     File getVendorOutputJarFile(String baseName) {
         return new File(getDestDir(), baseName + jarSuffix);
     }
 
-
     /**
      * Gets the options for the EJB Deploy operation
      *
@@ -494,7 +466,7 @@
      */
     protected String getOptions() {
         // Set the options
-        StringBuffer options = new StringBuffer();
+        StringBuilder options = new StringBuilder();
 
         if (dbVendor != null) {
             options.append(" -dbvendor ").append(dbVendor);
@@ -542,14 +514,13 @@
         return options.toString();
     }
 
-
     /**
-     * Helper method invoked by execute() for each websphere jar to be built.
+     * Helper method invoked by execute() for each WebSphere jar to be built.
      * Encapsulates the logic of constructing a java task for calling
      * websphere.ejbdeploy and executing it.
      *
      * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
-     * @param destJar java.io.File representing the destination, websphere
+     * @param destJar java.io.File representing the destination, WebSphere
      *      jarfile.
      */
     private void buildWebsphereJar(File sourceJar, File destJar) {
@@ -580,7 +551,7 @@
                 javaTask.createArg().setValue(destJar.getPath());
                 javaTask.createArg().setLine(getOptions());
                 if (getCombinedClasspath() != null
-                    && getCombinedClasspath().toString().length() > 0) {
+                    && !getCombinedClasspath().toString().isEmpty()) {
                     javaTask.createArg().setValue("-cp");
                     javaTask.createArg().setValue(getCombinedClasspath().toString());
                 }
@@ -603,15 +574,16 @@
             }
         } catch (Exception e) {
             // Have to catch this because of the semantics of calling main()
-            String msg = "Exception while calling ejbdeploy. Details: " + e.toString();
-
-            throw new BuildException(msg, e);
+            throw new BuildException(
+                "Exception while calling ejbdeploy. Details: " + e.toString(),
+                e);
         }
     }
 
     /** {@inheritDoc}. */
-    protected void writeJar(String baseName, File jarFile, Hashtable files, String publicId)
-         throws BuildException {
+    @Override
+    protected void writeJar(String baseName, File jarFile,
+        Hashtable<String, File> files, String publicId) throws BuildException {
         if (ejbdeploy) {
             // create the -generic.jar, if required
             File genericJarFile = super.getVendorOutputJarFile(baseName);
@@ -633,46 +605,45 @@
         }
     }
 
-
     /**
      * Called to validate that the tool parameters have been configured.
      * @throws BuildException if there is an error.
      */
+    @Override
     public void validateConfigured() throws BuildException {
         super.validateConfigured();
         if (ejbdeploy) {
             String home = getTask().getProject().getProperty("websphere.home");
             if (home == null) {
-                throw new BuildException("The 'websphere.home' property must "
-                    + "be set when 'ejbdeploy=true'");
+                throw new BuildException(
+                    "The 'websphere.home' property must be set when 'ejbdeploy=true'");
             }
             websphereHome = getTask().getProject().resolveFile(home);
         }
     }
 
-
     /**
-     * Helper method to check to see if a websphere EBJ1.1 jar needs to be
+     * Helper method to check to see if a WebSphere EJB 1.1 jar needs to be
      * rebuilt using ejbdeploy. Called from writeJar it sees if the "Bean"
      * classes are the only thing that needs to be updated and either updates
      * the Jar with the Bean classfile or returns true, saying that the whole
-     * websphere jar needs to be regened with ejbdeploy. This allows faster
+     * WebSphere jar needs to be regenerated with ejbdeploy. This allows faster
      * build times for working developers. <p>
      *
-     * The way websphere ejbdeploy works is it creates wrappers for the
+     * The way WebSphere ejbdeploy works is it creates wrappers for the
      * publicly defined methods as they are exposed in the remote interface.
      * If the actual bean changes without changing the the method signatures
      * then only the bean classfile needs to be updated and the rest of the
-     * websphere jar file can remain the same. If the Interfaces, ie. the
+     * WebSphere jar file can remain the same. If the Interfaces, ie. the
      * method signatures change or if the xml deployment descriptors changed,
      * the whole jar needs to be rebuilt with ejbdeploy. This is not strictly
      * true for the xml files. If the JNDI name changes then the jar doesn't
      * have to be rebuild, but if the resources references change then it
-     * does. At this point the websphere jar gets rebuilt if the xml files
+     * does. At this point the WebSphere jar gets rebuilt if the xml files
      * change at all.
      *
      * @param genericJarFile java.io.File The generic jar file.
-     * @param websphereJarFile java.io.File The websphere jar file to check to
+     * @param websphereJarFile java.io.File The WebSphere jar file to check to
      *      see if it needs to be rebuilt.
      * @return true if a rebuild is required.
      */
@@ -689,83 +660,71 @@
         try {
             log("Checking if websphere Jar needs to be rebuilt for jar "
                 + websphereJarFile.getName(), Project.MSG_VERBOSE);
-            // Only go forward if the generic and the websphere file both exist
+            // Only go forward if the generic and the WebSphere file both exist
             if (genericJarFile.exists() && genericJarFile.isFile()
                  && websphereJarFile.exists() && websphereJarFile.isFile()) {
                 //open jar files
                 genericJar = new JarFile(genericJarFile);
                 wasJar = new JarFile(websphereJarFile);
 
-                Hashtable genericEntries = new Hashtable();
-                Hashtable wasEntries = new Hashtable();
-                Hashtable replaceEntries = new Hashtable();
-
                 //get the list of generic jar entries
-                for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
-                    JarEntry je = (JarEntry) e.nextElement();
+                Map<String, JarEntry> genericEntries = genericJar.stream()
+                        .collect(Collectors.toMap(je -> je.getName().replace('\\', '/'),
+                                je -> je, (a, b) -> b));
 
-                    genericEntries.put(je.getName().replace('\\', '/'), je);
-                }
-                //get the list of websphere jar entries
-                for (Enumeration e = wasJar.entries(); e.hasMoreElements();) {
-                    JarEntry je = (JarEntry) e.nextElement();
+                // get the list of WebSphere jar entries
+                Map<String, JarEntry> wasEntries = wasJar.stream()
+                        .collect(Collectors.toMap(ZipEntry::getName, je -> je, (a, b) -> b));
 
-                    wasEntries.put(je.getName(), je);
-                }
-
-                //Cycle Through generic and make sure its in websphere
+                // Cycle through generic and make sure its in WebSphere
                 genericLoader = getClassLoaderFromJar(genericJarFile);
 
-                for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
-                    String filepath = (String) e.nextElement();
-
-                    if (wasEntries.containsKey(filepath)) {
-                        // File name/path match
-                        // Check files see if same
-                        JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
-                        JarEntry wasEntry = (JarEntry) wasEntries.get(filepath);
-
-                        if ((genericEntry.getCrc() != wasEntry.getCrc())
-                            || (genericEntry.getSize() != wasEntry.getSize())) {
-
-                            if (genericEntry.getName().endsWith(".class")) {
-                                //File are different see if its an object or an interface
-                                String classname
-                                    = genericEntry.getName().replace(File.separatorChar, '.');
-
-                                classname = classname.substring(0, classname.lastIndexOf(".class"));
-
-                                Class genclass = genericLoader.loadClass(classname);
-
-                                if (genclass.isInterface()) {
-                                    //Interface changed   rebuild jar.
-                                    log("Interface " + genclass.getName()
-                                        + " has changed", Project.MSG_VERBOSE);
-                                    rebuild = true;
-                                    break;
-                                } else {
-                                    //Object class Changed   update it.
-                                    replaceEntries.put(filepath, genericEntry);
-                                }
-                            } else {
-                                // is it the manifest. If so ignore it
-                                if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
-                                    //File other then class changed   rebuild
-                                    log("Non class file " + genericEntry.getName()
-                                        + " has changed", Project.MSG_VERBOSE);
-                                    rebuild = true;
-                                }
-                                break;
-                            }
-                        }
-                    } else {
+                Map<String, JarEntry> replaceEntries = new HashMap<>();
+                for (String filepath : genericEntries.keySet()) {
+                    if (!wasEntries.containsKey(filepath)) {
                         // a file doesn't exist rebuild
-
                         log("File " + filepath + " not present in websphere jar",
                             Project.MSG_VERBOSE);
                         rebuild = true;
                         break;
                     }
+                    // File name/path match
+                    // Check files see if same
+                    JarEntry genericEntry = genericEntries.get(filepath);
+                    JarEntry wasEntry = wasEntries.get(filepath);
+
+                    if (genericEntry.getCrc() != wasEntry.getCrc()
+                        || genericEntry.getSize() != wasEntry.getSize()) {
+
+                        if (genericEntry.getName().endsWith(".class")) {
+                            //File are different see if its an object or an interface
+                            String classname
+                                = genericEntry.getName().replace(File.separatorChar, '.');
+
+                            classname = classname.substring(0, classname.lastIndexOf(".class"));
+
+                            Class<?> genclass = genericLoader.loadClass(classname);
+
+                            if (genclass.isInterface()) {
+                                //Interface changed   rebuild jar.
+                                log("Interface " + genclass.getName()
+                                    + " has changed", Project.MSG_VERBOSE);
+                                rebuild = true;
+                                break;
+                            }
+                            //Object class Changed   update it.
+                            replaceEntries.put(filepath, genericEntry);
+                        } else {
+                            // is it the manifest. If so ignore it
+                            if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
+                                //File other then class changed  rebuild
+                                log("Non class file " + genericEntry.getName()
+                                    + " has changed", Project.MSG_VERBOSE);
+                                rebuild = true;
+                            }
+                            break;
+                        }
+                    }
                 }
 
                 if (!rebuild) {
@@ -775,16 +734,11 @@
                         newwasJarFile.delete();
                     }
 
-                    newJarStream = new JarOutputStream(new FileOutputStream(newwasJarFile));
+                    newJarStream = new JarOutputStream(Files.newOutputStream(newwasJarFile.toPath()));
                     newJarStream.setLevel(0);
 
-                    //Copy files from old websphere jar
-                    for (Enumeration e = wasEntries.elements(); e.hasMoreElements();) {
-                        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
-                        int bytesRead;
-                        InputStream is;
-                        JarEntry je = (JarEntry) e.nextElement();
-
+                    // Copy files from old WebSphere jar
+                    for (JarEntry je : wasEntries.values()) {
                         if (je.getCompressedSize() == -1
                             || je.getCompressedSize() == je.getSize()) {
                             newJarStream.setLevel(0);
@@ -792,20 +746,23 @@
                             newJarStream.setLevel(JAR_COMPRESS_LEVEL);
                         }
 
+                        InputStream is;
                         // Update with changed Bean class
                         if (replaceEntries.containsKey(je.getName())) {
                             log("Updating Bean class from generic Jar " + je.getName(),
                                 Project.MSG_VERBOSE);
                             // Use the entry from the generic jar
-                            je = (JarEntry) replaceEntries.get(je.getName());
+                            je = replaceEntries.get(je.getName());
                             is = genericJar.getInputStream(je);
                         } else {
-                            //use fle from original websphere jar
+                            // use fle from original WebSphere jar
 
                             is = wasJar.getInputStream(je);
                         }
                         newJarStream.putNextEntry(new JarEntry(je.getName()));
 
+                        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+                        int bytesRead;
                         while ((bytesRead = is.read(buffer)) != -1) {
                             newJarStream.write(buffer, 0, bytesRead);
                         }
@@ -819,36 +776,21 @@
                 rebuild = true;
             }
         } catch (ClassNotFoundException cnfe) {
-            String cnfmsg = "ClassNotFoundException while processing ejb-jar file"
-                 + ". Details: "
-                 + cnfe.getMessage();
-
-            throw new BuildException(cnfmsg, cnfe);
+            throw new BuildException(
+                "ClassNotFoundException while processing ejb-jar file. Details: "
+                    + cnfe.getMessage(),
+                cnfe);
         } catch (IOException ioe) {
-            String msg = "IOException while processing ejb-jar file "
-                 + ". Details: "
-                 + ioe.getMessage();
-
-            throw new BuildException(msg, ioe);
+            throw new BuildException(
+                "IOException while processing ejb-jar file . Details: "
+                    + ioe.getMessage(),
+                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);
@@ -857,17 +799,15 @@
                     rebuild = true;
                 }
             }
-            if (genericLoader != null
-                && genericLoader instanceof AntClassLoader) {
+            if (genericLoader instanceof AntClassLoader) {
+                @SuppressWarnings("resource")
                 AntClassLoader loader = (AntClassLoader) genericLoader;
                 loader.cleanup();
             }
         }
-
         return rebuild;
     }
 
-
     /**
      * Helper method invoked by isRebuildRequired to get a ClassLoader for a
      * Jar File passed to it.
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatability.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatability.java
index cbc7f37..d7578a2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatability.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatability.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -51,6 +51,7 @@
      *
      * @return the name of compatibility level
      */
+    @Override
     public String toString() {
         return name;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatibility.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatibility.java
index cfe12a1..5a598a5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatibility.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Compatibility.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -51,6 +51,7 @@
      *
      * @return the name of compatibility level
      */
+    @Override
     public String toString() {
         return name;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/DeweyDecimal.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/DeweyDecimal.java
index 2edc2a7..8649826 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/DeweyDecimal.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/DeweyDecimal.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java
index d13d2f4..73a7857 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,14 +18,15 @@
 package org.apache.tools.ant.taskdefs.optional.extension;
 
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.StringTokenizer;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.util.DeweyDecimal;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * <p>Utility class that represents either an available "Optional Package"
@@ -52,7 +53,7 @@
      * are not required for the library to operate but if present will be used.
      * It is NOT part of the official "Optional Package" specification.
      *
-     * @see <a href="http://java.sun.com/j2se/1.3/docs/guide/extensions/spec.html#dependency">
+     * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/spec.html#dependency">
      *      Installed extension dependency</a>
      */
     public static final Attributes.Name OPTIONAL_EXTENSION_LIST
@@ -187,31 +188,14 @@
      */
     public static Extension[] getAvailable(final Manifest manifest) {
         if (null == manifest) {
-            return new Extension[ 0 ];
+            return new Extension[0];
         }
-
-        final ArrayList results = new ArrayList();
-
-        final Attributes mainAttributes = manifest.getMainAttributes();
-        if (null != mainAttributes) {
-            final Extension extension = getExtension("", mainAttributes);
-            if (null != extension) {
-                results.add(extension);
-            }
-        }
-
-        final Map entries = manifest.getEntries();
-        final Iterator keys = entries.keySet().iterator();
-        while (keys.hasNext()) {
-            final String key = (String) keys.next();
-            final Attributes attributes = (Attributes) entries.get(key);
-            final Extension extension = getExtension("", attributes);
-            if (null != extension) {
-                results.add(extension);
-            }
-        }
-
-        return (Extension[]) results.toArray(new Extension[results.size()]);
+        return Stream
+            .concat(Optional.ofNullable(manifest.getMainAttributes())
+                    .map(Stream::of).orElse(Stream.empty()),
+                manifest.getEntries().values().stream())
+            .map(attrs -> getExtension("", attrs)).filter(Objects::nonNull)
+            .toArray(Extension[]::new);
     }
 
     /**
@@ -491,54 +475,35 @@
      *
      * @return string representation of object.
      */
+    @Override
     public String toString() {
-        final String brace = ": ";
+        final String format = "%s: %s%n";
 
-        final StringBuffer sb = new StringBuffer(EXTENSION_NAME.toString());
-        sb.append(brace);
-        sb.append(extensionName);
-        sb.append(StringUtils.LINE_SEP);
+        final StringBuilder sb = new StringBuilder(String.format(format,
+                EXTENSION_NAME, extensionName));
 
         if (null != specificationVersion) {
-            sb.append(SPECIFICATION_VERSION);
-            sb.append(brace);
-            sb.append(specificationVersion);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, SPECIFICATION_VERSION, specificationVersion));
         }
 
         if (null != specificationVendor) {
-            sb.append(SPECIFICATION_VENDOR);
-            sb.append(brace);
-            sb.append(specificationVendor);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, SPECIFICATION_VENDOR, specificationVendor));
         }
 
         if (null != implementationVersion) {
-            sb.append(IMPLEMENTATION_VERSION);
-            sb.append(brace);
-            sb.append(implementationVersion);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_VERSION, implementationVersion));
         }
 
         if (null != implementationVendorID) {
-            sb.append(IMPLEMENTATION_VENDOR_ID);
-            sb.append(brace);
-            sb.append(implementationVendorID);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_VENDOR_ID, implementationVendorID));
         }
 
         if (null != implementationVendor) {
-            sb.append(IMPLEMENTATION_VENDOR);
-            sb.append(brace);
-            sb.append(implementationVendor);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_VENDOR, implementationVendor));
         }
 
         if (null != implementationURL) {
-            sb.append(IMPLEMENTATION_URL);
-            sb.append(brace);
-            sb.append(implementationURL);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_URL, implementationURL));
         }
 
         return sb.toString();
@@ -567,22 +532,17 @@
      */
     private static Extension[] getListed(final Manifest manifest,
                                           final Attributes.Name listKey) {
-        final ArrayList results = new ArrayList();
+        final List<Extension> results = new ArrayList<>();
         final Attributes mainAttributes = manifest.getMainAttributes();
 
         if (null != mainAttributes) {
             getExtension(mainAttributes, results, listKey);
         }
 
-        final Map entries = manifest.getEntries();
-        final Iterator keys = entries.keySet().iterator();
-        while (keys.hasNext()) {
-            final String key = (String) keys.next();
-            final Attributes attributes = (Attributes) entries.get(key);
-            getExtension(attributes, results, listKey);
-        }
+        manifest.getEntries().values()
+            .forEach(attributes -> getExtension(attributes, results, listKey));
 
-        return (Extension[]) results.toArray(new Extension[results.size()]);
+        return results.toArray(new Extension[0]);
     }
 
     /**
@@ -595,18 +555,14 @@
      *    or OPTIONAL_EXTENSION_LIST
      */
     private static void getExtension(final Attributes attributes,
-                                     final ArrayList required,
+                                     final List<Extension> required,
                                      final Attributes.Name listKey) {
         final String names = attributes.getValue(listKey);
         if (null == names) {
             return;
         }
-
-        final String[] extensions = split(names, " ");
-        for (int i = 0; i < extensions.length; i++) {
-            final String prefix = extensions[ i ] + "-";
-            final Extension extension = getExtension(prefix, attributes);
-
+        for (final String prefix : split(names, " ")) {
+            final Extension extension = getExtension(prefix + "-", attributes);
             if (null != extension) {
                 required.add(extension);
             }
@@ -623,10 +579,10 @@
     private static String[] split(final String string,
                                         final String onToken) {
         final StringTokenizer tokenizer = new StringTokenizer(string, onToken);
-        final String[] result = new String[ tokenizer.countTokens() ];
+        final String[] result = new String[tokenizer.countTokens()];
 
         for (int i = 0; i < result.length; i++) {
-            result[ i ] = tokenizer.nextToken();
+            result[i] = tokenizer.nextToken();
         }
 
         return result;
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java
index 4befa4f..96865f5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -150,6 +150,7 @@
      * @param reference the reference to which this instance is associated
      * @exception BuildException if this instance already has been configured.
      */
+    @Override
     public void setRefid(final Reference reference)
         throws BuildException {
         if (null != extensionName
@@ -179,12 +180,11 @@
     Extension toExtension()
         throws BuildException {
         if (isReference()) {
-            return ((ExtensionAdapter) getCheckedRef()).toExtension();
+            return getRef().toExtension();
         }
         dieOnCircularReference();
         if (null == extensionName) {
-            final String message = "Extension is missing name.";
-            throw new BuildException(message);
+            throw new BuildException("Extension is missing name.");
         }
 
         String specificationVersionString = null;
@@ -209,7 +209,12 @@
      * @return the extension in a string.
      * @see java.lang.Object#toString()
      */
+    @Override
     public String toString() {
-        return "{" + toExtension().toString() + "}";
+        return "{" + toExtension() + "}";
+    }
+
+    private ExtensionAdapter getRef() {
+        return getCheckedRef(ExtensionAdapter.class);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionResolver.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionResolver.java
index a73282e..0a7b2d3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionResolver.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionResolver.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java
index 5aba37c..b35aa61 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Stack;
 
 import org.apache.tools.ant.BuildException;
@@ -39,12 +39,12 @@
     /**
      * ExtensionAdapter objects representing extensions.
      */
-    private final ArrayList extensions = new ArrayList();
+    private final List<ExtensionAdapter> extensions = new ArrayList<>();
 
     /**
      * Filesets specifying all the extensions wanted.
      */
-    private final ArrayList extensionsFilesets = new ArrayList();
+    private final List<FileSet> extensionsFilesets = new ArrayList<>();
 
     /**
      * Adds an extension that this library requires.
@@ -95,12 +95,12 @@
     public Extension[] toExtensions(final Project proj)
         throws BuildException {
         if (isReference()) {
-            return ((ExtensionSet) getCheckedRef()).toExtensions(proj);
+            return getRef().toExtensions(proj);
         }
         dieOnCircularReference();
-        final ArrayList extensionsList = ExtensionUtil.toExtensions(extensions);
+        final List<Extension> extensionsList = ExtensionUtil.toExtensions(extensions);
         ExtensionUtil.extractExtensions(proj, extensionsList, extensionsFilesets);
-        return (Extension[]) extensionsList.toArray(new Extension[extensionsList.size()]);
+        return extensionsList.toArray(new Extension[0]);
     }
 
     /**
@@ -123,7 +123,7 @@
     }
 
     @Override
-    protected synchronized void dieOnCircularReference(Stack stk, Project p)
+    protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
             return;
@@ -131,17 +131,20 @@
         if (isReference()) {
             super.dieOnCircularReference(stk, p);
         } else {
-            for (Iterator i = extensions.iterator(); i.hasNext();) {
-                pushAndInvokeCircularReferenceCheck((ExtensionAdapter) i.next(),
-                                                    stk, p);
+            for (ExtensionAdapter extensionAdapter : extensions) {
+                pushAndInvokeCircularReferenceCheck(extensionAdapter, stk, p);
             }
-            for (Iterator i = extensionsFilesets.iterator(); i.hasNext();) {
-                pushAndInvokeCircularReferenceCheck((FileSet) i.next(), stk, p);
+            for (FileSet fileSet : extensionsFilesets) {
+                pushAndInvokeCircularReferenceCheck(fileSet, stk, p);
             }
             setChecked(true);
         }
     }
 
+    private ExtensionSet getRef() {
+        return getCheckedRef(ExtensionSet.class);
+    }
+
     /**
      * @see java.lang.Object#toString()
      * @return the extensions in a string.
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java
index e631d3a..e83592c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtensionUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,10 +20,11 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Collections;
 import java.util.List;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -48,19 +49,10 @@
      * @param adapters the list of ExtensionAdapters to add to convert
      * @throws BuildException if an error occurs
      */
-    static ArrayList toExtensions(final List adapters)
+    static ArrayList<Extension> toExtensions(final List<? extends ExtensionAdapter> adapters)
         throws BuildException {
-        final ArrayList results = new ArrayList();
-
-        final int size = adapters.size();
-        for (int i = 0; i < size; i++) {
-            final ExtensionAdapter adapter =
-                (ExtensionAdapter) adapters.get(i);
-            final Extension extension = adapter.toExtension();
-            results.add(extension);
-        }
-
-        return results;
+        return adapters.stream().map(ExtensionAdapter::toExtension)
+            .collect(Collectors.toCollection(ArrayList::new));
     }
 
     /**
@@ -71,15 +63,11 @@
      * @throws BuildException if an error occurs
      */
     static void extractExtensions(final Project project,
-                                   final List libraries,
-                                   final List fileset)
+                                   final List<Extension> libraries,
+                                   final List<FileSet> fileset)
         throws BuildException {
         if (!fileset.isEmpty()) {
-            final Extension[] extensions = getExtensions(project,
-                                                          fileset);
-            for (int i = 0; i < extensions.length; i++) {
-                libraries.add(extensions[ i ]);
-            }
+            Collections.addAll(libraries, getExtensions(project, fileset));
         }
     }
 
@@ -91,13 +79,11 @@
      * @throws BuildException if failing to scan libraries
      */
     private static Extension[] getExtensions(final Project project,
-                                              final List libraries)
+                                              final List<FileSet> libraries)
         throws BuildException {
-        final ArrayList extensions = new ArrayList();
-        final Iterator iterator = libraries.iterator();
-        while (iterator.hasNext()) {
-            final FileSet fileSet = (FileSet) iterator.next();
+        final List<Extension> extensions = new ArrayList<>();
 
+        for (FileSet fileSet : libraries) {
             boolean includeImpl = true;
             boolean includeURL = true;
 
@@ -114,7 +100,7 @@
                 loadExtensions(file, extensions, includeImpl, includeURL);
             }
         }
-        return (Extension[]) extensions.toArray(new Extension[extensions.size()]);
+        return extensions.toArray(new Extension[0]);
     }
 
     /**
@@ -125,23 +111,17 @@
      * @throws BuildException if there is an error
      */
     private static void loadExtensions(final File file,
-                                        final List extensionList,
+                                        final List<Extension> extensionList,
                                         final boolean includeImpl,
                                         final boolean includeURL)
         throws BuildException {
-        JarFile jarFile = null;
-        try {
-            jarFile = new JarFile(file);
-            final Extension[] extensions =
-                Extension.getAvailable(jarFile.getManifest());
-            for (int i = 0; i < extensions.length; i++) {
-                final Extension extension = extensions[ i ];
+        try (JarFile jarFile = new JarFile(file)) {
+            for (Extension extension : Extension
+                .getAvailable(jarFile.getManifest())) {
                 addExtension(extensionList, extension, includeImpl, includeURL);
             }
         } catch (final Exception e) {
             throw new BuildException(e.getMessage(), e);
-        } finally {
-            close(jarFile);
         }
     }
 
@@ -156,7 +136,7 @@
      * @param includeImpl false to exclude implementation details
      * @param includeURL false to exclude implementation URL
      */
-    private static void addExtension(final List extensionList,
+    private static void addExtension(final List<Extension> extensionList,
                                       final Extension originalExtension,
                                       final boolean includeImpl,
                                       final boolean includeURL) {
@@ -203,28 +183,15 @@
      */
     static Manifest getManifest(final File file)
         throws BuildException {
-        JarFile jarFile = null;
-        try {
-            jarFile = new JarFile(file);
+        try (JarFile jarFile = new JarFile(file)) {
             Manifest m = jarFile.getManifest();
             if (m == null) {
-                throw new BuildException(file + " doesn't have a MANIFEST");
+                throw new BuildException("%s doesn't have a MANIFEST", file);
             }
             return m;
         } catch (final IOException ioe) {
             throw new BuildException(ioe.getMessage(), ioe);
-        } finally {
-            close(jarFile);
         }
     }
 
-    private static void close(JarFile device) {
-        if (null != device) {
-            try {
-                device.close();
-            } catch (IOException e) {
-                //ignore
-            }
-        }
-    }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtraAttribute.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtraAttribute.java
index d52bec4..2dd4fa7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtraAttribute.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/ExtraAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -73,11 +73,11 @@
      */
     public void validate() throws BuildException {
         if (null == name) {
-            final String message = "Missing name from parameter.";
-            throw new BuildException(message);
-        } else if (null == value) {
-            final String message = "Missing value from parameter " + name + ".";
-            throw new BuildException(message);
+            throw new BuildException("Missing name from parameter.");
+        }
+        if (null == value) {
+            throw new BuildException(
+                "Missing value from parameter " + name + ".");
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibAvailableTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibAvailableTask.java
index 4cce0f5..58efed2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibAvailableTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibAvailableTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,11 +18,12 @@
 package org.apache.tools.ant.taskdefs.optional.extension;
 
 import java.io.File;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Vector;
-import java.util.jar.Manifest;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 
 /**
@@ -40,7 +41,7 @@
      * Filesets specifying all the libraries
      * to display information about.
      */
-    private final Vector extensionFileSets = new Vector();
+    private final List<ExtensionSet> extensionFileSets = new Vector<>();
 
     /**
      * The name of the property to set if extension is available.
@@ -77,9 +78,8 @@
      */
     public void addConfiguredExtension(final ExtensionAdapter extension) {
         if (null != requiredExtension) {
-            final String message = "Can not specify extension to "
-                + "search for multiple times.";
-            throw new BuildException(message);
+            throw new BuildException(
+                "Can not specify extension to search for multiple times.");
         }
         requiredExtension = extension;
     }
@@ -90,7 +90,7 @@
      * @param extensionSet a set of extensions to search in.
      */
     public void addConfiguredExtensionSet(final ExtensionSet extensionSet) {
-        extensionFileSets.addElement(extensionSet);
+        extensionFileSets.add(extensionSet);
     }
 
     /**
@@ -98,35 +98,24 @@
      *
      * @throws BuildException if something goes wrong.
      */
+    @Override
     public void execute() throws BuildException {
         validate();
 
-        final Extension test = requiredExtension.toExtension();
+        final Project prj = getProject();
+        final Stream<Extension> extensions;
 
         // Check if list of files to check has been specified
         if (!extensionFileSets.isEmpty()) {
-            final Iterator iterator = extensionFileSets.iterator();
-            while (iterator.hasNext()) {
-                final ExtensionSet extensionSet
-                    = (ExtensionSet) iterator.next();
-                final Extension[] extensions =
-                    extensionSet.toExtensions(getProject());
-                for (int i = 0; i < extensions.length; i++) {
-                    final Extension extension = extensions[ i ];
-                    if (extension.isCompatibleWith(test)) {
-                        getProject().setNewProperty(propertyName, "true");
-                    }
-                }
-            }
+            extensions = extensionFileSets.stream()
+                .map(xset -> xset.toExtensions(prj)).flatMap(Stream::of);
         } else {
-            final Manifest manifest = ExtensionUtil.getManifest(libraryFile);
-            final Extension[] extensions = Extension.getAvailable(manifest);
-            for (int i = 0; i < extensions.length; i++) {
-                final Extension extension = extensions[ i ];
-                if (extension.isCompatibleWith(test)) {
-                    getProject().setNewProperty(propertyName, "true");
-                }
-            }
+            extensions = Stream.of(
+                Extension.getAvailable(ExtensionUtil.getManifest(libraryFile)));
+        }
+        final Extension test = requiredExtension.toExtension();
+        if (extensions.anyMatch(x -> x.isCompatibleWith(test))) {
+            prj.setNewProperty(propertyName, "true");
         }
     }
 
@@ -137,21 +126,16 @@
      */
     private void validate() throws BuildException {
         if (null == requiredExtension) {
-            final String message = "Extension element must be specified.";
-            throw new BuildException(message);
+            throw new BuildException("Extension element must be specified.");
         }
-
-        if (null == libraryFile && extensionFileSets.isEmpty()) {
-            final String message = "File attribute not specified.";
-            throw new BuildException(message);
-        }
-        if (null != libraryFile && !libraryFile.exists()) {
-            final String message = "File '" + libraryFile + "' does not exist.";
-            throw new BuildException(message);
-        }
-        if (null != libraryFile && !libraryFile.isFile()) {
-            final String message = "\'" + libraryFile + "\' is not a file.";
-            throw new BuildException(message);
+        if (null == libraryFile) {
+            if (extensionFileSets.isEmpty()) {
+                throw new BuildException("File attribute not specified.");
+            }
+        } else if (!libraryFile.exists()) {
+            throw new BuildException("File '%s' does not exist.", libraryFile);
+        } else if (!libraryFile.isFile()) {
+            throw new BuildException("'%s' is not a file.", libraryFile);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibDisplayTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibDisplayTask.java
index d441b32..c90f980 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibDisplayTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibDisplayTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,7 @@
 package org.apache.tools.ant.taskdefs.optional.extension;
 
 import java.io.File;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -34,8 +34,8 @@
  * The specification for this mechanism is available in the JDK1.3
  * documentation in the directory
  * $JDK_HOME/docs/guide/extensions/versioning.html. Alternatively it is
- * available online at <a href="http://java.sun.com/j2se/1.3/docs/guide/extensions/versioning.html">
- * http://java.sun.com/j2se/1.3/docs/guide/extensions/versioning.html</a>.</p>
+ * available online at <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html">
+ * https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html</a>.</p>
  *
  * @ant.task name="jarlib-display"
  */
@@ -49,7 +49,7 @@
      * Filesets specifying all the libraries
      * to display information about.
      */
-    private final Vector libraryFileSets = new Vector();
+    private final List<FileSet> libraryFileSets = new Vector<>();
 
     /**
      * The JAR library to display information for.
@@ -66,7 +66,7 @@
      * @param fileSet a set of files about which library data will be displayed.
      */
     public void addFileset(final FileSet fileSet) {
-        libraryFileSets.addElement(fileSet);
+        libraryFileSets.add(fileSet);
     }
 
     /**
@@ -74,26 +74,23 @@
      *
      * @throws BuildException if the task fails.
      */
+    @Override
     public void execute() throws BuildException {
         validate();
 
         final LibraryDisplayer displayer = new LibraryDisplayer();
         // Check if list of files to check has been specified
-        if (!libraryFileSets.isEmpty()) {
-            final Iterator iterator = libraryFileSets.iterator();
-            while (iterator.hasNext()) {
-                final FileSet fileSet = (FileSet) iterator.next();
-                final DirectoryScanner scanner
-                    = fileSet.getDirectoryScanner(getProject());
+        if (libraryFileSets.isEmpty()) {
+            displayer.displayLibrary(libraryFile);
+        } else {
+            for (FileSet fileSet : libraryFileSets) {
+                final DirectoryScanner scanner =
+                    fileSet.getDirectoryScanner(getProject());
                 final File basedir = scanner.getBasedir();
-                final String[] files = scanner.getIncludedFiles();
-                for (int i = 0; i < files.length; i++) {
-                    final File file = new File(basedir, files[ i ]);
-                    displayer.displayLibrary(file);
+                for (String filename : scanner.getIncludedFiles()) {
+                    displayer.displayLibrary(new File(basedir, filename));
                 }
             }
-        } else {
-            displayer.displayLibrary(libraryFile);
         }
     }
 
@@ -103,17 +100,14 @@
      * @throws BuildException if invalid parameters found
      */
     private void validate() throws BuildException {
-        if (null == libraryFile && libraryFileSets.isEmpty()) {
-            final String message = "File attribute not specified.";
-            throw new BuildException(message);
-        }
-        if (null != libraryFile && !libraryFile.exists()) {
-            final String message = "File '" + libraryFile + "' does not exist.";
-            throw new BuildException(message);
-        }
-        if (null != libraryFile && !libraryFile.isFile()) {
-            final String message = "\'" + libraryFile + "\' is not a file.";
-            throw new BuildException(message);
+        if (null == libraryFile) {
+            if (libraryFileSets.isEmpty()) {
+                throw new BuildException("File attribute not specified.");
+            }
+        } else if (!libraryFile.exists()) {
+            throw new BuildException("File '%s' does not exist.", libraryFile);
+        } else if (!libraryFile.isFile()) {
+            throw new BuildException("'%s' is not a file.", libraryFile);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibManifestTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibManifestTask.java
index 9941c86..ac4d914 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibManifestTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibManifestTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,18 +18,21 @@
 package org.apache.tools.ant.taskdefs.optional.extension;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.List;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Generates a manifest that declares all the dependencies.
@@ -41,8 +44,8 @@
  * The specification for this mechanism is available in the JDK1.3
  * documentation in the directory
  * $JDK_HOME/docs/guide/extensions/versioning.html. Alternatively it is
- * available online at <a href="http://java.sun.com/j2se/1.3/docs/guide/extensions/versioning.html">
- * http://java.sun.com/j2se/1.3/docs/guide/extensions/versioning.html</a>.</p>
+ * available online at <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html">
+ * https://docs.oracle.com/javase/8/docs/technotes/guides/extensions/versioning.html</a>.</p>
  *
  * @ant.task name="jarlib-manifest"
  */
@@ -71,19 +74,19 @@
      * ExtensionAdapter objects representing
      * dependencies required by library.
      */
-    private final ArrayList dependencies = new ArrayList();
+    private final List<ExtensionSet> dependencies = new ArrayList<>();
 
     /**
      * ExtensionAdapter objects representing optional
      * dependencies required by library.
      */
-    private final ArrayList optionals = new ArrayList();
+    private final List<ExtensionSet> optionals = new ArrayList<>();
 
     /**
      * Extra attributes the user specifies for main section
      * in manifest.
      */
-    private final ArrayList extraAttributes = new ArrayList();
+    private final List<ExtraAttribute> extraAttributes = new ArrayList<>();
 
     /**
      * The location where generated manifest is placed.
@@ -105,7 +108,8 @@
     public void addConfiguredExtension(final ExtensionAdapter extensionAdapter)
             throws BuildException {
         if (null != extension) {
-            throw new BuildException("Can not have multiple extensions defined in one library.");
+            throw new BuildException(
+                "Can not have multiple extensions defined in one library.");
         }
         extension = extensionAdapter.toExtension();
     }
@@ -142,6 +146,7 @@
      *
      * @throws BuildException if the task fails.
      */
+    @Override
     public void execute() throws BuildException {
         validate();
 
@@ -159,13 +164,13 @@
         }
 
         //Add all the dependency data to manifest for dependencies
-        final ArrayList depends = toExtensions(dependencies);
+        final List<Extension> depends = toExtensions(dependencies);
         appendExtensionList(attributes, Extension.EXTENSION_LIST, "lib", depends.size());
         appendLibraryList(attributes, "lib", depends);
 
         // Add all the dependency data to manifest for "optional"
         //dependencies
-        final ArrayList option = toExtensions(optionals);
+        final List<Extension> option = toExtensions(optionals);
         appendExtensionList(attributes, Extension.OPTIONAL_EXTENSION_LIST, "opt", option.size());
         appendLibraryList(attributes, "opt", option);
 
@@ -187,7 +192,7 @@
             throw new BuildException("Destfile attribute not specified.");
         }
         if (destFile.exists() && !destFile.isFile()) {
-            throw new BuildException(destFile + " is not a file.");
+            throw new BuildException("%s is not a file.", destFile);
         }
     }
 
@@ -198,12 +203,8 @@
      *        attributes to
      */
     private void appendExtraAttributes(final Attributes attributes) {
-        final Iterator iterator = extraAttributes.iterator();
-        while (iterator.hasNext()) {
-            final ExtraAttribute attribute =
-                (ExtraAttribute) iterator.next();
-            attributes.putValue(attribute.getName(),
-                                 attribute.getValue());
+        for (ExtraAttribute attribute : extraAttributes) {
+            attributes.putValue(attribute.getName(), attribute.getValue());
         }
     }
 
@@ -214,13 +215,9 @@
      * @throws IOException if error writing file
      */
     private void writeManifest(final Manifest manifest) throws IOException {
-        FileOutputStream output = null;
-        try {
-            output = new FileOutputStream(destFile);
+        try (OutputStream output = Files.newOutputStream(destFile.toPath())) {
             manifest.write(output);
             output.flush();
-        } finally {
-            FileUtils.close(output);
         }
     }
 
@@ -236,12 +233,11 @@
      * @throws BuildException if an error occurs
      */
     private void appendLibraryList(final Attributes attributes, final String listPrefix,
-            final ArrayList extensions) throws BuildException {
+            final List<Extension> extensions) throws BuildException {
         final int size = extensions.size();
         for (int i = 0; i < size; i++) {
-            final Extension ext = (Extension) extensions.get(i);
-            final String prefix = listPrefix + i + "-";
-            Extension.addExtension(ext, prefix, attributes);
+            Extension.addExtension(extensions.get(i), listPrefix + i + "-",
+                attributes);
         }
     }
 
@@ -258,15 +254,10 @@
      */
     private void appendExtensionList(final Attributes attributes,
             final Attributes.Name extensionKey, final String listPrefix, final int size) {
-        final StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < size; i++) {
-            sb.append(listPrefix);
-            sb.append(i);
-            sb.append(' ');
-        }
         //add in something like
         //"Extension-List: javahelp java3d"
-        attributes.put(extensionKey, sb.toString());
+        attributes.put(extensionKey, IntStream.range(0, size)
+            .mapToObj(i -> listPrefix + i).collect(Collectors.joining(" ")));
     }
 
     /**
@@ -275,17 +266,10 @@
      * @param extensionSets the list of ExtensionSets to add to list
      * @throws BuildException if an error occurs
      */
-    private ArrayList toExtensions(final ArrayList extensionSets) throws BuildException {
-        final ArrayList results = new ArrayList();
-
-        final int size = extensionSets.size();
-        for (int i = 0; i < size; i++) {
-            final ExtensionSet set = (ExtensionSet) extensionSets.get(i);
-            final Extension[] extensions = set.toExtensions(getProject());
-            for (int j = 0; j < extensions.length; j++) {
-                results.add(extensions[ j ]);
-            }
-        }
-        return results;
+    private List<Extension> toExtensions(final List<ExtensionSet> extensionSets)
+        throws BuildException {
+        final Project prj = getProject();
+        return extensionSets.stream().map(xset -> xset.toExtensions(prj))
+            .flatMap(Stream::of).collect(Collectors.toList());
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibResolveTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibResolveTask.java
index 9ebb4e3..e7f55b5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibResolveTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/JarLibResolveTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.jar.Manifest;
 
 import org.apache.tools.ant.BuildException;
@@ -49,7 +50,7 @@
     /**
      * The set of resolvers to use to attempt to locate library.
      */
-    private final ArrayList resolvers = new ArrayList();
+    private final List<ExtensionResolver> resolvers = new ArrayList<>();
 
     /**
      * Flag to indicate that you should check that
@@ -132,9 +133,8 @@
      */
     public void addConfiguredExtension(final ExtensionAdapter extension) {
         if (null != requiredExtension) {
-            final String message = "Can not specify extension to "
-                + "resolve multiple times.";
-            throw new BuildException(message);
+            throw new BuildException(
+                "Can not specify extension to resolve multiple times.");
         }
         requiredExtension = extension.toExtension();
     }
@@ -144,6 +144,7 @@
      *
      * @throws BuildException if the task fails.
      */
+    @Override
     public void execute() throws BuildException {
         validate();
 
@@ -160,28 +161,26 @@
             return;
         }
 
-        final int size = resolvers.size();
-        for (int i = 0; i < size; i++) {
-            final ExtensionResolver resolver =
-                (ExtensionResolver) resolvers.get(i);
-
+        for (ExtensionResolver resolver : resolvers) {
             getProject().log("Searching for extension using Resolver:" + resolver,
                     Project.MSG_VERBOSE);
-
             try {
-                final File file = resolver.resolve(requiredExtension, getProject());
+                final File file =
+                    resolver.resolve(requiredExtension, getProject());
                 try {
                     checkExtension(file);
                     return;
                 } catch (final BuildException be) {
-                    final String message = "File " + file + " returned by "
-                            + "resolver failed to satisfy extension due to: " + be.getMessage();
-                    getProject().log(message, Project.MSG_WARN);
+                    getProject().log("File " + file + " returned by "
+                        + "resolver failed to satisfy extension due to: "
+                        + be.getMessage(), Project.MSG_WARN);
                 }
             } catch (final BuildException be) {
-                final String message = "Failed to resolve extension to file " + "using resolver "
-                        + resolver + " due to: " + be;
-                getProject().log(message, Project.MSG_WARN);
+                getProject()
+                    .log(
+                        "Failed to resolve extension to file "
+                            + "using resolver " + resolver + " due to: " + be,
+                        Project.MSG_WARN);
             }
         }
         missingExtension();
@@ -210,10 +209,10 @@
      */
     private void checkExtension(final File file) {
         if (!file.exists()) {
-            throw new BuildException("File " + file + " does not exist");
+            throw new BuildException("File %s does not exist", file);
         }
         if (!file.isFile()) {
-            throw new BuildException("File " + file + " is not a file");
+            throw new BuildException("File %s is not a file", file);
         }
         if (!checkExtension) {
             getProject().log("Setting property to " + file
@@ -223,9 +222,7 @@
             getProject().log("Checking file " + file + " to see if it satisfies extension",
                     Project.MSG_VERBOSE);
             final Manifest manifest = ExtensionUtil.getManifest(file);
-            final Extension[] extensions = Extension.getAvailable(manifest);
-            for (int i = 0; i < extensions.length; i++) {
-                final Extension extension = extensions[ i ];
+            for (final Extension extension : Extension.getAvailable(manifest)) {
                 if (extension.isCompatibleWith(requiredExtension)) {
                     setLibraryProperty(file);
                     return;
@@ -256,13 +253,10 @@
      */
     private void validate() throws BuildException {
         if (null == propertyName) {
-            final String message = "Property attribute must be specified.";
-            throw new BuildException(message);
+            throw new BuildException("Property attribute must be specified.");
         }
-
         if (null == requiredExtension) {
-            final String message = "Extension element must be specified.";
-            throw new BuildException(message);
+            throw new BuildException("Extension element must be specified.");
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java
index 94dc879..24494f6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,8 +25,7 @@
  * how they are to be handled when building manifests.
  *
  */
-public class LibFileSet
-    extends FileSet {
+public class LibFileSet extends FileSet {
     /**
      * Flag indicating whether should include the
      * "Implementation-URL" attribute in manifest.
@@ -45,10 +44,10 @@
      * String that is the base URL for the libraries
      * when constructing the "Implementation-URL"
      * attribute. For instance setting the base to
-     * "http://jakarta.apache.org/avalon/libs/" and then
+     * "https://jakarta.apache.org/avalon/libs/" and then
      * including the library "excalibur-cli-1.0.jar" in the
      * fileset will result in the "Implementation-URL" attribute
-     * being set to "http://jakarta.apache.org/avalon/libs/excalibur-cli-1.0.jar"
+     * being set to "https://jakarta.apache.org/avalon/libs/excalibur-cli-1.0.jar"
      *
      * Note this is only used if the library does not define
      * "Implementation-URL" itself.
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibraryDisplayer.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibraryDisplayer.java
index 3eebc63..56d64a8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibraryDisplayer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/LibraryDisplayer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -134,12 +134,9 @@
     private void displaySpecification(final Specification specification) {
         final String[] sections = specification.getSections();
         if (null != sections) {
-            final StringBuffer sb = new StringBuffer("Sections: ");
-            for (int i = 0; i < sections.length; i++) {
-                sb.append(" ");
-                sb.append(sections[ i ]);
-            }
-            System.out.println(sb);
+            System.out.print("Sections:  ");
+            System.out
+                .println(String.join(" ", sections));
         }
         System.out.println(specification.toString());
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Specification.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Specification.java
index 8b09b98..1cb6833 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/Specification.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/Specification.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,14 +19,16 @@
 
 import java.text.ParseException;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.util.DeweyDecimal;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * <p>Utility class that represents either an available "Optional Package"
@@ -167,25 +169,16 @@
     public static Specification[] getSpecifications(final Manifest manifest)
         throws ParseException {
         if (null == manifest) {
-            return new Specification[ 0 ];
+            return new Specification[0];
         }
+        final List<Specification> results = new ArrayList<>();
 
-        final ArrayList results = new ArrayList();
-
-        final Map entries = manifest.getEntries();
-        final Iterator keys = entries.keySet().iterator();
-        while (keys.hasNext()) {
-            final String key = (String) keys.next();
-            final Attributes attributes = (Attributes) entries.get(key);
-            final Specification specification
-                = getSpecification(key, attributes);
-            if (null != specification) {
-                results.add(specification);
-            }
+        for (Map.Entry<String, Attributes> e : manifest.getEntries().entrySet()) {
+            Optional.ofNullable(getSpecification(e.getKey(), e.getValue()))
+                .ifPresent(results::add);
         }
-
-        final ArrayList trimmedResults = removeDuplicates(results);
-        return (Specification[]) trimmedResults.toArray(new Specification[trimmedResults.size()]);
+        return removeDuplicates(results)
+            .toArray(new Specification[0]);
     }
 
     /**
@@ -239,10 +232,10 @@
                 this.specificationVersion
                     = new DeweyDecimal(specificationVersion);
             } catch (final NumberFormatException nfe) {
-                final String error = "Bad specification version format '"
-                    + specificationVersion + "' in '" + specificationTitle
-                    + "'. (Reason: " + nfe + ")";
-                throw new IllegalArgumentException(error);
+                throw new IllegalArgumentException(
+                    "Bad specification version format '" + specificationVersion
+                        + "' in '" + specificationTitle + "'. (Reason: " + nfe
+                        + ")");
             }
         }
 
@@ -253,13 +246,7 @@
         if (null == this.specificationTitle) {
             throw new NullPointerException("specificationTitle");
         }
-
-        String[] copy = null;
-        if (null != sections) {
-            copy = new String[ sections.length ];
-            System.arraycopy(sections, 0, copy, 0, sections.length);
-        }
-        this.sections = copy;
+        this.sections = sections == null ? null : sections.clone();
     }
 
     /**
@@ -324,12 +311,7 @@
      *         or null if relevant to no sections.
      */
     public String[] getSections() {
-        if (null == sections) {
-            return null;
-        }
-        final String[] newSections = new String[ sections.length ];
-        System.arraycopy(sections, 0, newSections, 0, sections.length);
-        return newSections;
+        return sections == null ? null : sections.clone();
     }
 
     /**
@@ -348,33 +330,22 @@
         }
 
         // Available specification version must be >= required
-        final DeweyDecimal otherSpecificationVersion
-            = other.getSpecificationVersion();
-        if (null != specificationVersion) {
-            if (null == otherSpecificationVersion
-                || !isCompatible(specificationVersion, otherSpecificationVersion)) {
-                return REQUIRE_SPECIFICATION_UPGRADE;
-            }
+        final DeweyDecimal otherSpecificationVersion = other.getSpecificationVersion();
+        if (null != specificationVersion && (null == otherSpecificationVersion
+                || !isCompatible(specificationVersion, otherSpecificationVersion))) {
+            return REQUIRE_SPECIFICATION_UPGRADE;
         }
 
         // Implementation Vendor ID must match
-        final String otherImplementationVendor
-            = other.getImplementationVendor();
-        if (null != implementationVendor) {
-            if (null == otherImplementationVendor
-                || !implementationVendor.equals(otherImplementationVendor)) {
-                return REQUIRE_VENDOR_SWITCH;
-            }
+        if (null != implementationVendor
+                && !implementationVendor.equals(other.getImplementationVendor())) {
+            return REQUIRE_VENDOR_SWITCH;
         }
 
         // Implementation version must be >= required
-        final String otherImplementationVersion
-            = other.getImplementationVersion();
-        if (null != implementationVersion) {
-            if (null == otherImplementationVersion
-                || !implementationVersion.equals(otherImplementationVersion)) {
-                return REQUIRE_IMPLEMENTATION_CHANGE;
-            }
+        if (null != implementationVersion
+                && !implementationVersion.equals(other.getImplementationVersion())) {
+            return REQUIRE_IMPLEMENTATION_CHANGE;
         }
 
         // This available optional package satisfies the requirements
@@ -390,7 +361,7 @@
      * @return true if the specification is compatible with this specification
      */
     public boolean isCompatibleWith(final Specification other) {
-        return (COMPATIBLE == getCompatibilityWith(other));
+        return COMPATIBLE == getCompatibilityWith(other);
     }
 
     /**
@@ -398,48 +369,31 @@
      *
      * @return string representation of object.
      */
+    @Override
     public String toString() {
-        final String brace = ": ";
+        final String format = "%s: %s%n";
 
-        final StringBuffer sb
-            = new StringBuffer(SPECIFICATION_TITLE.toString());
-        sb.append(brace);
-        sb.append(specificationTitle);
-        sb.append(StringUtils.LINE_SEP);
+        final StringBuilder sb = new StringBuilder(String.format(format,
+                SPECIFICATION_TITLE, specificationTitle));
 
         if (null != specificationVersion) {
-            sb.append(SPECIFICATION_VERSION);
-            sb.append(brace);
-            sb.append(specificationVersion);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, SPECIFICATION_VERSION, specificationVersion));
         }
 
         if (null != specificationVendor) {
-            sb.append(SPECIFICATION_VENDOR);
-            sb.append(brace);
-            sb.append(specificationVendor);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, SPECIFICATION_VENDOR, specificationVendor));
         }
 
         if (null != implementationTitle) {
-            sb.append(IMPLEMENTATION_TITLE);
-            sb.append(brace);
-            sb.append(implementationTitle);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_TITLE, implementationTitle));
         }
 
         if (null != implementationVersion) {
-            sb.append(IMPLEMENTATION_VERSION);
-            sb.append(brace);
-            sb.append(implementationVersion);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_VERSION, implementationVersion));
         }
 
         if (null != implementationVendor) {
-            sb.append(IMPLEMENTATION_VENDOR);
-            sb.append(brace);
-            sb.append(implementationVendor);
-            sb.append(StringUtils.LINE_SEP);
+            sb.append(String.format(format, IMPLEMENTATION_VENDOR, implementationVendor));
         }
 
         return sb.toString();
@@ -467,30 +421,24 @@
      * @param list the array of results to trim
      * @return an array list with all duplicates removed
      */
-    private static ArrayList removeDuplicates(final ArrayList list) {
-        final ArrayList results = new ArrayList();
-        final ArrayList sections = new ArrayList();
-        while (list.size() > 0) {
-            final Specification specification = (Specification) list.remove(0);
-            final Iterator iterator = list.iterator();
-            while (iterator.hasNext()) {
-                final Specification other = (Specification) iterator.next();
+    private static List<Specification> removeDuplicates(final List<Specification> list) {
+        final List<Specification> results = new ArrayList<>();
+        final List<String> sections = new ArrayList<>();
+        while (!list.isEmpty()) {
+            final Specification specification = list.remove(0);
+            for (final Iterator<Specification> iterator =
+                list.iterator(); iterator.hasNext();) {
+                final Specification other = iterator.next();
                 if (isEqual(specification, other)) {
-                    final String[] otherSections = other.getSections();
-                    if (null != otherSections) {
-                        sections.addAll(Arrays.asList(otherSections));
-                    }
+                    Optional.ofNullable(other.getSections())
+                        .ifPresent(s -> Collections.addAll(sections, s));
                     iterator.remove();
                 }
             }
-
-            final Specification merged =
-                mergeInSections(specification, sections);
-            results.add(merged);
-            //Reset list of sections
+            results.add(mergeInSections(specification, sections));
+            // Reset list of sections
             sections.clear();
         }
-
         return results;
     }
 
@@ -522,22 +470,19 @@
      * @return the merged specification
      */
     private static Specification mergeInSections(final Specification specification,
-                                              final ArrayList sectionsToAdd) {
-        if (0 == sectionsToAdd.size()) {
+                                              final List<String> sectionsToAdd) {
+        if (sectionsToAdd.isEmpty()) {
             return specification;
         }
-        sectionsToAdd.addAll(Arrays.asList(specification.getSections()));
-
-        final String[] sections =
-            (String[]) sectionsToAdd.toArray(new String[sectionsToAdd.size()]);
+        Stream<String> sections = Stream.concat(Optional.ofNullable(specification.getSections())
+                        .map(Stream::of).orElse(Stream.empty()), sectionsToAdd.stream());
 
         return new Specification(specification.getSpecificationTitle(),
                 specification.getSpecificationVersion().toString(),
                 specification.getSpecificationVendor(),
                 specification.getImplementationTitle(),
                 specification.getImplementationVersion(),
-                specification.getImplementationVendor(),
-                sections);
+                specification.getImplementationVendor(), sections.toArray(String[]::new));
     }
 
     /**
@@ -562,38 +507,32 @@
         //WARNING: We trim the values of all the attributes because
         //Some extension declarations are badly defined (ie have spaces
         //after version or vendor)
-        final String name
-            = getTrimmedString(attributes.getValue(SPECIFICATION_TITLE));
+        final String name = getTrimmedString(attributes.getValue(SPECIFICATION_TITLE));
         if (null == name) {
             return null;
         }
 
-        final String specVendor
-            = getTrimmedString(attributes.getValue(SPECIFICATION_VENDOR));
+        final String specVendor = getTrimmedString(attributes.getValue(SPECIFICATION_VENDOR));
         if (null == specVendor) {
             throw new ParseException(MISSING + SPECIFICATION_VENDOR, 0);
         }
 
-        final String specVersion
-            = getTrimmedString(attributes.getValue(SPECIFICATION_VERSION));
+        final String specVersion = getTrimmedString(attributes.getValue(SPECIFICATION_VERSION));
         if (null == specVersion) {
             throw new ParseException(MISSING + SPECIFICATION_VERSION, 0);
         }
 
-        final String impTitle
-            = getTrimmedString(attributes.getValue(IMPLEMENTATION_TITLE));
+        final String impTitle = getTrimmedString(attributes.getValue(IMPLEMENTATION_TITLE));
         if (null == impTitle) {
             throw new ParseException(MISSING + IMPLEMENTATION_TITLE, 0);
         }
 
-        final String impVersion
-            = getTrimmedString(attributes.getValue(IMPLEMENTATION_VERSION));
+        final String impVersion = getTrimmedString(attributes.getValue(IMPLEMENTATION_VERSION));
         if (null == impVersion) {
             throw new ParseException(MISSING + IMPLEMENTATION_VERSION, 0);
         }
 
-        final String impVendor
-            = getTrimmedString(attributes.getValue(IMPLEMENTATION_VENDOR));
+        final String impVendor = getTrimmedString(attributes.getValue(IMPLEMENTATION_VENDOR));
         if (null == impVendor) {
             throw new ParseException(MISSING + IMPLEMENTATION_VENDOR, 0);
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/AntResolver.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/AntResolver.java
index 6284679..b02e414 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/AntResolver.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/AntResolver.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -66,6 +66,7 @@
      * @return the file resolved
      * @throws BuildException if the file cannot be resolved
      */
+    @Override
     public File resolve(final Extension extension,
                          final Project project) throws BuildException {
         validate();
@@ -111,6 +112,7 @@
      * Returns a string representation
      * @return the string representation
      */
+    @Override
     public String toString() {
         return "Ant[" + antfile + "==>" + destfile + "]";
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/LocationResolver.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/LocationResolver.java
index e2fec02..0358aef 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/LocationResolver.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/LocationResolver.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,19 +46,19 @@
      * @return the file resolved
      * @throws BuildException if no location is set
      */
+    @Override
     public File resolve(final Extension extension,
                         final Project project) throws BuildException {
         if (null == location) {
-            final String message = "No location specified for resolver";
-            throw new BuildException(message);
+            throw new BuildException("No location specified for resolver");
         }
-
         return project.resolveFile(location);
     }
     /**
      * Returns a string representation of the Location
      * @return the string representation
      */
+    @Override
     public String toString() {
         return "Location[" + location + "]";
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/URLResolver.java b/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/URLResolver.java
index d693b89..6ac3232 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/URLResolver.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/extension/resolvers/URLResolver.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -66,6 +66,7 @@
      * @return file the file resolved
      * @throws BuildException if the URL is invalid
      */
+    @Override
     public File resolve(final Extension extension,
                          final Project project) throws BuildException {
         validate();
@@ -110,16 +111,15 @@
      */
     private void validate() {
         if (null == url) {
-            final String message = "Must specify URL";
-            throw new BuildException(message);
+            throw new BuildException("Must specify URL");
         }
-
         if (null == destdir && null == destfile) {
-            final String message = "Must specify destination file or directory";
-            throw new BuildException(message);
-        } else if (null != destdir && null != destfile) {
-            final String message = "Must not specify both destination file or directory";
-            throw new BuildException(message);
+            throw new BuildException(
+                "Must specify destination file or directory");
+        }
+        if (null != destdir && null != destfile) {
+            throw new BuildException(
+                "Must not specify both destination file or directory");
         }
     }
 
@@ -127,6 +127,7 @@
      * Returns a string representation of the URL
      * @return the string representation
      */
+    @Override
     public String toString() {
         return "URL[" + url + "]";
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/i18n/Translate.java b/src/main/org/apache/tools/ant/taskdefs/optional/i18n/Translate.java
index 330a98c..f84aebe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/i18n/Translate.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/i18n/Translate.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,13 +20,15 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.nio.file.Files;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -137,12 +139,12 @@
     /**
      * Vector to hold source file sets.
      */
-    private Vector filesets = new Vector();
+    private List<FileSet> filesets = new Vector<>();
 
     /**
      * Holds key value pairs loaded from resource bundle file
      */
-    private Hashtable resourceMap = new Hashtable();
+    private Map<String, String> resourceMap = new Hashtable<>();
     /**
 
      * Used to resolve file names.
@@ -268,7 +270,7 @@
      * @param set the fileset to be added
      */
     public void addFileset(FileSet set) {
-        filesets.addElement(set);
+        filesets.add(set);
     }
 
     /**
@@ -280,6 +282,7 @@
      *       <li>endtoken</li>
      *            </ul>
      */
+    @Override
     public void execute() throws BuildException {
         if (bundle == null) {
             throw new BuildException("The bundle attribute must be set.",
@@ -318,7 +321,7 @@
         if (!toDir.exists()) {
             toDir.mkdirs();
         } else if (toDir.isFile()) {
-            throw new BuildException(toDir + " is not a directory");
+            throw new BuildException("%s is not a directory", toDir);
         }
 
         if (srcEncoding == null) {
@@ -361,44 +364,28 @@
         Locale locale = new Locale(bundleLanguage,
                                    bundleCountry,
                                    bundleVariant);
-        String language = locale.getLanguage().length() > 0
-            ? "_" + locale.getLanguage() : "";
-        String country = locale.getCountry().length() > 0
-            ? "_" + locale.getCountry() : "";
-        String variant = locale.getVariant().length() > 0
-            ? "_" + locale.getVariant() : "";
-        String bundleFile = bundle + language + country + variant;
-        processBundle(bundleFile, BUNDLE_SPECIFIED_LANGUAGE_COUNTRY_VARIANT, false);
 
-        bundleFile = bundle + language + country;
-        processBundle(bundleFile, BUNDLE_SPECIFIED_LANGUAGE_COUNTRY, false);
+        String language = locale.getLanguage().isEmpty() ? "" : "_" + locale.getLanguage();
+        String country = locale.getCountry().isEmpty() ? "" : "_" + locale.getCountry();
+        String variant = locale.getVariant().isEmpty() ? "" : "_" + locale.getVariant();
 
-        bundleFile = bundle + language;
-        processBundle(bundleFile, BUNDLE_SPECIFIED_LANGUAGE, false);
-
-        bundleFile = bundle;
-        processBundle(bundleFile, BUNDLE_NOMATCH, false);
+        processBundle(bundle + language + country + variant, BUNDLE_SPECIFIED_LANGUAGE_COUNTRY_VARIANT, false);
+        processBundle(bundle + language + country, BUNDLE_SPECIFIED_LANGUAGE_COUNTRY, false);
+        processBundle(bundle + language, BUNDLE_SPECIFIED_LANGUAGE, false);
+        processBundle(bundle, BUNDLE_NOMATCH, false);
 
         //Load default locale bundle files
         //using default file encoding scheme.
         locale = Locale.getDefault();
 
-        language = locale.getLanguage().length() > 0
-            ? "_" + locale.getLanguage() : "";
-        country = locale.getCountry().length() > 0
-            ? "_" + locale.getCountry() : "";
-        variant = locale.getVariant().length() > 0
-            ? "_" + locale.getVariant() : "";
+        language = locale.getLanguage().isEmpty() ? "" : "_" + locale.getLanguage();
+        country = locale.getCountry().isEmpty() ? "" : "_" + locale.getCountry();
+        variant = locale.getVariant().isEmpty() ? "" : "_" + locale.getVariant();
         bundleEncoding = System.getProperty("file.encoding");
 
-        bundleFile = bundle + language + country + variant;
-        processBundle(bundleFile, BUNDLE_DEFAULT_LANGUAGE_COUNTRY_VARIANT, false);
-
-        bundleFile = bundle + language + country;
-        processBundle(bundleFile, BUNDLE_DEFAULT_LANGUAGE_COUNTRY, false);
-
-        bundleFile = bundle + language;
-        processBundle(bundleFile, BUNDLE_DEFAULT_LANGUAGE, true);
+        processBundle(bundle + language + country + variant, BUNDLE_DEFAULT_LANGUAGE_COUNTRY_VARIANT, false);
+        processBundle(bundle + language + country, BUNDLE_DEFAULT_LANGUAGE_COUNTRY, false);
+        processBundle(bundle + language, BUNDLE_DEFAULT_LANGUAGE, true);
     }
 
     /**
@@ -407,9 +394,9 @@
     private void processBundle(final String bundleFile, final int i,
                                final boolean checkLoaded) throws BuildException {
         final File propsFile = getProject().resolveFile(bundleFile + ".properties");
-        FileInputStream ins = null;
+        InputStream ins = null;
         try {
-            ins = new FileInputStream(propsFile);
+            ins = Files.newInputStream(propsFile.toPath());
             loaded = true;
             bundleLastModified[i] = propsFile.lastModified();
             log("Using " + propsFile, Project.MSG_DEBUG);
@@ -429,12 +416,10 @@
      * Load resourceMap with key value pairs.  Values of existing keys
      * are not overwritten.  Bundle's encoding scheme is used.
      */
-    private void loadResourceMap(FileInputStream ins) throws BuildException {
-        try {
-            BufferedReader in = null;
-            InputStreamReader isr = new InputStreamReader(ins, bundleEncoding);
-            in = new BufferedReader(isr);
-            String line = null;
+    private void loadResourceMap(InputStream ins) throws BuildException {
+        try (BufferedReader in =
+            new BufferedReader(new InputStreamReader(ins, bundleEncoding))) {
+            String line;
             while ((line = in.readLine()) != null) {
                 //So long as the line isn't empty and isn't a comment...
                 if (line.trim().length() > 1 && '#' != line.charAt(0) && '!' != line.charAt(0)) {
@@ -460,23 +445,18 @@
                             value = value.substring(0, value.length() - 1);
                             line = in.readLine();
                             if (line != null) {
-                                value = value + line.trim();
+                                value += line.trim();
                             } else {
                                 break;
                             }
                         }
-                        if (key.length() > 0) {
+                        if (!key.isEmpty()) {
                             //Has key already been loaded into resourceMap?
-                            if (resourceMap.get(key) == null) {
-                                resourceMap.put(key, value);
-                            }
+                            resourceMap.putIfAbsent(key, value);
                         }
                     }
                 }
             }
-            if (in != null) {
-                in.close();
-            }
         } catch (IOException ioe) {
             throw new BuildException(ioe.getMessage(), getLocation());
         }
@@ -496,9 +476,7 @@
      */
     private void translate() throws BuildException {
         int filesProcessed = 0;
-        final int size = filesets.size();
-        for (int i = 0; i < size; i++) {
-            FileSet fs = (FileSet) filesets.elementAt(i);
+        for (FileSet fs : filesets) {
             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
             for (String srcFile : ds.getIncludedFiles()) {
                 try {
@@ -545,18 +523,14 @@
     }
 
     private void translateOneFile(File src, File dest) throws IOException {
-        BufferedWriter out = null;
-        BufferedReader in = null;
-        try {
-            FileOutputStream fos = new FileOutputStream(dest);
-            out = new BufferedWriter(new OutputStreamWriter(fos, destEncoding));
-            FileInputStream fis = new FileInputStream(src);
-            in = new BufferedReader(new InputStreamReader(fis, srcEncoding));
-            String line;
+        try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
+            Files.newOutputStream(dest.toPath()), destEncoding));
+                BufferedReader in = new BufferedReader(new InputStreamReader(
+                    Files.newInputStream(src.toPath()), srcEncoding))) {
             LineTokenizer lineTokenizer = new LineTokenizer();
             lineTokenizer.setIncludeDelims(true);
-            line = lineTokenizer.getToken(in);
-            while ((line) != null) {
+            String line = lineTokenizer.getToken(in);
+            while (line != null) {
                 // 2003-02-21 new replace algorithm by tbee (tbee@tbee.org)
                 // because it wasn't able to replace something like "@aaa;@bbb;"
 
@@ -598,7 +572,7 @@
                         } else {
                             // find the replace string
                             if (resourceMap.containsKey(token)) {
-                                replace = (String) resourceMap.get(token);
+                                replace = resourceMap.get(token);
                             } else {
                                 log("Replacement string missing for: " + token,
                                     Project.MSG_VERBOSE);
@@ -621,9 +595,6 @@
                 out.write(line);
                 line = lineTokenizer.getToken(in);
             }
-        } finally {
-            FileUtils.close(in);
-            FileUtils.close(out);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/image/Image.java b/src/main/org/apache/tools/ant/taskdefs/optional/image/Image.java
index 635b3bf..cd04da5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/image/Image.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/image/Image.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,9 @@
 package org.apache.tools.ant.taskdefs.optional.image;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.Locale;
 import java.util.Vector;
 
@@ -27,7 +28,6 @@
 import javax.media.jai.PlanarImage;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.MatchingTask;
 import org.apache.tools.ant.types.FileSet;
@@ -38,7 +38,6 @@
 import org.apache.tools.ant.types.optional.image.Scale;
 import org.apache.tools.ant.types.optional.image.TransformOperation;
 import org.apache.tools.ant.util.FileNameMapper;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.IdentityMapper;
 import org.apache.tools.ant.util.StringUtils;
 
@@ -46,22 +45,23 @@
 
 /**
  * A MatchingTask which relies on <a
- * href="http://java.sun.com/products/java-media/jai">JAI (Java
+ * href="https://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-client-419417.html">JAI (Java
  * Advanced Imaging)</a> to perform image manipulation operations on
  * existing images.  The operations are represented as ImageOperation
  * DataType objects.  The operations are arranged to conform to the
- * Chaining Model of JAI.  Check out the <a
- * href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/">
- * JAI Programming Guide</a>.
+ * Chaining Model of JAI.  Check out the JAI Programming Guide.
  *
+ * @deprecated JAI is not developed any more. Internal APIs that JAI depends on were
+ * scheduled for removal in Java 7 and finally removed in Java 9.
  * @see org.apache.tools.ant.types.optional.image.ImageOperation
  * @see org.apache.tools.ant.types.DataType
  */
+@Deprecated
 public class Image extends MatchingTask {
     // CheckStyle:VisibilityModifier OFF - bc
-    protected Vector instructions = new Vector();
+    protected Vector<ImageOperation> instructions = new Vector<>();
     protected boolean overwrite = false;
-    protected Vector filesets = new Vector();
+    protected Vector<FileSet> filesets = new Vector<>();
     protected File srcDir = null;
     protected File destDir = null;
 
@@ -84,7 +84,7 @@
      * @param set the FileSet to add.
      */
     public void addFileset(FileSet set) {
-        filesets.addElement(set);
+        filesets.add(set);
     }
 
     /**
@@ -105,9 +105,8 @@
     }
 
     /**
-     * Set the image encoding type.  <a
-     * href="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Encode.doc.html#56610">
-     * See this table in the JAI Programming Guide</a>.
+     * Set the image encoding type. 
+     * See the encoding table in the JAI Programming Guide.
      * @param encoding the String image encoding.
      */
     public void setEncoding(String encoding) {
@@ -233,14 +232,12 @@
                 continue;
             }
 
-            for (int j = 0; j < dstNames.length; ++j){
-
-                final String dstName = dstNames[j];
+            for (String dstName : dstNames) {
                 final File dstFile = new File(dstDir, dstName).getAbsoluteFile();
 
                 if (dstFile.exists()) {
                     // avoid overwriting unless necessary
-                    if(!overwrite
+                    if (!overwrite
                        && srcFile.lastModified() <= dstFile.lastModified()) {
 
                         log(srcFile + " omitted as " + dstFile
@@ -274,6 +271,7 @@
      * @param file The file to be processed.
      * @deprecated this method isn't used anymore
      */
+    @Deprecated
     public void processFile(File file) {
         processFile(file, new File(destDir == null
                                    ? srcDir : destDir, file.getName()));
@@ -290,14 +288,10 @@
         try {
             log("Processing File: " + file.getAbsolutePath());
 
-            FileSeekableStream input = null;
             PlanarImage image = null;
-            try {
-                input = new FileSeekableStream(file);
+            try (FileSeekableStream input = new FileSeekableStream(file)) {
                 image = JAI.create("stream", input);
-                final int size = instructions.size();
-                for (int i = 0; i < size; i++) {
-                    Object instr = instructions.elementAt(i);
+                for (ImageOperation instr : instructions) {
                     if (instr instanceof TransformOperation) {
                         image = ((TransformOperation) instr)
                             .executeTransformOperation(image);
@@ -305,33 +299,25 @@
                         log("Not a TransformOperation: " + instr);
                     }
                 }
-            } finally {
-                FileUtils.close(input);
             }
 
             File dstParent = newFile.getParentFile();
             if (!dstParent.isDirectory()
                 && !(dstParent.mkdirs() || dstParent.isDirectory())) {
-                throw new BuildException("Failed to create parent directory "
-                                         + dstParent);
+                throw new BuildException("Failed to create parent directory %s",
+                    dstParent);
             }
 
             if (overwrite && newFile.exists() && !newFile.equals(file)) {
                 newFile.delete();
             }
 
-            FileOutputStream stream = null;
-            try {
-                stream = new FileOutputStream(newFile);
-
+            try (OutputStream stream = Files.newOutputStream(newFile.toPath())) {
                 JAI.create("encode", image, stream,
-                           str_encoding.toUpperCase(Locale.ENGLISH),
-                           null);
+                    str_encoding.toUpperCase(Locale.ENGLISH), null);
                 stream.flush();
-            } finally {
-                FileUtils.close(stream);
             }
-        } catch (IOException err) {
+        } catch (IOException | RuntimeException err) {
             if (!file.equals(newFile)) {
                 newFile.delete();
             }
@@ -340,15 +326,6 @@
             } else {
                 throw new BuildException(err);
             }
-        } catch (java.lang.RuntimeException rerr) {
-            if (!file.equals(newFile)){
-                newFile.delete();
-            }
-            if (!failonerror) {
-                log("Error processing file:  " + rerr);
-            } else {
-                throw new BuildException(rerr);
-            }
         }
     }
 
@@ -356,6 +333,7 @@
      * Executes the Task.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
 
         validateAttributes();
@@ -366,29 +344,20 @@
             int writeCount = 0;
 
             // build mapper
-            final FileNameMapper mapper;
-            if (mapperElement==null){
-                mapper = new IdentityMapper();
-            } else {
-                mapper = mapperElement.getImplementation();
-            }
+            final FileNameMapper mapper = mapperElement == null
+                ? new IdentityMapper() : mapperElement.getImplementation();
 
             // deal with specified srcDir
             if (srcDir != null) {
-                final DirectoryScanner ds = super.getDirectoryScanner(srcDir);
-
-                final String[] files = ds.getIncludedFiles();
-                writeCount += processDir(srcDir, files, dest, mapper);
+                writeCount += processDir(srcDir,
+                    super.getDirectoryScanner(srcDir).getIncludedFiles(), dest,
+                    mapper);
             }
             // deal with the filesets
-            final int size = filesets.size();
-            for (int i = 0; i < size; i++) {
-                final FileSet fs = (FileSet) filesets.elementAt(i);
-                final DirectoryScanner ds =
-                    fs.getDirectoryScanner(getProject());
-                final String[] files = ds.getIncludedFiles();
-                final File fromDir = fs.getDir(getProject());
-                writeCount += processDir(fromDir, files, dest, mapper);
+            for (FileSet fs : filesets) {
+                writeCount += processDir(fs.getDir(),
+                    fs.getDirectoryScanner().getIncludedFiles(),
+                    dest, mapper);
             }
 
             if (writeCount > 0) {
@@ -408,16 +377,16 @@
      * @throws BuildException on error.
      */
     protected void validateAttributes() throws BuildException {
-        if (srcDir == null && filesets.size() == 0) {
-            throw new BuildException("Specify at least one source"
-                                     + "--a srcDir or a fileset.");
+        if (srcDir == null && filesets.isEmpty()) {
+            throw new BuildException(
+                "Specify at least one source--a srcDir or a fileset.");
         }
         if (srcDir == null && destDir == null) {
             throw new BuildException("Specify the destDir, or the srcDir.");
         }
-        if (str_encoding.equalsIgnoreCase("jpg")) {
+        if ("jpg".equalsIgnoreCase(str_encoding)) {
             str_encoding = "JPEG";
-        } else if (str_encoding.equalsIgnoreCase("tif")) {
+        } else if ("tif".equalsIgnoreCase(str_encoding)) {
             str_encoding = "TIFF";
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/image/ImageIOTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/image/ImageIOTask.java
new file mode 100644
index 0000000..6cd5649
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/image/ImageIOTask.java
@@ -0,0 +1,410 @@
+/*
+ *  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
+ *
+ *      https://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.image;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.MatchingTask;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Mapper;
+import org.apache.tools.ant.types.optional.imageio.Draw;
+import org.apache.tools.ant.types.optional.imageio.ImageOperation;
+import org.apache.tools.ant.types.optional.imageio.Rotate;
+import org.apache.tools.ant.types.optional.imageio.Scale;
+import org.apache.tools.ant.types.optional.imageio.TransformOperation;
+import org.apache.tools.ant.util.FileNameMapper;
+import org.apache.tools.ant.util.IdentityMapper;
+import org.apache.tools.ant.util.StringUtils;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A MatchingTask which relies on Java ImageIO to read existing image files
+ * and write the results of AWT image manipulation operations.
+ * The operations are represented as ImageOperation DataType objects.
+ * The task replaces a JAI-based Image task which no longer works with Java 9+.
+ *
+ * @see ImageOperation
+ * @see org.apache.tools.ant.types.DataType
+ */
+public class ImageIOTask extends MatchingTask {
+    private final List<ImageOperation> instructions = new ArrayList<>();
+    private boolean overwrite = false;
+    private final List<FileSet> filesets = new ArrayList<>();
+    private File srcDir = null;
+    private File destDir = null;
+
+    private ImageFormat outputFormat;
+
+    private boolean garbageCollect = false;
+
+    private boolean failOnError = true;
+
+    private Mapper mapperElement = null;
+
+    /**
+     * Add a set of files to be deleted.
+     * @param set the FileSet to add.
+     */
+    public void addFileset(FileSet set) {
+        filesets.add(set);
+    }
+
+    /**
+     * Set whether to fail on error.
+     * If false, note errors to the output but keep going.
+     * @param flag true or false.
+     */
+    public void setFailOnError(boolean flag) {
+        failOnError = flag;
+    }
+
+    /**
+     * Set the source dir to find the image files.
+     * @param srcDir the directory in which the image files reside.
+     */
+    public void setSrcdir(File srcDir) {
+        this.srcDir = srcDir;
+    }
+
+    /**
+     * Set the output image format.
+     * @param format an ImageFormat.
+     */
+    public void setFormat(ImageFormat format) {
+        outputFormat = format;
+    }
+
+    /**
+     * Set whether to overwrite a file if there is a naming conflict.
+     * @param overwrite whether to overwrite.
+     */
+    public void setOverwrite(boolean overwrite) {
+        this.overwrite = overwrite;
+    }
+
+    /**
+     * Set whether to invoke Garbage Collection after each image processed.
+     * Defaults to false.
+     * @param gc whether to invoke the garbage collector.
+     */
+    public void setGc(boolean gc) {
+        garbageCollect = gc;
+    }
+
+    /**
+     * Set the destination directory for manipulated images.
+     * @param destDir The destination directory.
+     */
+    public void setDestDir(File destDir) {
+        this.destDir = destDir;
+    }
+
+    /**
+     * Add an ImageOperation to chain.
+     * @param instr The ImageOperation to append to the chain.
+     */
+    public void addImageOperation(ImageOperation instr) {
+        instructions.add(instr);
+    }
+
+    /**
+     * Add a Rotate ImageOperation to the chain.
+     * @param instr The Rotate operation to add to the chain.
+     * @see Rotate
+     */
+    public void addRotate(Rotate instr) {
+        instructions.add(instr);
+    }
+
+    /**
+     * Add a Scale ImageOperation to the chain.
+     * @param instr The Scale operation to add to the chain.
+     * @see Scale
+     */
+    public void addScale(Scale instr) {
+        instructions.add(instr);
+    }
+
+    /**
+     * Add a Draw ImageOperation to the chain.  DrawOperation
+     * DataType objects can be nested inside the Draw object.
+     * @param instr The Draw operation to add to the chain.
+     * @see Draw
+     * @see org.apache.tools.ant.types.optional.image.DrawOperation
+     */
+    public void addDraw(Draw instr) {
+        instructions.add(instr);
+    }
+
+    /**
+    * Add an ImageOperation to chain.
+    * @param instr The ImageOperation to append to the chain.
+    * @since Ant 1.7
+    */
+    public void add(ImageOperation instr) {
+        addImageOperation(instr);
+    }
+
+    /**
+     * Defines the mapper to map source to destination files.
+     * @return a mapper to be configured
+     * @exception BuildException if more than one mapper is defined
+     * @since Ant 1.8.0
+     */
+    public Mapper createMapper() throws BuildException {
+        if (mapperElement != null) {
+            throw new BuildException("Cannot define more than one mapper",
+                                     getLocation());
+        }
+        mapperElement = new Mapper(getProject());
+        return mapperElement;
+    }
+
+    /**
+     * Add a nested filenamemapper.
+     * @param fileNameMapper the mapper to add.
+     * @since Ant 1.8.0
+     */
+    public void add(FileNameMapper fileNameMapper) {
+        createMapper().add(fileNameMapper);
+    }
+
+    /**
+     * Executes all the chained ImageOperations on the files inside
+     * the directory.
+     * @param srcDir File
+     * @param srcNames String[]
+     * @param dstDir File
+     * @param mapper FileNameMapper
+     * @return int
+     * @since Ant 1.8.0
+     */
+    public int processDir(final File srcDir, final String[] srcNames,
+                          final File dstDir, final FileNameMapper mapper) {
+        int writeCount = 0;
+
+        for (final String srcName : srcNames) {
+            final File srcFile = new File(srcDir, srcName).getAbsoluteFile();
+
+            final String[] dstNames = mapper.mapFileName(srcName);
+            if (dstNames == null) {
+                log(srcFile + " skipped, don't know how to handle it",
+                    Project.MSG_VERBOSE);
+                continue;
+            }
+
+            for (String dstName : dstNames) {
+                final File dstFile = new File(dstDir, dstName).getAbsoluteFile();
+
+                if (dstFile.exists()) {
+                    // avoid overwriting unless necessary
+                    if (!overwrite
+                       && srcFile.lastModified() <= dstFile.lastModified()) {
+
+                        log(srcFile + " omitted as " + dstFile
+                            + " is up to date.", Project.MSG_VERBOSE);
+
+                        // don't overwrite the file
+                        continue;
+                    }
+
+                    // avoid extra work while overwriting
+                    if (!srcFile.equals(dstFile)) {
+                        dstFile.delete();
+                    }
+                }
+                processFile(srcFile, dstFile);
+                ++writeCount;
+            }
+        }
+
+        // run the garbage collector if wanted
+        if (garbageCollect) {
+            System.gc();
+        }
+
+        return writeCount;
+    }
+
+    /**
+     * Executes all the chained ImageOperations on the file
+     * specified.
+     * @param file The file to be processed.
+     * @deprecated this method isn't used anymore
+     */
+    @Deprecated
+    public void processFile(File file) {
+        processFile(file, new File(destDir == null
+                                   ? srcDir : destDir, file.getName()));
+    }
+
+    /**
+     * Executes all the chained ImageOperations on the file
+     * specified.
+     * @param file The file to be processed.
+     * @param newFile The file to write to.
+     * @since Ant 1.8.0
+     */
+    public void processFile(File file, File newFile) {
+        log("Processing File: " + file.getAbsolutePath());
+
+        try (ImageInputStream input = ImageIO.createImageInputStream(file)) {
+            Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
+            if (!readers.hasNext()) {
+                log("No decoder available, skipping");
+                return;
+            }
+            ImageReader reader = readers.next();
+            if (outputFormat == null) {
+                outputFormat = new ImageFormat(reader.getFormatName());
+            }
+            reader.setInput(input);
+
+            BufferedImage image = reader.read(0);
+            reader.dispose();
+
+            for (ImageOperation instr : instructions) {
+                if (instr instanceof TransformOperation) {
+                    image = ((TransformOperation) instr).executeTransformOperation(image);
+                } else {
+                    log("Not a TransformOperation: " + instr);
+                }
+            }
+
+            File dstParent = newFile.getParentFile();
+            if (!dstParent.isDirectory()
+                && !(dstParent.mkdirs() || dstParent.isDirectory())) {
+                throw new BuildException("Failed to create parent directory %s",
+                    dstParent);
+            }
+
+            if (overwrite && newFile.exists() && !newFile.equals(file)) {
+                newFile.delete();
+            }
+
+            if (!ImageIO.write(image, outputFormat.getValue(), newFile)) {
+                log("Failed to save the transformed file");
+            }
+        } catch (IOException | RuntimeException err) {
+            if (!file.equals(newFile)) {
+                newFile.delete();
+            }
+            if (!failOnError) {
+                log("Error processing file:  " + err);
+            } else {
+                throw new BuildException(err);
+            }
+        }
+    }
+
+    /**
+     * Executes the Task.
+     * @throws BuildException on error.
+     */
+    @Override
+    public void execute() throws BuildException {
+
+        validateAttributes();
+
+        try {
+            File dest = (destDir != null) ? destDir : srcDir;
+
+            int writeCount = 0;
+
+            // build mapper
+            final FileNameMapper mapper = mapperElement == null
+                ? new IdentityMapper() : mapperElement.getImplementation();
+
+            // deal with specified srcDir
+            if (srcDir != null) {
+                writeCount += processDir(srcDir,
+                    super.getDirectoryScanner(srcDir).getIncludedFiles(), dest,
+                    mapper);
+            }
+            // deal with the filesets
+            for (FileSet fs : filesets) {
+                writeCount += processDir(fs.getDir(),
+                    fs.getDirectoryScanner().getIncludedFiles(),
+                    dest, mapper);
+            }
+
+            if (writeCount > 0) {
+                log("Processed " + writeCount + (writeCount == 1 ? " image." : " images."));
+            }
+
+        } catch (Exception err) {
+            log(StringUtils.getStackTrace(err), Project.MSG_ERR);
+            throw new BuildException(err.getMessage());
+        }
+    }
+
+    /**
+     * Ensure we have a consistent and legal set of attributes, and set
+     * any internal flags necessary based on different combinations
+     * of attributes.
+     * @throws BuildException on error.
+     */
+    protected void validateAttributes() throws BuildException {
+        if (srcDir == null && filesets.isEmpty()) {
+            throw new BuildException(
+                "Specify at least one source--a srcDir or a fileset.");
+        }
+        if (srcDir == null && destDir == null) {
+            throw new BuildException("Specify the destDir, or the srcDir.");
+        }
+    }
+
+    /**
+     * defines acceptable image formats.
+     */
+    public static class ImageFormat extends EnumeratedAttribute {
+
+        private static final String[] VALUES = ImageIO.getReaderFormatNames();
+
+        /**
+         * Constructor
+         */
+        public ImageFormat() {
+        }
+
+        /**
+         * Constructor using a string.
+         * @param value the value of the attribute
+         */
+        public ImageFormat(String value) {
+            setValue(value);
+        }
+
+        /** {@inheritDoc}. */
+        @Override
+        public String[] getValues() {
+            return VALUES;
+        }
+    }
+}
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/AbstractHotDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/AbstractHotDeploymentTool.java
index 7c47f71..3a34b45 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/AbstractHotDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/AbstractHotDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -87,13 +87,14 @@
      *  base class.  Subclasses should check attributes accordingly.
      *  @throws BuildException if the attributes are invalid or incomplete.
      */
+    @Override
     public void validateAttributes() throws BuildException {
         if (task.getAction() == null) {
             throw new BuildException("The \"action\" attribute must be set");
         }
 
         if (!isActionValid()) {
-            throw new BuildException("Invalid action \"" + task.getAction() + "\" passed");
+            throw new BuildException("Invalid action \"%s\" passed", task.getAction());
         }
 
         if (classpath == null) {
@@ -102,17 +103,11 @@
     }
 
     /**
-     *  Perform the actual deployment.
-     *  It's up to the subclasses to implement the actual behavior.
-     *  @exception org.apache.tools.ant.BuildException if the attributes are invalid or incomplete.
-     */
-    public abstract void deploy() throws BuildException;
-
-    /**
      *  Sets the parent task.
      *  @param task a ServerDeploy object representing the parent task.
      *  @ant.attribute ignore="true"
      */
+    @Override
     public void setTask(ServerDeploy task) {
         this.task = task;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/GenericHotDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/GenericHotDeploymentTool.java
index e4a5b6b..451a5ea 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/GenericHotDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/GenericHotDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -70,8 +70,9 @@
      *  For this generic implementation, the only valid action is "deploy"
      *  @return true if the "action" attribute is valid, false if not.
      */
+    @Override
     protected boolean isActionValid() {
-        return (getTask().getAction().equals(VALID_ACTIONS[0]));
+        return getTask().getAction().equals(VALID_ACTIONS[0]);
     }
 
     /**
@@ -79,6 +80,7 @@
      *  @param task An ServerDeploy object representing the parent task.
      *  @ant.attribute ignored="true"
      */
+    @Override
     public void setTask(ServerDeploy task) {
         super.setTask(task);
         java = new Java(task);
@@ -90,6 +92,7 @@
      *  supplied classpath, classname, JVM args, and command line arguments.
      *  @exception BuildException if the attributes are invalid or incomplete.
      */
+    @Override
     public void deploy() throws BuildException {
         java.setClassname(className);
         java.setClasspath(getClasspath());
@@ -103,6 +106,7 @@
      *  Ensures the className and arguments attribute have been set.
      *  @throws BuildException if the attributes are invalid or incomplete.
      */
+    @Override
     public void validateAttributes() throws BuildException {
         super.validateAttributes();
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/HotDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/HotDeploymentTool.java
index dae9667..6f16322 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/HotDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/HotDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/JonasHotDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/JonasHotDeploymentTool.java
index 4c7866c..e146f00 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/JonasHotDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/JonasHotDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -76,7 +76,6 @@
      */
     private int davidPort;
 
-
     /**
      *  Set the host for the David ORB; required if
      *  ORB==david.
@@ -87,7 +86,6 @@
         davidHost = inValue;
     }
 
-
     /**
      *  Set the port for the David ORB; required if
      *  ORB==david.
@@ -98,7 +96,6 @@
         davidPort = inValue;
     }
 
-
     /**
      *  set the jonas root directory (-Dinstall.root=). This
      *  element is required.
@@ -109,7 +106,6 @@
         jonasroot = inValue;
     }
 
-
     /**
      *
      * Choose your ORB : RMI, JEREMIE, DAVID, ...; optional.
@@ -124,14 +120,13 @@
         orb = inValue;
     }
 
-
     /**
      *  gets the classpath field.
      *
      *@return    A Path representing the "classpath" attribute.
      */
+    @Override
     public Path getClasspath() {
-
         Path aClassPath = super.getClasspath();
 
         if (aClassPath == null) {
@@ -147,7 +142,6 @@
         return aClassPath;
     }
 
-
     /**
      * Validates the passed in attributes.
      *
@@ -161,6 +155,7 @@
      *
      * @exception BuildException if something goes wrong
      */
+    @Override
     public void validateAttributes() throws BuildException {
         // super.validateAttributes(); // don't want to call this method
 
@@ -172,7 +167,7 @@
         }
 
         if (!isActionValid()) {
-            throw new BuildException("Invalid action \"" + action + "\" passed");
+            throw new BuildException("Invalid action \"%s\" passed", action);
         }
 
         if (getClassName() == null) {
@@ -213,9 +208,9 @@
             java.createArg().setLine("-n " + getServer());
         }
 
-        if (action.equals(ACTION_DEPLOY)
-            || action.equals(ACTION_UPDATE)
-            || action.equals("redeploy")) {
+        if (ACTION_DEPLOY.equals(action)
+            || ACTION_UPDATE.equals(action)
+            || "redeploy".equals(action)) {
             java.createArg().setLine("-a " + getTask().getSource());
         } else if (action.equals(ACTION_DELETE) || action.equals(ACTION_UNDEPLOY)) {
             java.createArg().setLine("-r " + getTask().getSource());
@@ -224,7 +219,6 @@
         }
     }
 
-
     /**
      *  Determines if the action supplied is valid. <p>
      *
@@ -234,19 +228,17 @@
      *@return    true if the action attribute is valid, false if
      *      not.
      */
+    @Override
     protected boolean isActionValid() {
-        boolean valid = false;
-
         String action = getTask().getAction();
 
-        for (int i = 0; i < VALID_ACTIONS.length; i++) {
-            if (action.equals(VALID_ACTIONS[i])) {
-                valid = true;
-                break;
+        for (String validAction : VALID_ACTIONS) {
+            if (action.equals(validAction)) {
+                return true;
             }
         }
-
-        return valid;
+        // TODO what about redeploy, mentioned in #validateAttribute
+        return false;
     }
 }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/ServerDeploy.java b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/ServerDeploy.java
index 02d6f61..dee9478 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/ServerDeploy.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/ServerDeploy.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant.taskdefs.optional.j2ee;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
@@ -44,7 +44,7 @@
     private File source;
 
     /** The vendor specific tool for deploying the component **/
-    private Vector vendorTools = new Vector();
+    private List<AbstractHotDeploymentTool> vendorTools = new Vector<>();
 
     ///////////////////////////////////////////////////////////////////////////
     //
@@ -60,7 +60,7 @@
      */
     public void addGeneric(GenericHotDeploymentTool tool) {
         tool.setTask(this);
-        vendorTools.addElement(tool);
+        vendorTools.add(tool);
     }
 
     /**
@@ -71,7 +71,7 @@
      */
     public void addWeblogic(WebLogicHotDeploymentTool tool) {
         tool.setTask(this);
-        vendorTools.addElement(tool);
+        vendorTools.add(tool);
     }
 
     /**
@@ -82,7 +82,7 @@
      */
     public void addJonas(JonasHotDeploymentTool tool) {
         tool.setTask(this);
-        vendorTools.addElement(tool);
+        vendorTools.add(tool);
     }
 
 
@@ -100,10 +100,9 @@
      *  @throws BuildException if the attributes
      *  are invalid or incomplete, or a failure occurs in the deployment process.
      */
+    @Override
     public void execute() throws BuildException {
-        for (Enumeration e = vendorTools.elements();
-             e.hasMoreElements();) {
-            HotDeploymentTool tool = (HotDeploymentTool) e.nextElement();
+        for (HotDeploymentTool tool : vendorTools) {
             tool.validateAttributes();
             tool.deploy();
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/WebLogicHotDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/WebLogicHotDeploymentTool.java
index d0dc91b..bd014c4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/WebLogicHotDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/j2ee/WebLogicHotDeploymentTool.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -59,6 +59,7 @@
      *  tools is executed.
      *  @exception BuildException if the attributes are invalid or incomplete.
      */
+    @Override
     public void deploy() {
         Java java = new Java(getTask());
         java.setFork(true);
@@ -80,35 +81,36 @@
      *
      *  @exception BuildException if the attributes are invalid or incomplete
      */
+    @Override
     public void validateAttributes() throws BuildException {
         super.validateAttributes();
 
         String action = getTask().getAction();
 
         // check that the password has been set
-        if ((getPassword() == null)) {
+        if (getPassword() == null) {
             throw new BuildException("The password attribute must be set.");
         }
 
         // check for missing application on deploy & update
         if ((action.equals(ACTION_DEPLOY) || action.equals(ACTION_UPDATE))
             && application == null) {
-            throw new BuildException("The application attribute must be set "
-                + "if action = " + action);
+            throw new BuildException(
+                "The application attribute must be set if action = %s", action);
         }
 
         // check for missing source on deploy & update
         if ((action.equals(ACTION_DEPLOY) || action.equals(ACTION_UPDATE))
             && getTask().getSource() == null) {
-            throw new BuildException("The source attribute must be set if "
-                + "action = " + action);
+            throw new BuildException(
+                "The source attribute must be set if action = %s", action);
         }
 
         // check for missing application on delete & undeploy
         if ((action.equals(ACTION_DELETE) || action.equals(ACTION_UNDEPLOY))
             && application == null) {
-            throw new BuildException("The application attribute must be set if "
-                + "action = " + action);
+            throw new BuildException(
+                "The application attribute must be set if action = %s", action);
         }
     }
 
@@ -120,17 +122,17 @@
      */
     public String getArguments() throws BuildException {
         String action = getTask().getAction();
-        String args = null;
 
         if (action.equals(ACTION_DEPLOY) || action.equals(ACTION_UPDATE)) {
-            args = buildDeployArgs();
-        } else if (action.equals(ACTION_DELETE) || action.equals(ACTION_UNDEPLOY)) {
-            args = buildUndeployArgs();
-        } else if (action.equals(ACTION_LIST)) {
-            args = buildListArgs();
+            return buildDeployArgs();
         }
-
-        return args;
+        if (action.equals(ACTION_DELETE) || action.equals(ACTION_UNDEPLOY)) {
+            return buildUndeployArgs();
+        }
+        if (action.equals(ACTION_LIST)) {
+            return buildListArgs();
+        }
+        return null;
     }
 
     /**
@@ -138,19 +140,16 @@
      * <p>Valid actions are contained in the static array VALID_ACTIONS</p>
      * @return true if the action attribute is valid, false if not.
      */
+    @Override
     protected boolean isActionValid() {
-        boolean valid = false;
-
         String action = getTask().getAction();
 
-        for (int i = 0; i < VALID_ACTIONS.length; i++) {
-            if (action.equals(VALID_ACTIONS[i])) {
-                valid = true;
-                break;
+        for (String validAction : VALID_ACTIONS) {
+            if (action.equals(validAction)) {
+                return true;
             }
         }
-
-        return valid;
+        return false;
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJDoc.java b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJDoc.java
index a4dc0f4..e774344 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJDoc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJDoc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,8 +20,8 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -44,7 +44,7 @@
     private static final String TEXT              = "TEXT";
     private static final String ONE_TABLE         = "ONE_TABLE";
 
-    private final Hashtable optionalAttrs = new Hashtable();
+    private final Map<String, Object> optionalAttrs = new Hashtable<>();
 
     private String outputFile = null;
     private boolean plainText = false;
@@ -65,7 +65,7 @@
      * @param plainText a <code>boolean</code> value.
      */
     public void setText(boolean plainText) {
-        optionalAttrs.put(TEXT, plainText ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(TEXT, plainText);
         this.plainText = plainText;
     }
 
@@ -74,7 +74,7 @@
      * @param oneTable a <code>boolean</code> value.
      */
     public void setOnetable(boolean oneTable) {
-        optionalAttrs.put(ONE_TABLE, oneTable ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(ONE_TABLE, oneTable);
     }
 
     /**
@@ -124,19 +124,15 @@
      * Do the task.
      * @throws BuildException if there is an error.
      */
+    @Override
     public void execute() throws BuildException {
 
         // load command line with optional attributes
-        Enumeration iter = optionalAttrs.keys();
-        while (iter.hasMoreElements()) {
-            String name  = (String) iter.nextElement();
-            Object value = optionalAttrs.get(name);
-            cmdl.createArgument()
-                .setValue("-" + name + ":" + value.toString());
-        }
+        optionalAttrs.forEach((name, value) -> cmdl.createArgument()
+            .setValue("-" + name + ":" + value.toString()));
 
         if (targetFile == null || !targetFile.isFile()) {
-            throw new BuildException("Invalid target: " + targetFile);
+            throw new BuildException("Invalid target: %s", targetFile);
         }
 
         if (outputFile != null) {
@@ -195,8 +191,8 @@
             suffix = DEFAULT_SUFFIX_TEXT;
         }
 
-        if ((optionalOutputFile == null) || optionalOutputFile.equals("")) {
-            int filePos = javaccFile.lastIndexOf("/");
+        if (optionalOutputFile == null || optionalOutputFile.isEmpty()) {
+            int filePos = javaccFile.lastIndexOf('/');
 
             if (filePos >= 0) {
                 javaccFile = javaccFile.substring(filePos + 1);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java
index 3d51afb..b552c8e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,8 +20,8 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -54,7 +54,7 @@
     private static final String VISITOR_EXCEPTION = "VISITOR_EXCEPTION";
     private static final String NODE_PREFIX       = "NODE_PREFIX";
 
-    private final Hashtable optionalAttrs = new Hashtable();
+    private final Map<String, Object> optionalAttrs = new Hashtable<>();
 
     private String outputFile = null;
 
@@ -74,7 +74,7 @@
      * @param buildNodeFiles a <code>boolean</code> value.
      */
     public void setBuildnodefiles(boolean buildNodeFiles) {
-        optionalAttrs.put(BUILD_NODE_FILES, buildNodeFiles ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(BUILD_NODE_FILES, buildNodeFiles);
     }
 
     /**
@@ -82,7 +82,7 @@
      * @param multi a <code>boolean</code> value.
      */
     public void setMulti(boolean multi) {
-        optionalAttrs.put(MULTI, multi ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(MULTI, multi);
     }
 
     /**
@@ -90,7 +90,7 @@
      * @param nodeDefaultVoid a <code>boolean</code> value.
      */
     public void setNodedefaultvoid(boolean nodeDefaultVoid) {
-        optionalAttrs.put(NODE_DEFAULT_VOID, nodeDefaultVoid ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(NODE_DEFAULT_VOID, nodeDefaultVoid);
     }
 
     /**
@@ -98,7 +98,7 @@
      * @param nodeFactory a <code>boolean</code> value.
      */
     public void setNodefactory(boolean nodeFactory) {
-        optionalAttrs.put(NODE_FACTORY, nodeFactory ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(NODE_FACTORY, nodeFactory);
     }
 
     /**
@@ -106,7 +106,7 @@
      * @param nodeScopeHook a <code>boolean</code> value.
      */
     public void setNodescopehook(boolean nodeScopeHook) {
-        optionalAttrs.put(NODE_SCOPE_HOOK, nodeScopeHook ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(NODE_SCOPE_HOOK, nodeScopeHook);
     }
 
     /**
@@ -114,7 +114,7 @@
      * @param nodeUsesParser a <code>boolean</code> value.
      */
     public void setNodeusesparser(boolean nodeUsesParser) {
-        optionalAttrs.put(NODE_USES_PARSER, nodeUsesParser ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(NODE_USES_PARSER, nodeUsesParser);
     }
 
     /**
@@ -122,7 +122,7 @@
      * @param staticParser a <code>boolean</code> value.
      */
     public void setStatic(boolean staticParser) {
-        optionalAttrs.put(STATIC, staticParser ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(STATIC, staticParser);
     }
 
     /**
@@ -130,7 +130,7 @@
      * @param visitor a <code>boolean</code> value.
      */
     public void setVisitor(boolean visitor) {
-        optionalAttrs.put(VISITOR, visitor ? Boolean.TRUE : Boolean.FALSE);
+        optionalAttrs.put(VISITOR, visitor);
     }
 
     /**
@@ -214,21 +214,18 @@
      * Run the task.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
 
         // load command line with optional attributes
-        Enumeration iter = optionalAttrs.keys();
-        while (iter.hasMoreElements()) {
-            String name  = (String) iter.nextElement();
-            Object value = optionalAttrs.get(name);
-            cmdl.createArgument().setValue("-" + name + ":" + value.toString());
-        }
+        optionalAttrs.forEach((name, value) -> cmdl.createArgument()
+            .setValue("-" + name + ":" + value.toString()));
 
         if (targetFile == null || !targetFile.isFile()) {
-            throw new BuildException("Invalid target: " + targetFile);
+            throw new BuildException("Invalid target: %s", targetFile);
         }
 
-        File javaFile = null;
+        File javaFile;
 
         // use the directory containing the target as the output directory
         if (outputDirectory == null) {
@@ -305,8 +302,8 @@
                                                 outputDir);
         String jjtreeFile = destFile.getAbsolutePath().replace('\\', '/');
 
-        if ((optionalOutputFile == null) || optionalOutputFile.equals("")) {
-            int filePos = jjtreeFile.lastIndexOf("/");
+        if (optionalOutputFile == null || optionalOutputFile.isEmpty()) {
+            int filePos = jjtreeFile.lastIndexOf('/');
 
             if (filePos >= 0) {
                 jjtreeFile = jjtreeFile.substring(filePos + 1);
@@ -328,7 +325,7 @@
             }
         }
 
-        if ((outputDir == null) || outputDir.equals("")) {
+        if (outputDir == null || outputDir.isEmpty()) {
             outputDir = getDefaultOutputDirectory();
         }
 
@@ -343,7 +340,7 @@
      *
      * @param destFile String
      * @param outputDir String
-     * @return validation file, relative if possible; <tt>null</tt> if not set
+     * @return validation file, relative if possible; <code>null</code> if not set
      * @throws BuildException if something goes wrong
      */
     private String validateOutputFile(String destFile,
@@ -353,7 +350,7 @@
             return null;
         }
 
-        if ((outputDir == null)
+        if (outputDir == null
             && (destFile.startsWith("/") || destFile.startsWith("\\"))) {
             String relativeOutputFile = makeOutputFileRelative(destFile);
             setOutputfile(relativeOutputFile);
@@ -363,17 +360,17 @@
 
         String root = getRoot(new File(destFile)).getAbsolutePath();
 
-        if ((root.length() > 1)
+        if (root.length() > 1
             && destFile.startsWith(root.substring(0, root.length() - 1))) {
-            throw new BuildException("Drive letter in 'outputfile' not "
-                                     + "supported: " + destFile);
+            throw new BuildException(
+                "Drive letter in 'outputfile' not supported: %s", destFile);
         }
 
         return destFile;
     }
 
     private String makeOutputFileRelative(String destFile) {
-        StringBuffer relativePath = new StringBuffer();
+        StringBuilder relativePath = new StringBuilder();
         String defaultOutputDirectory = getDefaultOutputDirectory();
         int nextPos = defaultOutputDirectory.indexOf('/');
         int startPos = nextPos + 1;
@@ -388,10 +385,7 @@
                 startPos = nextPos + 1;
             }
         }
-
-        relativePath.append(destFile);
-
-        return relativePath.toString();
+        return relativePath.append(destFile).toString();
     }
 
     private String getDefaultOutputDirectory() {
@@ -410,7 +404,6 @@
         while (root.getParent() != null) {
             root = root.getParentFile();
         }
-
         return root;
     }
 }
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 c8ce319..532afb5 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,8 +20,8 @@
 
 import java.io.File;
 import java.io.InputStream;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Map;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -64,7 +64,7 @@
     private static final String KEEP_LINE_COLUMN       = "KEEP_LINE_COLUMN";
     private static final String JDK_VERSION            = "JDK_VERSION";
 
-    private final Hashtable optionalAttrs = new Hashtable();
+    private final Map<String, Object> optionalAttrs = new Hashtable<>();
 
     // required attributes
     private File outputDirectory = null;
@@ -79,19 +79,19 @@
 
     protected static final String[] ARCHIVE_LOCATIONS = //NOSONAR
         new String[] {
-        "JavaCC.zip",
-        "bin/lib/JavaCC.zip",
-        "bin/lib/javacc.jar",
-        "javacc.jar", // used by jpackage for JavaCC 3.x
-    };
+            "JavaCC.zip",
+            "bin/lib/JavaCC.zip",
+            "bin/lib/javacc.jar",
+            "javacc.jar", // used by jpackage for JavaCC 3.x
+        };
 
     protected static final int[] ARCHIVE_LOCATIONS_VS_MAJOR_VERSION = //NOSONAR
         new int[] {
-        1,
-        2,
-        3,
-        3,
-    };
+            1,
+            2,
+            3,
+            3,
+        };
 
     protected static final String COM_PACKAGE = "COM.sun.labs.";
     protected static final String COM_JAVACC_CLASS = "javacc.Main";
@@ -111,7 +111,7 @@
      * @param lookahead an <code>int</code> value.
      */
     public void setLookahead(int lookahead) {
-        optionalAttrs.put(LOOKAHEAD, Integer.valueOf(lookahead));
+        optionalAttrs.put(LOOKAHEAD, lookahead);
     }
 
     /**
@@ -119,7 +119,7 @@
      * @param choiceAmbiguityCheck an <code>int</code> value.
      */
     public void setChoiceambiguitycheck(int choiceAmbiguityCheck) {
-        optionalAttrs.put(CHOICE_AMBIGUITY_CHECK, Integer.valueOf(choiceAmbiguityCheck));
+        optionalAttrs.put(CHOICE_AMBIGUITY_CHECK, choiceAmbiguityCheck);
     }
 
     /**
@@ -127,7 +127,7 @@
      * @param otherAmbiguityCheck an <code>int</code> value.
      */
     public void setOtherambiguityCheck(int otherAmbiguityCheck) {
-        optionalAttrs.put(OTHER_AMBIGUITY_CHECK, Integer.valueOf(otherAmbiguityCheck));
+        optionalAttrs.put(OTHER_AMBIGUITY_CHECK, otherAmbiguityCheck);
     }
 
     /**
@@ -331,19 +331,16 @@
      * Run the task.
      * @throws BuildException on error.
      */
+    @Override
     public void execute() throws BuildException {
 
         // load command line with optional attributes
-        Enumeration iter = optionalAttrs.keys();
-        while (iter.hasMoreElements()) {
-            String name  = (String) iter.nextElement();
-            Object value = optionalAttrs.get(name);
-            cmdl.createArgument().setValue("-" + name + ":" + value.toString());
-        }
+        optionalAttrs.forEach((name, value) -> cmdl.createArgument()
+            .setValue("-" + name + ":" + value));
 
         // check the target is a file
         if (targetFile == null || !targetFile.isFile()) {
-            throw new BuildException("Invalid target: " + targetFile);
+            throw new BuildException("Invalid target: %s", targetFile);
         }
 
         // use the directory containing the target as the output directory
@@ -425,12 +422,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 +494,6 @@
                 throw new BuildException("unknown task type " + type);
             }
             return packagePrefix + mainClass;
-        } finally {
-            if (l != null) {
-                l.cleanup();
-            }
         }
     }
 
@@ -528,8 +520,9 @@
             }
         }
 
-        throw new BuildException("Could not find a path to JavaCC.zip "
-                                 + "or javacc.jar from '" + home + "'.");
+        throw new BuildException(
+            "Could not find a path to JavaCC.zip or javacc.jar from '%s'.",
+            home);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/ForkingJavah.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/ForkingJavah.java
index c12f594..d7cb6b4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/ForkingJavah.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/ForkingJavah.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -45,6 +45,7 @@
      * @return true if the compilation was successful.
      * @throws BuildException if there is an error.
      */
+    @Override
     public boolean compile(Javah javah) throws BuildException {
         Commandline cmd = SunJavah.setupJavahCommand(javah);
         Project project = javah.getProject();
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/Gcjh.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/Gcjh.java
index c04eea3..966a3358 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/Gcjh.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/Gcjh.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java
index 121fa42..40b3419 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java
index d40e595..7a8786f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -42,12 +42,11 @@
     public static String getDefault() {
         if (JavaEnvUtils.isKaffe()) {
             return Kaffeh.IMPLEMENTATION_NAME;
-        } else if (JavaEnvUtils.isGij()) {
-            return Gcjh.IMPLEMENTATION_NAME;
-        } else if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
-            return ForkingJavah.IMPLEMENTATION_NAME;
         }
-        return SunJavah.IMPLEMENTATION_NAME;
+        if (JavaEnvUtils.isGij()) {
+            return Gcjh.IMPLEMENTATION_NAME;
+        }
+        return ForkingJavah.IMPLEMENTATION_NAME;
     }
 
     /**
@@ -86,29 +85,29 @@
         if ((JavaEnvUtils.isKaffe() && choice == null)
             || Kaffeh.IMPLEMENTATION_NAME.equals(choice)) {
             return new Kaffeh();
-        } else if ((JavaEnvUtils.isGij() && choice == null)
+        }
+        if ((JavaEnvUtils.isGij() && choice == null)
             || Gcjh.IMPLEMENTATION_NAME.equals(choice)) {
             return new Gcjh();
-        } else if (JavaEnvUtils.isAtLeastJavaVersion("10") &&
-                   (choice == null || ForkingJavah.IMPLEMENTATION_NAME.equals(choice))) {
+        }
+        if (JavaEnvUtils.isAtLeastJavaVersion("10") &&
+            (choice == null || ForkingJavah.IMPLEMENTATION_NAME.equals(choice))) {
             throw new BuildException("javah does not exist under Java 10 and higher,"
                 + " use the javac task with nativeHeaderDir instead");
-        } else if ((JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)
-                    && choice == null)
-                   || ForkingJavah.IMPLEMENTATION_NAME.equals(choice)) {
+        }
+        if (ForkingJavah.IMPLEMENTATION_NAME.equals(choice)) {
             return new ForkingJavah();
-        } else if (SunJavah.IMPLEMENTATION_NAME.equals(choice)) {
+        }
+        if (SunJavah.IMPLEMENTATION_NAME.equals(choice)) {
             return new SunJavah();
-        } else if (choice != null) {
+        }
+        if (choice != null) {
             return resolveClassName(choice,
                                     // Memory leak in line below
                                     log.getProject()
                                     .createClassLoader(classpath));
         }
-
-        // This default has been good enough until Ant 1.6.3, so stick
-        // with it
-        return new SunJavah();
+        return new ForkingJavah();
     }
 
     /**
@@ -123,7 +122,7 @@
     private static JavahAdapter resolveClassName(String className,
                                                  ClassLoader loader)
             throws BuildException {
-        return (JavahAdapter) ClasspathUtils.newInstance(className,
+        return ClasspathUtils.newInstance(className,
                 loader != null ? loader :
                 JavahAdapterFactory.class.getClassLoader(), JavahAdapter.class);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java
index 6bcba8c..51de22b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/Kaffeh.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java
index 7911b17..b448097 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/SunJavah.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,10 +44,11 @@
      * @throws BuildException if there is an error.
      * @since Ant 1.6.3
      */
+    @Override
     public boolean compile(Javah javah) throws BuildException {
         Commandline cmd = setupJavahCommand(javah);
         ExecuteJava ej = new ExecuteJava();
-        Class c = null;
+        Class<?> c;
         try {
             try {
                 // first search for the "old" javah class in 1.4.2 tools.jar
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java
index acccf9f..ef9d021 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,12 @@
 import java.io.PrintWriter;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
-import java.util.Vector;
+import java.util.Optional;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -42,18 +46,19 @@
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.LoaderUtils;
 
+import jdepend.textui.JDepend;
+
 /**
  * Runs JDepend tests.
  *
  * <p>JDepend is a tool to generate design quality metrics for each Java package.
  * It has been initially created by Mike Clark. JDepend can be found at <a
- * href="http://www.clarkware.com/software/JDepend.html">http://www.clarkware.com/software/JDepend.html</a>.
+ * href="https://github.com/clarkware/jdepend">https://github.com/clarkware/jdepend</a>.
  *
  * The current implementation spawn a new Java VM.
  *
  */
 public class JDependTask extends Task {
-    //private CommandlineJava commandline = new CommandlineJava();
 
     // required attributes
     private Path sourcesPath; // Deprecated!
@@ -71,7 +76,7 @@
     private String format = "text";
     private PatternSet defaultPatterns = new PatternSet();
 
-    private static Constructor packageFilterC;
+    private static Constructor<?> packageFilterC;
     private static Method setFilter;
 
     private boolean includeRuntime = false;
@@ -79,13 +84,12 @@
 
     static {
         try {
-            Class packageFilter =
+            Class<?> packageFilter =
                 Class.forName("jdepend.framework.PackageFilter");
             packageFilterC =
-                packageFilter.getConstructor(new Class[] {java.util.Collection.class});
+                packageFilter.getConstructor(Collection.class);
             setFilter =
-                jdepend.textui.JDepend.class.getDeclaredMethod("setFilter",
-                                                               new Class[] {packageFilter});
+                JDepend.class.getDeclaredMethod("setFilter", packageFilter);
         } catch (Throwable t) {
             if (setFilter == null) {
                 packageFilterC = null;
@@ -158,8 +162,8 @@
     /**
      * If true, forks into a new JVM. Default: false.
      *
-     * @param   value   <tt>true</tt> if a JVM should be forked,
-     *                  otherwise <tt>false</tt>
+     * @param   value   <code>true</code> if a JVM should be forked,
+     *                  otherwise <code>false</code>
      */
     public void setFork(boolean value) {
         fork = value;
@@ -175,8 +179,8 @@
     /**
      * The command used to invoke a forked Java Virtual Machine.
      *
-     * Default is <tt>java</tt>. Ignored if no JVM is forked.
-     * @param   value   the new VM to use instead of <tt>java</tt>
+     * Default is <code>java</code>. Ignored if no JVM is forked.
+     * @param   value   the new VM to use instead of <code>java</code>
      * @see #setFork(boolean)
      */
     public void setJvm(String value) {
@@ -189,6 +193,7 @@
      * @return a source path
      * @deprecated since 1.6.x.
      */
+    @Deprecated
     public Path createSourcespath() {
         if (sourcesPath == null) {
             sourcesPath = new Path(getProject());
@@ -201,6 +206,7 @@
      * @return the sources path
      * @deprecated since 1.6.x.
      */
+    @Deprecated
     public Path getSourcespath() {
         return sourcesPath;
     }
@@ -325,6 +331,7 @@
         /**
          * @return the enumerated values
          */
+        @Override
         public String[] getValues() {
             return formats;
         }
@@ -368,11 +375,11 @@
 
         File f = LoaderUtils.getResourceSource(getClass().getClassLoader(),
                                                resource);
-        if (f != null) {
+        if (f == null) {
+            log("Couldn't find " + resource, Project.MSG_DEBUG);
+        } else {
             log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG);
             runtimeClasses.createPath().setLocation(f);
-        } else {
-            log("Couldn\'t find " + resource, Project.MSG_DEBUG);
         }
     }
 
@@ -381,31 +388,29 @@
      *
      * @exception BuildException if an error occurs
      */
+    @Override
     public void execute() throws BuildException {
 
         CommandlineJava commandline = new CommandlineJava();
 
         if ("text".equals(format)) {
             commandline.setClassname("jdepend.textui.JDepend");
-        } else
-            if ("xml".equals(format)) {
-                commandline.setClassname("jdepend.xmlui.JDepend");
-            }
+        } else if ("xml".equals(format)) {
+            commandline.setClassname("jdepend.xmlui.JDepend");
+        }
 
         if (jvm != null) {
             commandline.setVm(jvm);
         }
         if (getSourcespath() == null && getClassespath() == null) {
             throw new BuildException("Missing classespath required argument");
-        } else if (getClassespath() == null) {
-            String msg =
-                "sourcespath is deprecated in JDepend >= 2.5 "
-                + "- please convert to classespath";
-            log(msg);
+        }
+        if (getClassespath() == null) {
+            log("sourcespath is deprecated in JDepend >= 2.5 - please convert to classespath");
         }
 
         // execute the test and get the return code
-        int exitValue = JDependTask.ERRORS;
+        int exitValue;
         boolean wasKilled = false;
         if (!getFork()) {
             exitValue = executeInVM(commandline);
@@ -426,11 +431,10 @@
             String errorMessage = "JDepend FAILED"
                 + (wasKilled ? " - Timed out" : "");
 
-            if  (getHaltonerror()) {
+            if (getHaltonerror()) {
                 throw new BuildException(errorMessage, getLocation());
-            } else {
-                log(errorMessage, Project.MSG_ERR);
             }
+            log(errorMessage, Project.MSG_ERR);
         }
     }
 
@@ -471,15 +475,10 @@
             log("Output to be stored in " + getOutputFile().getPath());
         }
 
-
         try {
-            if (getClassespath() != null) {
-                // This is the new, better way - use classespath instead
-                // of sourcespath.  The code is currently the same - you
-                // need class files in a directory to use this or jar files.
-                String[] cP = getClassespath().list();
-                for (int i = 0; i < cP.length; i++) {
-                    File f = new File(cP[i]);
+            getWorkingPath().ifPresent(path -> {
+                for (String filepath : path.list()) {
+                    File f = new File(filepath);
                     // not necessary as JDepend would fail, but why loose
                     // some time?
                     if (!f.exists()) {
@@ -500,48 +499,17 @@
                         throw new BuildException(msg);
                     }
                 }
-
-            } else if (getSourcespath() != null) {
-
-                // This is the old way and is deprecated - classespath is
-                // the right way to do this and is above
-                String[] sP = getSourcespath().list();
-                for (int i = 0; i < sP.length; i++) {
-                    File f = new File(sP[i]);
-
-                    // not necessary as JDepend would fail, but why loose
-                    // some time?
-                    if (!f.exists() || !f.isDirectory()) {
-                        String msg = "\""
-                            + f.getPath()
-                            + "\" does not represent a valid"
-                            + " directory. JDepend would fail.";
-                        log(msg);
-                        throw new BuildException(msg);
-                    }
-                    try {
-                        jdepend.addDirectory(f.getPath());
-                    } catch (IOException e) {
-                        String msg =
-                            "JDepend Failed when adding a source directory: "
-                            + e.getMessage();
-                        log(msg);
-                        throw new BuildException(msg);
-                    }
-                }
-            }
+            });
 
             // This bit turns <exclude> child tags into patters to ignore
             String[] patterns = defaultPatterns.getExcludePatterns(getProject());
             if (patterns != null && patterns.length > 0) {
                 if (setFilter != null) {
-                    Vector v = new Vector();
-                    for (int i = 0; i < patterns.length; i++) {
-                        v.addElement(patterns[i]);
-                    }
+                    List<String> v = new ArrayList<>();
+                    Collections.addAll(v, patterns);
                     try {
-                        Object o = packageFilterC.newInstance(new Object[] {v});
-                        setFilter.invoke(jdepend, new Object[] {o});
+                        Object o = packageFilterC.newInstance(v);
+                        setFilter.invoke(jdepend, o);
                     } catch (Throwable e) {
                         log("excludes will be ignored as JDepend doesn't like me: "
                             + e.getMessage(), Project.MSG_WARN);
@@ -554,8 +522,8 @@
 
             jdepend.analyze();
             if (pw != null && pw.checkError()) {
-                throw new IOException("Encountered an error writing JDepend"
-                                      + " output");
+                throw new IOException(
+                    "Encountered an error writing JDepend output");
             }
         } catch (IOException ex) {
             throw new BuildException(ex);
@@ -566,14 +534,13 @@
         return SUCCESS;
     }
 
-
     /**
      * Execute the task by forking a new JVM. The command will block until
      * it finishes. To know if the process was destroyed or not, use the
-     * <tt>killedProcess()</tt> method of the watchdog class.
+     * <code>killedProcess()</code> method of the watchdog class.
      * @param commandline the commandline for forked jvm
      * @param  watchdog   the watchdog in charge of cancelling the test if it
-     * exceeds a certain amount of time. Can be <tt>null</tt>.
+     * exceeds a certain amount of time. Can be <code>null</code>.
      * @return the result of running the jdepend
      * @throws BuildException in case of error
      */
@@ -588,14 +555,14 @@
 
         // not sure whether this test is needed but cost nothing to put.
         // hope it will be reviewed by anybody competent
-        if (getClasspath().toString().length() > 0) {
+        if (!getClasspath().toString().isEmpty()) {
             createJvmarg(commandline).setValue("-classpath");
             createJvmarg(commandline).setValue(getClasspath().toString());
         }
 
         if (includeRuntime) {
-            Map/*<String, String>*/ env = Execute.getEnvironmentVariables();
-            String cp = (String) env.get("CLASSPATH");
+            Map<String, String> env = Execute.getEnvironmentVariables();
+            String cp = env.get("CLASSPATH");
             if (cp != null) {
                 commandline.createClasspath(getProject()).createPath()
                     .append(new Path(getProject(), cp));
@@ -615,42 +582,20 @@
             // we have to find a cleaner way to put this output
         }
 
-        if (getSourcespath() != null) {
-            // This is deprecated - use classespath in the future
-            String[] sP = getSourcespath().list();
-            for (int i = 0; i < sP.length; i++) {
-                File f = new File(sP[i]);
+        getWorkingPath().ifPresent(path -> {
+            for (String filepath : path.list()) {
+                File f = new File(filepath);
 
                 // not necessary as JDepend would fail, but why loose
                 // some time?
                 if (!f.exists() || !f.isDirectory()) {
-                    throw new BuildException("\"" + f.getPath()
-                                             + "\" does not represent a valid"
-                                             + " directory. JDepend would"
-                                             + " fail.");
+                    throw new BuildException(
+                        "\"%s\" does not represent a valid directory. JDepend would fail.",
+                        f.getPath());
                 }
                 commandline.createArgument().setValue(f.getPath());
             }
-        }
-
-        if (getClassespath() != null) {
-            // This is the new way - use classespath - code is the
-            // same for now
-            String[] cP = getClassespath().list();
-            for (int i = 0; i < cP.length; i++) {
-                File f = new File(cP[i]);
-                // not necessary as JDepend would fail, but why loose
-                // some time?
-                if (!f.exists()) {
-                    throw new BuildException("\"" + f.getPath()
-                                             + "\" does not represent a valid"
-                                             + " file or directory. JDepend would"
-                                             + " fail.");
-                }
-                commandline.createArgument().setValue(f.getPath());
-            }
-        }
-
+        });
         Execute execute = new Execute(new LogStreamHandler(this,
             Project.MSG_INFO, Project.MSG_WARN), watchdog);
         execute.setCommandline(commandline.getCommandline());
@@ -671,7 +616,7 @@
     }
 
     /**
-     * @return <tt>null</tt> if there is a timeout value, otherwise the
+     * @return <code>null</code> if there is a timeout value, otherwise the
      * watchdog instance.
      * @throws BuildException in case of error
      */
@@ -679,6 +624,17 @@
         if (getTimeout() == null) {
             return null;
         }
-        return new ExecuteWatchdog(getTimeout().longValue());
+        return new ExecuteWatchdog(getTimeout());
     }
+
+    private Optional<Path> getWorkingPath() {
+        Optional<Path> result = Optional.ofNullable(getClassespath());
+        if (result.isPresent()) {
+            return result;
+        }
+        result = Optional.ofNullable(getSourcespath());
+        result.ifPresent(resources -> log("nested sourcespath is deprecated; please use classespath"));
+        return result;
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jlink/ClassNameReader.java b/src/main/org/apache/tools/ant/taskdefs/optional/jlink/ClassNameReader.java
index 20e9fc5..dbe2447 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jlink/ClassNameReader.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jlink/ClassNameReader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -49,8 +49,8 @@
         super();
 
         int count = data.readUnsignedShort();
-        types = new byte [ count ];
-        values = new Object [ count ];
+        types = new byte[count];
+        values = new Object[count];
         // read in all constant pool entries.
         for (int i = 1; i < count; i++) {
             byte type = data.readByte();
@@ -64,34 +64,32 @@
                 break;
 
             case INTEGER :
-                values[i] = new Integer(data.readInt());
+            case FIELDREF :
+            case METHODREF :
+            case INTERFACEMETHODREF :
+            case NAMEANDTYPE :
+                values[i] = data.readInt();
                 break;
 
             case FLOAT :
-                values[i] = new Float(data.readFloat());
+                values[i] = data.readFloat();
                 break;
 
             case LONG :
-                values[i] = new Long(data.readLong());
+                values[i] = data.readLong();
                 ++i;
                 break;
 
             case DOUBLE :
-                values[i] = new Double(data.readDouble());
+                values[i] = data.readDouble();
                 ++i;
                 break;
 
             case CLASS :
             case STRING :
-                values[i] = new Integer(data.readUnsignedShort());
+                values[i] = data.readUnsignedShort();
                 break;
 
-            case FIELDREF :
-            case METHODREF :
-            case INTERFACEMETHODREF :
-            case NAMEANDTYPE :
-                values[i] = new Integer(data.readInt());
-                break;
             default:
                 // Do nothing
             }
@@ -104,7 +102,7 @@
  * given just an InputStream. Reads in just enough to perform this
  * minimal task only.
  */
-public class ClassNameReader extends Object {
+public class ClassNameReader {
     private static final int CLASS_MAGIC_NUMBER =  0xCAFEBABE;
 
     /**
@@ -129,11 +127,9 @@
         /* int accessFlags = */ data.readUnsignedShort();
         int classIndex = data.readUnsignedShort();
         Integer stringIndex = (Integer) values[classIndex];
-        String className = (String) values[stringIndex.intValue()];
-        return className;
+        return (String) values[stringIndex];
     }
 
-
 }
 
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jlink/JlinkTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/jlink/JlinkTask.java
index 5a2cba6..df02abe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jlink/JlinkTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jlink/JlinkTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,8 +25,10 @@
 import org.apache.tools.ant.types.Path;
 
 /**
- * This class defines objects that can link together various jar and
- * zip files.
+ * This task defines objects that can link together various jar and
+ * zip files.  It is not related to the {@code jlink} tool present in
+ * Java 9 and later;  for that, see
+ * {@link org.apache.tools.ant.taskdefs.modules.Link}.
  *
  * <p>It is basically a wrapper for the jlink code written originally
  * by <a href="mailto:beard@netscape.com">Patrick Beard</a>.  The
@@ -52,11 +54,19 @@
  */
 public class JlinkTask extends MatchingTask {
 
+    private File outfile = null;
+
+    private Path mergefiles = null;
+
+    private Path addfiles = null;
+
+    private boolean compress = false;
+
     /**
      * The output file for this run of jlink. Usually a jar or zip file.
      * @param outfile the output file
      */
-    public  void setOutfile(File outfile) {
+    public void setOutfile(File outfile) {
         this.outfile = outfile;
     }
 
@@ -65,7 +75,7 @@
      * be merged into the output.
      * @return a path to be configured
      */
-    public  Path createMergefiles() {
+    public Path createMergefiles() {
         if (this.mergefiles == null) {
             this.mergefiles = new Path(getProject());
         }
@@ -76,7 +86,7 @@
      * Sets the files to be merged into the output.
      * @param mergefiles a path
      */
-    public  void setMergefiles(Path mergefiles) {
+    public void setMergefiles(Path mergefiles) {
         if (this.mergefiles == null) {
             this.mergefiles = mergefiles;
         } else {
@@ -89,7 +99,7 @@
      * be added to the output.
      * @return a path to be configured
      */
-    public  Path createAddfiles() {
+    public Path createAddfiles() {
         if (this.addfiles == null) {
             this.addfiles = new Path(getProject());
         }
@@ -100,7 +110,7 @@
      * Sets the files to be added into the output.
      * @param addfiles a path
      */
-    public  void setAddfiles(Path addfiles) {
+    public void setAddfiles(Path addfiles) {
         if (this.addfiles == null) {
             this.addfiles = addfiles;
         } else {
@@ -112,7 +122,7 @@
      * Defines whether or not the output should be compacted.
      * @param compress a <code>boolean</code> value
      */
-    public  void setCompress(boolean compress) {
+    public void setCompress(boolean compress) {
         this.compress = compress;
     }
 
@@ -120,15 +130,16 @@
      * Does the adding and merging.
      * @throws BuildException on error
      */
-    public  void execute() throws BuildException {
+    @Override
+    public void execute() throws BuildException {
         //Be sure everything has been set.
         if (outfile == null) {
-            throw new BuildException("outfile attribute is required! "
-                + "Please set.");
+            throw new BuildException(
+                "outfile attribute is required! Please set.");
         }
         if (!haveAddFiles() && !haveMergeFiles()) {
-            throw new BuildException("addfiles or mergefiles required! "
-                + "Please set.");
+            throw new BuildException(
+                "addfiles or mergefiles required! Please set.");
         }
         log("linking:     " + outfile.getPath());
         log("compression: " + compress, Project.MSG_VERBOSE);
@@ -159,23 +170,6 @@
     }
 
     private boolean haveEntries(Path p) {
-        if (p == null) {
-            return false;
-        }
-        if (p.size() > 0) {
-            return true;
-        }
-        return false;
+        return !(p == null || p.isEmpty());
     }
-
-    private  File outfile = null;
-
-    private  Path mergefiles = null;
-
-    private  Path addfiles = null;
-
-    private  boolean compress = false;
-
 }
-
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java b/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java
index 744fa40..480c4ca 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,11 +24,12 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 import java.util.zip.CRC32;
 import java.util.zip.Deflater;
@@ -37,8 +38,6 @@
 import java.util.zip.ZipFile;
 import java.util.zip.ZipOutputStream;
 
-import org.apache.tools.ant.util.FileUtils;
-
 // CheckStyle:TypeNameCheck OFF - bc
 /**
  * jlink links together multiple .jar files.
@@ -49,9 +48,9 @@
 
     private String outfile = null;
 
-    private Vector mergefiles = new Vector(VECTOR_INIT_SIZE);
+    private List<String> mergefiles = new Vector<>(VECTOR_INIT_SIZE);
 
-    private Vector addfiles = new Vector(VECTOR_INIT_SIZE);
+    private List<String> addfiles = new Vector<>(VECTOR_INIT_SIZE);
 
     private boolean compression = false;
 
@@ -71,7 +70,6 @@
         this.outfile = outfile;
     }
 
-
     /**
      * Adds a file to be merged into the output.
      * @param fileToMerge the file to merge into the output.
@@ -80,10 +78,9 @@
         if (fileToMerge == null) {
             return;
         }
-        mergefiles.addElement(fileToMerge);
+        mergefiles.add(fileToMerge);
     }
 
-
     /** Adds a file to be added into the output.
      * @param fileToAdd the file to add to the output.
      */
@@ -91,38 +88,35 @@
         if (fileToAdd == null) {
             return;
         }
-        addfiles.addElement(fileToAdd);
+        addfiles.add(fileToAdd);
     }
 
-
     /**
      * Adds several files to be merged into the output.
      * @param filesToMerge an array of files to merge into the output.
      */
-    public void addMergeFiles(String[] filesToMerge) {
+    public void addMergeFiles(String... filesToMerge) {
         if (filesToMerge == null) {
             return;
         }
-        for (int i = 0; i < filesToMerge.length; i++) {
-            addMergeFile(filesToMerge[i]);
+        for (String element : filesToMerge) {
+            addMergeFile(element);
         }
     }
 
-
     /**
-     * Adds several file to be added into the output.
+     * Adds several files to be added into the output.
      * @param filesToAdd an array of files to add to the output.
      */
-    public void addAddFiles(String[] filesToAdd) {
+    public void addAddFiles(String... filesToAdd) {
         if (filesToAdd == null) {
             return;
         }
-        for (int i = 0; i < filesToAdd.length; i++) {
-            addAddFile(filesToAdd[i]);
+        for (String element : filesToAdd) {
+            addAddFile(element);
         }
     }
 
-
     /**
      * Determines whether output will be compressed.
      * @param compress if true use compression.
@@ -131,7 +125,6 @@
         this.compression = compress;
     }
 
-
     /**
      * Performs the linking of files. Addfiles are added to the output as-is.
      * For example, a jar file is added to the output as a jar file. However,
@@ -145,48 +138,40 @@
      * @throws Exception on error.
      */
     public void link() throws Exception { //NOSONAR
-        ZipOutputStream output = new ZipOutputStream(new FileOutputStream(outfile));
+        try (ZipOutputStream output =
+            new ZipOutputStream(Files.newOutputStream(Paths.get(outfile)))) {
 
-        if (compression) {
-            output.setMethod(ZipOutputStream.DEFLATED);
-            output.setLevel(Deflater.DEFAULT_COMPRESSION);
-        } else {
-            output.setMethod(ZipOutputStream.STORED);
-        }
-
-        Enumeration merges = mergefiles.elements();
-
-        while (merges.hasMoreElements()) {
-            String path = (String) merges.nextElement();
-            File f = new File(path);
-
-            if (f.getName().endsWith(".jar") || f.getName().endsWith(".zip")) {
-                //Do the merge
-                mergeZipJarContents(output, f);
+            if (compression) {
+                output.setMethod(ZipOutputStream.DEFLATED);
+                output.setLevel(Deflater.DEFAULT_COMPRESSION);
             } else {
-                //Add this file to the addfiles Vector and add it
-                //later at the top level of the output file.
-                addAddFile(path);
+                output.setMethod(ZipOutputStream.STORED);
+            }
+            for (String path : mergefiles) {
+                File f = new File(path);
+
+                if (f.getName().endsWith(".jar")
+                    || f.getName().endsWith(".zip")) {
+                    //Do the merge
+                    mergeZipJarContents(output, f);
+                } else {
+                    //Add this file to the addfiles Vector and add it
+                    //later at the top level of the output file.
+                    addAddFile(path);
+                }
+            }
+            for (String name : addfiles) {
+                File f = new File(name);
+
+                if (f.isDirectory()) {
+                    addDirContents(output, f, f.getName() + '/', compression);
+                } else {
+                    addFile(output, f, "", compression);
+                }
             }
         }
-
-        Enumeration adds = addfiles.elements();
-
-        while (adds.hasMoreElements()) {
-            String name = (String) adds.nextElement();
-            File f = new File(name);
-
-            if (f.isDirectory()) {
-                //System.out.println("in jlink: adding directory contents of " + f.getPath());
-                addDirContents(output, f, f.getName() + '/', compression);
-            } else {
-                addFile(output, f, "", compression);
-            }
-        }
-        FileUtils.close(output);
     }
 
-
     /**
      * The command line entry point for jlink.
      * @param args an array of arguments
@@ -212,7 +197,6 @@
         }
     }
 
-
     /*
      * Actually performs the merging of f into the output.
      * f should be a zip or jar file.
@@ -222,12 +206,10 @@
         if (!f.exists()) {
             return;
         }
-        ZipFile zipf = new ZipFile(f);
-        try {
-            Enumeration entries = zipf.entries();
-
+        try (ZipFile zipf = new ZipFile(f)) {
+            Enumeration<? extends ZipEntry> entries = zipf.entries();
             while (entries.hasMoreElements()) {
-                ZipEntry inputEntry = (ZipEntry) entries.nextElement();
+                ZipEntry inputEntry = entries.nextElement();
                 //Ignore manifest entries.  They're bound to cause conflicts between
                 //files that are being merged.  User should supply their own
                 //manifest file when doing the merge.
@@ -248,30 +230,26 @@
                         if (ex.getMessage().contains("duplicate")) {
                             //It was the duplicate entry.
                             continue;
-                        } else {
-                            // I hate to admit it, but we don't know what happened
-                            // here.  Throw the Exception.
-                            throw ex;
                         }
+                        // I hate to admit it, but we don't know what happened
+                        // here.  Throw the Exception.
+                        throw ex;
                     }
 
-                    InputStream in = zipf.getInputStream(inputEntry);
-                    int len = buffer.length;
-                    int count = -1;
+                    try (InputStream in = zipf.getInputStream(inputEntry)) {
+                        int len = buffer.length;
+                        int count = -1;
 
-                    while ((count = in.read(buffer, 0, len)) > 0) {
-                        output.write(buffer, 0, count);
+                        while ((count = in.read(buffer, 0, len)) > 0) {
+                            output.write(buffer, 0, count);
+                        }
+                        output.closeEntry();
                     }
-                    in.close();
-                    output.closeEntry();
                 }
             }
-        } finally {
-            zipf.close();
         }
     }
 
-
     /*
      * Adds contents of a directory to the output.
      */
@@ -288,7 +266,6 @@
         }
     }
 
-
     /*
      * Gets the name of an entry in the file.  This is the real name
      * which for a class is the name of the package with the class
@@ -299,9 +276,7 @@
 
         if (!name.endsWith(".class")) {
             // see if the file is in fact a .class file, and determine its actual name.
-            InputStream input = null;
-            try {
-                input = new FileInputStream(file);
+            try (InputStream input = Files.newInputStream(file.toPath())) {
                 String className = ClassNameReader.getClassName(input);
 
                 if (className != null) {
@@ -309,13 +284,12 @@
                 }
             } catch (IOException ioe) {
                 //do nothing
-            } finally {
-                FileUtils.close(input);
             }
         }
-        System.out.println("From " + file.getPath() + " and prefix " + prefix
-                           + ", creating entry " + prefix + name);
-        return (prefix + name);
+        System.out.printf(
+            "From %1$s and prefix %2$s, creating entry %2$s%3$s%n",
+            file.getPath(), prefix, name);
+        return prefix + name;
     }
 
 
@@ -335,12 +309,9 @@
         if (!compress) {
             entry.setCrc(calcChecksum(file));
         }
-        FileInputStream input = new FileInputStream(file);
-
-        addToOutputStream(output, input, entry);
+        addToOutputStream(output, Files.newInputStream(file.toPath()), entry);
     }
 
-
     /*
      * A convenience method that several other methods might call.
      */
@@ -354,7 +325,7 @@
             return;
         }
 
-        int numBytes = -1;
+        int numBytes;
 
         while ((numBytes = input.read(buffer)) > 0) {
             output.write(buffer, 0, numBytes);
@@ -363,7 +334,6 @@
         input.close();
     }
 
-
     /*
      * A method that does the work on a given entry in a mergefile.
      * The big deal is to set the right parameters in the ZipEntry
@@ -384,12 +354,10 @@
         */
         String name = inputEntry.getName();
 
-        if (!(inputEntry.isDirectory() || name.endsWith(".class"))) {
-            try {
-                InputStream input = zip.getInputStream(zip.getEntry(name));
+        if (!inputEntry.isDirectory() && !name.endsWith(".class")) {
+            try (InputStream input = zip.getInputStream(zip.getEntry(name))) {
                 String className = ClassNameReader.getClassName(input);
 
-                input.close();
                 if (className != null) {
                     name = className.replace('.', '/') + ".class";
                 }
@@ -414,18 +382,15 @@
         return outputEntry;
     }
 
-
     /*
      * Necessary in the case where you add a entry that
      * is not compressed.
      */
     private long calcChecksum(File f) throws IOException {
-        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
-
-        return calcChecksum(in);
+        return calcChecksum(
+            new BufferedInputStream(Files.newInputStream(f.toPath())));
     }
 
-
     /*
      * Necessary in the case where you add a entry that
      * is not compressed.
@@ -433,18 +398,15 @@
     private long calcChecksum(InputStream in) throws IOException {
         CRC32 crc = new CRC32();
         int len = buffer.length;
-        int count = -1;
-        int haveRead = 0;
+        int count;
 
         while ((count = in.read(buffer, 0, len)) > 0) {
-            haveRead += count;
             crc.update(buffer, 0, count);
         }
         in.close();
         return crc.getValue();
     }
 
-
 }
 
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/Jasper41Mangler.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/Jasper41Mangler.java
index c71a6d5..41677bf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/Jasper41Mangler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/Jasper41Mangler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,13 +27,13 @@
  */
 public class Jasper41Mangler implements JspMangler {
 
-
     /**
      * map from a jsp file to a java filename; does not do packages
      *
      * @param jspFile file
      * @return java filename
      */
+    @Override
     public String mapJspToJavaName(File jspFile) {
         String jspUri = jspFile.getAbsolutePath();
         int start = jspUri.lastIndexOf(File.separatorChar) + 1;
@@ -75,7 +75,6 @@
         // CheckStyle:MagicNumber ON
     }
 
-
     /**
      * taking in the substring representing the path relative to the source dir
      * return a new string representing the destination path
@@ -83,6 +82,7 @@
      * @return null as this is not implemented.
      * @todo
      */
+    @Override
     public String mapPath(String path) {
         return null;
     }
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 42cab7e..6b0fb5c 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,8 +19,7 @@
 package org.apache.tools.ant.taskdefs.optional.jsp;
 
 import java.io.File;
-import java.util.Date;
-import java.util.Enumeration;
+import java.time.Instant;
 import java.util.Vector;
 
 import org.apache.tools.ant.AntClassLoader;
@@ -80,8 +79,8 @@
     private boolean mapped;
     private int verbose = 0;
     // CheckStyle:VisibilityModifier OFF - bc
-    protected Vector compileList = new Vector();
-    Vector javaFiles = new Vector();
+    protected Vector<String> compileList = new Vector<>();
+    Vector<File> javaFiles = new Vector<>();
 
     /**
      *  flag to control action on execution trouble
@@ -209,6 +208,7 @@
     public String getIeplugin() {
         return iepluginid;
     }
+
     /**
      * Java Plugin CLASSID for Internet Explorer
      * @param iepluginid the id to use.
@@ -272,7 +272,6 @@
         return uriroot;
     }
 
-
     /**
      * Set the classpath to be used for this compilation.
      * @param cp the path to be used.
@@ -413,7 +412,7 @@
      * get the list of files to compile
      * @return the list of files.
      */
-    public Vector getCompileList() {
+    public Vector<String> getCompileList() {
         return compileList;
     }
 
@@ -422,6 +421,7 @@
      * have changed and hand them off to a jsp compiler
      * @throws BuildException on error.
      */
+    @Override
     public void execute()
         throws BuildException {
 
@@ -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
@@ -499,7 +496,7 @@
             log("compiling " + compileList.size() + " files",
                 Project.MSG_VERBOSE);
 
-            if (compileList.size() > 0) {
+            if (!compileList.isEmpty()) {
 
                 log("Compiling " + compileList.size() + " source file"
                     + (compileList.size() == 1 ? "" : "s")
@@ -507,16 +504,10 @@
                     + dest);
                 doCompilation(compiler);
 
+            } else if (filecount == 0) {
+                log("there were no files to compile", Project.MSG_INFO);
             } else {
-                if (filecount == 0) {
-                    log("there were no files to compile", Project.MSG_INFO);
-                } else {
-                    log("all files are up to date", Project.MSG_VERBOSE);
-                }
-            }
-        } finally {
-            if (al != null) {
-                al.cleanup();
+                log("all files are up to date", Project.MSG_VERBOSE);
             }
         }
     }
@@ -526,15 +517,11 @@
      * this is destDir or it id destDir + the package name
      */
     private File getActualDestDir() {
-        File dest = null;
         if (packageName == null) {
-            dest = destDir;
-        } else {
-            String path = destDir.getPath() + File.separatorChar
-                + packageName.replace('.', File.separatorChar);
-            dest = new File(path);
+            return destDir;
         }
-        return dest;
+        return new File(destDir.getPath() + File.separatorChar
+            + packageName.replace('.', File.separatorChar));
     }
 
     /**
@@ -549,9 +536,8 @@
         if (!compiler.execute()) {
             if (failOnError) {
                 throw new BuildException(FAIL_MSG, getLocation());
-            } else {
-                log(FAIL_MSG, Project.MSG_ERR);
             }
+            log(FAIL_MSG, Project.MSG_ERR);
         }
     }
 
@@ -573,23 +559,19 @@
     protected void scanDir(File srcDir, File dest, JspMangler mangler,
                            String[] files) {
 
-        long now = (new Date()).getTime();
+        long now = Instant.now().toEpochMilli();
 
-        for (int i = 0; i < files.length; i++) {
-            String filename = files[i];
+        for (String filename : files) {
             File srcFile = new File(srcDir, filename);
             File javaFile = mapToJavaFile(mangler, srcFile, srcDir, dest);
             if (javaFile == null) {
                 continue;
             }
-
             if (srcFile.lastModified() > now) {
                 log("Warning: file modified in the future: " + filename,
                     Project.MSG_WARN);
             }
-            boolean shouldCompile = false;
-            shouldCompile = isCompileNeeded(srcFile, javaFile);
-            if (shouldCompile) {
+            if (isCompileNeeded(srcFile, javaFile)) {
                 compileList.addElement(srcFile.getAbsolutePath());
                 javaFiles.addElement(javaFile);
             }
@@ -619,26 +601,21 @@
             log("Compiling " + srcFile.getPath()
                 + " because java file " + javaFile.getPath()
                 + " does not exist", Project.MSG_VERBOSE);
-        } else {
-            if (srcFile.lastModified() > javaFile.lastModified()) {
-                shouldCompile = true;
-                log("Compiling " + srcFile.getPath()
-                    + " because it is out of date with respect to "
-                    + javaFile.getPath(),
-                    Project.MSG_VERBOSE);
-            } else {
-                if (javaFile.length() == 0) {
-                    shouldCompile = true;
-                    log("Compiling " + srcFile.getPath()
-                        + " because java file " + javaFile.getPath()
-                        + " is empty", Project.MSG_VERBOSE);
-                }
-            }
+        } else if (srcFile.lastModified() > javaFile.lastModified()) {
+            shouldCompile = true;
+            log("Compiling " + srcFile.getPath()
+                + " because it is out of date with respect to "
+                + javaFile.getPath(),
+                Project.MSG_VERBOSE);
+        } else if (javaFile.length() == 0) {
+            shouldCompile = true;
+            log("Compiling " + srcFile.getPath()
+                + " because java file " + javaFile.getPath()
+                + " is empty", Project.MSG_VERBOSE);
         }
         return shouldCompile;
     }
 
-
     /**
      * get a filename from our jsp file.
      * @param mangler the jsp filename manager.
@@ -654,7 +631,6 @@
             return null;
         }
         String javaFileName = mangler.mapJspToJavaName(srcFile);
-        //        String srcFileDir=srcFile.getParent();
         return new File(dest, javaFileName);
     }
 
@@ -665,9 +641,7 @@
      */
     public void deleteEmptyJavaFiles() {
         if (javaFiles != null) {
-            Enumeration e = javaFiles.elements();
-            while (e.hasMoreElements()) {
-                File file = (File) e.nextElement();
+            for (File file : javaFiles) {
                 if (file.exists() && file.length() == 0) {
                     log("deleting empty output file " + file);
                     file.delete();
@@ -701,9 +675,6 @@
         public void setBaseDir(File directory) {
             this.directory = directory;
         }
-        //end inner class
     }
 
-
-    //end class
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspMangler.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspMangler.java
index f62492c..4ddc9ad 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspMangler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspMangler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java
index 855376a..38a27fe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,6 +58,7 @@
      * @param jspFile file
      * @return java filename
      */
+    @Override
     public String mapJspToJavaName(File jspFile) {
         return mapJspToBaseName(jspFile) + ".java";
     }
@@ -70,20 +71,19 @@
      * @return extensionless potentially remapped name
      */
     private String mapJspToBaseName(File jspFile) {
-        String className;
-        className = stripExtension(jspFile);
+        String className = stripExtension(jspFile);
 
         // since we don't mangle extensions like the servlet does,
         // we need to check for keywords as class names
-        for (int i = 0; i < keywords.length; ++i) {
-            if (className.equals(keywords[i])) {
+        for (String keyword : keywords) {
+            if (className.equals(keyword)) {
                 className += "%";
                 break;
             }
         }
 
         // Fix for invalid characters. If you think of more add to the list.
-        StringBuffer modifiedClassName = new StringBuffer(className.length());
+        StringBuilder modifiedClassName = new StringBuilder(className.length());
         // first char is more restrictive than the rest
         char firstChar = className.charAt(0);
         if (Character.isJavaIdentifierStart(firstChar)) {
@@ -147,6 +147,7 @@
      * @param path not used
      * @return null always.
      */
+    @Override
     public String mapPath(String path) {
         return null;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/WLJspc.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/WLJspc.java
index 2680847..12cc6e8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/WLJspc.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/WLJspc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,8 @@
 
 //apache/ant imports
 import java.io.File;
-import java.util.Date;
+import java.time.Instant;
+import java.util.List;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -33,18 +34,18 @@
 /**
  * Precompiles JSP's using WebLogic's JSP compiler (weblogic.jspc).
  *
- * Tested only on Weblogic 4.5.1 - NT4.0 and Solaris 5.7
+ * Tested only on WebLogic 4.5.1 - NT4.0 and Solaris 5.7
  *
  * required attributes
- *      src : root of source tree for JSP, ie, the document root for your weblogic server
+ *      src : root of source tree for JSP, ie, the document root for your WebLogic server
  *      dest : root of destination directory, what you have set as
- *             WorkingDir in the weblogic properties
+ *             WorkingDir in the WebLogic properties
  *      package : start package name under which your JSP's would be compiled
  *
  * other attributes
  *     classpath
  *
- * A classpath should be set which contains the weblogic classes as well as all
+ * A classpath should be set which contains the WebLogic classes as well as all
  * application classes referenced by the JSP. The system classpath is also
  * appended when the jspc is called, so you may choose to put everything in
  * the classpath while calling Ant. However, since presumably the JSP's will
@@ -54,11 +55,11 @@
  * The task checks timestamps on the JSP's and the generated classes, and compiles
  * only those files that have changed.
  *
- * It follows the weblogic naming convention of putting classes in
+ * It follows the WebLogic naming convention of putting classes in
  *  <b> _dirName/_fileName.class for dirname/fileName.jsp   </b>
  *
- * Limitation: It compiles the files thru the Classic compiler only.
- * Limitation: Since it is my experience that weblogic jspc throws out of
+ * Limitation: It compiles the files through the Classic compiler only.
+ * Limitation: Since it is my experience that WebLogic jspc throws out of
  *             memory error on being given too many files at one go, it is
  *             called multiple times with one jsp file each.
  *
@@ -79,7 +80,7 @@
  */
 
 public class WLJspc extends MatchingTask {
-    //TODO Test on other versions of weblogic
+    //TODO Test on other versions of WebLogic
     //TODO add more attributes to the task, to take care of all jspc options
     //TODO Test on Unix
 
@@ -98,21 +99,22 @@
     //private String compilerPath; //fully qualified name for the compiler executable
 
     private String pathToPackage = "";
-    private Vector filesToDo = new Vector();
+    private List<String> filesToDo = new Vector<>();
 
     /**
      * Run the task.
      * @throws BuildException if there is an error.
      */
+    @Override
     public void execute() throws BuildException {
         if (!destinationDirectory.isDirectory()) {
-            throw new BuildException("destination directory "
-                + destinationDirectory.getPath() + " is not valid");
+            throw new BuildException("destination directory %s is not valid",
+                destinationDirectory.getPath());
         }
 
         if (!sourceDirectory.isDirectory()) {
-            throw new BuildException("src directory "
-                + sourceDirectory.getPath() + " is not valid");
+            throw new BuildException("src directory %s is not valid",
+                sourceDirectory.getPath());
         }
 
         if (destinationPackage == null) {
@@ -120,7 +122,6 @@
                                      getLocation());
         }
 
-
         pathToPackage
             = this.destinationPackage.replace('.', File.separatorChar);
         // get all the files in the sourceDirectory
@@ -132,9 +133,8 @@
         }
 
         compileClasspath = compileClasspath.concatSystemClasspath();
-        String[] files = ds.getIncludedFiles();
 
-        //Weblogic.jspc calls System.exit() ... have to fork
+        // WebLogic jspc calls System.exit() ... have to fork
         // Therefore, takes loads of time
         // Can pass directories at a time (*.jsp) but easily runs out of
         // memory on hefty dirs (even on  a Sun)
@@ -146,8 +146,6 @@
         String[] args = new String[12];
         // CheckStyle:MagicNumber ON
 
-        File jspFile = null;
-        String parents = "";
         int j = 0;
         //TODO  this array stuff is a remnant of prev trials.. gotta remove.
         args[j++] = "-d";
@@ -159,33 +157,30 @@
         //Use classic compiler -- can be parameterised?
         args[j++] =  "-compilerclass";
         args[j++] = "sun.tools.javac.Main";
-        //Weblogic jspc does not seem to work unless u explicitly set this...
+        // WebLogic jspc does not seem to work unless u explicitly set this...
         // Does not take the classpath from the env....
         // Am i missing something about the Java task??
         args[j++] = "-classpath";
         args[j++] = compileClasspath.toString();
 
-        this.scanDir(files);
+        this.scanDir(ds.getIncludedFiles());
         log("Compiling " + filesToDo.size() + " JSP files");
 
-        final int size = filesToDo.size();
-        for (int i = 0; i < size; i++) {
+        for (String filename : filesToDo) {
             //TODO
-            // All this to get package according to weblogic standards
+            // All this to get package according to WebLogic standards
             // Can be written better... this is too hacky!
-            // Careful.. similar code in scanDir , but slightly different!!
-            String filename = (String) filesToDo.elementAt(i);
-            jspFile = new File(filename);
+            // Careful.. similar code in scanDir, but slightly different!!
+            File jspFile = new File(filename);
             args[j] = "-package";
-            parents = jspFile.getParent();
-            if ((parents != null)  && (!("").equals(parents))) {
-                parents =  this.replaceString(parents, File.separator, "_.");
-                args[j + 1] = destinationPackage + "." + "_" + parents;
-            } else {
+            String parents = jspFile.getParent();
+            if (parents == null || parents.isEmpty()) {
                 args[j + 1] = destinationPackage;
+            } else {
+                parents = this.replaceString(parents, File.separator, "_.");
+                args[j + 1] = destinationPackage + "." + "_" + parents;
             }
 
-
             args[j + 2] =  sourceDirectory + File.separator + filename;
             helperTask.clearArgs();
 
@@ -202,8 +197,6 @@
         }
     }
 
-
-
     /**
      * Set the classpath to be used for this compilation.
      * @param classpath the classpath to use.
@@ -234,7 +227,6 @@
      * @param dirName the directory containing the source jsp's
      */
     public void setSrc(File dirName) {
-
         sourceDirectory = dirName;
     }
 
@@ -245,7 +237,6 @@
      * @param dirName the directory containing the source jsp's
      */
     public void setDest(File dirName) {
-
         destinationDirectory = dirName;
     }
 
@@ -255,7 +246,6 @@
      * @param packageName the package name for the classes
      */
     public void setPackage(String packageName) {
-
         destinationPackage = packageName;
     }
 
@@ -265,52 +255,48 @@
      * @param files the files to scan.
      */
     protected void scanDir(String[] files) {
-
-        long now = (new Date()).getTime();
-        File jspFile = null;
-        String parents = null;
-        String pack = "";
-        for (int i = 0; i < files.length; i++) {
-            File srcFile = new File(this.sourceDirectory, files[i]);
+        long now = Instant.now().toEpochMilli();
+        for (String file : files) {
+            File srcFile = new File(this.sourceDirectory, file);
             //TODO
             // All this to convert source to destination directory according
-            // to weblogic standards Can be written better... this is too hacky!
-            jspFile = new File(files[i]);
-            parents = jspFile.getParent();
+            // to WebLogic standards - can be written better... this is too hacky!
+            File jspFile = new File(file);
+            String parents = jspFile.getParent();
 
-            if ((parents != null)  && (!("").equals(parents))) {
+            String pack;
+            if (parents == null || parents.isEmpty()) {
+                pack = pathToPackage;
+            } else {
                 parents =  this.replaceString(parents, File.separator, "_/");
                 pack = pathToPackage + File.separator + "_" + parents;
-            } else {
-                pack = pathToPackage;
             }
 
             String filePath = pack + File.separator + "_";
-            int startingIndex = files[i].lastIndexOf(File.separator) != -1
-                    ? files[i].lastIndexOf(File.separator) + 1 : 0;
-            int endingIndex = files[i].indexOf(".jsp");
+            int startingIndex = file.lastIndexOf(File.separator) != -1
+                    ? file.lastIndexOf(File.separator) + 1 : 0;
+            int endingIndex = file.indexOf(".jsp");
             if (endingIndex == -1) {
-                log("Skipping " + files[i] + ". Not a JSP",
+                log("Skipping " + file + ". Not a JSP",
                     Project.MSG_VERBOSE);
                 continue;
             }
 
-            filePath += files[i].substring(startingIndex, endingIndex);
+            filePath += file.substring(startingIndex, endingIndex);
             filePath += ".class";
             File classFile = new File(this.destinationDirectory, filePath);
 
             if (srcFile.lastModified() > now) {
                 log("Warning: file modified in the future: "
-                    + files[i], Project.MSG_WARN);
+                    + file, Project.MSG_WARN);
             }
             if (srcFile.lastModified() > classFile.lastModified()) {
-                filesToDo.addElement(files[i]);
-                log("Recompiling File " + files[i], Project.MSG_VERBOSE);
+                filesToDo.add(file);
+                log("Recompiling File " + file, Project.MSG_VERBOSE);
             }
         }
     }
 
-
     /**
      * Replace occurrences of a string with a replacement string.
      * @param inpString the string to convert.
@@ -320,15 +306,14 @@
      */
     protected String replaceString(String inpString, String escapeChars,
                                    String replaceChars) {
-        String localString = "";
-        int numTokens = 0;
+        StringBuilder localString = new StringBuilder();
         StringTokenizer st = new StringTokenizer(inpString, escapeChars, true);
-        numTokens = st.countTokens();
+        int numTokens = st.countTokens();
         for (int i = 0; i < numTokens; i++) {
             String test = st.nextToken();
-            test = (test.equals(escapeChars) ? replaceChars : test);
-            localString += test;
+            test = test.equals(escapeChars) ? replaceChars : test;
+            localString.append(test);
         }
-        return localString;
+        return localString.toString();
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultJspCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultJspCompilerAdapter.java
index 59a9b2c..06dbb07 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultJspCompilerAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultJspCompilerAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,8 +19,8 @@
 package org.apache.tools.ant.taskdefs.optional.jsp.compilers;
 
 import java.io.File;
-import java.util.Enumeration;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.optional.jsp.JspC;
@@ -35,8 +35,6 @@
 public abstract class DefaultJspCompilerAdapter
     implements JspCompilerAdapter {
 
-    private static String lSep = System.getProperty("line.separator");
-
     /**
      * Logs the compilation parameters, adds the files to compile and logs the
      * &quot;niceSourceList&quot;
@@ -45,29 +43,17 @@
      * @param cmd the command line used
      */
     protected void logAndAddFilesToCompile(JspC jspc,
-                                           Vector compileList,
+                                           Vector<String> compileList,
                                            CommandlineJava cmd) {
         jspc.log("Compilation " + cmd.describeJavaCommand(),
                  Project.MSG_VERBOSE);
 
-        StringBuffer niceSourceList = new StringBuffer("File");
-        if (compileList.size() != 1) {
-            niceSourceList.append("s");
-        }
-        niceSourceList.append(" to be compiled:");
-
-        niceSourceList.append(lSep);
-
-        Enumeration e = compileList.elements();
-        while (e.hasMoreElements()) {
-            String arg = (String) e.nextElement();
-            cmd.createArgument().setValue(arg);
-            niceSourceList.append("    ");
-            niceSourceList.append(arg);
-            niceSourceList.append(lSep);
-        }
-
-        jspc.log(niceSourceList.toString(), Project.MSG_VERBOSE);
+        String niceSourceList = compileList.stream()
+                        .peek(arg -> cmd.createArgument().setValue(arg))
+                        .map(arg -> String.format("    %s%n", arg))
+                        .collect(Collectors.joining(""));
+        jspc.log(String.format("File%s to be compiled:%n%s",
+                compileList.size() == 1 ? "" : "s", niceSourceList), Project.MSG_VERBOSE);
     }
 
     // CheckStyle:VisibilityModifier OFF - bc
@@ -83,6 +69,7 @@
      * set the owner
      * @param owner the owner JspC compiler
      */
+    @Override
     public void setJspc(JspC owner) {
         this.owner = owner;
     }
@@ -94,21 +81,20 @@
         return owner;
     }
 
-
     /**
-     * add a single argument to the argument list, if the value aint null
+     * add a single argument to the argument list, if the value isn't null
      * @param cmd the command line
      * @param  argument  The argument
      */
     protected void addArg(CommandlineJava cmd, String argument) {
-        if (argument != null && argument.length() != 0) {
+        if (argument != null && !argument.isEmpty()) {
            cmd.createArgument().setValue(argument);
         }
     }
 
 
     /**
-     *  add an argument tuple to the argument list, if the value aint null
+     *  add an argument tuple to the argument list, if the value isn't null
      * @param cmd the command line
      * @param  argument  The argument
      * @param  value     the parameter
@@ -121,7 +107,7 @@
     }
 
     /**
-     *  add an argument tuple to the arg list, if the file parameter aint null
+     *  add an argument tuple to the arg list, if the file parameter isn't null
      * @param cmd the command line
      * @param  argument  The argument
      * @param  file     the parameter
@@ -138,6 +124,7 @@
      * @return true if the compiler wants to do its own
      * depends
      */
+    @Override
     public boolean implementsOwnDependencyChecking() {
         return false;
     }
@@ -150,4 +137,3 @@
         return getJspc().getProject();
     }
 }
-
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..bdcae84 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -59,6 +59,7 @@
      * @return true if successful
      * @throws BuildException on error
      */
+    @Override
     public boolean execute()
         throws BuildException {
         getJspc().log("Using jasper compiler", Project.MSG_VERBOSE);
@@ -80,9 +81,8 @@
             java.setDir(getProject().getBaseDir());
             java.setClassname("org.apache.jasper.JspC");
             //this is really irritating; we need a way to set stuff
-            String []args = cmd.getJavaCommand().getArguments();
-            for (int i = 0; i < args.length; i++) {
-                java.createArg().setValue(args[i]);
+            for (String arg : cmd.getJavaCommand().getArguments()) {
+                java.createArg().setValue(arg);
             }
             java.setFailonerror(getJspc().getFailonerror());
             //we are forking here to be sure that if JspC calls
@@ -94,17 +94,14 @@
         } catch (Exception ex) {
             if (ex instanceof BuildException) {
                 throw (BuildException) ex;
-            } else {
-                throw new BuildException("Error running jsp compiler: ",
-                                         ex, getJspc().getLocation());
             }
+            throw new BuildException("Error running jsp compiler: ",
+                                         ex, getJspc().getLocation());
         } finally {
             getJspc().deleteEmptyJavaFiles();
         }
     }
 
-
-
     /**
      * build up a command line
      * @return a command line for jasper
@@ -144,7 +141,7 @@
     /**
      * @return an instance of the mangler this compiler uses
      */
-
+    @Override
     public JspMangler createMangler() {
         return mangler;
     }
@@ -157,26 +154,19 @@
         if (p == null) {
             p = new Path(getProject());
             return p.concatSystemClasspath("only");
-        } else {
-            return p.concatSystemClasspath("ignore");
         }
+        return p.concatSystemClasspath("ignore");
     }
 
     /**
      * @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/jsp/compilers/JspCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapter.java
index 68e693c..d3505d3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapterFactory.java
index 2876ba0..a894621 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapterFactory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JspCompilerAdapterFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -80,11 +80,11 @@
                                                  AntClassLoader loader)
         throws BuildException {
 
-        if (compilerType.equalsIgnoreCase("jasper")) {
+        if ("jasper".equalsIgnoreCase(compilerType)) {
             //tomcat4.0 gets the old mangler
             return new JasperC(new JspNameMangler());
         }
-        if (compilerType.equalsIgnoreCase("jasper41")) {
+        if ("jasper41".equalsIgnoreCase(compilerType)) {
             //tomcat4.1 gets the new one
             return new JasperC(new Jasper41Mangler());
         }
@@ -104,13 +104,12 @@
                                                        AntClassLoader classloader)
         throws BuildException {
         try {
-            Class c = classloader.findClass(className);
-            Object o = c.newInstance();
-            return (JspCompilerAdapter) o;
+            Class<? extends JspCompilerAdapter> c = classloader.findClass(className).asSubclass(JspCompilerAdapter.class);
+            return c.getDeclaredConstructor().newInstance();
         } catch (ClassNotFoundException cnfe) {
-            throw new BuildException(className + " can\'t be found.", cnfe);
+            throw new BuildException(className + " can't be found.", cnfe);
         } catch (ClassCastException cce) {
-            throw new BuildException(className + " isn\'t the classname of "
+            throw new BuildException(className + " isn't the classname of "
                                      + "a compiler adapter.", cce);
         } catch (Throwable t) {
             // for all other possibilities
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 911fb4b..7ad3ed5 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,11 @@
 package org.apache.tools.ant.taskdefs.optional.junit;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
-
+import java.nio.file.Files;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.TransformerFactory;
@@ -72,12 +71,27 @@
          * list authorized values.
          * @return authorized values.
          */
+        @Override
         public String[] getValues() {
             return new String[]{FRAMES, NOFRAMES};
         }
     }
 
+    private static final String JDK_INTERNAL_FACTORY =
+            "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
+
     // CheckStyle:VisibilityModifier OFF - bc
+    /** XML Parser factory */
+    private static DocumentBuilderFactory privateDBFactory;
+
+    /** XML Parser factory accessible to subclasses */
+    protected static DocumentBuilderFactory dbfactory;
+
+    static {
+       privateDBFactory = DocumentBuilderFactory.newInstance();
+       dbfactory = privateDBFactory;
+    }
+
     /** Task */
     protected Task task;
 
@@ -114,19 +128,9 @@
      */
     private static volatile int counter = 0;
 
-    /** the format to use for the report. Must be <tt>FRAMES</tt> or <tt>NOFRAMES</tt> */
+    /** the format to use for the report. Must be <code>FRAMES</code> or <code>NOFRAMES</code> */
     protected String format = FRAMES;
 
-    /** XML Parser factory */
-    private static DocumentBuilderFactory privateDBFactory;
-
-    /** XML Parser factory accessible to subclasses */
-    protected static DocumentBuilderFactory dbfactory;
-
-    static {
-       privateDBFactory = DocumentBuilderFactory.newInstance();
-       dbfactory = privateDBFactory;
-    }
     // CheckStyle:VisibilityModifier ON
 
     /**
@@ -150,7 +154,7 @@
 
     /**
      * sets the format.
-     * @param format  Must be <tt>FRAMES</tt> or <tt>NOFRAMES</tt>
+     * @param format  Must be <code>FRAMES</code> or <code>NOFRAMES</code>
      */
     public void setFormat(Format format) {
         this.format = format.getValue();
@@ -173,12 +177,9 @@
     protected void setXmlfile(File xmlfile) throws BuildException {
         try {
             DocumentBuilder builder = privateDBFactory.newDocumentBuilder();
-            InputStream in = new FileInputStream(xmlfile);
-            try {
+            try (InputStream in = Files.newInputStream(xmlfile.toPath())) {
                 Document doc = builder.parse(in);
                 setXmlDocument(doc);
-            } finally {
-                in.close();
             }
         } catch (Exception e) {
             throw new BuildException("Error while parsing document: " + xmlfile, e);
@@ -257,9 +258,9 @@
 
         // acrobatic cast.
         xsltTask.setIn(((XMLResultAggregator) task).getDestinationFile());
-        File outputFile = null;
-        if (format.equals(FRAMES)) {
-            String tempFileProperty = getClass().getName() + String.valueOf(counter++); //NOSONAR
+        File outputFile;
+        if (FRAMES.equals(format)) {
+            String tempFileProperty = getClass().getName() + counter++; //NOSONAR
             File tmp = FILE_UTILS.resolveFile(project.getBaseDir(), project
                     .getProperty("java.io.tmpdir"));
             tempFileTask.setDestDir(tmp);
@@ -296,10 +297,7 @@
      * @return stylesheet as a resource
      */
     protected Resource getStylesheet() {
-        String xslname = "junit-frames.xsl";
-        if (NOFRAMES.equals(format)) {
-            xslname = "junit-noframes.xsl";
-        }
+        final String xslname = getXslName();
         if (styleDir == null) {
             // If style dir is not specified we have to retrieve
             // the stylesheet from the classloader
@@ -312,6 +310,32 @@
         return new FileResource(new File(styleDir, xslname));
     }
 
+    /**
+     * Gets the filename of the XSL stylesheet
+     *
+     * Will provide Xalan or Saxon specific
+     * stylesheets.
+     *
+     * @return The filename of the stylesheet
+     */
+    private String getXslName() {
+        final String suffix;
+
+        final String xsltFactoryName = xsltFactory == null ? null :  xsltFactory.getName();
+        if ("net.sf.saxon.TransformerFactoryImpl".equals(xsltFactoryName)) {
+            suffix = "-saxon.xsl";
+        } else {
+            suffix = ".xsl";
+        }
+        final String xslname;
+        if (NOFRAMES.equals(format)) {
+            xslname = "junit-noframes" + suffix;
+        } else {
+            xslname = "junit-frames" + suffix;
+        }
+        return xslname;
+    }
+
     /** check for invalid options
      * @throws BuildException if something goes wrong.
      */
@@ -334,10 +358,7 @@
      * not exist.
      */
     protected String getStylesheetSystemId() throws IOException {
-        String xslname = "junit-frames.xsl";
-        if (NOFRAMES.equals(format)) {
-            xslname = "junit-noframes.xsl";
-        }
+        final String xslname = getXslName();
         if (styleDir == null) {
             URL url = getClass().getResource("xsl/" + xslname);
             if (url == null) {
@@ -352,8 +373,6 @@
         return JAXPUtils.getSystemId(file);
     }
 
-    private static final String JDK_INTERNAL_FACTORY = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
-
     /**
      * If we end up using the JDK's own TraX factory on Java 9+, then
      * set the features and attributes necessary to allow redirect
@@ -372,8 +391,9 @@
         }
         if (JDK_INTERNAL_FACTORY.equals(factoryName)
             && JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
-            factory.addFeature(new XSLTProcess.Factory.Feature("http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions",
-                                                               true));
+            factory.addFeature(new XSLTProcess.Factory.Feature(
+                "http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions",
+                true));
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java
index 24e6c07..245f168 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,7 +33,7 @@
     protected boolean fork = false;
     protected String ifProperty = null;
     protected String unlessProperty = null;
-    protected Vector formatters = new Vector();
+    protected Vector<FormatterElement> formatters = new Vector<>();
     /** destination directory */
     protected File destDir = null;
 
@@ -191,7 +191,7 @@
     /**
      * Get the destination directory.
      * @return the destination directory as an absolute path if it exists
-     *         otherwise return <tt>null</tt>
+     *         otherwise return <code>null</code>
      */
     public String getTodir() {
         if (destDir != null) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java
index 8eeccc8..6ee7627 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,12 @@
 
 package org.apache.tools.ant.taskdefs.optional.junit;
 
-
 import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Vector;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.FileSet;
@@ -59,7 +61,7 @@
 
     /**
      * Add a new fileset instance to this batchtest. Whatever the fileset is,
-     * only filename that are <tt>.java</tt> or <tt>.class</tt> will be
+     * only filename that are <code>.java</code> or <code>.class</code> will be
      * considered as 'candidates'.
      * @param     fs the new fileset containing the rules to get the testcases.
      */
@@ -79,11 +81,10 @@
         }
     }
 
-
     /**
      * Add a new ResourceCollection instance to this
      * batchtest. Whatever the collection is, only names that are
-     * <tt>.java</tt> or <tt>.class</tt> will be considered as
+     * <code>.java</code> or <code>.class</code> will be considered as
      * 'candidates'.
      * @param rc the new ResourceCollection containing the rules to
      * get the testcases.
@@ -94,22 +95,21 @@
     }
 
     /**
-     * Return all <tt>JUnitTest</tt> instances obtain by applying the fileset rules.
+     * Return all <code>JUnitTest</code> instances obtain by applying the fileset rules.
      * @return  an enumeration of all elements of this batchtest that are
-     * a <tt>JUnitTest</tt> instance.
+     * a <code>JUnitTest</code> instance.
      */
-    public Enumeration elements() {
-        JUnitTest[] tests = createAllJUnitTest();
-        return Enumerations.fromArray(tests);
+    public Enumeration<JUnitTest> elements() {
+        return Collections.enumeration(Arrays.asList(createAllJUnitTest()));
     }
 
     /**
-     * Convenient method to merge the <tt>JUnitTest</tt>s of this batchtest
-     * to a <tt>Vector</tt>.
+     * Convenient method to merge the <code>JUnitTest</code>s of this batchtest
+     * to a <code>Vector</code>.
      * @param v the vector to which should be added all individual tests of this
      * batch test.
      */
-    void addTestsTo(Vector v) {
+    void addTestsTo(Vector<? super JUnitTest> v) {
         JUnitTest[] tests = createAllJUnitTest();
         v.ensureCapacity(v.size() + tests.length);
         for (JUnitTest test : tests) {
@@ -118,52 +118,37 @@
     }
 
     /**
-     * Create all <tt>JUnitTest</tt>s based on the filesets. Each instance
+     * Create all <code>JUnitTest</code>s based on the filesets. Each instance
      * is configured to match this instance properties.
-     * @return the array of all <tt>JUnitTest</tt>s that belongs to this batch.
+     * @return the array of all <code>JUnitTest</code>s that belongs to this batch.
      */
     private JUnitTest[] createAllJUnitTest() {
-        String[] filenames = getFilenames();
-        JUnitTest[] tests = new JUnitTest[filenames.length];
-        for (int i = 0; i < tests.length; i++) {
-            String classname = javaToClass(filenames[i]);
-            tests[i] = createJUnitTest(classname);
-        }
-        return tests;
+        return Stream.of(getFilenames()).map(BatchTest::javaToClass)
+            .map(this::createJUnitTest).toArray(JUnitTest[]::new);
     }
 
     /**
      * Iterate over all filesets and return the filename of all files
-     * that end with <tt>.java</tt> or <tt>.class</tt>. This is to avoid
-     * wrapping a <tt>JUnitTest</tt> over an xml file for example. A Testcase
+     * that end with <code>.java</code> or <code>.class</code>. This is to avoid
+     * wrapping a <code>JUnitTest</code> over an xml file for example. A Testcase
      * is obviously a java file (compiled or not).
      * @return an array of filenames without their extension. As they should
      * normally be taken from their root, filenames should match their fully
      * qualified class name (If it is not the case it will fail when running the test).
-     * For the class <tt>org/apache/Whatever.class</tt> it will return <tt>org/apache/Whatever</tt>.
+     * For the class <code>org/apache/Whatever.class</code> it will return <code>org/apache/Whatever</code>.
      */
     private String[] getFilenames() {
-        Vector v = new Vector();
-        for (Resource r : resources) {
-            if (r.isExists()) {
-                String pathname = r.getName();
-                if (pathname.endsWith(".java")) {
-                    v.addElement(pathname.substring(0, pathname.length() - ".java".length()));
-                } else if (pathname.endsWith(".class")) {
-                    v.addElement(pathname.substring(0, pathname.length() - ".class".length()));
-                }
-            }
-        }
-
-        String[] files = new String[v.size()];
-        v.copyInto(files);
-        return files;
+        return resources.stream().filter(Resource::isExists)
+            .map(Resource::getName)
+            .filter(name -> name.endsWith(".java") || name.endsWith(".class"))
+            .map(name -> name.substring(0, name.lastIndexOf('.')))
+            .toArray(String[]::new);
     }
 
     /**
      * Convenient method to convert a pathname without extension to a
-     * fully qualified classname. For example <tt>org/apache/Whatever</tt> will
-     * be converted to <tt>org.apache.Whatever</tt>
+     * fully qualified classname. For example <code>org/apache/Whatever</code> will
+     * be converted to <code>org.apache.Whatever</code>
      * @param filename the filename to "convert" to a classname.
      * @return the classname matching the filename.
      */
@@ -173,11 +158,11 @@
     }
 
     /**
-     * Create a <tt>JUnitTest</tt> that has the same property as this
-     * <tt>BatchTest</tt> instance.
+     * Create a <code>JUnitTest</code> that has the same property as this
+     * <code>BatchTest</code> instance.
      * @param classname the name of the class that should be run as a
-     * <tt>JUnitTest</tt>. It must be a fully qualified name.
-     * @return the <tt>JUnitTest</tt> over the given classname.
+     * <code>JUnitTest</code>. It must be a fully qualified name.
+     * @return the <code>JUnitTest</code> over the given classname.
      */
     private JUnitTest createJUnitTest(String classname) {
         JUnitTest test = new JUnitTest();
@@ -192,10 +177,7 @@
         test.setFailureProperty(failureProperty);
         test.setErrorProperty(errorProperty);
         test.setSkipNonTests(isSkipNonTests());
-        Enumeration list = this.formatters.elements();
-        while (list.hasMoreElements()) {
-            test.addFormatter((FormatterElement) list.nextElement());
-        }
+        this.formatters.forEach(test::addFormatter);
         return test;
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java
index 8d106b2..4e4b091 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.io.BufferedWriter;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.StringWriter;
 import java.text.NumberFormat;
 
@@ -29,7 +30,6 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Prints plain text output of the test to a specified Writer.
@@ -89,15 +89,17 @@
      * Sets the stream the formatter is supposed to write its results to.
      * @param out the output stream to write to
      */
+    @Override
     public void setOutput(OutputStream out) {
         this.out = out;
-        output = new BufferedWriter(new java.io.OutputStreamWriter(out));
+        output = new BufferedWriter(new OutputStreamWriter(out));
     }
 
     /**
      * @see JUnitResultFormatter#setSystemOutput(String)
      * {@inheritDoc}.
      */
+    @Override
     public void setSystemOutput(String out) {
         systemOutput = out;
     }
@@ -106,6 +108,7 @@
      * @see JUnitResultFormatter#setSystemError(String)
      * {@inheritDoc}.
      */
+    @Override
     public void setSystemError(String err) {
         systemError = err;
     }
@@ -115,15 +118,13 @@
      * The whole testsuite started.
      * @param suite the test suite
      */
+    @Override
     public void startTestSuite(JUnitTest suite) {
         if (output == null) {
             return; // Quick return - no output do nothing.
         }
-        StringBuffer sb = new StringBuffer("Testsuite: ");
-        sb.append(suite.getName());
-        sb.append(StringUtils.LINE_SEP);
         try {
-            output.write(sb.toString());
+            output.write(String.format("Testsuite: %s%n", suite.getName()));
             output.flush();
         } catch (IOException ex) {
             throw new BuildException(ex);
@@ -134,8 +135,9 @@
      * The whole testsuite ended.
      * @param suite the test suite
      */
+    @Override
     public void endTestSuite(JUnitTest suite) {
-        StringBuffer sb = new StringBuffer("Tests run: ");
+        StringBuilder sb = new StringBuilder("Tests run: ");
         sb.append(suite.runCount());
         sb.append(", Failures: ");
         sb.append(suite.failureCount());
@@ -145,25 +147,19 @@
         sb.append(suite.skipCount());
         sb.append(", Time elapsed: ");
         sb.append(numberFormat.format(suite.getRunTime() / ONE_SECOND));
-        sb.append(" sec");
-        sb.append(StringUtils.LINE_SEP);
-        sb.append(StringUtils.LINE_SEP);
+        sb.append(String.format(" sec%n%n"));
 
         // append the err and output streams to the log
-        if (systemOutput != null && systemOutput.length() > 0) {
-            sb.append("------------- Standard Output ---------------")
-                    .append(StringUtils.LINE_SEP)
-                    .append(systemOutput)
-                    .append("------------- ---------------- ---------------")
-                    .append(StringUtils.LINE_SEP);
+        if (systemOutput != null && !systemOutput.isEmpty()) {
+            sb.append(String.format("------------- Standard Output ---------------%n"));
+            sb.append(systemOutput);
+            sb.append(String.format("------------- ---------------- ---------------%n"));
         }
 
-        if (systemError != null && systemError.length() > 0) {
-            sb.append("------------- Standard Error -----------------")
-                    .append(StringUtils.LINE_SEP)
-                    .append(systemError)
-                    .append("------------- ---------------- ---------------")
-                    .append(StringUtils.LINE_SEP);
+        if (systemError != null && !systemError.isEmpty()) {
+            sb.append(String.format("------------- Standard Error -----------------%n"));
+            sb.append(systemError);
+            sb.append(String.format("------------- ---------------- ---------------%n"));
         }
 
         if (output != null) {
@@ -190,6 +186,7 @@
      * A test started.
      * @param test a test
      */
+    @Override
     public void startTest(Test test) {
     }
 
@@ -197,6 +194,7 @@
      * A test ended.
      * @param test a test
      */
+    @Override
     public void endTest(Test test) {
     }
 
@@ -218,6 +216,7 @@
      * @param test a test
      * @param t    the assertion failed by the test
      */
+    @Override
     public void addFailure(Test test, AssertionFailedError t) {
         addFailure(test, (Throwable) t);
     }
@@ -227,6 +226,7 @@
      * @param test  a test
      * @param error the error thrown by the test
      */
+    @Override
     public void addError(Test test, Throwable error) {
         formatError("\tCaused an ERROR", test, error);
     }
@@ -239,9 +239,8 @@
     protected String formatTest(Test test) {
         if (test == null) {
             return "Null Test: ";
-        } else {
-            return "Testcase: " + test.toString() + ":";
         }
+        return "Testcase: " + test.toString() + ":";
     }
 
     /**
@@ -271,6 +270,7 @@
     }
 
 
+    @Override
     public void testIgnored(Test test) {
         formatSkip(test, JUnitVersionHelper.getIgnoreMessage(test));
     }
@@ -294,6 +294,7 @@
 
     }
 
+    @Override
     public void testAssumptionFailure(Test test, Throwable cause) {
         formatSkip(test, cause.getMessage());
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java
index e9bd301..734d9a3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/Constants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache.java
index 8ad40dd..bf9982c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,11 +30,11 @@
 /**
  * Provides a custom implementation of the notifier for a JUnit4TestAdapter
  * so that skipped and ignored tests can be reported to the existing
- * <tt>TestListener</tt>s.
+ * <code>TestListener</code>s.
  *
  */
 public class CustomJUnit4TestAdapterCache extends JUnit4TestAdapterCache {
-
+    private static final long serialVersionUID = 1L;
     private static final CustomJUnit4TestAdapterCache INSTANCE = new CustomJUnit4TestAdapterCache();
 
     public static CustomJUnit4TestAdapterCache getInstance() {
@@ -45,6 +45,7 @@
         super();
     }
 
+    @Override
     public RunNotifier getNotifier(final TestResult result, final JUnit4TestAdapter adapter) {
         return getNotifier(result);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/DOMUtil.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/DOMUtil.java
index cb1939e..f45b844 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/DOMUtil.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/DOMUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,13 +43,13 @@
 
     /**
      * Filter interface to be applied when iterating over a DOM tree.
-     * Just think of it like a <tt>FileFilter</tt> clone.
+     * Just think of it like a <code>FileFilter</code> clone.
      */
     public interface NodeFilter {
         /**
          * @param       node    the node to check for acceptance.
-         * @return      <tt>true</tt> if the node is accepted by this filter,
-         *                      otherwise <tt>false</tt>
+         * @return      <code>true</code> if the node is accepted by this filter,
+         *                      otherwise <code>false</code>
          */
         boolean accept(Node node);
     }
@@ -59,8 +59,8 @@
      * recursively or not.
      * @param   parent  the parent node to search from
      * @param   filter  the filter that children should match.
-     * @param   recurse <tt>true</tt> if you want the list to be made recursively
-     *                  otherwise <tt>false</tt>.
+     * @param   recurse <code>true</code> if you want the list to be made recursively
+     *                  otherwise <code>false</code>.
      * @return the node list that matches the filter.
      */
     public static NodeList listChildNodes(Node parent, NodeFilter filter, boolean recurse) {
@@ -86,13 +86,14 @@
     }
 
     /** custom implementation of a nodelist */
-    public static class NodeListImpl extends Vector implements NodeList {
+    public static class NodeListImpl extends Vector<Node> implements NodeList {
         private static final long serialVersionUID = 3175749150080946423L;
 
         /**
          * Get the number of nodes in the list.
          * @return the length of the list.
          */
+        @Override
         public int getLength() {
             return size();
         }
@@ -101,9 +102,10 @@
          * @param i the index of the node to get.
          * @return the node if the index is in bounds, null otherwise.
          */
+        @Override
         public Node item(int i) {
             try {
-                return (Node) elementAt(i);
+                return elementAt(i);
             } catch (ArrayIndexOutOfBoundsException e) {
                 return null; // conforming to NodeList interface
             }
@@ -114,8 +116,8 @@
      * return the attribute value of an element.
      * @param node the node to get the attribute from.
      * @param name the name of the attribute we are looking for the value.
-     * @return the value of the requested attribute or <tt>null</tt> if the
-     *         attribute was not found or if <tt>node</tt> is not an <tt>Element</tt>.
+     * @return the value of the requested attribute or <code>null</code> if the
+     *         attribute was not found or if <code>node</code> is not an <code>Element</code>.
      */
     public static String getNodeAttribute(Node node, String name) {
         if (node instanceof Element) {
@@ -129,10 +131,10 @@
     /**
      * Iterate over the children of a given node and return the first node
      * that has a specific name.
-     * @param   parent  the node to search child from. Can be <tt>null</tt>.
-     * @param   tagname the child name we are looking for. Cannot be <tt>null</tt>.
-     * @return  the first child that matches the given name or <tt>null</tt> if
-     *                  the parent is <tt>null</tt> or if a child does not match the
+     * @param   parent  the node to search child from. Can be <code>null</code>.
+     * @param   tagname the child name we are looking for. Cannot be <code>null</code>.
+     * @return  the first child that matches the given name or <code>null</code> if
+     *                  the parent is <code>null</code> or if a child does not match the
      *                  given name.
      */
     public static Element getChildByTagName(Node parent, String tagname) {
@@ -153,20 +155,20 @@
 
     /**
      * Simple tree walker that will clone recursively a node. This is to
-     * avoid using parser-specific API such as Sun's <tt>changeNodeOwner</tt>
-     * when we are dealing with DOM L1 implementations since <tt>cloneNode(boolean)</tt>
+     * avoid using parser-specific API such as Sun's <code>changeNodeOwner</code>
+     * when we are dealing with DOM L1 implementations since <code>cloneNode(boolean)</code>
      * will not change the owner document.
-     * <tt>changeNodeOwner</tt> is much faster and avoid the costly cloning process.
-     * <tt>importNode</tt> is in the DOM L2 interface.
+     * <code>changeNodeOwner</code> is much faster and avoid the costly cloning process.
+     * <code>importNode</code> is in the DOM L2 interface.
      * @param   parent  the node parent to which we should do the import to.
      * @param   child   the node to clone recursively. Its clone will be
-     *              appended to <tt>parent</tt>.
-     * @return  the cloned node that is appended to <tt>parent</tt>
+     *              appended to <code>parent</code>.
+     * @return  the cloned node that is appended to <code>parent</code>
      */
     public static Node importNode(Node parent, Node child) {
-        Node copy = null;
         final Document doc = parent.getOwnerDocument();
 
+        Node copy;
         switch (child.getNodeType()) {
         case Node.CDATA_SECTION_NODE:
             copy = doc.createCDATASection(((CDATASection) child).getData());
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/Enumerations.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/Enumerations.java
index c6a014d..4e711e0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/Enumerations.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/Enumerations.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,8 @@
  */
 package org.apache.tools.ant.taskdefs.optional.junit;
 
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.NoSuchElementException;
 
@@ -26,6 +28,7 @@
  * instead of 1.1.
  *
  */
+@Deprecated
 public final class Enumerations {
 
     private Enumerations() {
@@ -33,73 +36,36 @@
 
     /**
      * creates an enumeration from an array of objects.
-     * @param       array   the array of object to enumerate.
+     * @param <T> object type
+     * @param array the array of object to enumerate.
      * @return the enumeration over the array of objects.
+     * @deprecated use Collections.enumeration(Arrays.asList(array))
      */
-    public static Enumeration fromArray(Object[] array) {
-        return new ArrayEnumeration(array);
+    @Deprecated
+    @SafeVarargs
+    public static <T> Enumeration<T> fromArray(T... array) {
+        return Collections.enumeration(Arrays.asList(array));
     }
 
     /**
      * creates an enumeration from an array of enumeration. The created enumeration
      * will sequentially enumerate over all elements of each enumeration and skip
-     * <tt>null</tt> enumeration elements in the array.
-     * @param        enums   the array of enumerations.
+     * <code>null</code> enumeration elements in the array.
+     * @param <T> object type
+     * @param enums the array of enumerations.
      * @return the enumeration over the array of enumerations.
+     * @deprecated use Stream.concat(Collections.list(one).stream(), Collections.list(two).stream())
+     *                 .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::enumeration))
      */
-    public static Enumeration fromCompound(Enumeration[] enums) {
-        return new CompoundEnumeration(enums);
+    @Deprecated
+    @SafeVarargs
+    public static <T> Enumeration<T> fromCompound(Enumeration<? extends T>... enums) {
+        return new CompoundEnumeration<>(enums);
     }
 
 }
 
 /**
- * Convenient enumeration over an array of objects.
- */
-class ArrayEnumeration implements Enumeration {
-
-    /** object array */
-    private Object[] array;
-
-    /** current index */
-    private int pos;
-
-    /**
-     * Initialize a new enumeration that wraps an array.
-     * @param       array   the array of object to enumerate.
-     */
-    public ArrayEnumeration(Object[] array) {
-        this.array = array;
-        this.pos = 0;
-    }
-    /**
-     * Tests if this enumeration contains more elements.
-     *
-     * @return  <code>true</code> if and only if this enumeration object
-     *           contains at least one more element to provide;
-     *          <code>false</code> otherwise.
-     */
-    public boolean hasMoreElements() {
-        return (pos < array.length);
-    }
-
-    /**
-     * Returns the next element of this enumeration if this enumeration
-     * object has at least one more element to provide.
-     *
-     * @return     the next element of this enumeration.
-     * @throws  NoSuchElementException  if no more elements exist.
-     */
-    public Object nextElement() throws NoSuchElementException {
-        if (hasMoreElements()) {
-            Object o = array[pos];
-            pos++;
-            return o;
-        }
-        throw new NoSuchElementException();
-    }
-}
-/**
  * Convenient enumeration over an array of enumeration. For example:
  * <pre>
  * Enumeration e1 = v1.elements();
@@ -129,15 +95,17 @@
  * }
  * </pre>
  */
-class CompoundEnumeration implements Enumeration {
+@Deprecated
+class CompoundEnumeration<T> implements Enumeration<T> {
 
     /** enumeration array */
-    private Enumeration[] enumArray;
+    private Enumeration<? extends T>[] enumArray;
 
     /** index in the enums array */
     private int index = 0;
 
-    public CompoundEnumeration(Enumeration[] enumarray) {
+    @SafeVarargs
+    public CompoundEnumeration(Enumeration<? extends T>... enumarray) {
         this.enumArray = enumarray;
     }
 
@@ -148,6 +116,7 @@
      *           contains at least one more element to provide;
      *          <code>false</code> otherwise.
      */
+    @Override
     public boolean hasMoreElements() {
         while (index < enumArray.length) {
             if (enumArray[index] != null && enumArray[index].hasMoreElements()) {
@@ -165,7 +134,8 @@
      * @return     the next element of this enumeration.
      * @throws  NoSuchElementException  if no more elements exist.
      */
-    public Object nextElement() throws NoSuchElementException {
+    @Override
+    public T nextElement() throws NoSuchElementException {
         if (hasMoreElements()) {
             return enumArray[index].nextElement();
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java
index c6a338b..9761f18 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FailureRecorder.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,11 +23,10 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.text.SimpleDateFormat;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.SortedSet;
 import java.util.TreeSet;
-import java.util.Vector;
-
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
 
@@ -88,7 +87,7 @@
     private static final String LOG_PREFIX = "    [junit]";
 
     /** Class names of failed tests without duplicates. */
-    private static SortedSet<TestInfos> failedTests = new TreeSet<TestInfos>();
+    private static SortedSet<TestInfos> failedTests = new TreeSet<>();
 
     /** A writer for writing the generated source to. */
     private BufferedWriter writer;
@@ -145,22 +144,13 @@
      * @param project
      *            project reference
      */
+    @Override
     public void setProject(Project project) {
         // store project reference for logging
         super.setProject(project);
         // check if already registered
-        boolean alreadyRegistered = false;
-        Vector allListeners = project.getBuildListeners();
-        final int size = allListeners.size();
-        for (int i = 0; i < size; i++) {
-            Object listener = allListeners.get(i);
-            if (listener instanceof FailureRecorder) {
-                alreadyRegistered = true;
-                break;
-            }
-        }
         // register if needed
-        if (!alreadyRegistered) {
+        if (project.getBuildListeners().stream().noneMatch(FailureRecorder.class::isInstance)) {
             verbose("Register FailureRecorder (@" + this.hashCode() + ") as BuildListener");
             project.addBuildListener(this);
         }
@@ -172,6 +162,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void endTestSuite(JUnitTest suite) throws BuildException {
     }
 
@@ -181,6 +172,7 @@
      * @param throwable the reason it erred.
      * @see junit.framework.TestListener#addError(junit.framework.Test, java.lang.Throwable)
      */
+    @Override
     public void addError(Test test, Throwable throwable) {
         failedTests.add(new TestInfos(test));
     }
@@ -193,6 +185,7 @@
      * @see junit.framework.TestListener#addFailure(junit.framework.Test, junit.framework.AssertionFailedError)
      */
     // CheckStyle:LineLengthCheck ON
+    @Override
     public void addFailure(Test test, AssertionFailedError error) {
         failedTests.add(new TestInfos(test));
     }
@@ -201,6 +194,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void setOutput(OutputStream out) {
         // unused, close output file so it can be deleted before the VM exits
         if (out != System.out) {
@@ -212,6 +206,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void setSystemError(String err) {
     }
 
@@ -219,6 +214,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void setSystemOutput(String out) {
     }
 
@@ -226,6 +222,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void startTestSuite(JUnitTest suite) throws BuildException {
     }
 
@@ -233,6 +230,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void endTest(Test test) {
     }
 
@@ -240,6 +238,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void startTest(Test test) {
     }
 
@@ -247,7 +246,7 @@
 
     private void writeJavaClass() {
         try {
-            File sourceFile = new File((getLocationName() + ".java"));
+            File sourceFile = new File(getLocationName() + ".java");
             verbose("Write collector class to '" + sourceFile.getAbsolutePath() + "'");
 
             if (sourceFile.exists() && !sourceFile.delete()) {
@@ -268,7 +267,7 @@
 
     private void createClassHeader() throws IOException {
         String className = getLocationName().replace('\\', '/');
-        if (className.indexOf('/') > -1) {
+        if (className.contains("/")) {
             className = className.substring(className.lastIndexOf('/') + 1);
         }
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss,SSS");
@@ -321,6 +320,7 @@
      * Logging facade in INFO-mode.
      * @param message Log-message
      */
+    @Override
     public void log(String message) {
         getProject().log(LOG_PREFIX + " " + message, Project.MSG_INFO);
     }
@@ -336,7 +336,7 @@
     /**
      * TestInfos holds information about a given test for later use.
      */
-    public static class TestInfos implements Comparable {
+    public static class TestInfos implements Comparable<TestInfos> {
 
         /** The class name of the test. */
         private final String className;
@@ -350,8 +350,8 @@
          */
         public TestInfos(Test test) {
             className = test.getClass().getName();
-            String _methodName = test.toString();
-            methodName = _methodName.substring(0, _methodName.indexOf('('));
+            String methodName = test.toString();
+            this.methodName = methodName.substring(0, methodName.indexOf('('));
         }
 
         /**
@@ -361,6 +361,7 @@
          * @see java.lang.Object#toString()
          * @see FailureRecorder#createSuiteMethod()
          */
+        @Override
         public String toString() {
             return "new " + className + "(\"" + methodName + "\")";
         }
@@ -372,17 +373,18 @@
          * @see java.lang.Comparable#compareTo
          * @see SortedSet#comparator()
          */
-        public int compareTo(Object other) {
-            if (other instanceof TestInfos) {
-                TestInfos otherInfos = (TestInfos) other;
-                return toString().compareTo(otherInfos.toString());
-            } else {
-                return -1;
-            }
+        @Override
+        public int compareTo(TestInfos other) {
+            return Comparator.comparing(Object::toString).compare(this, other);
         }
+
+        @Override
         public boolean equals(Object obj) {
-            return obj instanceof TestInfos && toString().equals(obj.toString());
+            return obj == this || obj instanceof TestInfos
+                && toString().equals(obj.toString());
         }
+
+        @Override
         public int hashCode() {
             return toString().hashCode();
         }
@@ -394,6 +396,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void buildFinished(BuildEvent event) {
     }
 
@@ -401,6 +404,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void buildStarted(BuildEvent event) {
     }
 
@@ -408,6 +412,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void messageLogged(BuildEvent event) {
     }
 
@@ -415,6 +420,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void targetFinished(BuildEvent event) {
     }
 
@@ -422,6 +428,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void targetStarted(BuildEvent event) {
     }
 
@@ -431,6 +438,7 @@
      * @param event  not used
      * @see org.apache.tools.ant.BuildListener#taskFinished(org.apache.tools.ant.BuildEvent)
      */
+    @Override
     public void taskFinished(BuildEvent event) {
         if (!failedTests.isEmpty()) {
             writeJavaClass();
@@ -441,6 +449,7 @@
      * Not used
      * {@inheritDoc}
      */
+    @Override
     public void taskStarted(BuildEvent event) {
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
index 5b31e7f..b64f5af 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,17 +20,18 @@
 
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.PropertyHelper;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.optional.junit.JUnitTaskMirror.JUnitResultFormatterMirror;
 import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.util.KeepAliveOutputStream;
 
@@ -59,6 +60,18 @@
  * @see JUnitResultFormatter
  */
 public class FormatterElement {
+    /** xml formatter class */
+    public static final String XML_FORMATTER_CLASS_NAME =
+        "org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter";
+    /** brief formatter class */
+    public static final String BRIEF_FORMATTER_CLASS_NAME =
+        "org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter";
+    /** plain formatter class */
+    public static final String PLAIN_FORMATTER_CLASS_NAME =
+        "org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter";
+    /** failure recorder class */
+    public static final String FAILURE_RECORDER_CLASS_NAME =
+        "org.apache.tools.ant.taskdefs.optional.junit.FailureRecorder";
 
     private String classname;
     private String extension;
@@ -74,19 +87,6 @@
      */
     private Project project;
 
-    /** xml formatter class */
-    public static final String XML_FORMATTER_CLASS_NAME =
-        "org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter";
-    /** brief formatter class */
-    public static final String BRIEF_FORMATTER_CLASS_NAME =
-        "org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter";
-    /** plain formatter class */
-    public static final String PLAIN_FORMATTER_CLASS_NAME =
-        "org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter";
-    /** failure recorder class */
-    public static final String FAILURE_RECORDER_CLASS_NAME =
-        "org.apache.tools.ant.taskdefs.optional.junit.FailureRecorder";
-
     /**
      * <p>Quick way to use a standard formatter.</p>
      *
@@ -104,18 +104,19 @@
      * @param type the enumerated value to use.
      */
     public void setType(TypeAttribute type) {
-        if ("xml".equals(type.getValue())) {
+        switch (type.getValue()) {
+        case "xml":
             setClassname(XML_FORMATTER_CLASS_NAME);
-        } else {
-            if ("brief".equals(type.getValue())) {
-                setClassname(BRIEF_FORMATTER_CLASS_NAME);
-            } else {
-                if ("failure".equals(type.getValue())) {
-                    setClassname(FAILURE_RECORDER_CLASS_NAME);
-                } else { // must be plain, ensured by TypeAttribute
-                    setClassname(PLAIN_FORMATTER_CLASS_NAME);
-                }
-            }
+            break;
+        case "brief":
+            setClassname(BRIEF_FORMATTER_CLASS_NAME);
+            break;
+        case "failure":
+            setClassname(FAILURE_RECORDER_CLASS_NAME);
+            break;
+        default:
+            setClassname(PLAIN_FORMATTER_CLASS_NAME);
+            break;
         }
     }
 
@@ -127,12 +128,18 @@
      */
     public void setClassname(String classname) {
         this.classname = classname;
-        if (XML_FORMATTER_CLASS_NAME.equals(classname)) {
-           setExtension(".xml");
-        } else if (PLAIN_FORMATTER_CLASS_NAME.equals(classname)) {
-           setExtension(".txt");
-        } else if (BRIEF_FORMATTER_CLASS_NAME.equals(classname)) {
-           setExtension(".txt");
+        if (classname != null) {
+            switch (classname) {
+            case XML_FORMATTER_CLASS_NAME:
+                setExtension(".xml");
+                break;
+            case PLAIN_FORMATTER_CLASS_NAME:
+                setExtension(".txt");
+                break;
+            case BRIEF_FORMATTER_CLASS_NAME:
+                setExtension(".txt");
+                break;
+            }
         }
     }
 
@@ -268,7 +275,6 @@
         this.project = project;
     }
 
-
     /**
      * @since Ant 1.6
      */
@@ -281,43 +287,34 @@
         //although this code appears to duplicate that of ClasspathUtils.newInstance,
         //we cannot use that because this formatter may run in a forked process,
         //without that class.
-        Class f = null;
+        Class<?> f;
         try {
             if (loader == null) {
                 f = Class.forName(classname);
             } else {
                 f = Class.forName(classname, true, loader);
             }
-        } catch (ClassNotFoundException e) {
-            throw new BuildException(
-                "Using loader " + loader + " on class " + classname
-                + ": " + e, e);
-        } catch (NoClassDefFoundError e) {
+        } catch (ClassNotFoundException | NoClassDefFoundError e) {
             throw new BuildException(
                 "Using loader " + loader + " on class " + classname
                 + ": " + e, e);
         }
 
-        Object o = null;
+        JUnitResultFormatterMirror r;
         try {
-            o = f.newInstance();
-        } catch (InstantiationException e) {
-            throw new BuildException(e);
-        } catch (IllegalAccessException e) {
+            r = f.asSubclass(JUnitResultFormatterMirror.class).getDeclaredConstructor().newInstance();
+        } catch (ClassCastException e) {
+            throw new BuildException("%s is not a JUnitResultFormatter", classname);
+        } catch (InstantiationException | IllegalAccessException
+                | NoSuchMethodException | InvocationTargetException e) {
             throw new BuildException(e);
         }
 
-        if (!(o instanceof JUnitTaskMirror.JUnitResultFormatterMirror)) {
-            throw new BuildException(classname + " is not a JUnitResultFormatter");
-        }
-        JUnitTaskMirror.JUnitResultFormatterMirror r =
-            (JUnitTaskMirror.JUnitResultFormatterMirror) o;
         if (useFile && outFile != null) {
             out = new DelayedFileOutputStream(outFile);
         }
         r.setOutput(out);
 
-
         boolean needToSetProjectReference = true;
         try {
             Field field = r.getClass().getField("project");
@@ -335,13 +332,11 @@
         if (needToSetProjectReference) {
             Method setter;
             try {
-                setter = r.getClass().getMethod("setProject", new Class[] {Project.class});
-                setter.invoke(r, new Object[] {project});
+                setter = r.getClass().getMethod("setProject", Project.class);
+                setter.invoke(r, project);
             } catch (NoSuchMethodException e) {
                 // no setProject to invoke; just ignore
-            } catch (IllegalAccessException e) {
-                throw new BuildException(e);
-            } catch (InvocationTargetException e) {
+            } catch (IllegalAccessException | InvocationTargetException e) {
                 throw new BuildException(e);
             }
         }
@@ -356,6 +351,7 @@
      */
     public static class TypeAttribute extends EnumeratedAttribute {
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
             return new String[] {"plain", "xml", "brief", "failure"};
         }
@@ -380,7 +376,7 @@
         public void write(int b) throws IOException {
             synchronized (this) {
                 if (outputStream == null) {
-                    outputStream = new BufferedOutputStream(new FileOutputStream(file));
+                    outputStream = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
                 }
             }
             outputStream.write(b);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestListener.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestListener.java
index 2c3103a..29c345e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestListener.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java
index 1497151..c91b534 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,15 +33,15 @@
 public class IgnoredTestResult extends TestResult {
 
 
-    private List<IgnoredTestListener> listeners = new ArrayList<IgnoredTestListener>();
-    private List<TestIgnored> ignored = new ArrayList<TestIgnored>();
-    private List<TestIgnored> skipped = new ArrayList<TestIgnored>();
+    private List<IgnoredTestListener> listeners = new ArrayList<>();
+    private List<TestIgnored> ignored = new ArrayList<>();
+    private List<TestIgnored> skipped = new ArrayList<>();
 
     public IgnoredTestResult() {
         super();
     }
 
-
+    @Override
     public synchronized void addListener(TestListener listener) {
         if (listener instanceof IgnoredTestListener) {
             listeners.add((IgnoredTestListener) listener);
@@ -49,6 +49,7 @@
         super.addListener(listener);
     }
 
+    @Override
     public synchronized  void removeListener(TestListener listener) {
         if (listener instanceof IgnoredTestListener) {
             listeners.remove(listener);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java
index 603495b..ff66de6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,8 @@
 
 package org.apache.tools.ant.taskdefs.optional.junit;
 
-import java.util.Iterator;
 import java.util.List;
+import java.util.function.Predicate;
 
 import junit.framework.Test;
 import junit.framework.TestResult;
@@ -41,7 +41,7 @@
  */
 public class JUnit4TestMethodAdapter implements Test {
 
-    private final Class testClass;
+    private final Class<?> testClass;
     private final String[] methodNames;
     private final Runner runner;
     private final CustomJUnit4TestAdapterCache cache;
@@ -55,7 +55,7 @@
      *             if any of the arguments is {@code null}
      *             or if any of the given method names is {@code null} or empty
      */
-    public JUnit4TestMethodAdapter(final Class testClass,
+    public JUnit4TestMethodAdapter(final Class<?> testClass,
                                    final String[] methodNames) {
         if (testClass == null) {
             throw new IllegalArgumentException("testClass is <null>");
@@ -67,7 +67,7 @@
             if (methodNames[i] == null) {
                 throw new IllegalArgumentException("method name #" + i + " is <null>");
             }
-            if (methodNames[i].length() == 0) {
+            if (methodNames[i].isEmpty()) {
                 throw new IllegalArgumentException("method name #" + i + " is empty");
             }
         }
@@ -87,6 +87,7 @@
         runner = request.getRunner();
     }
 
+    @Override
     public int countTestCases() {
         return runner.testCount();
     }
@@ -95,41 +96,31 @@
         return runner.getDescription();
     }
 
-    public List/*<Test>*/ getTests() {
+    public List<Test> getTests() {
         return cache.asTestList(getDescription());
     }
 
-    public Class getTestClass() {
+    public Class<?> getTestClass() {
         return testClass;
     }
 
+    @Override
     public void run(final TestResult result) {
         runner.run(cache.getNotifier(result));
     }
 
     @Override
     public String toString() {
-        String testClassName = testClass.getName();
-        StringBuilder buf = new StringBuilder(testClassName.length()
-                                              + 12 * methodNames.length)
-                            .append(':');
-        if (methodNames.length != 0) {
-            buf.append(methodNames[0]);
-            for (int i = 1; i < methodNames.length; i++) {
-                buf.append(',')
-                   .append(methodNames[i]);
-            }
-        }
-        return buf.toString();
+        return ":" + String.join(",", methodNames);
     }
 
     private static final class MultipleMethodsFilter extends Filter {
 
         private final Description methodsListDescription;
-        private final Class testClass;
+        private final Class<?> testClass;
         private final String[] methodNames;
 
-        private MultipleMethodsFilter(Class testClass, String[] methodNames) {
+        private MultipleMethodsFilter(Class<?> testClass, String[] methodNames) {
             if (testClass == null) {
                 throw new IllegalArgumentException("testClass is <null>");
             }
@@ -151,23 +142,10 @@
                 return false;
             }
             if (description.isTest()) {
-                Iterator/*<Description>*/ it = methodsListDescription.getChildren().iterator();
-                while (it.hasNext()) {
-                    Description methodDescription = (Description) it.next();
-                    if (methodDescription.equals(description)) {
-                        return true;
-                    }
-                }
-            } else {
-                Iterator/*<Description>*/ it = description.getChildren().iterator();
-                while (it.hasNext()) {
-                    Description each = (Description) it.next();
-                    if (shouldRun(each)) {
-                        return true;
-                    }
-                }
+                return methodsListDescription.getChildren().stream()
+                    .anyMatch(Predicate.isEqual(description));
             }
-            return false;
+            return description.getChildren().stream().anyMatch(this::shouldRun);
         }
 
         @Override
@@ -177,10 +155,7 @@
                 buf.append("No methods");
             } else {
                 buf.append(methodNames.length == 1 ? "Method " : "Methods ");
-                for (String methodName : methodNames) {
-                    buf.append(methodName).append(',');
-                }
-                buf.setLength(buf.length() - 1);
+                buf.append(String.join(",", methodNames));
             }
             buf.append('(').append(testClass.getName()).append(')');
             return buf.toString();
@@ -188,5 +163,4 @@
 
     }
 
-
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
index 2119fc9..66599f0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
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 0bdc6e1..2f6b42e 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,8 +21,6 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FilenameFilter;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -30,6 +28,7 @@
 import java.io.PrintStream;
 import java.lang.reflect.Constructor;
 import java.net.URL;
+import java.nio.file.Files;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
@@ -44,9 +43,12 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Vector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.taskdefs.Execute;
@@ -71,7 +73,7 @@
  *
  * <p>JUnit is a framework to create unit tests. It has been initially
  * created by Erich Gamma and Kent Beck.  JUnit can be found at <a
- * href="http://www.junit.org">http://www.junit.org</a>.
+ * href="https://www.junit.org">https://www.junit.org</a>.
  *
  * <p><code>JUnitTask</code> can run a single specific
  * <code>JUnitTest</code> using the <code>test</code> element.</p>
@@ -101,7 +103,7 @@
  *   &lt;junit printsummary="no" haltonfailure="yes" fork="${junit.fork}"&gt;
  *     &lt;jvmarg value="-classic"/&gt;
  *     &lt;classpath refid="tests-classpath"/&gt;
- *     &lt;sysproperty key="build.tests" value="${build.tests}"/&gt;
+ *     &lt;sysproperty key="build.tests.value" value="${build.tests.value}"/&gt;
  *     &lt;formatter type="brief" usefile="false" /&gt;
  *     &lt;batchtest&gt;
  *       &lt;fileset dir="${tests.dir}"&gt;
@@ -134,13 +136,27 @@
  */
 public class JUnitTask extends Task {
 
-    private static final String LINE_SEP
-        = System.getProperty("line.separator");
     private static final String CLASSPATH = "CLASSPATH";
+
+    private static final int STRING_BUFFER_SIZE = 128;
+    /**
+     * @since Ant 1.7
+     */
+    public static final String TESTLISTENER_PREFIX =
+        "junit.framework.TestListener: ";
+
+    /**
+     * Name of magic property that enables test listener events.
+     */
+    public static final String ENABLE_TESTLISTENER_EVENTS =
+        "ant.junit.enabletestlistenerevents";
+
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
     private CommandlineJava commandline;
-    private final Vector<JUnitTest> tests = new Vector<JUnitTest>();
-    private final Vector<BatchTest> batchTests = new Vector<BatchTest>();
-    private final Vector<FormatterElement> formatters = new Vector<FormatterElement>();
+    private final List<JUnitTest> tests = new Vector<>();
+    private final List<BatchTest> batchTests = new Vector<>();
+    private final Vector<FormatterElement> formatters = new Vector<>();
     private File dir = null;
 
     private Integer timeout = null;
@@ -188,21 +204,6 @@
     private String  failureProperty;
     private String  errorProperty;
 
-    private static final int STRING_BUFFER_SIZE = 128;
-    /**
-     * @since Ant 1.7
-     */
-    public static final String TESTLISTENER_PREFIX =
-        "junit.framework.TestListener: ";
-
-    /**
-     * Name of magic property that enables test listener events.
-     */
-    public static final String ENABLE_TESTLISTENER_EVENTS =
-        "ant.junit.enabletestlistenerevents";
-
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
     /**
      * If true, force ant to re-classload all classes for each JUnit TestCase
      *
@@ -219,8 +220,8 @@
      * <p>This property is applied on all BatchTest (batchtest) and
      * JUnitTest (test) however it can possibly be overridden by their
      * own properties.</p>
-     * @param value <tt>false</tt> if it should not filter, otherwise
-     * <tt>true</tt>
+     * @param value <code>false</code> if it should not filter, otherwise
+     * <code>true</code>
      *
      * @since Ant 1.5
      */
@@ -233,8 +234,8 @@
      * This property is applied on all BatchTest (batchtest) and JUnitTest
      * (test) however it can possibly be overridden by their own
      * properties.
-     * @param value <tt>true</tt> if it should halt, otherwise
-     * <tt>false</tt>
+     * @param value <code>true</code> if it should halt, otherwise
+     * <code>false</code>
      *
      * @since Ant 1.2
      */
@@ -263,8 +264,8 @@
      * This property is applied on all BatchTest (batchtest) and
      * JUnitTest (test) however it can possibly be overridden by their
      * own properties.
-     * @param value <tt>true</tt> if it should halt, otherwise
-     * <tt>false</tt>
+     * @param value <code>true</code> if it should halt, otherwise
+     * <code>false</code>
      *
      * @since Ant 1.2
      */
@@ -294,8 +295,8 @@
      * hanging the build.  this property is applied on all BatchTest
      * (batchtest) and JUnitTest (test) however it can possibly be
      * overridden by their own properties.</p>
-     * @param value <tt>true</tt> if a JVM should be forked, otherwise
-     * <tt>false</tt>
+     * @param value <code>true</code> if a JVM should be forked, otherwise
+     * <code>false</code>
      * @see #setTimeout
      *
      * @since Ant 1.2
@@ -350,9 +351,9 @@
      *
      * Can take the values on, off, and withOutAndErr.
      *
-     * @param value <tt>true</tt> to print a summary,
-     * <tt>withOutAndErr</tt> to include the test's output as
-     * well, <tt>false</tt> otherwise.
+     * @param value <code>true</code> to print a summary,
+     * <code>withOutAndErr</code> to include the test's output as
+     * well, <code>false</code> otherwise.
      * @see SummaryJUnitResultFormatter
      * @since Ant 1.2
      */
@@ -405,7 +406,7 @@
     /**
      * Set the maximum memory to be used by all forked JVMs.
      *
-     * @param   max     the value as defined by <tt>-mx</tt> or <tt>-Xmx</tt>
+     * @param   max     the value as defined by <code>-mx</code> or <code>-Xmx</code>
      *                  in the java command line options.
      * @since Ant 1.2
      */
@@ -418,7 +419,7 @@
      * default is 'java'. The command is resolved by
      * java.lang.Runtime.exec(). Ignored if fork is disabled.
      *
-     * @param   value   the new VM to use instead of <tt>java</tt>
+     * @param   value   the new VM to use instead of <code>java</code>
      * @see #setFork(boolean)
      *
      * @since Ant 1.2
@@ -589,7 +590,7 @@
      * @since Ant 1.2
      */
     public void addTest(final JUnitTest test) {
-        tests.addElement(test);
+        tests.add(test);
         preConfigure(test);
     }
 
@@ -602,7 +603,7 @@
      */
     public BatchTest createBatchTest() {
         final BatchTest test = new BatchTest(getProject());
-        batchTests.addElement(test);
+        batchTests.add(test);
         preConfigure(test);
         return test;
     }
@@ -614,7 +615,7 @@
      * @since Ant 1.2
      */
     public void addFormatter(final FormatterElement fe) {
-        formatters.addElement(fe);
+        formatters.add(fe);
     }
 
     /**
@@ -722,11 +723,9 @@
      * @since Ant 1.6
      */
     public void setTempdir(final File tmpDir) {
-        if (tmpDir != null) {
-            if (!tmpDir.exists() || !tmpDir.isDirectory()) {
-                throw new BuildException(tmpDir.toString()
-                                         + " is not a valid temp directory");
-            }
+        if (tmpDir != null && (!tmpDir.exists() || !tmpDir.isDirectory())) {
+            throw new BuildException("%s is not a valid temp directory",
+                tmpDir);
         }
         this.tmpDir = tmpDir;
     }
@@ -787,12 +786,12 @@
                     e, task.getLocation());
         }
         try {
-            final Class c = loader.loadClass(JUnitTaskMirror.class.getName() + "Impl");
+            final Class<? extends JUnitTaskMirror> c = loader.loadClass(JUnitTaskMirror.class.getName() + "Impl").asSubclass(JUnitTaskMirror.class);
             if (c.getClassLoader() != loader) {
                 throw new BuildException("Overdelegating loader", task.getLocation());
             }
-            final Constructor cons = c.getConstructor(new Class[] {JUnitTask.class});
-            return (JUnitTaskMirror) cons.newInstance(new Object[] {task});
+            final Constructor<? extends JUnitTaskMirror> cons = c.getConstructor(JUnitTask.class);
+            return cons.newInstance(task);
         } catch (final Exception e) {
             throw new BuildException(e, task.getLocation());
         }
@@ -818,18 +817,16 @@
             if (extra != null && !hasJunit(path)) {
                 path.add(expandModulePath(extra));
             }
-            mirrorLoader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    return new SplitClassLoader(myLoader, path, getProject(),
-                            new String[] {"BriefJUnitResultFormatter", "JUnit4TestMethodAdapter",
-                                    "JUnitResultFormatter", "JUnitTaskMirrorImpl", "JUnitTestRunner",
-                                    "JUnitVersionHelper", "OutErrSummaryJUnitResultFormatter",
-                                    "PlainJUnitResultFormatter", "SummaryJUnitResultFormatter",
-                                    "TearDownOnVmCrash", "XMLJUnitResultFormatter", "IgnoredTestListener",
-                                    "IgnoredTestResult", "CustomJUnit4TestAdapterCache",
-                                    "TestListenerWrapper"});
-                }
-            });
+            mirrorLoader = AccessController.doPrivileged(
+                (PrivilegedAction<ClassLoader>) () -> new SplitClassLoader(
+                    myLoader, path, getProject(),
+                    new String[] {"BriefJUnitResultFormatter", "JUnit4TestMethodAdapter",
+                            "JUnitResultFormatter", "JUnitTaskMirrorImpl", "JUnitTestRunner",
+                            "JUnitVersionHelper", "OutErrSummaryJUnitResultFormatter",
+                            "PlainJUnitResultFormatter", "SummaryJUnitResultFormatter",
+                            "TearDownOnVmCrash", "XMLJUnitResultFormatter", "IgnoredTestListener",
+                            "IgnoredTestResult", "CustomJUnit4TestAdapterCache",
+                            "TestListenerWrapper"}));
         } else {
             mirrorLoader = myLoader;
         }
@@ -848,23 +845,20 @@
         checkModules();
         setupJUnitDelegate();
 
-        final List<List> testLists = new ArrayList<List>();
+        final List<List<JUnitTest>> testLists = new ArrayList<>();
         /* parallel test execution is only supported for multi-process execution */
         final int threads = !fork || forkMode.getValue().equals(ForkMode.ONCE) ? 1 : this.threads;
 
-        final boolean forkPerTest = forkMode.getValue().equals(ForkMode.PER_TEST);
-        if (forkPerTest || forkMode.getValue().equals(ForkMode.ONCE)) {
+        final boolean forkPerTest = ForkMode.PER_TEST.equals(forkMode.getValue());
+        if (forkPerTest || ForkMode.ONCE.equals(forkMode.getValue())) {
             testLists.addAll(executeOrQueue(getIndividualTests(),
                                             forkPerTest));
         } else { /* forkMode.getValue().equals(ForkMode.PER_BATCH) */
-            final int count = batchTests.size();
-            for (int i = 0; i < count; i++) {
-                final BatchTest batchtest = batchTests.elementAt(i);
-                testLists.addAll(executeOrQueue(batchtest.elements(), false));
-            }
-            testLists.addAll(executeOrQueue(tests.elements(), forkPerTest));
+            batchTests.stream().map(b -> executeOrQueue(b.elements(), false))
+                .forEach(testLists::addAll);
+            testLists.addAll(
+                executeOrQueue(Collections.enumeration(tests), forkPerTest));
         }
-
         try {
             /* prior to parallel the code in 'oneJunitThread' used to be here. */
             runTestsInThreads(testLists, threads);
@@ -889,12 +883,13 @@
      */
     private class JunitTestThread implements Runnable {
 
-        JunitTestThread(final JUnitTask master, final Iterator<List> iterator, final int id) {
+        JunitTestThread(final JUnitTask master, final Iterator<List<JUnitTest>> iterator, final int id) {
             this.masterTask = master;
             this.iterator = iterator;
             this.id = id;
         }
 
+        @Override
         public void run() {
             try {
                 masterTask.oneJunitThread(iterator, id);
@@ -905,7 +900,7 @@
         }
 
         private final JUnitTask masterTask;
-        private final Iterator<List> iterator;
+        private final Iterator<List<JUnitTest>> iterator;
         private final int id;
     }
 
@@ -916,8 +911,8 @@
      * threads get the same test, or two threads simultaneously pop the list so that a test
      * gets skipped!
      */
-    private List getNextTest(final Iterator<List> iter) {
-        synchronized(iter) {
+    private List<JUnitTest> getNextTest(final Iterator<List<JUnitTest>> iter) {
+        synchronized (iter) {
             if (iter.hasNext()) {
                 return iter.next();
             }
@@ -936,14 +931,14 @@
      * fatal reason, no new tests/batches will be started but the running threads will be
      * permitted to complete.  Additional tests may start in already-running batch-test threads.
      */
-    private void oneJunitThread(final Iterator<List> iter, final int threadId) {
+    private void oneJunitThread(final Iterator<List<JUnitTest>> iter, final int threadId) {
 
-        List l;
+        List<JUnitTest> l;
         log("Starting test thread " + threadId, Project.MSG_VERBOSE);
         while ((caughtBuildException == null) && ((l = getNextTest(iter)) != null)) {
             log("Running test " + l.get(0).toString() + "(" + l.size() + ") in thread " + threadId, Project.MSG_VERBOSE);
             if (l.size() == 1) {
-                execute((JUnitTest) l.get(0), threadId);
+                execute(l.get(0), threadId);
             } else {
                 execute(l, threadId);
             }
@@ -952,9 +947,9 @@
     }
 
 
-    private void runTestsInThreads(final List<List> testList, final int numThreads) {
+    private void runTestsInThreads(final List<List<JUnitTest>> testList, final int numThreads) {
 
-        Iterator<List> iter = testList.iterator();
+        Iterator<List<JUnitTest>> iter = testList.iterator();
 
         if (numThreads == 1) {
             /* with just one thread just run the test - don't create any threads */
@@ -967,7 +962,7 @@
             /* Need to split apart tests, which are still grouped in batches */
             /* is there a simpler Java mechanism to do this? */
             /* I assume we don't want to do this with "per batch" forking. */
-            List<List> newlist = new ArrayList<List>();
+            List<List<JUnitTest>> newlist = new ArrayList<>();
             if (forkMode.getValue().equals(ForkMode.PER_TEST)) {
                 for (List<JUnitTest> list : testList) {
                     if (list.size() == 1) {
@@ -979,7 +974,7 @@
                     }
                 }
             } else {
-                 newlist = testList;
+                newlist = testList;
             }
             iter = newlist.iterator();
 
@@ -995,7 +990,7 @@
 
                 try {
                     for (i = 0; i < numThreads; i++) {
-                         threads[i].join();
+                        threads[i].join();
                     }
                 } catch (final InterruptedException e) {
                     exceptionOccurred = true;
@@ -1036,13 +1031,13 @@
         }
 
         // execute the test and get the return code
-        TestResultHolder result = null;
-        if (!test.getFork()) {
-            result = executeInVM(test);
-        } else {
+        TestResultHolder result;
+        if (test.getFork()) {
             final ExecuteWatchdog watchdog = createWatchdog();
             result = executeAsForked(test, watchdog, null);
             // null watchdog means no timeout, you'd better not check with null
+        } else {
+            result = executeInVM(test);
         }
         actOnTestResult(result, test, "Test " + test.getName());
     }
@@ -1064,8 +1059,8 @@
      * @throws BuildException if <code>testName</code> is not a valid test name
      */
     private void validateTestName(final String testName) throws BuildException {
-        if (testName == null || testName.length() == 0
-            || testName.equals("null")) {
+        if (testName == null || testName.isEmpty()
+            || "null".equals(testName)) {
             throw new BuildException("test name must be specified");
         }
     }
@@ -1076,23 +1071,21 @@
      * @param thread Identifies which thread is test running in (0 for single-threaded runs)
      * @throws BuildException on error.
      */
-    protected void execute(final List testList, final int thread) throws BuildException {
-        JUnitTest test = null;
+    protected void execute(final List<JUnitTest> testList, final int thread) throws BuildException {
         // Create a temporary file to pass the test cases to run to
         // the runner (one test case per line)
         final File casesFile = createTempPropertiesFile("junittestcases");
-        BufferedWriter writer = null;
-        try {
-            writer = new BufferedWriter(new FileWriter(casesFile));
+        try (BufferedWriter writer =
+            new BufferedWriter(new FileWriter(casesFile))) {
 
             log("Creating casesfile '" + casesFile.getAbsolutePath()
                 + "' with content: ", Project.MSG_VERBOSE);
             final PrintStream logWriter =
                 new PrintStream(new LogOutputStream(this, Project.MSG_VERBOSE));
 
-            final Iterator iter = testList.iterator();
-            while (iter.hasNext()) {
-                test = (JUnitTest) iter.next();
+            JUnitTest test = null;
+            for (JUnitTest t : testList) {
+                test = t;
                 test.setThread(thread);
                 printDual(writer, logWriter, test.getName());
                 if (test.getMethods() != null) {
@@ -1113,8 +1106,6 @@
                 }
             }
             writer.flush();
-            writer.close();
-            writer = null;
 
             // execute the test and get the return code
             final ExecuteWatchdog watchdog = createWatchdog();
@@ -1125,8 +1116,6 @@
             log(e.toString(), Project.MSG_ERR);
             throw new BuildException(e);
         } finally {
-            FileUtils.close(writer);
-
             try {
                 FILE_UTILS.tryHardToDelete(casesFile);
             } catch (final Exception e) {
@@ -1140,7 +1129,7 @@
      * @param testList the list of tests to execute.
      * @throws BuildException on error.
      */
-    protected void execute(final List testList) throws BuildException {
+    protected void execute(final List<JUnitTest> testList) throws BuildException {
         execute(testList, 0);
     }
 
@@ -1151,9 +1140,9 @@
      * attributes of the returned holder object.
      * @param  test       the testcase to execute.
      * @param  watchdog   the watchdog in charge of cancelling the test if it
-     * exceeds a certain amount of time. Can be <tt>null</tt>, in this case
+     * exceeds a certain amount of time. Can be <code>null</code>, in this case
      * the test could probably hang forever.
-     * @param casesFile list of test cases to execute. Can be <tt>null</tt>,
+     * @param casesFile list of test cases to execute. Can be <code>null</code>,
      * in this case only one test is executed.
      * @return the test results from the JVM itself.
      * @throws BuildException in case of error creating a temporary property file,
@@ -1171,7 +1160,7 @@
 
         CommandlineJava cmd;
         try {
-            cmd = (CommandlineJava) (getCommandline().clone());
+            cmd = (CommandlineJava) getCommandline().clone();
         } catch (final CloneNotSupportedException e) {
             throw new BuildException("This shouldn't happen", e, getLocation());
         }
@@ -1185,7 +1174,7 @@
             cmd.createArgument().setValue(Constants.TESTSFILE + casesFile);
         }
 
-        cmd.createArgument().setValue(Constants.SKIP_NON_TESTS + String.valueOf(test.isSkipNonTests()));
+        cmd.createArgument().setValue(Constants.SKIP_NON_TESTS + test.isSkipNonTests());
         cmd.createArgument().setValue(Constants.FILTERTRACE + test.getFiltertrace());
         cmd.createArgument().setValue(Constants.HALT_ON_ERROR + test.getHaltonerror());
         cmd.createArgument().setValue(Constants.HALT_ON_FAILURE
@@ -1195,19 +1184,19 @@
         checkIncludeSummary(cmd);
 
         cmd.createArgument().setValue(Constants.SHOWOUTPUT
-                                      + String.valueOf(showOutput));
+                                      + showOutput);
         cmd.createArgument().setValue(Constants.OUTPUT_TO_FORMATTERS
-                                      + String.valueOf(outputToFormatters));
+                                      + outputToFormatters);
         cmd.createArgument().setValue(Constants.LOG_FAILED_TESTS
-                                      + String.valueOf(logFailedTests));
+                                      + logFailedTests);
         cmd.createArgument().setValue(Constants.THREADID
-                                      + String.valueOf(test.getThread()));
+                                      + test.getThread());
 
         // #31885
         cmd.createArgument().setValue(Constants.LOGTESTLISTENEREVENTS
-                                      + String.valueOf(getEnableTestListenerEvents()));
+                                      + getEnableTestListenerEvents());
 
-        StringBuffer formatterArg = new StringBuffer(STRING_BUFFER_SIZE);
+        StringBuilder formatterArg = new StringBuilder(STRING_BUFFER_SIZE);
         final FormatterElement[] feArray = mergeFormatters(test);
         for (final FormatterElement fe : feArray) {
             if (fe.shouldUse(this)) {
@@ -1219,7 +1208,7 @@
                     formatterArg.append(outFile);
                 }
                 cmd.createArgument().setValue(formatterArg.toString());
-                formatterArg = new StringBuffer();
+                formatterArg = new StringBuilder();
             }
         }
 
@@ -1229,17 +1218,14 @@
         final File propsFile = createTempPropertiesFile("junit");
         cmd.createArgument().setValue(Constants.PROPSFILE
                                       + propsFile.getAbsolutePath());
-        final Hashtable p = getProject().getProperties();
+        final Hashtable<String, Object> p = getProject().getProperties();
         final Properties props = new Properties();
-        for (final Enumeration e = p.keys(); e.hasMoreElements();) {
-            final Object key = e.nextElement();
-            props.put(key, p.get(key));
-        }
+        props.putAll(p);
         try {
-            final FileOutputStream outstream = new FileOutputStream(propsFile);
+            final OutputStream outstream = Files.newOutputStream(propsFile.toPath());
             props.store(outstream, "Ant JUnitTask generated properties file");
             outstream.close();
-        } catch (final java.io.IOException e) {
+        } catch (final IOException e) {
             FILE_UTILS.tryHardToDelete(propsFile);
             throw new BuildException("Error creating temporary properties "
                                      + "file.", e, getLocation());
@@ -1321,9 +1307,9 @@
                     + propsFile.getAbsolutePath() + "'.";
                 if (success) {
                     throw new BuildException(msg); //NOSONAR
-                } else { // don't hide inner exception
-                    log(msg, Project.MSG_ERR);
                 }
+                // don't hide inner exception
+                log(msg, Project.MSG_ERR);
             }
         }
 
@@ -1336,8 +1322,8 @@
      */
     private void checkIncludeAntRuntime(final CommandlineJava cmd) {
         if (includeAntRuntime) {
-            final Map/*<String, String>*/ env = Execute.getEnvironmentVariables();
-            final String cp = (String) env.get(CLASSPATH);
+            final Map<String, String> env = Execute.getEnvironmentVariables();
+            final String cp = env.get(CLASSPATH);
             if (cp != null) {
                 cmd.createClasspath(getProject()).createPath()
                     .append(new Path(getProject(), cp));
@@ -1349,7 +1335,6 @@
         }
     }
 
-
     /**
      * check for the parameter being "withoutanderr" in a locale-independent way.
      * @param summaryOption the summary option -can be null
@@ -1385,26 +1370,21 @@
         if (!cmd.haveClasspath()) {
             return;
         }
-        AntClassLoader loader = null;
-        try {
-            loader =
-                AntClassLoader.newAntClassLoader(null, getProject(),
-                                                 cmd.createClasspath(getProject()),
-                                                 false);
+        try (AntClassLoader loader =
+            AntClassLoader.newAntClassLoader(null, getProject(),
+                                             cmd.createClasspath(getProject()),
+                                             false)) {
             loader.setIsolated(true);
             final String projectResourceName =
                 LoaderUtils.classNameToResource(Project.class.getName());
             URL previous = null;
             try {
-                for (final Enumeration e = loader.getResources(projectResourceName);
-                     e.hasMoreElements();) {
-                    final URL current = (URL) e.nextElement();
+                for (final URL current : Collections.list(loader.getResources(projectResourceName))) {
                     if (previous != null && !urlEquals(current, previous)) {
-                        log("WARNING: multiple versions of ant detected "
-                            + "in path for junit "
-                            + LINE_SEP + "         " + previous
-                            + LINE_SEP + "     and " + current,
-                            Project.MSG_WARN);
+                        log(String.format(
+                                "WARNING: multiple versions of ant detected in path for junit%n"
+                                        + "         %s%n     and %s", previous, current),
+                                Project.MSG_WARN);
                         return;
                     }
                     previous = current;
@@ -1412,10 +1392,6 @@
             } catch (final Exception ex) {
                 // Ignore exception
             }
-        } finally {
-            if (loader != null) {
-                loader.cleanup();
-            }
         }
     }
 
@@ -1452,10 +1428,8 @@
      * @return created file
      */
     private File createTempPropertiesFile(final String prefix) {
-        final File propsFile =
-            FILE_UTILS.createTempFile(getProject(), prefix, ".properties",
-                tmpDir != null ? tmpDir : getProject().getBaseDir(), true, true);
-        return propsFile;
+        return FILE_UTILS.createTempFile(getProject(), prefix, ".properties",
+            tmpDir != null ? tmpDir : getProject().getBaseDir(), true, true);
     }
 
 
@@ -1501,9 +1475,8 @@
         throws IOException {
         if (runner != null) {
             return runner.handleInput(buffer, offset, length);
-        } else {
-            return super.handleInput(buffer, offset, length);
         }
+        return super.handleInput(buffer, offset, length);
     }
 
 
@@ -1657,7 +1630,7 @@
     }
 
     /**
-     * @return <tt>null</tt> if there is a timeout value, otherwise the
+     * @return <code>null</code> if there is a timeout value, otherwise the
      * watchdog instance.
      *
      * @throws BuildException under unspecified circumstances
@@ -1667,7 +1640,7 @@
         if (timeout == null) {
             return null;
         }
-        return new ExecuteWatchdog((long) timeout.intValue());
+        return new ExecuteWatchdog((long) timeout);
     }
 
     /**
@@ -1682,20 +1655,15 @@
 
     /**
      * Merge all individual tests from the batchtest with all individual tests
-     * and return an enumeration over all <tt>JUnitTest</tt>.
+     * and return an enumeration over all <code>JUnitTest</code>.
      *
      * @return enumeration over individual tests
      * @since Ant 1.3
      */
     protected Enumeration<JUnitTest> getIndividualTests() {
-        final int count = batchTests.size();
-        final Enumeration[] enums = new Enumeration[ count + 1];
-        for (int i = 0; i < count; i++) {
-            final BatchTest batchtest = batchTests.elementAt(i);
-            enums[i] = batchtest.elements();
-        }
-        enums[enums.length - 1] = tests.elements();
-        return Enumerations.fromCompound(enums);
+        return Collections.enumeration(Stream.concat(batchTests.stream()
+                .flatMap(b -> Collections.list(b.elements()).stream()), tests.stream())
+                .collect(Collectors.toList()));
     }
 
     /**
@@ -1711,14 +1679,8 @@
         if (tests.isEmpty()) {
             return;
         }
-
-        final Enumeration<JUnitTest> testsEnum = tests.elements();
-        while (testsEnum.hasMoreElements()) {
-            final JUnitTest test = testsEnum.nextElement();
-            if (test.hasMethodsSpecified() && test.shouldRun(getProject())) {
-                test.resolveMethods();
-            }
-        }
+        tests.stream().filter(test -> test.hasMethodsSpecified() && test.shouldRun(getProject()))
+                .forEach(JUnitTest::resolveMethods);
     }
 
     /**
@@ -1726,17 +1688,12 @@
      * @since 1.9.8
      */
     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.");
-                }
+        if (hasPath(getCommandline().getModulepath())
+                || hasPath(getCommandline().getUpgrademodulepath())) {
+            if (!batchTests.stream().allMatch(BaseTest::getFork)
+                    || !tests.stream().allMatch(BaseTest::getFork)) {
+                throw new BuildException(
+                    "The module path requires fork attribute to be set to true.");
             }
         }
     }
@@ -1748,23 +1705,17 @@
      * @since 1.9.8
      */
     private boolean hasJunit(final Path path) {
-        AntClassLoader loader = null;
-        try {
-            loader = AntClassLoader.newAntClassLoader(
+        try (AntClassLoader loader = AntClassLoader.newAntClassLoader(
                 null,
                 getProject(),
                 path,
-                true);
+                true)) {
             try {
                 loader.loadClass("junit.framework.Test");
                 return true;
             } catch (final Exception ex) {
                 return false;
             }
-        } finally {
-            if (loader != null) {
-                loader.close();
-            }
         }
     }
 
@@ -1779,11 +1730,8 @@
         for (String path : modulePath.list()) {
             final File modulePathEntry = getProject().resolveFile(path);
             if (modulePathEntry.isDirectory() && !hasModuleInfo(modulePathEntry)) {
-                final File[] modules = modulePathEntry.listFiles(new FilenameFilter() {
-                        public boolean accept(File dir, String name) {
-                            return name.toLowerCase(Locale.ENGLISH).endsWith(".jar");
-                        }
-                    });
+                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(
@@ -1805,9 +1753,9 @@
      * @return enumeration
      * @since Ant 1.3
      */
-    protected Enumeration<JUnitTest> allTests() {
-        final Enumeration[] enums = {tests.elements(), batchTests.elements()};
-        return Enumerations.fromCompound(enums);
+    protected Enumeration<BaseTest> allTests() {
+        return Collections.enumeration(Stream.concat(tests.stream(), batchTests.stream())
+                .collect(Collectors.toList()));
     }
 
     /**
@@ -1816,6 +1764,7 @@
      * @since Ant 1.3
      */
     private FormatterElement[] mergeFormatters(final JUnitTest test) {
+        @SuppressWarnings("unchecked")
         final Vector<FormatterElement> feVector = (Vector<FormatterElement>) formatters.clone();
         test.addFormattersTo(feVector);
         final FormatterElement[] feArray = new FormatterElement[feVector.size()];
@@ -1890,7 +1839,7 @@
             antRuntimeClasses.createPath().setLocation(f);
             return true;
         } else {
-            log("Couldn\'t find " + resource, Project.MSG_DEBUG);
+            log("Couldn't find " + resource, Project.MSG_DEBUG);
             return false;
         }
     }
@@ -1960,7 +1909,7 @@
                         final File outFile = getOutput(fe, test);
                         if (outFile != null) {
                             try {
-                                out = new FileOutputStream(outFile);
+                                out = Files.newOutputStream(outFile.toPath());
                             } catch (final IOException e) {
                                 // ignore
                             }
@@ -2024,7 +1973,7 @@
                 // make sure the test annotation are accepted
                 classLoader.addSystemPackageRoot("org.junit");
                 // will cause trouble in JDK 1.1 if omitted
-                classLoader.addSystemPackageRoot("org.apache.tools.ant");
+                classLoader.addSystemPackageRoot(MagicNames.ANT_CORE_PACKAGE);
             }
         }
     }
@@ -2202,25 +2151,21 @@
      * @return a list of tasks to be executed.
      * @since 1.6.2
      */
-    protected Collection<List> executeOrQueue(final Enumeration<JUnitTest> testList,
-                                        final boolean runIndividual) {
-        final Map<ForkedTestConfiguration, List> testConfigurations = new HashMap<ForkedTestConfiguration, List>();
-        while (testList.hasMoreElements()) {
-            final JUnitTest test = testList.nextElement();
+    protected Collection<List<JUnitTest>> executeOrQueue(
+        final Enumeration<JUnitTest> testList, final boolean runIndividual) {
+        final Map<ForkedTestConfiguration, List<JUnitTest>> testConfigurations =
+            new HashMap<>();
+        for (final JUnitTest test : Collections.list(testList)) {
             if (test.shouldRun(getProject())) {
                 /* with multi-threaded runs need to defer execution of even */
                 /* individual tests so the threads can pick tests off the queue. */
-                if ((runIndividual || !test.getFork()) && (threads == 1)) {
+                if ((runIndividual || !test.getFork()) && threads == 1) {
                     execute(test, 0);
                 } else {
-                    final ForkedTestConfiguration c =
-                        new ForkedTestConfiguration(test);
-                    List<JUnitTest> l = testConfigurations.get(c);
-                    if (l == null) {
-                        l = new ArrayList<JUnitTest>();
-                        testConfigurations.put(c, l);
-                    }
-                    l.add(test);
+                    testConfigurations
+                        .computeIfAbsent(new ForkedTestConfiguration(test),
+                            k -> new ArrayList<>())
+                        .add(test);
                 }
             }
         }
@@ -2402,7 +2347,7 @@
 
     /**
      * Checks if a given folder is an unpacked module.
-     * @param root the fodler to be checked
+     * @param root the folder to be checked
      * @return true if the root is an unpacked module
      * @since 1.9.8
      */
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
index b95e7dc..15bed61 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirror.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
index c7dae25..9e80241 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskMirrorImpl.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,6 +35,7 @@
  */
 public final class JUnitTaskMirrorImpl implements JUnitTaskMirror {
 
+    @SuppressWarnings("unused")
     private final JUnitTask task;
 
     /**
@@ -46,6 +47,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void addVmExit(JUnitTest test, JUnitTaskMirror.JUnitResultFormatterMirror aFormatter,
             OutputStream out, String message, String testCase) {
         JUnitResultFormatter formatter = (JUnitResultFormatter) aFormatter;
@@ -61,6 +63,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public JUnitTaskMirror.JUnitTestRunnerMirror newJUnitTestRunner(JUnitTest test,
             String[] methods,
             boolean haltOnError, boolean filterTrace, boolean haltOnFailure,
@@ -70,6 +73,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public JUnitTaskMirror.SummaryJUnitResultFormatterMirror newSummaryJUnitResultFormatter() {
         return new SummaryJUnitResultFormatter();
     }
@@ -86,14 +90,17 @@
             testCase = aTestCase;
         }
 
+        @Override
         public int countTestCases() {
             return 1;
         }
 
+        @Override
         public void run(TestResult r) {
             throw new AssertionFailedError(message);
         }
 
+        @Override
         public String getName() {
             return testCase;
         }
@@ -102,6 +109,7 @@
             return test.getName();
         }
 
+        @Override
         public String toString() {
             return test.getName() + ":" + testCase;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
index eb969d5..1646b7d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 
 package org.apache.tools.ant.taskdefs.optional.junit;
 
-import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Properties;
 import java.util.Vector;
@@ -130,7 +129,7 @@
         this.haltOnFail = haltOnFailure;
         this.filtertrace = filtertrace;
         this.methodsSpecified = methods != null;
-        this.methods = methodsSpecified ? (String[]) methods.clone() : null;
+        this.methods = methodsSpecified ? methods.clone() : null;
         this.antThreadID = thread;
     }
 
@@ -222,19 +221,8 @@
      * @since 1.8.2
      */
     String getMethodsString() {
-        if ((methodsList == null) && methodsSpecified) {
-            if (methods.length == 0) {
-                methodsList = "";
-            } else if (methods.length == 1) {
-                methodsList = methods[0];
-            } else {
-                StringBuffer buf = new StringBuffer(methods.length * 16);
-                buf.append(methods[0]);
-                for (int i = 1; i < methods.length; i++) {
-                    buf.append(',').append(methods[i]);
-                }
-                methodsList = buf.toString();
-            }
+        if (methodsList == null && methodsSpecified) {
+            methodsList = String.join(",", methods);
         }
         return methodsList;
     }
@@ -247,7 +235,7 @@
      * @since 1.8.2
      */
     void resolveMethods() {
-        if ((methods == null) && methodsSpecified) {
+        if (methods == null && methodsSpecified) {
             try {
                 methods = parseTestMethodNamesList(methodsList);
             } catch (IllegalArgumentException ex) {
@@ -482,12 +470,9 @@
      * @param p the properties.
      *          This is a copy of the projects ant properties.
      */
-    public void setProperties(Hashtable p) {
+    public void setProperties(Hashtable<?, ?> p) {
         props = new Properties();
-        for (Enumeration e = p.keys(); e.hasMoreElements();) {
-            Object key = e.nextElement();
-            props.put(key, p.get(key));
-        }
+        props.putAll(p);
     }
 
     /**
@@ -516,7 +501,7 @@
     /**
      * Convenient method to add formatters to a vector
      */
-    void addFormattersTo(Vector v) {
+    void addFormattersTo(Vector<? super FormatterElement> v) {
         final int count = formatters.size();
         for (int i = 0; i < count; i++) {
             v.addElement(formatters.elementAt(i));
@@ -527,12 +512,13 @@
      * @since Ant 1.5
      * @return a clone of this test.
      */
+    @SuppressWarnings("unchecked")
     @Override
     public Object clone() {
         try {
             JUnitTest t = (JUnitTest) super.clone();
             t.props = props == null ? null : (Properties) props.clone();
-            t.formatters = (Vector) formatters.clone();
+            t.formatters = (Vector<FormatterElement>) formatters.clone();
             return t;
         } catch (CloneNotSupportedException e) {
             // plain impossible
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
index 7a0a2f6..8c35e9d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,18 +22,20 @@
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Enumeration;
-import java.util.Hashtable;
 import java.util.Properties;
 import java.util.StringTokenizer;
 import java.util.Vector;
@@ -47,6 +49,7 @@
 import junit.framework.TestSuite;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.Permissions;
 import org.apache.tools.ant.util.FileUtils;
@@ -72,22 +75,47 @@
  */
 
 public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestRunnerMirror {
+    private static final String JUNIT_4_TEST_ADAPTER = "junit.framework.JUnit4TestAdapter";
 
-    /**
-     * Holds the registered formatters.
-     */
-    private final Vector<JUnitTaskMirror.JUnitResultFormatterMirror> formatters = new Vector();
-
-    /**
-     * Collects TestResults.
-     */
-    private IgnoredTestResult res;
+    private static final String[] DEFAULT_TRACE_FILTERS = new String[] {"junit.framework.TestCase",
+            "junit.framework.TestResult",
+            "junit.framework.TestSuite",
+            "junit.framework.Assert.", // don't filter AssertionFailure
+            "junit.swingui.TestRunner",
+            "junit.awtui.TestRunner",
+            "junit.textui.TestRunner",
+            "java.lang.reflect.Method.invoke(",
+            "sun.reflect.",
+            MagicNames.ANT_CORE_PACKAGE + ".",
+            // JUnit 4 support:
+            "org.junit.",
+            "junit.framework.JUnit4TestAdapter",
+            " more"};
 
     /**
      * Do we filter junit.*.* stack frames out of failure and error exceptions.
      */
     private static boolean filtertrace = true;
 
+    /** Running more than one test suite? */
+    private static boolean multipleTests = false;
+
+    /**
+     * The file used to indicate that the build crashed.
+     * File will be empty in case the build did not crash.
+     */
+    private static String crashFile = null;
+
+    /**
+     * Holds the registered formatters.
+     */
+    private final Vector<JUnitTaskMirror.JUnitResultFormatterMirror> formatters = new Vector<>();
+
+    /**
+     * Collects TestResults.
+     */
+    private IgnoredTestResult res;
+
     /**
      * Do we send output to System.out/.err in addition to the formatters?
      */
@@ -100,24 +128,6 @@
      */
     private Permissions perm = null;
 
-    private static final String JUNIT_4_TEST_ADAPTER = "junit.framework.JUnit4TestAdapter";
-
-    private static final String[] DEFAULT_TRACE_FILTERS = new String[] {"junit.framework.TestCase",
-            "junit.framework.TestResult",
-            "junit.framework.TestSuite",
-            "junit.framework.Assert.", // don't filter AssertionFailure
-            "junit.swingui.TestRunner",
-            "junit.awtui.TestRunner",
-            "junit.textui.TestRunner",
-            "java.lang.reflect.Method.invoke(",
-            "sun.reflect.",
-            "org.apache.tools.ant.",
-            // JUnit 4 support:
-            "org.junit.",
-            "junit.framework.JUnit4TestAdapter",
-            " more"};
-
-
     /**
      * Do we stop on errors.
      */
@@ -147,9 +157,6 @@
     /** is this runner running in forked mode? */
     private boolean forked = false;
 
-    /** Running more than one test suite? */
-    private static boolean multipleTests = false;
-
     /** ClassLoader passed in in non-forked mode. */
     private final ClassLoader loader;
 
@@ -159,12 +166,6 @@
     /** Turned on if we are using JUnit 4 for this test suite. see #38811 */
     private boolean junit4;
 
-    /**
-     * The file used to indicate that the build crashed.
-     * File will be empty in case the build did not crash.
-     */
-    private static String crashFile = null;
-
     /** Names of test methods to execute */
     private String[] methods = null;
 
@@ -306,7 +307,7 @@
         this.haltOnFailure = haltOnFailure;
         this.showOutput = showOutput;
         this.logTestListenerEvents = logTestListenerEvents;
-        this.methods = methods != null ? (String[]) methods.clone() : null;
+        this.methods = methods != null ? methods.clone() : null;
         this.loader = loader;
     }
 
@@ -361,6 +362,7 @@
     /**
      * Run the test.
      */
+    @Override
     public void run() {
         res = new IgnoredTestResult();
         res.addListener(wrapListener(this));
@@ -380,7 +382,7 @@
         try {
 
             try {
-                Class testClass = null;
+                Class<?> testClass;
                 if (loader == null) {
                     testClass = Class.forName(junitTest.getName(), false,
                                               getClass().getClassLoader());
@@ -395,24 +397,24 @@
                 // JUnit 4
                 Method suiteMethod = null;
                 if (!testMethodsSpecified) {
-                try {
-                    // check if there is a suite method
-                    suiteMethod = testClass.getMethod("suite", new Class[0]);
-                } catch (final NoSuchMethodException e) {
-                    // no appropriate suite method found. We don't report any
-                    // error here since it might be perfectly normal.
-                }
+                    try {
+                        // check if there is a suite method
+                        suiteMethod = testClass.getMethod("suite");
+                    } catch (final NoSuchMethodException e) {
+                        // no appropriate suite method found. We don't report any
+                        // error here since it might be perfectly normal.
+                    }
                 }
 
                 if (suiteMethod != null) {
                     // if there is a suite method available, then try
                     // to extract the suite from it. If there is an error
                     // here it will be caught below and reported.
-                    suite = (Test) suiteMethod.invoke(null, new Object[0]);
+                    suite = (Test) suiteMethod.invoke(null);
 
                 } else {
-                    Class junit4TestAdapterClass = null;
-                    Class junit4TestAdapterCacheClass = null;
+                    Class<?> junit4TestAdapterClass = null;
+                    Class<?> junit4TestAdapterCacheClass = null;
                     boolean useSingleMethodAdapter = false;
 
                     if (junit.framework.TestCase.class.isAssignableFrom(testClass)) {
@@ -438,50 +440,49 @@
                     // In that case first C.fN will fail with CNFE and we
                     // will avoid UnsupportedClassVersionError.
 
-                    try {
-                        Class.forName("java.lang.annotation.Annotation");
-                        junit4TestAdapterCacheClass = Class.forName("org.apache.tools.ant.taskdefs.optional.junit.CustomJUnit4TestAdapterCache");
-                        if (loader == null) {
-                            junit4TestAdapterClass =
-                                Class.forName(JUNIT_4_TEST_ADAPTER);
-                            if (testMethodsSpecified) {
-                                /*
-                                 * We cannot try to load the JUnit4TestAdapter
-                                 * before trying to load JUnit4TestMethodAdapter
-                                 * because it might fail with
-                                 * NoClassDefFoundException, instead of plain
-                                 * ClassNotFoundException.
-                                 */
-                                junit4TestAdapterClass = Class.forName(
-                                    "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter");
-                                useSingleMethodAdapter = true;
+                        try {
+                            Class.forName("java.lang.annotation.Annotation");
+                            junit4TestAdapterCacheClass = Class.forName(
+                                "org.apache.tools.ant.taskdefs.optional.junit.CustomJUnit4TestAdapterCache");
+                            if (loader == null) {
+                                junit4TestAdapterClass = Class.forName(JUNIT_4_TEST_ADAPTER);
+                                if (testMethodsSpecified) {
+                                    /*
+                                     * We cannot try to load the JUnit4TestAdapter
+                                     * before trying to load JUnit4TestMethodAdapter
+                                     * because it might fail with
+                                     * NoClassDefFoundException, instead of plain
+                                     * ClassNotFoundException.
+                                     */
+                                    junit4TestAdapterClass = Class.forName(
+                                        "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter");
+                                    useSingleMethodAdapter = true;
+                                }
+                            } else {
+                                junit4TestAdapterClass =
+                                    Class.forName(JUNIT_4_TEST_ADAPTER,
+                                                  true, loader);
+                                if (testMethodsSpecified) {
+                                    junit4TestAdapterClass = Class.forName(
+                                            "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter",
+                                            true, loader);
+                                    useSingleMethodAdapter = true;
+                                }
                             }
-                        } else {
-                            junit4TestAdapterClass = Class.forName(JUNIT_4_TEST_ADAPTER,
-                                              true, loader);
-                            if (testMethodsSpecified) {
-                                junit4TestAdapterClass = Class.forName(
-                                        "org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter",
-                                        true, loader);
-                                useSingleMethodAdapter = true;
-                            }
+                        } catch (final ClassNotFoundException e) {
+                            // OK, fall back to JUnit 3.
                         }
-                    } catch (final ClassNotFoundException e) {
-                        // OK, fall back to JUnit 3.
-                    }
                     }
                     junit4 = junit4TestAdapterClass != null;
 
-                    if (junitTest.isSkipNonTests()) {
-                       if (!containsTests(testClass, junit4)) {
-                           return;
-                       }
+                    if (junitTest.isSkipNonTests()
+                        && !containsTests(testClass, junit4)) {
+                        return;
                     }
 
-
                     if (junit4) {
                         // Let's use it!
-                        Class[] formalParams;
+                        Class<?>[] formalParams;
                         Object[] actualParams;
                         if (useSingleMethodAdapter) {
                             formalParams = new Class[] {Class.class, String[].class};
@@ -492,8 +493,8 @@
                             actualParams = new Object[] {testClass, junit4TestAdapterCacheClass
                                     .getMethod("getInstance").invoke(null)};
                         }
-                        suite = (Test) junit4TestAdapterClass.getConstructor(formalParams)
-                                .newInstance(actualParams);
+                        suite = junit4TestAdapterClass.asSubclass(Test.class)
+                                .getConstructor(formalParams).newInstance(actualParams);
                     } else {
                         // Use JUnit 3.
 
@@ -512,9 +513,7 @@
                             suite = testSuite;
                         }
                     }
-
                 }
-
             } catch (final Throwable e) {
                 retCode = ERRORS;
                 exception = e;
@@ -587,12 +586,13 @@
     }
 
     private static boolean containsTests(final Class<?> testClass, final boolean isJUnit4) {
-        Class testAnnotation = null;
-        Class suiteAnnotation = null;
-        Class runWithAnnotation = null;
+        Class<? extends Annotation> testAnnotation = null;
+        Class<? extends Annotation> suiteAnnotation = null;
+        Class<? extends Annotation> runWithAnnotation = null;
 
         try {
-            testAnnotation = Class.forName("org.junit.Test");
+            testAnnotation =
+                Class.forName("org.junit.Test").asSubclass(Annotation.class);
         } catch (final ClassNotFoundException e) {
             if (isJUnit4) {
                 // odd - we think we're JUnit4 but don't support the test annotation. We therefore can't have any tests!
@@ -602,17 +602,18 @@
         }
 
         try {
-            suiteAnnotation = Class.forName("org.junit.Suite.SuiteClasses");
+            suiteAnnotation = Class.forName("org.junit.Suite.SuiteClasses")
+                .asSubclass(Annotation.class);
         } catch (final ClassNotFoundException ex) {
             // ignore - we don't have this annotation so make sure we don't check for it
         }
         try {
-            runWithAnnotation = Class.forName("org.junit.runner.RunWith");
+            runWithAnnotation = Class.forName("org.junit.runner.RunWith")
+                .asSubclass(Annotation.class);
         } catch (final ClassNotFoundException ex) {
             // also ignore as this annotation doesn't exist so tests can't use it
         }
 
-
         if (!isJUnit4 && !TestCase.class.isAssignableFrom(testClass)) {
             //a test we think is JUnit3 but does not extend TestCase. Can't really be a test.
             return false;
@@ -625,16 +626,17 @@
             }
         }
 
-        if (Modifier.isAbstract(testClass.getModifiers()) || Modifier.isInterface(testClass.getModifiers())) {
+        if (Modifier.isAbstract(testClass.getModifiers())
+                || Modifier.isInterface(testClass.getModifiers())) {
             // can't instantiate class and no inner classes are tests either
             return false;
         }
 
         if (isJUnit4) {
-             if (suiteAnnotation != null && testClass.getAnnotation(suiteAnnotation) != null) {
+            if (suiteAnnotation != null && testClass.getAnnotation(suiteAnnotation) != null) {
                 // class is marked as a suite. Let JUnit try and work its magic on it.
                 return true;
-             }
+            }
             if (runWithAnnotation != null && testClass.getAnnotation(runWithAnnotation) != null) {
                 /* Class is marked with @RunWith. If this class is badly written (no test methods,
                  * multiple constructors, private constructor etc) then the class is automatically
@@ -657,16 +659,19 @@
             } else {
                 // check if JUnit3 class have public or protected no-args methods starting with
                 // names starting with test
-                if (m.getName().startsWith("test") && m.getParameterTypes().length == 0
-                        && (Modifier.isProtected(m.getModifiers()) || Modifier.isPublic(m.getModifiers()))) {
+                if (m.getName().startsWith("test")
+                    && m.getParameterTypes().length == 0
+                    && (Modifier.isProtected(m.getModifiers())
+                        || Modifier.isPublic(m.getModifiers()))) {
                     return true;
                 }
             }
             // check if JUnit3 or JUnit4 test have a public or protected, static,
             // no-args 'suite' method
-            if (m.getName().equals("suite") && m.getParameterTypes().length == 0
-                    && (Modifier.isProtected(m.getModifiers()) || Modifier.isPublic(m.getModifiers()))
-                    && Modifier.isStatic(m.getModifiers())) {
+            if ("suite".equals(m.getName()) && m.getParameterTypes().length == 0
+                && (Modifier.isProtected(m.getModifiers())
+                    || Modifier.isPublic(m.getModifiers()))
+                && Modifier.isStatic(m.getModifiers())) {
                 return true;
             }
         }
@@ -680,6 +685,7 @@
      *
      * @return 2 if errors occurred, 1 if tests failed else 0.
      */
+    @Override
     public int getRetCode() {
         return retCode;
     }
@@ -690,6 +696,7 @@
      * <p>A new Test is started.
      * @param t the test.
      */
+    @Override
     public void startTest(final Test t) {
         final String testName = JUnitVersionHelper.getTestCaseName(t);
         logTestListenerEvent("startTest(" + testName + ")");
@@ -701,22 +708,21 @@
      * <p>A Test is finished.
      * @param test the test.
      */
+    @Override
     public void endTest(final Test test) {
         final String testName = JUnitVersionHelper.getTestCaseName(test);
         logTestListenerEvent("endTest(" + testName + ")");
     }
 
-    private void logTestListenerEvent(String msg) {
+    private void logTestListenerEvent(String message) {
         if (logTestListenerEvents) {
             @SuppressWarnings("resource")
             final PrintStream out = savedOut != null ? savedOut : System.out;
             out.flush();
-            if (msg == null) {
-                msg = "null";
-            }
-            final StringTokenizer msgLines = new StringTokenizer(msg, "\r\n", false);
-            while (msgLines.hasMoreTokens()) {
-                out.println(JUnitTask.TESTLISTENER_PREFIX + msgLines.nextToken());
+            final StringTokenizer messageLines =
+                new StringTokenizer(String.valueOf(message), "\r\n", false);
+            while (messageLines.hasMoreTokens()) {
+                out.println(JUnitTask.TESTLISTENER_PREFIX + messageLines.nextToken());
             }
             out.flush();
         }
@@ -744,6 +750,7 @@
      * @param test the test.
      * @param t    the assertion thrown by the test.
      */
+    @Override
     public void addFailure(final Test test, final AssertionFailedError t) {
         addFailure(test, (Throwable) t);
     }
@@ -755,6 +762,7 @@
      * @param test the test.
      * @param t    the error thrown by the test.
      */
+    @Override
     public void addError(final Test test, final Throwable t) {
         final String testName = JUnitVersionHelper.getTestCaseName(test);
         logTestListenerEvent("addError(" + testName + ", " + t.getMessage() + ")");
@@ -768,6 +776,7 @@
      * @since Ant 1.6
      * @param permissions the permissions to use.
      */
+    @Override
     public void setPermissions(final Permissions permissions) {
         perm = permissions;
     }
@@ -776,6 +785,7 @@
      * Handle a string destined for standard output.
      * @param output the string to output
      */
+    @Override
     public void handleOutput(final String output) {
         if (!logTestListenerEvents && output.startsWith(JUnitTask.TESTLISTENER_PREFIX)) {
             // ignore
@@ -795,12 +805,14 @@
      *
      * @since Ant 1.6
      */
+    @Override
     public int handleInput(final byte[] buffer, final int offset, final int length)
         throws IOException {
         return -1;
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void handleErrorOutput(final String output) {
         if (systemError != null) {
             systemError.print(output);
@@ -808,6 +820,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void handleFlush(final String output) {
         if (systemOut != null) {
             systemOut.print(output);
@@ -815,6 +828,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void handleErrorFlush(final String output) {
         if (systemError != null) {
             systemError.print(output);
@@ -850,6 +864,7 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void addFormatter(final JUnitTaskMirror.JUnitResultFormatterMirror f) {
         formatters.addElement(f);
     }
@@ -942,8 +957,8 @@
                     System.exit(ERRORS);
                 }
             } else if (arg.startsWith(Constants.PROPSFILE)) {
-                final FileInputStream in = new FileInputStream(arg
-                        .substring(Constants.PROPSFILE.length()));
+                final InputStream in = Files.newInputStream(Paths.get(arg
+                        .substring(Constants.PROPSFILE.length())));
                 props.load(in);
                 in.close();
             } else if (arg.startsWith(Constants.SHOWOUTPUT)) {
@@ -966,18 +981,11 @@
         }
 
         // Add/overlay system properties on the properties from the Ant project
-        final Hashtable p = System.getProperties();
-        for (final Enumeration e = p.keys(); e.hasMoreElements();) {
-            final Object key = e.nextElement();
-            props.put(key, p.get(key));
-        }
+        props.putAll(System.getProperties());
 
         int returnCode = SUCCESS;
         if (multipleTests) {
-            try {
-                final BufferedReader reader = new BufferedReader(new FileReader(args[0]));
-                String testCaseName;
-                String[] testMethodNames;
+            try (final BufferedReader reader = new BufferedReader(new FileReader(args[0]))) {
                 int code = 0;
                 boolean errorOccurred = false;
                 boolean failureOccurred = false;
@@ -986,6 +994,8 @@
                     final StringTokenizer st = new StringTokenizer(line, ",");
                     final String testListSpec = st.nextToken();
                     final int colonIndex = testListSpec.indexOf(':');
+                    String testCaseName;
+                    String[] testMethodNames;
                     if (colonIndex == -1) {
                         testCaseName = testListSpec;
                         testMethodNames = null;
@@ -1037,36 +1047,45 @@
         System.exit(returnCode);
     }
 
-    private static Vector<FormatterElement> fromCmdLine = new Vector<FormatterElement>();
+    private static Vector<FormatterElement> fromCmdLine = new Vector<>();
 
     private static void transferFormatters(final JUnitTestRunner runner,
                                            final JUnitTest test) {
         runner.addFormatter(new JUnitResultFormatter() {
 
+            @Override
             public void startTestSuite(final JUnitTest suite) throws BuildException {
             }
 
+            @Override
             public void endTestSuite(final JUnitTest suite) throws BuildException {
             }
 
+            @Override
             public void setOutput(final OutputStream out) {
             }
 
+            @Override
             public void setSystemOutput(final String out) {
             }
 
+            @Override
             public void setSystemError(final String err) {
             }
 
+            @Override
             public void addError(final Test arg0, final Throwable arg1) {
             }
 
+            @Override
             public void addFailure(final Test arg0, final AssertionFailedError arg1) {
             }
 
+            @Override
             public void endTest(final Test arg0) {
             }
 
+            @Override
             public void startTest(final Test arg0) {
                 registerTestCase(JUnitVersionHelper.getTestCaseName(arg0));
             }
@@ -1185,28 +1204,18 @@
     private static void registerNonCrash()
             throws IOException {
         if (crashFile != null) {
-            FileWriter out = null;
-            try {
-                out = new FileWriter(crashFile);
+            try (FileWriter out = new FileWriter(crashFile)) {
                 out.write(Constants.TERMINATED_SUCCESSFULLY + "\n");
                 out.flush();
-            } finally {
-                FileUtils.close(out);
             }
         }
     }
 
     private static void registerTestCase(final String testCase) {
         if (crashFile != null) {
-            try {
-                FileWriter out = null;
-                try {
-                    out = new FileWriter(crashFile);
-                    out.write(testCase + "\n");
-                    out.flush();
-                } finally {
-                    FileUtils.close(out);
-                }
+            try (FileWriter out = new FileWriter(crashFile)) {
+                out.write(testCase + "\n");
+                out.flush();
             } catch (final IOException e) {
                 // ignored.
             }
@@ -1233,9 +1242,9 @@
                     // JUnit 4-specific test GUIs will show just "failures".
                     // But Ant's output shows "failures" vs. "errors".
                     // We would prefer to show "failure" for things that logically are.
-                    final String msg = t.getMessage();
-                    final AssertionFailedError failure = msg != null
-                        ? new AssertionFailedError(msg) : new AssertionFailedError();
+                    final String message = t.getMessage();
+                    final AssertionFailedError failure = message != null
+                        ? new AssertionFailedError(message) : new AssertionFailedError();
                     failure.initCause(t.getCause());
                     failure.setStackTrace(t.getStackTrace());
                     testListener.addFailure(test, failure);
@@ -1247,6 +1256,7 @@
             public void addFailure(final Test test, final AssertionFailedError t) {
                 testListener.addFailure(test, t);
             }
+            @SuppressWarnings("unused")
             public void addFailure(final Test test, final Throwable t) { // pre-3.4
                 if (t instanceof AssertionFailedError) {
                     testListener.addFailure(test, (AssertionFailedError) t);
@@ -1273,14 +1283,19 @@
     private int[] findJUnit4FailureErrorCount(final TestResult result) {
         int failures = 0;
         int errors = 0;
-        Enumeration e = result.failures();
-        while (e.hasMoreElements()) {
-            e.nextElement();
-            failures++;
+        {
+            @SuppressWarnings("unchecked")
+            Enumeration<TestFailure> e = result.failures();
+            while (e.hasMoreElements()) {
+                e.nextElement();
+                failures++;
+            }
         }
-        e = result.errors();
+        @SuppressWarnings("unchecked")
+        Enumeration<TestFailure> e = result.errors();
         while (e.hasMoreElements()) {
-            final Throwable t = ((TestFailure) e.nextElement()).thrownException();
+            final Throwable t =
+                e.nextElement().thrownException();
             if (t instanceof AssertionFailedError
                 || t instanceof AssertionError) {
                 failures++;
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
index f0d7433..6a7d9ad 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,11 +46,11 @@
 
     static {
         try {
-            testCaseName = TestCase.class.getMethod("getName", new Class[0]);
+            testCaseName = TestCase.class.getMethod("getName");
         } catch (NoSuchMethodException e) {
             // pre JUnit 3.7
             try {
-                testCaseName = TestCase.class.getMethod("name", new Class[0]);
+                testCaseName = TestCase.class.getMethod("name");
             } catch (NoSuchMethodException ignored) {
                 // ignore
             }
@@ -82,9 +82,8 @@
             if (name.endsWith(")")) {
                 int paren = name.lastIndexOf('(');
                 return name.substring(0, paren);
-            } else {
-                return name;
             }
+            return name;
         }
         if (t instanceof TestCase && testCaseName != null) {
             try {
@@ -94,17 +93,16 @@
             }
         } else {
             try {
-                Method getNameMethod = null;
+                Method getNameMethod;
                 try {
                     getNameMethod =
-                        t.getClass().getMethod("getName", new Class [0]);
+                        t.getClass().getMethod("getName");
                 } catch (NoSuchMethodException e) {
-                    getNameMethod = t.getClass().getMethod("name",
-                                                           new Class [0]);
+                    getNameMethod = t.getClass().getMethod("name");
                 }
                 if (getNameMethod != null
                     && getNameMethod.getReturnType() == String.class) {
-                    return (String) getNameMethod.invoke(t, new Object[0]);
+                    return (String) getNameMethod.invoke(t);
                 }
             } catch (Throwable ignored) {
                 // ignore
@@ -125,8 +123,7 @@
         String className = test.getClass().getName();
         if (test instanceof JUnitTaskMirrorImpl.VmExitErrorTest) {
             className = ((JUnitTaskMirrorImpl.VmExitErrorTest) test).getClassName();
-        } else
-        if (className.equals(JUNIT_FRAMEWORK_JUNIT4_TEST_CASE_FACADE)) {
+        } else if (className.equals(JUNIT_FRAMEWORK_JUNIT4_TEST_CASE_FACADE)) {
             // JUnit 4 wraps solo tests this way. We can extract
             // the original test name with a little hack.
             String name = test.toString();
@@ -152,28 +149,22 @@
                 Class<?> testClass = Class.forName(JUnitVersionHelper.getTestCaseClassName(test));
 
                 Method testMethod = testClass.getMethod(JUnitVersionHelper.getTestCaseName(test));
-                Class ignoreAnnotation = Class.forName("org.junit.Ignore");
+                Class<? extends Annotation> ignoreAnnotation = Class
+                    .forName("org.junit.Ignore").asSubclass(Annotation.class);
                 Annotation annotation = testMethod.getAnnotation(ignoreAnnotation);
                 if (annotation != null) {
-                    Method valueMethod = annotation.getClass().getMethod("value");
+                    Method valueMethod = annotation.annotationType().getMethod("value");
                     String value = (String) valueMethod.invoke(annotation);
-                    if (value != null && value.length() > 0) {
+                    if (value != null && !value.isEmpty()) {
                         message = value;
                     }
                 }
-
             }
-        } catch (NoSuchMethodException e) {
-            // silently ignore - we'll report a skip with no message
-        } catch (ClassNotFoundException e) {
-            // silently ignore - we'll report a skip with no message
-        } catch (InvocationTargetException e) {
-            // silently ignore - we'll report a skip with no message
-        } catch (IllegalAccessException e) {
+        } catch (NoSuchMethodException | ClassNotFoundException
+                | InvocationTargetException | IllegalAccessException e) {
             // silently ignore - we'll report a skip with no message
         }
         return message;
-
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/OutErrSummaryJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/OutErrSummaryJUnitResultFormatter.java
index e0dc16c..134979f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/OutErrSummaryJUnitResultFormatter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/OutErrSummaryJUnitResultFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
index 6eedf53..b8cc8de 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,20 +24,18 @@
 import java.io.StringWriter;
 import java.text.NumberFormat;
 import java.util.Hashtable;
+import java.util.Map;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
-
 
 /**
  * Prints plain text output of the test to a specified Writer.
  *
  */
-
 public class PlainJUnitResultFormatter implements JUnitResultFormatter, IgnoredTestListener {
 
     private static final double ONE_SECOND = 1000.0;
@@ -49,7 +47,7 @@
     /**
      * Timing helper.
      */
-    private Hashtable testStarts = new Hashtable();
+    private Map<Test, Long> testStarts = new Hashtable<>();
     /**
      * Where to write the log to.
      */
@@ -65,7 +63,7 @@
     /**
      * Suppress endTest if testcase failed.
      */
-    private Hashtable failed = new Hashtable();
+    private Map<Test, Boolean> failed = new Hashtable<>();
 
     private String systemOutput = null;
     private String systemError = null;
@@ -77,16 +75,19 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setOutput(OutputStream out) {
         this.out = out;
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setSystemOutput(String out) {
         systemOutput = out;
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setSystemError(String err) {
         systemError = err;
     }
@@ -96,15 +97,13 @@
      * @param suite the test suite
      * @throws BuildException if unable to write the output
      */
+    @Override
     public void startTestSuite(JUnitTest suite) throws BuildException {
         if (out == null) {
             return; // Quick return - no output do nothing.
         }
-        StringBuffer sb = new StringBuffer("Testsuite: ");
-        sb.append(suite.getName());
-        sb.append(StringUtils.LINE_SEP);
         try {
-            out.write(sb.toString().getBytes());
+            out.write(String.format("Testsuite: %s%n",suite.getName()).getBytes());
             out.flush();
         } catch (IOException ex) {
             throw new BuildException("Unable to write output", ex);
@@ -116,41 +115,28 @@
      * @param suite the test suite
      * @throws BuildException if unable to write the output
      */
+    @Override
     public void endTestSuite(JUnitTest suite) throws BuildException {
         boolean success = false;
         try {
-            StringBuffer sb = new StringBuffer("Tests run: ");
-            sb.append(suite.runCount());
-            sb.append(", Failures: ");
-            sb.append(suite.failureCount());
-            sb.append(", Errors: ");
-            sb.append(suite.errorCount());
-            sb.append(", Skipped: ");
-            sb.append(suite.skipCount());
-            sb.append(", Time elapsed: ");
-            sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
-            sb.append(" sec");
-            sb.append(StringUtils.LINE_SEP);
-            write(sb.toString());
+            write(String.format("Tests run: %d, Failures: %d, Errors: %d, Skipped: %d, Time elapsed: %s sec%n",
+                    suite.runCount(), suite.failureCount(), suite.errorCount(), suite.skipCount(),
+                    nf.format(suite.getRunTime() / ONE_SECOND)));
 
             // write the err and output streams to the log
-            if (systemOutput != null && systemOutput.length() > 0) {
-                write("------------- Standard Output ---------------");
-                write(StringUtils.LINE_SEP);
+            if (systemOutput != null && !systemOutput.isEmpty()) {
+                write(String.format("------------- Standard Output ---------------%n"));
                 write(systemOutput);
-                write("------------- ---------------- ---------------");
-                write(StringUtils.LINE_SEP);
+                write(String.format("------------- ---------------- ---------------%n"));
             }
 
-            if (systemError != null && systemError.length() > 0) {
-                write("------------- Standard Error -----------------");
-                write(StringUtils.LINE_SEP);
+            if (systemError != null && !systemError.isEmpty()) {
+                write(String.format("------------- Standard Error -----------------%n"));
                 write(systemError);
-                write("------------- ---------------- ---------------");
-                write(StringUtils.LINE_SEP);
+                write(String.format("------------- ---------------- ---------------%n"));
             }
 
-            write(StringUtils.LINE_SEP);
+            write(System.lineSeparator());
             if (out != null) {
                 try {
                     wri.flush();
@@ -185,8 +171,9 @@
      * <p>A new Test is started.
      * @param t the test.
      */
+    @Override
     public void startTest(Test t) {
-        testStarts.put(t, new Long(System.currentTimeMillis()));
+        testStarts.put(t, System.currentTimeMillis());
         failed.put(t, Boolean.FALSE);
     }
 
@@ -196,6 +183,7 @@
      * <p>A Test is finished.
      * @param test the test.
      */
+    @Override
     public void endTest(Test test) {
         if (Boolean.TRUE.equals(failed.get(test))) {
             return;
@@ -204,12 +192,12 @@
             try {
                 wri.write("Testcase: "
                           + JUnitVersionHelper.getTestCaseName(test));
-                Long l = (Long) testStarts.get(test);
+                Long l = testStarts.get(test);
                 double seconds = 0;
                 // can be null if an error occurred in setUp
                 if (l != null) {
                     seconds =
-                        (System.currentTimeMillis() - l.longValue()) / ONE_SECOND;
+                        (System.currentTimeMillis() - l) / ONE_SECOND;
                 }
 
                 wri.write(" took " + nf.format(seconds) + " sec");
@@ -238,6 +226,7 @@
      * @param test the test.
      * @param t  the assertion that failed.
      */
+    @Override
     public void addFailure(Test test, AssertionFailedError t) {
         addFailure(test, (Throwable) t);
     }
@@ -249,6 +238,7 @@
      * @param test the test.
      * @param t    the exception.
      */
+    @Override
     public void addError(Test test, Throwable t) {
         formatError("\tCaused an ERROR", test, t);
     }
@@ -274,6 +264,7 @@
         }
     }
 
+    @Override
     public void testIgnored(Test test) {
         formatSkip(test, JUnitVersionHelper.getIgnoreMessage(test));
     }
@@ -297,6 +288,7 @@
 
     }
 
+    @Override
     public void testAssumptionFailure(Test test, Throwable throwable) {
         formatSkip(test, throwable.getMessage());
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
index 4eb30fb..cca3e67 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -52,12 +52,6 @@
     private String systemError = null;
 
     /**
-     * Empty
-     */
-    public SummaryJUnitResultFormatter() {
-    }
-
-    /**
      *  Insures that a line of log output is written and flushed as a single
      *  operation, to prevent lines from being spliced into other lines.
      *  (Hopefully this solves the issue of run on lines -
@@ -81,9 +75,9 @@
      * The testsuite started.
      * @param suite the testsuite.
      */
+    @Override
     public void startTestSuite(JUnitTest suite) {
-        String newLine = System.getProperty("line.separator");
-        StringBuffer sb = new StringBuffer("Running ");
+        StringBuilder sb = new StringBuilder("Running ");
         int antThreadID = suite.getThread();
 
         sb.append(suite.getName());
@@ -92,19 +86,21 @@
             sb.append(" in thread ");
             sb.append(antThreadID);
         }
-        sb.append(newLine);
+        sb.append(System.lineSeparator());
         writeOutputLine(sb.toString().getBytes());
     }
     /**
      * Empty
      * @param t not used.
      */
+    @Override
     public void startTest(Test t) {
     }
     /**
      * Empty
      * @param test not used.
      */
+    @Override
     public void endTest(Test test) {
     }
     /**
@@ -121,6 +117,7 @@
      * @param test not used.
      * @param t not used.
      */
+    @Override
     public void addFailure(Test test, AssertionFailedError t) {
         addFailure(test, (Throwable) t);
     }
@@ -129,20 +126,24 @@
      * @param test not used.
      * @param t not used.
      */
+    @Override
     public void addError(Test test, Throwable t) {
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setOutput(OutputStream out) {
         this.out = out;
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setSystemOutput(String out) {
         systemOutput = out;
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setSystemError(String err) {
         systemError = err;
     }
@@ -152,6 +153,7 @@
      * the summary.
      * @param value if true write System.out and System.err to the summary.
      */
+    @Override
     public void setWithOutAndErr(boolean value) {
         withOutAndErr = value;
     }
@@ -161,9 +163,9 @@
      * @param suite the testsuite.
      * @throws BuildException if there is an error.
      */
+    @Override
     public void endTestSuite(JUnitTest suite) throws BuildException {
-        String newLine = System.getProperty("line.separator");
-        StringBuffer sb = new StringBuffer("Tests run: ");
+        StringBuilder sb = new StringBuilder("Tests run: ");
         sb.append(suite.runCount());
         sb.append(", Failures: ");
         sb.append(suite.failureCount());
@@ -185,17 +187,15 @@
             sb.append(", Class: ");
             sb.append(suite.getName());
         }
-        sb.append(newLine);
+        sb.append(System.lineSeparator());
 
         if (withOutAndErr) {
-            if (systemOutput != null && systemOutput.length() > 0) {
-                sb.append("Output:").append(newLine).append(systemOutput)
-                    .append(newLine);
+            if (systemOutput != null && !systemOutput.isEmpty()) {
+                sb.append(String.format("Output:%n%s%n", systemOutput));
             }
 
-            if (systemError != null && systemError.length() > 0) {
-                sb.append("Error: ").append(newLine).append(systemError)
-                    .append(newLine);
+            if (systemError != null && !systemError.isEmpty()) {
+                sb.append(String.format("Error: %n%s%n", systemError));
             }
         }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrash.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrash.java
index 7bf8816..8a84cbd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrash.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrash.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 package org.apache.tools.ant.taskdefs.optional.junit;
 
 import java.io.OutputStream;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import junit.framework.AssertionFailedError;
@@ -43,6 +42,7 @@
      * Records the suite's name to later determine the class to invoke
      * tearDown on.
      */
+    @Override
     public void startTestSuite(final JUnitTest suite) {
         suiteName = suite.getName();
         if (suiteName != null && suiteName.endsWith(JUnitTask.NAME_OF_DUMMY_TEST)) {
@@ -56,6 +56,7 @@
      * test we get when a Batch fails and the error is an actual
      * error generated by Ant.
      */
+    @Override
     public void addError(final Test fakeTest, final Throwable t) {
         if (suiteName != null && fakeTest instanceof JUnitTaskMirrorImpl.VmExitErrorTest) {
             tearDown();
@@ -66,24 +67,31 @@
     public void addFailure(Test test, Throwable t) {
     }
 
+    @Override
     public void addFailure(Test test, AssertionFailedError t) {
     }
 
+    @Override
     public void startTest(Test test) {
     }
 
+    @Override
     public void endTest(Test test) {
     }
 
+    @Override
     public void endTestSuite(JUnitTest suite) {
     }
 
+    @Override
     public void setOutput(OutputStream out) {
     }
 
+    @Override
     public void setSystemOutput(String out) {
     }
 
+    @Override
     public void setSystemError(String err) {
     }
 
@@ -91,7 +99,7 @@
         try {
             // first try to load the class and let's hope it is on our
             // classpath
-            Class testClass = null;
+            Class<?> testClass = null;
             if (Thread.currentThread().getContextClassLoader() != null) {
                 try {
                     testClass = Thread.currentThread().getContextClassLoader()
@@ -116,7 +124,7 @@
             // which test of the executed suite timed out, ignore it
             try {
                 // check if there is a suite method
-                testClass.getMethod("suite", new Class[0]);
+                testClass.getMethod("suite");
                 return;
             } catch (NoSuchMethodException e) {
                 // no suite method
@@ -127,9 +135,9 @@
             // doesn't have any tearDown method.
 
             try {
-                Method td = testClass.getMethod("tearDown", new Class[0]);
+                Method td = testClass.getMethod("tearDown");
                 if (td.getReturnType() == Void.TYPE) {
-                    td.invoke(testClass.newInstance(), new Object[0]);
+                    td.invoke(testClass.getDeclaredConstructor().newInstance());
                 }
             } catch (NoSuchMethodException nsme) {
                 // no tearDown, fine
@@ -138,9 +146,6 @@
         } catch (ClassNotFoundException cnfe) {
             // class probably is not in our classpath, there is
             // nothing we can do
-        } catch (InvocationTargetException ite) {
-            System.err.println("Caught an exception while trying to invoke"
-                               + " tearDown: " + ite.getMessage());
         } catch (Throwable t) {
             System.err.println("Caught an exception while trying to invoke"
                                + " tearDown: " + t.getMessage());
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestIgnored.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestIgnored.java
index 79a8878..432faf9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestIgnored.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestIgnored.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java
index 692e4fc..6b48c81 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,31 +32,38 @@
         wrapped = listener;
     }
 
+    @Override
     public void addError(Test test, Throwable throwable) {
         wrapped.addError(test, throwable);
     }
 
+    @Override
     public void addFailure(Test test, AssertionFailedError assertionFailedError) {
         wrapped.addFailure(test, assertionFailedError);
     }
 
+    @Override
     public void endTest(Test test) {
         wrapped.endTest(test);
     }
 
+    @Override
     public void startTest(Test test) {
         wrapped.startTest(test);
     }
 
+    @Override
     public void testIgnored(Test test) {
         if (wrapped instanceof IgnoredTestListener) {
-            ((IgnoredTestListener)wrapped).testIgnored(test);
+            ((IgnoredTestListener) wrapped).testIgnored(test);
         }
     }
 
+    @Override
     public void testAssumptionFailure(Test test, Throwable throwable) {
         if (wrapped instanceof IgnoredTestListener) {
-            ((IgnoredTestListener)wrapped).testAssumptionFailure(test, throwable);
+            ((IgnoredTestListener) wrapped).testAssumptionFailure(test,
+                throwable);
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLConstants.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLConstants.java
index c29271d..1432d5c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLConstants.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLConstants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,8 +19,8 @@
 
 /**
  * <p>Interface groups XML constants.
- * Interface that groups all constants used throughout the <tt>XML</tt>
- * documents that are generated by the <tt>XMLJUnitResultFormatter</tt>.
+ * Interface that groups all constants used throughout the <code>XML</code>
+ * documents that are generated by the <code>XMLJUnitResultFormatter</code>.
  * </p>
  * As of now the DTD is:
  * <pre>
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
index 171348f..5ed9ddd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,9 +25,10 @@
 import java.io.Writer;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Map;
 import java.util.Properties;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -50,7 +51,6 @@
  *
  * @see FormatterElement
  */
-
 public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants, IgnoredTestListener {
 
     private static final double ONE_SECOND = 1000.0;
@@ -84,45 +84,44 @@
      * so we can't easily match Test objects without manually iterating over all keys and checking
      * individual fields.
      */
-    private final Hashtable<String, Element> testElements = new Hashtable<String, Element>();
+    private final Hashtable<String, Element> testElements = new Hashtable<>();
 
     /**
      * tests that failed.
      */
-    private final Hashtable failedTests = new Hashtable();
+    private final Map<Test, Test> failedTests = new Hashtable<>();
 
     /**
      * Tests that were skipped.
      */
-    private final Hashtable<String, Test> skippedTests = new Hashtable<String, Test>();
+    private final Map<String, Test> skippedTests = new Hashtable<>();
     /**
      * Tests that were ignored. See the note above about the key being a bit of a hack.
      */
-    private final Hashtable<String, Test> ignoredTests = new Hashtable<String, Test>();
+    private final Map<String, Test> ignoredTests = new Hashtable<>();
     /**
      * Timing helper.
      */
-    private final Hashtable<String, Long> testStarts = new Hashtable<String, Long>();
+    private final Map<String, Long> testStarts = new Hashtable<>();
     /**
      * Where to write the log to.
      */
     private OutputStream out;
 
-    /** No arg constructor. */
-    public XMLJUnitResultFormatter() {
-    }
-
     /** {@inheritDoc}. */
+    @Override
     public void setOutput(final OutputStream out) {
         this.out = out;
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setSystemOutput(final String out) {
         formatOutput(SYSTEM_OUT, out);
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void setSystemError(final String out) {
         formatOutput(SYSTEM_ERR, out);
     }
@@ -131,6 +130,7 @@
      * The whole testsuite started.
      * @param suite the testsuite.
      */
+    @Override
     public void startTestSuite(final JUnitTest suite) {
         doc = getDocumentBuilder().newDocument();
         rootElement = doc.createElement(TESTSUITE);
@@ -149,9 +149,7 @@
         rootElement.appendChild(propsElement);
         final Properties props = suite.getProperties();
         if (props != null) {
-            final Enumeration e = props.propertyNames();
-            while (e.hasMoreElements()) {
-                final String name = (String) e.nextElement();
+            for (String name : props.stringPropertyNames()) {
                 final Element propElement = doc.createElement(PROPERTY);
                 propElement.setAttribute(ATTR_NAME, name);
                 propElement.setAttribute(ATTR_VALUE, props.getProperty(name));
@@ -182,19 +180,20 @@
      * @param suite the testsuite.
      * @throws BuildException on error.
      */
+    @Override
     public void endTestSuite(final JUnitTest suite) throws BuildException {
-        rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
-        rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
-        rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
-        rootElement.setAttribute(ATTR_SKIPPED, "" + suite.skipCount());
+        rootElement.setAttribute(ATTR_TESTS, Long.toString(suite.runCount()));
+        rootElement.setAttribute(ATTR_FAILURES, Long.toString(suite.failureCount()));
+        rootElement.setAttribute(ATTR_ERRORS, Long.toString(suite.errorCount()));
+        rootElement.setAttribute(ATTR_SKIPPED, Long.toString(suite.skipCount()));
         rootElement.setAttribute(
-            ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
+            ATTR_TIME, Double.toString(suite.getRunTime() / ONE_SECOND));
         if (out != null) {
             Writer wri = null;
             try {
-                wri = new BufferedWriter(new OutputStreamWriter(out, "UTF8"));
+                wri = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
                 wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
-                (new DOMElementWriter()).write(rootElement, wri, 0, "  ");
+                new DOMElementWriter().write(rootElement, wri, 0, "  ");
             } catch (final IOException exc) {
                 throw new BuildException("Unable to write log file", exc);
             } finally {
@@ -218,12 +217,14 @@
      * <p>A new Test is started.
      * @param t the test.
      */
+    @Override
     public void startTest(final Test t) {
         testStarts.put(createDescription(t), System.currentTimeMillis());
     }
 
     private static String createDescription(final Test test) throws BuildException {
-        return JUnitVersionHelper.getTestCaseName(test) + "(" + JUnitVersionHelper.getTestCaseClassName(test) + ")";
+        return JUnitVersionHelper.getTestCaseName(test) + "("
+            + JUnitVersionHelper.getTestCaseClassName(test) + ")";
     }
 
     /**
@@ -232,6 +233,7 @@
      * <p>A Test is finished.
      * @param test the test.
      */
+    @Override
     public void endTest(final Test test) {
         final String testDescription = createDescription(test);
 
@@ -242,7 +244,9 @@
             startTest(test);
         }
         Element currentTest;
-        if (!failedTests.containsKey(test) && !skippedTests.containsKey(testDescription) && !ignoredTests.containsKey(testDescription)) {
+        if (!failedTests.containsKey(test)
+            && !skippedTests.containsKey(testDescription)
+            && !ignoredTests.containsKey(testDescription)) {
             currentTest = doc.createElement(TESTCASE);
             final String n = JUnitVersionHelper.getTestCaseName(test);
             currentTest.setAttribute(ATTR_NAME,
@@ -259,7 +263,7 @@
 
         final Long l = testStarts.get(createDescription(test));
         currentTest.setAttribute(ATTR_TIME,
-            "" + ((System.currentTimeMillis() - l) / ONE_SECOND));
+            Double.toString((System.currentTimeMillis() - l) / ONE_SECOND));
     }
 
     /**
@@ -280,6 +284,7 @@
      * @param test the test.
      * @param t the assertion.
      */
+    @Override
     public void addFailure(final Test test, final AssertionFailedError t) {
         addFailure(test, (Throwable) t);
     }
@@ -291,6 +296,7 @@
      * @param test the test.
      * @param t the error.
      */
+    @Override
     public void addError(final Test test, final Throwable t) {
         formatError(ERROR, test, t);
     }
@@ -302,17 +308,13 @@
         }
 
         final Element nested = doc.createElement(type);
-        Element currentTest;
-        if (test != null) {
-            currentTest = testElements.get(createDescription(test));
-        } else {
-            currentTest = rootElement;
-        }
+        Element currentTest = test == null ? rootElement
+            : testElements.get(createDescription(test));
 
         currentTest.appendChild(nested);
 
         final String message = t.getMessage();
-        if (message != null && message.length() > 0) {
+        if (message != null && !message.isEmpty()) {
             nested.setAttribute(ATTR_MESSAGE, t.getMessage());
         }
         nested.setAttribute(ATTR_TYPE, t.getClass().getName());
@@ -328,6 +330,7 @@
         nested.appendChild(doc.createCDATASection(output));
     }
 
+    @Override
     public void testIgnored(final Test test) {
         formatSkip(test, JUnitVersionHelper.getIgnoreMessage(test));
         if (test != null) {
@@ -335,7 +338,6 @@
         }
     }
 
-
     public void formatSkip(final Test test, final String message) {
         if (test != null) {
             endTest(test);
@@ -347,17 +349,14 @@
             nested.setAttribute("message", message);
         }
 
-        Element currentTest;
-        if (test != null) {
-            currentTest = testElements.get(createDescription(test));
-        } else {
-            currentTest = rootElement;
-        }
+        Element currentTest = test == null ? rootElement
+            : testElements.get(createDescription(test));
 
         currentTest.appendChild(nested);
 
     }
 
+    @Override
     public void testAssumptionFailure(final Test test, final Throwable failure) {
         formatSkip(test, failure.getMessage());
         skippedTests.put(createDescription(test), test);
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 a851233..4eac79a 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,13 @@
 
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.util.Enumeration;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.Vector;
+import java.util.stream.Stream;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -60,7 +60,7 @@
 
     // CheckStyle:VisibilityModifier OFF - bc
     /** the list of all filesets, that should contains the xml to aggregate */
-    protected Vector filesets = new Vector();
+    protected Vector<FileSet> filesets = new Vector<>();
 
     /** the name of the result file */
     protected String toFile;
@@ -68,12 +68,12 @@
     /** the directory to write the file to */
     protected File toDir;
 
-    protected Vector transformers = new Vector();
+    protected Vector<AggregateTransformer> transformers = new Vector<>();
 
-    /** The default directory: <tt>&#046;</tt>. It is resolved from the project directory */
+    /** The default directory: <code>&#046;</code>. It is resolved from the project directory */
     public static final String DEFAULT_DIR = ".";
 
-    /** the default file name: <tt>TESTS-TestSuites.xml</tt> */
+    /** the default file name: <code>TESTS-TestSuites.xml</code> */
     public static final String DEFAULT_FILENAME = "TESTS-TestSuites.xml";
 
     /** the current generated id */
@@ -102,13 +102,13 @@
      */
     public AggregateTransformer createReport() {
         AggregateTransformer transformer = new AggregateTransformer(this);
-        transformers.addElement(transformer);
+        transformers.add(transformer);
         return transformer;
     }
 
     /**
      * Set the name of the aggregated results file. It must be relative
-     * from the <tt>todir</tt> attribute. If not set it will use {@link #DEFAULT_FILENAME}
+     * from the <code>todir</code> attribute. If not set it will use {@link #DEFAULT_FILENAME}
      * @param  value   the name of the file.
      * @see #setTodir(File)
      */
@@ -132,7 +132,7 @@
      * @param    fs      the new fileset of xml results.
      */
     public void addFileSet(FileSet fs) {
-        filesets.addElement(fs);
+        filesets.add(fs);
     }
 
     /**
@@ -141,6 +141,7 @@
      * @throws  BuildException  thrown if there is a serious error while writing
      *          the document.
      */
+    @Override
     public void execute() throws BuildException {
         Element rootElement = createDocument();
         File destFile = getDestinationFile();
@@ -151,10 +152,7 @@
             throw new BuildException("Unable to write test aggregate to '" + destFile + "'", e);
         }
         // apply transformation
-        Enumeration e = transformers.elements();
-        while (e.hasMoreElements()) {
-            AggregateTransformer transformer =
-                (AggregateTransformer) e.nextElement();
+        for (AggregateTransformer transformer : transformers) {
             transformer.setXmlDocument(rootElement.getOwnerDocument());
             transformer.transform();
         }
@@ -162,7 +160,7 @@
 
     /**
      * Get the full destination file where to write the result. It is made of
-     * the <tt>todir</tt> and <tt>tofile</tt> attributes.
+     * the <code>todir</code> and <code>tofile</code> attributes.
      * @return the destination file where should be written the result file.
      */
     public File getDestinationFile() {
@@ -181,26 +179,14 @@
      * @return all files in the fileset that end with a '.xml'.
      */
     protected File[] getFiles() {
-        Vector v = new Vector();
-        final int size = filesets.size();
-        for (int i = 0; i < size; i++) {
-            FileSet fs = (FileSet) filesets.elementAt(i);
-            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+        Project p = getProject();
+        return filesets.stream().flatMap(fs -> {
+            DirectoryScanner ds = fs.getDirectoryScanner(p);
             ds.scan();
-            String[] f = ds.getIncludedFiles();
-            for (int j = 0; j < f.length; j++) {
-                String pathname = f[j];
-                if (pathname.endsWith(".xml")) {
-                    File file = new File(ds.getBasedir(), pathname);
-                    file = getProject().resolveFile(file.getPath());
-                    v.addElement(file);
-                }
-            }
-        }
-
-        File[] files = new File[v.size()];
-        v.copyInto(files);
-        return files;
+            return Stream.of(ds.getIncludedFiles())
+                .filter(pathname -> pathname.endsWith(".xml"))
+                    .map(pathname -> p.resolveFile(new File(ds.getBasedir(), pathname).getPath()));
+        }).toArray(File[]::new);
     }
 
     //----- from now, the methods are all related to DOM tree manipulation
@@ -212,18 +198,17 @@
      * @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 (PrintWriter wri = new PrintWriter(new OutputStreamWriter(
+                new BufferedOutputStream(Files.newOutputStream(file.toPath())),
+                StandardCharsets.UTF_8))) {
             wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
-            (new DOMElementWriter()).write(doc.getDocumentElement(), wri, 0, "  ");
+            new DOMElementWriter().write(doc.getDocumentElement(), wri, 0,
+                "  ");
             wri.flush();
             // writers do not throw exceptions, so check for them.
             if (wri.checkError()) {
                 throw new IOException("Error while writing DOM content");
             }
-        } finally {
-            os.close();
         }
     }
 
@@ -285,10 +270,10 @@
      * <p>Add a new testsuite node to the document.
      * The main difference is that it
      * split the previous fully qualified name into a package and a name.</p>
-     * <p>For example: <tt>org.apache.Whatever</tt> will be split into
-     * <tt>org.apache</tt> and <tt>Whatever</tt>.</p>
+     * <p>For example: <code>org.apache.Whatever</code> will be split into
+     * <code>org.apache</code> and <code>Whatever</code>.</p>
      *
-     * @param root the root element to which the <tt>testsuite</tt> node should
+     * @param root the root element to which the <code>testsuite</code> node should
      *        be appended.
      * @param testsuite the element to append to the given root. It will slightly
      *        modify the original node to change the name attribute and add
@@ -310,7 +295,7 @@
     }
 
     /**
-     * Create a new document builder. Will issue an <tt>ExceptionInitializerError</tt>
+     * Create a new document builder. Will issue an <code>ExceptionInitializerError</code>
      * if something is going wrong. It is fatal anyway.
      * @todo factorize this somewhere else. It is duplicated code.
      * @return a new document builder to create a DOM
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
new file mode 100644
index 0000000..be70e94
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
@@ -0,0 +1,308 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter {
+
+    protected TestExecutionContext context;
+
+    private SysOutErrContentStore sysOutStore;
+    private SysOutErrContentStore sysErrStore;
+
+    @Override
+    public void sysOutAvailable(final byte[] data) {
+        if (this.sysOutStore == null) {
+            this.sysOutStore = new SysOutErrContentStore(context, true);
+        }
+        try {
+            this.sysOutStore.store(data);
+        } catch (IOException e) {
+            handleException(e);
+        }
+    }
+
+    @Override
+    public void sysErrAvailable(final byte[] data) {
+        if (this.sysErrStore == null) {
+            this.sysErrStore = new SysOutErrContentStore(context, false);
+        }
+        try {
+            this.sysErrStore.store(data);
+        } catch (IOException e) {
+            handleException(e);
+        }
+    }
+
+    @Override
+    public void setContext(final TestExecutionContext context) {
+        this.context = context;
+    }
+
+    /**
+     * @return Returns true if there's any stdout data, that was generated during the
+     * tests, is available for use. Else returns false.
+     */
+    boolean hasSysOut() {
+        return this.sysOutStore != null && this.sysOutStore.hasData();
+    }
+
+    /**
+     * @return Returns true if there's any stderr data, that was generated during the
+     * tests, is available for use. Else returns false.
+     */
+    boolean hasSysErr() {
+        return this.sysErrStore != null && this.sysErrStore.hasData();
+    }
+
+    /**
+     * @return Returns a {@link Reader} for reading any stdout data that was generated
+     * during the test execution. It is expected that the {@link #hasSysOut()} be first
+     * called to see if any such data is available and only if there is, then this method
+     * be called
+     * @throws IOException If there's any I/O problem while creating the {@link Reader}
+     */
+    Reader getSysOutReader() throws IOException {
+        return this.sysOutStore.getReader();
+    }
+
+    /**
+     * @return Returns a {@link Reader} for reading any stderr data that was generated
+     * during the test execution. It is expected that the {@link #hasSysErr()} be first
+     * called to see if any such data is available and only if there is, then this method
+     * be called
+     * @throws IOException If there's any I/O problem while creating the {@link Reader}
+     */
+    Reader getSysErrReader() throws IOException {
+        return this.sysErrStore.getReader();
+    }
+
+    /**
+     * Writes out any stdout data that was generated during the
+     * test execution. If there was no such data then this method just returns.
+     *
+     * @param writer The {@link Writer} to use. Cannot be null.
+     * @throws IOException If any I/O problem occurs during writing the data
+     */
+    void writeSysOut(final Writer writer) throws IOException {
+        Objects.requireNonNull(writer, "Writer cannot be null");
+        this.writeFrom(this.sysOutStore, writer);
+    }
+
+    /**
+     * Writes out any stderr data that was generated during the
+     * test execution. If there was no such data then this method just returns.
+     *
+     * @param writer The {@link Writer} to use. Cannot be null.
+     * @throws IOException If any I/O problem occurs during writing the data
+     */
+    void writeSysErr(final Writer writer) throws IOException {
+        Objects.requireNonNull(writer, "Writer cannot be null");
+        this.writeFrom(this.sysErrStore, writer);
+    }
+
+    static Optional<TestIdentifier> traverseAndFindTestClass(final TestPlan testPlan, final TestIdentifier testIdentifier) {
+        if (isTestClass(testIdentifier).isPresent()) {
+            return Optional.of(testIdentifier);
+        }
+        final Optional<TestIdentifier> parent = testPlan.getParent(testIdentifier);
+        return parent.isPresent() ? traverseAndFindTestClass(testPlan, parent.get()) : Optional.empty();
+    }
+
+    static Optional<ClassSource> isTestClass(final TestIdentifier testIdentifier) {
+        if (testIdentifier == null) {
+            return Optional.empty();
+        }
+        final Optional<TestSource> source = testIdentifier.getSource();
+        if (!source.isPresent()) {
+            return Optional.empty();
+        }
+        final TestSource testSource = source.get();
+        if (testSource instanceof ClassSource) {
+            return Optional.of((ClassSource) testSource);
+        }
+        return Optional.empty();
+    }
+
+    private void writeFrom(final SysOutErrContentStore store, final Writer writer) throws IOException {
+        final char[] chars = new char[1024];
+        int numRead = -1;
+        try (final Reader reader = store.getReader()) {
+            while ((numRead = reader.read(chars)) != -1) {
+                writer.write(chars, 0, numRead);
+            }
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        FileUtils.close(this.sysOutStore);
+        FileUtils.close(this.sysErrStore);
+    }
+
+    protected void handleException(final Throwable t) {
+        // we currently just log it and move on.
+        this.context.getProject().ifPresent((p) -> p.log("Exception in listener "
+                + AbstractJUnitResultFormatter.this.getClass().getName(), t, Project.MSG_DEBUG));
+    }
+
+
+    /*
+    A "store" for sysout/syserr content that gets sent to the AbstractJUnitResultFormatter.
+    This store first uses a relatively decent sized in-memory buffer for storing the sysout/syserr
+    content. This in-memory buffer will be used as long as it can fit in the new content that
+    keeps coming in. When the size limit is reached, this store switches to a file based store
+    by creating a temporarily file and writing out the already in-memory held buffer content
+    and any new content that keeps arriving to this store. Once the file has been created,
+    the in-memory buffer will never be used any more and in fact is destroyed as soon as the
+    file is created.
+    Instances of this class are not thread-safe and users of this class are expected to use necessary thread
+    safety guarantees, if they want to use an instance of this class by multiple threads.
+    */
+    private static final class SysOutErrContentStore implements Closeable {
+        private static final int DEFAULT_CAPACITY_IN_BYTES = 50 * 1024; // 50 KB
+        private static final Reader EMPTY_READER = new Reader() {
+            @Override
+            public int read(final char[] cbuf, final int off, final int len) throws IOException {
+                return -1;
+            }
+
+            @Override
+            public void close() throws IOException {
+            }
+        };
+
+        private final TestExecutionContext context;
+        private final String tmpFileSuffix;
+        private ByteBuffer inMemoryStore = ByteBuffer.allocate(DEFAULT_CAPACITY_IN_BYTES);
+        private boolean usingFileStore = false;
+        private Path filePath;
+        private OutputStream fileOutputStream;
+
+        private SysOutErrContentStore(final TestExecutionContext context, final boolean isSysOut) {
+            this.context = context;
+            this.tmpFileSuffix = isSysOut ? ".sysout" : ".syserr";
+        }
+
+        private void store(final byte[] data) throws IOException {
+            if (this.usingFileStore) {
+                this.storeToFile(data, 0, data.length);
+                return;
+            }
+            // we haven't yet created a file store and the data can fit in memory,
+            // so we write it in our buffer
+            try {
+                this.inMemoryStore.put(data);
+                return;
+            } catch (BufferOverflowException boe) {
+                // the buffer capacity can't hold this incoming data, so this
+                // incoming data hasn't been transferred to the buffer. let's
+                // now fall back to a file store
+                this.usingFileStore = true;
+            }
+            // since the content couldn't be transferred into in-memory buffer,
+            // we now create a file and transfer already (previously) stored in-memory
+            // content into that file, before finally transferring this new content
+            // into the file too. We then finally discard this in-memory buffer and
+            // just keep using the file store instead
+            this.fileOutputStream = createFileStore();
+            // first the existing in-memory content
+            storeToFile(this.inMemoryStore.array(), 0, this.inMemoryStore.position());
+            storeToFile(data, 0, data.length);
+            // discard the in-memory store
+            this.inMemoryStore = null;
+        }
+
+        private void storeToFile(final byte[] data, final int offset, final int length) throws IOException {
+            if (this.fileOutputStream == null) {
+                // no backing file was created so we can't do anything
+                return;
+            }
+            this.fileOutputStream.write(data, offset, length);
+        }
+
+        private OutputStream createFileStore() throws IOException {
+            this.filePath = FileUtils.getFileUtils()
+                .createTempFile(context.getProject().orElse(null), null, this.tmpFileSuffix, null, true, true)
+                .toPath();
+            return Files.newOutputStream(this.filePath);
+        }
+
+        /*
+         * Returns a Reader for reading the sysout/syserr content. If there's no data
+         * available in this store, then this returns a Reader which when used for read operations,
+         * will immediately indicate an EOF.
+         */
+        private Reader getReader() throws IOException {
+            if (this.usingFileStore && this.filePath != null) {
+                // we use a FileReader here so that we can use the system default character
+                // encoding for reading the contents on sysout/syserr stream, since that's the
+                // encoding that System.out/System.err uses to write out the messages
+                return new BufferedReader(new FileReader(this.filePath.toFile()));
+            }
+            if (this.inMemoryStore != null) {
+                return new InputStreamReader(new ByteArrayInputStream(this.inMemoryStore.array(), 0, this.inMemoryStore.position()));
+            }
+            // no data to read, so we return an "empty" reader
+            return EMPTY_READER;
+        }
+
+        /*
+         *  Returns true if this store has any data (either in-memory or in a file). Else
+         *  returns false.
+         */
+        private boolean hasData() {
+            if (this.inMemoryStore != null && this.inMemoryStore.position() > 0) {
+                return true;
+            }
+            return this.usingFileStore && this.filePath != null;
+        }
+
+        @Override
+        public void close() throws IOException {
+            this.inMemoryStore = null;
+            FileUtils.close(this.fileOutputStream);
+            FileUtils.delete(this.filePath.toFile());
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/InVMExecution.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/InVMExecution.java
new file mode 100644
index 0000000..505305a
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/InVMExecution.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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask;
+
+import java.util.Optional;
+import java.util.Properties;
+
+/**
+ * Used during in-vm (non-forked mode) launching of tests
+ */
+public class InVMExecution implements TestExecutionContext {
+
+    private final JUnitLauncherTask task;
+    private final Properties props;
+
+    public InVMExecution(final JUnitLauncherTask task) {
+        this.task = task;
+        this.props = new Properties();
+        this.props.putAll(task.getProject().getProperties());
+    }
+
+    @Override
+    public Properties getProperties() {
+        return this.props;
+    }
+
+    @Override
+    public Optional<Project> getProject() {
+        return Optional.of(this.task.getProject());
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java
new file mode 100644
index 0000000..00b76df
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java
@@ -0,0 +1,718 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.LaunchDefinition;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.ListenerDefinition;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.NamedTest;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.SingleTestClass;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestClasses;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.apache.tools.ant.util.LeadPipeInputStream;
+import org.junit.platform.engine.Filter;
+import org.junit.platform.engine.discovery.DiscoverySelectors;
+import org.junit.platform.launcher.EngineFilter;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TagFilter;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Responsible for doing the real work involved in launching the JUnit platform
+ * and passing it the relevant tests that need to be executed by the JUnit platform.
+ * <p>
+ * This class relies on a {@link LaunchDefinition} for setting up the launch of the
+ * JUnit platform.
+ * <p>
+ * The {@code LauncherSupport} isn't concerned with whether or not
+ * it's being executed in the same JVM as the build in which the {@code junitlauncher}
+ * was triggered or if it's running as part of a forked JVM. Instead it just relies
+ * on the {@code LaunchDefinition} to do whatever decisions need to be done before and
+ * after launching the tests.
+ * <p>
+ * This class is not thread-safe and isn't expected to be used for launching from
+ * multiple different threads simultaneously.
+ * <p>This class is an internal implementation detail of the Ant project and although
+ * it's a public class, it isn't meant to be used outside of this project. This class
+ * can be changed, across releases, without any backward compatible guarantees and hence
+ * shouldn't be used or relied upon outside of this project.
+ */
+public class LauncherSupport {
+
+    private final LaunchDefinition launchDefinition;
+    private final TestExecutionContext testExecutionContext;
+
+    private boolean testsFailed;
+
+    /**
+     * Create a {@link LauncherSupport} for the passed {@link LaunchDefinition}
+     *
+     * @param definition           The launch definition which will be used for launching the tests
+     * @param testExecutionContext The {@link TestExecutionContext} to use for the tests
+     */
+    public LauncherSupport(final LaunchDefinition definition, final TestExecutionContext testExecutionContext) {
+        if (definition == null) {
+            throw new IllegalArgumentException("Launch definition cannot be null");
+        }
+        if (testExecutionContext == null) {
+            throw new IllegalArgumentException("Test execution context cannot be null");
+        }
+        this.launchDefinition = definition;
+        this.testExecutionContext = testExecutionContext;
+    }
+
+    /**
+     * Launches the tests defined in the {@link LaunchDefinition}
+     *
+     * @throws BuildException If any tests failed and the launch definition was configured to throw
+     *                        an exception, or if any other exception occurred before or after launching
+     *                        the tests
+     */
+    public void launch() throws BuildException {
+        final ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(this.launchDefinition.getClassLoader());
+            final Launcher launcher = LauncherFactory.create();
+            final List<TestRequest> requests = buildTestRequests();
+            for (final TestRequest testRequest : requests) {
+                try {
+                    final TestDefinition test = testRequest.getOwner();
+                    final LauncherDiscoveryRequest request = testRequest.getDiscoveryRequest().build();
+                    final List<TestExecutionListener> testExecutionListeners = new ArrayList<>();
+                    // a listener that we always put at the front of list of listeners
+                    // for this request.
+                    final Listener firstListener = new Listener(System.out);
+                    // we always enroll the summary generating listener, to the request, so that we
+                    // get to use some of the details of the summary for our further decision making
+                    testExecutionListeners.add(firstListener);
+                    testExecutionListeners.addAll(getListeners(testRequest, this.launchDefinition.getClassLoader()));
+                    final PrintStream originalSysOut = System.out;
+                    final PrintStream originalSysErr = System.err;
+                    try {
+                        firstListener.switchedSysOutHandle = trySwitchSysOutErr(testRequest, StreamType.SYS_OUT, originalSysErr);
+                        firstListener.switchedSysErrHandle = trySwitchSysOutErr(testRequest, StreamType.SYS_ERR, originalSysErr);
+                        launcher.execute(request, testExecutionListeners.toArray(new TestExecutionListener[0]));
+                    } finally {
+                        // switch back sysout/syserr to the original
+                        try {
+                            System.setOut(originalSysOut);
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                        try {
+                            System.setErr(originalSysErr);
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                        // close the streams that we had used to redirect System.out/System.err
+                        try {
+                            firstListener.switchedSysOutHandle.ifPresent((h) -> {
+                                try {
+                                    h.close();
+                                } catch (Exception e) {
+                                    // ignore
+                                }
+                            });
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                        try {
+                            firstListener.switchedSysErrHandle.ifPresent((h) -> {
+                                try {
+                                    h.close();
+                                } catch (Exception e) {
+                                    // ignore
+                                }
+                            });
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                    }
+                    handleTestExecutionCompletion(test, firstListener.getSummary());
+                } finally {
+                    try {
+                        testRequest.close();
+                    } catch (Exception e) {
+                        // log and move on
+                        log("Failed to cleanly close test request", e, Project.MSG_DEBUG);
+                    }
+                }
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(previousClassLoader);
+        }
+    }
+
+    /**
+     * Returns true if there were any test failures, when this {@link LauncherSupport} was used
+     * to {@link #launch()} tests. False otherwise.
+     *
+     * @return
+     */
+    boolean hasTestFailures() {
+        return this.testsFailed;
+    }
+
+    private List<TestRequest> buildTestRequests() {
+        final List<TestDefinition> tests = this.launchDefinition.getTests();
+        if (tests.isEmpty()) {
+            return Collections.emptyList();
+        }
+        final List<TestRequest> requests = new ArrayList<>();
+        for (final TestDefinition test : tests) {
+            final List<TestRequest> testRequests;
+            if (test instanceof SingleTestClass || test instanceof TestClasses) {
+                testRequests = createTestRequests(test);
+            } else {
+                throw new BuildException("Unexpected test definition type " + test.getClass().getName());
+            }
+            if (testRequests == null || testRequests.isEmpty()) {
+                continue;
+            }
+            requests.addAll(testRequests);
+        }
+        return requests;
+    }
+
+    private List<TestExecutionListener> getListeners(final TestRequest testRequest, final ClassLoader classLoader) {
+        final TestDefinition test = testRequest.getOwner();
+        final List<ListenerDefinition> applicableListenerElements = test.getListeners().isEmpty()
+                ? this.launchDefinition.getListeners() : test.getListeners();
+        final List<TestExecutionListener> listeners = new ArrayList<>();
+        final Optional<Project> project = this.testExecutionContext.getProject();
+        for (final ListenerDefinition applicableListener : applicableListenerElements) {
+            if (project.isPresent() && !applicableListener.shouldUse(project.get())) {
+                log("Excluding listener " + applicableListener.getClassName() + " since it's not applicable" +
+                        " in the context of project", null, Project.MSG_DEBUG);
+                continue;
+            }
+            final TestExecutionListener listener = requireTestExecutionListener(applicableListener, classLoader);
+            if (listener instanceof TestResultFormatter) {
+                // setup/configure the result formatter
+                setupResultFormatter(testRequest, applicableListener, (TestResultFormatter) listener);
+            }
+            listeners.add(listener);
+        }
+        return listeners;
+    }
+
+    private void setupResultFormatter(final TestRequest testRequest, final ListenerDefinition formatterDefinition,
+                                      final TestResultFormatter resultFormatter) {
+
+        testRequest.closeUponCompletion(resultFormatter);
+        // set the execution context
+        resultFormatter.setContext(this.testExecutionContext);
+        resultFormatter.setUseLegacyReportingName(formatterDefinition.isUseLegacyReportingName());
+        // set the destination output stream for writing out the formatted result
+        final java.nio.file.Path resultOutputFile = getListenerOutputFile(testRequest, formatterDefinition);
+        try {
+            final OutputStream resultOutputStream = Files.newOutputStream(resultOutputFile);
+            // enroll the output stream to be closed when the execution of the TestRequest completes
+            testRequest.closeUponCompletion(resultOutputStream);
+            resultFormatter.setDestination(new KeepAliveOutputStream(resultOutputStream));
+        } catch (IOException e) {
+            throw new BuildException(e);
+        }
+        // check if system.out/system.err content needs to be passed on to the listener
+        if (formatterDefinition.shouldSendSysOut()) {
+            testRequest.addSysOutInterest(resultFormatter);
+        }
+        if (formatterDefinition.shouldSendSysErr()) {
+            testRequest.addSysErrInterest(resultFormatter);
+        }
+    }
+
+    private Path getListenerOutputFile(final TestRequest testRequest, final ListenerDefinition listener) {
+        final TestDefinition test = testRequest.getOwner();
+        final String filename;
+        if (listener.getResultFile() != null) {
+            filename = listener.getResultFile();
+        } else {
+            // compute a file name
+            final StringBuilder sb = new StringBuilder("TEST-");
+            sb.append(testRequest.getName() == null ? "unknown" : testRequest.getName());
+            sb.append(".");
+            sb.append(listener.getExtension());
+            filename = sb.toString();
+        }
+        if (listener.getOutputDir() != null) {
+            // use the output dir defined on the listener
+            return Paths.get(listener.getOutputDir(), filename);
+        }
+        // check on the enclosing test definition, in context of which this listener is being run
+        if (test.getOutputDir() != null) {
+            return Paths.get(test.getOutputDir(), filename);
+        }
+        // neither listener nor the test define a output dir, so use basedir of the project
+        final TestExecutionContext testExecutionContext = this.testExecutionContext;
+        final String baseDir = testExecutionContext.getProperties().getProperty(MagicNames.PROJECT_BASEDIR);
+        return Paths.get(baseDir, filename);
+    }
+
+    private TestExecutionListener requireTestExecutionListener(final ListenerDefinition listener, final ClassLoader classLoader) {
+        final String className = listener.getClassName();
+        if (className == null || className.trim().isEmpty()) {
+            throw new BuildException("classname attribute value is missing on listener element");
+        }
+        final Class<?> klass;
+        try {
+            klass = Class.forName(className, false, classLoader);
+        } catch (ClassNotFoundException e) {
+            throw new BuildException("Failed to load listener class " + className, e);
+        }
+        if (!TestExecutionListener.class.isAssignableFrom(klass)) {
+            throw new BuildException("Listener class " + className + " is not of type " + TestExecutionListener.class.getName());
+        }
+        try {
+            return (TestExecutionListener) klass.getDeclaredConstructor().newInstance();
+        } catch (Exception e) {
+            throw new BuildException("Failed to create an instance of listener " + className, e);
+        }
+    }
+
+    private void handleTestExecutionCompletion(final TestDefinition test, final TestExecutionSummary summary) {
+        final boolean hasTestFailures = summary.getTotalFailureCount() != 0;
+        if (hasTestFailures) {
+            // keep track of the test failure(s) for the entire launched instance
+            this.testsFailed = true;
+        }
+        try {
+            if (hasTestFailures && test.getFailureProperty() != null) {
+                // if there are test failures and the test is configured to set a property in case
+                // of failure, then set the property to true
+                final TestExecutionContext testExecutionContext = this.testExecutionContext;
+                if (testExecutionContext.getProject().isPresent()) {
+                    final Project project = testExecutionContext.getProject().get();
+                    project.setNewProperty(test.getFailureProperty(), "true");
+                }
+            }
+        } finally {
+            if (hasTestFailures && test.isHaltOnFailure()) {
+                // if the test is configured to halt on test failures, throw a build error
+                final String errorMessage;
+                if (test instanceof NamedTest) {
+                    errorMessage = "Test " + ((NamedTest) test).getName() + " has " + summary.getTestsFailedCount() + " failure(s)";
+                } else {
+                    errorMessage = "Some test(s) have failure(s)";
+                }
+                throw new BuildException(errorMessage);
+            }
+        }
+    }
+
+    private Optional<SwitchedStreamHandle> trySwitchSysOutErr(final TestRequest testRequest, final StreamType streamType,
+                                                              final PrintStream originalSysErr) {
+        switch (streamType) {
+            case SYS_OUT: {
+                if (!testRequest.interestedInSysOut()) {
+                    return Optional.empty();
+                }
+                break;
+            }
+            case SYS_ERR: {
+                if (!testRequest.interestedInSysErr()) {
+                    return Optional.empty();
+                }
+                break;
+            }
+            default: {
+                // unknown, but no need to error out, just be lenient
+                // and return back
+                return Optional.empty();
+            }
+        }
+        final PipedOutputStream pipedOutputStream = new PipedOutputStream();
+        final PipedInputStream pipedInputStream;
+        try {
+            pipedInputStream = new LeadPipeInputStream(pipedOutputStream);
+        } catch (IOException ioe) {
+            // log and return
+            return Optional.empty();
+        }
+        final PrintStream printStream = new PrintStream(pipedOutputStream, true);
+        final SysOutErrStreamReader streamer;
+        switch (streamType) {
+            case SYS_OUT: {
+                System.setOut(new PrintStream(printStream));
+                streamer = new SysOutErrStreamReader(this, pipedInputStream,
+                        StreamType.SYS_OUT, testRequest.getSysOutInterests(), originalSysErr);
+                final Thread sysOutStreamer = new Thread(streamer);
+                sysOutStreamer.setDaemon(true);
+                sysOutStreamer.setName("junitlauncher-sysout-stream-reader");
+                sysOutStreamer.setUncaughtExceptionHandler((t, e) -> {
+                    // skip the logging redirection infrastructure of junitlauncher task (which is what has
+                    // failed here) and instead directly write out the error to the original System.err
+                    originalSysErr.println("Failed in sysout streaming");
+                    e.printStackTrace(originalSysErr);
+                });
+                sysOutStreamer.start();
+                break;
+            }
+            case SYS_ERR: {
+                System.setErr(new PrintStream(printStream));
+                streamer = new SysOutErrStreamReader(this, pipedInputStream,
+                        StreamType.SYS_ERR, testRequest.getSysErrInterests(), originalSysErr);
+                final Thread sysErrStreamer = new Thread(streamer);
+                sysErrStreamer.setDaemon(true);
+                sysErrStreamer.setName("junitlauncher-syserr-stream-reader");
+                sysErrStreamer.setUncaughtExceptionHandler((t, e) -> {
+                    // skip the logging redirection infrastructure of junitlauncher task (which is what has
+                    // failed here) and instead directly write out the error to the original System.err
+                    originalSysErr.println("Failed in syserr streaming");
+                    e.printStackTrace(originalSysErr);
+                });
+                sysErrStreamer.start();
+                break;
+            }
+            default: {
+                return Optional.empty();
+            }
+        }
+        return Optional.of(new SwitchedStreamHandle(pipedOutputStream, streamer));
+    }
+
+    private void log(final String message, final Throwable t, final int level) {
+        final TestExecutionContext testExecutionContext = this.testExecutionContext;
+        if (testExecutionContext.getProject().isPresent()) {
+            testExecutionContext.getProject().get().log(message, t, level);
+            return;
+        }
+        if (t == null) {
+            System.out.println(message);
+        } else {
+            System.err.println(message);
+            t.printStackTrace();
+        }
+    }
+
+
+    private List<TestRequest> createTestRequests(final TestDefinition test) {
+        // create TestRequest(s) and add necessary selectors, filters to it
+
+        if (test instanceof SingleTestClass) {
+            final SingleTestClass singleTestClass = (SingleTestClass) test;
+            final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request();
+            final TestRequest request = new TestRequest(test, requestBuilder);
+            request.setName(singleTestClass.getName());
+            final String[] methods = singleTestClass.getMethods();
+            if (methods == null) {
+                requestBuilder.selectors(DiscoverySelectors.selectClass(singleTestClass.getName()));
+            } else {
+                // add specific methods
+                for (final String method : methods) {
+                    requestBuilder.selectors(DiscoverySelectors.selectMethod(singleTestClass.getName(), method));
+                }
+            }
+            addFilters(request);
+            return Collections.singletonList(request);
+        }
+
+        if (test instanceof TestClasses) {
+            final List<String> testClasses = ((TestClasses) test).getTestClassNames();
+            if (testClasses.isEmpty()) {
+                return Collections.emptyList();
+            }
+            final List<TestRequest> requests = new ArrayList<>();
+            for (final String testClass : testClasses) {
+                final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request();
+                final TestRequest request = new TestRequest(test, requestBuilder);
+                request.setName(testClass);
+                requestBuilder.selectors(DiscoverySelectors.selectClass(testClass));
+                addFilters(request);
+
+                requests.add(request);
+            }
+            return requests;
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Add necessary {@link Filter JUnit filters} to the {@code testRequest}
+     *
+     * @param testRequest The test request
+     */
+    private void addFilters(final TestRequest testRequest) {
+        final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest();
+        // add any engine filters
+        final String[] enginesToInclude = testRequest.getOwner().getIncludeEngines();
+        if (enginesToInclude != null && enginesToInclude.length > 0) {
+            requestBuilder.filters(EngineFilter.includeEngines(enginesToInclude));
+        }
+        final String[] enginesToExclude = testRequest.getOwner().getExcludeEngines();
+        if (enginesToExclude != null && enginesToExclude.length > 0) {
+            requestBuilder.filters(EngineFilter.excludeEngines(enginesToExclude));
+        }
+        // add any tag filters
+        if (this.launchDefinition.getIncludeTags().size() > 0) {
+            requestBuilder.filters(TagFilter.includeTags(this.launchDefinition.getIncludeTags()));
+        }
+        if (this.launchDefinition.getExcludeTags().size() > 0) {
+            requestBuilder.filters(TagFilter.excludeTags(this.launchDefinition.getExcludeTags()));
+        }
+    }
+
+    private enum StreamType {
+        SYS_OUT,
+        SYS_ERR
+    }
+
+    // Implementation note: Logging from this class is prohibited since it can lead
+    // to deadlocks (see bz-64733 for details)
+    private static final class SysOutErrStreamReader implements Runnable {
+        private static final byte[] EMPTY = new byte[0];
+
+        private final LauncherSupport launchManager;
+        private final PrintStream originalSysErr;
+        private final InputStream sourceStream;
+        private final StreamType streamType;
+        private final Collection<TestResultFormatter> resultFormatters;
+        private volatile SysOutErrContentDeliverer contentDeliverer;
+
+        SysOutErrStreamReader(final LauncherSupport launchManager, final InputStream source,
+                              final StreamType streamType, final Collection<TestResultFormatter> resultFormatters,
+                              final PrintStream originalSysErr) {
+            this.launchManager = launchManager;
+            this.sourceStream = source;
+            this.streamType = streamType;
+            this.resultFormatters = resultFormatters;
+            this.originalSysErr = originalSysErr;
+        }
+
+        @Override
+        public void run() {
+            final SysOutErrContentDeliverer streamContentDeliver = new SysOutErrContentDeliverer(this.streamType, this.resultFormatters);
+            final Thread deliveryThread = new Thread(streamContentDeliver);
+            deliveryThread.setName("junitlauncher-" + (this.streamType == StreamType.SYS_OUT ? "sysout" : "syserr") + "-stream-deliverer");
+            deliveryThread.setDaemon(true);
+            deliveryThread.start();
+            this.contentDeliverer = streamContentDeliver;
+            int numRead = -1;
+            final byte[] data = new byte[1024];
+            try {
+                while ((numRead = this.sourceStream.read(data)) != -1) {
+                    final byte[] copy = Arrays.copyOf(data, numRead);
+                    streamContentDeliver.availableData.offer(copy);
+                }
+            } catch (IOException e) {
+                // let the UncaughtExceptionHandler of this thread deal with this exception
+                throw new UncheckedIOException(e);
+            } finally {
+                streamContentDeliver.stop = true;
+                // just "wakeup" the delivery thread, to take into account
+                // those race conditions, where that other thread didn't yet
+                // notice that it was asked to stop and has now gone into a
+                // X amount of wait, waiting for any new data
+                streamContentDeliver.availableData.offer(EMPTY);
+            }
+        }
+    }
+
+    private static final class SysOutErrContentDeliverer implements Runnable {
+        private volatile boolean stop;
+        private final Collection<TestResultFormatter> resultFormatters;
+        private final StreamType streamType;
+        private final BlockingQueue<byte[]> availableData = new LinkedBlockingQueue<>();
+        private final CountDownLatch completionLatch = new CountDownLatch(1);
+
+        SysOutErrContentDeliverer(final StreamType streamType, final Collection<TestResultFormatter> resultFormatters) {
+            this.streamType = streamType;
+            this.resultFormatters = resultFormatters;
+        }
+
+        @Override
+        public void run() {
+            try {
+                while (!this.stop) {
+                    final byte[] streamData;
+                    try {
+                        streamData = this.availableData.poll(2, TimeUnit.SECONDS);
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        return;
+                    }
+                    if (streamData != null) {
+                        deliver(streamData);
+                    }
+                }
+                // drain it
+                final List<byte[]> remaining = new ArrayList<>();
+                this.availableData.drainTo(remaining);
+                if (!remaining.isEmpty()) {
+                    for (final byte[] data : remaining) {
+                        deliver(data);
+                    }
+                }
+            } finally {
+                this.completionLatch.countDown();
+            }
+        }
+
+        private void deliver(final byte[] data) {
+            if (data == null || data.length == 0) {
+                return;
+            }
+            for (final TestResultFormatter resultFormatter : this.resultFormatters) {
+                // send it to the formatter
+                switch (streamType) {
+                    case SYS_OUT: {
+                        resultFormatter.sysOutAvailable(data);
+                        break;
+                    }
+                    case SYS_ERR: {
+                        resultFormatter.sysErrAvailable(data);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    private final class SwitchedStreamHandle implements AutoCloseable {
+        private final PipedOutputStream outputStream;
+        private final SysOutErrStreamReader streamReader;
+
+        SwitchedStreamHandle(final PipedOutputStream outputStream, final SysOutErrStreamReader streamReader) {
+            this.streamReader = streamReader;
+            this.outputStream = outputStream;
+        }
+
+        @Override
+        public void close() throws Exception {
+            outputStream.close();
+            streamReader.sourceStream.close();
+        }
+    }
+
+    private final class Listener extends SummaryGeneratingListener {
+        private final PrintStream originalSysOut;
+
+        private Optional<SwitchedStreamHandle> switchedSysOutHandle;
+        private Optional<SwitchedStreamHandle> switchedSysErrHandle;
+
+        private Listener(final PrintStream originalSysOut) {
+            this.originalSysOut = originalSysOut;
+        }
+
+        @Override
+        public void executionStarted(final TestIdentifier testIdentifier) {
+            super.executionStarted(testIdentifier);
+            AbstractJUnitResultFormatter.isTestClass(testIdentifier).ifPresent(testClass ->
+                    this.originalSysOut.println("Running " + testClass.getClassName()));
+        }
+
+
+        private static final double ONE_SECOND = 1000.0;
+        // We use this only in the testPlanExecutionFinished method, which
+        // as per the JUnit5 platform semantics won't be called concurrently
+        // by multiple threads (https://github.com/junit-team/junit5/issues/2539#issuecomment-766325555).
+        // So it's safe to use this without any additional thread safety access controls.
+        private NumberFormat timeFormatter = NumberFormat.getInstance();
+
+        @Override
+        public void testPlanExecutionFinished(final TestPlan testPlan) {
+            super.testPlanExecutionFinished(testPlan);
+            if (!testPlan.containsTests()) {
+                // we print the summary only if any tests are present
+                return;
+            }
+            if (launchDefinition.isPrintSummary()) {
+                final TestExecutionSummary summary = this.getSummary();
+                // Keep the summary as close to as the old junit task summary
+                // tests run, failed, skipped, duration
+                final StringBuilder sb = new StringBuilder("Tests run: ");
+                sb.append(summary.getTestsStartedCount());
+                sb.append(", Failures: ");
+                sb.append(summary.getTestsFailedCount());
+                sb.append(", Aborted: ");
+                sb.append(summary.getTestsAbortedCount());
+                sb.append(", Skipped: ");
+                sb.append(summary.getTestsSkippedCount());
+                sb.append(", Time elapsed: ");
+                final long elapsedMs = summary.getTimeFinished() - summary.getTimeStarted();
+                sb.append(timeFormatter.format(elapsedMs / ONE_SECOND));
+                sb.append(" sec");
+                this.originalSysOut.println(sb.toString());
+            }
+            // now that the test plan execution is finished, close the switched sysout/syserr output streams
+            // and wait for the sysout and syserr content delivery, to result formatters, to finish
+            if (this.switchedSysOutHandle.isPresent()) {
+                final SwitchedStreamHandle sysOut = this.switchedSysOutHandle.get();
+                try {
+                    closeAndWait(sysOut);
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    return;
+                }
+            }
+            if (this.switchedSysErrHandle.isPresent()) {
+                final SwitchedStreamHandle sysErr = this.switchedSysErrHandle.get();
+                try {
+                    closeAndWait(sysErr);
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+            }
+        }
+
+        private void closeAndWait(final SwitchedStreamHandle handle) throws InterruptedException {
+            FileUtils.close(handle.outputStream);
+            if (handle.streamReader.contentDeliverer == null) {
+                return;
+            }
+            // wait for a few seconds
+            handle.streamReader.contentDeliverer.completionLatch.await(2, TimeUnit.SECONDS);
+        }
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyBriefResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyBriefResultFormatter.java
new file mode 100644
index 0000000..7debbf0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyBriefResultFormatter.java
@@ -0,0 +1,34 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.launcher.TestIdentifier;
+
+/**
+ * A {@link TestResultFormatter} which prints a brief statistic for tests that have
+ * failed, aborted or skipped
+ */
+class LegacyBriefResultFormatter extends LegacyPlainResultFormatter implements TestResultFormatter {
+
+    @Override
+    protected boolean shouldReportExecutionFinished(final TestIdentifier testIdentifier, final TestExecutionResult testExecutionResult) {
+        final TestExecutionResult.Status resultStatus = testExecutionResult.getStatus();
+        return resultStatus == TestExecutionResult.Status.ABORTED || resultStatus == TestExecutionResult.Status.FAILED;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyPlainResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyPlainResultFormatter.java
new file mode 100644
index 0000000..7583d78
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyPlainResultFormatter.java
@@ -0,0 +1,290 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.engine.reporting.ReportEntry;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+
+/**
+ * A {@link TestResultFormatter} which prints a short statistic for each of the tests
+ */
+class LegacyPlainResultFormatter extends AbstractJUnitResultFormatter implements TestResultFormatter {
+
+    private OutputStream outputStream;
+    private final Map<TestIdentifier, Stats> testIds = new ConcurrentHashMap<>();
+    private TestPlan testPlan;
+    private BufferedWriter writer;
+    private boolean useLegacyReportingName = true;
+
+    @Override
+    public void testPlanExecutionStarted(final TestPlan testPlan) {
+        this.testPlan = testPlan;
+    }
+
+    @Override
+    public void testPlanExecutionFinished(final TestPlan testPlan) {
+        for (final Map.Entry<TestIdentifier, Stats> entry : this.testIds.entrySet()) {
+            final TestIdentifier testIdentifier = entry.getKey();
+            if (!isTestClass(testIdentifier).isPresent()) {
+                // we are not interested in anything other than a test "class" in this section
+                continue;
+            }
+            final Stats stats = entry.getValue();
+            final StringBuilder sb = new StringBuilder("Tests run: ").append(stats.numTestsRun.get());
+            sb.append(", Failures: ").append(stats.numTestsFailed.get());
+            sb.append(", Skipped: ").append(stats.numTestsSkipped.get());
+            sb.append(", Aborted: ").append(stats.numTestsAborted.get());
+            sb.append(", Time elapsed: ");
+            stats.appendElapsed(sb);
+            try {
+                this.writer.write(sb.toString());
+                this.writer.newLine();
+            } catch (IOException ioe) {
+                handleException(ioe);
+                return;
+            }
+        }
+        // write out sysout and syserr content if any
+        try {
+            if (this.hasSysOut()) {
+                this.writer.write("------------- Standard Output ---------------");
+                this.writer.newLine();
+                writeSysOut(writer);
+                this.writer.write("------------- ---------------- ---------------");
+                this.writer.newLine();
+            }
+            if (this.hasSysErr()) {
+                this.writer.write("------------- Standard Error ---------------");
+                this.writer.newLine();
+                writeSysErr(writer);
+                this.writer.write("------------- ---------------- ---------------");
+                this.writer.newLine();
+            }
+        } catch (IOException ioe) {
+            handleException(ioe);
+        }
+    }
+
+    @Override
+    public void dynamicTestRegistered(final TestIdentifier testIdentifier) {
+        // nothing to do
+    }
+
+    @Override
+    public void executionSkipped(final TestIdentifier testIdentifier, final String reason) {
+        final long currentTime = System.currentTimeMillis();
+        this.testIds.putIfAbsent(testIdentifier, new Stats(testIdentifier, currentTime));
+        final Stats stats = this.testIds.get(testIdentifier);
+        stats.setEndedAt(currentTime);
+        if (testIdentifier.isTest()) {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("Test: ");
+            sb.append(this.useLegacyReportingName ? testIdentifier.getLegacyReportingName() : testIdentifier.getDisplayName());
+            sb.append(" took ");
+            stats.appendElapsed(sb);
+            sb.append(" SKIPPED");
+            if (reason != null && !reason.isEmpty()) {
+                sb.append(": ").append(reason);
+            }
+            try {
+                this.writer.write(sb.toString());
+                this.writer.newLine();
+            } catch (IOException ioe) {
+                handleException(ioe);
+                return;
+            }
+        }
+        // get the parent test class to which this skipped test belongs to
+        final Optional<TestIdentifier> parentTestClass = traverseAndFindTestClass(this.testPlan, testIdentifier);
+        if (!parentTestClass.isPresent()) {
+            return;
+        }
+        final Stats parentClassStats = this.testIds.get(parentTestClass.get());
+        parentClassStats.numTestsSkipped.incrementAndGet();
+    }
+
+    @Override
+    public void executionStarted(final TestIdentifier testIdentifier) {
+        final long currentTime = System.currentTimeMillis();
+        // record this testidentifier's start
+        this.testIds.putIfAbsent(testIdentifier, new Stats(testIdentifier, currentTime));
+        final Optional<ClassSource> testClass = isTestClass(testIdentifier);
+        if (testClass.isPresent()) {
+            // if this is a test class, then print it out
+            try {
+                this.writer.write("Testcase: " + testClass.get().getClassName());
+                this.writer.newLine();
+            } catch (IOException ioe) {
+                handleException(ioe);
+                return;
+            }
+        }
+        // if this is a test (method) then increment the tests run for the test class to which
+        // this test belongs to
+        if (testIdentifier.isTest()) {
+            final Optional<TestIdentifier> parentTestClass = traverseAndFindTestClass(this.testPlan, testIdentifier);
+            if (parentTestClass.isPresent()) {
+                final Stats parentClassStats = this.testIds.get(parentTestClass.get());
+                if (parentClassStats != null) {
+                    parentClassStats.numTestsRun.incrementAndGet();
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("incomplete-switch")
+    @Override
+    public void executionFinished(final TestIdentifier testIdentifier, final TestExecutionResult testExecutionResult) {
+        final long currentTime = System.currentTimeMillis();
+        final Stats stats = this.testIds.get(testIdentifier);
+        if (stats != null) {
+            stats.setEndedAt(currentTime);
+        }
+        if (testIdentifier.isTest() && shouldReportExecutionFinished(testIdentifier, testExecutionResult)) {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("Test: ");
+            sb.append(this.useLegacyReportingName ? testIdentifier.getLegacyReportingName() : testIdentifier.getDisplayName());
+            if (stats != null) {
+                sb.append(" took ");
+                stats.appendElapsed(sb);
+            }
+            switch (testExecutionResult.getStatus()) {
+                case ABORTED: {
+                    sb.append(" ABORTED");
+                    appendThrowable(sb, testExecutionResult);
+                    break;
+                }
+                case FAILED: {
+                    sb.append(" FAILED");
+                    appendThrowable(sb, testExecutionResult);
+                    break;
+                }
+            }
+            try {
+                this.writer.write(sb.toString());
+                this.writer.newLine();
+            } catch (IOException ioe) {
+                handleException(ioe);
+                return;
+            }
+        }
+        // get the parent test class in which this test completed
+        final Optional<TestIdentifier> parentTestClass = traverseAndFindTestClass(this.testPlan, testIdentifier);
+        if (!parentTestClass.isPresent()) {
+            return;
+        }
+        // update the stats of the parent test class
+        final Stats parentClassStats = this.testIds.get(parentTestClass.get());
+        switch (testExecutionResult.getStatus()) {
+            case ABORTED: {
+                parentClassStats.numTestsAborted.incrementAndGet();
+                break;
+            }
+            case FAILED: {
+                parentClassStats.numTestsFailed.incrementAndGet();
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void reportingEntryPublished(final TestIdentifier testIdentifier, final ReportEntry entry) {
+        // nothing to do
+    }
+
+    @Override
+    public void setDestination(final OutputStream os) {
+        this.outputStream = os;
+        this.writer = new BufferedWriter(new OutputStreamWriter(this.outputStream, StandardCharsets.UTF_8));
+    }
+
+    @Override
+    public void setUseLegacyReportingName(final boolean useLegacyReportingName) {
+        this.useLegacyReportingName = useLegacyReportingName;
+    }
+
+    protected boolean shouldReportExecutionFinished(final TestIdentifier testIdentifier, final TestExecutionResult testExecutionResult) {
+        return true;
+    }
+
+    private static void appendThrowable(final StringBuilder sb, TestExecutionResult result) {
+        if (!result.getThrowable().isPresent()) {
+            return;
+        }
+        final Throwable throwable = result.getThrowable().get();
+        sb.append(String.format(": %s%n", throwable.getMessage()));
+        final StringWriter stacktrace = new StringWriter();
+        throwable.printStackTrace(new PrintWriter(stacktrace));
+        sb.append(stacktrace.toString());
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (this.writer != null) {
+            this.writer.close();
+        }
+        super.close();
+    }
+
+    private final class Stats {
+        @SuppressWarnings("unused")
+        private final TestIdentifier testIdentifier;
+        private final AtomicLong numTestsRun = new AtomicLong(0);
+        private final AtomicLong numTestsFailed = new AtomicLong(0);
+        private final AtomicLong numTestsSkipped = new AtomicLong(0);
+        private final AtomicLong numTestsAborted = new AtomicLong(0);
+        private final long startedAt;
+        private long endedAt;
+
+        private Stats(final TestIdentifier testIdentifier, final long startedAt) {
+            this.testIdentifier = testIdentifier;
+            this.startedAt = startedAt;
+        }
+
+        private void setEndedAt(final long endedAt) {
+            this.endedAt = endedAt;
+        }
+
+        private void appendElapsed(StringBuilder sb) {
+            final long timeElapsed = endedAt - startedAt;
+            if (timeElapsed < 1000) {
+                sb.append(timeElapsed).append(" milli sec(s)");
+            } else {
+                sb.append(TimeUnit.SECONDS.convert(timeElapsed, TimeUnit.MILLISECONDS)).append(" sec(s)");
+            }
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java
new file mode 100644
index 0000000..3db1227
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java
@@ -0,0 +1,434 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.util.DOMElementWriter;
+import org.apache.tools.ant.util.DateUtils;
+import org.apache.tools.ant.util.StringUtils;
+import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.reporting.ReportEntry;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.util.Date;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A {@link TestResultFormatter} which generates an XML report of the tests. The generated XML reports
+ * conforms to the schema of the XML that was generated by the {@code junit} task's XML
+ * report formatter and can be used by the {@code junitreport} task
+ */
+class LegacyXmlResultFormatter extends AbstractJUnitResultFormatter implements TestResultFormatter {
+
+    private static final double ONE_SECOND = 1000.0;
+
+    private OutputStream outputStream;
+    private final Map<TestIdentifier, Stats> testIds = new ConcurrentHashMap<>();
+    private final Map<TestIdentifier, Optional<String>> skipped = new ConcurrentHashMap<>();
+    private final Map<TestIdentifier, Optional<Throwable>> failed = new ConcurrentHashMap<>();
+    private final Map<TestIdentifier, Optional<Throwable>> aborted = new ConcurrentHashMap<>();
+
+    private TestPlan testPlan;
+    private long testPlanStartedAt = -1;
+    private long testPlanEndedAt = -1;
+    private final AtomicLong numTestsRun = new AtomicLong(0);
+    private final AtomicLong numTestsFailed = new AtomicLong(0);
+    private final AtomicLong numTestsSkipped = new AtomicLong(0);
+    private final AtomicLong numTestsAborted = new AtomicLong(0);
+    private boolean useLegacyReportingName = true;
+
+
+    @Override
+    public void testPlanExecutionStarted(final TestPlan testPlan) {
+        this.testPlan = testPlan;
+        this.testPlanStartedAt = System.currentTimeMillis();
+    }
+
+    @Override
+    public void testPlanExecutionFinished(final TestPlan testPlan) {
+        this.testPlanEndedAt = System.currentTimeMillis();
+        // format and print out the result
+        try {
+            new XMLReportWriter().write();
+        } catch (IOException | XMLStreamException e) {
+            handleException(e);
+        }
+    }
+
+    @Override
+    public void dynamicTestRegistered(final TestIdentifier testIdentifier) {
+        // nothing to do
+    }
+
+    @Override
+    public void executionSkipped(final TestIdentifier testIdentifier, final String reason) {
+        final long currentTime = System.currentTimeMillis();
+        this.numTestsSkipped.incrementAndGet();
+        this.skipped.put(testIdentifier, Optional.ofNullable(reason));
+        // a skipped test is considered started and ended now
+        final Stats stats = new Stats(testIdentifier, currentTime);
+        stats.endedAt = currentTime;
+        this.testIds.put(testIdentifier, stats);
+    }
+
+    @Override
+    public void executionStarted(final TestIdentifier testIdentifier) {
+        final long currentTime = System.currentTimeMillis();
+        this.testIds.putIfAbsent(testIdentifier, new Stats(testIdentifier, currentTime));
+        if (testIdentifier.isTest()) {
+            this.numTestsRun.incrementAndGet();
+        }
+    }
+
+    @Override
+    public void executionFinished(final TestIdentifier testIdentifier, final TestExecutionResult testExecutionResult) {
+        final long currentTime = System.currentTimeMillis();
+        final Stats stats = this.testIds.get(testIdentifier);
+        if (stats != null) {
+            stats.endedAt = currentTime;
+        }
+        switch (testExecutionResult.getStatus()) {
+            case SUCCESSFUL: {
+                break;
+            }
+            case ABORTED: {
+                this.numTestsAborted.incrementAndGet();
+                this.aborted.put(testIdentifier, testExecutionResult.getThrowable());
+                break;
+            }
+            case FAILED: {
+                this.numTestsFailed.incrementAndGet();
+                this.failed.put(testIdentifier, testExecutionResult.getThrowable());
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void reportingEntryPublished(final TestIdentifier testIdentifier, final ReportEntry entry) {
+        // nothing to do
+    }
+
+    @Override
+    public void setDestination(final OutputStream os) {
+        this.outputStream = os;
+    }
+
+    @Override
+    public void setUseLegacyReportingName(final boolean useLegacyReportingName) {
+        this.useLegacyReportingName = useLegacyReportingName;
+    }
+
+    private final class Stats {
+        @SuppressWarnings("unused")
+        private final TestIdentifier testIdentifier;
+        private final long startedAt;
+        private long endedAt;
+
+        private Stats(final TestIdentifier testIdentifier, final long startedAt) {
+            this.testIdentifier = testIdentifier;
+            this.startedAt = startedAt;
+        }
+    }
+
+    private final class XMLReportWriter {
+
+        private static final String ELEM_TESTSUITE = "testsuite";
+        private static final String ELEM_PROPERTIES = "properties";
+        private static final String ELEM_PROPERTY = "property";
+        private static final String ELEM_TESTCASE = "testcase";
+        private static final String ELEM_SKIPPED = "skipped";
+        private static final String ELEM_FAILURE = "failure";
+        private static final String ELEM_ABORTED = "aborted";
+        private static final String ELEM_SYSTEM_OUT = "system-out";
+        private static final String ELEM_SYSTEM_ERR = "system-err";
+
+
+        private static final String ATTR_CLASSNAME = "classname";
+        private static final String ATTR_NAME = "name";
+        private static final String ATTR_VALUE = "value";
+        private static final String ATTR_TIME = "time";
+        private static final String ATTR_TIMESTAMP = "timestamp";
+        private static final String ATTR_NUM_ABORTED = "aborted";
+        private static final String ATTR_NUM_FAILURES = "failures";
+        private static final String ATTR_NUM_TESTS = "tests";
+        private static final String ATTR_NUM_SKIPPED = "skipped";
+        private static final String ATTR_MESSAGE = "message";
+        private static final String ATTR_TYPE = "type";
+
+        void write() throws XMLStreamException, IOException {
+            final XMLStreamWriter writer = XMLOutputFactory.newFactory().createXMLStreamWriter(outputStream, "UTF-8");
+            try {
+                writer.writeStartDocument();
+                writeTestSuite(writer);
+                writer.writeEndDocument();
+            } finally {
+                writer.close();
+            }
+        }
+
+        void writeTestSuite(final XMLStreamWriter writer) throws XMLStreamException, IOException {
+            // write the testsuite element
+            writer.writeStartElement(ELEM_TESTSUITE);
+            final String testsuiteName = determineTestSuiteName();
+            writeAttribute(writer, ATTR_NAME, testsuiteName);
+            // time taken for the tests execution
+            writeAttribute(writer, ATTR_TIME, String.valueOf((testPlanEndedAt - testPlanStartedAt) / ONE_SECOND));
+            // add the timestamp of report generation
+            final String timestamp = DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN);
+            writeAttribute(writer, ATTR_TIMESTAMP, timestamp);
+            writeAttribute(writer, ATTR_NUM_TESTS, String.valueOf(numTestsRun.longValue()));
+            writeAttribute(writer, ATTR_NUM_FAILURES, String.valueOf(numTestsFailed.longValue()));
+            writeAttribute(writer, ATTR_NUM_SKIPPED, String.valueOf(numTestsSkipped.longValue()));
+            writeAttribute(writer, ATTR_NUM_ABORTED, String.valueOf(numTestsAborted.longValue()));
+
+            // write the properties
+            writeProperties(writer);
+            // write the tests
+            writeTestCase(writer);
+            writeSysOut(writer);
+            writeSysErr(writer);
+            // end the testsuite
+            writer.writeEndElement();
+        }
+
+        void writeProperties(final XMLStreamWriter writer) throws XMLStreamException {
+            final Properties properties = LegacyXmlResultFormatter.this.context.getProperties();
+            if (properties == null || properties.isEmpty()) {
+                return;
+            }
+            writer.writeStartElement(ELEM_PROPERTIES);
+            for (final String prop : properties.stringPropertyNames()) {
+                writer.writeStartElement(ELEM_PROPERTY);
+                writeAttribute(writer, ATTR_NAME, prop);
+                writeAttribute(writer, ATTR_VALUE, properties.getProperty(prop));
+                writer.writeEndElement();
+            }
+            writer.writeEndElement();
+        }
+
+        void writeTestCase(final XMLStreamWriter writer) throws XMLStreamException {
+            for (final Map.Entry<TestIdentifier, Stats> entry : testIds.entrySet()) {
+                final TestIdentifier testId = entry.getKey();
+                if (!testId.isTest() && !failed.containsKey(testId)) {
+                    // only interested in test methods unless there was a failure,
+                    // in which case we want the exception reported
+                    // (https://bz.apache.org/bugzilla/show_bug.cgi?id=63850)
+                    continue;
+                }
+                // find the associated class of this test
+                final Optional<ClassSource> parentClassSource;
+                if (testId.isTest()) {
+                    parentClassSource = findFirstParentClassSource(testId);
+                }
+                else {
+                    parentClassSource = findFirstClassSource(testId);
+                }
+                if (!parentClassSource.isPresent()) {
+                    continue;
+                }
+                final String classname = (parentClassSource.get()).getClassName();
+                writer.writeStartElement(ELEM_TESTCASE);
+                writeAttribute(writer, ATTR_CLASSNAME, classname);
+                writeAttribute(writer, ATTR_NAME, useLegacyReportingName ? testId.getLegacyReportingName()
+                        : testId.getDisplayName());
+                final Stats stats = entry.getValue();
+                writeAttribute(writer, ATTR_TIME, String.valueOf((stats.endedAt - stats.startedAt) / ONE_SECOND));
+                // skipped element if the test was skipped
+                writeSkipped(writer, testId);
+                // failed element if the test failed
+                writeFailed(writer, testId);
+                // aborted element if the test was aborted
+                writeAborted(writer, testId);
+
+                writer.writeEndElement();
+            }
+        }
+
+        private void writeSkipped(final XMLStreamWriter writer, final TestIdentifier testIdentifier) throws XMLStreamException {
+            if (!skipped.containsKey(testIdentifier)) {
+                return;
+            }
+            writer.writeStartElement(ELEM_SKIPPED);
+            final Optional<String> reason = skipped.get(testIdentifier);
+            if (reason.isPresent()) {
+                writeAttribute(writer, ATTR_MESSAGE, reason.get());
+            }
+            writer.writeEndElement();
+        }
+
+        private void writeFailed(final XMLStreamWriter writer, final TestIdentifier testIdentifier) throws XMLStreamException {
+            if (!failed.containsKey(testIdentifier)) {
+                return;
+            }
+            writer.writeStartElement(ELEM_FAILURE);
+            final Optional<Throwable> cause = failed.get(testIdentifier);
+            if (cause.isPresent()) {
+                final Throwable t = cause.get();
+                final String message = t.getMessage();
+                if (message != null && !message.trim().isEmpty()) {
+                    writeAttribute(writer, ATTR_MESSAGE, message);
+                }
+                writeAttribute(writer, ATTR_TYPE, t.getClass().getName());
+                // write out the stacktrace
+                this.writeCDataSafely(writer, StringUtils.getStackTrace(t));
+            }
+            writer.writeEndElement();
+        }
+
+        private void writeAborted(final XMLStreamWriter writer, final TestIdentifier testIdentifier) throws XMLStreamException {
+            if (!aborted.containsKey(testIdentifier)) {
+                return;
+            }
+            writer.writeStartElement(ELEM_ABORTED);
+            final Optional<Throwable> cause = aborted.get(testIdentifier);
+            if (cause.isPresent()) {
+                final Throwable t = cause.get();
+                final String message = t.getMessage();
+                if (message != null && !message.trim().isEmpty()) {
+                    writeAttribute(writer, ATTR_MESSAGE, message);
+                }
+                writeAttribute(writer, ATTR_TYPE, t.getClass().getName());
+                // write out the stacktrace
+                this.writeCDataSafely(writer, StringUtils.getStackTrace(t));
+            }
+            writer.writeEndElement();
+        }
+
+        private void writeSysOut(final XMLStreamWriter writer) throws XMLStreamException, IOException {
+            if (!LegacyXmlResultFormatter.this.hasSysOut()) {
+                return;
+            }
+            writer.writeStartElement(ELEM_SYSTEM_OUT);
+            try (final Reader reader = LegacyXmlResultFormatter.this.getSysOutReader()) {
+                writeCharactersFrom(reader, writer);
+            }
+            writer.writeEndElement();
+        }
+
+        private void writeSysErr(final XMLStreamWriter writer) throws XMLStreamException, IOException {
+            if (!LegacyXmlResultFormatter.this.hasSysErr()) {
+                return;
+            }
+            writer.writeStartElement(ELEM_SYSTEM_ERR);
+            try (final Reader reader = LegacyXmlResultFormatter.this.getSysErrReader()) {
+                writeCharactersFrom(reader, writer);
+            }
+            writer.writeEndElement();
+        }
+
+        /**
+         * Write cdata safely (escape special sequence {@code "]]>"})
+         * @param writer The xml writer to use
+         * @param cdata The cdata to write
+         * @see <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=65833">Bugzilla #65833</a>
+         */
+        private void writeCDataSafely(final XMLStreamWriter writer, final String cdata) throws XMLStreamException {
+            writer.writeCData(cdata.replace("]]>", "]]]]><![CDATA[>"));
+        }
+
+        private void writeCharactersFrom(final Reader reader, final XMLStreamWriter writer) throws IOException, XMLStreamException {
+            final char[] chars = new char[1024];
+            int numRead = -1;
+            while ((numRead = reader.read(chars)) != -1) {
+                writer.writeCharacters(encode(new String(chars, 0, numRead)));
+            }
+        }
+
+        private void writeAttribute(final XMLStreamWriter writer, final String name, final String value)
+            throws XMLStreamException {
+            writer.writeAttribute(name, encode(value));
+        }
+
+        private String encode(final String s) {
+            boolean changed = false;
+            final StringBuilder sb = new StringBuilder();
+            for (char c : s.toCharArray()) {
+                if (!DOMElementWriter.isLegalXmlCharacter(c)) {
+                    changed = true;
+                    sb.append("&#").append((int) c).append(';');
+                } else {
+                    sb.append(c);
+                }
+            }
+            return changed ? sb.toString() : s;
+        }
+
+        private String determineTestSuiteName() {
+            // this is really a hack to try and match the expectations of the XML report in JUnit4.x
+            // world. In JUnit5, the TestPlan doesn't have a name and a TestPlan (for which this is a
+            // listener) can have numerous tests within it
+            final Set<TestIdentifier> roots = testPlan.getRoots();
+            if (roots.isEmpty()) {
+                return "UNKNOWN";
+            }
+            for (final TestIdentifier root : roots) {
+                final Optional<ClassSource> classSource = findFirstClassSource(root);
+                if (classSource.isPresent()) {
+                    return classSource.get().getClassName();
+                }
+            }
+            return "UNKNOWN";
+        }
+
+        private Optional<ClassSource> findFirstClassSource(final TestIdentifier root) {
+            if (root.getSource().isPresent()) {
+                final TestSource source = root.getSource().get();
+                if (source instanceof ClassSource) {
+                    return Optional.of((ClassSource) source);
+                }
+            }
+            for (final TestIdentifier child : testPlan.getChildren(root)) {
+                final Optional<ClassSource> classSource = findFirstClassSource(child);
+                if (classSource.isPresent()) {
+                    return classSource;
+                }
+            }
+            return Optional.empty();
+        }
+
+        private Optional<ClassSource> findFirstParentClassSource(final TestIdentifier testId) {
+            final Optional<TestIdentifier> parent = testPlan.getParent(testId);
+            if (!parent.isPresent()) {
+                return Optional.empty();
+            }
+            if (!parent.get().getSource().isPresent()) {
+                // the source of the parent is unknown, so we move up the
+                // hierarchy and try and find a class source
+                return findFirstParentClassSource(parent.get());
+            }
+            final TestSource parentSource = parent.get().getSource().get();
+            return parentSource instanceof ClassSource ? Optional.of((ClassSource) parentSource)
+                    : findFirstParentClassSource(parent.get());
+        }
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java
new file mode 100644
index 0000000..11416ef
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java
@@ -0,0 +1,284 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.LaunchDefinition;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.ListenerDefinition;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.SingleTestClass;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestClasses;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_DOCUMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_TAGS;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_INCLUDE_TAGS;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_PRINT_SUMMARY;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LAUNCH_DEF;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LISTENER;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST_CLASSES;
+
+
+/**
+ * Used for launching forked tests from the {@link JUnitLauncherTask}.
+ * <p>
+ * Although this class is public, this isn't meant for external use. The contract of what
+ * program arguments {@link #main(String[]) the main method} accepts and how it interprets it,
+ * is also an internal detail and can change across Ant releases.
+ *
+ * @since Ant 1.10.6
+ */
+public class StandaloneLauncher {
+
+    /**
+     * Entry point to launching the forked test.
+     *
+     * @param args The arguments passed to this program for launching the tests
+     * @throws Exception If any exception occurs during the execution
+     */
+    public static void main(final String[] args) throws Exception {
+        // The main responsibility of this entry point is to create a LaunchDefinition,
+        // by parsing the passed arguments and then use the LauncherSupport to
+        // LauncherSupport#launch the tests
+        try {
+            ForkedLaunch launchDefinition = null;
+            final ForkedExecution forkedExecution = new ForkedExecution();
+            for (int i = 0; i < args.length; ) {
+                final String arg = args[i];
+                int numArgsConsumed = 1;
+                switch (arg) {
+                    case Constants.ARG_PROPERTIES: {
+                        final Path propsPath = Paths.get(args[i + 1]);
+                        if (!Files.isRegularFile(propsPath)) {
+                            throw new IllegalArgumentException(propsPath + " does not point to a properties file");
+                        }
+                        final Properties properties = new Properties();
+                        try (final InputStream is = Files.newInputStream(propsPath)) {
+                            properties.load(is);
+                        }
+                        forkedExecution.setProperties(properties);
+                        numArgsConsumed = 2;
+                        break;
+                    }
+                    case Constants.ARG_LAUNCH_DEFINITION: {
+                        final Path launchDefXmlPath = Paths.get(args[i + 1]);
+                        if (!Files.isRegularFile(launchDefXmlPath)) {
+                            throw new IllegalArgumentException(launchDefXmlPath + " does not point to a launch definition file");
+                        }
+                        launchDefinition = parseLaunchDefinition(launchDefXmlPath);
+                        numArgsConsumed = 2;
+                        break;
+                    }
+                }
+                i = i + numArgsConsumed;
+            }
+
+            final LauncherSupport launcherSupport = new LauncherSupport(launchDefinition, forkedExecution);
+            try {
+                launcherSupport.launch();
+            } catch (Throwable t) {
+                if (launcherSupport.hasTestFailures()) {
+                    System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED);
+                }
+                throw t;
+            }
+            if (launcherSupport.hasTestFailures()) {
+                System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED);
+                return;
+            }
+            System.exit(Constants.FORK_EXIT_CODE_SUCCESS);
+            return;
+        } catch (Throwable t) {
+            t.printStackTrace();
+            throw t;
+        }
+    }
+
+    private static ForkedLaunch parseLaunchDefinition(final Path pathToLaunchDefXml) {
+        if (pathToLaunchDefXml == null || !Files.isRegularFile(pathToLaunchDefXml)) {
+            throw new IllegalArgumentException(pathToLaunchDefXml + " is not a file");
+        }
+        final ForkedLaunch forkedLaunch = new ForkedLaunch();
+        try (final InputStream is = Files.newInputStream(pathToLaunchDefXml)) {
+            final XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(is);
+            reader.require(START_DOCUMENT, null, null);
+            reader.nextTag();
+            reader.require(START_ELEMENT, null, LD_XML_ELM_LAUNCH_DEF);
+            final String haltOnFailure = reader.getAttributeValue(null, LD_XML_ATTR_HALT_ON_FAILURE);
+            if (haltOnFailure != null) {
+                forkedLaunch.setHaltOnFailure(Boolean.parseBoolean(haltOnFailure));
+            }
+            final String includeTags = reader.getAttributeValue(null, LD_XML_ATTR_INCLUDE_TAGS);
+            if (includeTags != null) {
+                Stream.of(includeTags.split(",")).forEach(forkedLaunch::addIncludeTag);
+            }
+            final String excludeTags = reader.getAttributeValue(null, LD_XML_ATTR_EXCLUDE_TAGS);
+            if (excludeTags != null) {
+                Stream.of(excludeTags.split(",")).forEach(forkedLaunch::addExcludeTag);
+            }
+            final String printSummary = reader.getAttributeValue(null, LD_XML_ATTR_PRINT_SUMMARY);
+            if (printSummary != null) {
+                forkedLaunch.setPrintSummary(Boolean.parseBoolean(printSummary));
+            }
+            int nextTag = reader.nextTag();
+            while (nextTag == START_ELEMENT) {
+                reader.require(START_ELEMENT, null, null);
+                final String elementName = reader.getLocalName();
+                switch (elementName) {
+                    case LD_XML_ELM_TEST: {
+                        forkedLaunch.addTests(Collections.singletonList(SingleTestClass.fromForkedRepresentation(reader)));
+                        break;
+                    }
+                    case LD_XML_ELM_TEST_CLASSES: {
+                        forkedLaunch.addTests(TestClasses.fromForkedRepresentation(reader));
+                        break;
+                    }
+                    case LD_XML_ELM_LISTENER: {
+                        forkedLaunch.addListener(ListenerDefinition.fromForkedRepresentation(reader));
+                        break;
+                    }
+                }
+                nextTag = reader.nextTag();
+            }
+            reader.require(END_ELEMENT, null, LD_XML_ELM_LAUNCH_DEF);
+            reader.next();
+            reader.require(END_DOCUMENT, null, null);
+            return forkedLaunch;
+        } catch (Exception e) {
+            throw new BuildException("Failed to construct definition from forked representation", e);
+        }
+    }
+
+
+    private static final class ForkedExecution implements TestExecutionContext {
+        private Properties properties = new Properties();
+
+        private ForkedExecution() {
+        }
+
+        private ForkedExecution setProperties(final Properties properties) {
+            this.properties = properties;
+            return this;
+        }
+
+        @Override
+        public Properties getProperties() {
+            return this.properties;
+        }
+
+        @Override
+        public Optional<Project> getProject() {
+            // forked execution won't have access to the Ant Project
+            return Optional.empty();
+        }
+    }
+
+    private static final class ForkedLaunch implements LaunchDefinition {
+
+        private boolean printSummary;
+        private boolean haltOnFailure;
+        private List<TestDefinition> tests = new ArrayList<>();
+        private List<ListenerDefinition> listeners = new ArrayList<>();
+        private List<String> includeTags = new ArrayList<>();
+        private List<String> excludeTags = new ArrayList<>();
+
+        @Override
+        public List<TestDefinition> getTests() {
+            return this.tests;
+        }
+
+        ForkedLaunch addTests(final List<TestDefinition> tests) {
+            this.tests.addAll(tests);
+            return this;
+        }
+
+        @Override
+        public List<ListenerDefinition> getListeners() {
+            return this.listeners;
+        }
+
+        ForkedLaunch addListener(final ListenerDefinition listener) {
+            this.listeners.add(listener);
+            return this;
+        }
+
+        @Override
+        public boolean isPrintSummary() {
+            return this.printSummary;
+        }
+
+        private ForkedLaunch setPrintSummary(final boolean printSummary) {
+            this.printSummary = printSummary;
+            return this;
+        }
+
+        @Override
+        public boolean isHaltOnFailure() {
+            return this.haltOnFailure;
+        }
+
+        public ForkedLaunch setHaltOnFailure(final boolean haltOnFailure) {
+            this.haltOnFailure = haltOnFailure;
+            return this;
+        }
+
+        @Override
+        public ClassLoader getClassLoader() {
+            return this.getClass().getClassLoader();
+        }
+
+        void addIncludeTag(final String filter) {
+            this.includeTags.add(filter);
+        }
+
+        @Override
+        public List<String> getIncludeTags() {
+            return includeTags;
+        }
+
+        void addExcludeTag(final String filter) {
+            this.excludeTags.add(filter);
+        }
+
+        @Override
+        public List<String> getExcludeTags() {
+            return excludeTags;
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestExecutionContext.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestExecutionContext.java
new file mode 100644
index 0000000..86e304b
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestExecutionContext.java
@@ -0,0 +1,46 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask;
+
+import java.util.Optional;
+import java.util.Properties;
+
+/**
+ * A {@link TestExecutionContext} represents the execution context for a test
+ * that has been launched by the {@link JUnitLauncherTask} and provides any necessary
+ * contextual information about such tests.
+ */
+public interface TestExecutionContext {
+
+    /**
+     * @return Returns the properties that were used for the execution of the test
+     */
+    Properties getProperties();
+
+
+    /**
+     * @return Returns the {@link Project} in whose context the test is being executed.
+     * The {@code Project} is sometimes not available, like in the case where
+     * the test is being run in a forked mode, in such cases this method returns
+     * {@link Optional#empty() an empty value}
+     */
+    Optional<Project> getProject();
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestRequest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestRequest.java
new file mode 100644
index 0000000..836394d
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestRequest.java
@@ -0,0 +1,101 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition;
+import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
+
+import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Holds together the necessary details about a request that will be launched by the {@link JUnitLauncherTask}
+ */
+final class TestRequest implements AutoCloseable {
+    private final TestDefinition ownerTest;
+    private final LauncherDiscoveryRequestBuilder discoveryRequest;
+    private final List<Closeable> closables = new ArrayList<>();
+    private final List<TestResultFormatter> interestedInSysOut = new ArrayList<>();
+    private final List<TestResultFormatter> interestedInSysErr = new ArrayList<>();
+    private String name;
+
+    TestRequest(final TestDefinition ownerTest, final LauncherDiscoveryRequestBuilder discoveryRequest) {
+        this.ownerTest = ownerTest;
+        this.discoveryRequest = discoveryRequest;
+    }
+
+    TestDefinition getOwner() {
+        return ownerTest;
+    }
+
+    LauncherDiscoveryRequestBuilder getDiscoveryRequest() {
+        return discoveryRequest;
+    }
+
+    void setName(final String name) {
+        this.name = name;
+    }
+
+    String getName() {
+        return this.name;
+    }
+
+    void closeUponCompletion(final Closeable closeable) {
+        if (closeable == null) {
+            return;
+        }
+        this.closables.add(closeable);
+    }
+
+    void addSysOutInterest(final TestResultFormatter out) {
+        this.interestedInSysOut.add(out);
+    }
+
+    boolean interestedInSysOut() {
+        return !this.interestedInSysOut.isEmpty();
+    }
+
+    Collection<TestResultFormatter> getSysOutInterests() {
+        return Collections.unmodifiableList(this.interestedInSysOut);
+    }
+
+    void addSysErrInterest(final TestResultFormatter err) {
+        this.interestedInSysErr.add(err);
+    }
+
+    boolean interestedInSysErr() {
+        return !this.interestedInSysErr.isEmpty();
+    }
+
+    Collection<TestResultFormatter> getSysErrInterests() {
+        return Collections.unmodifiableList(this.interestedInSysErr);
+    }
+
+    public void close() throws Exception {
+        if (this.closables.isEmpty()) {
+            return;
+        }
+        for (final Closeable closeable : closables) {
+            closeable.close();
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestResultFormatter.java
new file mode 100644
index 0000000..4de168a
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestResultFormatter.java
@@ -0,0 +1,86 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.junit.platform.launcher.TestExecutionListener;
+
+import java.io.Closeable;
+import java.io.OutputStream;
+
+/**
+ * A {@code TestExecutionListener} which lets implementing classes
+ * format and write out the test execution results.
+ */
+public interface TestResultFormatter extends TestExecutionListener, Closeable {
+
+    /**
+     * This method will be invoked by the <code>junitlauncher</code> and will be passed the
+     * {@link OutputStream} to a file, to which the formatted result is expected to be written
+     * to.
+     * <p>
+     * This method will be called once, early on, during the initialization of this
+     * {@link TestResultFormatter}, typically before the test execution itself has started.
+     * </p>
+     *
+     * @param os The output stream to which to write out the result
+     */
+    void setDestination(OutputStream os);
+
+    /**
+     * This method will be invoked by the <code>junitlauncher</code> and will be passed a
+     * {@link TestExecutionContext}. This allows the {@link TestResultFormatter} to have access
+     * to any additional contextual information to use in the test reports.
+     *
+     * @param context The context of the execution of the test
+     */
+    void setContext(TestExecutionContext context);
+
+    /**
+     * This method will be invoked by the {@code junitlauncher} to let the result formatter implementation
+     * know whether or not to use JUnit 4 style, legacy reporting names for test identifiers that get
+     * displayed in the test reports. Result formatter implementations are allowed to default to a specific
+     * reporting style for test identifiers, if this method isn't invoked.
+     * @param useLegacyReportingName {@code true} if legacy reporting name is to be used, {@code false}
+     *                               otherwise.
+     * @since Ant 1.10.10
+     */
+    void setUseLegacyReportingName(boolean useLegacyReportingName);
+
+    /**
+     * This method will be invoked by the <code>junitlauncher</code>, <strong>regularly/multiple times</strong>,
+     * as and when any content is generated on the standard output stream during the test execution.
+     * This method will be only be called if the <code>sendSysOut</code> attribute of the <code>listener</code>,
+     * to which this {@link TestResultFormatter} is configured for, is enabled
+     *
+     * @param data The content generated on standard output stream
+     */
+    default void sysOutAvailable(byte[] data) {
+    }
+
+    /**
+     * This method will be invoked by the <code>junitlauncher</code>, <strong>regularly/multiple times</strong>,
+     * as and when any content is generated on the standard error stream during the test execution.
+     * This method will be only be called if the <code>sendSysErr</code> attribute of the <code>listener</code>,
+     * to which this {@link TestResultFormatter} is configured for, is enabled
+     *
+     * @param data The content generated on standard error stream
+     */
+    default void sysErrAvailable(byte[] data) {
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/Constants.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/Constants.java
new file mode 100644
index 0000000..215d3f8
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/Constants.java
@@ -0,0 +1,58 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+/**
+ * Constants used within the junitlauncher task
+ */
+public final class Constants {
+
+    public static final int FORK_EXIT_CODE_SUCCESS = 0;
+    public static final int FORK_EXIT_CODE_EXCEPTION = 1;
+    public static final int FORK_EXIT_CODE_TESTS_FAILED = 2;
+    public static final int FORK_EXIT_CODE_TIMED_OUT = 3;
+
+    public static final String ARG_PROPERTIES = "--properties";
+    public static final String ARG_LAUNCH_DEFINITION = "--launch-definition";
+
+
+    public static final String LD_XML_ELM_LAUNCH_DEF = "launch-definition";
+    public static final String LD_XML_ELM_TEST = "test";
+    public static final String LD_XML_ELM_TEST_CLASSES = "test-classes";
+    public static final String LD_XML_ATTR_HALT_ON_FAILURE = "haltOnFailure";
+    public static final String LD_XML_ATTR_INCLUDE_TAGS = "includeTags";
+    public static final String LD_XML_ATTR_EXCLUDE_TAGS = "excludeTags";
+    public static final String LD_XML_ATTR_OUTPUT_DIRECTORY = "outDir";
+    public static final String LD_XML_ATTR_INCLUDE_ENGINES = "includeEngines";
+    public static final String LD_XML_ATTR_EXCLUDE_ENGINES = "excludeEngines";
+    public static final String LD_XML_ATTR_CLASS_NAME = "classname";
+    public static final String LD_XML_ATTR_METHODS = "methods";
+    public static final String LD_XML_ATTR_PRINT_SUMMARY = "printSummary";
+    public static final String LD_XML_ELM_LISTENER = "listener";
+    public static final String LD_XML_ATTR_SEND_SYS_ERR = "sendSysErr";
+    public static final String LD_XML_ATTR_SEND_SYS_OUT = "sendSysOut";
+    public static final String LD_XML_ATTR_LISTENER_RESULT_FILE = "resultFile";
+    public static final String LD_XML_ATTR_LISTENER_EXTENSION = "extension";
+    public static final String LD_XML_ATTR_LISTENER_USE_LEGACY_REPORTING_NAME = "useLegacyReportingName";
+
+
+    private Constants() {
+
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
new file mode 100644
index 0000000..cfa01d4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
@@ -0,0 +1,143 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Commandline;
+import org.apache.tools.ant.types.CommandlineJava;
+import org.apache.tools.ant.types.Environment;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.PropertySet;
+
+/**
+ * Represents the {@code fork} element within test definitions of the
+ * {@code junitlauncher} task
+ */
+public class ForkDefinition {
+
+    private static final String STANDALONE_LAUNCHER_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.StandaloneLauncher";
+
+    private boolean includeAntRuntimeLibraries = true;
+    private boolean includeJUnitPlatformLibraries = true;
+
+    private final CommandlineJava commandLineJava;
+    private final Environment env = new Environment();
+
+    private String dir;
+    private long timeout = -1;
+
+    ForkDefinition() {
+        this.commandLineJava = new CommandlineJava();
+    }
+
+    public void setDir(final String dir) {
+        this.dir = dir;
+    }
+
+    String getDir() {
+        return this.dir;
+    }
+
+    public void setTimeout(final long timeout) {
+        this.timeout = timeout;
+    }
+
+    long getTimeout() {
+        return this.timeout;
+    }
+
+    public void setIncludeJUnitPlatformLibraries(final boolean include) {
+        this.includeJUnitPlatformLibraries = include;
+    }
+
+    public void setIncludeAntRuntimeLibraries(final boolean include) {
+        this.includeAntRuntimeLibraries = include;
+    }
+
+    public Commandline.Argument createJvmArg() {
+        return this.commandLineJava.createVmArgument();
+    }
+
+    public void addConfiguredSysProperty(final Environment.Variable sysProp) {
+        // validate that key/value are present
+        sysProp.validate();
+        this.commandLineJava.addSysproperty(sysProp);
+    }
+
+    public void addConfiguredSysPropertySet(final PropertySet propertySet) {
+        this.commandLineJava.addSyspropertyset(propertySet);
+    }
+
+    public void addConfiguredEnv(final Environment.Variable var) {
+        this.env.addVariable(var);
+    }
+
+    public void addConfiguredModulePath(final Path modulePath) {
+        this.commandLineJava.createModulepath(modulePath.getProject()).add(modulePath);
+    }
+
+    public void addConfiguredUpgradeModulePath(final Path upgradeModulePath) {
+        this.commandLineJava.createUpgrademodulepath(upgradeModulePath.getProject()).add(upgradeModulePath);
+    }
+
+    Environment getEnv() {
+        return this.env;
+    }
+
+    /**
+     * Generates a new {@link CommandlineJava} constructed out of the configurations set on this
+     * {@link ForkDefinition}
+     *
+     * @param task The junitlaunchertask for which this is a fork definition
+     * @return
+     */
+    CommandlineJava generateCommandLine(final JUnitLauncherTask task) {
+        final CommandlineJava cmdLine;
+        try {
+            cmdLine = (CommandlineJava) this.commandLineJava.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new BuildException(e);
+        }
+        cmdLine.setClassname(STANDALONE_LAUNCHER_CLASS_NAME);
+        // VM arguments
+        final Project project = task.getProject();
+        final ClassLoader taskClassLoader = task.getClass().getClassLoader();
+        // Ant runtime classes
+        if (this.includeAntRuntimeLibraries) {
+            final Path antRuntimeResources = new Path(project);
+            JUnitLauncherClassPathUtil.addAntRuntimeResourceLocations(antRuntimeResources, taskClassLoader);
+            final Path classPath = cmdLine.createClasspath(project);
+            classPath.createPath().append(antRuntimeResources);
+        } else {
+            task.log("Excluding Ant runtime libraries from forked JVM classpath", Project.MSG_DEBUG);
+        }
+        // JUnit platform classes
+        if (this.includeJUnitPlatformLibraries) {
+            final Path junitPlatformResources = new Path(project);
+            JUnitLauncherClassPathUtil.addJUnitPlatformResourceLocations(junitPlatformResources, taskClassLoader);
+            final Path classPath = cmdLine.createClasspath(project);
+            classPath.createPath().append(junitPlatformResources);
+        } else {
+            task.log("Excluding JUnit platform libraries from forked JVM classpath", Project.MSG_DEBUG);
+        }
+        return cmdLine;
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherClassPathUtil.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherClassPathUtil.java
new file mode 100644
index 0000000..82ba0d0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherClassPathUtil.java
@@ -0,0 +1,76 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.launch.AntMain;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.LoaderUtils;
+
+import java.io.File;
+
+/**
+ *
+ */
+final class JUnitLauncherClassPathUtil {
+
+    private static final String RESOURCE_IN_PLATFORM_ENGINE = "org/junit/platform/engine/TestEngine.class";
+    private static final String RESOURCE_IN_PLATFORM_LAUNCHER = "org/junit/platform/launcher/core/LauncherFactory.class";
+    private static final String RESOURCE_IN_PLATFORM_COMMON = "org/junit/platform/commons/annotation/Testable.class";
+    private static final String RESOURCE_NAME_LAUNCHER_SUPPORT = "org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.class";
+
+
+    static void addAntRuntimeResourceLocations(final Path path, final ClassLoader classLoader) {
+        addResourceLocationToPath(path, classLoader, toResourceName(AntMain.class));
+        addResourceLocationToPath(path, classLoader, toResourceName(Task.class));
+        addResourceLocationToPath(path, classLoader, RESOURCE_NAME_LAUNCHER_SUPPORT);
+    }
+
+    static void addLauncherSupportResourceLocation(final Path path, final ClassLoader classLoader) {
+        addResourceLocationToPath(path, classLoader, RESOURCE_NAME_LAUNCHER_SUPPORT);
+    }
+
+    static void addJUnitPlatformResourceLocations(final Path path, final ClassLoader classLoader) {
+        // platform-engine
+        addResourceLocationToPath(path, classLoader, RESOURCE_IN_PLATFORM_ENGINE);
+        // platform-launcher
+        addResourceLocationToPath(path, classLoader, RESOURCE_IN_PLATFORM_LAUNCHER);
+        // platform-commons
+        addResourceLocationToPath(path, classLoader, RESOURCE_IN_PLATFORM_COMMON);
+    }
+
+    static boolean addResourceLocationToPath(final Path path, final ClassLoader classLoader, final String resource) {
+        final File f = LoaderUtils.getResourceSource(classLoader, resource);
+        if (f == null) {
+            return false;
+        }
+        path.createPath().setLocation(f);
+        return true;
+    }
+
+    static boolean hasJUnitPlatformResources(final ClassLoader cl) {
+        final File f = LoaderUtils.getResourceSource(cl, RESOURCE_IN_PLATFORM_ENGINE);
+        return f != null;
+    }
+
+    private static String toResourceName(final Class klass) {
+        final String name = klass.getName();
+        return name.replaceAll("\\.", "/") + ".class";
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
new file mode 100644
index 0000000..dbe8a1f
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
@@ -0,0 +1,494 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Execute;
+import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
+import org.apache.tools.ant.taskdefs.LogOutputStream;
+import org.apache.tools.ant.taskdefs.PumpStreamHandler;
+import org.apache.tools.ant.types.CommandlineJava;
+import org.apache.tools.ant.types.Environment;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileUtils;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_TAGS;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_INCLUDE_TAGS;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_PRINT_SUMMARY;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LAUNCH_DEF;
+
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which the JUnit platform launcher
+ * APIs were introduced.
+ * <p>
+ * This task in itself doesn't run the JUnit tests, instead the sole responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on this Ant task.
+ * </p>
+ * <p>
+ * Furthermore, this task allows users control over which classes to select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see <a href="https://junit.org/junit5/">JUnit 5 documentation</a>
+ */
+public class JUnitLauncherTask extends Task {
+
+    private static final String LAUNCHER_SUPPORT_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.LauncherSupport";
+    private static final String IN_VM_TEST_EXECUTION_CONTEXT_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.InVMExecution";
+    private static final String TEST_EXECUTION_CONTEXT_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.TestExecutionContext";
+
+    private Path classPath;
+    private boolean haltOnFailure;
+    private String failureProperty;
+    private boolean printSummary;
+    private final List<TestDefinition> tests = new ArrayList<>();
+    private final List<ListenerDefinition> listeners = new ArrayList<>();
+    private List<String> includeTags = new ArrayList<>();
+    private List<String> excludeTags = new ArrayList<>();
+
+    public JUnitLauncherTask() {
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (this.tests.isEmpty()) {
+            return;
+        }
+        final Project project = getProject();
+        for (final TestDefinition test : this.tests) {
+            if (!test.shouldRun(project)) {
+                log("Excluding test " + test + " since it's considered not to run " +
+                        "in context of project " + project, Project.MSG_DEBUG);
+                continue;
+            }
+            if (test.getForkDefinition() != null) {
+                forkTest(test);
+            } else {
+                launchViaReflection(new InVMLaunch(Collections.singletonList(test)));
+            }
+        }
+    }
+
+    /**
+     * Adds the {@link Path} to the classpath which will be used for execution of the tests
+     *
+     * @param path The classpath
+     */
+    public void addConfiguredClassPath(final Path path) {
+        if (this.classPath == null) {
+            // create a "wrapper" path which can hold on to multiple
+            // paths that get passed to this method (if at all the task in the build is
+            // configured with multiple classpaht elements)
+            this.classPath = new Path(getProject());
+        }
+        this.classPath.add(path);
+    }
+
+    /**
+     * Adds a {@link SingleTestClass} that will be passed on to the underlying JUnit platform
+     * for possible execution of the test
+     *
+     * @param test The test
+     */
+    public void addConfiguredTest(final SingleTestClass test) {
+        this.preConfigure(test);
+        this.tests.add(test);
+    }
+
+    /**
+     * Adds {@link TestClasses} that will be passed on to the underlying JUnit platform for
+     * possible execution of the tests
+     *
+     * @param testClasses The test classes
+     */
+    public void addConfiguredTestClasses(final TestClasses testClasses) {
+        this.preConfigure(testClasses);
+        this.tests.add(testClasses);
+    }
+
+    /**
+     * Adds a {@link ListenerDefinition listener} which will be enrolled for listening to test
+     * execution events
+     *
+     * @param listener The listener
+     */
+    public void addConfiguredListener(final ListenerDefinition listener) {
+        this.listeners.add(listener);
+    }
+
+    public void setHaltonfailure(final boolean haltonfailure) {
+        this.haltOnFailure = haltonfailure;
+    }
+
+    public void setFailureProperty(final String failureProperty) {
+        this.failureProperty = failureProperty;
+    }
+
+    public void setPrintSummary(final boolean printSummary) {
+        this.printSummary = printSummary;
+    }
+
+    /**
+     * Tags to include. Will trim each tag.
+     *
+     * @param includes comma separated list of tags to include while running the tests.
+     * @since Ant 1.10.7
+     */
+    public void setIncludeTags(final String includes) {
+        final StringTokenizer tokens = new StringTokenizer(includes, ",");
+        while (tokens.hasMoreTokens()) {
+            includeTags.add(tokens.nextToken().trim());
+        }
+    }
+
+    /**
+     * Tags to exclude. Will trim each tag.
+     *
+     * @param excludes comma separated list of tags to exclude while running the tests.
+     * @since Ant 1.10.7
+     */
+    public void setExcludeTags(final String excludes) {
+        final StringTokenizer tokens = new StringTokenizer(excludes, ",");
+        while (tokens.hasMoreTokens()) {
+            excludeTags.add(tokens.nextToken().trim());
+        }
+    }
+
+    private void preConfigure(final TestDefinition test) {
+        if (test.getHaltOnFailure() == null) {
+            test.setHaltOnFailure(this.haltOnFailure);
+        }
+        if (test.getFailureProperty() == null) {
+            test.setFailureProperty(this.failureProperty);
+        }
+    }
+
+    private void launchViaReflection(final InVMLaunch launchDefinition) {
+        final ClassLoader cl = launchDefinition.getClassLoader();
+        // instantiate a new TestExecutionContext instance using the launch definition's classloader
+        final Class<?> testExecutionCtxClass;
+        final Object testExecutionCtx;
+        try {
+            testExecutionCtxClass = Class.forName(TEST_EXECUTION_CONTEXT_CLASS_NAME, false, cl);
+            final Class<?> klass = Class.forName(IN_VM_TEST_EXECUTION_CONTEXT_CLASS_NAME, false, cl);
+            testExecutionCtx = klass.getConstructor(JUnitLauncherTask.class).newInstance(this);
+        } catch (Exception e) {
+            throw new BuildException("Failed to create a test execution context for in-vm tests", e);
+        }
+        // instantiate a new LauncherSupport instance using the launch definition's ClassLoader
+        try {
+            final Class<?> klass = Class.forName(LAUNCHER_SUPPORT_CLASS_NAME, false, cl);
+            final Object launcherSupport = klass.getConstructor(LaunchDefinition.class, testExecutionCtxClass)
+                    .newInstance(launchDefinition, testExecutionCtx);
+            klass.getMethod("launch").invoke(launcherSupport);
+        } catch (Exception e) {
+            throw new BuildException("Failed to launch in-vm tests", e);
+        }
+    }
+
+    private java.nio.file.Path dumpProjectProperties() throws IOException {
+        final java.nio.file.Path propsPath = FileUtils.getFileUtils()
+            .createTempFile(getProject(), null, "properties", null, true, true)
+            .toPath();
+        final Hashtable<String, Object> props = this.getProject().getProperties();
+        final Properties projProperties = new Properties();
+        projProperties.putAll(props);
+        try (final OutputStream os = Files.newOutputStream(propsPath)) {
+            // TODO: Is it always UTF-8?
+            projProperties.store(os, StandardCharsets.UTF_8.name());
+        }
+        return propsPath;
+    }
+
+    private void forkTest(final TestDefinition test) {
+        // create launch command
+        final ForkDefinition forkDefinition = test.getForkDefinition();
+        final CommandlineJava commandlineJava = forkDefinition.generateCommandLine(this);
+        if (this.classPath != null) {
+            commandlineJava.createClasspath(getProject()).createPath().append(this.classPath);
+        }
+        final java.nio.file.Path projectPropsPath;
+        try {
+            projectPropsPath = dumpProjectProperties();
+        } catch (IOException e) {
+            throw new BuildException("Could not create the necessary properties file while forking a process" +
+                    " for a test", e);
+        }
+        // --properties <path-to-properties-file>
+        commandlineJava.createArgument().setValue(Constants.ARG_PROPERTIES);
+        commandlineJava.createArgument().setValue(projectPropsPath.toAbsolutePath().toString());
+
+        final java.nio.file.Path launchDefXmlPath = newLaunchDefinitionXml();
+        try (final OutputStream os = Files.newOutputStream(launchDefXmlPath)) {
+            final XMLStreamWriter writer = XMLOutputFactory.newFactory().createXMLStreamWriter(os, "UTF-8");
+            try {
+                writer.writeStartDocument();
+                writer.writeStartElement(LD_XML_ELM_LAUNCH_DEF);
+                if (this.printSummary) {
+                    writer.writeAttribute(LD_XML_ATTR_PRINT_SUMMARY, "true");
+                }
+                if (this.haltOnFailure) {
+                    writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, "true");
+                }
+                if (this.includeTags.size() > 0) {
+                    writer.writeAttribute(LD_XML_ATTR_INCLUDE_TAGS, commaSeparatedListElements(includeTags));
+                }
+                if (this.excludeTags.size() > 0) {
+                    writer.writeAttribute(LD_XML_ATTR_EXCLUDE_TAGS, commaSeparatedListElements(excludeTags));
+                }
+                // task level listeners
+                for (final ListenerDefinition listenerDef : this.listeners) {
+                    if (!listenerDef.shouldUse(getProject())) {
+                        continue;
+                    }
+                    // construct the listener definition argument
+                    listenerDef.toForkedRepresentation(writer);
+                }
+                // test definition as XML
+                test.toForkedRepresentation(this, writer);
+                writer.writeEndElement();
+                writer.writeEndDocument();
+            } finally {
+                writer.close();
+            }
+        } catch (Exception e) {
+            throw new BuildException("Failed to construct command line for test", e);
+        }
+        // --launch-definition <xml-file-path>
+        commandlineJava.createArgument().setValue(Constants.ARG_LAUNCH_DEFINITION);
+        commandlineJava.createArgument().setValue(launchDefXmlPath.toAbsolutePath().toString());
+
+        // launch the process and wait for process to complete
+        final int exitCode = executeForkedTest(forkDefinition, commandlineJava);
+        switch (exitCode) {
+            case Constants.FORK_EXIT_CODE_SUCCESS: {
+                // success
+                break;
+            }
+            case Constants.FORK_EXIT_CODE_EXCEPTION: {
+                // process failed with some exception
+                throw new BuildException("Forked test(s) failed with an exception");
+            }
+            case Constants.FORK_EXIT_CODE_TESTS_FAILED: {
+                // test has failure(s)
+                try {
+                    if (test.getFailureProperty() != null) {
+                        // if there are test failures and the test is configured to set a property in case
+                        // of failure, then set the property to true
+                        this.getProject().setNewProperty(test.getFailureProperty(), "true");
+                    }
+                } finally {
+                    if (test.isHaltOnFailure()) {
+                        // if the test is configured to halt on test failures, throw a build error
+                        final String errorMessage;
+                        if (test instanceof NamedTest) {
+                            errorMessage = "Test " + ((NamedTest) test).getName() + " has failure(s)";
+                        } else {
+                            errorMessage = "Some test(s) have failure(s)";
+                        }
+                        throw new BuildException(errorMessage);
+                    }
+                }
+                break;
+            }
+            case Constants.FORK_EXIT_CODE_TIMED_OUT: {
+                throw new BuildException(new TimeoutException("Forked test(s) timed out"));
+            }
+        }
+    }
+
+    private static String commaSeparatedListElements(final List<String> stringList) {
+        return stringList.stream()
+                .map(Object::toString)
+                .collect(Collectors.joining(", "));
+    }
+
+    private int executeForkedTest(final ForkDefinition forkDefinition, final CommandlineJava commandlineJava) {
+        final LogOutputStream outStream = new LogOutputStream(this, Project.MSG_INFO);
+        final LogOutputStream errStream = new LogOutputStream(this, Project.MSG_WARN);
+        final ExecuteWatchdog watchdog = forkDefinition.getTimeout() > 0
+                ? createExecuteWatchdog(forkDefinition.getTimeout()) : null;
+        final Execute execute = new Execute(new PumpStreamHandler(outStream, errStream), watchdog);
+        execute.setCommandline(commandlineJava.getCommandline());
+        execute.setAntRun(getProject());
+        if (forkDefinition.getDir() != null) {
+            execute.setWorkingDirectory(Paths.get(forkDefinition.getDir()).toFile());
+        }
+        final Environment env = forkDefinition.getEnv();
+        if (env != null && env.getVariables() != null) {
+            execute.setEnvironment(env.getVariables());
+        }
+        log(commandlineJava.describeCommand(), Project.MSG_VERBOSE);
+        int exitCode;
+        try {
+            exitCode = execute.execute();
+        } catch (IOException e) {
+            throw new BuildException("Process fork failed", e, getLocation());
+        }
+        return (watchdog != null && watchdog.killedProcess()) ? Constants.FORK_EXIT_CODE_TIMED_OUT : exitCode;
+    }
+
+    protected ExecuteWatchdog createExecuteWatchdog(long timeout) {
+        return new ExecuteWatchdog(timeout);
+    }
+
+    private java.nio.file.Path newLaunchDefinitionXml() {
+        return FileUtils.getFileUtils()
+            .createTempFile(getProject(), null, ".xml", null, true, true)
+            .toPath();
+    }
+
+    private final class InVMLaunch implements LaunchDefinition {
+
+        private final List<TestDefinition> inVMTests;
+        private final ClassLoader executionCL;
+
+        private InVMLaunch(final List<TestDefinition> inVMTests) {
+            this.inVMTests = inVMTests;
+            this.executionCL = createInVMExecutionClassLoader();
+        }
+
+        @Override
+        public List<TestDefinition> getTests() {
+            return this.inVMTests;
+        }
+
+        @Override
+        public List<ListenerDefinition> getListeners() {
+            return listeners;
+        }
+
+        @Override
+        public boolean isPrintSummary() {
+            return printSummary;
+        }
+
+        @Override
+        public boolean isHaltOnFailure() {
+            return haltOnFailure;
+        }
+
+        @Override
+        public List<String> getIncludeTags() {
+            return includeTags;
+        }
+
+        @Override
+        public List<String> getExcludeTags() {
+            return excludeTags;
+        }
+
+        @Override
+        public ClassLoader getClassLoader() {
+            return this.executionCL;
+        }
+
+        private ClassLoader createInVMExecutionClassLoader() {
+            final Path taskConfiguredClassPath = JUnitLauncherTask.this.classPath;
+            if (taskConfiguredClassPath == null) {
+                // no specific classpath configured for the task, so use the classloader
+                // of this task
+                return JUnitLauncherTask.class.getClassLoader();
+            }
+            // there's a classpath configured for the task.
+            // we first check if the Ant runtime classpath has JUnit platform classes.
+            // - if it does, then we use the Ant runtime classpath plus the task's configured classpath
+            // with the traditional parent first loading.
+            // - else (i.e. Ant runtime classpath doesn't have JUnit platform classes), then we
+            // expect/assume the task's configured classpath to have the JUnit platform classes and we
+            // then create a "overriding" classloader which prefers certain resources (specifically the classes
+            // from org.apache.tools.ant.taskdefs.optional.junitlauncher package), from the task's
+            // classpath, even if the Ant's runtime classpath has those resources.
+            if (JUnitLauncherClassPathUtil.hasJUnitPlatformResources(JUnitLauncherTask.class.getClassLoader())) {
+                return new AntClassLoader(JUnitLauncherTask.class.getClassLoader(), getProject(), taskConfiguredClassPath, true);
+            }
+            final Path cp = new Path(getProject());
+            cp.add(taskConfiguredClassPath);
+            // add the Ant runtime resources to this path
+            JUnitLauncherClassPathUtil.addLauncherSupportResourceLocation(cp, JUnitLauncherTask.class.getClassLoader());
+            return new TaskConfiguredPathClassLoader(JUnitLauncherTask.class.getClassLoader(), cp, getProject());
+        }
+    }
+
+    /**
+     * A {@link ClassLoader}, very similar to the {@link org.apache.tools.ant.util.SplitClassLoader},
+     * which uses the {@link #TaskConfiguredPathClassLoader(ClassLoader, Path, Project) configured Path}
+     * to load a class, if the class belongs to the {@code org.apache.tools.ant.taskdefs.optional.junitlauncher}
+     * package.
+     * <p>
+     * While looking for classes belonging to the {@code org.apache.tools.ant.taskdefs.optional.junitlauncher}
+     * package, this classloader completely ignores Ant runtime classpath, even if that classpath has
+     * those classes. This allows the users of this classloader to use a custom location and thus more control over
+     * where these classes reside, when running the {@code junitlauncher} task
+     */
+    private final class TaskConfiguredPathClassLoader extends AntClassLoader {
+
+        /**
+         * @param parent  ClassLoader
+         * @param path    Path
+         * @param project Project
+         */
+        private TaskConfiguredPathClassLoader(ClassLoader parent, Path path, Project project) {
+            super(parent, project, path, true);
+        }
+
+        // forceLoadClass is not convenient here since it would not
+        // properly deal with inner classes of these classes.
+        @Override
+        protected synchronized Class<?> loadClass(String classname, boolean resolve)
+                throws ClassNotFoundException {
+            Class<?> theClass = findLoadedClass(classname);
+            if (theClass != null) {
+                return theClass;
+            }
+            final String packageName = classname.contains(".") ? classname.substring(0, classname.lastIndexOf('.'))
+                    : "";
+            if (packageName.equals("org.apache.tools.ant.taskdefs.optional.junitlauncher")) {
+                theClass = findClass(classname);
+                if (resolve) {
+                    resolveClass(theClass);
+                }
+                return theClass;
+            }
+            return super.loadClass(classname, resolve);
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/LaunchDefinition.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/LaunchDefinition.java
new file mode 100644
index 0000000..fe6e07d
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/LaunchDefinition.java
@@ -0,0 +1,69 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import java.util.List;
+
+/**
+ * Defines the necessary context for launching the JUnit platform for running
+ * tests.
+ */
+public interface LaunchDefinition {
+
+    /**
+     * @return Returns the {@link TestDefinition tests} that have to be launched
+     */
+    List<TestDefinition> getTests();
+
+    /**
+     * @return Returns the default {@link ListenerDefinition listeners} that will be used
+     * for the tests, if the {@link #getTests() tests} themselves don't specify any
+     */
+    List<ListenerDefinition> getListeners();
+
+    /**
+     * @return Returns true if a summary needs to be printed out after the execution of the
+     * tests. False otherwise.
+     */
+    boolean isPrintSummary();
+
+    /**
+     * @return Returns true if any remaining tests launch need to be stopped if any test execution
+     * failed. False otherwise.
+     */
+    boolean isHaltOnFailure();
+
+    /**
+     * @return Returns the {@link ClassLoader} that has to be used for launching and execution of the
+     * tests
+     */
+    ClassLoader getClassLoader();
+
+    /**
+     * @return Returns the list of tags which will be used to evaluate tests that need to be included
+     * in the test execution
+     */
+    List<String> getIncludeTags();
+
+    /**
+     * @return Returns the list of tags which will be used to evaluate tests that need to be excluded
+     * from the test execution
+     */
+    List<String> getExcludeTags();
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ListenerDefinition.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ListenerDefinition.java
new file mode 100644
index 0000000..e661fd3
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ListenerDefinition.java
@@ -0,0 +1,255 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.PropertyHelper;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_CLASS_NAME;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_LISTENER_EXTENSION;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_LISTENER_RESULT_FILE;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_LISTENER_USE_LEGACY_REPORTING_NAME;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_SEND_SYS_ERR;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_SEND_SYS_OUT;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LISTENER;
+
+/**
+ * Represents the {@code &lt;listener&gt;} element within the {@code &lt;junitlauncher&gt;}
+ * task
+ */
+public class ListenerDefinition {
+
+
+    private static final String LEGACY_PLAIN = "legacy-plain";
+    private static final String LEGACY_BRIEF = "legacy-brief";
+    private static final String LEGACY_XML = "legacy-xml";
+
+    private String ifProperty;
+    private String unlessProperty;
+    private String className;
+    private String resultFile;
+    private String extension = "txt";
+    private boolean sendSysOut;
+    private boolean sendSysErr;
+    private String outputDir;
+    private boolean useLegacyReportingName = true;
+
+    public ListenerDefinition() {
+
+    }
+
+    public void setClassName(final String className) {
+        this.className = className;
+    }
+
+    public String getClassName() {
+        return this.className;
+    }
+
+    String getIfProperty() {
+        return ifProperty;
+    }
+
+    public void setIf(final String ifProperty) {
+        this.ifProperty = ifProperty;
+    }
+
+    String getUnlessProperty() {
+        return unlessProperty;
+    }
+
+    public void setUnless(final String unlessProperty) {
+        this.unlessProperty = unlessProperty;
+    }
+
+    public void setType(final ListenerType type) {
+        switch (type.getValue()) {
+            case LEGACY_PLAIN: {
+                this.setClassName("org.apache.tools.ant.taskdefs.optional.junitlauncher.LegacyPlainResultFormatter");
+                break;
+            }
+            case LEGACY_BRIEF: {
+                this.setClassName("org.apache.tools.ant.taskdefs.optional.junitlauncher.LegacyBriefResultFormatter");
+                break;
+            }
+            case LEGACY_XML: {
+                this.setClassName("org.apache.tools.ant.taskdefs.optional.junitlauncher.LegacyXmlResultFormatter");
+                this.setExtension("xml");
+                break;
+            }
+        }
+    }
+
+    public void setResultFile(final String filename) {
+        this.resultFile = filename;
+    }
+
+    public String getResultFile() {
+        return this.resultFile;
+    }
+
+    /**
+     * Sets the output file extension for this listener.
+     *
+     * @param extension file extension to use
+     * @since Ant 1.10.13
+     */
+    public void setExtension(String extension) {
+        this.extension = extension;
+    }
+
+    public String getExtension() {
+        return extension;
+    }
+
+    public void setSendSysOut(final boolean sendSysOut) {
+        this.sendSysOut = sendSysOut;
+    }
+
+    public boolean shouldSendSysOut() {
+        return this.sendSysOut;
+    }
+
+    public void setSendSysErr(final boolean sendSysErr) {
+        this.sendSysErr = sendSysErr;
+    }
+
+    public boolean shouldSendSysErr() {
+        return this.sendSysErr;
+    }
+
+    /**
+     * Sets the output directory for this listener
+     *
+     * @param dir Path to the output directory
+     * @since Ant 1.10.6
+     */
+    public void setOutputDir(final String dir) {
+        this.outputDir = dir;
+    }
+
+    public String getOutputDir() {
+        return this.outputDir;
+    }
+
+    /**
+     *
+     * @return Returns {@code true} if legacy reporting name (JUnit 4 style) is to be used.
+     *         Else returns {@code false}.
+     * @since Ant 1.10.10
+     */
+    public boolean isUseLegacyReportingName() {
+        return useLegacyReportingName;
+    }
+
+    /**
+     * Set the test identifier reporting style
+     * @param useLegacyReportingName {@code true} if legacy reporting name (JUnit 4 style) is to
+     *                               be used. Else {@code false}.
+     * @since Ant 1.10.10
+     */
+    public void setUseLegacyReportingName(final boolean useLegacyReportingName) {
+        this.useLegacyReportingName = useLegacyReportingName;
+    }
+
+    public boolean shouldUse(final Project project) {
+        final PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(project);
+        return propertyHelper.testIfCondition(this.ifProperty) && propertyHelper.testUnlessCondition(this.unlessProperty);
+    }
+
+    /**
+     * defines available listener types.
+     */
+    public static class ListenerType extends EnumeratedAttribute {
+
+        /** {@inheritDoc}. */
+        @Override
+        public String[] getValues() {
+            return new String[]{LEGACY_PLAIN, LEGACY_BRIEF, LEGACY_XML};
+        }
+    }
+
+    void toForkedRepresentation(final XMLStreamWriter writer) throws XMLStreamException {
+        writer.writeStartElement(LD_XML_ELM_LISTENER);
+        writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, this.className);
+        writer.writeAttribute(LD_XML_ATTR_SEND_SYS_ERR, Boolean.toString(this.sendSysErr));
+        writer.writeAttribute(LD_XML_ATTR_SEND_SYS_OUT, Boolean.toString(this.sendSysOut));
+        writer.writeAttribute(LD_XML_ATTR_LISTENER_USE_LEGACY_REPORTING_NAME, Boolean.toString(this.useLegacyReportingName));
+        if (this.outputDir != null) {
+            writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, this.outputDir);
+        }
+        if (this.resultFile != null) {
+            writer.writeAttribute(LD_XML_ATTR_LISTENER_RESULT_FILE, this.resultFile);
+        }
+        if (this.extension != null) {
+            writer.writeAttribute(LD_XML_ATTR_LISTENER_EXTENSION, this.extension);
+        }
+        writer.writeEndElement();
+    }
+
+    public static ListenerDefinition fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException {
+        reader.require(XMLStreamConstants.START_ELEMENT, null, LD_XML_ELM_LISTENER);
+        final ListenerDefinition listenerDef = new ListenerDefinition();
+        final String className = requireAttributeValue(reader, LD_XML_ATTR_CLASS_NAME);
+        listenerDef.setClassName(className);
+        final String sendSysErr = reader.getAttributeValue(null, LD_XML_ATTR_SEND_SYS_ERR);
+        if (sendSysErr != null) {
+            listenerDef.setSendSysErr(Boolean.parseBoolean(sendSysErr));
+        }
+        final String sendSysOut = reader.getAttributeValue(null, LD_XML_ATTR_SEND_SYS_OUT);
+        if (sendSysOut != null) {
+            listenerDef.setSendSysOut(Boolean.parseBoolean(sendSysOut));
+        }
+        final String outputDir = reader.getAttributeValue(null, LD_XML_ATTR_OUTPUT_DIRECTORY);
+        if (outputDir != null) {
+            listenerDef.setOutputDir(outputDir);
+        }
+        final String resultFile = reader.getAttributeValue(null, LD_XML_ATTR_LISTENER_RESULT_FILE);
+        if (resultFile != null) {
+            listenerDef.setResultFile(resultFile);
+        }
+        final String extension = reader.getAttributeValue(null, LD_XML_ATTR_LISTENER_EXTENSION);
+        if (extension != null) {
+            listenerDef.setExtension(extension);
+        }
+        final String useLegacyReportingName = reader.getAttributeValue(null,
+                LD_XML_ATTR_LISTENER_USE_LEGACY_REPORTING_NAME);
+        if (useLegacyReportingName != null) {
+            listenerDef.setUseLegacyReportingName(Boolean.parseBoolean(useLegacyReportingName));
+        }
+        reader.nextTag();
+        reader.require(XMLStreamConstants.END_ELEMENT, null, LD_XML_ELM_LISTENER);
+        return listenerDef;
+    }
+
+    private static String requireAttributeValue(final XMLStreamReader reader, final String attrName) throws XMLStreamException {
+        final String val = reader.getAttributeValue(null, attrName);
+        if (val != null) {
+            return val;
+        }
+        throw new XMLStreamException("Attribute " + attrName + " is missing at " + reader.getLocation());
+    }
+
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/NamedTest.java
similarity index 72%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/NamedTest.java
index 9d6fcba..ae661fe 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/NamedTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,15 @@
  *  limitations under the License.
  *
  */
+package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined;
+
 /**
+ * A test that has a name associated with it
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+public interface NamedTest {
+
+    /**
+     * @return Returns the name of the test
+     */
+    String getName();
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
new file mode 100644
index 0000000..25961b8
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
@@ -0,0 +1,171 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_CLASS_NAME;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_ENGINES;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_INCLUDE_ENGINES;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_METHODS;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST;
+
+/**
+ * Represents the single {@code test} (class) that's configured to be launched by the {@link JUnitLauncherTask}
+ */
+public class SingleTestClass extends TestDefinition implements NamedTest {
+
+    private String testClass;
+    private Set<String> testMethods;
+
+    public SingleTestClass() {
+
+    }
+
+    public void setName(final String test) {
+        if (test == null || test.trim().isEmpty()) {
+            throw new IllegalArgumentException("Test name cannot be null or empty string");
+        }
+        this.testClass = test;
+    }
+
+    public String getName() {
+        return this.testClass;
+    }
+
+    public void setMethods(final String methods) {
+        // parse the comma separated set of methods
+        if (methods == null || methods.trim().isEmpty()) {
+            this.testMethods = Collections.emptySet();
+            return;
+        }
+        final StringTokenizer tokenizer = new StringTokenizer(methods, ",");
+        if (!tokenizer.hasMoreTokens()) {
+            this.testMethods = Collections.emptySet();
+            return;
+        }
+        // maintain specified ordering
+        this.testMethods = new LinkedHashSet<>();
+        while (tokenizer.hasMoreTokens()) {
+            final String method = tokenizer.nextToken().trim();
+            if (method.isEmpty()) {
+                continue;
+            }
+            this.testMethods.add(method);
+        }
+    }
+
+    boolean hasMethodsSpecified() {
+        return this.testMethods != null && !this.testMethods.isEmpty();
+    }
+
+    public String[] getMethods() {
+        if (!hasMethodsSpecified()) {
+            return null;
+        }
+        return this.testMethods.toArray(new String[0]);
+    }
+
+    @Override
+    protected void toForkedRepresentation(final JUnitLauncherTask task, final XMLStreamWriter writer) throws XMLStreamException {
+        writer.writeStartElement(LD_XML_ELM_TEST);
+        writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, testClass);
+        if (testMethods != null) {
+            final StringBuilder sb = new StringBuilder();
+            for (final String method : testMethods) {
+                if (sb.length() != 0) {
+                    sb.append(",");
+                }
+                sb.append(method);
+            }
+            writer.writeAttribute(LD_XML_ATTR_METHODS, sb.toString());
+        }
+        if (haltOnFailure != null) {
+            writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, haltOnFailure.toString());
+        }
+        if (outputDir != null) {
+            writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, outputDir);
+        }
+        if (includeEngines != null) {
+            writer.writeAttribute(LD_XML_ATTR_INCLUDE_ENGINES, includeEngines);
+        }
+        if (excludeEngines != null) {
+            writer.writeAttribute(LD_XML_ATTR_EXCLUDE_ENGINES, excludeEngines);
+        }
+        // listeners for this test
+        if (listeners != null) {
+            for (final ListenerDefinition listenerDef : getListeners()) {
+                if (!listenerDef.shouldUse(task.getProject())) {
+                    // not applicable
+                    continue;
+                }
+                listenerDef.toForkedRepresentation(writer);
+            }
+        }
+        writer.writeEndElement();
+    }
+
+    public static TestDefinition fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException {
+        reader.require(XMLStreamConstants.START_ELEMENT, null, LD_XML_ELM_TEST);
+        final SingleTestClass testDefinition = new SingleTestClass();
+        final String testClassName = requireAttributeValue(reader, LD_XML_ATTR_CLASS_NAME);
+        testDefinition.setName(testClassName);
+        final String methodNames = reader.getAttributeValue(null, LD_XML_ATTR_METHODS);
+        if (methodNames != null) {
+            testDefinition.setMethods(methodNames);
+        }
+        final String halt = reader.getAttributeValue(null, LD_XML_ATTR_HALT_ON_FAILURE);
+        if (halt != null) {
+            testDefinition.setHaltOnFailure(Boolean.parseBoolean(halt));
+        }
+        final String outDir = reader.getAttributeValue(null, LD_XML_ATTR_OUTPUT_DIRECTORY);
+        if (outDir != null) {
+            testDefinition.setOutputDir(outDir);
+        }
+        final String includeEngs = reader.getAttributeValue(null, LD_XML_ATTR_INCLUDE_ENGINES);
+        if (includeEngs != null) {
+            testDefinition.setIncludeEngines(includeEngs);
+        }
+        final String excludeEngs = reader.getAttributeValue(null, LD_XML_ATTR_EXCLUDE_ENGINES);
+        if (excludeEngs != null) {
+            testDefinition.setExcludeEngines(excludeEngs);
+        }
+        while (reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
+            reader.require(XMLStreamConstants.START_ELEMENT, null, Constants.LD_XML_ELM_LISTENER);
+            testDefinition.addConfiguredListener(ListenerDefinition.fromForkedRepresentation(reader));
+        }
+        return testDefinition;
+    }
+
+    private static String requireAttributeValue(final XMLStreamReader reader, final String attrName) throws XMLStreamException {
+        final String val = reader.getAttributeValue(null, attrName);
+        if (val != null) {
+            return val;
+        }
+        throw new XMLStreamException("Attribute " + attrName + " is missing at " + reader.getLocation());
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
new file mode 100644
index 0000000..4286f44
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
@@ -0,0 +1,153 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.Resources;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_CLASS_NAME;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_ENGINES;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_INCLUDE_ENGINES;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST;
+import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST_CLASSES;
+
+/**
+ * Represents a {@code testclasses} that's configured to be launched by the {@link JUnitLauncherTask}
+ */
+public class TestClasses extends TestDefinition {
+
+    private final Resources resources = new Resources();
+
+    public TestClasses() {
+
+    }
+
+    public void add(final ResourceCollection resourceCollection) {
+        this.resources.add(resourceCollection);
+    }
+
+    public List<String> getTestClassNames() {
+        if (this.resources.isEmpty()) {
+            return Collections.emptyList();
+        }
+        final List<String> tests = new ArrayList<>();
+        for (final Resource resource : resources) {
+            if (!resource.isExists()) {
+                continue;
+            }
+            final String name = resource.getName();
+            // we only consider .class files
+            if (!name.endsWith(".class")) {
+                continue;
+            }
+            final String className = name.substring(0, name.lastIndexOf('.'));
+            tests.add(className.replace(File.separatorChar, '.').replace('/', '.').replace('\\', '.'));
+        }
+        return tests;
+    }
+
+    @Override
+    protected void toForkedRepresentation(final JUnitLauncherTask task, final XMLStreamWriter writer) throws XMLStreamException {
+        writer.writeStartElement(LD_XML_ELM_TEST_CLASSES);
+        // write out each test class
+        for (final String test : getTestClassNames()) {
+            writer.writeStartElement(LD_XML_ELM_TEST);
+            writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, test);
+            if (haltOnFailure != null) {
+                writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, haltOnFailure.toString());
+            }
+            if (outputDir != null) {
+                writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, outputDir);
+            }
+            if (includeEngines != null) {
+                writer.writeAttribute(LD_XML_ATTR_INCLUDE_ENGINES, includeEngines);
+            }
+            if (excludeEngines != null) {
+                writer.writeAttribute(LD_XML_ATTR_EXCLUDE_ENGINES, excludeEngines);
+            }
+            // listeners for this test
+            if (listeners != null) {
+                for (final ListenerDefinition listenerDef : getListeners()) {
+                    if (!listenerDef.shouldUse(task.getProject())) {
+                        // not applicable
+                        continue;
+                    }
+                    listenerDef.toForkedRepresentation(writer);
+                }
+            }
+            writer.writeEndElement();
+        }
+        writer.writeEndElement();
+    }
+
+    public static List<TestDefinition> fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException {
+        reader.require(XMLStreamConstants.START_ELEMENT, null, LD_XML_ELM_TEST_CLASSES);
+        final List<TestDefinition> testDefinitions = new ArrayList<>();
+        // read out as multiple SingleTestClass representations
+        while (reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
+            final SingleTestClass testDefinition = new SingleTestClass();
+            reader.require(XMLStreamConstants.START_ELEMENT, null, Constants.LD_XML_ELM_TEST);
+            final String testClassName = requireAttributeValue(reader, LD_XML_ATTR_CLASS_NAME);
+            testDefinition.setName(testClassName);
+            final String halt = reader.getAttributeValue(null, LD_XML_ATTR_HALT_ON_FAILURE);
+            if (halt != null) {
+                testDefinition.setHaltOnFailure(Boolean.parseBoolean(halt));
+            }
+            final String outDir = reader.getAttributeValue(null, LD_XML_ATTR_OUTPUT_DIRECTORY);
+            if (outDir != null) {
+                testDefinition.setOutputDir(outDir);
+            }
+            final String includeEngs = reader.getAttributeValue(null, LD_XML_ATTR_INCLUDE_ENGINES);
+            if (includeEngs != null) {
+                testDefinition.setIncludeEngines(includeEngs);
+            }
+            final String excludeEngs = reader.getAttributeValue(null, LD_XML_ATTR_EXCLUDE_ENGINES);
+            if (excludeEngs != null) {
+                testDefinition.setExcludeEngines(excludeEngs);
+            }
+            while (reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
+                reader.require(XMLStreamConstants.START_ELEMENT, null, Constants.LD_XML_ELM_LISTENER);
+                testDefinition.addConfiguredListener(ListenerDefinition.fromForkedRepresentation(reader));
+            }
+            reader.require(XMLStreamConstants.END_ELEMENT, null, Constants.LD_XML_ELM_TEST);
+            testDefinitions.add(testDefinition);
+        }
+        reader.require(XMLStreamConstants.END_ELEMENT, null, LD_XML_ELM_TEST_CLASSES);
+        return Collections.unmodifiableList(testDefinitions);
+    }
+
+    private static String requireAttributeValue(final XMLStreamReader reader, final String attrName) throws XMLStreamException {
+        final String val = reader.getAttributeValue(null, attrName);
+        if (val != null) {
+            return val;
+        }
+        throw new XMLStreamException("Attribute " + attrName + " is missing at " + reader.getLocation());
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
new file mode 100644
index 0000000..a3df6d5
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
@@ -0,0 +1,148 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher.confined;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.PropertyHelper;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Represents the configuration details of a test that needs to be launched by the {@link JUnitLauncherTask}
+ */
+public abstract class TestDefinition {
+
+    protected String ifProperty;
+    protected String unlessProperty;
+    protected Boolean haltOnFailure;
+    protected String failureProperty;
+    protected String outputDir;
+    protected String includeEngines;
+    protected String excludeEngines;
+    protected ForkDefinition forkDefinition;
+
+    protected List<ListenerDefinition> listeners = new ArrayList<>();
+
+    String getIfProperty() {
+        return ifProperty;
+    }
+
+    public void setIf(final String ifProperty) {
+        this.ifProperty = ifProperty;
+    }
+
+    String getUnlessProperty() {
+        return unlessProperty;
+    }
+
+    public void setUnless(final String unlessProperty) {
+        this.unlessProperty = unlessProperty;
+    }
+
+    public boolean isHaltOnFailure() {
+        return this.haltOnFailure != null && this.haltOnFailure;
+    }
+
+    Boolean getHaltOnFailure() {
+        return this.haltOnFailure;
+    }
+
+    public void setHaltOnFailure(final boolean haltonfailure) {
+        this.haltOnFailure = haltonfailure;
+    }
+
+    public String getFailureProperty() {
+        return failureProperty;
+    }
+
+    public void setFailureProperty(final String failureProperty) {
+        this.failureProperty = failureProperty;
+    }
+
+    public void addConfiguredListener(final ListenerDefinition listener) {
+        this.listeners.add(listener);
+    }
+
+    public List<ListenerDefinition> getListeners() {
+        return Collections.unmodifiableList(this.listeners);
+    }
+
+    public void setOutputDir(final String dir) {
+        this.outputDir = dir;
+    }
+
+    public String getOutputDir() {
+        return this.outputDir;
+    }
+
+    public ForkDefinition createFork() {
+        if (this.forkDefinition != null) {
+            throw new BuildException("Test definition cannot have more than one fork elements");
+        }
+        this.forkDefinition = new ForkDefinition();
+        return this.forkDefinition;
+    }
+
+    ForkDefinition getForkDefinition() {
+        return this.forkDefinition;
+    }
+
+    protected boolean shouldRun(final Project project) {
+        final PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(project);
+        return propertyHelper.testIfCondition(this.ifProperty) && propertyHelper.testUnlessCondition(this.unlessProperty);
+    }
+
+    public String[] getIncludeEngines() {
+        return includeEngines == null ? new String[0] : split(this.includeEngines, ",");
+    }
+
+    public void setIncludeEngines(final String includeEngines) {
+        this.includeEngines = includeEngines;
+    }
+
+    public String[] getExcludeEngines() {
+        return excludeEngines == null ? new String[0] : split(this.excludeEngines, ",");
+    }
+
+    public void setExcludeEngines(final String excludeEngines) {
+        this.excludeEngines = excludeEngines;
+    }
+
+    private static String[] split(final String value, final String delimiter) {
+        if (value == null) {
+            return new String[0];
+        }
+        final List<String> parts = new ArrayList<>();
+        for (final String part : value.split(delimiter)) {
+            if (part.trim().isEmpty()) {
+                // skip it
+                continue;
+            }
+            parts.add(part);
+        }
+        return parts.toArray(new String[0]);
+    }
+
+    protected abstract void toForkedRepresentation(JUnitLauncherTask task, XMLStreamWriter writer) throws XMLStreamException;
+
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/package-info.java
similarity index 61%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/package-info.java
index 9d6fcba..2be9779 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/package-info.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -16,10 +16,12 @@
  *
  */
 /**
+ * The classes/interfaces in this package <em>must not</em>
+ * have any compile time dependency on any of JUnit platform or
+ * engine classes/interfaces. They <em>must not</em> even have any
+ * compile time dependency on any classes/interfaces that belong to the
+ * {@code org.apache.tools.ant.taskdefs.optional.junitlauncher} package.
+ *
+ * @since Ant 1.10.6
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
-}
+package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined;
\ No newline at end of file
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/package-info.java
similarity index 62%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/package-info.java
index 9d6fcba..d02a77f 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/package-info.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -16,10 +16,13 @@
  *
  */
 /**
+ * The classes/interfaces in this package are allowed
+ * to have compile time dependency on JUnit platform classes/interfaces.
+ * Furthermore classes/interfaces in this package are also
+ * allowed to have compile time dependency on the
+ * {@link org.apache.tools.ant.taskdefs.optional.junitlauncher.confined}
+ * package
+ *
+ * @since Ant 1.10.6
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
-}
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
\ No newline at end of file
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..eba66e5 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,20 +20,18 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.nio.file.Files;
+import java.util.function.UnaryOperator;
 
 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;
 
 /**
  * Encapsulates the built-in Native2Ascii implementation.
@@ -44,23 +42,16 @@
 
     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 ? Native2AsciiUtils::ascii2native
+                : Native2AsciiUtils::native2ascii);
             return true;
         } catch (IOException ex) {
             throw new BuildException("Exception trying to translate data", ex);
@@ -69,11 +60,11 @@
 
     private BufferedReader getReader(File srcFile, String encoding,
                                      boolean reverse) throws IOException {
-        if (!reverse && encoding != null) {
-            return new BufferedReader(new InputStreamReader(
-                new FileInputStream(srcFile), encoding));
+        if (reverse || encoding == null) {
+            return new BufferedReader(new FileReader(srcFile));
         }
-        return new BufferedReader(new FileReader(srcFile));
+        return new BufferedReader(new InputStreamReader(
+            Files.newInputStream(srcFile.toPath()), encoding));
     }
 
     private Writer getWriter(File destFile, String encoding,
@@ -81,24 +72,19 @@
         if (!reverse) {
             encoding = "ASCII";
         }
-        if (encoding != null) {
-            return new BufferedWriter(
-                new OutputStreamWriter(new FileOutputStream(destFile),
-                                       encoding));
+        if (encoding == null) {
+            return new BufferedWriter(new FileWriter(destFile));
         }
-        return new BufferedWriter(new FileWriter(destFile));
+        return new BufferedWriter(
+            new OutputStreamWriter(Files.newOutputStream(destFile.toPath()),
+                                   encoding));
     }
 
     private void translate(BufferedReader input, Writer output,
-                           boolean reverse) throws IOException {
-        String line = null;
-        while ((line = input.readLine()) != null) {
-            if (!reverse) {
-                output.write(Native2AsciiUtils.native2ascii(line));
-            } else {
-                output.write(Native2AsciiUtils.ascii2native(line));
-            }
-            output.write(StringUtils.LINE_SEP);
+        UnaryOperator<String> translation) throws IOException {
+        for (String line : (Iterable<String>) () -> input.lines()
+            .map(translation).iterator()) {
+            output.write(String.format("%s%n", line));
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/DefaultNative2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/DefaultNative2Ascii.java
index c16a1a3..f0cf94c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/DefaultNative2Ascii.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/DefaultNative2Ascii.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -47,6 +47,7 @@
      * (delegated to {@link #addFiles addFiles}) and running the tool
      * (delegated to {@link #run run}).
      */
+    @Override
     public final boolean convert(Native2Ascii args, File srcFile,
                                  File destFile) throws BuildException {
         Commandline cmd = new Commandline();
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/KaffeNative2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/KaffeNative2Ascii.java
index afb88d9..295eec0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/KaffeNative2Ascii.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/KaffeNative2Ascii.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,6 +43,7 @@
     public static final String IMPLEMENTATION_NAME = "kaffe";
 
     /** {@inheritDoc} */
+    @Override
     protected void setup(Commandline cmd, Native2Ascii args)
         throws BuildException {
         if (args.getReverse()) {
@@ -52,13 +53,14 @@
     }
 
     /** {@inheritDoc} */
+    @Override
     protected boolean run(Commandline cmd, ProjectComponent log)
         throws BuildException {
         ExecuteJava ej = new ExecuteJava();
-        Class c = getN2aClass();
+        Class<?> c = getN2aClass();
         if (c == null) {
-            throw new BuildException("Couldn't load Kaffe's Native2Ascii"
-                                     + " class");
+            throw new BuildException(
+                "Couldn't load Kaffe's Native2Ascii class");
         }
 
         cmd.setExecutable(c.getName());
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapter.java
index af41400..0ccfd1b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
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..1f35980 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,12 +40,9 @@
      * vendor
      */
     public static String getDefault() {
-        if (shouldUseKaffee()) {
+        if (shouldUseKaffe()) {
             return KaffeNative2Ascii.IMPLEMENTATION_NAME;
         }
-        if (shouldUseSun()) {
-            return SunNative2Ascii.IMPLEMENTATION_NAME;
-        }
         return BuiltinNative2Ascii.IMPLEMENTATION_NAME;
     }
 
@@ -82,11 +79,10 @@
                                                  ProjectComponent log,
                                                  Path classpath)
         throws BuildException {
-        if ((shouldUseKaffee() && choice == null)
+        if ((shouldUseKaffe() && 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();
@@ -112,20 +108,13 @@
     private static Native2AsciiAdapter resolveClassName(String className,
                                                         ClassLoader loader)
         throws BuildException {
-        return (Native2AsciiAdapter) ClasspathUtils.newInstance(className,
+        return ClasspathUtils.newInstance(className,
             loader != null ? loader :
             Native2AsciiAdapterFactory.class.getClassLoader(),
             Native2AsciiAdapter.class);
     }
 
-    private static final boolean shouldUseKaffee() {
+    private static final boolean shouldUseKaffe() {
         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/native2ascii/SunNative2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/SunNative2Ascii.java
index fac94b1..5e062a3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/SunNative2Ascii.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/SunNative2Ascii.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,7 +36,10 @@
      */
     public static final String IMPLEMENTATION_NAME = "sun";
 
+    private static final String SUN_TOOLS_NATIVE2ASCII_MAIN = "sun.tools.native2ascii.Main";
+
     /** {@inheritDoc} */
+    @Override
     protected void setup(Commandline cmd, Native2Ascii args)
         throws BuildException {
         if (args.getReverse()) {
@@ -46,23 +49,20 @@
     }
 
     /** {@inheritDoc} */
+    @Override
     protected boolean run(Commandline cmd, ProjectComponent log)
         throws BuildException {
         try {
-            Class n2aMain = Class.forName("sun.tools.native2ascii.Main");
-            Class[] param = new Class[] {String[].class};
-            Method convert = n2aMain.getMethod("convert", param);
-            if (convert == null) {
-                throw new BuildException("Could not find convert() method in "
-                                         + "sun.tools.native2ascii.Main");
-            }
-            Object o = n2aMain.newInstance();
-            return ((Boolean) convert.invoke(o,
-                                             new Object[] {cmd.getArguments()})
-                    ).booleanValue();
+            Class<?> n2aMain = Class.forName(SUN_TOOLS_NATIVE2ASCII_MAIN);
+            Method convert = n2aMain.getMethod("convert", String[].class);
+            return Boolean.TRUE.equals(convert.invoke(n2aMain.getDeclaredConstructor().newInstance(),
+                (Object) cmd.getArguments()));
         } catch (BuildException ex) {
             //rethrow
             throw ex;
+        } catch (NoSuchMethodException ex) {
+            throw new BuildException("Could not find convert() method in %s",
+                SUN_TOOLS_NATIVE2ASCII_MAIN);
         } catch (Exception ex) {
             //wrap
            throw new BuildException("Error starting Sun's native2ascii: ", ex);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
index 8e3aee4..8662993 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,30 +21,32 @@
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.Vector;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 import org.apache.commons.net.ftp.FTPClient;
 import org.apache.commons.net.ftp.FTPClientConfig;
 import org.apache.commons.net.ftp.FTPFile;
 import org.apache.commons.net.ftp.FTPReply;
+import org.apache.commons.net.ftp.FTPConnectionClosedException;
+import org.apache.commons.net.ftp.FTPSClient;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
@@ -58,6 +60,8 @@
 import org.apache.tools.ant.util.Retryable;
 import org.apache.tools.ant.util.VectorSet;
 
+import javax.net.ssl.HostnameVerifier;
+
 /**
  * Basic FTP client. Performs the following actions:
  * <ul>
@@ -111,6 +115,8 @@
     private String userid;
     private String password;
     private String account;
+    private boolean useFtps = false;
+    private HostnameVerifier hostnameVerifier;
     private File listing;
     private boolean binary = true;
     private boolean passive = false;
@@ -120,8 +126,8 @@
     private long granularityMillis = 0L;
     private boolean timeDiffAuto = false;
     private int action = SEND_FILES;
-    private Vector filesets = new Vector();
-    private Set dirCache = new HashSet();
+    private Vector<FileSet> filesets = new Vector<>();
+    private Set<File> dirCache = new HashSet<>();
     private int transferred = 0;
     private String remoteFileSep = "/";
     private int port = DEFAULT_FTP_PORT;
@@ -143,8 +149,12 @@
     private String siteCommand = null;
     private String initialSiteCommand = null;
     private boolean enableRemoteVerification = true;
+    private int dataTimeout = -1;
+    private int wakeUpTransferInterval = -1;
+    private long lastWakeUpTime = 0;
 
-    protected static final String[] ACTION_STRS = { //NOSONAR
+
+    protected static final String[] ACTION_STRS = {//NOSONAR
         "sending",
         "getting",
         "deleting",
@@ -155,7 +165,7 @@
         "site"
     };
 
-    protected static final String[] COMPLETED_ACTION_STRS = { //NOSONAR
+    protected static final String[] COMPLETED_ACTION_STRS = {//NOSONAR
         "sent",
         "retrieved",
         "deleted",
@@ -166,7 +176,7 @@
         "site command executed"
     };
 
-    protected static final String[] ACTION_TARGET_STRS = { //NOSONAR
+    protected static final String[] ACTION_TARGET_STRS = {//NOSONAR
         "files",
         "files",
         "files",
@@ -183,6 +193,7 @@
      *
      */
     protected static class FTPFileProxy extends File {
+        private static final long serialVersionUID = 1L;
 
         private final FTPFile file;
         private final String[] parts;
@@ -214,6 +225,7 @@
         /* (non-Javadoc)
          * @see java.io.File#exists()
          */
+        @Override
         public boolean exists() {
             return true;
         }
@@ -222,6 +234,7 @@
         /* (non-Javadoc)
          * @see java.io.File#getAbsolutePath()
          */
+        @Override
         public String getAbsolutePath() {
             return name;
         }
@@ -230,6 +243,7 @@
         /* (non-Javadoc)
          * @see java.io.File#getName()
          */
+        @Override
         public String getName() {
             return parts.length > 0 ? parts[parts.length - 1] : name;
         }
@@ -238,18 +252,16 @@
         /* (non-Javadoc)
          * @see java.io.File#getParent()
          */
+        @Override
         public String getParent() {
-            String result = "";
-            for (int i = 0; i < parts.length - 1; i++){
-                result += File.separatorChar + parts[i];
-            }
-            return result;
+            return File.separator + String.join(File.separator, parts);
         }
 
 
         /* (non-Javadoc)
          * @see java.io.File#getPath()
          */
+        @Override
         public String getPath() {
             return name;
         }
@@ -259,6 +271,7 @@
          * FTP files are stored as absolute paths
          * @return true
          */
+        @Override
         public boolean isAbsolute() {
             return true;
         }
@@ -267,6 +280,7 @@
         /* (non-Javadoc)
          * @see java.io.File#isDirectory()
          */
+        @Override
         public boolean isDirectory() {
             return file == null;
         }
@@ -275,6 +289,7 @@
         /* (non-Javadoc)
          * @see java.io.File#isFile()
          */
+        @Override
         public boolean isFile() {
             return file != null;
         }
@@ -285,6 +300,7 @@
          *
          * @return  false
          */
+        @Override
         public boolean isHidden() {
             return false;
         }
@@ -293,6 +309,7 @@
         /* (non-Javadoc)
          * @see java.io.File#lastModified()
          */
+        @Override
         public long lastModified() {
             if (file != null) {
                 return file.getTimestamp().getTimeInMillis();
@@ -304,6 +321,7 @@
         /* (non-Javadoc)
          * @see java.io.File#length()
          */
+        @Override
         public long length() {
             if (file != null) {
                 return file.getSize();
@@ -349,6 +367,7 @@
          * scans the remote directory,
          * storing internally the included files, directories, ...
          */
+        @Override
         public void scan() {
             if (includes == null) {
                 // No includes supplied, so set it to 'matches all'
@@ -359,12 +378,12 @@
                 excludes = new String[0];
             }
 
-            filesIncluded = new VectorSet();
-            filesNotIncluded = new Vector();
-            filesExcluded = new VectorSet();
-            dirsIncluded = new VectorSet();
-            dirsNotIncluded = new Vector();
-            dirsExcluded = new VectorSet();
+            filesIncluded = new VectorSet<>();
+            filesNotIncluded = new Vector<>();
+            filesExcluded = new VectorSet<>();
+            dirsIncluded = new VectorSet<>();
+            dirsNotIncluded = new Vector<>();
+            dirsExcluded = new VectorSet<>();
 
             try {
                 String cwd = ftp.printWorkingDirectory();
@@ -387,7 +406,7 @@
          */
         private void checkIncludePatterns() {
 
-            Hashtable newroots = new Hashtable();
+            Map<String, String> newroots = new HashMap<>();
             // put in the newroots vector the include patterns without
             // wildcard tokens
             for (String include : includes) {
@@ -412,69 +431,65 @@
             } else {
                 // only scan directories that can include matched files or
                 // directories
-                Enumeration enum2 = newroots.keys();
+                newroots.forEach((k, v) -> scanRoots(baseFTPFile, k, v));
+            }
+        }
 
-                while (enum2.hasMoreElements()) {
-                    String currentelement = (String) enum2.nextElement();
-                    String originalpattern = (String) newroots.get(currentelement);
-                    AntFTPFile myfile = new AntFTPFile(baseFTPFile, currentelement);
-                    boolean isOK = true;
-                    boolean traversesSymlinks = false;
-                    String path = null;
+        private void scanRoots(AntFTPFile baseFTPFile, String currentelement,
+                               String originalpattern) {
+            AntFTPFile myfile = new AntFTPFile(baseFTPFile, currentelement);
+            boolean isOK = true;
+            boolean traversesSymlinks = false;
+            String path = null;
 
-                    if (myfile.exists()) {
-                        forceRemoteSensitivityCheck();
-                        if (remoteSensitivityChecked
-                            && remoteSystemCaseSensitive && isFollowSymlinks()) {
-                            // cool case,
-                            //we do not need to scan all the subdirs in the relative path
-                            path = myfile.getFastRelativePath();
-                        } else {
-                            // may be on a case insensitive file system.  We want
-                            // the results to show what's really on the disk, so
-                            // we need to double check.
-                            try {
-                                path = myfile.getRelativePath();
-                                traversesSymlinks = myfile.isTraverseSymlinks();
-                            }  catch (IOException be) {
-                                throw new BuildException(be, getLocation());
-                            } catch (BuildException be) {
-                                isOK = false;
-                            }
-                        }
-                    } else {
+            if (myfile.exists()) {
+                forceRemoteSensitivityCheck();
+                if (remoteSensitivityChecked
+                    && remoteSystemCaseSensitive && isFollowSymlinks()) {
+                    // cool case,
+                    //we do not need to scan all the subdirs in the relative path
+                    path = myfile.getFastRelativePath();
+                } else {
+                    // may be on a case insensitive file system.  We want
+                    // the results to show what's really on the disk, so
+                    // we need to double check.
+                    try {
+                        path = myfile.getRelativePath();
+                        traversesSymlinks = myfile.isTraverseSymlinks();
+                    } catch (IOException be) {
+                        throw new BuildException(be, getLocation());
+                    } catch (BuildException be) {
                         isOK = false;
                     }
-                    if (isOK) {
-                        currentelement = path.replace(remoteFileSep.charAt(0), File.separatorChar);
-                        if (!isFollowSymlinks() && traversesSymlinks) {
-                            continue;
-                        }
+                }
+            } else {
+                isOK = false;
+            }
+            if (isOK) {
+                currentelement = path.replace(remoteFileSep.charAt(0), File.separatorChar);
+                if (!isFollowSymlinks() && traversesSymlinks) {
+                    return;
+                }
 
-                        if (myfile.isDirectory()) {
-                            if (isIncluded(currentelement) && currentelement.length() > 0) {
-                                accountForIncludedDir(currentelement, myfile, true);
-                            }  else {
-                                if (currentelement.length() > 0) {
-                                    if (currentelement.charAt(currentelement.length() - 1)
-                                        != File.separatorChar) {
-                                        currentelement = currentelement + File.separatorChar;
-                                    }
-                                }
-                                scandir(myfile.getAbsolutePath(), currentelement, true);
-                            }
-                        } else {
-                            if (isCaseSensitive && originalpattern.equals(currentelement)) {
-                                accountForIncludedFile(currentelement);
-                            } else if (!isCaseSensitive
-                                       && originalpattern.equalsIgnoreCase(currentelement)) {
-                                accountForIncludedFile(currentelement);
-                            }
+                if (myfile.isDirectory()) {
+                    if (isIncluded(currentelement) && !currentelement.isEmpty()) {
+                        accountForIncludedDir(currentelement, myfile, true);
+                    } else {
+                        if (!currentelement.isEmpty()
+                                && currentelement.charAt(currentelement.length() - 1)
+                                != File.separatorChar) {
+                            currentelement += File.separatorChar;
                         }
+                        scandir(myfile.getAbsolutePath(), currentelement, true);
                     }
+                } else if (isCaseSensitive && originalpattern.equals(currentelement)) {
+                    accountForIncludedFile(currentelement);
+                } else if (!isCaseSensitive && originalpattern.equalsIgnoreCase(currentelement)) {
+                    accountForIncludedFile(currentelement);
                 }
             }
         }
+
         /**
          * scans a particular directory. populates the scannedDirs cache.
          *
@@ -493,7 +508,7 @@
                     return;
                 }
                 String completePath = null;
-                if (!vpath.equals("")) {
+                if (!vpath.isEmpty()) {
                     completePath = rootPath + remoteFileSep
                         + vpath.replace(File.separatorChar, remoteFileSep.charAt(0));
                 } else {
@@ -533,11 +548,22 @@
                         } else {
                             if (!isFollowSymlinks() && file.isSymbolicLink()) {
                                 filesExcluded.addElement(name);
-                            } else if (isFunctioningAsFile(ftp, dir, file)) {
+                            } else {
+                                // at this point, it's either a symbolic link or a file,
+                                // but not a directory, so we include it
                                 accountForIncludedFile(name);
                             }
                         }
                     }
+                    if (wakeUpTransferInterval > 0) {
+                        if (wakeUpTransferIntervalExpired()) {
+                            getProject().log("wakeUpTransferInterval is reached,"
+                                    + " trigger a data connection ", Project.MSG_DEBUG);
+                            // send a minimalist command to trigger a data connection
+                            ftp.listFiles(file.getName());
+                        }
+                    }
+
                 }
                 ftp.changeToParentDirectory();
             } catch (IOException e) {
@@ -555,7 +581,7 @@
 
                 if (isIncluded(name)) {
                     if (!isExcluded(name)
-                        && isSelected(name, (File) scannedDirs.get(name))) {
+                        && isSelected(name, scannedDirs.get(name))) {
                         filesIncluded.addElement(name);
                     } else {
                         filesExcluded.addElement(name);
@@ -617,14 +643,14 @@
          *
          * @since Ant 1.6
          */
-        private Map fileListMap = new HashMap();
+        private Map<String, FTPFile[]> fileListMap = new HashMap<>();
         /**
          * List of all scanned directories.
          *
          * @since Ant 1.6
          */
 
-        private Map scannedDirs = new HashMap();
+        private Map<String, FTPFileProxy> scannedDirs = new HashMap<>();
 
         /**
          * Has the directory with the given path relative to the base
@@ -652,12 +678,10 @@
          * @return array of FTPFile
          */
         public FTPFile[] listFiles(String directory, boolean changedir) {
-            //getProject().log("listing files in directory " + directory, Project.MSG_DEBUG);
             String currentPath = directory;
             if (changedir) {
                 try {
-                    boolean result = ftp.changeWorkingDirectory(directory);
-                    if (!result) {
+                    if (!ftp.changeWorkingDirectory(directory)) {
                         return null;
                     }
                     currentPath = ftp.printWorkingDirectory();
@@ -667,9 +691,9 @@
             }
             if (fileListMap.containsKey(currentPath)) {
                 getProject().log("filelist map used in listing files", Project.MSG_DEBUG);
-                return ((FTPFile[]) fileListMap.get(currentPath));
+                return fileListMap.get(currentPath);
             }
-            FTPFile[] result = null;
+            FTPFile[] result;
             try {
                 result = ftp.listFiles();
             } catch (IOException ioe) {
@@ -700,6 +724,7 @@
         public FTPFile[] listFiles(String directory) {
             return listFiles(directory, true);
         }
+
         private void checkRemoteSensitivity(FTPFile[] array, String directory) {
             if (array == null) {
                 return;
@@ -708,12 +733,13 @@
             String target = null;
             for (int icounter = 0; icounter < array.length; icounter++) {
                 if (array[icounter] != null && array[icounter].isDirectory()) {
-                    if (!array[icounter].getName().equals(".")
-                        && !array[icounter].getName().equals("..")) {
+                    if (!".".equals(array[icounter].getName())
+                        && !"..".equals(array[icounter].getName())) {
                         candidateFound = true;
                         target = fiddleName(array[icounter].getName());
                         getProject().log("will try to cd to "
-                                         + target + " where a directory called " + array[icounter].getName()
+                                         + target + " where a directory called "
+                                         + array[icounter].getName()
                                          + " exists", Project.MSG_DEBUG);
                         for (int pcounter = 0; pcounter < array.length; pcounter++) {
                             if (array[pcounter] != null
@@ -748,6 +774,7 @@
                 remoteSensitivityChecked = true;
             }
         }
+
         private String fiddleName(String origin) {
             StringBuilder result = new StringBuilder();
             for (char ch : origin.toCharArray()) {
@@ -761,6 +788,7 @@
             }
             return result.toString();
         }
+
         /**
          * an AntFTPFile is a representation of a remote file
          * @since Ant 1.6
@@ -804,44 +832,45 @@
             public AntFTPFile(AntFTPFile parent, String path) {
                 this.parent = parent;
                 this.client = parent.client;
-                Vector<String> pathElements = SelectorUtils.tokenizePath(path);
+                List<String> pathElements = SelectorUtils.tokenizePath(path);
                 try {
-                    boolean result = this.client.changeWorkingDirectory(parent.getAbsolutePath());
                     //this should not happen, except if parent has been deleted by another process
-                    if (!result) {
+                    if (!this.client.changeWorkingDirectory(parent.getAbsolutePath())) {
                         return;
                     }
                     this.curpwd = parent.getAbsolutePath();
                 } catch (IOException ioe) {
-                    throw new BuildException("could not change working dir to "
-                                             + parent.curpwd);
+                    throw new BuildException(
+                        "could not change working dir to %s", parent.curpwd);
                 }
                 for (String currentPathElement : pathElements) {
                     try {
-                        boolean result = this.client.changeWorkingDirectory(currentPathElement);
-                        if (!result && !isCaseSensitive()
-                            && (remoteSystemCaseSensitive || !remoteSensitivityChecked)) {
-                            currentPathElement = findPathElementCaseUnsensitive(this.curpwd,
-                                                                                currentPathElement);
-                            if (currentPathElement == null) {
-                                return;
+                        if (!this.client
+                            .changeWorkingDirectory(currentPathElement)) {
+                            if (!isCaseSensitive() && (remoteSystemCaseSensitive
+                                || !remoteSensitivityChecked)) {
+                                currentPathElement =
+                                    findPathElementCaseUnsensitive(this.curpwd,
+                                        currentPathElement);
+                                if (currentPathElement == null) {
+                                    return;
+                                }
                             }
-                        } else if (!result) {
                             return;
                         }
-                        this.curpwd = getCurpwdPlusFileSep()
-                            + currentPathElement;
+                        this.curpwd =
+                            getCurpwdPlusFileSep() + currentPathElement;
                     } catch (IOException ioe) {
-                        throw new BuildException("could not change working dir to "
-                                                 + currentPathElement
-                                                 + " from " + this.curpwd);
+                        throw new BuildException(
+                            "could not change working dir to %s from %s",
+                            currentPathElement, curpwd);
                     }
-
                 }
-                String lastpathelement = pathElements.elementAt(pathElements.size() - 1);
-                FTPFile [] theFiles = listFiles(this.curpwd);
+                String lastpathelement = pathElements.get(pathElements.size() - 1);
+                FTPFile[] theFiles = listFiles(this.curpwd);
                 this.ftpFile = getFile(theFiles, lastpathelement);
             }
+
             /**
              * find a file in a directory in case insensitive way
              * @param parentPath        where we are
@@ -857,12 +886,14 @@
                     return null;
                 }
                 for (FTPFile file : files) {
-                    if (file != null && file.getName().equalsIgnoreCase(soughtPathElement)) {
+                    if (file != null
+                        && file.getName().equalsIgnoreCase(soughtPathElement)) {
                         return file.getName();
                     }
                 }
                 return null;
             }
+
             /**
              * find out if the file exists
              * @return  true if the file exists
@@ -870,6 +901,7 @@
             public boolean exists() {
                 return (ftpFile != null);
             }
+
             /**
              * if the file is a symbolic link, find out to what it is pointing
              * @return the target of the symbolic link
@@ -877,6 +909,7 @@
             public String getLink() {
                 return ftpFile.getLink();
             }
+
             /**
              * get the name of the file
              * @return the name of the file
@@ -884,6 +917,7 @@
             public String getName() {
                 return ftpFile.getName();
             }
+
             /**
              * find out the absolute path of the file
              * @return absolute path as string
@@ -891,6 +925,7 @@
             public String getAbsolutePath() {
                 return getCurpwdPlusFileSep() + ftpFile.getName();
             }
+
             /**
              * find out the relative path assuming that the path used to construct
              * this AntFTPFile was spelled properly with regards to case.
@@ -904,6 +939,7 @@
                 }
                 return null;
             }
+
             /**
              * find out the relative path to the rootPath of the enclosing scanner.
              * this relative path is spelled exactly like on disk,
@@ -930,6 +966,7 @@
                 }
                 return relativePath;
             }
+
             /**
              * get the relative path of this file
              * @param currentPath          base path
@@ -937,35 +974,36 @@
              * @return relative path
              */
             private String getRelativePath(String currentPath, String currentRelativePath) {
-                Vector pathElements = SelectorUtils.tokenizePath(getAbsolutePath(), remoteFileSep);
-                Vector pathElements2 = SelectorUtils.tokenizePath(currentPath, remoteFileSep);
-                String relPath = currentRelativePath;
-                final int size = pathElements.size();
-                for (int pcount = pathElements2.size(); pcount < size; pcount++) {
-                    String currentElement = (String) pathElements.elementAt(pcount);
+                List<String> pathElements = SelectorUtils.tokenizePath(getAbsolutePath(),
+                        remoteFileSep);
+                StringBuilder relPath = new StringBuilder(currentRelativePath == null
+                        ? "" : currentRelativePath);
+                for (String currentElement : pathElements.subList(
+                                SelectorUtils.tokenizePath(currentPath, remoteFileSep).size(),
+                                pathElements.size())) {
                     FTPFile[] theFiles = listFiles(currentPath);
                     FTPFile theFile = null;
                     if (theFiles != null) {
                         theFile = getFile(theFiles, currentElement);
                     }
-                    if (!relPath.equals("")) {
-                        relPath = relPath + remoteFileSep;
+                    if (relPath.length() > 0) {
+                        relPath.append(remoteFileSep);
                     }
                     if (theFile == null) {
                         // hit a hidden file assume not a symlink
-                        relPath = relPath + currentElement;
-                        currentPath = currentPath + remoteFileSep + currentElement;
-                        log("Hidden file " + relPath
-                            + " assumed to not be a symlink.",
+                        relPath.append(currentElement);
+                        currentPath += remoteFileSep + currentElement;
+                        log("Hidden file " + relPath + " assumed to not be a symlink.",
                             Project.MSG_VERBOSE);
                     } else {
                         traversesSymlinks = traversesSymlinks || theFile.isSymbolicLink();
-                        relPath = relPath + theFile.getName();
-                        currentPath = currentPath + remoteFileSep + theFile.getName();
+                        relPath.append(theFile.getName());
+                        currentPath += remoteFileSep + theFile.getName();
                     }
                 }
-                return relPath;
+                return relPath.toString();
             }
+
             /**
              * find a file matching a string in an array of FTPFile.
              * This method will find "alpha" when requested for "ALPHA"
@@ -979,19 +1017,15 @@
                 if (theFiles == null) {
                     return null;
                 }
-                for (int fcount = 0; fcount < theFiles.length; fcount++) {
-                    if (theFiles[fcount] != null) {
-                        if (theFiles[fcount].getName().equals(lastpathelement)) {
-                            return theFiles[fcount];
-                        } else if (!isCaseSensitive()
-                                   && theFiles[fcount].getName().equalsIgnoreCase(
-                                                                                  lastpathelement)) {
-                            return theFiles[fcount];
-                        }
-                    }
-                }
-                return null;
+                Predicate<String> test =
+                    isCaseSensitive() ? lastpathelement::equals
+                        : lastpathelement::equalsIgnoreCase;
+                return Stream.of(theFiles)
+                    .filter(Objects::nonNull)
+                    .filter(f -> test.test(f.getName()))
+                    .findFirst().orElse(null);
             }
+
             /**
              * tell if a file is a directory.
              * note that it will return false for symbolic links pointing to directories.
@@ -1000,6 +1034,7 @@
             public boolean isDirectory() {
                 return ftpFile.isDirectory();
             }
+
             /**
              * tell if a file is a symbolic link
              * @return <code>true</code> for symbolic links
@@ -1007,6 +1042,7 @@
             public boolean isSymbolicLink() {
                 return ftpFile.isSymbolicLink();
             }
+
             /**
              * return the attached FTP client object.
              * Warning : this instance is really shared with the enclosing class.
@@ -1023,6 +1059,7 @@
             protected void setCurpwd(String curpwd) {
                 this.curpwd = curpwd;
             }
+
             /**
              * returns the path of the directory containing the AntFTPFile.
              * of the full path of the file itself in case of AntFTPRootFile
@@ -1031,6 +1068,7 @@
             public String getCurpwd() {
                 return curpwd;
             }
+
             /**
              * returns the path of the directory containing the AntFTPFile.
              * of the full path of the file itself in case of AntFTPRootFile
@@ -1042,6 +1080,7 @@
                 return curpwd.endsWith(remoteFileSep) ? curpwd
                     : curpwd + remoteFileSep;
             }
+
             /**
              * find out if a symbolic link is encountered in the relative path of this file
              * from rootPath.
@@ -1062,16 +1101,19 @@
              * Get a string rep of this object.
              * @return a string containing the pwd and the file.
              */
+            @Override
             public String toString() {
                 return "AntFtpFile: " + curpwd + "%" + ftpFile;
             }
         }
+
         /**
          * special class to represent the remote directory itself
          * @since Ant 1.6
          */
         protected class AntFTPRootFile extends AntFTPFile {
             private String remotedir;
+
             /**
              * constructor
              * @param aclient FTP client
@@ -1087,24 +1129,29 @@
                     throw new BuildException(ioe, getLocation());
                 }
             }
+
             /**
              * find the absolute path
              * @return absolute path
              */
+            @Override
             public String getAbsolutePath() {
                 return this.getCurpwd();
             }
+
             /**
              * find out the relative path to root
              * @return empty string
              * @throws BuildException actually never
              * @throws IOException  actually never
              */
+            @Override
             public String getRelativePath() throws BuildException, IOException {
                 return "";
             }
         }
     }
+
     /**
      * check FTPFiles to check whether they function as directories too
      * the FTPFile API seem to make directory and symbolic links incompatible
@@ -1114,24 +1161,36 @@
      * @return true if it is possible to cd to this directory
      * @since ant 1.6
      */
-    private boolean isFunctioningAsDirectory(FTPClient ftp, String dir, FTPFile file) {
-        boolean result = false;
-        String currentWorkingDir = null;
+    private boolean isFunctioningAsDirectory(FTPClient ftp, String dir, FTPFile file)
+            throws FTPConnectionClosedException {
         if (file.isDirectory()) {
             return true;
-        } else if (file.isFile()) {
+        }
+        if (file.isFile()) {
             return false;
         }
+        String currentWorkingDir = null;
         try {
             currentWorkingDir = ftp.printWorkingDirectory();
+        } catch (FTPConnectionClosedException ftpcce) {
+            getProject().log("could not find current working directory " + dir
+                             + " while checking a symlink because connection was closed",
+                             Project.MSG_DEBUG);
+            throw(ftpcce);
         } catch (IOException ioe) {
             getProject().log("could not find current working directory " + dir
                              + " while checking a symlink",
                              Project.MSG_DEBUG);
         }
+        boolean result = false;
         if (currentWorkingDir != null) {
             try {
                 result = ftp.changeWorkingDirectory(file.getLink());
+            } catch (FTPConnectionClosedException ftpcce) {
+                getProject().log("could not find current working directory " + dir
+                                + " while checking a symlink because connection was closed",
+                                Project.MSG_DEBUG);
+                throw(ftpcce);
             } catch (IOException ioe) {
                 getProject().log("could not cd to " + file.getLink() + " while checking a symlink",
                                  Project.MSG_DEBUG);
@@ -1145,14 +1204,16 @@
                                      Project.MSG_ERR);
                 } finally {
                     if (!comeback) {
-                        throw new BuildException("could not cd back to " + dir //NOSONAR
-                                                 + " while checking a symlink");
+                        throw new BuildException(
+                            "could not cd back to %s while checking a symlink",
+                            dir);
                     }
                 }
             }
         }
         return result;
     }
+
     /**
      * check FTPFiles to check whether they function as directories too
      * the FTPFile API seem to make directory and symbolic links incompatible
@@ -1162,14 +1223,11 @@
      * @return true if it is possible to cd to this directory
      * @since ant 1.6
      */
-    private boolean isFunctioningAsFile(FTPClient ftp, String dir, FTPFile file) {
-        if (file.isDirectory()) {
-            return false;
-        } else if (file.isFile()) {
-            return true;
-        }
-        return !isFunctioningAsDirectory(ftp, dir, file);
+    private boolean isFunctioningAsFile(FTPClient ftp, String dir, FTPFile file)
+            throws FTPConnectionClosedException {
+        return !file.isDirectory() && (file.isFile() || !isFunctioningAsDirectory(ftp, dir, file));
     }
+
     /**
      * Sets the remote directory where files will be placed. This may be a
      * relative or absolute path, and must be in the path syntax expected by
@@ -1181,7 +1239,6 @@
         this.remotedir = dir;
     }
 
-
     /**
      * Sets the FTP server to send files to.
      *
@@ -1211,6 +1268,18 @@
         this.userid = userid;
     }
 
+    /**
+     * Whether to use ftps instead of ftp.
+     *
+     * @since 1.10.13
+     */
+    public void setUseFtps(boolean useFtps) {
+        this.useFtps = useFtps;
+    }
+
+    public void add(HostnameVerifier hostnameVerifier) {
+        this.hostnameVerifier = hostnameVerifier;
+    }
 
     /**
      * Sets the login password for the given user id.
@@ -1266,7 +1335,7 @@
 
 
     /**
-     * A synonym for <tt>depends</tt>. Set to true to transmit only new
+     * A synonym for <code>depends</code>. Set to true to transmit only new
      * or changed files.
      *
      * See the related attributes timediffmillis and timediffauto.
@@ -1388,10 +1457,10 @@
      *
      * @throws BuildException if the action is not a valid action.
      */
+    @Deprecated
     public void setAction(String action) throws BuildException {
         log("DEPRECATED - The setAction(String) method has been deprecated."
-            + " Use setAction(FTP.Action) instead.");
-
+                + " Use setAction(FTP.Action) instead.");
         Action a = new Action();
 
         a.setValue(action);
@@ -1459,7 +1528,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setSystemTypeKey(FTPSystemType systemKey) {
-        if (systemKey != null && !systemKey.getValue().equals("")) {
+        if (systemKey != null && !systemKey.getValue().isEmpty()) {
             this.systemTypeKey = systemKey;
             configurationHasBeenSet();
         }
@@ -1472,7 +1541,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setDefaultDateFormatConfig(String defaultDateFormat) {
-        if (defaultDateFormat != null && !defaultDateFormat.equals("")) {
+        if (defaultDateFormat != null && !defaultDateFormat.isEmpty()) {
             this.defaultDateFormatConfig = defaultDateFormat;
             configurationHasBeenSet();
         }
@@ -1485,7 +1554,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setRecentDateFormatConfig(String recentDateFormat) {
-        if (recentDateFormat != null && !recentDateFormat.equals("")) {
+        if (recentDateFormat != null && !recentDateFormat.isEmpty()) {
             this.recentDateFormatConfig = recentDateFormat;
             configurationHasBeenSet();
         }
@@ -1498,7 +1567,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setServerLanguageCodeConfig(LanguageCode serverLanguageCode) {
-        if (serverLanguageCode != null && !"".equals(serverLanguageCode.getValue())) {
+        if (serverLanguageCode != null && !serverLanguageCode.getValue().isEmpty()) {
             this.serverLanguageCodeConfig = serverLanguageCode;
             configurationHasBeenSet();
         }
@@ -1511,7 +1580,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setServerTimeZoneConfig(String serverTimeZoneId) {
-        if (serverTimeZoneId != null && !serverTimeZoneId.equals("")) {
+        if (serverTimeZoneId != null && !serverTimeZoneId.isEmpty()) {
             this.serverTimeZoneConfig = serverTimeZoneId;
             configurationHasBeenSet();
         }
@@ -1525,7 +1594,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setShortMonthNamesConfig(String shortMonthNames) {
-        if (shortMonthNames != null && !shortMonthNames.equals("")) {
+        if (shortMonthNames != null && !shortMonthNames.isEmpty()) {
             this.shortMonthNamesConfig = shortMonthNames;
             configurationHasBeenSet();
         }
@@ -1549,72 +1618,84 @@
                 int retries = Integer.parseInt(retriesAllowed);
                 if (retries < Retryable.RETRY_FOREVER) {
                     throw new BuildException(
-                                             "Invalid value for retriesAllowed attribute: "
-                                             + retriesAllowed);
-
+                        "Invalid value for retriesAllowed attribute: %s",
+                        retriesAllowed);
                 }
                 this.retriesAllowed = retries;
             } catch (NumberFormatException px) {
                 throw new BuildException(
-                                         "Invalid value for retriesAllowed attribute: "
-                                         + retriesAllowed);
-
+                    "Invalid value for retriesAllowed attribute: %s",
+                    retriesAllowed);
             }
-
         }
     }
+
     /**
      * @return Returns the systemTypeKey.
      */
+    @Override
     public String getSystemTypeKey() {
         return systemTypeKey.getValue();
     }
+
     /**
      * @return Returns the defaultDateFormatConfig.
      */
+    @Override
     public String getDefaultDateFormatConfig() {
         return defaultDateFormatConfig;
     }
+
     /**
      * @return Returns the recentDateFormatConfig.
      */
+    @Override
     public String getRecentDateFormatConfig() {
         return recentDateFormatConfig;
     }
+
     /**
      * @return Returns the serverLanguageCodeConfig.
      */
+    @Override
     public String getServerLanguageCodeConfig() {
         return serverLanguageCodeConfig.getValue();
     }
+
     /**
      * @return Returns the serverTimeZoneConfig.
      */
+    @Override
     public String getServerTimeZoneConfig() {
         return serverTimeZoneConfig;
     }
+
     /**
      * @return Returns the shortMonthNamesConfig.
      */
+    @Override
     public String getShortMonthNamesConfig() {
         return shortMonthNamesConfig;
     }
+
     /**
      * @return Returns the timestampGranularity.
      */
     Granularity getTimestampGranularity() {
         return timestampGranularity;
     }
+
     /**
      * Sets the timestampGranularity attribute
      * @param timestampGranularity The timestampGranularity to set.
      */
     public void setTimestampGranularity(Granularity timestampGranularity) {
-        if (null == timestampGranularity || "".equals(timestampGranularity.getValue())) {
+        if (null == timestampGranularity || timestampGranularity.getValue().isEmpty()) {
             return;
         }
         this.timestampGranularity = timestampGranularity;
     }
+
     /**
      * Sets the siteCommand attribute.  This attribute
      * names the command that will be executed if the action
@@ -1624,6 +1705,7 @@
     public void setSiteCommand(String siteCommand) {
         this.siteCommand = siteCommand;
     }
+
     /**
      * Sets the initialSiteCommand attribute.  This attribute
      * names a site command that will be executed immediately
@@ -1646,6 +1728,35 @@
     }
 
     /**
+     * Sets the timeout on the data connection in milliseconds.
+     * Any negative value is discarded and leaves the default
+     * A value of 0 means an infinite timeout
+     *
+     * @param dataTimeout int
+     * @since Ant 1.10.7
+     */
+    public void setDataTimeout(int dataTimeout) {
+        if (dataTimeout >= 0) {
+            this.dataTimeout = dataTimeout;
+        }
+    }
+
+    /**
+     * Sets the time interval when we should automatically
+     * call a command triggering a transfer
+     * The parameter is in seconds
+     *
+     * @param wakeUpTransferInterval int
+     * @since Ant 1.10.7
+     */
+    public void setWakeUpTransferInterval(int wakeUpTransferInterval) {
+        if (wakeUpTransferInterval > 0) {
+            this.wakeUpTransferInterval = wakeUpTransferInterval;
+        }
+    }
+
+
+    /**
      * Checks to see that all required parameters are set.
      *
      * @throws BuildException if the configuration is not valid.
@@ -1661,33 +1772,31 @@
             throw new BuildException("password attribute must be set!");
         }
 
-        if ((action == LIST_FILES) && (listing == null)) {
-            throw new BuildException("listing attribute must be set for list "
-                                     + "action!");
+        if (action == LIST_FILES && listing == null) {
+            throw new BuildException(
+                "listing attribute must be set for list action!");
         }
 
         if (action == MK_DIR && remotedir == null) {
-            throw new BuildException("remotedir attribute must be set for "
-                                     + "mkdir action!");
+            throw new BuildException(
+                "remotedir attribute must be set for mkdir action!");
         }
 
         if (action == CHMOD && chmod == null) {
-            throw new BuildException("chmod attribute must be set for chmod "
-                                     + "action!");
+            throw new BuildException(
+                "chmod attribute must be set for chmod action!");
         }
         if (action == SITE_CMD && siteCommand == null) {
-            throw new BuildException("sitecommand attribute must be set for site "
-                                     + "action!");
+            throw new BuildException(
+                "sitecommand attribute must be set for site action!");
         }
 
-
         if (this.isConfigurationSet) {
             try {
                 Class.forName("org.apache.commons.net.ftp.FTPClientConfig");
             } catch (ClassNotFoundException e) {
                 throw new BuildException(
-                                         "commons-net.jar >= 1.4.0 is required for at least one"
-                                         + " of the attributes specified.");
+                    "commons-net.jar >= 1.4.0 is required for the specified attributes.");
             }
         }
     }
@@ -1730,7 +1839,7 @@
             ds.scan();
         }
 
-        String[] dsfiles = null;
+        String[] dsfiles;
         if (action == RM_DIR) {
             dsfiles = ds.getIncludedDirectories();
         } else {
@@ -1738,14 +1847,13 @@
         }
         String dir = null;
 
-        if ((ds.getBasedir() == null)
-            && ((action == SEND_FILES) || (action == GET_FILES))) {
-            throw new BuildException("the dir attribute must be set for send "
-                                     + "and get actions");
-        } else {
-            if ((action == SEND_FILES) || (action == GET_FILES)) {
-                dir = ds.getBasedir().getAbsolutePath();
-            }
+        if (ds.getBasedir() == null
+            && (action == SEND_FILES || action == GET_FILES)) {
+            throw new BuildException(
+                "the dir attribute must be set for send and get actions");
+        }
+        if (action == SEND_FILES || action == GET_FILES) {
+            dir = ds.getBasedir().getAbsolutePath();
         }
 
         // If we are doing a listing, we need the output stream created now.
@@ -1766,11 +1874,7 @@
                 // the trunk does not let itself be removed before the leaves
                 for (int i = dsfiles.length - 1; i >= 0; i--) {
                     final String dsfile = dsfiles[i];
-                    executeRetryable(h, new Retryable() {
-                            public void execute() throws IOException {
-                                rmDir(ftp, dsfile);
-                            }
-                        }, dsfile);
+                    executeRetryable(h, () -> rmDir(ftp, dsfile), dsfile);
                 }
             } else {
                 final BufferedWriter fbw = bw;
@@ -1780,29 +1884,27 @@
                         this.timestampGranularity.getMilliseconds(action);
                 }
                 for (final String dsfile : dsfiles) {
-                    executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            switch (action) {
-                                case SEND_FILES:
-                                    sendFile(ftp, fdir, dsfile);
-                                    break;
-                                case GET_FILES:
-                                    getFile(ftp, fdir, dsfile);
-                                    break;
-                                case DEL_FILES:
-                                    delFile(ftp, dsfile);
-                                    break;
-                                case LIST_FILES:
-                                    listFile(ftp, fbw, dsfile);
-                                    break;
-                                case CHMOD:
-                                    doSiteCommand(ftp, "chmod " + chmod
-                                            + " " + resolveFile(dsfile));
-                                    transferred++;
-                                    break;
-                                default:
-                                    throw new BuildException("unknown ftp action " + action);
-                            }
+                    executeRetryable(h, () -> {
+                        switch (action) {
+                            case SEND_FILES:
+                                sendFile(ftp, fdir, dsfile);
+                                break;
+                            case GET_FILES:
+                                getFile(ftp, fdir, dsfile);
+                                break;
+                            case DEL_FILES:
+                                delFile(ftp, dsfile);
+                                break;
+                            case LIST_FILES:
+                                listFile(ftp, fbw, dsfile);
+                                break;
+                            case CHMOD:
+                                doSiteCommand(ftp, "chmod " + chmod
+                                        + " " + resolveFile(dsfile));
+                                transferred++;
+                                break;
+                            default:
+                                throw new BuildException("unknown ftp action " + action);
                         }
                     }, dsfile);
                 }
@@ -1814,7 +1916,6 @@
         return dsfiles.length;
     }
 
-
     /**
      * Sends all files specified by the configured filesets to the remote
      * server.
@@ -1829,17 +1930,12 @@
         transferred = 0;
         skipped = 0;
 
-        if (filesets.size() == 0) {
+        if (filesets.isEmpty()) {
             throw new BuildException("at least one fileset must be specified.");
-        } else {
-            // get files from filesets
-            final int size = filesets.size();
-            for (int i = 0; i < size; i++) {
-                FileSet fs = (FileSet) filesets.elementAt(i);
-
-                if (fs != null) {
-                    transferFiles(ftp, fs);
-                }
+        }
+        for (FileSet fs : filesets) {
+            if (fs != null) {
+                transferFiles(ftp, fs);
             }
         }
 
@@ -1851,7 +1947,6 @@
         }
     }
 
-
     /**
      * Correct a file path to correspond to the remote host requirements. This
      * implementation currently assumes that the remote end can handle
@@ -1864,11 +1959,9 @@
      * @return the filename as it will appear on the server.
      */
     protected String resolveFile(String file) {
-        return file.replace(System.getProperty("file.separator").charAt(0),
-                            remoteFileSep.charAt(0));
+        return file.replace(File.separator.charAt(0), remoteFileSep.charAt(0));
     }
 
-
     /**
      * Creates all parent directories specified in a complete relative
      * pathname. Attempts to create existing directories will not cause
@@ -1889,7 +1982,7 @@
             return;
         }
 
-        Vector parents = new Vector();
+        List<File> parents = new Vector<>();
         String dirname;
 
         while ((dirname = dir.getParent()) != null) {
@@ -1898,7 +1991,7 @@
                 break;
             }
             dir = checkDir;
-            parents.addElement(dir);
+            parents.add(dir);
         }
 
         // find first non cached dir
@@ -1907,15 +2000,14 @@
         if (i >= 0) {
             String cwd = ftp.printWorkingDirectory();
             String parent = dir.getParent();
-            if (parent != null) {
-                if (!ftp.changeWorkingDirectory(resolveFile(parent))) {
-                    throw new BuildException("could not change to "
-                                             + "directory: " + ftp.getReplyString());
-                }
+            if (parent != null
+                && !ftp.changeWorkingDirectory(resolveFile(parent))) {
+                throw new BuildException("could not change to directory: %s",
+                    ftp.getReplyString());
             }
 
             while (i >= 0) {
-                dir = (File) parents.elementAt(i--);
+                dir = parents.get(i--);
                 // check if dir exists by trying to change into it.
                 if (!ftp.changeWorkingDirectory(dir.getName())) {
                     // could not change to it - try to create it
@@ -1925,8 +2017,9 @@
                         handleMkDirFailure(ftp);
                     }
                     if (!ftp.changeWorkingDirectory(dir.getName())) {
-                        throw new BuildException("could not change to "
-                                                 + "directory: " + ftp.getReplyString());
+                        throw new BuildException(
+                            "could not change to directory: %s",
+                            ftp.getReplyString());
                     }
                 }
                 dirCache.add(dir);
@@ -1947,12 +2040,13 @@
             // create a local temporary file
             FILE_UTILS.createNewFile(tempFile);
             long localTimeStamp = tempFile.lastModified();
-            BufferedInputStream instream = new BufferedInputStream(new FileInputStream(tempFile));
+            BufferedInputStream instream = new BufferedInputStream(
+                    Files.newInputStream(tempFile.toPath()));
             ftp.storeFile(tempFile.getName(), instream);
             instream.close();
             boolean success = FTPReply.isPositiveCompletion(ftp.getReplyCode());
             if (success) {
-                FTPFile [] ftpFiles = ftp.listFiles(tempFile.getName());
+                FTPFile[] ftpFiles = ftp.listFiles(tempFile.getName());
                 if (ftpFiles.length == 1) {
                     long remoteTimeStamp = ftpFiles[0].getTimestamp().getTime().getTime();
                     returnValue = localTimeStamp - remoteTimeStamp;
@@ -1970,6 +2064,7 @@
         }
         return returnValue;
     }
+
     /**
      *  find a suitable name for local and remote temporary file
      */
@@ -1978,7 +2073,7 @@
         final int maxIterations = 1000;
         for (int counter = 1; counter < maxIterations; counter++) {
             File localFile = FILE_UTILS.createTempFile(getProject(),
-                                                       "ant" + Integer.toString(counter), ".tmp",
+                                                       "ant" + counter, ".tmp",
                                                        null, false, false);
             String fileName = localFile.getName();
             boolean found = false;
@@ -2031,10 +2126,9 @@
                 log("Could not date test remote file: " + remoteFile
                     + "assuming out of date.", Project.MSG_VERBOSE);
                 return false;
-            } else {
-                throw new BuildException("could not date test remote file: "
-                                         + ftp.getReplyString());
             }
+            throw new BuildException("could not date test remote file: %s",
+                ftp.getReplyString());
         }
 
         long remoteTimestamp = files[0].getTimestamp().getTime().getTime();
@@ -2042,38 +2136,36 @@
         long adjustedRemoteTimestamp =
             remoteTimestamp + this.timeDiffMillis + this.granularityMillis;
 
-        StringBuffer msg;
-        synchronized(TIMESTAMP_LOGGING_SDF) {
-            msg = new StringBuffer("   [")
+        StringBuilder msg;
+        synchronized (TIMESTAMP_LOGGING_SDF) {
+            msg = new StringBuilder("   [")
                 .append(TIMESTAMP_LOGGING_SDF.format(new Date(localTimestamp)))
                 .append("] local");
         }
         log(msg.toString(), Project.MSG_VERBOSE);
 
-        synchronized(TIMESTAMP_LOGGING_SDF) {
-            msg = new StringBuffer("   [")
-                .append(TIMESTAMP_LOGGING_SDF.format(new Date(adjustedRemoteTimestamp)))
+        synchronized (TIMESTAMP_LOGGING_SDF) {
+            msg = new StringBuilder("   [")
+                .append(TIMESTAMP_LOGGING_SDF
+                    .format(new Date(adjustedRemoteTimestamp)))
                 .append("] remote");
         }
         if (remoteTimestamp != adjustedRemoteTimestamp) {
-            synchronized(TIMESTAMP_LOGGING_SDF) {
+            synchronized (TIMESTAMP_LOGGING_SDF) {
                 msg.append(" - (raw: ")
-                    .append(TIMESTAMP_LOGGING_SDF.format(new Date(remoteTimestamp)))
+                    .append(
+                        TIMESTAMP_LOGGING_SDF.format(new Date(remoteTimestamp)))
                     .append(")");
             }
         }
         log(msg.toString(), Project.MSG_VERBOSE);
 
-
-
         if (this.action == SEND_FILES) {
             return adjustedRemoteTimestamp >= localTimestamp;
-        } else {
-            return localTimestamp >= adjustedRemoteTimestamp;
         }
+        return localTimestamp >= adjustedRemoteTimestamp;
     }
 
-
     /**
      * Sends a site command to the ftp server
      * @param ftp ftp client
@@ -2083,14 +2175,10 @@
      */
     protected void doSiteCommand(FTPClient ftp, String theCMD)
         throws IOException, BuildException {
-        boolean rc;
-        String[] myReply = null;
 
         log("Doing Site Command: " + theCMD, Project.MSG_VERBOSE);
 
-        rc = ftp.sendSiteCommand(theCMD);
-
-        if (!rc) {
+        if (!ftp.sendSiteCommand(theCMD)) {
             log("Failed to issue Site Command: " + theCMD, Project.MSG_WARN);
         } else {
             for (String reply : ftp.getReplyStrings()) {
@@ -2101,7 +2189,6 @@
         }
     }
 
-
     /**
      * Sends a single file to the remote host. <code>filename</code> may
      * contain a relative path specification. When this is the case, <code>sendFile</code>
@@ -2134,7 +2221,7 @@
                 log("transferring " + file.getAbsolutePath());
             }
 
-            instream = new BufferedInputStream(new FileInputStream(file));
+            instream = new BufferedInputStream(Files.newInputStream(file.toPath()));
 
             createParents(ftp, filename);
 
@@ -2166,7 +2253,6 @@
         }
     }
 
-
     /**
      * Delete a file from the remote host.
      * @param ftp ftp client
@@ -2246,10 +2332,9 @@
      */
     protected void getFile(FTPClient ftp, String dir, String filename)
         throws IOException, BuildException {
+        File file = getProject().resolveFile(new File(dir, filename).getPath());
         OutputStream outstream = null;
         try {
-            File file = getProject().resolveFile(new File(dir, filename).getPath());
-
             if (newerOnly && isUpToDate(ftp, file, resolveFile(filename))) {
                 return;
             }
@@ -2264,7 +2349,7 @@
             if (!pdir.exists()) {
                 pdir.mkdirs();
             }
-            outstream = new BufferedOutputStream(new FileOutputStream(file));
+            outstream = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
             ftp.retrieveFile(resolveFile(filename), outstream);
 
             if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
@@ -2297,7 +2382,6 @@
         }
     }
 
-
     /**
      * List information about a single file from the remote host. <code>filename</code>
      * may contain a relative path specification. <p>
@@ -2342,41 +2426,41 @@
     protected void makeRemoteDir(FTPClient ftp, String dir)
         throws IOException, BuildException {
         String workingDirectory = ftp.printWorkingDirectory();
+        boolean absolute = dir.startsWith("/");
         if (verbose) {
-            if (dir.startsWith("/") || workingDirectory == null) {
+            if (absolute || workingDirectory == null) {
                 log("Creating directory: " + dir + " in /");
             } else {
                 log("Creating directory: " + dir + " in " + workingDirectory);
             }
         }
-        if (dir.startsWith("/")) {
+        if (absolute) {
             ftp.changeWorkingDirectory("/");
         }
-        String subdir = "";
         StringTokenizer st = new StringTokenizer(dir, "/");
         while (st.hasMoreTokens()) {
-            subdir = st.nextToken();
+            String subdir = st.nextToken();
             log("Checking " + subdir, Project.MSG_DEBUG);
             if (!ftp.changeWorkingDirectory(subdir)) {
-                if (!ftp.makeDirectory(subdir)) {
-                    // codes 521, 550 and 553 can be produced by FTP Servers
-                    //  to indicate that an attempt to create a directory has
-                    //  failed because the directory already exists.
-                    int rc = ftp.getReplyCode();
-                    if (!(ignoreNoncriticalErrors
-                          && (rc == CODE_550 || rc == CODE_553
-                              || rc == CODE_521))) {
-                        throw new BuildException("could not create directory: "
-                                                 + ftp.getReplyString());
-                    }
-                    if (verbose) {
-                        log("Directory already exists");
-                    }
-                } else {
+                if (ftp.makeDirectory(subdir)) {
                     if (verbose) {
                         log("Directory created OK");
                     }
                     ftp.changeWorkingDirectory(subdir);
+                } else {
+                    // codes 521, 550 and 553 can be produced by FTP Servers
+                    //  to indicate that an attempt to create a directory has
+                    //  failed because the directory already exists.
+                    int rc = ftp.getReplyCode();
+                    if (!ignoreNoncriticalErrors
+                            || rc != CODE_550 && rc != CODE_553 && rc != CODE_521) {
+                        throw new BuildException(
+                            "could not create directory: %s",
+                            ftp.getReplyString());
+                    }
+                    if (verbose) {
+                        log("Directory already exists");
+                    }
                 }
             }
         }
@@ -2394,37 +2478,72 @@
     private void handleMkDirFailure(FTPClient ftp)
         throws BuildException {
         int rc = ftp.getReplyCode();
-        if (!(ignoreNoncriticalErrors
-              && (rc == CODE_550 || rc == CODE_553 || rc == CODE_521))) {
-            throw new BuildException("could not create directory: "
-                                     + ftp.getReplyString());
+        if (!ignoreNoncriticalErrors || rc != CODE_550 && rc != CODE_553 && rc != CODE_521) {
+            throw new BuildException("could not create directory: %s",
+                ftp.getReplyString());
         }
     }
 
     /**
+     * checks if the wake up interval is expired
+     */
+    private boolean wakeUpTransferIntervalExpired() {
+        boolean result = false;
+
+        // on the first call, initialize the keep-alive mechanism
+        // by storing the current date
+        if (lastWakeUpTime == 0) {
+            lastWakeUpTime = (new Date()).getTime();
+        } else {
+            long currentTime = (new Date()).getTime();
+            if (currentTime > (lastWakeUpTime + wakeUpTransferInterval * 1000)) {
+                lastWakeUpTime = currentTime;
+                result = true;
+            }
+        }
+
+        return result;
+    }
+
+    /**
      * Runs the task.
      *
      * @throws BuildException if the task fails or is not configured
      *         correctly.
      */
+    @Override
     public void execute() throws BuildException {
         checkAttributes();
 
         FTPClient ftp = null;
 
         try {
-            log("Opening FTP connection to " + server, Project.MSG_VERBOSE);
-
-            ftp = new FTPClient();
+            if (useFtps) {
+                log("Opening FTPs connection to " + server, Project.MSG_VERBOSE);
+                FTPSClient ftps = new FTPSClient();
+                ftps.setEndpointCheckingEnabled(true);
+                if (hostnameVerifier != null) {
+                    ftps.setHostnameVerifier(hostnameVerifier);
+                }
+                ftp = ftps;
+            } else {
+                log("Opening FTP connection to " + server, Project.MSG_VERBOSE);
+                ftp = new FTPClient();
+            }
             if (this.isConfigurationSet) {
                 ftp = FTPConfigurator.configure(ftp, this);
             }
 
             ftp.setRemoteVerificationEnabled(enableRemoteVerification);
             ftp.connect(server, port);
+
+            if (dataTimeout >= 0) {
+                ftp.setDataTimeout(dataTimeout);
+                log("Setting data timeout to " + dataTimeout, Project.MSG_VERBOSE);
+            }
             if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                throw new BuildException("FTP connection failed: "
-                                         + ftp.getReplyString());
+                throw new BuildException("FTP connection failed: %s",
+                    ftp.getReplyString());
             }
 
             log("connected", Project.MSG_VERBOSE);
@@ -2439,24 +2558,21 @@
 
             if (binary) {
                 ftp.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
-                if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                    throw new BuildException("could not set transfer type: "
-                                             + ftp.getReplyString());
-                }
             } else {
                 ftp.setFileType(org.apache.commons.net.ftp.FTP.ASCII_FILE_TYPE);
-                if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                    throw new BuildException("could not set transfer type: "
-                                             + ftp.getReplyString());
-                }
+            }
+            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
+                throw new BuildException("could not set transfer type: %s",
+                    ftp.getReplyString());
             }
 
             if (passive) {
                 log("entering passive mode", Project.MSG_VERBOSE);
                 ftp.enterLocalPassiveMode();
                 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                    throw new BuildException("could not enter into passive "
-                                             + "mode: " + ftp.getReplyString());
+                    throw new BuildException(
+                        "could not enter into passive mode: %s",
+                        ftp.getReplyString());
                 }
             }
 
@@ -2465,56 +2581,43 @@
             // E.G. switching between a UNIX file system mode and
             // a legacy file system.
             if (this.initialSiteCommand != null) {
-                RetryHandler h = new RetryHandler(this.retriesAllowed, this);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            doSiteCommand(lftp, FTP.this.initialSiteCommand);
-                        }
-                    }, "initial site command: " + this.initialSiteCommand);
+                executeRetryable(new RetryHandler(this.retriesAllowed, this),
+                    () -> doSiteCommand(lftp, FTP.this.initialSiteCommand),
+                    "initial site command: " + this.initialSiteCommand);
             }
 
-
             // For a unix ftp server you can set the default mask for all files
             // created.
 
             if (umask != null) {
-                RetryHandler h = new RetryHandler(this.retriesAllowed, this);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            doSiteCommand(lftp, "umask " + umask);
-                        }
-                    }, "umask " + umask);
+                executeRetryable(new RetryHandler(this.retriesAllowed, this),
+                    () -> doSiteCommand(lftp, "umask " + umask),
+                    "umask " + umask);
             }
 
             // If the action is MK_DIR, then the specified remote
             // directory is the directory to create.
 
             if (action == MK_DIR) {
-                RetryHandler h = new RetryHandler(this.retriesAllowed, this);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            makeRemoteDir(lftp, remotedir);
-                        }
-                    }, remotedir);
+                executeRetryable(new RetryHandler(this.retriesAllowed, this),
+                    () -> makeRemoteDir(lftp, remotedir), remotedir);
             } else if (action == SITE_CMD) {
-                RetryHandler h = new RetryHandler(this.retriesAllowed, this);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            doSiteCommand(lftp, FTP.this.siteCommand);
-                        }
-                    }, "Site Command: " + this.siteCommand);
+                executeRetryable(new RetryHandler(this.retriesAllowed, this),
+                    () -> doSiteCommand(lftp, FTP.this.siteCommand),
+                    "Site Command: " + this.siteCommand);
             } else {
                 if (remotedir != null) {
                     log("changing the remote directory to " + remotedir,
                         Project.MSG_VERBOSE);
                     ftp.changeWorkingDirectory(remotedir);
                     if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                        throw new BuildException("could not change remote "
-                                                 + "directory: " + ftp.getReplyString());
+                        throw new BuildException(
+                            "could not change remote directory: %s",
+                            ftp.getReplyString());
                     }
                 }
                 if (newerOnly && timeDiffAuto) {
@@ -2527,6 +2630,23 @@
             }
 
         } catch (IOException ex) {
+            final Throwable cause = ex.getCause();
+            if (cause != null) {
+                final String msg = cause.toString();
+                if (msg != null && msg.contains("java.net.SocketTimeoutException")) {
+                    // When a read timeout occurs, inform the server that it
+                    // should abort.
+                    // Note that the latest commons-net (3.6) still does not
+                    // support sending urgent data, which is normally a
+                    // prerequisite for ABORT command.
+                    // As a consequence, it  might not be taken in account immediately
+                    try {
+                        ftp.abort();
+                    } catch (IOException ioe) {
+                        // ignore it
+                    }
+                }
+            }
             throw new BuildException("error during FTP transfer: " + ex, ex);
         } finally {
             if (ftp != null && ftp.isConnected()) {
@@ -2541,7 +2661,6 @@
         }
     }
 
-
     /**
      * an action to perform, one of
      * "send", "put", "recv", "get", "del", "delete", "list", "mkdir", "chmod",
@@ -2554,44 +2673,49 @@
             "chmod", "rmdir", "site"
         };
 
-
         /**
          * Get the valid values
          *
          * @return an array of the valid FTP actions.
          */
+        @Override
         public String[] getValues() {
             return VALID_ACTIONS;
         }
 
-
         /**
          * Get the symbolic equivalent of the action value.
          *
          * @return the SYMBOL representing the given action.
          */
         public int getAction() {
-            String actionL = getValue().toLowerCase(Locale.ENGLISH);
-            if (actionL.equals("send") || actionL.equals("put")) {
+            switch (getValue().toLowerCase(Locale.ENGLISH)) {
+            case "send":
+            case "put":
                 return SEND_FILES;
-            } else if (actionL.equals("recv") || actionL.equals("get")) {
+            case "recv":
+            case "get":
                 return GET_FILES;
-            } else if (actionL.equals("del") || actionL.equals("delete")) {
+            case "del":
+            case "delete":
                 return DEL_FILES;
-            } else if (actionL.equals("list")) {
+            case "list":
                 return LIST_FILES;
-            } else if (actionL.equals("chmod")) {
+            case "chmod":
                 return CHMOD;
-            } else if (actionL.equals("mkdir")) {
+            case "mkdir":
                 return MK_DIR;
-            } else if (actionL.equals("rmdir")) {
+            case "rmdir":
                 return RM_DIR;
-            } else if (actionL.equals("site")) {
+            case "site":
                 return SITE_CMD;
+            default:
+                return SEND_FILES;
             }
-            return SEND_FILES;
+
         }
     }
+
     /**
      * represents one of the valid timestamp adjustment values
      * recognized by the <code>timestampGranularity</code> attribute.<p>
@@ -2617,9 +2741,11 @@
          * Get the valid values.
          * @return the list of valid Granularity values
          */
+        @Override
         public String[] getValues() {
             return VALID_GRANULARITIES;
         }
+
         /**
          * returns the number of milliseconds associated with
          * the attribute, which can vary in some cases depending
@@ -2630,7 +2756,7 @@
          */
         public long getMilliseconds(int action) {
             String granularityU = getValue().toUpperCase(Locale.ENGLISH);
-            if ("".equals(granularityU)) {
+            if (granularityU.isEmpty()) {
                 if (action == SEND_FILES) {
                     return GRANULARITY_MINUTE;
                 }
@@ -2639,13 +2765,14 @@
             }
             return 0L;
         }
+
         static final Granularity getDefault() {
             Granularity g = new Granularity();
             g.setValue("");
             return g;
         }
-
     }
+
     /**
      * one of the valid system type keys recognized by the systemTypeKey
      * attribute.
@@ -2662,6 +2789,7 @@
          * Get the valid values.
          * @return the list of valid system types.
          */
+        @Override
         public String[] getValues() {
             return VALID_SYSTEM_TYPES;
         }
@@ -2672,31 +2800,31 @@
             return ftpst;
         }
     }
+
     /**
      * Enumerated class for languages.
      */
     public static class LanguageCode extends EnumeratedAttribute {
 
-
         private static final String[] VALID_LANGUAGE_CODES =
             getValidLanguageCodes();
 
         private static String[] getValidLanguageCodes() {
-            Collection c = FTPClientConfig.getSupportedLanguageCodes();
+            Collection<String> c = FTPClientConfig.getSupportedLanguageCodes();
             String[] ret = new String[c.size() + 1];
             int i = 0;
             ret[i++] = "";
-            for (Iterator it = c.iterator(); it.hasNext(); i++) {
-                ret[i] = (String) it.next();
+            for (String element : c) {
+                ret[i++] = element;
             }
             return ret;
         }
 
-
         /**
          * Return the value values.
          * @return the list of valid language types.
          */
+        @Override
         public String[] getValues() {
             return VALID_LANGUAGE_CODES;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java
index 0604dac..ba659dc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,7 +43,7 @@
         task.log("custom configuration", Project.MSG_VERBOSE);
         FTPClientConfig config;
         String systemTypeKey = task.getSystemTypeKey();
-        if (systemTypeKey != null && !"".equals(systemTypeKey)) {
+        if (systemTypeKey != null && !systemTypeKey.isEmpty()) {
             config = new FTPClientConfig(systemTypeKey);
             task.log("custom config: system key = "
                     + systemTypeKey, Project.MSG_VERBOSE);
@@ -69,7 +69,7 @@
 
         String serverLanguageCodeConfig = task.getServerLanguageCodeConfig();
         if (serverLanguageCodeConfig != null) {
-            if (!"".equals(serverLanguageCodeConfig)
+            if (!serverLanguageCodeConfig.isEmpty()
                 && !FTPClientConfig.getSupportedLanguageCodes()
                 .contains(serverLanguageCodeConfig)) {
                 throw new BuildException("unsupported language code" +
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java
index d53f16d..6d2e739 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -83,7 +83,7 @@
     private long granularityMillis = 0L;
     private boolean timeDiffAuto = false;
     private int action = SEND_FILES;
-    private Vector filesets = new Vector();
+    private Vector<FileSet> filesets = new Vector<>();
     private String remoteFileSep = "/";
     private int port = DEFAULT_FTP_PORT;
     private boolean skipFailedTransfers = false;
@@ -265,7 +265,7 @@
     }
 
     /**
-     * A synonym for <tt>depends</tt>. Set to true to transmit only new
+     * A synonym for <code>depends</code>. Set to true to transmit only new
      * or changed files.
      *
      * See the related attributes timediffmillis and timediffauto.
@@ -396,7 +396,7 @@
         filesets.addElement(set);
     }
 
-    public Vector getFilesets() {
+    public Vector<FileSet> getFilesets() {
         return filesets;
     }
 
@@ -415,6 +415,7 @@
      *
      * @throws BuildException if the action is not a valid action.
      */
+    @Deprecated
     public void setAction(String action) throws BuildException {
         log("DEPRECATED - The setAction(String) method has been deprecated."
             + " Use setAction(FTP.Action) instead.");
@@ -503,7 +504,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setSystemTypeKey(FTPSystemType systemKey) {
-        if (systemKey != null && !systemKey.getValue().equals("")) {
+        if (systemKey != null && !systemKey.getValue().isEmpty()) {
             this.systemTypeKey = systemKey;
             configurationHasBeenSet();
         }
@@ -516,7 +517,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setDefaultDateFormatConfig(String defaultDateFormat) {
-        if (defaultDateFormat != null && !defaultDateFormat.equals("")) {
+        if (defaultDateFormat != null && !defaultDateFormat.isEmpty()) {
             this.defaultDateFormatConfig = defaultDateFormat;
             configurationHasBeenSet();
         }
@@ -529,7 +530,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setRecentDateFormatConfig(String recentDateFormat) {
-        if (recentDateFormat != null && !recentDateFormat.equals("")) {
+        if (recentDateFormat != null && !recentDateFormat.isEmpty()) {
             this.recentDateFormatConfig = recentDateFormat;
             configurationHasBeenSet();
         }
@@ -542,7 +543,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setServerLanguageCodeConfig(String serverLanguageCode) {
-        if (serverLanguageCode != null && !"".equals(serverLanguageCode)) {
+        if (serverLanguageCode != null && !serverLanguageCode.isEmpty()) {
             this.serverLanguageCodeConfig = serverLanguageCode;
             configurationHasBeenSet();
         }
@@ -555,7 +556,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setServerTimeZoneConfig(String serverTimeZoneId) {
-        if (serverTimeZoneId != null && !serverTimeZoneId.equals("")) {
+        if (serverTimeZoneId != null && !serverTimeZoneId.isEmpty()) {
             this.serverTimeZoneConfig = serverTimeZoneId;
             configurationHasBeenSet();
         }
@@ -569,7 +570,7 @@
      * @see org.apache.commons.net.ftp.FTPClientConfig
      */
     public void setShortMonthNamesConfig(String shortMonthNames) {
-        if (shortMonthNames != null && !shortMonthNames.equals("")) {
+        if (shortMonthNames != null && !shortMonthNames.isEmpty()) {
             this.shortMonthNamesConfig = shortMonthNames;
             configurationHasBeenSet();
         }
@@ -593,16 +594,14 @@
                 int retries = Integer.parseInt(retriesAllowed);
                 if (retries < Retryable.RETRY_FOREVER) {
                     throw new BuildException(
-                                             "Invalid value for retriesAllowed attribute: "
-                                             + retriesAllowed);
-
+                        "Invalid value for retriesAllowed attribute: %s",
+                        retriesAllowed);
                 }
                 this.retriesAllowed = retries;
             } catch (NumberFormatException px) {
                 throw new BuildException(
-                                         "Invalid value for retriesAllowed attribute: "
-                                         + retriesAllowed);
-
+                    "Invalid value for retriesAllowed attribute: %s",
+                    retriesAllowed);
             }
 
         }
@@ -615,55 +614,69 @@
     /**
      * @return Returns the systemTypeKey.
      */
+    @Override
     public String getSystemTypeKey() {
         return systemTypeKey.getValue();
     }
+
     /**
      * @return Returns the defaultDateFormatConfig.
      */
+    @Override
     public String getDefaultDateFormatConfig() {
         return defaultDateFormatConfig;
     }
+
     /**
      * @return Returns the recentDateFormatConfig.
      */
+    @Override
     public String getRecentDateFormatConfig() {
         return recentDateFormatConfig;
     }
+
     /**
      * @return Returns the serverLanguageCodeConfig.
      */
+    @Override
     public String getServerLanguageCodeConfig() {
         return serverLanguageCodeConfig;
     }
+
     /**
      * @return Returns the serverTimeZoneConfig.
      */
+    @Override
     public String getServerTimeZoneConfig() {
         return serverTimeZoneConfig;
     }
+
     /**
      * @return Returns the shortMonthNamesConfig.
      */
+    @Override
     public String getShortMonthNamesConfig() {
         return shortMonthNamesConfig;
     }
+
     /**
      * @return Returns the timestampGranularity.
      */
     public Granularity getTimestampGranularity() {
         return timestampGranularity;
     }
+
     /**
      * Sets the timestampGranularity attribute
      * @param timestampGranularity The timestampGranularity to set.
      */
     public void setTimestampGranularity(Granularity timestampGranularity) {
-        if (null == timestampGranularity || "".equals(timestampGranularity.getValue())) {
+        if (null == timestampGranularity || timestampGranularity.getValue().isEmpty()) {
             return;
         }
         this.timestampGranularity = timestampGranularity;
     }
+
     /**
      * Sets the siteCommand attribute.  This attribute
      * names the command that will be executed if the action
@@ -731,33 +744,31 @@
             throw new BuildException("password attribute must be set!");
         }
 
-        if ((action == LIST_FILES) && (listing == null)) {
-            throw new BuildException("listing attribute must be set for list "
-                                     + "action!");
+        if (action == LIST_FILES && listing == null) {
+            throw new BuildException(
+                "listing attribute must be set for list action!");
         }
 
         if (action == MK_DIR && remotedir == null) {
-            throw new BuildException("remotedir attribute must be set for "
-                                     + "mkdir action!");
+            throw new BuildException(
+                "remotedir attribute must be set for mkdir action!");
         }
 
         if (action == CHMOD && chmod == null) {
-            throw new BuildException("chmod attribute must be set for chmod "
-                                     + "action!");
+            throw new BuildException(
+                "chmod attribute must be set for chmod action!");
         }
         if (action == SITE_CMD && siteCommand == null) {
-            throw new BuildException("sitecommand attribute must be set for site "
-                                     + "action!");
+            throw new BuildException(
+                "sitecommand attribute must be set for site action!");
         }
 
-
         if (this.isConfigurationSet) {
             try {
                 Class.forName("org.apache.commons.net.ftp.FTPClientConfig");
             } catch (ClassNotFoundException e) {
                 throw new BuildException(
-                                         "commons-net.jar >= 1.4.0 is required for at least one"
-                                         + " of the attributes specified.");
+                    "commons-net.jar >= 1.4.0 is required for at least one of the attributes specified.");
             }
         }
     }
@@ -768,6 +779,7 @@
      * @throws BuildException if the task fails or is not configured
      *         correctly.
      */
+    @Override
     public void execute() throws BuildException {
         checkAttributes();
         try {
@@ -815,18 +827,21 @@
         try {
             loader.loadClass("org.apache.commons.net.ftp.FTP"); // sanity check
         } catch (ClassNotFoundException e) {
-            throw new BuildException("The <classpath> for <ftp> must include"
-                                     + " commons-net.jar if not in Ant's own "
-                                     + " classpath", e, task.getLocation());
+            throw new BuildException(
+                "The <classpath> for <ftp> must include commons-net.jar if not in Ant's own classpath",
+                e, task.getLocation());
         }
         try {
-            Class c = loader.loadClass(FTPTaskMirror.class.getName() + "Impl");
+            Class<? extends FTPTaskMirror> c =
+                loader.loadClass(FTPTaskMirror.class.getName() + "Impl")
+                    .asSubclass(FTPTaskMirror.class);
             if (c.getClassLoader() != loader) {
                 throw new BuildException("Overdelegating loader",
-                                         task.getLocation());
+                    task.getLocation());
             }
-            Constructor cons = c.getConstructor(new Class[] {FTPTask.class});
-            return (FTPTaskMirror) cons.newInstance(new Object[] {task});
+            Constructor<? extends FTPTaskMirror> cons =
+                c.getConstructor(FTPTask.class);
+            return cons.newInstance(task);
         } catch (Exception e) {
             throw new BuildException(e, task.getLocation());
         }
@@ -844,17 +859,16 @@
             "chmod", "rmdir", "site"
         };
 
-
         /**
          * Get the valid values
          *
          * @return an array of the valid FTP actions.
          */
+        @Override
         public String[] getValues() {
             return VALID_ACTIONS;
         }
 
-
         /**
          * Get the symbolic equivalent of the action value.
          *
@@ -862,26 +876,31 @@
          */
         public int getAction() {
             String actionL = getValue().toLowerCase(Locale.ENGLISH);
-            if (actionL.equals("send") || actionL.equals("put")) {
+            switch (actionL) {
+            case "send":
+            case "put":
                 return SEND_FILES;
-            } else if (actionL.equals("recv") || actionL.equals("get")) {
+            case "recv":
+            case "get":
                 return GET_FILES;
-            } else if (actionL.equals("del") || actionL.equals("delete")) {
+            case "del":
+            case "delete":
                 return DEL_FILES;
-            } else if (actionL.equals("list")) {
+            case "list":
                 return LIST_FILES;
-            } else if (actionL.equals("chmod")) {
+            case "chmod":
                 return CHMOD;
-            } else if (actionL.equals("mkdir")) {
+            case "mkdir":
                 return MK_DIR;
-            } else if (actionL.equals("rmdir")) {
+            case "rmdir":
                 return RM_DIR;
-            } else if (actionL.equals("site")) {
+            case "site":
                 return SITE_CMD;
             }
             return SEND_FILES;
         }
     }
+
     /**
      * represents one of the valid timestamp adjustment values
      * recognized by the <code>timestampGranularity</code> attribute.<p>
@@ -907,9 +926,11 @@
          * Get the valid values.
          * @return the list of valid Granularity values
          */
+        @Override
         public String[] getValues() {
             return VALID_GRANULARITIES;
         }
+
         /**
          * returns the number of milliseconds associated with
          * the attribute, which can vary in some cases depending
@@ -920,7 +941,7 @@
          */
         public long getMilliseconds(int action) {
             String granularityU = getValue().toUpperCase(Locale.ENGLISH);
-            if ("".equals(granularityU)) {
+            if (granularityU.isEmpty()) {
                 if (action == SEND_FILES) {
                     return GRANULARITY_MINUTE;
                 }
@@ -929,13 +950,14 @@
             }
             return 0L;
         }
+
         static final Granularity getDefault() {
             Granularity g = new Granularity();
             g.setValue("");
             return g;
         }
-
     }
+
     /**
      * one of the valid system type keys recognized by the systemTypeKey
      * attribute.
@@ -947,11 +969,11 @@
             "MVS"
         };
 
-
         /**
          * Get the valid values.
          * @return the list of valid system types.
          */
+        @Override
         public String[] getValues() {
             return VALID_SYSTEM_TYPES;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskConfig.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskConfig.java
index 006df61..42a9513 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskConfig.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskConfig.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirror.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirror.java
index 5d09e6f..0f9342d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirror.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirror.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
index ec4e28f..3d45cb1 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPTaskMirrorImpl.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,22 +21,24 @@
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.Vector;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 import org.apache.commons.net.ftp.FTPClient;
 import org.apache.commons.net.ftp.FTPFile;
@@ -66,7 +68,7 @@
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     private final FTPTask task;
-    private Set dirCache = new HashSet();
+    private Set<File> dirCache = new HashSet<>();
     private int transferred = 0;
     private int skipped = 0;
 
@@ -84,6 +86,7 @@
      *
      */
     protected static class FTPFileProxy extends File {
+        private static final long serialVersionUID = 1L;
 
         private final FTPFile file;
         private final String[] parts;
@@ -111,89 +114,89 @@
             parts = FileUtils.getPathStack(completePath);
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#exists()
          */
+        @Override
         public boolean exists() {
             return true;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#getAbsolutePath()
          */
+        @Override
         public String getAbsolutePath() {
             return name;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#getName()
          */
+        @Override
         public String getName() {
             return parts.length > 0 ? parts[parts.length - 1] : name;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#getParent()
          */
+        @Override
         public String getParent() {
-            String result = "";
-            for(int i = 0; i < parts.length - 1; i++){
-                result += File.separatorChar + parts[i];
+            StringBuilder result = new StringBuilder();
+            for (int i = 0; i < parts.length - 1; i++) {
+                result.append(File.separatorChar).append(parts[i]);
             }
-            return result;
+            return result.toString();
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#getPath()
          */
+        @Override
         public String getPath() {
             return name;
         }
 
-
         /**
          * FTP files are stored as absolute paths
          * @return true
          */
+        @Override
         public boolean isAbsolute() {
             return true;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#isDirectory()
          */
+        @Override
         public boolean isDirectory() {
             return file == null;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#isFile()
          */
+        @Override
         public boolean isFile() {
             return file != null;
         }
 
-
         /**
          * FTP files cannot be hidden
          *
          * @return  false
          */
+        @Override
         public boolean isHidden() {
             return false;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#lastModified()
          */
+        @Override
         public long lastModified() {
             if (file != null) {
                 return file.getTimestamp().getTimeInMillis();
@@ -201,10 +204,10 @@
             return 0;
         }
 
-
         /* (non-Javadoc)
          * @see java.io.File#length()
          */
+        @Override
         public long length() {
             if (file != null) {
                 return file.getSize();
@@ -245,11 +248,11 @@
             this.setFollowSymlinks(false);
         }
 
-
         /**
          * scans the remote directory,
          * storing internally the included files, directories, ...
          */
+        @Override
         public void scan() {
             if (includes == null) {
                 // No includes supplied, so set it to 'matches all'
@@ -260,12 +263,12 @@
                 excludes = new String[0];
             }
 
-            filesIncluded = new VectorSet();
-            filesNotIncluded = new Vector();
-            filesExcluded = new VectorSet();
-            dirsIncluded = new VectorSet();
-            dirsNotIncluded = new Vector();
-            dirsExcluded = new VectorSet();
+            filesIncluded = new VectorSet<>();
+            filesNotIncluded = new Vector<>();
+            filesExcluded = new VectorSet<>();
+            dirsIncluded = new VectorSet<>();
+            dirsNotIncluded = new Vector<>();
+            dirsExcluded = new VectorSet<>();
 
             try {
                 String cwd = ftp.printWorkingDirectory();
@@ -280,7 +283,6 @@
             }
         }
 
-
         /**
          * this routine is actually checking all the include patterns in
          * order to avoid scanning everything under base dir
@@ -288,7 +290,7 @@
          */
         private void checkIncludePatterns() {
 
-            Hashtable newroots = new Hashtable();
+            Map<String, String> newroots = new Hashtable<>();
             // put in the newroots vector the include patterns without
             // wildcard tokens
             for (String include : includes) {
@@ -313,75 +315,68 @@
             } else {
                 // only scan directories that can include matched files or
                 // directories
-                Enumeration enum2 = newroots.keys();
+                newroots.forEach(
+                    (k, v) -> scanRoot(new AntFTPFile(baseFTPFile, k), v));
+            }
+        }
 
-                while (enum2.hasMoreElements()) {
-                    String currentelement = (String) enum2.nextElement();
-                    String originalpattern = (String) newroots.get(currentelement);
-                    AntFTPFile myfile = new AntFTPFile(baseFTPFile, currentelement);
-                    boolean isOK = true;
-                    boolean traversesSymlinks = false;
-                    String path = null;
+        private void scanRoot(AntFTPFile myfile, String originalpattern) {
+            String currentelement;
+            boolean isOK = true;
+            boolean traversesSymlinks = false;
+            String path = null;
 
-                    if (myfile.exists()) {
-                        forceRemoteSensitivityCheck();
-                        if (remoteSensitivityChecked
-                            && remoteSystemCaseSensitive && isFollowSymlinks()) {
-                            // cool case,
-                            //we do not need to scan all the subdirs in the relative path
-                            path = myfile.getFastRelativePath();
-                        } else {
-                            // may be on a case insensitive file system.  We want
-                            // the results to show what's really on the disk, so
-                            // we need to double check.
-                            try {
-                                path = myfile.getRelativePath();
-                                traversesSymlinks = myfile.isTraverseSymlinks();
-                            } catch (IOException be) {
-                                throw new BuildException(be, task.getLocation());
-                            } catch (BuildException be) {
-                                isOK = false;
-                            }
-                        }
-                    } else {
+            if (myfile.exists()) {
+                forceRemoteSensitivityCheck();
+                if (remoteSensitivityChecked
+                    && remoteSystemCaseSensitive && isFollowSymlinks()) {
+                    // cool case,
+                    //we do not need to scan all the subdirs in the relative path
+                    path = myfile.getFastRelativePath();
+                } else {
+                    // may be on a case insensitive file system.  We want
+                    // the results to show what's really on the disk, so
+                    // we need to double check.
+                    try {
+                        path = myfile.getRelativePath();
+                        traversesSymlinks = myfile.isTraverseSymlinks();
+                    } catch (IOException be) {
+                        throw new BuildException(be, task.getLocation());
+                    } catch (BuildException be) {
                         isOK = false;
                     }
-                    if (isOK) {
-                        currentelement = path.replace(task.getSeparator().charAt(0), File.separatorChar);
-                        if (!isFollowSymlinks()
-                            && traversesSymlinks) {
-                            continue;
-                        }
+                }
+            } else {
+                isOK = false;
+            }
+            if (isOK) {
+                currentelement = path.replace(task.getSeparator().charAt(0), File.separatorChar);
+                if (!isFollowSymlinks()
+                    && traversesSymlinks) {
+                    return;
+                }
 
-                        if (myfile.isDirectory()) {
-                            if (isIncluded(currentelement)
-                                && currentelement.length() > 0) {
-                                accountForIncludedDir(currentelement, myfile, true);
-                            }  else {
-                                if (currentelement.length() > 0) {
-                                    if (currentelement.charAt(currentelement
-                                                              .length() - 1)
-                                        != File.separatorChar) {
-                                        currentelement =
-                                            currentelement + File.separatorChar;
-                                    }
-                                }
-                                scandir(myfile.getAbsolutePath(), currentelement, true);
-                            }
-                        } else {
-                            if (isCaseSensitive
-                                && originalpattern.equals(currentelement)) {
-                                accountForIncludedFile(currentelement);
-                            } else if (!isCaseSensitive
-                                       && originalpattern
-                                       .equalsIgnoreCase(currentelement)) {
-                                accountForIncludedFile(currentelement);
-                            }
+                if (myfile.isDirectory()) {
+                    if (isIncluded(currentelement) && !currentelement.isEmpty()) {
+                        accountForIncludedDir(currentelement, myfile, true);
+                    } else {
+                        if (!currentelement.isEmpty() && currentelement.charAt(currentelement.length() - 1)
+                                != File.separatorChar) {
+                            currentelement += File.separatorChar;
                         }
+                        scandir(myfile.getAbsolutePath(), currentelement, true);
                     }
+                } else if (isCaseSensitive
+                    && originalpattern.equals(currentelement)) {
+                    accountForIncludedFile(currentelement);
+                } else if (!isCaseSensitive
+                           && originalpattern
+                           .equalsIgnoreCase(currentelement)) {
+                    accountForIncludedFile(currentelement);
                 }
             }
         }
+
         /**
          * scans a particular directory. populates the scannedDirs cache.
          *
@@ -399,12 +394,12 @@
                 if (!ftp.changeWorkingDirectory(dir)) {
                     return;
                 }
-                String completePath = null;
-                if (!vpath.equals("")) {
+                String completePath;
+                if (vpath.isEmpty()) {
+                    completePath = rootPath;
+                } else {
                     completePath = rootPath + task.getSeparator()
                         + vpath.replace(File.separatorChar, task.getSeparator().charAt(0));
-                } else {
-                    completePath = rootPath;
                 }
                 FTPFile[] newfiles = listFiles(completePath, false);
 
@@ -462,7 +457,7 @@
 
                 if (isIncluded(name)) {
                     if (!isExcluded(name)
-                        && isSelected(name, (File) scannedDirs.get(name))) {
+                        && isSelected(name, scannedDirs.get(name))) {
                         filesIncluded.addElement(name);
                     } else {
                         filesExcluded.addElement(name);
@@ -517,19 +512,21 @@
                 }
             }
         }
+
         /**
          * temporary table to speed up the various scanning methods below
          *
          * @since Ant 1.6
          */
-        private Map fileListMap = new HashMap();
+        private Map<String, FTPFile[]> fileListMap = new HashMap<>();
+
         /**
          * List of all scanned directories.
          *
          * @since Ant 1.6
          */
 
-        private Map scannedDirs = new HashMap();
+        private Map<String, FTPFileProxy> scannedDirs = new HashMap<>();
 
         /**
          * Has the directory with the given path relative to the base
@@ -550,6 +547,7 @@
             fileListMap.clear();
             scannedDirs.clear();
         }
+
         /**
          * list the files present in one directory.
          * @param directory full path on the remote side
@@ -561,8 +559,7 @@
             String currentPath = directory;
             if (changedir) {
                 try {
-                    boolean result = ftp.changeWorkingDirectory(directory);
-                    if (!result) {
+                    if (!ftp.changeWorkingDirectory(directory)) {
                         return null;
                     }
                     currentPath = ftp.printWorkingDirectory();
@@ -572,9 +569,9 @@
             }
             if (fileListMap.containsKey(currentPath)) {
                 task.log("filelist map used in listing files", Project.MSG_DEBUG);
-                return ((FTPFile[]) fileListMap.get(currentPath));
+                return fileListMap.get(currentPath);
             }
-            FTPFile[] result = null;
+            FTPFile[] result;
             try {
                 result = ftp.listFiles();
             } catch (IOException ioe) {
@@ -596,6 +593,7 @@
                 }
             }
         }
+
         /**
          * cd into one directory and
          * list the files present in one directory.
@@ -605,6 +603,7 @@
         public FTPFile[] listFiles(String directory) {
             return listFiles(directory, true);
         }
+
         private void checkRemoteSensitivity(FTPFile[] array, String directory) {
             if (array == null) {
                 return;
@@ -613,8 +612,8 @@
             String target = null;
             for (int icounter = 0; icounter < array.length; icounter++) {
                 if (array[icounter] != null && array[icounter].isDirectory()) {
-                    if (!array[icounter].getName().equals(".")
-                        && !array[icounter].getName().equals("..")) {
+                    if (!".".equals(array[icounter].getName())
+                        && !"..".equals(array[icounter].getName())) {
                         candidateFound = true;
                         target = fiddleName(array[icounter].getName());
                         task.log("will try to cd to "
@@ -654,6 +653,7 @@
                 remoteSensitivityChecked = true;
             }
         }
+
         private String fiddleName(String origin) {
             StringBuilder result = new StringBuilder();
             for (char ch : origin.toCharArray()) {
@@ -667,6 +667,7 @@
             }
             return result.toString();
         }
+
         /**
          * an AntFTPFile is a representation of a remote file
          * @since Ant 1.6
@@ -691,6 +692,7 @@
             private boolean relativePathCalculated = false;
             private boolean traversesSymlinks = false;
             private String relativePath = "";
+
             /**
              * constructor
              * @param client ftp client variable
@@ -702,6 +704,7 @@
                 this.ftpFile = ftpFile;
                 this.curpwd = curpwd;
             }
+
             /**
              * other constructor
              * @param parent the parent file
@@ -710,7 +713,7 @@
             public AntFTPFile(AntFTPFile parent, String path) {
                 this.parent = parent;
                 this.client = parent.client;
-                Vector<String> pathElements = SelectorUtils.tokenizePath(path);
+                List<String> pathElements = SelectorUtils.tokenizePath(path);
                 try {
                     boolean result = this.client.changeWorkingDirectory(parent.getAbsolutePath());
                     //this should not happen, except if parent has been deleted by another process
@@ -719,28 +722,26 @@
                     }
                     this.curpwd = parent.getAbsolutePath();
                 } catch (IOException ioe) {
-                    throw new BuildException("could not change working dir to " + parent.curpwd);
+                    throw new BuildException("could not change working dir to %s", parent.curpwd);
                 }
                 for (String currentPathElement : pathElements) {
                     try {
-                        boolean result = this.client.changeWorkingDirectory(currentPathElement);
-                        if (!result && !isCaseSensitive()
-                            && (remoteSystemCaseSensitive || !remoteSensitivityChecked)) {
-                            currentPathElement = findPathElementCaseUnsensitive(this.curpwd,
-                                    currentPathElement);
-                            if (currentPathElement == null) {
-                                return;
+                        if (!this.client.changeWorkingDirectory(currentPathElement)) {
+                            if (!isCaseSensitive() && (remoteSystemCaseSensitive
+                                    || !remoteSensitivityChecked)) {
+                                currentPathElement = findPathElementCaseUnsensitive(this.curpwd,
+                                        currentPathElement);
+                                if (currentPathElement == null) {
+                                    return;
+                                }
                             }
-                        } else if (!result) {
                             return;
                         }
-                        this.curpwd = getCurpwdPlusFileSep()
-                            + currentPathElement;
+                        this.curpwd = getCurpwdPlusFileSep() + currentPathElement;
                     } catch (IOException ioe) {
-                        throw new BuildException("could not change working dir to "
-                                + currentPathElement + " from " + this.curpwd);
+                        throw new BuildException("could not change working dir to %s from %s",
+                                currentPathElement, this.curpwd);
                     }
-
                 }
                 String lastpathelement = pathElements.get(pathElements.size() - 1);
                 this.ftpFile = getFile(listFiles(this.curpwd), lastpathelement);
@@ -760,7 +761,8 @@
                     return null;
                 }
                 for (FTPFile file : files) {
-                    if (file != null && file.getName().equalsIgnoreCase(soughtPathElement)) {
+                    if (file != null
+                        && file.getName().equalsIgnoreCase(soughtPathElement)) {
                         return file.getName();
                     }
                 }
@@ -771,8 +773,9 @@
              * @return  true if the file exists
              */
             public boolean exists() {
-                return (ftpFile != null);
+                return ftpFile != null;
             }
+
             /**
              * if the file is a symbolic link, find out to what it is pointing
              * @return the target of the symbolic link
@@ -780,6 +783,7 @@
             public String getLink() {
                 return ftpFile.getLink();
             }
+
             /**
              * get the name of the file
              * @return the name of the file
@@ -787,6 +791,7 @@
             public String getName() {
                 return ftpFile.getName();
             }
+
             /**
              * find out the absolute path of the file
              * @return absolute path as string
@@ -794,6 +799,7 @@
             public String getAbsolutePath() {
                 return getCurpwdPlusFileSep() + ftpFile.getName();
             }
+
             /**
              * find out the relative path assuming that the path used to construct
              * this AntFTPFile was spelled properly with regards to case.
@@ -808,6 +814,7 @@
                 }
                 return null;
             }
+
             /**
              * find out the relative path to the rootPath of the enclosing scanner.
              * this relative path is spelled exactly like on disk,
@@ -834,6 +841,7 @@
                 }
                 return relativePath;
             }
+
             /**
              * get the relative path of this file
              * @param currentPath          base path
@@ -841,38 +849,38 @@
              * @return relative path
              */
             private String getRelativePath(String currentPath, String currentRelativePath) {
-                Vector pathElements = SelectorUtils.tokenizePath(getAbsolutePath(), task.getSeparator());
-                Vector pathElements2 = SelectorUtils.tokenizePath(currentPath,
-                                                                  task.getSeparator());
-                String relPath = currentRelativePath;
+                List<String> pathElements = SelectorUtils
+                    .tokenizePath(getAbsolutePath(), task.getSeparator());
+                List<String> pathElements2 = SelectorUtils
+                    .tokenizePath(currentPath, task.getSeparator());
+                StringBuilder relPath = new StringBuilder(currentRelativePath);
                 final int size = pathElements.size();
                 for (int pcount = pathElements2.size(); pcount < size; pcount++) {
-                    String currentElement = (String) pathElements.elementAt(pcount);
+                    String currentElement = pathElements.get(pcount);
                     FTPFile[] theFiles = listFiles(currentPath);
                     FTPFile theFile = null;
                     if (theFiles != null) {
                         theFile = getFile(theFiles, currentElement);
                     }
-                    if (!relPath.equals("")) {
-                        relPath = relPath + task.getSeparator();
+                    if (relPath.length() > 0) {
+                        relPath.append(task.getSeparator());
                     }
                     if (theFile == null) {
                         // hit a hidden file assume not a symlink
-                        relPath = relPath + currentElement;
-                        currentPath = currentPath + task.getSeparator()
-                            + currentElement;
+                        relPath.append(currentElement);
+                        currentPath += task.getSeparator() + currentElement;
                         task.log("Hidden file " + relPath
                                  + " assumed to not be a symlink.",
                                  Project.MSG_VERBOSE);
                     } else {
                         traversesSymlinks = traversesSymlinks || theFile.isSymbolicLink();
-                        relPath = relPath + theFile.getName();
-                        currentPath = currentPath + task.getSeparator()
-                            + theFile.getName();
+                        relPath.append(theFile.getName());
+                        currentPath += task.getSeparator() + theFile.getName();
                     }
                 }
-                return relPath;
+                return relPath.toString();
             }
+
             /**
              * find a file matching a string in an array of FTPFile.
              * This method will find "alpha" when requested for "ALPHA"
@@ -886,19 +894,15 @@
                 if (theFiles == null) {
                     return null;
                 }
-                for (int fcount = 0; fcount < theFiles.length; fcount++) {
-                    if (theFiles[fcount] != null) {
-                        if (theFiles[fcount].getName().equals(lastpathelement)) {
-                            return theFiles[fcount];
-                        } else if (!isCaseSensitive()
-                                   && theFiles[fcount].getName().equalsIgnoreCase(
-                                                                                  lastpathelement)) {
-                            return theFiles[fcount];
-                        }
-                    }
-                }
-                return null;
+                Predicate<String> test =
+                    isCaseSensitive() ? lastpathelement::equals
+                        : lastpathelement::equalsIgnoreCase;
+                return Stream.of(theFiles)
+                    .filter(Objects::nonNull)
+                    .filter(f -> test.test(f.getName()))
+                    .findFirst().orElse(null);
             }
+
             /**
              * tell if a file is a directory.
              * note that it will return false for symbolic links pointing to directories.
@@ -907,6 +911,7 @@
             public boolean isDirectory() {
                 return ftpFile.isDirectory();
             }
+
             /**
              * tell if a file is a symbolic link
              * @return <code>true</code> for symbolic links
@@ -914,6 +919,7 @@
             public boolean isSymbolicLink() {
                 return ftpFile.isSymbolicLink();
             }
+
             /**
              * return the attached FTP client object.
              * Warning : this instance is really shared with the enclosing class.
@@ -930,6 +936,7 @@
             protected void setCurpwd(String curpwd) {
                 this.curpwd = curpwd;
             }
+
             /**
              * returns the path of the directory containing the AntFTPFile.
              * of the full path of the file itself in case of AntFTPRootFile
@@ -938,6 +945,7 @@
             public String getCurpwd() {
                 return curpwd;
             }
+
             /**
              * returns the path of the directory containing the AntFTPFile.
              * of the full path of the file itself in case of AntFTPRootFile
@@ -949,6 +957,7 @@
                 String sep = task.getSeparator();
                 return curpwd.endsWith(sep) ? curpwd : curpwd + sep;
             }
+
             /**
              * find out if a symbolic link is encountered in the relative path of this file
              * from rootPath.
@@ -969,16 +978,19 @@
              * Get a string rep of this object.
              * @return a string containing the pwd and the file.
              */
+            @Override
             public String toString() {
                 return "AntFtpFile: " + curpwd + "%" + ftpFile;
             }
         }
+
         /**
          * special class to represent the remote directory itself
          * @since Ant 1.6
          */
         protected class AntFTPRootFile extends AntFTPFile {
             private String remotedir;
+
             /**
              * constructor
              * @param aclient FTP client
@@ -994,24 +1006,29 @@
                     throw new BuildException(ioe, task.getLocation());
                 }
             }
+
             /**
              * find the absolute path
              * @return absolute path
              */
+            @Override
             public String getAbsolutePath() {
                 return this.getCurpwd();
             }
+
             /**
              * find out the relative path to root
              * @return empty string
              * @throws BuildException actually never
              * @throws IOException  actually never
              */
+            @Override
             public String getRelativePath() throws BuildException, IOException {
                 return "";
             }
         }
     }
+
     /**
      * check FTPFiles to check whether they function as directories too
      * the FTPFile API seem to make directory and symbolic links incompatible
@@ -1026,7 +1043,8 @@
         String currentWorkingDir = null;
         if (file.isDirectory()) {
             return true;
-        } else if (file.isFile()) {
+        }
+        if (file.isFile()) {
             return false;
         }
         try {
@@ -1052,14 +1070,16 @@
                                           Project.MSG_ERR);
                 } finally {
                     if (!comeback) {
-                        throw new BuildException("could not cd back to " + dir //NOSONAR
-                                                 + " while checking a symlink");
+                        throw new BuildException(
+                            "could not cd back to %s while checking a symlink",
+                            dir);
                     }
                 }
             }
         }
         return result;
     }
+
     /**
      * check FTPFiles to check whether they function as directories too
      * the FTPFile API seem to make directory and symbolic links incompatible
@@ -1070,12 +1090,7 @@
      * @since ant 1.6
      */
     private boolean isFunctioningAsFile(FTPClient ftp, String dir, FTPFile file) {
-        if (file.isDirectory()) {
-            return false;
-        } else if (file.isFile()) {
-            return true;
-        }
-        return !isFunctioningAsDirectory(ftp, dir, file);
+        return !file.isDirectory() && (file.isFile() || !isFunctioningAsDirectory(ftp, dir, file));
     }
 
     /**
@@ -1091,7 +1106,6 @@
         h.execute(r, descr);
     }
 
-
     /**
      * For each file in the fileset, do the appropriate action: send, get,
      * delete, or list.
@@ -1122,16 +1136,15 @@
         } else {
             dsfiles = ds.getIncludedFiles();
         }
-        String dir = null;
 
-        if ((ds.getBasedir() == null)
-            && ((task.getAction() == FTPTask.SEND_FILES) || (task.getAction() == FTPTask.GET_FILES))) {
-            throw new BuildException("the dir attribute must be set for send "
-                                     + "and get actions");
-        } else {
-            if ((task.getAction() == FTPTask.SEND_FILES) || (task.getAction() == FTPTask.GET_FILES)) {
-                dir = ds.getBasedir().getAbsolutePath();
-            }
+        if (ds.getBasedir() == null
+            && (task.getAction() == FTPTask.SEND_FILES || task.getAction() == FTPTask.GET_FILES)) {
+            throw new BuildException(
+                "the dir attribute must be set for send and get actions");
+        }
+        String dir = null;
+        if (task.getAction() == FTPTask.SEND_FILES || task.getAction() == FTPTask.GET_FILES) {
+            dir = ds.getBasedir().getAbsolutePath();
         }
 
         // If we are doing a listing, we need the output stream created now.
@@ -1152,11 +1165,7 @@
                 // the trunk does not let itself be removed before the leaves
                 for (int i = dsfiles.length - 1; i >= 0; i--) {
                     final String dsfile = dsfiles[i];
-                    executeRetryable(h, new Retryable() {
-                            public void execute() throws IOException {
-                                rmDir(ftp, dsfile);
-                            }
-                        }, dsfile);
+                    executeRetryable(h, () -> rmDir(ftp, dsfile), dsfile);
                 }
             } else {
                 final BufferedWriter fbw = bw;
@@ -1166,30 +1175,28 @@
                                               .getMilliseconds(task.getAction()));
                 }
                 for (final String dsfile : dsfiles) {
-                    executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            switch (task.getAction()) {
-                                case FTPTask.SEND_FILES:
-                                    sendFile(ftp, fdir, dsfile);
-                                    break;
-                                case FTPTask.GET_FILES:
-                                    getFile(ftp, fdir, dsfile);
-                                    break;
-                                case FTPTask.DEL_FILES:
-                                    delFile(ftp, dsfile);
-                                    break;
-                                case FTPTask.LIST_FILES:
-                                    listFile(ftp, fbw, dsfile);
-                                    break;
-                                case FTPTask.CHMOD:
-                                    doSiteCommand(ftp, "chmod " + task.getChmod() + " "
-                                                  + resolveFile(dsfile));
-                                    transferred++;
-                                    break;
-                                default:
-                                    throw new BuildException("unknown ftp action "
-                                                             + task.getAction());
-                            }
+                    executeRetryable(h, () -> {
+                        switch (task.getAction()) {
+                            case FTPTask.SEND_FILES:
+                                sendFile(ftp, fdir, dsfile);
+                                break;
+                            case FTPTask.GET_FILES:
+                                getFile(ftp, fdir, dsfile);
+                                break;
+                            case FTPTask.DEL_FILES:
+                                delFile(ftp, dsfile);
+                                break;
+                            case FTPTask.LIST_FILES:
+                                listFile(ftp, fbw, dsfile);
+                                break;
+                            case FTPTask.CHMOD:
+                                doSiteCommand(ftp, "chmod " + task.getChmod() + " "
+                                        + resolveFile(dsfile));
+                                transferred++;
+                                break;
+                            default:
+                                throw new BuildException("unknown ftp action %s",
+                                        task.getAction());
                         }
                     }, dsfile);
                 }
@@ -1218,29 +1225,26 @@
         transferred = 0;
         skipped = 0;
 
-        if (task.getFilesets().size() == 0) {
+        if (task.getFilesets().isEmpty()) {
             throw new BuildException("at least one fileset must be specified.");
-        } else {
-            // get files from filesets
-            final int size = task.getFilesets().size();
-            for (int i = 0; i < size; i++) {
-                FileSet fs = (FileSet) task.getFilesets().elementAt(i);
-
-                if (fs != null) {
-                    transferFiles(ftp, fs);
-                }
+        }
+        // get files from filesets
+        for (FileSet fs : task.getFilesets()) {
+            if (fs != null) {
+                transferFiles(ftp, fs);
             }
         }
-
-        task.log(transferred + " " + FTPTask.ACTION_TARGET_STRS[task.getAction()] + " "
-                 + FTPTask.COMPLETED_ACTION_STRS[task.getAction()]);
+        task.log(
+            transferred + " " + FTPTask.ACTION_TARGET_STRS[task.getAction()]
+                + " " + FTPTask.COMPLETED_ACTION_STRS[task.getAction()]);
         if (skipped != 0) {
-            task.log(skipped + " " + FTPTask.ACTION_TARGET_STRS[task.getAction()]
-                     + " were not successfully " + FTPTask.COMPLETED_ACTION_STRS[task.getAction()]);
+            task.log(
+                skipped + " " + FTPTask.ACTION_TARGET_STRS[task.getAction()]
+                    + " were not successfully "
+                    + FTPTask.COMPLETED_ACTION_STRS[task.getAction()]);
         }
     }
 
-
     /**
      * Correct a file path to correspond to the remote host requirements. This
      * implementation currently assumes that the remote end can handle
@@ -1253,11 +1257,9 @@
      * @return the filename as it will appear on the server.
      */
     protected String resolveFile(String file) {
-        return file.replace(System.getProperty("file.separator").charAt(0),
-                            task.getSeparator().charAt(0));
+        return file.replace(File.separator.charAt(0), task.getSeparator().charAt(0));
     }
 
-
     /**
      * Creates all parent directories specified in a complete relative
      * pathname. Attempts to create existing directories will not cause
@@ -1278,7 +1280,7 @@
             return;
         }
 
-        Vector parents = new Vector();
+        Vector<File> parents = new Vector<>();
         String dirname;
 
         while ((dirname = dir.getParent()) != null) {
@@ -1298,13 +1300,14 @@
             String parent = dir.getParent();
             if (parent != null) {
                 if (!ftp.changeWorkingDirectory(resolveFile(parent))) {
-                    throw new BuildException("could not change to "
-                                             + "directory: " + ftp.getReplyString());
+                    throw new BuildException(
+                        "could not change to directory: %s",
+                        ftp.getReplyString());
                 }
             }
 
             while (i >= 0) {
-                dir = (File) parents.elementAt(i--);
+                dir = parents.elementAt(i--);
                 // check if dir exists by trying to change into it.
                 if (!ftp.changeWorkingDirectory(dir.getName())) {
                     // could not change to it - try to create it
@@ -1314,8 +1317,9 @@
                         handleMkDirFailure(ftp);
                     }
                     if (!ftp.changeWorkingDirectory(dir.getName())) {
-                        throw new BuildException("could not change to "
-                                                 + "directory: " + ftp.getReplyString());
+                        throw new BuildException(
+                            "could not change to directory: %s",
+                            ftp.getReplyString());
                     }
                 }
                 dirCache.add(dir);
@@ -1323,6 +1327,7 @@
             ftp.changeWorkingDirectory(cwd);
         }
     }
+
     /**
      * auto find the time difference between local and remote
      * @param ftp handle to ftp client
@@ -1336,12 +1341,11 @@
             // create a local temporary file
             FILE_UTILS.createNewFile(tempFile);
             long localTimeStamp = tempFile.lastModified();
-            BufferedInputStream instream = new BufferedInputStream(new FileInputStream(tempFile));
+            BufferedInputStream instream = new BufferedInputStream(Files.newInputStream(tempFile.toPath()));
             ftp.storeFile(tempFile.getName(), instream);
             instream.close();
-            boolean success = FTPReply.isPositiveCompletion(ftp.getReplyCode());
-            if (success) {
-                FTPFile [] ftpFiles = ftp.listFiles(tempFile.getName());
+            if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
+                FTPFile[] ftpFiles = ftp.listFiles(tempFile.getName());
                 if (ftpFiles.length == 1) {
                     long remoteTimeStamp = ftpFiles[0].getTimestamp().getTime().getTime();
                     returnValue = localTimeStamp - remoteTimeStamp;
@@ -1359,6 +1363,7 @@
         }
         return returnValue;
     }
+
     /**
      *  find a suitable name for local and remote temporary file
      */
@@ -1367,7 +1372,7 @@
         final int maxIterations = 1000;
         for (int counter = 1; counter < maxIterations; counter++) {
             File localFile = FILE_UTILS.createTempFile(task.getProject(),
-                                                       "ant" + Integer.toString(counter), ".tmp",
+                                                       "ant" + counter, ".tmp",
                                                        null, false, false);
             String fileName = localFile.getName();
             boolean found = false;
@@ -1420,10 +1425,9 @@
                 task.log("Could not date test remote file: " + remoteFile
                          + "assuming out of date.", Project.MSG_VERBOSE);
                 return false;
-            } else {
-                throw new BuildException("could not date test remote file: "
-                                         + ftp.getReplyString());
             }
+            throw new BuildException("could not date test remote file: %s",
+                ftp.getReplyString());
         }
 
         long remoteTimestamp = files[0].getTimestamp().getTime().getTime();
@@ -1431,16 +1435,16 @@
         long adjustedRemoteTimestamp = remoteTimestamp + task.getTimeDiffMillis()
             + task.getGranularityMillis();
 
-        StringBuffer msg;
+        StringBuilder msg;
         synchronized (TIMESTAMP_LOGGING_SDF) {
-            msg = new StringBuffer("   [")
+            msg = new StringBuilder("   [")
                 .append(TIMESTAMP_LOGGING_SDF.format(new Date(localTimestamp)))
                 .append("] local");
         }
         task.log(msg.toString(), Project.MSG_VERBOSE);
 
         synchronized (TIMESTAMP_LOGGING_SDF) {
-            msg = new StringBuffer("   [")
+            msg = new StringBuilder("   [")
                 .append(TIMESTAMP_LOGGING_SDF.format(new Date(adjustedRemoteTimestamp)))
                 .append("] remote");
         }
@@ -1455,9 +1459,8 @@
 
         if (task.getAction() == FTPTask.SEND_FILES) {
             return adjustedRemoteTimestamp >= localTimestamp;
-        } else {
-            return localTimestamp >= adjustedRemoteTimestamp;
         }
+        return localTimestamp >= adjustedRemoteTimestamp;
     }
 
 
@@ -1470,15 +1473,12 @@
      */
     protected void doSiteCommand(FTPClient ftp, String theCMD)
         throws IOException, BuildException {
-        boolean rc;
-        String[] myReply = null;
 
         task.log("Doing Site Command: " + theCMD, Project.MSG_VERBOSE);
 
-        rc = ftp.sendSiteCommand(theCMD);
-
-        if (!rc) {
-            task.log("Failed to issue Site Command: " + theCMD, Project.MSG_WARN);
+        if (!ftp.sendSiteCommand(theCMD)) {
+            task.log("Failed to issue Site Command: " + theCMD,
+                Project.MSG_WARN);
         } else {
             for (String reply : ftp.getReplyStrings()) {
                 if (!reply.contains("200")) {
@@ -1488,7 +1488,6 @@
         }
     }
 
-
     /**
      * Sends a single file to the remote host. <code>filename</code> may
      * contain a relative path specification. When this is the case, <code>sendFile</code>
@@ -1521,15 +1520,13 @@
                 task.log("transferring " + file.getAbsolutePath());
             }
 
-            instream = new BufferedInputStream(new FileInputStream(file));
+            instream = new BufferedInputStream(Files.newInputStream(file.toPath()));
 
             createParents(ftp, filename);
 
             ftp.storeFile(resolveFile(filename), instream);
 
-            boolean success = FTPReply.isPositiveCompletion(ftp.getReplyCode());
-
-            if (!success) {
+            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                 String s = "could not put file: " + ftp.getReplyString();
 
                 if (task.isSkipFailedTransfers()) {
@@ -1554,7 +1551,6 @@
         }
     }
 
-
     /**
      * Delete a file from the remote host.
      * @param ftp ftp client
@@ -1615,7 +1611,6 @@
         }
     }
 
-
     /**
      * Retrieve a single file from the remote host. <code>filename</code> may
      * contain a relative path specification. <p>
@@ -1652,7 +1647,7 @@
             if (!pdir.exists()) {
                 pdir.mkdirs();
             }
-            outstream = new BufferedOutputStream(new FileOutputStream(file));
+            outstream = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
             ftp.retrieveFile(resolveFile(filename), outstream);
 
             if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
@@ -1686,7 +1681,6 @@
         }
     }
 
-
     /**
      * List information about a single file from the remote host. <code>filename</code>
      * may contain a relative path specification. <p>
@@ -1715,7 +1709,6 @@
         }
     }
 
-
     /**
      * Create the specified directory on the remote host.
      *
@@ -1741,10 +1734,9 @@
         if (dir.startsWith("/")) {
             ftp.changeWorkingDirectory("/");
         }
-        String subdir = "";
         StringTokenizer st = new StringTokenizer(dir, "/");
         while (st.hasMoreTokens()) {
-            subdir = st.nextToken();
+            String subdir = st.nextToken();
             task.log("Checking " + subdir, Project.MSG_DEBUG);
             if (!ftp.changeWorkingDirectory(subdir)) {
                 if (!ftp.makeDirectory(subdir)) {
@@ -1752,9 +1744,8 @@
                     //  to indicate that an attempt to create a directory has
                     //  failed because the directory already exists.
                     int rc = ftp.getReplyCode();
-                    if (!(task.isIgnoreNoncriticalErrors() && (rc == CODE_550
-                                                               || rc == CODE_553
-                                                               || rc == CODE_521))) {
+                    if (!task.isIgnoreNoncriticalErrors()
+                            || rc != CODE_550 && rc != CODE_553 && rc != CODE_521) {
                         throw new BuildException("could not create directory: "
                                                  + ftp.getReplyString());
                     }
@@ -1783,14 +1774,14 @@
     private void handleMkDirFailure(FTPClient ftp)
         throws BuildException {
         int rc = ftp.getReplyCode();
-        if (!(task.isIgnoreNoncriticalErrors() && (rc == CODE_550
-                                                   || rc == CODE_553
-                                                   || rc == CODE_521))) {
+        if (!task.isIgnoreNoncriticalErrors()
+                || rc != CODE_550 && rc != CODE_553 && rc != CODE_521) {
             throw new BuildException("could not create directory: "
                                      + ftp.getReplyString());
         }
     }
 
+    @Override
     public void doFTP() throws BuildException {
         FTPClient ftp = null;
 
@@ -1805,8 +1796,8 @@
             ftp.setRemoteVerificationEnabled(task.getEnableRemoteVerification());
             ftp.connect(task.getServer(), task.getPort());
             if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                throw new BuildException("FTP connection failed: "
-                                         + ftp.getReplyString());
+                throw new BuildException("FTP connection failed: %s",
+                    ftp.getReplyString());
             }
 
             task.log("connected", Project.MSG_VERBOSE);
@@ -1821,24 +1812,21 @@
 
             if (task.isBinary()) {
                 ftp.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
-                if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                    throw new BuildException("could not set transfer type: "
-                                             + ftp.getReplyString());
-                }
             } else {
                 ftp.setFileType(org.apache.commons.net.ftp.FTP.ASCII_FILE_TYPE);
-                if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                    throw new BuildException("could not set transfer type: "
-                                             + ftp.getReplyString());
-                }
+            }
+            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
+                throw new BuildException("could not set transfer type: %s",
+                    ftp.getReplyString());
             }
 
             if (task.isPassive()) {
                 task.log("entering passive mode", Project.MSG_VERBOSE);
                 ftp.enterLocalPassiveMode();
                 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                    throw new BuildException("could not enter into passive "
-                                             + "mode: " + ftp.getReplyString());
+                    throw new BuildException(
+                        "could not enter into passive mode: %s",
+                        ftp.getReplyString());
                 }
             }
 
@@ -1847,55 +1835,46 @@
             // E.G. switching between a UNIX file system mode and
             // a legacy file system.
             if (task.getInitialSiteCommand() != null) {
-                RetryHandler h = new RetryHandler(task.getRetriesAllowed(), task);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            doSiteCommand(lftp, task.getInitialSiteCommand());
-                        }
-                    }, "initial site command: " + task.getInitialSiteCommand());
+                executeRetryable(new RetryHandler(task.getRetriesAllowed(), task),
+                    () -> doSiteCommand(lftp, task.getInitialSiteCommand()),
+                    "initial site command: " + task.getInitialSiteCommand());
             }
 
-
             // For a unix ftp server you can set the default mask for all files
             // created.
 
             if (task.getUmask() != null) {
-                RetryHandler h = new RetryHandler(task.getRetriesAllowed(), task);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            doSiteCommand(lftp, "umask " + task.getUmask());
-                        }
-                    }, "umask " + task.getUmask());
+                executeRetryable(
+                    new RetryHandler(task.getRetriesAllowed(), task),
+                    () -> doSiteCommand(lftp, "umask " + task.getUmask()),
+                    "umask " + task.getUmask());
             }
 
             // If the action is MK_DIR, then the specified remote
             // directory is the directory to create.
 
             if (task.getAction() == FTPTask.MK_DIR) {
-                RetryHandler h = new RetryHandler(task.getRetriesAllowed(), task);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            makeRemoteDir(lftp, task.getRemotedir());
-                        }
-                    }, task.getRemotedir());
+                executeRetryable(
+                    new RetryHandler(task.getRetriesAllowed(), task),
+                    () -> makeRemoteDir(lftp, task.getRemotedir()),
+                    task.getRemotedir());
             } else if (task.getAction() == FTPTask.SITE_CMD) {
-                RetryHandler h = new RetryHandler(task.getRetriesAllowed(), task);
                 final FTPClient lftp = ftp;
-                executeRetryable(h, new Retryable() {
-                        public void execute() throws IOException {
-                            doSiteCommand(lftp, task.getSiteCommand());
-                        }
-                    }, "Site Command: " + task.getSiteCommand());
+                executeRetryable(
+                    new RetryHandler(task.getRetriesAllowed(), task),
+                    () -> doSiteCommand(lftp, task.getSiteCommand()),
+                    "Site Command: " + task.getSiteCommand());
             } else {
                 if (task.getRemotedir() != null) {
                     task.log("changing the remote directory", Project.MSG_VERBOSE);
                     ftp.changeWorkingDirectory(task.getRemotedir());
                     if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
-                        throw new BuildException("could not change remote "
-                                                 + "directory: " + ftp.getReplyString());
+                        throw new BuildException(
+                            "could not change remote directory: %s",
+                            ftp.getReplyString());
                     }
                 }
                 if (task.isNewer() && task.isTimeDiffAuto()) {
@@ -1906,7 +1885,6 @@
                 task.log(FTPTask.ACTION_STRS[task.getAction()] + " " + FTPTask.ACTION_TARGET_STRS[task.getAction()]);
                 transferFiles(ftp);
             }
-
         } catch (IOException ex) {
             throw new BuildException("error during FTP transfer: " + ex, ex);
         } finally {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java
index fca4215..118f1f5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/MimeMail.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,19 +21,21 @@
 import org.apache.tools.ant.taskdefs.email.EmailTask;
 
 /**
- * A task to send SMTP email; Use <tt>mail</tt> instead
+ * A task to send SMTP email; Use <code>mail</code> instead
  *
  * @deprecated since 1.6.x.
  *             Use {@link EmailTask} instead.
  *
  * @since Ant1.4
  */
+@Deprecated
 public class MimeMail extends EmailTask {
     /**
      * Executes this build task.
      *
      * @exception BuildException On error.
      */
+    @Override
     public void execute()
         throws BuildException {
         log("DEPRECATED - The " + getTaskName() + " task is deprecated. "
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
index d88874f..12fae86 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/RExecTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Calendar;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.commons.net.bsd.RExecClient;
@@ -68,7 +68,7 @@
     /**
      *  The list of read/write commands for this session
      */
-    private Vector rexecTasks = new Vector();
+    private List<RExecSubTask> rexecTasks = new Vector<>();
 
     /**
      *  If true, adds a CR to beginning of login script
@@ -97,7 +97,7 @@
          */
         public void execute(AntRExecClient rexec)
                 throws BuildException {
-            throw new BuildException("Shouldn't be able instantiate a SubTask directly");
+            throw new BuildException("Shouldn't be able to instantiate a SubTask directly");
         }
 
         /**
@@ -127,6 +127,7 @@
          * @param rexec the task to use
          * @throws BuildException on error
          */
+        @Override
         public void execute(AntRExecClient rexec)
                throws BuildException {
            rexec.sendString(taskString, echoString);
@@ -153,6 +154,7 @@
          * @param rexec the task to use
          * @throws BuildException on error
          */
+        @Override
         public void execute(AntRExecClient rexec)
                throws BuildException {
             rexec.waitForString(taskString, timeout);
@@ -180,7 +182,7 @@
     /**
      *  This class handles the abstraction of the rexec protocol.
      *  Currently it is a wrapper around <a
-     *  href="http://jakarta.apache.org/commons/net/index.html">Jakarta
+     *  href="https://jakarta.apache.org/commons/net/index.html">Jakarta
      *  Commons Net</a>.
      */
     public class AntRExecClient extends RExecClient {
@@ -202,9 +204,9 @@
         public void waitForString(String s, Integer timeout) {
             InputStream is = this.getInputStream();
             try {
-                StringBuffer sb = new StringBuffer();
+                StringBuilder sb = new StringBuilder();
                 int windowStart = -s.length();
-                if (timeout == null || timeout.intValue() == 0) {
+                if (timeout == null || timeout == 0) {
                     while (windowStart < 0
                            || !sb.substring(windowStart).equals(s)) {
                         sb.append((char) is.read());
@@ -212,7 +214,7 @@
                     }
                 } else {
                     Calendar endTime = Calendar.getInstance();
-                    endTime.add(Calendar.SECOND, timeout.intValue());
+                    endTime.add(Calendar.SECOND, timeout);
                     while (windowStart < 0
                            || !sb.substring(windowStart).equals(s)) {
                         while (Calendar.getInstance().before(endTime)
@@ -253,6 +255,7 @@
                 throw new BuildException(e, getLocation());
             }
         }
+
         /**
          * Read from the rexec session until the EOF is found or
          * the timeout has been reached
@@ -261,44 +264,44 @@
         public void waitForEOF(Integer timeout) {
             InputStream is = this.getInputStream();
             try {
-                StringBuffer sb = new StringBuffer();
-                if (timeout == null || timeout.intValue() == 0) {
+                StringBuilder sb = new StringBuilder();
+                if (timeout == null || timeout == 0) {
                 int read;
                     while ((read = is.read()) != -1) {
                         char c = (char) read;
                         sb.append(c);
                         if (c == '\n') {
-                        log(sb.toString(), Project.MSG_INFO);
-                        sb.delete(0, sb.length());
+                            log(sb.toString(), Project.MSG_INFO);
+                            sb.delete(0, sb.length());
                         }
                     }
                 } else {
                     Calendar endTime = Calendar.getInstance();
-                    endTime.add(Calendar.SECOND, timeout.intValue());
-                int read = 0;
+                    endTime.add(Calendar.SECOND, timeout);
+                    int read = 0;
                     while (read != -1) {
                         while (Calendar.getInstance().before(endTime) && is.available() == 0) {
                             Thread.sleep(PAUSE_TIME);
                         }
                         if (is.available() == 0) {
-                        log(sb.toString(), Project.MSG_INFO);
-                            throw new BuildException(
-                                                     "Response timed-out waiting for EOF",
-                                                     getLocation());
+                            log(sb.toString(), Project.MSG_INFO);
+                                throw new BuildException(
+                                                         "Response timed-out waiting for EOF",
+                                                         getLocation());
                         }
-                        read =  is.read();
+                        read = is.read();
                         if (read != -1) {
-                        char c = (char) read;
-                        sb.append(c);
-                        if (c == '\n') {
+                            char c = (char) read;
+                            sb.append(c);
+                            if (c == '\n') {
                                 log(sb.toString(), Project.MSG_INFO);
                                 sb.delete(0, sb.length());
-                        }
+                            }
                         }
                     }
                 }
                 if (sb.length() > 0) {
-                log(sb.toString(), Project.MSG_INFO);
+                    log(sb.toString(), Project.MSG_INFO);
                 }
             } catch (BuildException be) {
                 throw be;
@@ -306,8 +309,8 @@
                 throw new BuildException(e, getLocation());
             }
         }
-
     }
+
     /**
      *  A string to wait for from the server.
      *  A subTask &lt;read&gt; tag was found.  Create the object,
@@ -316,10 +319,11 @@
      */
 
     public RExecSubTask createRead() {
-        RExecSubTask task = (RExecSubTask) new RExecRead();
-        rexecTasks.addElement(task);
+        RExecSubTask task = new RExecRead();
+        rexecTasks.add(task);
         return task;
     }
+
     /**
      *  Add text to send to the server
      *  A subTask &lt;write&gt; tag was found.  Create the object,
@@ -327,16 +331,18 @@
      * @return a write sub task
      */
     public RExecSubTask createWrite() {
-        RExecSubTask task = (RExecSubTask) new RExecWrite();
-        rexecTasks.addElement(task);
+        RExecSubTask task = new RExecWrite();
+        rexecTasks.add(task);
         return task;
     }
+
     /**
      *  Verify that all parameters are included.
      *  Connect and possibly login.
      *  Iterate through the list of Reads and writes.
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
         /**  A server name is required to continue */
         if (server == null) {
@@ -363,7 +369,7 @@
                 throw new BuildException("Can't connect to " + server);
             }
             if (userid != null && password != null && command != null //NOSONAR
-                && rexecTasks.size() == 0) {
+                && rexecTasks.isEmpty()) {
                 // simple one-shot execution
                 rexec.rexec(userid, password, command);
             } else {
@@ -384,13 +390,14 @@
                     String msg = "Error disconnecting from " + server;
                     if (success) {
                         throw new BuildException(msg); //NOSONAR
-                    } else { // don't hide inner exception
-                        log(msg, Project.MSG_ERR);
                     }
+                    // don't hide inner exception
+                    log(msg, Project.MSG_ERR);
                 }
             }
         }
     }
+
     /**
      *  Process a 'typical' login.  If it differs, use the read
      *  and write tasks explicitly
@@ -404,6 +411,7 @@
         rexec.waitForString("assword:");
         rexec.sendString(password, false);
     }
+
     /**
      * Set the the command to execute on the server;
      * @param c a <code>String</code> value
@@ -419,9 +427,10 @@
     public void setInitialCR(boolean b) {
         this.addCarriageReturn = b;
     }
+
     /**
      *  Set the the login password to use
-     * required if <tt>userid</tt> is set.
+     * required if <code>userid</code> is set.
      * @param p a <code>String</code> value
      */
     public void setPassword(String p) {
@@ -452,9 +461,10 @@
     public void setTimeout(Integer i) {
         this.defaultTimeout = i;
     }
+
     /**
      * Set the the login id to use on the server;
-     * required if <tt>password</tt> is set.
+     * required if <code>password</code> is set.
      * @param u a <code>String</code> value
      */
     public void setUserid(String u) {
@@ -473,9 +483,7 @@
             login(rexec);
         }
         /**  Process each sub command */
-        Enumeration tasksToRun = rexecTasks.elements();
-        while (tasksToRun != null && tasksToRun.hasMoreElements()) {
-            RExecSubTask task = (RExecSubTask) tasksToRun.nextElement();
+        for (RExecSubTask task : rexecTasks) {
             if (task instanceof RExecRead && defaultTimeout != null) {
                 ((RExecRead) task).setDefaultTimeout(defaultTimeout);
             }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/SetProxy.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/SetProxy.java
index 1e1f659..4dd70e5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/SetProxy.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/SetProxy.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -47,12 +47,12 @@
  * <pre>&lt;setproxy socksproxyhost=""/&gt;</pre>
  * stop using the socks server.
  * <p>
- * You can set a username and password for http with the <tt>proxyHost</tt>
- * and <tt>proxyPassword</tt> attributes. These can also be
+ * You can set a username and password for http with the <code>proxyHost</code>
+ * and <code>proxyPassword</code> attributes. These can also be
  * used against SOCKS5 servers.
  * </p>
- * @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/net/properties.html">
- *  java 1.5 network property list</a>
+ * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html">
+ *  https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html</a>
   *@since       Ant 1.5
  * @ant.task category="network"
  */
@@ -175,14 +175,13 @@
      * apply to all network connections
      * Relevant docs: buglist #4183340
      */
-
     public void applyWebProxySettings() {
         boolean settingsChanged = false;
         boolean enablingProxy = false;
         Properties sysprops = System.getProperties();
         if (proxyHost != null) {
             settingsChanged = true;
-            if (proxyHost.length() != 0) {
+            if (!proxyHost.isEmpty()) {
                 traceSettingInfo();
                 enablingProxy = true;
                 sysprops.put(ProxySetup.HTTP_PROXY_HOST, proxyHost);
@@ -217,7 +216,7 @@
         //socks
         if (socksProxyHost != null) {
             settingsChanged = true;
-            if (socksProxyHost.length() != 0) {
+            if (!socksProxyHost.isEmpty()) {
                 enablingProxy = true;
                 sysprops.put(ProxySetup.SOCKS_PROXY_HOST, socksProxyHost);
                 sysprops.put(ProxySetup.SOCKS_PROXY_PORT, Integer.toString(socksProxyPort));
@@ -261,6 +260,7 @@
      *
      * @exception BuildException thrown in unrecoverable error.
      */
+    @Override
     public void execute() throws BuildException {
         applyWebProxySettings();
     }
@@ -275,6 +275,7 @@
             auth = new PasswordAuthentication(user, pass.toCharArray());
         }
 
+        @Override
         protected PasswordAuthentication getPasswordAuthentication() {
             return auth;
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
index a89e7a9..cbc9f37 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/TelnetTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Calendar;
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import org.apache.commons.net.telnet.TelnetClient;
@@ -34,7 +34,6 @@
  * Automates the telnet protocol.
  *
  */
-
 public class TelnetTask extends Task {
     private static final int WAIT_INTERVAL = 250;
     private static final int TELNET_PORT = 23;
@@ -62,7 +61,7 @@
     /**
      *  The list of read/write commands for this session
      */
-    private Vector telnetTasks = new Vector();
+    private List<TelnetSubTask> telnetTasks = new Vector<>();
 
     /**
      *  If true, adds a CR to beginning of login script
@@ -81,6 +80,7 @@
      *  Iterate through the list of Reads and writes
      * @throws BuildException on error
      */
+    @Override
     public void execute() throws BuildException {
        /**  A server name is required to continue */
        if (server == null) {
@@ -111,9 +111,7 @@
                login(telnet);
            }
            /**  Process each sub command */
-           Enumeration tasksToRun = telnetTasks.elements();
-           while (tasksToRun != null && tasksToRun.hasMoreElements()) {
-               TelnetSubTask task = (TelnetSubTask) tasksToRun.nextElement();
+           for (TelnetSubTask task : telnetTasks) {
                if (task instanceof TelnetRead && defaultTimeout != null) {
                    ((TelnetRead) task).setDefaultTimeout(defaultTimeout);
                }
@@ -152,7 +150,7 @@
 
     /**
      * Set the the login id to use on the server;
-     * required if <tt>password</tt> is set.
+     * required if <code>password</code> is set.
      * @param u a <code>String</code> value
      */
     public void setUserid(String u) {
@@ -161,7 +159,7 @@
 
     /**
      *  Set the the login password to use
-     * required if <tt>userid</tt> is set.
+     * required if <code>userid</code> is set.
      * @param p a <code>String</code> value
      */
     public void setPassword(String p) {
@@ -209,8 +207,8 @@
      */
 
     public TelnetSubTask createRead() {
-        TelnetSubTask task = (TelnetSubTask) new TelnetRead();
-        telnetTasks.addElement(task);
+        TelnetSubTask task = new TelnetRead();
+        telnetTasks.add(task);
         return task;
     }
 
@@ -221,8 +219,8 @@
      * @return a write telnet sub task
      */
     public TelnetSubTask createWrite() {
-        TelnetSubTask task = (TelnetSubTask) new TelnetWrite();
-        telnetTasks.addElement(task);
+        TelnetSubTask task = new TelnetWrite();
+        telnetTasks.add(task);
         return task;
     }
 
@@ -271,6 +269,7 @@
          * @param telnet the task to use
          * @throws BuildException on error
          */
+        @Override
         public void execute(AntTelnetClient telnet)
                throws BuildException {
            telnet.sendString(taskString, echoString);
@@ -297,6 +296,7 @@
          * @param telnet the task to use
          * @throws BuildException on error
          */
+        @Override
         public void execute(AntTelnetClient telnet)
                throws BuildException {
             telnet.waitForString(taskString, timeout);
@@ -324,7 +324,7 @@
     /**
      *  This class handles the abstraction of the telnet protocol.
      *  Currently it is a wrapper around <a
-     *  href="http://jakarta.apache.org/commons/net/index.html">Jakarta
+     *  href="https://jakarta.apache.org/commons/net/index.html">Jakarta
      *  Commons Net</a>.
      */
     public class AntTelnetClient extends TelnetClient {
@@ -346,9 +346,9 @@
         public void waitForString(String s, Integer timeout) {
             InputStream is = this.getInputStream();
             try {
-                StringBuffer sb = new StringBuffer();
+                StringBuilder sb = new StringBuilder();
                 int windowStart = -s.length();
-                if (timeout == null || timeout.intValue() == 0) {
+                if (timeout == null || timeout == 0) {
                     while (windowStart < 0
                            || !sb.substring(windowStart).equals(s)) {
                         sb.append((char) is.read());
@@ -356,7 +356,7 @@
                     }
                 } else {
                     Calendar endTime = Calendar.getInstance();
-                    endTime.add(Calendar.SECOND, timeout.intValue());
+                    endTime.add(Calendar.SECOND, timeout);
                     while (windowStart < 0
                            || !sb.substring(windowStart).equals(s)) {
                         while (Calendar.getInstance().before(endTime)
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java b/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java
index 9644661..c31ae35 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,14 +20,13 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.text.MessageFormat;
 import java.text.ParseException;
-import java.util.Enumeration;
 import java.util.Random;
 import java.util.Vector;
 
@@ -46,7 +45,7 @@
  *
  * Extracts the latest edition of the source code from a PVCS repository.
  * PVCS is a version control system
- * developed by <a href="http://www.merant.com/products/pvcs">Merant</a>.
+ * developed by Merant.
  * <p>
  * Before using this tag, the user running ant must have access to the commands
  * of PVCS (get and pcli) and must have access to the repository. Note that the way to specify
@@ -79,10 +78,20 @@
     private static final int POS_2 = 2;
     private static final int POS_3 = 3;
 
+    /**
+     * Constant for the thing to execute
+     */
+    private static final String PCLI_EXE = "pcli";
+
+    /**
+     * Constant for the thing to execute
+     */
+    private static final String GET_EXE = "get";
+
     private String pvcsbin;
     private String repository;
     private String pvcsProject;
-    private Vector pvcsProjects;
+    private Vector<PvcsProject> pvcsProjects;
     private String workspace;
     private String force;
     private String promotiongroup;
@@ -94,21 +103,25 @@
     private String lineStart;
     private String userId;
     private String config;
-    /**
-     * Constant for the thing to execute
-     */
-    private static final String PCLI_EXE = "pcli";
-
-    /*
-     * Constant for the PCLI listversionedfiles recursive i a format "get" understands
-     */
-    // private static final String PCLI_LVF_ARGS = "lvf -z -aw";
 
     /**
-     * Constant for the thing to execute
+     * Creates a Pvcs object
      */
-    private static final String GET_EXE = "get";
-
+    public Pvcs() {
+        super();
+        pvcsProject = null;
+        pvcsProjects = new Vector<>();
+        workspace = null;
+        repository = null;
+        pvcsbin = null;
+        force = null;
+        promotiongroup = null;
+        label = null;
+        ignorerc = false;
+        updateOnly = false;
+        lineStart = "\"P:";
+        filenameFormat = "{0}-arc({1})";
+    }
 
     /**
      * Run the command.
@@ -124,7 +137,7 @@
             exe.setWorkingDirectory(aProj.getBaseDir());
             exe.setCommandline(cmd.getCommandline());
             return exe.execute();
-        } catch (java.io.IOException e) {
+        } catch (IOException e) {
             String msg = "Failed executing: " + cmd.toString()
                 + ". Exception: " + e.getMessage();
             throw new BuildException(msg, getLocation());
@@ -132,7 +145,7 @@
     }
 
     private String getExecutable(String exe) {
-        StringBuffer correctedExe = new StringBuffer();
+        StringBuilder correctedExe = new StringBuilder();
         if (getPvcsbin() != null) {
             if (pvcsbin.endsWith(File.separator)) {
                 correctedExe.append(pvcsbin);
@@ -146,10 +159,11 @@
     /**
      * @throws BuildException Something is stopping the build...
      */
-    public void execute() throws org.apache.tools.ant.BuildException {
+    @Override
+    public void execute() throws BuildException {
         int result = 0;
 
-        if (repository == null || repository.trim().equals("")) {
+        if (repository == null || repository.trim().isEmpty()) {
             throw new BuildException("Required argument repository not specified");
         }
 
@@ -183,12 +197,10 @@
             commandLine.createArgument().setValue(getPvcsproject());
         }
         if (!getPvcsprojects().isEmpty()) {
-            Enumeration e = getPvcsprojects().elements();
-            while (e.hasMoreElements()) {
-                String projectName = ((PvcsProject) e.nextElement()).getName();
-                if (projectName == null || (projectName.trim()).equals("")) {
-                    throw new BuildException("name is a required attribute "
-                        + "of pvcsproject");
+            for (PvcsProject pvcsProject : getPvcsprojects()) {
+                String projectName = pvcsProject.getName();
+                if (projectName == null || projectName.trim().isEmpty()) {
+                    throw new BuildException("name is a required attribute of pvcsproject");
                 }
                 commandLine.createArgument().setValue(projectName);
             }
@@ -199,7 +211,7 @@
         try {
             Random rand = new Random(System.currentTimeMillis());
             tmp = new File("pvcs_ant_" + rand.nextLong() + ".log");
-            FileOutputStream fos = new FileOutputStream(tmp);
+            OutputStream fos = Files.newOutputStream(tmp.toPath());
             tmp2 = new File("pvcs_ant_" + rand.nextLong() + ".log");
             log(commandLine.describeCommand(), Project.MSG_VERBOSE);
             try {
@@ -231,7 +243,7 @@
             commandLine.clearArgs();
             commandLine.setExecutable(getExecutable(GET_EXE));
 
-            if (getConfig() != null && getConfig().length() > 0) {
+            if (getConfig() != null && !getConfig().isEmpty()) {
                 commandLine.createArgument().setValue("-c" + getConfig());
             }
 
@@ -269,15 +281,7 @@
                 throw new BuildException(msg, getLocation());
             }
 
-        } catch (FileNotFoundException e) {
-            String msg = "Failed executing: " + commandLine.toString()
-                + ". Exception: " + e.getMessage();
-            throw new BuildException(msg, getLocation());
-        } catch (IOException e) {
-            String msg = "Failed executing: " + commandLine.toString()
-                + ". Exception: " + e.getMessage();
-            throw new BuildException(msg, getLocation());
-        } catch (ParseException e) {
+        } catch (ParseException | IOException e) {
             String msg = "Failed executing: " + commandLine.toString()
                 + ". Exception: " + e.getMessage();
             throw new BuildException(msg, getLocation());
@@ -295,9 +299,7 @@
      * Parses the file and creates the folders specified in the output section
      */
     private void createFolders(File file) throws IOException, ParseException {
-        BufferedReader in = null;
-        try {
-            in = new BufferedReader(new FileReader(file));
+        try (BufferedReader in = new BufferedReader(new FileReader(file))) {
             MessageFormat mf = new MessageFormat(getFilenameFormat());
             String line = in.readLine();
             while (line != null) {
@@ -315,7 +317,10 @@
                     int index = f.lastIndexOf(File.separator);
                     if (index > -1) {
                         File dir = new File(f.substring(0, index));
-                        if (!dir.exists()) {
+                        if (dir.exists()) {
+                            log(dir.getAbsolutePath() + " exists. Skipping",
+                                Project.MSG_VERBOSE);
+                        } else {
                             log("Creating " + dir.getAbsolutePath(),
                                 Project.MSG_VERBOSE);
                             if (dir.mkdirs() || dir.isDirectory()) {
@@ -326,9 +331,6 @@
                                     + dir.getAbsolutePath(),
                                     Project.MSG_INFO);
                             }
-                        } else {
-                            log(dir.getAbsolutePath() + " exists. Skipping",
-                                Project.MSG_VERBOSE);
                         }
                     } else {
                         log("File separator problem with " + line,
@@ -339,8 +341,6 @@
                 }
                 line = in.readLine();
             }
-        } finally {
-            FileUtils.close(in);
         }
     }
 
@@ -352,20 +352,13 @@
      */
     private void massagePCLI(File in, File out)
         throws IOException {
-        BufferedReader inReader = null;
-        BufferedWriter outWriter = null;
-        try {
-            inReader = new BufferedReader(new FileReader(in));
-            outWriter = new BufferedWriter(new FileWriter(out));
-            String s = null;
-            while ((s = inReader.readLine()) != null) {
-                String sNormal = s.replace('\\', '/');
-                outWriter.write(sNormal);
+        try (BufferedReader inReader = new BufferedReader(new FileReader(in));
+                BufferedWriter outWriter = new BufferedWriter(new FileWriter(out))) {
+            for (String line : (Iterable<String>) () -> inReader.lines()
+                    .map(s -> s.replace('\\', '/')).iterator()) {
+                outWriter.write(line);
                 outWriter.newLine();
             }
-        } finally {
-            FileUtils.close(inReader);
-            FileUtils.close(outWriter);
         }
     }
 
@@ -455,7 +448,7 @@
      * Get name of the project in the PVCS repository
      * @return Vector
      */
-    public Vector getPvcsprojects() {
+    public Vector<PvcsProject> getPvcsprojects() {
         return pvcsProjects;
     }
 
@@ -520,11 +513,7 @@
      * @param f String (yes/no)
      */
     public void setForce(String f) {
-        if (f != null && f.equalsIgnoreCase("yes")) {
-            force = "yes";
-        } else {
-            force = "no";
-        }
+        force = "yes".equalsIgnoreCase(f) ? "yes" : "no";
     }
 
     /**
@@ -651,23 +640,5 @@
         userId = u;
     }
 
-    /**
-     * Creates a Pvcs object
-     */
-    public Pvcs() {
-        super();
-        pvcsProject = null;
-        pvcsProjects = new Vector();
-        workspace = null;
-        repository = null;
-        pvcsbin = null;
-        force = null;
-        promotiongroup = null;
-        label = null;
-        ignorerc = false;
-        updateOnly = false;
-        lineStart = "\"P:";
-        filenameFormat = "{0}-arc({1})";
-    }
 }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/PvcsProject.java b/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/PvcsProject.java
index a8c6a2a..89cbee2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/PvcsProject.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/PvcsProject.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,11 +26,6 @@
 public class PvcsProject {
     private String name;
 
-    /** no arg constructor */
-    public PvcsProject() {
-        super();
-    }
-
     /**
      * Set the name of the project
      * @param name the value to use.
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
index ac9eb88..1c21cf2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,11 +21,12 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.AntTypeDefinition;
 import org.apache.tools.ant.BuildException;
@@ -36,11 +37,12 @@
 import org.apache.tools.ant.taskdefs.DefBase;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.util.ClasspathUtils;
+import org.apache.tools.ant.util.ScriptManager;
 import org.apache.tools.ant.util.ScriptRunnerBase;
 import org.apache.tools.ant.util.ScriptRunnerHelper;
 
 /**
- * Define a task using a script
+ * Defines a task using a script.
  *
  * @since Ant 1.6
  */
@@ -54,29 +56,36 @@
     private String name;
 
     /** Attributes definitions of this script */
-    private List attributes = new ArrayList();
+    private List<Attribute> attributes = new ArrayList<>();
 
     /** Nested Element definitions of this script */
-    private List nestedElements = new ArrayList();
+    private List<NestedElement> nestedElements = new ArrayList<>();
 
     /** The attribute names as a set */
-    private Set attributeSet;
+    private Set<String> attributeSet;
 
     /** The nested element definitions indexed by their names */
-    private Map nestedElementMap;
+    private Map<String, NestedElement> nestedElementMap;
 
     /**
-     * Set the project.
-     * @param project the project that this def belows to.
+     * Create a new {@link ScriptDef}.
      */
-    public void setProject(Project project) {
-        super.setProject(project);
-        helper.setProjectComponent(this);
+    public ScriptDef() {
         helper.setSetBeans(false);
     }
 
     /**
-     * set the name under which this script will be activated in a build
+     * Set the project.
+     * @param project the project that this definition belongs to.
+     */
+    @Override
+    public void setProject(Project project) {
+        super.setProject(project);
+        helper.setProjectComponent(this);
+    }
+
+    /**
+     * Sets the name under which this script will be activated in a build
      * file
      *
      * @param name the name of the script
@@ -103,18 +112,59 @@
         /** The attribute name */
         private String name;
 
+        /** The attribute's default value */
+        private String defaultValue;
+
         /**
-         * Set the attribute name
+         * Sets the attribute name.
          *
          * @param name the attribute name
          */
         public void setName(String name) {
             this.name = name.toLowerCase(Locale.ENGLISH);
         }
+
+        /**
+         * Get the name of this {@link Attribute}.
+         * 
+         * @return {@link String}
+         */
+        String getName() {
+            return name;
+        }
+
+        /**
+         * Set the default value of this {@link Attribute}.
+         *
+         * @param defaultValue {@link String}
+         * @since Ant 1.10.13
+         */
+        public void setDefault(String defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
+        /**
+         * Get the default value of this {@link Attribute}, {@code null} if
+         * unset.
+         * 
+         * @return {@link String}
+         * @since Ant 1.10.13
+         */
+        String getDefault() {
+            return defaultValue;
+        }
+
+        /**
+         * Learn whether this {@link Attribute} has a default value set.
+         * @return {@code boolean}
+         */
+        boolean hasDefault() {
+            return defaultValue != null;
+        }
     }
 
     /**
-     * Add an attribute definition to this script.
+     * Adds an attribute definition to this script.
      *
      * @param attribute the attribute definition.
      */
@@ -136,7 +186,7 @@
         private String className;
 
         /**
-         * set the tag name for this nested element
+         * Sets the tag name for this nested element
          *
          * @param name the name of this nested element
          */
@@ -145,7 +195,7 @@
         }
 
         /**
-         * Set the type of this element. This is the name of an
+         * Sets the type of this element. This is the name of an
          * Ant task or type which is to be used when this element is to be
          * created. This is an alternative to specifying the class name directly
          *
@@ -157,7 +207,7 @@
         }
 
         /**
-         * Set the classname of the class to be used for the nested element.
+         * Sets the classname of the class to be used for the nested element.
          * This specifies the class directly and is an alternative to specifying
          * the Ant type name.
          *
@@ -170,7 +220,7 @@
     }
 
     /**
-     * Add a nested element definition.
+     * Adds a nested element definition.
      *
      * @param nestedElement the nested element definition.
      */
@@ -179,17 +229,23 @@
     }
 
     /**
-     * Define the script.
+     * Defines the script.
      */
+    @Override
     public void execute() {
         if (name == null) {
-            throw new BuildException("scriptdef requires a name attribute to "
-                + "name the script");
+            throw new BuildException(
+                "scriptdef requires a name attribute to name the script");
         }
 
         if (helper.getLanguage() == null) {
-            throw new BuildException("<scriptdef> requires a language attribute "
-                + "to specify the script language");
+            throw new BuildException(
+                "scriptdef requires a language attribute to specify the script language");
+        }
+
+        if (helper.getSrc() == null && helper.getEncoding() != null) {
+            throw new BuildException(
+                "scriptdef requires a src attribute if the encoding is set");
         }
 
         // Check if need to set the loader
@@ -197,52 +253,47 @@
             helper.setClassLoader(createLoader());
         }
 
-        attributeSet = new HashSet();
-        for (Iterator i = attributes.iterator(); i.hasNext();) {
-            Attribute attribute = (Attribute) i.next();
+        attributeSet = new HashSet<>();
+        for (Attribute attribute : attributes) {
             if (attribute.name == null) {
-                throw new BuildException("scriptdef <attribute> elements "
-                    + "must specify an attribute name");
+                throw new BuildException(
+                    "scriptdef <attribute> elements must specify an attribute name");
             }
-
             if (attributeSet.contains(attribute.name)) {
-                throw new BuildException("scriptdef <" + name + "> declares "
-                    + "the " + attribute.name + " attribute more than once");
+                throw new BuildException(
+                    "scriptdef <%s> declares the %s attribute more than once",
+                    name, attribute.name);
             }
             attributeSet.add(attribute.name);
         }
 
-        nestedElementMap = new HashMap();
-        for (Iterator i = nestedElements.iterator(); i.hasNext();) {
-            NestedElement nestedElement = (NestedElement) i.next();
+        nestedElementMap = new HashMap<>();
+        for (NestedElement nestedElement : nestedElements) {
             if (nestedElement.name == null) {
-                throw new BuildException("scriptdef <element> elements "
-                    + "must specify an element name");
+                throw new BuildException(
+                    "scriptdef <element> elements must specify an element name");
             }
             if (nestedElementMap.containsKey(nestedElement.name)) {
-                throw new BuildException("scriptdef <" + name + "> declares "
-                    + "the " + nestedElement.name + " nested element more "
-                    + "than once");
+                throw new BuildException(
+                    "scriptdef <%s> declares the %s nested element more than once",
+                    name, nestedElement.name);
             }
 
             if (nestedElement.className == null
                 && nestedElement.type == null) {
-                throw new BuildException("scriptdef <element> elements "
-                    + "must specify either a classname or type attribute");
+                throw new BuildException(
+                    "scriptdef <element> elements must specify either a classname or type attribute");
             }
             if (nestedElement.className != null
                 && nestedElement.type != null) {
-                throw new BuildException("scriptdef <element> elements "
-                    + "must specify only one of the classname and type "
-                    + "attributes");
+                throw new BuildException(
+                    "scriptdef <element> elements must specify only one of the classname and type attributes");
             }
-
-
             nestedElementMap.put(nestedElement.name, nestedElement);
         }
 
         // find the script repository - it is stored in the project
-        Map scriptRepository = lookupScriptRepository();
+        Map<String, ScriptDef> scriptRepository = lookupScriptRepository();
         name = ProjectHelper.genComponentName(getURI(), name);
         scriptRepository.put(name, this);
         AntTypeDefinition def = new AntTypeDefinition();
@@ -253,18 +304,18 @@
     }
 
     /**
-     * Find or create the script repository - it is stored in the project.
+     * Finds or creates the script repository - it is stored in the project.
      * This method is synchronized on the project under {@link MagicNames#SCRIPT_REPOSITORY}
      * @return the current script repository registered as a reference.
      */
-    private Map lookupScriptRepository() {
-        Map scriptRepository = null;
+    private Map<String, ScriptDef> lookupScriptRepository() {
+        Map<String, ScriptDef> scriptRepository;
         Project p = getProject();
         synchronized (p) {
             scriptRepository =
-                    (Map) p.getReference(MagicNames.SCRIPT_REPOSITORY);
+                    p.getReference(MagicNames.SCRIPT_REPOSITORY);
             if (scriptRepository == null) {
-                scriptRepository = new HashMap();
+                scriptRepository = new HashMap<>();
                 p.addReference(MagicNames.SCRIPT_REPOSITORY,
                         scriptRepository);
             }
@@ -273,20 +324,20 @@
     }
 
     /**
-     * Create a nested element to be configured.
+     * Creates a nested element to be configured.
      *
      * @param elementName the name of the nested element.
      * @return object representing the element name.
      */
     public Object createNestedElement(String elementName) {
-        NestedElement definition
-            = (NestedElement) nestedElementMap.get(elementName);
+        NestedElement definition = nestedElementMap.get(elementName);
         if (definition == null) {
-            throw new BuildException("<" + name + "> does not support "
-                + "the <" + elementName + "> nested element");
+            throw new BuildException(
+                "<%s> does not support the <%s> nested element", name,
+                elementName);
         }
 
-        Object instance = null;
+        Object instance;
         String classname = definition.className;
         if (classname == null) {
             instance = getProject().createTask(definition.type);
@@ -294,11 +345,6 @@
                 instance = getProject().createDataType(definition.type);
             }
         } else {
-            /*
-            // try the context classloader
-            ClassLoader loader
-                = Thread.currentThread().getContextClassLoader();
-            */
             ClassLoader loader = createLoader();
 
             try {
@@ -306,31 +352,33 @@
             } catch (BuildException e) {
                 instance = ClasspathUtils.newInstance(classname, ScriptDef.class.getClassLoader());
             }
-
             getProject().setProjectReference(instance);
         }
 
         if (instance == null) {
-            throw new BuildException("<" + name + "> is unable to create "
-                + "the <" + elementName + "> nested element");
+            throw new BuildException(
+                "<%s> is unable to create the <%s> nested element", name,
+                elementName);
         }
         return instance;
     }
 
     /**
-     * Execute the script.
+     * Executes the script.
      *
      * @param attributes collection of attributes
      * @param elements a list of nested element values.
      * @deprecated since 1.7.
      *             Use executeScript(attribute, elements, instance) instead.
      */
-    public void executeScript(Map attributes, Map elements) {
+    @Deprecated
+    public void executeScript(Map<String, String> attributes,
+        Map<String, List<Object>> elements) {
         executeScript(attributes, elements, null);
     }
 
     /**
-     * Execute the script.
+     * Executes the script.
      * This is called by the script instance to execute the script for this
      * definition.
      *
@@ -338,9 +386,11 @@
      * @param elements   a list of nested element values.
      * @param instance   the script instance; can be null
      */
-    public void executeScript(Map attributes, Map elements, ScriptDefBase instance) {
+    public void executeScript(Map<String, String> attributes,
+        Map<String, List<Object>> elements, ScriptDefBase instance) {
         ScriptRunnerBase runner = helper.getScriptRunner();
-        runner.addBean("attributes", attributes);
+
+        runner.addBean("attributes", withDefault(attributes));
         runner.addBean("elements", elements);
         runner.addBean("project", getProject());
         if (instance != null) {
@@ -354,11 +404,20 @@
      *
      * @param manager the scripting manager.
      */
+    @Deprecated
     public void setManager(String manager) {
         helper.setManager(manager);
     }
 
     /**
+     * Set the script manager.
+     * @param manager
+     */
+    public void setManager(ScriptManager manager) {
+        helper.setManager(manager);
+    }
+
+    /**
      * Defines the language (required).
      *
      * @param language the scripting language name for the script.
@@ -368,7 +427,17 @@
     }
 
     /**
-     * Load the script from an external file ; optional.
+     * Defines the compilation feature; optional.
+     *
+     * @param compiled enables the script compilation if available.
+     * @since Ant 1.10.2
+     */
+    public void setCompiled(boolean compiled) {
+        helper.setCompiled(compiled);
+    }
+
+    /**
+     * Loads the script from an external file; optional.
      *
      * @param file the file containing the script source.
      */
@@ -377,7 +446,31 @@
     }
 
     /**
-     * Set the script text.
+     * Sets the encoding of the script from an external file; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public void setEncoding(String encoding) {
+        helper.setEncoding(encoding);
+    }
+
+    /**
+     * Set the setbeans attribute.
+     * If this is true, &lt;script&gt; will create variables in the
+     * script instance for all
+     * properties, targets and references of the current project.
+     * It this is false, only the project and self variables will
+     * be set.
+     * The default is true.
+     * @param setBeans the value to set.
+     */
+    public void setSetBeans(boolean setBeans) {
+        helper.setSetBeans(setBeans);
+    }
+
+    /**
+     * Sets the script text.
      *
      * @param text a component of the script text to be added.
      */
@@ -386,12 +479,35 @@
     }
 
     /**
-     * Add any source resource.
-     * @since Ant1.7.1
+     * Adds any source resource.
+     * @since Ant 1.7.1
      * @param resource source of script
      */
     public void add(ResourceCollection resource) {
         helper.add(resource);
     }
-}
 
+    private Map<String, String> withDefault(Map<String, String> attributes) {
+        /*
+         * The following is checked in ScriptDefBase but some other caller to
+         * #executeScript() could pass in anything they like
+         */
+        final Set<String> unsupported =
+            attributeSet.stream().filter(a -> !this.isAttributeSupported(a)).map(s -> '@' + s)
+                .collect(Collectors.toSet());
+
+        if (!unsupported.isEmpty()) {
+            throw new BuildException("Found unsupported attributes " + unsupported);
+        }
+        if (this.attributes.isEmpty()) {
+            return attributes;
+        }
+        final Map<String, String> result =
+            this.attributes.stream().filter(Attribute::hasDefault).collect(Collectors
+                .toMap(Attribute::getName, Attribute::getDefault, (l, r) -> r, LinkedHashMap::new));
+
+        result.putAll(attributes);
+
+        return result;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDefBase.java b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDefBase.java
index 95d15aa..8a0dd94 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDefBase.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDefBase.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,10 +36,10 @@
 public class ScriptDefBase extends Task implements DynamicConfigurator {
 
     /** Nested elements */
-    private Map nestedElementMap = new HashMap();
+    private Map<String, List<Object>> nestedElementMap = new HashMap<>();
 
     /** Attributes */
-    private Map attributes = new HashMap();
+    private Map<String, String> attributes = new HashMap<>();
 
     private String text;
 
@@ -47,19 +47,20 @@
      * Locate the script defining task and execute the script by passing
      * control to it
      */
+    @Override
     public void execute() {
         getScript().executeScript(attributes, nestedElementMap, this);
     }
 
     private ScriptDef getScript() {
         String name = getTaskType();
-        Map scriptRepository
-            = (Map) getProject().getReference(MagicNames.SCRIPT_REPOSITORY);
+        Map<String, ScriptDef> scriptRepository =
+            getProject().getReference(MagicNames.SCRIPT_REPOSITORY);
         if (scriptRepository == null) {
             throw new BuildException("Script repository not found for " + name);
         }
 
-        ScriptDef definition = (ScriptDef) scriptRepository.get(getTaskType());
+        ScriptDef definition = scriptRepository.get(getTaskType());
         if (definition == null) {
             throw new BuildException("Script definition not found for " + name);
         }
@@ -72,12 +73,10 @@
      * @param name the nested element name
      * @return the element to be configured
      */
+    @Override
     public Object createDynamicElement(String name)  {
-        List nestedElementList = (List) nestedElementMap.get(name);
-        if (nestedElementList == null) {
-            nestedElementList = new ArrayList();
-            nestedElementMap.put(name, nestedElementList);
-        }
+        List<Object> nestedElementList =
+            nestedElementMap.computeIfAbsent(name, k -> new ArrayList<>());
         Object element = getScript().createNestedElement(name);
         nestedElementList.add(element);
         return element;
@@ -89,13 +88,14 @@
      * @param name the attribute name.
      * @param value the attribute's string value
      */
+    @Override
     public void setDynamicAttribute(String name, String value) {
         ScriptDef definition = getScript();
         if (!definition.isAttributeSupported(name)) {
-                throw new BuildException("<" + getTaskType()
-                    + "> does not support the \"" + name + "\" attribute");
+            throw new BuildException(
+                "<%s> does not support the \"%s\" attribute", getTaskType(),
+                name);
         }
-
         attributes.put(name, value);
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOS.java b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOS.java
index be2e336..50cc745 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOS.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOS.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -388,6 +388,7 @@
      *
      * @throws BuildException on error.
      */
+    @Override
     public void execute()
         throws BuildException {
         int result = 0;
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckin.java b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckin.java
index 7a8a246..08605b9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckin.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckin.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -70,6 +70,7 @@
      *
      * @return    Commandline the generated command to be executed
      */
+    @Override
     protected Commandline buildCmdLine() {
         commandLine = new Commandline();
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckout.java b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckout.java
index 6994dfa..c673c95 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckout.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCheckout.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -59,6 +59,7 @@
      *
      * @return    Commandline the generated command to be executed
      */
+    @Override
     protected Commandline buildCmdLine() {
         commandLine = new Commandline();
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCmd.java b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCmd.java
index 9d7d543..7b67962 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCmd.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSCmd.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSGet.java b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSGet.java
index bd13959..0f357b2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSGet.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSGet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -79,6 +79,7 @@
      *
      * @return    Commandline the generated command to be executed
      */
+    @Override
     protected Commandline buildCmdLine() {
         commandLine = new Commandline();
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSLabel.java b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSLabel.java
index 21e8815..73481ff 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSLabel.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/SOSLabel.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -65,6 +65,7 @@
      *
      * @return    Commandline the generated command to be executed
      */
+    @Override
     protected Commandline buildCmdLine() {
         commandLine = new Commandline();
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sos/package.html b/src/main/org/apache/tools/ant/taskdefs/optional/sos/package.html
index 401c7d7..f0915ae 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sos/package.html
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sos/package.html
@@ -1,4 +1,4 @@
-<html>
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -15,15 +15,19 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
+<html lang="en">
+<head>
+  <title>SourceOffSite SCM tasks</title>
+</head>
 <body>
   <p>
     Ant tasks for working with a SourceOffSite source control system.
   </p>
-  <p>
-    The &lt;SOSGet&gt; Retrieves file(s) from a SOS database<br/>
-    The &lt;SOSCheckin&gt; Commits and unlocks file(s) in a SOS database<br/>
-    The &lt;SOSCheckout&gt; Retrieves and lock file(s) in a SOS database<br/>
-    The &lt;SOSLabel&gt; Label a SOS database
-  </p>
+  <dl>
+    <dt>&lt;SOSGet&gt;</dt><dd>Retrieves file(s) from a SOS database</dd>
+    <dt>&lt;SOSCheckin&gt;</dt><dd>Commits and unlocks file(s) in a SOS database</dd>
+    <dt>&lt;SOSCheckout&gt;</dt><dd>Retrieves and lock file(s) in a SOS database</dd>
+    <dt>&lt;SOSLabel&gt;</dt><dd>Label a SOS database</dd>
+  </dl>
 </body>
 </html>
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sound/AntSoundPlayer.java b/src/main/org/apache/tools/ant/taskdefs/optional/sound/AntSoundPlayer.java
index d1675a8..623fb61 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sound/AntSoundPlayer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sound/AntSoundPlayer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,7 +36,7 @@
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildListener;
 import org.apache.tools.ant.Project;
-
+import org.apache.tools.ant.util.FileUtils;
 
 
 /**
@@ -60,10 +60,6 @@
     private int loopsFail = 0;
     private Long durationFail = null;
 
-    /** Constructor for AntSoundPlayer. */
-    public AntSoundPlayer() {
-    }
-
     /**
      * @param file the location of the audio file to be played when the
      *        build is successful
@@ -102,7 +98,6 @@
 
         AudioInputStream audioInputStream = null;
 
-
         try {
             audioInputStream = AudioSystem.getAudioInputStream(file);
         } catch (UnsupportedAudioFileException uafe) {
@@ -114,8 +109,7 @@
 
         if (audioInputStream != null) {
             AudioFormat format = audioInputStream.getFormat();
-            DataLine.Info   info = new DataLine.Info(Clip.class, format,
-                                             AudioSystem.NOT_SPECIFIED);
+            DataLine.Info info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED);
             try {
                 try {
                     audioClip = (Clip) AudioSystem.getLine(info);
@@ -129,7 +123,7 @@
                 }
 
                 if (duration != null) {
-                    playClip(audioClip, duration.longValue());
+                    playClip(audioClip, duration);
                 } else {
                     playClip(audioClip, loops);
                 }
@@ -137,9 +131,7 @@
                     audioClip.drain();
                 }
             } finally {
-                if (audioClip != null) {
-                    audioClip.close();
-                }
+                FileUtils.close(audioClip);
             }
         } else {
             project.log("Can't get data from file " + file.getName());
@@ -182,6 +174,7 @@
      * clip if required.
      * @param event the line event to follow
      */
+    @Override
     public void update(LineEvent event) {
         if (event.getType().equals(LineEvent.Type.STOP)) {
             Line line = event.getLine();
@@ -194,6 +187,7 @@
      *  Fired before any targets are started.
      * @param event ignored
      */
+    @Override
     public void buildStarted(BuildEvent event) {
     }
 
@@ -203,6 +197,7 @@
      * @param event the build finished event.
      *  @see BuildEvent#getException()
      */
+    @Override
     public void buildFinished(BuildEvent event) {
         if (event.getException() == null && fileSuccess != null) {
             // build successful!
@@ -217,6 +212,7 @@
      * @param event ignored.
      *  @see BuildEvent#getTarget()
      */
+    @Override
     public void targetStarted(BuildEvent event) {
     }
 
@@ -226,6 +222,7 @@
      * @param event ignored.
      *  @see BuildEvent#getException()
      */
+    @Override
     public void targetFinished(BuildEvent event) {
     }
 
@@ -234,6 +231,7 @@
      * @param event ignored.
      *  @see BuildEvent#getTask()
      */
+    @Override
     public void taskStarted(BuildEvent event) {
     }
 
@@ -243,6 +241,7 @@
      * @param event ignored.
      *  @see BuildEvent#getException()
      */
+    @Override
     public void taskFinished(BuildEvent event) {
     }
 
@@ -252,6 +251,7 @@
      *  @see BuildEvent#getMessage()
      *  @see BuildEvent#getPriority()
      */
+    @Override
     public void messageLogged(BuildEvent event) {
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sound/SoundTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/sound/SoundTask.java
index 48e36b0..9193627 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sound/SoundTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sound/SoundTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -147,7 +147,7 @@
             if (source.exists()) {
                 if (source.isDirectory()) {
                     // get the list of files in the dir
-                    Vector<File> files = new Vector<File>();
+                    Vector<File> files = new Vector<>();
                     for (String file : source.list()) {
                         File f = new File(source, file);
                         if (f.isFile()) {
@@ -162,7 +162,7 @@
                     Random rn = new Random();
                     int x = rn.nextInt(numfiles);
                     // set the source to the file at that location
-                    this.source = (File) files.elementAt(x);
+                    this.source = files.elementAt(x);
                 }
             } else {
                 log(source + ": invalid path.", Project.MSG_WARN);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashScreen.java b/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashScreen.java
index 5de84cc..0c2e54f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashScreen.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashScreen.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,8 +37,10 @@
 
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.Project;
 
 class SplashScreen extends JWindow implements ActionListener, BuildListener {
+    private static final long serialVersionUID = 1L;
     private static final int FONT_SIZE = 12;
     private JLabel text;
     private JProgressBar pb;
@@ -118,6 +120,7 @@
         text.setText(txt);
     }
 
+    @Override
     public void actionPerformed(ActionEvent a) {
         if (!hasProgressPattern()) {
             if (total < MAX) {
@@ -129,31 +132,38 @@
         }
     }
 
+    @Override
     public void buildStarted(BuildEvent event) {
         actionPerformed(null);
     }
 
+    @Override
     public void buildFinished(BuildEvent event) {
         pb.setValue(MAX);
         setVisible(false);
         dispose();
     }
+    @Override
     public void targetStarted(BuildEvent event) {
         actionPerformed(null);
     }
 
+    @Override
     public void targetFinished(BuildEvent event) {
         actionPerformed(null);
     }
 
+    @Override
     public void taskStarted(BuildEvent event) {
         actionPerformed(null);
     }
 
+    @Override
     public void taskFinished(BuildEvent event) {
         actionPerformed(null);
     }
 
+    @Override
     public void messageLogged(BuildEvent event) {
         actionPerformed(null);
         if (hasProgressPattern()) {
@@ -162,12 +172,11 @@
             if (matcher != null && matcher.matches()) {
                 String gr = matcher.group(1);
                 try {
-                    int i = Math.min(new Integer(gr).intValue() * 2, MAX);
-                    pb.setValue(i);
+                    pb.setValue(Math.min(Integer.parseInt(gr) * 2, MAX));
                 } catch (NumberFormatException e) {
-                    //TODO: how to reach logger?!?
-                    //log("Number parsing error in progressRegExp", Project.MSG_VERBOSE);
-
+                    event.getProject().log(
+                        "Number parsing error in progressRegExp",
+                        Project.MSG_VERBOSE);
                 }
             }
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashTask.java
index 9d995bc..3518cf3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/splash/SplashTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,6 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
@@ -111,7 +110,7 @@
     }
 
     /**
-     * Proxy password; required if <tt>user</tt> is set.
+     * Proxy password; required if <code>user</code> is set.
      * @param password the proxy password
      * @deprecated since 1.5.x.
      *             Use org.apache.tools.ant.taskdefs.optional.net.SetProxy
@@ -183,8 +182,8 @@
                 sp.setProxyPassword(password);
                 sp.applyWebProxySettings();
 
-                if (useProxy && (proxy != null && proxy.length() > 0)
-                    && (port != null && port.length() > 0)) {
+                if (useProxy && (proxy != null && !proxy.isEmpty())
+                    && (port != null && !port.isEmpty())) {
 
                     log("Using proxied Connection",  Project.MSG_DEBUG);
                     System.getProperties().put("http.proxySet", "true");
@@ -192,7 +191,7 @@
                     URL url = new URL(imgurl);
 
                     conn = url.openConnection();
-                    if (user != null && user.length() > 0) {
+                    if (user != null && !user.isEmpty()) {
                         // converted from sun internal classes to
                         // new Base64Converter
                         // utility class extracted from Get task
@@ -237,9 +236,8 @@
 
         boolean success = false;
         if (in != null) {
-            DataInputStream din = new DataInputStream(in);
-            try {
-                ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            try (DataInputStream din = new DataInputStream(in);
+                 ByteArrayOutputStream bout = new ByteArrayOutputStream()) {
                 int data;
                 while ((data = din.read()) != -1) {
                     bout.write((byte) data);
@@ -257,15 +255,6 @@
             } catch (Exception e) {
                 throw new BuildException(e);
             } finally {
-                try {
-                    din.close();
-                } catch (IOException ioe) {
-                    // swallow if there was an error before so that
-                    // original error will be passed up
-                    if (success) {
-                        throw new BuildException(ioe); //NOSONAR
-                    }
-                }
             }
         } else {
             try {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/AbstractSshMessage.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/AbstractSshMessage.java
index 4ce07ff..8572011 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/AbstractSshMessage.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/AbstractSshMessage.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,10 +41,8 @@
     private final Session session;
     private final boolean verbose;
     private final boolean compressed;
-    private LogListener listener = new LogListener() {
-        public void log(final String message) {
-            // do nothing;
-        }
+    private LogListener listener = message -> {
+        // do nothing;
     };
 
     /**
@@ -97,9 +95,7 @@
      * @throws JSchException on error
      */
     protected ChannelSftp openSftpChannel() throws JSchException {
-        final ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
-
-        return channel;
+        return (ChannelSftp) session.openChannel("sftp");
     }
 
     /**
@@ -132,8 +128,9 @@
         if (b == -1) {
             // didn't receive any response
             throw new BuildException("No response from server");
-        } else if (b != 0) {
-            final StringBuffer sb = new StringBuffer();
+        }
+        if (b != 0) {
+            final StringBuilder sb = new StringBuilder();
 
             int c = in.read();
             while (c > 0 && c != '\n') {
@@ -270,12 +267,12 @@
         private long totalLength = 0;
         private int percentTransmitted = 0;
 
+        @Override
         public void init(final int op, final String src, final String dest, final long max) {
             initFileSize = max;
-            totalLength = 0;
-            percentTransmitted = 0;
         }
 
+        @Override
         public boolean count(final long len) {
             totalLength += len;
             percentTransmitted = trackProgress(initFileSize,
@@ -284,6 +281,7 @@
             return true;
         }
 
+        @Override
         public void end() {
         }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Directory.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Directory.java
index db857fc..493e9ed 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Directory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Directory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.StringTokenizer;
 
@@ -31,8 +32,8 @@
 public class Directory {
 
     private File directory;
-    private Set childDirectories;
-    private ArrayList files;
+    private Set<Directory> childDirectories;
+    private List<File> files;
     private Directory parent;
 
     /**
@@ -50,8 +51,8 @@
      */
     public Directory(File directory, Directory parent) {
         this.parent = parent;
-        this.childDirectories = new LinkedHashSet();
-        this.files = new ArrayList();
+        this.childDirectories = new LinkedHashSet<>();
+        this.files = new ArrayList<>();
         this.directory = directory;
     }
 
@@ -60,9 +61,7 @@
      * @param directory a Directory
      */
     public void addDirectory(Directory directory) {
-        if (!childDirectories.contains(directory)) {
-            childDirectories.add(directory);
-        }
+        childDirectories.add(directory);
     }
 
     /**
@@ -77,7 +76,7 @@
      * Get an iterator over the child Directories.
      * @return an iterator
      */
-    public Iterator directoryIterator() {
+    public Iterator<Directory> directoryIterator() {
         return childDirectories.iterator();
     }
 
@@ -85,7 +84,7 @@
      * Get an iterator over the files.
      * @return an iterator
      */
-    public Iterator filesIterator() {
+    public Iterator<File> filesIterator() {
         return files.iterator();
     }
 
@@ -119,8 +118,7 @@
      * @return the child directory, or null if not found
      */
     public Directory getChild(File dir) {
-        for (Iterator i = childDirectories.iterator(); i.hasNext();) {
-            Directory current = (Directory) i.next();
+        for (Directory current : childDirectories) {
             if (current.getDirectory().equals(dir)) {
                 return current;
             }
@@ -140,13 +138,12 @@
             return true;
         }
 
-        if (!(obj instanceof Directory)) {
-            return false;
+        if (obj instanceof Directory) {
+            Directory d = (Directory) obj;
+            return this.directory.equals(d.directory);
         }
 
-        Directory d = (Directory) obj;
-
-        return this.directory.equals(d.directory);
+        return false;
     }
 
     /**
@@ -175,7 +172,7 @@
     public static String[] getPath(String thePath) {
         StringTokenizer tokenizer = new StringTokenizer(thePath,
                 File.separator);
-        String[] path = new String[ tokenizer.countTokens() ];
+        String[] path = new String[tokenizer.countTokens()];
 
         int i = 0;
         while (tokenizer.hasMoreTokens()) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/LogListener.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/LogListener.java
index 41209ce..59e653d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/LogListener.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/LogListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHBase.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHBase.java
index 591d610..9677901 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHBase.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHBase.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,17 @@
 
 package org.apache.tools.ant.taskdefs.optional.ssh;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.jcraft.jsch.ConfigRepository;
+import com.jcraft.jsch.OpenSSHConfig;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Environment.Variable;
 
 import com.jcraft.jsch.JSch;
 import com.jcraft.jsch.JSchException;
@@ -42,8 +50,10 @@
     private boolean failOnError = true;
     private boolean verbose;
     private final SSHUserInfo userInfo;
+    private String sshConfig;
     private int serverAliveCountMax = 3;
     private int serverAliveIntervalSeconds = 0;
+    private final Map<String, String> additionalConfig = new HashMap<>();
 
     /**
      * Constructor for SSHBase.
@@ -107,6 +117,24 @@
     }
 
     /**
+     * Get the OpenSSH config file (~/.ssh/config).
+     * @return the OpenSSH config file
+     * @since Ant 1.10.8
+     */
+    public String getSshConfig() {
+        return sshConfig;
+    }
+
+    /**
+     * Set the OpenSSH config file (~/.ssh/config).
+     * @param sshConfig the OpenSSH config file
+     * @since Ant 1.10.8
+     */
+    public void setSshConfig(String sshConfig) {
+        this.sshConfig = sshConfig;
+    }
+
+    /**
      * Set the serverAliveCountMax value.
      * @param countMax int
      * @since Ant 1.9.7
@@ -223,11 +251,16 @@
         return port;
     }
 
+    public void addConfiguredAdditionalConfig(final Variable v) {
+        additionalConfig.put(v.getKey(), v.getValue());
+    }
+
     /**
      * Initialize the task.
      * This initializes the known hosts and sets the default port.
      * @throws BuildException on error
      */
+    @Override
     public void init() throws BuildException {
         super.init();
         this.knownHosts = System.getProperty("user.home") + "/.ssh/known_hosts";
@@ -235,6 +268,39 @@
     }
 
     /**
+     * Load the SSH configuration file.
+     * @throws BuildException on error
+     */
+    protected void loadSshConfig() throws BuildException {
+        if (sshConfig != null && (userInfo.getName() == null || userInfo.getKeyfile() == null)) {
+            if (!new File(sshConfig).exists()) {
+                throw new BuildException("The SSH configuration file specified doesn't exist: " + sshConfig);
+            }
+
+            log("Loading SSH configuration file " + sshConfig, Project.MSG_DEBUG);
+            ConfigRepository.Config config = null;
+            try {
+                config = OpenSSHConfig.parseFile(sshConfig).getConfig(host);
+            } catch (IOException e) {
+                throw new BuildException("Failed to load the SSH configuration file " + sshConfig, e);
+            }
+
+            if (config.getHostname() != null) {
+                host = config.getHostname();
+            }
+
+            if (userInfo.getName() == null) {
+                userInfo.setName(config.getUser());
+            }
+
+            if (userInfo.getKeyfile() == null) {
+                log("Using SSH key file " + config.getValue("IdentityFile") + " for host " + host, Project.MSG_INFO);
+                userInfo.setKeyfile(config.getValue("IdentityFile"));
+            }
+        }
+    }
+
+    /**
      * Open an ssh session.
      * @return the opened session
      * @throws JSchException on error
@@ -243,14 +309,17 @@
         final JSch jsch = new JSch();
         final SSHBase base = this;
         if (verbose) {
-            JSch.setLogger(new com.jcraft.jsch.Logger(){
-                    public boolean isEnabled(final int level){
-                        return true;
-                    }
-                    public void log(final int level, final String message){
-                        base.log(message, Project.MSG_INFO);
-                    }
-                });
+            JSch.setLogger(new com.jcraft.jsch.Logger() {
+                @Override
+                public boolean isEnabled(final int level) {
+                    return true;
+                }
+
+                @Override
+                public void log(final int level, final String message) {
+                    base.log(message, Project.MSG_INFO);
+                }
+            });
         }
         if (null != userInfo.getKeyfile()) {
             jsch.addIdentity(userInfo.getKeyfile());
@@ -271,6 +340,11 @@
             session.setServerAliveInterval(getServerAliveIntervalSeconds() * 1000);
         }
 
+        additionalConfig.forEach((k,v) -> {
+            log("Setting additional config value " + k, Project.MSG_DEBUG);
+            session.setConfig(k, v);
+        });
+
         log("Connecting to " + host + ":" + port);
         session.connect();
         return session;
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 13615a2..17dd431 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,17 +18,18 @@
 
 package org.apache.tools.ant.taskdefs.optional.ssh;
 
+import java.io.BufferedWriter;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -218,7 +219,7 @@
      *      will be stored.
      * @since Apache Ant 1.9.4
      */
-    public void setErrorproperty (final String property) {
+    public void setErrorproperty(final String property) {
         errorProperty = property;
     }
 
@@ -283,6 +284,9 @@
         if (getHost() == null) {
             throw new BuildException("Host is required.");
         }
+        
+        loadSshConfig();
+        
         if (getUserInfo().getName() == null) {
             throw new BuildException("Username is required.");
         }
@@ -298,18 +302,16 @@
             + (inputProperty != null ? 1 : 0)
             + (inputString != null ? 1 : 0);
         if (numberOfInputs > 1) {
-            throw new BuildException("You can't specify more than one of"
-                                     + " inputFile, inputProperty and"
-                                     + " inputString.");
+            throw new BuildException(
+                "You can't specify more than one of inputFile, inputProperty and inputString.");
         }
         if (inputFile != null && !inputFile.exists()) {
-            throw new BuildException("The input file "
-                                     + inputFile.getAbsolutePath()
-                                     + " does not exist.");
+            throw new BuildException("The input file %s does not exist.",
+                inputFile.getAbsolutePath());
         }
 
         Session session = null;
-        final StringBuffer output = new StringBuffer();
+        final StringBuilder output = new StringBuilder();
         try {
             session = openSession();
             /* called once */
@@ -317,32 +319,27 @@
                 log("cmd : " + command, Project.MSG_INFO);
                 executeCommand(session, command, output);
             } else { // read command resource and execute for each command
-                try {
-                    final BufferedReader br = new BufferedReader(
-                            new InputStreamReader(commandResource.getInputStream()));
-                    String cmd;
-                    while ((cmd = br.readLine()) != null) {
+                try (final BufferedReader br = new BufferedReader(
+                    new InputStreamReader(commandResource.getInputStream()))) {
+                    final Session s = session;
+                    br.lines().forEach(cmd -> {
                         log("cmd : " + cmd, Project.MSG_INFO);
                         output.append(cmd).append(" : ");
-                        executeCommand(session, cmd, output);
+                        executeCommand(s, cmd, output);
                         output.append("\n");
-                    }
-                    FileUtils.close(br);
+                    });
                 } catch (final IOException e) {
                     if (getFailonerror()) {
                         throw new BuildException(e);
-                    } else {
-                        log("Caught exception: " + e.getMessage(),
-                            Project.MSG_ERR);
                     }
+                    log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
                 }
             }
         } catch (final JSchException e) {
             if (getFailonerror()) {
                 throw new BuildException(e);
-            } else {
-                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
             }
+            log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
         } finally {
             if (outputProperty != null) {
                 getProject().setNewProperty(outputProperty, output.toString());
@@ -353,7 +350,7 @@
         }
     }
 
-    private void executeCommand(final Session session, final String cmd, final StringBuffer sb)
+    private void executeCommand(final Session session, final String cmd, final StringBuilder sb)
         throws BuildException {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
         final ByteArrayOutputStream errout = new ByteArrayOutputStream();
@@ -363,7 +360,7 @@
         InputStream istream = null;
         if (inputFile != null) {
             try {
-                istream = new FileInputStream(inputFile);
+                istream = Files.newInputStream(inputFile.toPath());
             } catch (final IOException e) {
                 // because we checked the existence before, this one
                 // shouldn't happen What if the file exists, but there
@@ -402,21 +399,18 @@
             channel.connect();
             // wait for it to finish
             thread =
-                new Thread() {
-                    @Override
-                    public void run() {
+                    new Thread(() -> {
                         while (!channel.isClosed()) {
                             if (thread == null) {
                                 return;
                             }
                             try {
-                                sleep(RETRY_INTERVAL);
+                                Thread.sleep(RETRY_INTERVAL);
                             } catch (final Exception e) {
                                 // ignored
                             }
                         }
-                    }
-                };
+                    });
 
             thread.start();
             thread.join(maxwait);
@@ -426,9 +420,8 @@
                 thread = null;
                 if (getFailonerror()) {
                     throw new BuildException(TIMEOUT_MESSAGE);
-                } else {
-                    log(TIMEOUT_MESSAGE, Project.MSG_ERR);
                 }
+                log(TIMEOUT_MESSAGE, Project.MSG_ERR);
             } else {
                 // stdout to outputFile
                 if (outputFile != null) {
@@ -453,9 +446,8 @@
                     final String msg = "Remote command failed with exit status " + ec;
                     if (getFailonerror()) {
                         throw new BuildException(msg);
-                    } else {
-                        log(msg, Project.MSG_ERR);
                     }
+                    log(msg, Project.MSG_ERR);
                 }
             }
         } catch (final BuildException e) {
@@ -464,23 +456,19 @@
             if (e.getMessage().contains("session is down")) {
                 if (getFailonerror()) {
                     throw new BuildException(TIMEOUT_MESSAGE, e);
-                } else {
-                    log(TIMEOUT_MESSAGE, Project.MSG_ERR);
                 }
+                log(TIMEOUT_MESSAGE, Project.MSG_ERR);
             } else {
                 if (getFailonerror()) {
                     throw new BuildException(e);
-                } else {
-                    log("Caught exception: " + e.getMessage(),
-                        Project.MSG_ERR);
                 }
+                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
             }
         } catch (final Exception e) {
             if (getFailonerror()) {
                 throw new BuildException(e);
-            } else {
-                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
             }
+            log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
         } finally {
             sb.append(out.toString());
             FileUtils.close(istream);
@@ -497,24 +485,20 @@
      */
     private void writeToFile(final String from, final boolean append, final File to)
         throws IOException {
-        FileWriter out = null;
-        try {
-            out = new FileWriter(to.getAbsolutePath(), append);
+        final StandardOpenOption appendOrTruncate = append ? StandardOpenOption.APPEND
+            : StandardOpenOption.TRUNCATE_EXISTING;
+        try (BufferedWriter out = Files.newBufferedWriter(to.getAbsoluteFile().toPath(),
+            appendOrTruncate, StandardOpenOption.CREATE)) {
             final StringReader in = new StringReader(from);
             final char[] buffer = new char[BUFFER_SIZE];
-            int bytesRead;
             while (true) {
-                bytesRead = in.read(buffer);
+                int bytesRead = in.read(buffer);
                 if (bytesRead == -1) {
                     break;
                 }
                 out.write(buffer, 0, bytesRead);
             }
             out.flush();
-        } finally {
-            if (out != null) {
-                out.close();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHSession.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHSession.java
index 6394c86..5c52246 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHSession.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHSession.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 package org.apache.tools.ant.taskdefs.optional.ssh;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
@@ -29,7 +28,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.TaskContainer;
-
 import com.jcraft.jsch.JSchException;
 import com.jcraft.jsch.Session;
 
@@ -45,10 +43,10 @@
     /** units are milliseconds, default is 0=infinite */
     private long maxwait = 0;
 
-    private final Vector localTunnels = new Vector();
-    private final Set localPortsUsed = new TreeSet();
-    private final Vector remoteTunnels = new Vector();
-    private final Set remotePortsUsed = new TreeSet();
+    private final List<LocalTunnel> localTunnels = new Vector<>();
+    private final Set<Integer> localPortsUsed = new TreeSet<>();
+    private final List<RemoteTunnel> remoteTunnels = new Vector<>();
+    private final Set<Integer> remotePortsUsed = new TreeSet<>();
     private NestedSequential nestedSequential = null;
 
     private static final String TIMEOUT_MESSAGE =
@@ -56,7 +54,7 @@
 
 
     /** Optional Vector holding the nested tasks */
-    private final Vector nestedTasks = new Vector();
+    private final List<Task> nestedTasks = new Vector<>();
 
     /**
      * Add a nested task to Sequential.
@@ -64,7 +62,7 @@
      * @param nestedTask Nested task to execute sequentially
      */
     public void addTask(final Task nestedTask) {
-        nestedTasks.addElement(nestedTask);
+        nestedTasks.add(nestedTask);
     }
 
     /**
@@ -87,7 +85,7 @@
      */
     public void setLocaltunnels(final String tunnels) {
         for (String tunnelSpec : tunnels.split(", ")) {
-            if (tunnelSpec.length() > 0) {
+            if (!tunnelSpec.isEmpty()) {
                 final String[] spec = tunnelSpec.split(":", 3);
                 final int lport = Integer.parseInt(spec[0]);
                 final String rhost = spec[1];
@@ -109,7 +107,7 @@
      */
     public void setRemotetunnels(final String tunnels) {
         for (String tunnelSpec : tunnels.split(", ")) {
-            if (tunnelSpec.length() > 0) {
+            if (!tunnelSpec.isEmpty()) {
                 final String[] spec = tunnelSpec.split(":", 3);
                 final int rport = Integer.parseInt(spec[0]);
                 final String lhost = spec[1];
@@ -134,6 +132,9 @@
         if (getHost() == null) {
             throw new BuildException("Host is required.");
         }
+        
+        loadSshConfig();
+        
         if (getUserInfo().getName() == null) {
             throw new BuildException("Username is required.");
         }
@@ -145,48 +146,38 @@
             throw new BuildException("Missing sequential element.");
         }
 
-
         Session session = null;
         try {
             // establish the session
             session = openSession();
             session.setTimeout((int) maxwait);
 
-            for (final Iterator i = localTunnels.iterator(); i.hasNext();) {
-                final LocalTunnel tunnel = (LocalTunnel) i.next();
+            for (LocalTunnel tunnel : localTunnels) {
                 session.setPortForwardingL(tunnel.getLPort(),
                                            tunnel.getRHost(),
                                            tunnel.getRPort());
             }
 
-            for (final Iterator i = remoteTunnels.iterator(); i.hasNext();) {
-                final RemoteTunnel tunnel = (RemoteTunnel) i.next();
+            for (RemoteTunnel tunnel : remoteTunnels) {
                 session.setPortForwardingR(tunnel.getRPort(),
                                            tunnel.getLHost(),
                                            tunnel.getLPort());
             }
 
-            for (final Iterator i = nestedSequential.getNested().iterator();
-                 i.hasNext();) {
-                final Task nestedTask = (Task) i.next();
-                nestedTask.perform();
-            }
+            nestedSequential.getNested().forEach(Task::perform);
             // completed successfully
 
         } catch (final JSchException e) {
             if (e.getMessage().contains("session is down")) {
                 if (getFailonerror()) {
                     throw new BuildException(TIMEOUT_MESSAGE, e);
-                } else {
-                    log(TIMEOUT_MESSAGE, Project.MSG_ERR);
                 }
+                log(TIMEOUT_MESSAGE, Project.MSG_ERR);
             } else {
                 if (getFailonerror()) {
                     throw new BuildException(e);
-                } else {
-                    log("Caught exception: " + e.getMessage(),
-                        Project.MSG_ERR);
                 }
+                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
             }
         } catch (final BuildException e) {
             // avoid wrapping it into yet another BuildException further down
@@ -194,9 +185,8 @@
         } catch (final Exception e) {
             if (getFailonerror()) {
                 throw new BuildException(e);
-            } else {
-                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
             }
+            log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
         } finally {
             if (session != null && session.isConnected()) {
                 session.disconnect();
@@ -217,34 +207,44 @@
     }
 
     public class LocalTunnel {
-        public LocalTunnel() {}
 
         int lport = 0;
         String rhost = null;
         int rport = 0;
+
         public void setLPort(final int lport) {
-            final Integer portKey = new Integer(lport);
+            final Integer portKey = lport;
             if (localPortsUsed.contains(portKey)) {
-                throw new BuildException("Multiple local tunnels defined to"
-                                         + " use same local port " + lport);
+                throw new BuildException(
+                    "Multiple local tunnels defined to use same local port %d",
+                    lport);
             }
             localPortsUsed.add(portKey);
             this.lport = lport;
         }
-        public void setRHost(final String rhost) { this.rhost = rhost; }
-        public void setRPort(final int rport) { this.rport = rport; }
+
+        public void setRHost(final String rhost) {
+            this.rhost = rhost;
+        }
+
+        public void setRPort(final int rport) {
+            this.rport = rport;
+        }
+
         public int getLPort() {
             if (lport == 0) {
                 throw new BuildException("lport is required for LocalTunnel.");
             }
             return lport;
         }
+
         public String getRHost() {
             if (rhost == null) {
                 throw new BuildException("rhost is required for LocalTunnel.");
             }
             return rhost;
         }
+
         public int getRPort() {
             if (rport == 0) {
                 throw new BuildException("rport is required for LocalTunnel.");
@@ -254,34 +254,44 @@
     }
 
     public class RemoteTunnel {
-        public RemoteTunnel() {}
 
         int lport = 0;
         String lhost = null;
         int rport = 0;
-        public void setLPort(final int lport) { this.lport = lport; }
-        public void setLHost(final String lhost) { this.lhost = lhost; }
+
+        public void setLPort(final int lport) {
+            this.lport = lport;
+        }
+
+        public void setLHost(final String lhost) {
+            this.lhost = lhost;
+        }
+
         public void setRPort(final int rport) {
-            final Integer portKey = new Integer(rport);
+            final Integer portKey = rport;
             if (remotePortsUsed.contains(portKey)) {
-                throw new BuildException("Multiple remote tunnels defined to"
-                                         + " use same remote port " + rport);
+                throw new BuildException(
+                    "Multiple remote tunnels defined to use same remote port %d",
+                    rport);
             }
             remotePortsUsed.add(portKey);
             this.rport = rport;
         }
+
         public int getLPort() {
             if (lport == 0) {
                 throw new BuildException("lport is required for RemoteTunnel.");
             }
             return lport;
         }
+
         public String getLHost() {
             if (lhost == null) {
                 throw new BuildException("lhost is required for RemoteTunnel.");
             }
             return lhost;
         }
+
         public int getRPort() {
             if (rport == 0) {
                 throw new BuildException("rport is required for RemoteTunnel.");
@@ -308,13 +318,14 @@
      * This is a simple task container.
      */
     public static class NestedSequential implements TaskContainer {
-        private final List<Task> nested = new ArrayList<Task>();
+        private final List<Task> nested = new ArrayList<>();
 
         /**
          * Add a task or type to the container.
          *
          * @param task an unknown element.
          */
+        @Override
         public void addTask(final Task task) {
             nested.add(task);
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHUserInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHUserInfo.java
index 54e7029..16d3b1f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHUserInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHUserInfo.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,8 +35,7 @@
 
     /** Constructor for SSHUserInfo. */
     public SSHUserInfo() {
-        super();
-        this.trustAllCertificates = false;
+        this(null, false);
     }
 
     /**
@@ -71,6 +70,7 @@
      * Gets the user's password.
      * @return the user's password
      */
+    @Override
     public String getPassword() {
         return password;
     }
@@ -135,6 +135,7 @@
      * Returns the passphrase.
      * @return String
      */
+    @Override
     public String getPassphrase() {
         return passphrase;
     }
@@ -160,6 +161,7 @@
      * @param message ignored
      * @return true always
      */
+    @Override
     public boolean promptPassphrase(String message) {
         return true;
     }
@@ -169,6 +171,7 @@
      * @param passwordPrompt ignored
      * @return true the first time this is called, false otherwise
      */
+    @Override
     public boolean promptPassword(String passwordPrompt) {
         return true;
     }
@@ -178,6 +181,7 @@
      * @param message ignored
      * @return the value of trustAllCertificates
      */
+    @Override
     public boolean promptYesNo(String message) {
         return trustAllCertificates;
     }
@@ -187,6 +191,7 @@
      * Implement the UserInfo interface (noop).
      * @param message ignored
      */
+    @Override
     public void showMessage(String message) {
         //log(message, Project.MSG_DEBUG);
     }
@@ -201,6 +206,7 @@
      * @return the password in an size one array if there is a password
      *         and if the prompt and echo checks pass.
      */
+    @Override
     public String[] promptKeyboardInteractive(String destination,
                                               String name,
                                               String instruction,
@@ -209,9 +215,7 @@
         if (prompt.length != 1 || echo[0] || this.password == null) {
             return null;
         }
-        String[] response = new String[1];
-        response[0] = this.password;
-        return response;
+        return new String[] { this.password };
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
index 4e04a46..3d181d3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,9 +21,9 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -165,11 +165,9 @@
 
     private static void validateRemoteUri(final String type, final String aToUri) {
         if (!isRemoteUri(aToUri)) {
-            throw new BuildException(type + " '" + aToUri + "' is invalid. "
-                                     + "The 'remoteToDir' attribute must "
-                                     + "have syntax like the "
-                                     + "following: user:password@host:/path"
-                                     + " - the :password part is optional");
+            throw new BuildException(
+                "%s '%s' is invalid. The 'remoteToDir' attribute must have syntax like the following: user:password@host:/path - the :password part is optional",
+                type, aToUri);
         }
     }
 
@@ -240,7 +238,7 @@
      */
     public void add(ResourceCollection res) {
         if (rcs == null) {
-            rcs = new LinkedList<ResourceCollection>();
+            rcs = new LinkedList<>();
         }
         rcs.add(res);
     }
@@ -282,24 +280,21 @@
                 throw new BuildException(
                     "Copying from a remote server to a remote server is not supported.");
             } else {
-                throw new BuildException("'todir' and 'file' attributes "
-                    + "must have syntax like the following: "
-                    + "user:password@host:/path");
+                throw new BuildException(
+                    "'todir' and 'file' attributes must have syntax like the following: user:password@host:/path");
             }
         } catch (final Exception e) {
             if (getFailonerror()) {
-                if(e instanceof BuildException) {
+                if (e instanceof BuildException) {
                     final BuildException be = (BuildException) e;
-                    if(be.getLocation() == null) {
+                    if (be.getLocation() == null) {
                         be.setLocation(getLocation());
                     }
                     throw be;
-                } else {
-                    throw new BuildException(e);
                 }
-            } else {
-                log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
+                throw new BuildException(e);
             }
+            log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
         }
     }
 
@@ -341,9 +336,8 @@
 
         Session session = null;
         try {
-            final List<Directory> list = new ArrayList<Directory>(rcs.size());
-            for (final Iterator<ResourceCollection> i = rcs.iterator(); i.hasNext();) {
-                final ResourceCollection rc = (ResourceCollection) i.next();
+            final List<Directory> list = new ArrayList<>(rcs.size());
+            for (ResourceCollection rc : rcs) {
                 if (rc instanceof FileSet && rc.isFilesystemOnly()) {
                     FileSet fs = (FileSet) rc;
                     final Directory d = createDirectory(fs);
@@ -351,15 +345,15 @@
                         list.add(d);
                     }
                 } else {
-                       List<Directory> ds = createDirectoryCollection(rc);
-                       if (ds !=null) {
-                               list.addAll(ds);
-                       }
+                    List<Directory> ds = createDirectoryCollection(rc);
+                    if (ds != null) {
+                        list.addAll(ds);
+                    }
                 }
             }
             if (!list.isEmpty()) {
                 session = openSession();
-                ScpToMessage message = null;
+                ScpToMessage message;
                 if (!isSftp) {
                     message = new ScpToMessage(getVerbose(), compressed, session,
                                                list, file, preserveLastModified);
@@ -369,10 +363,10 @@
                 }
                 message.setLogListener(this);
                 if (fileMode != null) {
-                    message.setFileMode(fileMode.intValue());
+                    message.setFileMode(fileMode);
                 }
                 if (dirMode != null) {
-                    message.setDirMode(dirMode.intValue());
+                    message.setDirMode(dirMode);
                 }
                 message.execute();
             }
@@ -404,10 +398,10 @@
             }
             message.setLogListener(this);
             if (fileMode != null) {
-                message.setFileMode(fileMode.intValue());
+                message.setFileMode(fileMode);
             }
             if (dirMode != null) {
-                message.setDirMode(dirMode.intValue());
+                message.setDirMode(dirMode);
             }
             message.execute();
         } finally {
@@ -441,59 +435,55 @@
             throw new BuildException("no username was given.  Can't authenticate.");
         }
 
-        if (getUserInfo().getPassword() == null
-            && getUserInfo().getKeyfile() == null) {
-            throw new BuildException("neither password nor keyfile for user "
-                                     + getUserInfo().getName() + " has been "
-                                     + "given.  Can't authenticate.");
-        }
-
         final int indexOfPath = uri.indexOf(':', indexOfAt + 1);
         if (indexOfPath == -1) {
-            throw new BuildException("no remote path in " + uri);
+            throw new BuildException("no remote path in %s", uri);
         }
 
         setHost(uri.substring(indexOfAt + 1, indexOfPath));
+        
+        loadSshConfig();
+        
+        if (getUserInfo().getPassword() == null
+            && getUserInfo().getKeyfile() == null) {
+            throw new BuildException(
+                "neither password nor keyfile for user %s has been given.  Can't authenticate.",
+                getUserInfo().getName());
+        }
+        
         String remotePath = uri.substring(indexOfPath + 1);
-        if (remotePath.equals("")) {
+        if (remotePath.isEmpty()) {
             remotePath = ".";
         }
         return remotePath;
     }
 
     private static boolean isRemoteUri(final String uri) {
-        boolean isRemote = true;
-        final int indexOfAt = uri.indexOf('@');
-        if (indexOfAt < 0) {
-            isRemote = false;
-        }
-        return isRemote;
+        return uri.contains("@");
     }
 
     private Directory createDirectory(final FileSet set) {
         final DirectoryScanner scanner = set.getDirectoryScanner(getProject());
-        Directory root = new Directory(scanner.getBasedir());
         final String[] files = scanner.getIncludedFiles();
-        if (files.length != 0) {
-            for (int j = 0; j < files.length; j++) {
-                final String[] path = Directory.getPath(files[j]);
-                Directory current = root;
-                File currentParent = scanner.getBasedir();
-                for (int i = 0; i < path.length; i++) {
-                    final File file = new File(currentParent, path[i]);
-                    if (file.isDirectory()) {
-                        current.addDirectory(new Directory(file));
-                        current = current.getChild(file);
-                        currentParent = current.getDirectory();
-                    } else if (file.isFile()) {
-                        current.addFile(file);
-                    }
+        if (files.length == 0) {
+            // skip
+            return null;
+        }
+        Directory root = new Directory(scanner.getBasedir());
+        Stream.of(files).map(Directory::getPath).forEach(path -> {
+            Directory current = root;
+            File currentParent = scanner.getBasedir();
+            for (String element : path) {
+                final File file = new File(currentParent, element);
+                if (file.isDirectory()) {
+                    current.addDirectory(new Directory(file));
+                    current = current.getChild(file);
+                    currentParent = current.getDirectory();
+                } else if (file.isFile()) {
+                    current.addFile(file);
                 }
             }
-        } else {
-            // skip
-            root = null;
-        }
+        });
         return root;
     }
 
@@ -503,21 +493,24 @@
             throw new BuildException("Only FileSystem resources are supported.");
         }
 
-        List<Directory> ds = new ArrayList<Directory>();
+        List<Directory> ds = new ArrayList<>();
         for (Resource r : rc) {
-               if (!r.isExists()) {
-                throw new BuildException("Could not find resource " + r.toLongString() + " to scp.");
+            if (!r.isExists()) {
+                throw new BuildException("Could not find resource %s to scp.",
+                        r.toLongString());
             }
 
             FileProvider fp = r.as(FileProvider.class);
             if (fp == null) {
-                throw new BuildException("Resource " + r.toLongString() + " is not a file.");
+                throw new BuildException("Resource %s is not a file.",
+                        r.toLongString());
             }
 
             FileResource fr = ResourceUtils.asFileResource(fp);
             File baseDir = fr.getBaseDir();
             if (baseDir == null) {
-                throw new BuildException("basedir for resource " + r.toLongString() + " is undefined.");
+                throw new BuildException("basedir for resource %s is undefined.",
+                        r.toLongString());
             }
 
             // if the basedir is set, the name will be relative to that
@@ -525,9 +518,8 @@
             Directory root = new Directory(baseDir);
             Directory current = root;
             File currentParent = baseDir;
-            final String[] path = Directory.getPath(name);
-            for (int i = 0; i < path.length; i++) {
-                final File file = new File(currentParent, path[i]);
+            for (String element : Directory.getPath(name)) {
+                final File file = new File(currentParent, element);
                 if (file.isDirectory()) {
                     current.addDirectory(new Directory(file));
                     current = current.getChild(file);
@@ -537,7 +529,7 @@
                 }
             }
             ds.add(root);
-       }
+        }
         return ds;
     }
 
@@ -560,15 +552,8 @@
     }
 
     private BuildException exactlyOne(final String[] attrs, final String alt) {
-        final StringBuffer buf = new StringBuffer("Exactly one of ").append(
-                '[').append(attrs[0]);
-        for (int i = 1; i < attrs.length; i++) {
-            buf.append('|').append(attrs[i]);
-        }
-        buf.append(']');
-        if (alt != null) {
-            buf.append(" or ").append(alt);
-        }
-        return new BuildException(buf.append(" is required.").toString());
+        return new BuildException("Exactly one of [%s]%s is required",
+                String.join("|", attrs),
+            alt == null ? "" : " or " + alt);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java
index 96be344..93e3554 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,10 +21,10 @@
 import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.util.FileUtils;
 
@@ -149,6 +149,7 @@
      * @throws IOException on i/o errors
      * @throws JSchException on errors detected by scp
      */
+    @Override
     public void execute() throws IOException, JSchException {
         String command = "scp -f ";
         if (isRecursive) {
@@ -220,9 +221,9 @@
 
     private File parseAndCreateDirectory(final String serverResponse,
                                          final File localFile) {
-        int start = serverResponse.indexOf(" ");
+        int start = serverResponse.indexOf(' ');
         // appears that the next token is not used and it's zero.
-        start = serverResponse.indexOf(" ", start + 1);
+        start = serverResponse.indexOf(' ', start + 1);
         final String directoryName = serverResponse.substring(start + 1);
         if (localFile.isDirectory()) {
             final File dir = new File(localFile, directoryName);
@@ -239,13 +240,13 @@
                                    final InputStream in)
         throws IOException, JSchException  {
         int start = 0;
-        int end = serverResponse.indexOf(" ", start + 1);
+        int end = serverResponse.indexOf(' ', start + 1);
         start = end + 1;
-        end = serverResponse.indexOf(" ", start + 1);
+        end = serverResponse.indexOf(' ', start + 1);
         final long filesize = Long.parseLong(serverResponse.substring(start, end));
         final String filename = serverResponse.substring(end + 1);
         log("Receiving: " + filename + " : " + filesize);
-        final File transferFile = (localFile.isDirectory())
+        final File transferFile = localFile.isDirectory()
                 ? new File(localFile, filename)
                 : localFile;
         fetchFile(transferFile, filesize, out, in);
@@ -262,7 +263,7 @@
         sendAck(out);
 
         // read a content of lfile
-        final FileOutputStream fos = new FileOutputStream(localFile);
+        final OutputStream fos = Files.newOutputStream(localFile.toPath());
         int length;
         long totalLength = 0;
         final long startTime = System.currentTimeMillis();
@@ -277,7 +278,7 @@
         try {
             while (true) {
                 length = in.read(buf, 0,
-                                 (BUFFER_SIZE < filesize) ? BUFFER_SIZE
+                                 BUFFER_SIZE < filesize ? BUFFER_SIZE
                                                           : (int) filesize);
                 if (length < 0) {
                     throw new EOFException("Unexpected end of stream.");
@@ -285,15 +286,14 @@
                 fos.write(buf, 0, length);
                 filesize -= length;
                 totalLength += length;
-                if (filesize == 0) {
-                    break;
-                }
-
                 if (trackProgress) {
                     percentTransmitted = trackProgress(initFilesize,
                                                        totalLength,
                                                        percentTransmitted);
                 }
+                if (filesize == 0) {
+                    break;
+                }
             }
         } finally {
             final long endTime = System.currentTimeMillis();
@@ -322,19 +322,17 @@
             channel.disconnect();
         }
         FileUtils.getFileUtils().setFileLastModified(localFile,
-                                                     ((long) fileAttributes
-                                                      .getMTime())
-                                                     * 1000);
+                ((long) fileAttributes.getMTime()) * 1000);
     }
 
     /**
      * returns the directory part of the remote file, if any.
      */
     private static String remoteDir(final String remoteFile) {
-        int index = remoteFile.lastIndexOf("/");
+        int index = remoteFile.lastIndexOf('/');
         if (index < 0) {
-            index = remoteFile.lastIndexOf("\\");
+            index = remoteFile.lastIndexOf('\\');
         }
-        return index > -1 ? remoteFile.substring(0, index + 1) : "";
+        return index < 0 ? "" : remoteFile.substring(0, index + 1);
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java
index 04f72d2..7e5edab 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,7 @@
 
 import java.io.File;
 import java.io.IOException;
-
+import java.util.List;
 import org.apache.tools.ant.util.FileUtils;
 
 import com.jcraft.jsch.ChannelSftp;
@@ -39,7 +39,9 @@
 
     private String remoteFile;
     private final File localFile;
+    @SuppressWarnings("unused")
     private boolean isRecursive = false;
+    @SuppressWarnings("unused")
     private boolean verbose = false;
 
     /**
@@ -103,6 +105,7 @@
      * @throws IOException on i/o errors
      * @throws JSchException on errors detected by scp
      */
+    @Override
     public void execute() throws IOException, JSchException {
         final ChannelSftp channel = openSftpChannel();
         try {
@@ -110,18 +113,15 @@
             try {
                 final SftpATTRS attrs = channel.stat(remoteFile);
                 if (attrs.isDir() && !remoteFile.endsWith("/")) {
-                    remoteFile = remoteFile + "/";
+                    remoteFile += "/";
                 }
             } catch (final SftpException ee) {
                 // Ignored
             }
             getDir(channel, remoteFile, localFile);
         } catch (final SftpException e) {
-            final JSchException schException = new JSchException("Could not get '"+ remoteFile
-                    +"' to '"+localFile+"' - "
-                    +e.toString());
-            schException.initCause(e);
-            throw schException;
+            throw new JSchException("Could not get '" + remoteFile + "' to '"
+                + localFile + "' - " + e.toString(), e);
         } finally {
             if (channel != null) {
                 channel.disconnect();
@@ -132,24 +132,30 @@
 
     private void getDir(final ChannelSftp channel,
                         final String remoteFile,
-                        final File localFile) throws IOException, SftpException {
+                        final File localFile) throws SftpException {
         String pwd = remoteFile;
-        if (remoteFile.lastIndexOf('/') != -1) {
+        final int lastIndexOfFileSeparator = remoteFile.lastIndexOf('/');
+        if (lastIndexOfFileSeparator != -1) {
             if (remoteFile.length() > 1) {
-                pwd = remoteFile.substring(0, remoteFile.lastIndexOf('/'));
+                if (lastIndexOfFileSeparator == 0) {
+                    // the file path is of the form "/foo....." i.e. the file separator
+                    // occurs at the start (and only there).
+                    pwd = "/";
+                } else {
+                    pwd = remoteFile.substring(0, lastIndexOfFileSeparator);
+                }
             }
         }
         channel.cd(pwd);
         if (!localFile.exists()) {
             localFile.mkdirs();
         }
-        final java.util.Vector files = channel.ls(remoteFile);
-        final int size = files.size();
-        for (int i = 0; i < size; i++) {
-            final ChannelSftp.LsEntry le = (ChannelSftp.LsEntry) files.elementAt(i);
+        @SuppressWarnings("unchecked")
+        final List<ChannelSftp.LsEntry> files = channel.ls(remoteFile);
+        for (ChannelSftp.LsEntry le : files) {
             final String name = le.getFilename();
             if (le.getAttrs().isDir()) {
-                if (name.equals(".") || name.equals("..")) {
+                if (".".equals(name) || "..".equals(name)) {
                     continue;
                 }
                 getDir(channel,
@@ -164,7 +170,7 @@
 
     private void getFile(final ChannelSftp channel,
                          final ChannelSftp.LsEntry le,
-                         File localFile) throws IOException, SftpException {
+                         File localFile) throws SftpException {
         final String remoteFile = le.getFilename();
         if (!localFile.exists()) {
             final String path = localFile.getAbsolutePath();
@@ -197,9 +203,7 @@
         }
         if (getPreserveLastModified()) {
             FileUtils.getFileUtils().setFileLastModified(localFile,
-                                                         ((long) le.getAttrs()
-                                                          .getMTime())
-                                                         * 1000);
+                    ((long) le.getAttrs().getMTime()) * 1000);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java
index 650804f..74029b7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,10 @@
 package org.apache.tools.ant.taskdefs.optional.ssh;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.Iterator;
 import java.util.List;
 
@@ -42,7 +42,7 @@
 
     private File localFile;
     private String remotePath;
-    private List directoryList;
+    private List<Directory> directoryList;
     private Integer fileMode, dirMode;
     private boolean preserveLastModified;
 
@@ -124,7 +124,7 @@
      */
     public ScpToMessage(final boolean verbose,
                         final Session session,
-                        final List aDirectoryList,
+                        final List<Directory> aDirectoryList,
                         final String aRemotePath,
                         final boolean preserveLastModified) {
         this(verbose, false, session, aDirectoryList, aRemotePath, preserveLastModified);
@@ -143,7 +143,7 @@
     public ScpToMessage(final boolean verbose,
                         final boolean compressed,
                         final Session session,
-                        final List aDirectoryList,
+                        final List<Directory> aDirectoryList,
                         final String aRemotePath,
                         final boolean preserveLastModified) {
         this(verbose, compressed, session, aRemotePath);
@@ -176,7 +176,7 @@
      */
     public ScpToMessage(final boolean verbose,
                         final Session session,
-                        final List aDirectoryList,
+                        final List<Directory> aDirectoryList,
                         final String aRemotePath) {
         this(verbose, session, aDirectoryList, aRemotePath, false);
     }
@@ -184,19 +184,6 @@
     /**
      * Constructor for ScpToMessage.
      * @param verbose if true do verbose logging
-     * @param session the scp session to use
-     * @param aRemotePath the remote path
-     * @since Ant 1.6.2
-     */
-    private ScpToMessage(final boolean verbose,
-                         final Session session,
-                         final String aRemotePath) {
-        this(verbose, false, session, aRemotePath);
-    }
-
-    /**
-     * Constructor for ScpToMessage.
-     * @param verbose if true do verbose logging
      * @param compressed if true use compression
      * @param session the scp session to use
      * @param aRemotePath the remote path
@@ -229,7 +216,7 @@
      * @param aRemotePath the remote path
      */
     public ScpToMessage(final Session session,
-                         final List aDirectoryList,
+                         final List<Directory> aDirectoryList,
                          final String aRemotePath) {
         this(false, session, aDirectoryList, aRemotePath);
     }
@@ -262,7 +249,6 @@
         final String cmd = sb.toString();
         final Channel channel = openExecChannel(cmd);
         try {
-
             final OutputStream out = channel.getOutputStream();
             final InputStream in = channel.getInputStream();
 
@@ -294,8 +280,7 @@
             channel.connect();
 
             waitForAck(in);
-            for (final Iterator i = directoryList.iterator(); i.hasNext();) {
-                final Directory current = (Directory) i.next();
+            for (Directory current : directoryList) {
                 sendDirectory(current, in, out);
             }
         } finally {
@@ -308,12 +293,11 @@
     private void sendDirectory(final Directory current,
                                final InputStream in,
                                final OutputStream out) throws IOException {
-        for (final Iterator fileIt = current.filesIterator(); fileIt.hasNext();) {
-            sendFileToRemote((File) fileIt.next(), in, out);
+        for (final Iterator<File> fileIt = current.filesIterator(); fileIt.hasNext();) {
+            sendFileToRemote(fileIt.next(), in, out);
         }
-        for (final Iterator dirIt = current.directoryIterator(); dirIt.hasNext();) {
-            final Directory dir = (Directory) dirIt.next();
-            sendDirectoryToRemote(dir, in, out);
+        for (final Iterator<Directory> dirIt = current.directoryIterator(); dirIt.hasNext();) {
+            sendDirectoryToRemote(dirIt.next(), in, out);
         }
     }
 
@@ -363,7 +347,6 @@
         waitForAck(in);
 
         // send a content of lfile
-        final FileInputStream fis = new FileInputStream(localFile);
         final byte[] buf = new byte[BUFFER_SIZE];
         final long startTime = System.currentTimeMillis();
         long totalLength = 0;
@@ -375,7 +358,7 @@
         final long initFilesize = filesize;
         int percentTransmitted = 0;
 
-        try {
+        try (InputStream fis = Files.newInputStream(localFile.toPath())) {
             if (this.getVerbose()) {
                 log("Sending: " + localFile.getName() + " : " + localFile.length());
             }
@@ -401,7 +384,6 @@
                 final long endTime = System.currentTimeMillis();
                 logStats(startTime, endTime, totalLength);
             }
-            fis.close();
         }
     }
 
@@ -436,7 +418,7 @@
      * @since Ant 1.9.5
      */
     public int getFileMode() {
-        return fileMode != null ? fileMode.intValue() : DEFAULT_FILE_MODE;
+        return fileMode != null ? fileMode : DEFAULT_FILE_MODE;
     }
 
     /**
@@ -454,7 +436,7 @@
      * @since Ant 1.9.5
      */
     public int getDirMode() {
-        return dirMode != null ? dirMode.intValue() : DEFAULT_DIR_MODE;
+        return dirMode != null ? dirMode : DEFAULT_DIR_MODE;
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java
index 093ce2a..c6266bf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,7 +38,7 @@
 
     private File localFile;
     private final String remotePath;
-    private List directoryList;
+    private List<Directory> directoryList;
     private final boolean preserveLastModified;
 
     /**
@@ -88,7 +88,7 @@
      */
     public ScpToMessageBySftp(final boolean verbose,
                               final Session session,
-                              final List aDirectoryList,
+                              final List<Directory> aDirectoryList,
                               final String aRemotePath) {
         this(verbose, session, aDirectoryList, aRemotePath, false);
     }
@@ -105,7 +105,7 @@
      */
     public ScpToMessageBySftp(final boolean verbose,
                               final Session session,
-                              final List aDirectoryList,
+                              final List<Directory> aDirectoryList,
                               final String aRemotePath,
                               final boolean preserveLastModified) {
         this(verbose, session, aRemotePath, preserveLastModified);
@@ -150,7 +150,7 @@
      * @param aRemotePath the remote path
      */
     public ScpToMessageBySftp(final Session session,
-                              final List aDirectoryList,
+                              final List<Directory> aDirectoryList,
                               final String aRemotePath) {
         this(false, session, aDirectoryList, aRemotePath);
     }
@@ -171,7 +171,7 @@
         log("done.\n");
     }
 
-    private void doSingleTransfer() throws IOException, JSchException {
+    private void doSingleTransfer() throws JSchException {
         final ChannelSftp channel = openSftpChannel();
         try {
             channel.connect();
@@ -212,21 +212,19 @@
                 throw new JSchException("Could not CD to '" + remotePath
                                         + "' - " + e.toString(), e);
             }
-            Directory current = null;
-            try {
-                for (final Iterator i = directoryList.iterator(); i.hasNext();) {
-                    current = (Directory) i.next();
+            for (Directory current : directoryList) {
+                try {
                     if (getVerbose()) {
                         log("Sending directory " + current);
                     }
                     sendDirectory(channel, current);
+                } catch (final SftpException e) {
+                    String msg = "Error sending directory";
+                    if (current != null && current.getDirectory() != null) {
+                        msg += " '" + current.getDirectory().getName() + "'";
+                    }
+                    throw new JSchException(msg, e);
                 }
-            } catch (final SftpException e) {
-                String msg = "Error sending directory";
-                if (current != null && current.getDirectory() != null) {
-                    msg += " '" + current.getDirectory().getName() + "'";
-                }
-                throw new JSchException(msg, e);
             }
         } finally {
             if (channel != null) {
@@ -238,12 +236,11 @@
     private void sendDirectory(final ChannelSftp channel,
                                final Directory current)
         throws IOException, SftpException {
-        for (final Iterator fileIt = current.filesIterator(); fileIt.hasNext();) {
-            sendFileToRemote(channel, (File) fileIt.next(), null);
+        for (final Iterator<File> fileIt = current.filesIterator(); fileIt.hasNext();) {
+            sendFileToRemote(channel, fileIt.next(), null);
         }
-        for (final Iterator dirIt = current.directoryIterator(); dirIt.hasNext();) {
-            final Directory dir = (Directory) dirIt.next();
-            sendDirectoryToRemote(channel, dir);
+        for (final Iterator<Directory> dirIt = current.directoryIterator(); dirIt.hasNext();) {
+            sendDirectoryToRemote(channel, dirIt.next());
         }
     }
 
@@ -268,7 +265,7 @@
     private void sendFileToRemote(final ChannelSftp channel,
                                   final File localFile,
                                   String remotePath)
-        throws IOException, SftpException {
+        throws SftpException {
         final long filesize = localFile.length();
 
         if (remotePath == null) {
@@ -329,6 +326,7 @@
      * Get the local file.
      * @return the local file.
      */
+    @Override
     public File getLocalFile() {
         return localFile;
     }
@@ -337,6 +335,7 @@
      * Get the remote path.
      * @return the remote path.
      */
+    @Override
     public String getRemotePath() {
         return remotePath;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/testing/BlockFor.java b/src/main/org/apache/tools/ant/taskdefs/optional/testing/BlockFor.java
index 4b2978a..758cb47 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/testing/BlockFor.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/testing/BlockFor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -54,6 +54,7 @@
      * @throws BuildTimeoutException on timeout, using the text in {@link #text}
      *
      */
+    @Override
     protected void processTimeout() throws BuildTimeoutException {
         super.processTimeout();
         throw new BuildTimeoutException(text, getLocation());
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/testing/BuildTimeoutException.java b/src/main/org/apache/tools/ant/taskdefs/optional/testing/BuildTimeoutException.java
index 143d08c..c805db5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/testing/BuildTimeoutException.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/testing/BuildTimeoutException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/testing/Funtest.java b/src/main/org/apache/tools/ant/taskdefs/optional/testing/Funtest.java
index 303a9d6..863be82 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/testing/Funtest.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/testing/Funtest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,6 +58,19 @@
  */
 
 public class Funtest extends Task {
+    /** {@value} */
+    public static final String WARN_OVERRIDING = "Overriding previous definition of ";
+    /** {@value} */
+    public static final String APPLICATION_FORCIBLY_SHUT_DOWN = "Application forcibly shut down";
+    /** {@value} */
+    public static final String SHUTDOWN_INTERRUPTED = "Shutdown interrupted";
+    /** {@value} */
+    public static final String SKIPPING_TESTS
+        = "Condition failed -skipping tests";
+    /** Application exception : {@value} */
+    public static final String APPLICATION_EXCEPTION = "Application Exception";
+    /** Teardown exception : {@value} */
+    public static final String TEARDOWN_EXCEPTION = "Teardown Exception";
 
     /**
      * A condition that must be true before the tests are run. This makes it
@@ -158,20 +171,6 @@
      */
     private BuildException taskException;
 
-    /** {@value} */
-    public static final String WARN_OVERRIDING = "Overriding previous definition of ";
-    /** {@value} */
-    public static final String APPLICATION_FORCIBLY_SHUT_DOWN = "Application forcibly shut down";
-    /** {@value} */
-    public static final String SHUTDOWN_INTERRUPTED = "Shutdown interrupted";
-    /** {@value} */
-    public static final String SKIPPING_TESTS
-        = "Condition failed -skipping tests";
-    /** Application exception : {@value} */
-    public static final String APPLICATION_EXCEPTION = "Application Exception";
-    /** Teardown exception : {@value} */
-    public static final String TEARDOWN_EXCEPTION = "Teardown Exception";
-
     /**
      * Log if the definition is overriding something
      *
@@ -378,8 +377,9 @@
      * @param role role of the task
      */
     private void validateTask(Task task, String role) {
-        if (task!=null && task.getProject() == null) {
-            throw new BuildException(role + " task is not bound to the project" + task);
+        if (task != null && task.getProject() == null) {
+            throw new BuildException("%s task is not bound to the project %s",
+                role, task);
         }
     }
 
@@ -392,6 +392,7 @@
      * test failing that is more important.
      * @throws BuildException if something was caught during the run or teardown.
      */
+    @Override
     public void execute() throws BuildException {
 
         //validation
@@ -561,12 +562,13 @@
     }
 
     private static class NestedCondition extends ConditionBase implements Condition {
+        @Override
         public boolean eval() {
             if (countConditions() != 1) {
                 throw new BuildException(
                     "A single nested condition is required.");
             }
-            return ((Condition) (getConditions().nextElement())).eval();
+            return getConditions().nextElement().eval();
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/unix/AbstractAccessTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/unix/AbstractAccessTask.java
index a2b53db..cf666dc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/unix/AbstractAccessTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/unix/AbstractAccessTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -69,9 +69,10 @@
      * @ant.attribute ignore="true"
      * @param cmdl A user supplied command line that we won't accept.
      */
+    @Override
     public void setCommand(Commandline cmdl) {
         throw new BuildException(getTaskType()
-                                 + " doesn\'t support the command attribute",
+                                 + " doesn't support the command attribute",
                                  getLocation());
     }
 
@@ -81,8 +82,9 @@
      * @ant.attribute ignore="true"
      * @param skip A user supplied boolean we won't accept.
      */
+    @Override
     public void setSkipEmptyFilesets(boolean skip) {
-        throw new BuildException(getTaskType() + " doesn\'t support the "
+        throw new BuildException(getTaskType() + " doesn't support the "
                                  + "skipemptyfileset attribute",
                                  getLocation());
     }
@@ -93,9 +95,10 @@
      * @ant.attribute ignore="true"
      * @param b A user supplied boolean we won't accept.
      */
+    @Override
     public void setAddsourcefile(boolean b) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the addsourcefile attribute", getLocation());
+            + " doesn't support the addsourcefile attribute", getLocation());
     }
 
     /**
@@ -103,6 +106,7 @@
      * @return true if a valid OS, for unix this is always true, otherwise
      *              use the superclasses' test (user set).
      */
+    @Override
     protected boolean isValidOs() {
         return getOs() == null && getOsFamily() == null
             ? Os.isFamily(Os.FAMILY_UNIX) : super.isValidOs();
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chgrp.java b/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chgrp.java
index cd2cc49..61b7b35 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chgrp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chgrp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -63,6 +63,7 @@
      * Ensure that all the required arguments and other conditions have
      * been set.
      */
+    @Override
     protected void checkConfiguration() {
         if (!haveGroup) {
             throw new BuildException("Required attribute group not set in "
@@ -76,9 +77,10 @@
      *
      * @param e User supplied executable that we won't accept.
      */
+    @Override
     public void setExecutable(String e) {
         throw new BuildException(getTaskType()
-                                 + " doesn\'t support the executable"
+                                 + " doesn't support the executable"
                                  + " attribute", getLocation());
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chown.java b/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chown.java
index 02a1c17..41745ec 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chown.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/unix/Chown.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -63,6 +63,7 @@
      * Ensure that all the required arguments and other conditions have
      * been set.
      */
+    @Override
     protected void checkConfiguration() {
         if (!haveOwner) {
             throw new BuildException("Required attribute owner not set in"
@@ -76,9 +77,10 @@
      *
      * @param e User supplied executable that we won't accept.
      */
+    @Override
     public void setExecutable(String e) {
         throw new BuildException(getTaskType()
-                                 + " doesn\'t support the executable"
+                                 + " doesn't support the executable"
                                  + " attribute", getLocation());
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java b/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java
index 86f199d..54d6811 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/unix/Symlink.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,28 +32,30 @@
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
-import java.util.Vector;
+import java.util.Set;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.dispatch.DispatchTask;
 import org.apache.tools.ant.dispatch.DispatchUtils;
-import org.apache.tools.ant.taskdefs.Execute;
 import org.apache.tools.ant.taskdefs.LogOutputStream;
 import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.SymbolicLinkUtils;
 
 /**
  * Creates, Deletes, Records and Restores Symlinks.
@@ -98,28 +100,14 @@
  * &lt;symlink action=&quot;delete&quot; link=&quot;${dir.top}/foo&quot;/&gt;
  * </pre>
  *
- * <p><strong>LIMITATIONS:</strong> Because Java has no direct support for
- * handling symlinks this task divines them by comparing canonical and
- * absolute paths. On non-unix systems this may cause false positives.
- * Furthermore, any operating system on which the command
- * <code>ln -s link resource</code> is not a valid command on the command line
- * will not be able to use action=&quot;delete&quot;, action=&quot;single&quot;
- * or action=&quot;recreate&quot;, but action=&quot;record&quot; should still
- * work. Finally, the lack of support for symlinks in Java means that all links
- * are recorded as links to the <strong>canonical</strong> resource name.
- * Therefore the link: <code>link --&gt; subdir/dir/../foo.bar</code> will be
- * recorded as <code>link=subdir/foo.bar</code> and restored as
- * <code>link --&gt; subdir/foo.bar</code>.</p>
- *
+ * <p><strong>Note:</strong> Starting Ant version 1.10.2, this task relies on the symbolic link support
+ * introduced in Java 7 through the {@link Files} APIs.
  */
 public class Symlink extends DispatchTask {
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    private static final SymbolicLinkUtils SYMLINK_UTILS =
-        SymbolicLinkUtils.getSymbolicLinkUtils();
 
     private String resource;
     private String link;
-    private Vector fileSets = new Vector();
+    private List<FileSet> fileSets = new ArrayList<>();
     private String linkFileName;
     private boolean overwrite;
     private boolean failonerror;
@@ -185,14 +173,18 @@
                 handleError("Must define the link name for symlink!");
                 return;
             }
+            final Path linkPath = Paths.get(link);
+            if (!Files.isSymbolicLink(linkPath)) {
+                log("Skipping deletion of " + linkPath + " since it's not a symlink", Project.MSG_VERBOSE);
+                // just ignore and silently return (this is consistent
+                // with the current, 1.9.x versions, of Ant)
+                return;
+
+            }
             log("Removing symlink: " + link);
-            SYMLINK_UTILS.deleteSymbolicLink(FILE_UTILS
-                                             .resolveFile(new File("."), link),
-                                             this);
-        } catch (FileNotFoundException fnfe) {
-            handleError(fnfe.toString());
+            deleteSymLink(linkPath);
         } catch (IOException ioe) {
-            handleError(ioe.toString());
+            handleError(ioe.getMessage());
         } finally {
             setDefaults();
         }
@@ -206,28 +198,34 @@
     public void recreate() throws BuildException {
         try {
             if (fileSets.isEmpty()) {
-                handleError("File set identifying link file(s) "
-                            + "required for action recreate");
+                handleError(
+                        "File set identifying link file(s) required for action recreate");
                 return;
             }
-            Properties links = loadLinks(fileSets);
-
-            for (Iterator kitr = links.keySet().iterator(); kitr.hasNext();) {
-                String lnk = (String) kitr.next();
-                String res = links.getProperty(lnk);
-                // handle the case where lnk points to a directory (bug 25181)
+            final Properties links = loadLinks(fileSets);
+            for (final String link : links.stringPropertyNames()) {
+                final String resource = links.getProperty(link);
                 try {
-                    File test = new File(lnk);
-                    if (!SYMLINK_UTILS.isSymbolicLink(lnk)) {
-                        doLink(res, lnk);
-                    } else if (!test.getCanonicalPath().equals(
-                        new File(res).getCanonicalPath())) {
-                        SYMLINK_UTILS.deleteSymbolicLink(test, this);
-                        doLink(res, lnk);
-                    } // else lnk exists, do nothing
-                } catch (IOException ioe) {
-                    handleError("IO exception while creating link");
+                    if (Files.isSymbolicLink(Paths.get(link)) &&
+                            new File(link).getCanonicalPath().equals(new File(resource).getCanonicalPath())) {
+                        // it's already a symlink and the symlink target is the same
+                        // as the target noted in the properties file. So there's no
+                        // need to recreate it
+                        log("not recreating " + link + " as it points to the correct target already",
+                            Project.MSG_DEBUG);
+                        continue;
+                    }
+                } catch (IOException e) {
+                    final String errMessage = "Failed to check if path " + link + " is a symbolic link, linking to " + resource;
+                    if (failonerror) {
+                        throw new BuildException(errMessage, e);
+                    }
+                    // log and continue
+                    log(errMessage, Project.MSG_INFO);
+                    continue;
                 }
+                // create the link
+                this.doLink(resource, link);
             }
         } finally {
             setDefaults();
@@ -249,38 +247,28 @@
                 handleError("Name of file to record links in required");
                 return;
             }
-            // create a hashtable to group them by parent directory:
-            Hashtable byDir = new Hashtable();
+            // create a map to group them by parent directory:
+            Map<File, List<File>> byDir = new HashMap<>();
 
             // get an Iterator of file objects representing links (canonical):
-            for (Iterator litr = findLinks(fileSets).iterator();
-                litr.hasNext();) {
-                File thisLink = (File) litr.next();
-                File parent = thisLink.getParentFile();
-                Vector v = (Vector) byDir.get(parent);
-                if (v == null) {
-                    v = new Vector();
-                    byDir.put(parent, v);
-                }
-                v.addElement(thisLink);
-            }
+            findLinks(fileSets).forEach(link -> byDir
+                .computeIfAbsent(link.getParentFile(), k -> new ArrayList<>())
+                .add(link));
+
             // write a Properties file in each directory:
-            for (Iterator dirs = byDir.keySet().iterator(); dirs.hasNext();) {
-                File dir = (File) dirs.next();
-                Vector linksInDir = (Vector) byDir.get(dir);
+            byDir.forEach((dir, linksInDir) -> {
                 Properties linksToStore = new Properties();
 
                 // fill up a Properties object with link and resource names:
-                for (Iterator dlnk = linksInDir.iterator(); dlnk.hasNext();) {
-                    File lnk = (File) dlnk.next();
+                for (File link : linksInDir) {
                     try {
-                        linksToStore.put(lnk.getName(), lnk.getCanonicalPath());
+                        linksToStore.put(link.getName(), link.getCanonicalPath());
                     } catch (IOException ioe) {
                         handleError("Couldn't get canonical name of parent link");
                     }
                 }
                 writePropertyFile(linksToStore, dir);
-            }
+            });
         } finally {
             setDefaults();
         }
@@ -335,10 +323,10 @@
     /**
      * Set the name of the link. Used when action = &quot;single&quot;.
      *
-     * @param lnk     The name for the link.
+     * @param link     The name for the link.
      */
-    public void setLink(String lnk) {
-        this.link = lnk;
+    public void setLink(String link) {
+        this.link = link;
     }
 
     /**
@@ -367,61 +355,49 @@
      * @param set      The fileset to add.
      */
     public void addFileset(FileSet set) {
-        fileSets.addElement(set);
+        fileSets.add(set);
     }
 
     /**
      * Delete a symlink (without deleting the associated resource).
      *
-     * <p>This is a convenience method that simply invokes
-     * <code>deleteSymlink(java.io.File)</code>.
+     * <p>This is a convenience method that simply invokes {@link #deleteSymlink(File)}</p>
      *
-     * @param path    A string containing the path of the symlink to delete.
+     * @param path A string containing the path of the symlink to delete.
+     * @throws IOException If the deletion attempt fails
      *
-     * @throws IOException             If calls to <code>File.rename</code>
-     *                                   or <code>File.delete</code> fail.
-     * @deprecated use
-     * org.apache.tools.ant.util.SymbolicLinkUtils#deleteSymbolicLink
-     * instead
+     * @deprecated use {@link Files#delete(Path)} instead
      */
     @Deprecated
-    public static void deleteSymlink(String path)
-        throws IOException {
-        SYMLINK_UTILS.deleteSymbolicLink(new File(path), null);
+    public static void deleteSymlink(final String path)
+            throws IOException {
+        deleteSymlink(Paths.get(path).toFile());
     }
 
     /**
      * Delete a symlink (without deleting the associated resource).
      *
-     * <p>This is a utility method that removes a unix symlink without removing
+     * <p>This is a utility method that removes a symlink without removing
      * the resource that the symlink points to. If it is accidentally invoked
-     * on a real file, the real file will not be harmed.</p>
+     * on a real file, the real file will not be harmed and instead this method
+     * returns silently.</p>
      *
-     * <p>This method works by
-     * getting the canonical path of the link, using the canonical path to
-     * rename the resource (breaking the link) and then deleting the link.
-     * The resource is then returned to its original name inside a finally
-     * block to ensure that the resource is unharmed even in the event of
-     * an exception.</p>
+     * <p>Since Ant 1.10.2 this method relies on the {@link Files#isSymbolicLink(Path)}
+     * and {@link Files#delete(Path)} to check and delete the symlink
+     * </p>
      *
-     * <p>Since Ant 1.8.0 this method will try to delete the File object if
-     * it reports it wouldn't exist (as symlinks pointing nowhere usually do).
-     * Prior version would throw a FileNotFoundException in that case.</p>
+     * @param linkfil A <code>File</code> object of the symlink to delete. Cannot be null.
+     * @throws IOException If the attempt to delete runs into exception
      *
-     * @param linkfil    A <code>File</code> object of the symlink to delete.
-     *
-     * @throws IOException             If calls to <code>File.rename</code>,
-     *                                   <code>File.delete</code> or
-     *                                   <code>File.getCanonicalPath</code>
-     *                                   fail.
-     * @deprecated use
-     * org.apache.tools.ant.util.SymbolicLinkUtils#deleteSymbolicLink
-     * instead
+     * @deprecated use {@link Files#delete(Path)} instead
      */
     @Deprecated
-    public static void deleteSymlink(File linkfil)
-        throws IOException {
-        SYMLINK_UTILS.deleteSymbolicLink(linkfil, null);
+    public static void deleteSymlink(final File linkfil)
+            throws IOException {
+        if (!Files.isSymbolicLink(linkfil.toPath())) {
+            return;
+        }
+        deleteSymLink(linkfil.toPath());
     }
 
     /**
@@ -434,15 +410,11 @@
      */
     private void writePropertyFile(Properties properties, File dir)
         throws BuildException {
-        BufferedOutputStream bos = null;
-        try {
-            bos = new BufferedOutputStream(
-                new FileOutputStream(new File(dir, linkFileName)));
+        try (BufferedOutputStream bos = new BufferedOutputStream(
+            Files.newOutputStream(new File(dir, linkFileName).toPath()))) {
             properties.store(bos, "Symlinks from " + dir);
         } catch (IOException ioe) {
             throw new BuildException(ioe, getLocation());
-        } finally {
-            FileUtils.close(bos);
         }
     }
 
@@ -463,38 +435,50 @@
     /**
      * Conduct the actual construction of a link.
      *
-     * <p>The link is constructed by calling <code>Execute.runCommand</code>.</p>
-     *
-     * @param res   The path of the resource we are linking to.
-     * @param lnk       The name of the link we wish to make.
+     * @param resource The path of the resource we are linking to.
+     * @param link The name of the link we wish to make.
      * @throws BuildException when things go wrong
      */
-    private void doLink(String res, String lnk) throws BuildException {
-        File linkfil = new File(lnk);
-        String options = "-s";
-        if (overwrite) {
-            options += "f";
-            if (linkfil.exists()) {
-                try {
-                    SYMLINK_UTILS.deleteSymbolicLink(linkfil, this);
-                } catch (FileNotFoundException fnfe) {
-                    log("Symlink disappeared before it was deleted: " + lnk);
-                } catch (IOException ioe) {
-                    log("Unable to overwrite preexisting link or file: " + lnk,
-                        ioe, Project.MSG_INFO);
+    private void doLink(String resource, String link) throws BuildException {
+        final Path linkPath = Paths.get(link);
+        final Path target = Paths.get(resource);
+        final boolean alreadyExists = Files.exists(linkPath, LinkOption.NOFOLLOW_LINKS);
+        if (!alreadyExists) {
+            // if the path (at which the link is expected to be created) isn't already present
+            // then we just go ahead and attempt to symlink
+            try {
+                log("creating symlink " + linkPath + " -> " + target, Project.MSG_DEBUG);
+                Files.createSymbolicLink(linkPath, target);
+            } catch (IOException e) {
+                if (failonerror) {
+                    throw new BuildException("Failed to create symlink " + link + " to target " + resource, e);
                 }
+                log("Unable to create symlink " + link + " to target " + resource, e, Project.MSG_INFO);
             }
+            return;
         }
-        String[] cmd = new String[] {"ln", options, res, lnk};
+        // file already exists, see if we are allowed to overwrite
+        if (!overwrite) {
+            log("Skipping symlink creation, since file at " + link + " already exists and overwrite is set to false", Project.MSG_INFO);
+            return;
+        }
+        // we have been asked to overwrite, so we now do the necessary steps
+
+        // initiate a deletion of the existing file
+        final boolean existingFileDeleted = linkPath.toFile().delete();
+        if (!existingFileDeleted) {
+            handleError("Deletion of file at " + link + " failed, while trying to overwrite it with a symlink");
+            return;
+        }
         try {
-            Execute.runCommand(this, cmd);
-        } catch (BuildException failedToExecute) {
+            log("creating symlink " + linkPath + " -> " + target + " after removing original",
+                Project.MSG_DEBUG);
+            Files.createSymbolicLink(linkPath, target);
+        } catch (IOException e) {
             if (failonerror) {
-                throw failedToExecute;
-            } else {
-                //log at the info level, and keep going.
-                log(failedToExecute.getMessage(), failedToExecute, Project.MSG_INFO);
+                throw new BuildException("Failed to create symlink " + link + " to target " + resource, e);
             }
+            log("Unable to create symlink " + link + " to target " + resource, e, Project.MSG_INFO);
         }
     }
 
@@ -505,33 +489,33 @@
      * &quot;record&quot;. This means that filesets are interpreted
      * as the directories in which links may be found.</p>
      *
-     * @param v   The filesets specified by the user.
-     * @return A HashSet of <code>File</code> objects containing the
-     *         links (with canonical parent directories).
+     * @param fileSets The filesets specified by the user.
+     * @return A Set of <code>File</code> objects containing the
+     * links (with canonical parent directories).
      */
-    private HashSet findLinks(Vector v) {
-        HashSet result = new HashSet();
-        final int size = v.size();
-        for (int i = 0; i < size; i++) {
-            FileSet fs = (FileSet) v.get(i);
+    private Set<File> findLinks(List<FileSet> fileSets) {
+        final Set<File> result = new HashSet<>();
+        for (FileSet fs : fileSets) {
             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
-            String[][] fnd = new String[][]
-                {ds.getIncludedFiles(), ds.getIncludedDirectories()};
+
             File dir = fs.getDir(getProject());
-            for (int j = 0; j < fnd.length; j++) {
-                for (int k = 0; k < fnd[j].length; k++) {
-                    try {
-                        File f = new File(dir, fnd[j][k]);
-                        File pf = f.getParentFile();
-                        String name = f.getName();
-                        if (SYMLINK_UTILS.isSymbolicLink(pf, name)) {
-                            result.add(new File(pf.getCanonicalFile(), name));
+
+            Stream.of(ds.getIncludedFiles(), ds.getIncludedDirectories())
+                    .flatMap(Stream::of).forEach(path -> {
+                        try {
+                            final File f = new File(dir, path);
+                            final File pf = f.getParentFile();
+                            final String name = f.getName();
+                            // we use the canonical path of the parent dir in which the (potential)
+                            // link resides
+                            final File parentDirCanonicalizedFile = new File(pf.getCanonicalPath(), name);
+                            if (Files.isSymbolicLink(parentDirCanonicalizedFile.toPath())) {
+                                result.add(parentDirCanonicalizedFile);
+                            }
+                        } catch (IOException e) {
+                            handleError("IOException: " + path + " omitted");
                         }
-                    } catch (IOException e) {
-                        handleError("IOException: " + fnd[j][k] + " omitted");
-                    }
-                }
-            }
+            });
         }
         return result;
     }
@@ -544,55 +528,72 @@
      * names of the property files with the link information and the
      * subdirectories in which to look for them.</p>
      *
-     * @param v    The <code>FileSet</code>s for this task.
+     * @param fileSets    The <code>FileSet</code>s for this task.
      * @return            The links to be made.
      */
-    private Properties loadLinks(Vector v) {
+    private Properties loadLinks(List<FileSet> fileSets) {
         Properties finalList = new Properties();
         // loop through the supplied file sets:
-        final int size = v.size();
-        for (int i = 0; i < size; i++) {
-            FileSet fs = (FileSet) v.elementAt(i);
+        for (FileSet fs : fileSets) {
             DirectoryScanner ds = new DirectoryScanner();
             fs.setupDirectoryScanner(ds, getProject());
             ds.setFollowSymlinks(false);
             ds.scan();
-            String[] incs = ds.getIncludedFiles();
             File dir = fs.getDir(getProject());
 
             // load included files as properties files:
-            for (int j = 0; j < incs.length; j++) {
-                File inc = new File(dir, incs[j]);
+            for (String name : ds.getIncludedFiles()) {
+                File inc = new File(dir, name);
                 File pf = inc.getParentFile();
-                Properties lnks = new Properties();
-                InputStream is = null;
-                try {
-                    is = new BufferedInputStream(new FileInputStream(inc));
-                    lnks.load(is);
+                Properties links = new Properties();
+                try (InputStream is = new BufferedInputStream(
+                    Files.newInputStream(inc.toPath()))) {
+                    links.load(is);
                     pf = pf.getCanonicalFile();
                 } catch (FileNotFoundException fnfe) {
-                    handleError("Unable to find " + incs[j] + "; skipping it.");
+                    handleError("Unable to find " + name + "; skipping it.");
                     continue;
                 } catch (IOException ioe) {
-                    handleError("Unable to open " + incs[j]
-                                + " or its parent dir; skipping it.");
+                    handleError("Unable to open " + name
+                        + " or its parent dir; skipping it.");
                     continue;
-                } finally {
-                    FileUtils.close(is);
                 }
-                lnks.list(new PrintStream(
-                    new LogOutputStream(this, Project.MSG_INFO)));
+                try {
+                    links.store(new PrintStream(
+                        new LogOutputStream(this, Project.MSG_INFO)),
+                        "listing properties");
+                } catch (IOException ex) {
+                    log("failed to log unshortened properties");
+                    links.list(new PrintStream(
+                        new LogOutputStream(this, Project.MSG_INFO)));
+                }
                 // Write the contents to our master list of links
                 // This method assumes that all links are defined in
                 // terms of absolute paths, or paths relative to the
                 // working directory:
-                for (Iterator kitr = lnks.keySet().iterator(); kitr.hasNext();) {
-                    String key = (String) kitr.next();
+                for (String key : links.stringPropertyNames()) {
                     finalList.put(new File(pf, key).getAbsolutePath(),
-                        lnks.getProperty(key));
+                        links.getProperty(key));
                 }
             }
         }
         return finalList;
     }
+
+    private static void deleteSymLink(final Path path) throws IOException {
+        // Implementation note: We intentionally use java.io.File#delete() instead of
+        // java.nio.file.Files#delete(Path) since it turns out that the latter doesn't
+        // update/clear the "canonical file paths cache" maintained by the JRE FileSystemProvider.
+        // Not clearing/updating that cache results in this deleted (and later recreated) symlink
+        // to point to a wrong/outdated target for a few seconds (30 seconds is the time the JRE
+        // maintains the cache entries for). All this is implementation detail of the JRE and
+        // is a JRE bug https://mail.openjdk.java.net/pipermail/core-libs-dev/2017-December/050540.html,
+        // but given that it affects our tests (SymlinkTest#testRecreate consistently fails
+        // on MacOS/Unix) as well as the Symlink task, it makes sense to use this API instead of
+        // the Files#delete(Path) API
+        final boolean deleted = path.toFile().delete();
+        if (!deleted) {
+            throw new IOException("Could not delete symlink at " + path);
+        }
+    }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java
index ce240e3..6448604 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -179,9 +179,8 @@
      * @throws BuildException if the command cannot execute.
      */
     public void execute() throws BuildException {
-        int result = 0;
         Commandline commandLine = buildCmdLine();
-        result = run(commandLine);
+        int result = run(commandLine);
         if (Execute.isFailure(result) && getFailOnError()) {
             String msg = "Failed executing: " + formatCommandLine(commandLine)
                      + " With a return code of " + result;
@@ -418,7 +417,7 @@
      */
     protected String getLabel() {
         String shortLabel = "";
-        if (label != null && label.length() > 0) {
+        if (label != null && !label.isEmpty()) {
                 shortLabel = FLAG_LABEL + getShortLabel();
         }
         return shortLabel;
@@ -464,7 +463,7 @@
             // Use getShortLabel() so labels longer then 30 char are truncated
             // and the user is warned
             String shortLabel = getShortLabel();
-            if (shortLabel != null && !shortLabel.equals("")) {
+            if (shortLabel != null && !shortLabel.isEmpty()) {
                 versionDateLabel = FLAG_VERSION_LABEL + shortLabel;
             }
         }
@@ -640,7 +639,7 @@
      * @return    True if the FailOnError flag has been set or if 'writablefiles=skip'.
      */
     private boolean getFailOnError() {
-        return getWritableFiles().equals(WRITABLE_SKIP) ? false : failOnError;
+        return !getWritableFiles().equals(WRITABLE_SKIP) && failOnError;
     }
 
 
@@ -746,7 +745,7 @@
      * @return The command line as a string with out the password
      */
     private String formatCommandLine(Commandline cmd) {
-        StringBuffer sBuff = new StringBuffer(cmd.toString());
+        final StringBuilder sBuff = new StringBuilder(cmd.toString());
         int indexUser = sBuff.substring(0).indexOf(FLAG_LOGIN);
         if (indexUser > 0) {
             int indexPass = sBuff.substring(0).indexOf(",", indexUser);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java
index 2e04e20..005a100 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java
index f9521aa..5eb0133 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java
index 4e56e0b..ec455c6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java
index 7d7edc2..a2b9eac 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java
index 26c3c8d..d44ddba 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java
index 9e5ec60..1efb4c7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java
index afecf95..763a783 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java
index 4fdc95d..d32f4cf 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -171,16 +171,21 @@
      */
     public void setStyle(BriefCodediffNofile attr) {
         String option = attr.getValue();
-        if (option.equals(STYLE_BRIEF)) {
-            super.setInternalStyle(FLAG_BRIEF);
-        } else if (option.equals(STYLE_CODEDIFF)) {
-            super.setInternalStyle(FLAG_CODEDIFF);
-        } else if (option.equals(STYLE_DEFAULT)) {
-            super.setInternalStyle("");
-        } else if (option.equals(STYLE_NOFILE)) {
-            super.setInternalStyle(FLAG_NO_FILE);
-        } else {
-            throw new BuildException("Style " + attr + " unknown.", getLocation());
+        switch (option) {
+            case STYLE_BRIEF:
+                super.setInternalStyle(FLAG_BRIEF);
+                break;
+            case STYLE_CODEDIFF:
+                super.setInternalStyle(FLAG_CODEDIFF);
+                break;
+            case STYLE_DEFAULT:
+                super.setInternalStyle("");
+                break;
+            case STYLE_NOFILE:
+                super.setInternalStyle(FLAG_NO_FILE);
+                break;
+            default:
+                throw new BuildException("Style " + attr + " unknown.", getLocation());
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java
index 6290f2e..0bb798f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,7 +41,7 @@
         }
 
         String label = getLabel();
-        if (label.equals("")) {
+        if (label.isEmpty()) {
             String msg = "label attribute must be set!";
             throw new BuildException(msg, getLocation());
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/windows/Attrib.java b/src/main/org/apache/tools/ant/taskdefs/optional/windows/Attrib.java
index 5c0b96a..8b89413 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/windows/Attrib.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/windows/Attrib.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -93,6 +93,7 @@
     /**
      * Check the attributes.
      */
+    @Override
     protected void checkConfiguration() {
         if (!haveAttr()) {
             throw new BuildException("Missing attribute parameter",
@@ -107,9 +108,10 @@
      * @param e ignored
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setExecutable(String e) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the executable attribute", getLocation());
+            + " doesn't support the executable attribute", getLocation());
     }
 
     /**
@@ -120,7 +122,7 @@
      */
     public void setCommand(String e) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the command attribute", getLocation());
+            + " doesn't support the command attribute", getLocation());
     }
 
     /**
@@ -129,9 +131,10 @@
      * @param b ignored
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setAddsourcefile(boolean b) {
         throw new BuildException(getTaskType()
-            + " doesn\'t support the addsourcefile attribute", getLocation());
+            + " doesn't support the addsourcefile attribute", getLocation());
     }
 
     /**
@@ -140,8 +143,9 @@
      * @param skip ignored
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setSkipEmptyFilesets(boolean skip) {
-        throw new BuildException(getTaskType() + " doesn\'t support the "
+        throw new BuildException(getTaskType() + " doesn't support the "
                                  + "skipemptyfileset attribute",
                                  getLocation());
     }
@@ -152,9 +156,10 @@
      * @param parallel ignored
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setParallel(boolean parallel) {
         throw new BuildException(getTaskType()
-                                 + " doesn\'t support the parallel attribute",
+                                 + " doesn't support the parallel attribute",
                                  getLocation());
     }
 
@@ -164,9 +169,10 @@
      * @param max ignored
      * @ant.attribute ignore="true"
      */
+    @Override
     public void setMaxParallel(int max) {
         throw new BuildException(getTaskType()
-                                 + " doesn\'t support the maxparallel attribute",
+                                 + " doesn't support the maxparallel attribute",
                                  getLocation());
     }
 
@@ -175,13 +181,14 @@
      * Default is to allow windows
      * @return true if the os is valid.
      */
+    @Override
     protected boolean isValidOs() {
         return getOs() == null && getOsFamily() == null
             ? Os.isFamily(Os.FAMILY_WINDOWS) : super.isValidOs();
     }
 
     private static String getSignString(boolean attr) {
-        return (attr ? SET : UNSET);
+        return attr ? SET : UNSET;
     }
 
     private void addArg(boolean sign, String attribute) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/xz/Unxz.java b/src/main/org/apache/tools/ant/taskdefs/optional/xz/Unxz.java
new file mode 100644
index 0000000..210f644
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/xz/Unxz.java
@@ -0,0 +1,87 @@
+/*
+ *  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
+ *
+ *      https://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.xz;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Unpack;
+import org.tukaani.xz.XZInputStream;
+
+/**
+ * Expands a file that has been compressed with the XZ
+ * algorithm. Normally used to compress non-compressed archives such
+ * as TAR files.
+ *
+ * @since Ant 1.10.1
+ *
+ * @ant.task category="packaging"
+ */
+
+public class Unxz extends Unpack {
+    private static final int BUFFER_SIZE = 8 * 1024;
+    private static final String DEFAULT_EXTENSION = ".xz";
+
+    /**
+     * Get the default extension.
+     * @return the value ".xz"
+     */
+    @Override
+    protected String getDefaultExtension() {
+        return DEFAULT_EXTENSION;
+    }
+
+    /**
+     * Implement the gunzipping.
+     */
+    @Override
+    protected void extract() {
+        if (srcResource.getLastModified() > dest.lastModified()) {
+            log("Expanding " + srcResource.getName() + " to "
+                        + dest.getAbsolutePath());
+
+            try (XZInputStream zIn =
+                new XZInputStream(srcResource.getInputStream());
+                    OutputStream out = Files.newOutputStream(dest.toPath())) {
+                byte[] buffer = new byte[BUFFER_SIZE];
+                int count = 0;
+                do {
+                    out.write(buffer, 0, count);
+                    count = zIn.read(buffer, 0, buffer.length);
+                } while (count != -1);
+            } catch (IOException ioe) {
+                String msg = "Problem expanding xz " + ioe.getMessage();
+                throw new BuildException(msg, ioe, getLocation());
+            }
+        }
+    }
+
+    /**
+     * Whether this task can deal with non-file resources.
+     *
+     * <p>This implementation returns true only.</p>
+     * @return true
+     */
+    @Override
+    protected boolean supportsNonFileResources() {
+        return true;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/xz/Xz.java b/src/main/org/apache/tools/ant/taskdefs/optional/xz/Xz.java
new file mode 100644
index 0000000..acd33c0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/xz/Xz.java
@@ -0,0 +1,63 @@
+/*
+ *  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
+ *
+ *      https://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.xz;
+
+import java.io.IOException;
+import java.nio.file.Files;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Pack;
+import org.tukaani.xz.LZMA2Options;
+import org.tukaani.xz.XZOutputStream;
+
+/**
+ * Compresses a file with the XZ algorithm. Normally used to compress
+ * non-compressed archives such as TAR files.
+ *
+ * @since Ant 1.10.1
+ *
+ * @ant.task category="packaging"
+ */
+
+public class Xz extends Pack {
+    /**
+     * Compress the zipFile.
+     */
+    @Override
+    protected void pack() {
+        try (XZOutputStream zOut = new XZOutputStream(
+            Files.newOutputStream(zipFile.toPath()), new LZMA2Options())) {
+            zipResource(getSrcResource(), zOut);
+        } catch (IOException ioe) {
+            String msg = "Problem creating xz " + ioe.getMessage();
+            throw new BuildException(msg, ioe, getLocation());
+        }
+    }
+
+    /**
+     * Whether this task can deal with non-file resources.
+     *
+     * <p>This implementation always returns true only.</p>
+     * @return true
+     */
+    @Override
+    protected boolean supportsNonFileResources() {
+        return true;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java b/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java
index 420597a..40d18a2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.util.List;
 import java.util.Random;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -42,8 +43,6 @@
  */
 public abstract class DefaultRmicAdapter implements RmicAdapter {
 
-    private Rmic attributes;
-    private FileNameMapper mapper;
     private static final Random RAND = new Random();
     /** suffix denoting a stub file: {@value} */
     public static final String RMI_STUB_SUFFIX = "_Stub";
@@ -71,16 +70,14 @@
      */
     public static final String STUB_OPTION_COMPAT = "compat";
 
-    /**
-     * Default constructor
-     */
-    public DefaultRmicAdapter() {
-    }
+    private Rmic attributes;
+    private FileNameMapper mapper;
 
     /**
      * Sets Rmic attributes
      * @param attributes the rmic attributes
      */
+    @Override
     public void setRmic(final Rmic attributes) {
         this.attributes = attributes;
         mapper = new RmicFileNameMapper();
@@ -135,6 +132,7 @@
      * </ul>
      * @return a <code>FileNameMapper</code>
      */
+    @Override
     public FileNameMapper getMapper() {
         return mapper;
     }
@@ -143,6 +141,7 @@
      * Gets the CLASSPATH this rmic process will use.
      * @return the classpath
      */
+    @Override
     public Path getClasspath() {
         return getCompileClasspath();
     }
@@ -182,7 +181,7 @@
      * <p>This implementation returns false if running on Java 11
      * onwards and true otherwise.</p>
      * @return true if the iiop and idl switches are supported
-     * @since Ant 1.9.11
+     * @since Ant 1.10.3
      */
     protected boolean areIiopAndIdlSupported() {
         return !JavaEnvUtils.isAtLeastJavaVersion("11");
@@ -329,7 +328,7 @@
      */
     protected String[] filterJvmCompilerArgs(String[] compilerArgs) {
         int len = compilerArgs.length;
-        List<String> args = new ArrayList<String>(len);
+        List<String> args = new ArrayList<>(len);
         for (String arg : compilerArgs) {
             if (arg.startsWith("-J")) {
                 attributes.log("Dropping " + arg + " from compiler arguments");
@@ -337,8 +336,7 @@
                 args.add(arg);
             }
         }
-        int count = args.size();
-        return (String[]) args.toArray(new String[count]);
+        return args.toArray(new String[0]);
     }
 
 
@@ -348,26 +346,16 @@
      * @param cmd the commandline args
      */
     protected void logAndAddFilesToCompile(Commandline cmd) {
-        Vector compileList = attributes.getCompileList();
+        Vector<String> compileList = attributes.getCompileList();
 
         attributes.log("Compilation " + cmd.describeArguments(),
                        Project.MSG_VERBOSE);
 
-        StringBuffer niceSourceList = new StringBuffer("File");
-        int cListSize = compileList.size();
-        if (cListSize != 1) {
-            niceSourceList.append("s");
-        }
-        niceSourceList.append(" to be compiled:");
-
-        for (int i = 0; i < cListSize; i++) {
-            String arg = (String) compileList.elementAt(i);
-            cmd.createArgument().setValue(arg);
-            niceSourceList.append("    ");
-            niceSourceList.append(arg);
-        }
-
-        attributes.log(niceSourceList.toString(), Project.MSG_VERBOSE);
+        String niceSourceList = (compileList.size() == 1 ? "File" : "Files") +
+                " to be compiled:" +
+                compileList.stream().peek(arg -> cmd.createArgument().setValue(arg))
+                        .collect(Collectors.joining("    "));
+        attributes.log(niceSourceList, Project.MSG_VERBOSE);
     }
 
     private void verifyArguments(Commandline cmd) {
@@ -397,20 +385,20 @@
      */
     private class RmicFileNameMapper implements FileNameMapper {
 
-        RmicFileNameMapper() {
-        }
-
         /**
          * Empty implementation.
          */
+        @Override
         public void setFrom(String s) {
         }
         /**
          * Empty implementation.
          */
+        @Override
         public void setTo(String s) {
         }
 
+        @Override
         public String[] mapFileName(String name) {
             if (name == null
                 || !name.endsWith(".class")
@@ -455,7 +443,7 @@
             } else if (!attributes.getIdl()) {
                 int lastSlash = base.lastIndexOf(File.separatorChar);
 
-                String dirname = "";
+                String dirname;
                 /*
                  * I know, this is not necessary, but I prefer it explicit (SB)
                  */
@@ -463,6 +451,7 @@
                 if (lastSlash == -1) {
                     // no package
                     index = 0;
+                    dirname = "";
                 } else {
                     index = lastSlash + 1;
                     dirname = base.substring(0, index);
@@ -471,7 +460,7 @@
                 String filename = base.substring(index);
 
                 try {
-                    Class c = attributes.getLoader().loadClass(classname);
+                    Class<?> c = attributes.getLoader().loadClass(classname);
 
                     if (c.isInterface()) {
                         // only stub, no tie
@@ -484,14 +473,15 @@
                          * stub is derived from implementation,
                          * tie from interface name.
                          */
-                        Class interf = attributes.getRemoteInterface(c);
+                        Class<?> interf = attributes.getRemoteInterface(c);
                         String iName = interf.getName();
-                        String iDir = "";
-                        int iIndex = -1;
-                        int lastDot = iName.lastIndexOf(".");
+                        String iDir;
+                        int iIndex;
+                        int lastDot = iName.lastIndexOf('.');
                         if (lastDot == -1) {
                             // no package
                             iIndex = 0;
+                            iDir = "";
                         } else {
                             iIndex = lastDot + 1;
                             iDir = iName.substring(0, iIndex);
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java
index 5afae42..cfd5fca 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,7 +46,7 @@
     public static final String COMPILER_NAME = "forking";
 
     /**
-     * @since Ant 1.9.11
+     * @since Ant 1.10.3
      */
     @Override
     protected boolean areIiopAndIdlSupported() {
@@ -65,6 +65,7 @@
      * @return true if the command ran successfully
      * @throws BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
         Rmic owner = getRmic();
         Commandline cmd = setupRmicCommand();
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java
index 5b2233f..784dc6a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,21 +44,22 @@
     public static final String COMPILER_NAME = "kaffe";
 
     /**
-     * @since Ant 1.9.11
+     * @since Ant 1.10.3
      */
     @Override
     protected boolean areIiopAndIdlSupported() {
-        // actually I don't think Kaffee supports either, but we've
-        // accepted the flags prior to 1.9.11
+        // actually I don't think Kaffe supports either, but we've
+        // accepted the flags prior to 1.10.3
         return true;
     }
 
     /** {@inheritDoc} */
+    @Override
     public boolean execute() throws BuildException {
         getRmic().log("Using Kaffe rmic", Project.MSG_VERBOSE);
         Commandline cmd = setupRmicCommand();
 
-        Class c = getRmicClass();
+        Class<?> c = getRmicClass();
         if (c == null) {
             StringBuilder buf = new StringBuilder(
                 "Cannot use Kaffe rmic, as it is not available.  None of ");
@@ -69,8 +70,8 @@
 
                 buf.append(className);
             }
-            buf.append(" have been found. A common solution is to set the"
-                       + " environment variable JAVA_HOME or CLASSPATH.");
+            buf.append(
+                " have been found. A common solution is to set the environment variable JAVA_HOME or CLASSPATH.");
             throw new BuildException(buf.toString(),
                                      getRmic().getLocation());
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java
index 2cabe2f..9d795ab 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java
index a604144..0735cac 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -77,7 +77,7 @@
      * <li>kaffe = Kaffe's rmic
      * <li><i>a fully qualified classname</i> = the name of a rmic
      * adapter
-     * <li>weblogic = weblogic compiler
+     * <li>weblogic = WebLogic compiler
      * <li>forking = Sun's RMIC by forking a new JVM
      * </ul>
      *
@@ -95,7 +95,7 @@
                                       Path classpath)
         throws BuildException {
         //handle default specially by choosing the sun or kaffe compiler
-        if (DEFAULT_COMPILER.equalsIgnoreCase(rmicType) || rmicType.length() == 0) {
+        if (DEFAULT_COMPILER.equalsIgnoreCase(rmicType) || rmicType.isEmpty()) {
             if (KaffeRmic.isAvailable()) {
                 rmicType = KaffeRmic.COMPILER_NAME;
             } else if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
@@ -106,13 +106,17 @@
         }
         if (SunRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
             return new SunRmic();
-        } else if (KaffeRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
+        }
+        if (KaffeRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
             return new KaffeRmic();
-        } else if (WLRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
+        }
+        if (WLRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
             return new WLRmic();
-        } else if (ForkingSunRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
+        }
+        if (ForkingSunRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
             return new ForkingSunRmic();
-        } else if (XNewRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
+        }
+        if (XNewRmic.COMPILER_NAME.equalsIgnoreCase(rmicType)) {
             return new XNewRmic();
         }
         //no match?
@@ -133,7 +137,7 @@
     private static RmicAdapter resolveClassName(String className,
                                                 ClassLoader loader)
             throws BuildException {
-        return (RmicAdapter) ClasspathUtils.newInstance(className,
+        return ClasspathUtils.newInstance(className,
                 loader != null ? loader :
                 RmicAdapterFactory.class.getClassLoader(), RmicAdapter.class);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java
index 7281252..74c1d75 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -51,13 +51,10 @@
      */
     public static final String RMIC_EXECUTABLE = "rmic";
     /** Error message to use with the sun rmic is not the classpath. */
-    public static final String ERROR_NO_RMIC_ON_CLASSPATH = "Cannot use SUN rmic, as it is not "
-                                         + "available.  A common solution is to "
-                                         + "set the environment variable "
-                                         + "JAVA_HOME";
-    public static final String ERROR_NO_RMIC_ON_CLASSPATH_JAVA_9 = "Cannot use SUN rmic, as it is not "
-                                         + "available.  The class we try to use is part of the jdk.rmic module which may not be. "
-                                         + "Please use the 'forking' compiler for JDK 9+";
+    public static final String ERROR_NO_RMIC_ON_CLASSPATH =
+        "Cannot use SUN rmic, as it is not available.  A common solution is to set the environment variable JAVA_HOME";
+    public static final String ERROR_NO_RMIC_ON_CLASSPATH_JAVA_9 =
+        "Cannot use SUN rmic, as it is not available.  The class we try to use is part of the jdk.rmic module which may not be. Please use the 'forking' compiler for JDK 9+";
     /** Error message to use when there is an error starting the sun rmic compiler */
     public static final String ERROR_RMIC_FAILED = "Error starting SUN rmic: ";
 
@@ -66,29 +63,28 @@
      * @return true if the compilation succeeded
      * @throws BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
         getRmic().log("Using SUN rmic compiler", Project.MSG_VERBOSE);
         Commandline cmd = setupRmicCommand();
 
         // Create an instance of the rmic, redirecting output to
         // the project log
-        LogOutputStream logstr = new LogOutputStream(getRmic(),
-                                                     Project.MSG_WARN);
+        LogOutputStream logstr =
+            new LogOutputStream(getRmic(), Project.MSG_WARN);
 
         boolean success = false;
         try {
-            Class c = Class.forName(RMIC_CLASSNAME);
-            Constructor cons
-                = c.getConstructor(new Class[]  {OutputStream.class, String.class});
-            Object rmic = cons.newInstance(new Object[] {logstr, "rmic"});
+            Class<?> c = Class.forName(RMIC_CLASSNAME);
+            Constructor<?> cons =
+                c.getConstructor(OutputStream.class, String.class);
+            Object rmic = cons.newInstance(logstr, "rmic");
 
-            Method doRmic = c.getMethod("compile",
-                                        new Class [] {String[].class});
-            Boolean ok =
-                (Boolean) doRmic.invoke(rmic,
-                                       (new Object[] {cmd.getArguments()}));
+            Method doRmic = c.getMethod("compile", String[].class);
+            boolean ok = Boolean.TRUE
+                .equals(doRmic.invoke(rmic, (Object) cmd.getArguments()));
             success = true;
-            return ok.booleanValue();
+            return ok;
         } catch (ClassNotFoundException ex) {
             if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
                 throw new BuildException(ERROR_NO_RMIC_ON_CLASSPATH_JAVA_9,
@@ -99,10 +95,9 @@
         } catch (Exception ex) {
             if (ex instanceof BuildException) {
                 throw (BuildException) ex;
-            } else {
-                throw new BuildException(ERROR_RMIC_FAILED,
-                                         ex, getRmic().getLocation());
             }
+            throw new BuildException(ERROR_RMIC_FAILED,
+                                     ex, getRmic().getLocation());
         } finally {
             try {
                 logstr.close();
@@ -122,6 +117,7 @@
      * @param compilerArgs the original compiler arguments
      * @return the filtered set.
      */
+    @Override
     protected String[] preprocessCompilerArgs(String[] compilerArgs) {
         return filterJvmCompilerArgs(compilerArgs);
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java
index a4236d2..2328922 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,8 +40,7 @@
 
     /** The error string to use if not able to find the weblogic rmic */
     public static final String ERROR_NO_WLRMIC_ON_CLASSPATH =
-        "Cannot use WebLogic rmic, as it is not "
-        + "available. Add it to Ant's classpath with the -lib option";
+        "Cannot use WebLogic rmic, as it is not available. Add it to Ant's classpath with the -lib option";
 
     /** The error string to use if not able to start the weblogic rmic */
     public static final String ERROR_WLRMIC_FAILED = "Error starting WebLogic rmic: ";
@@ -53,12 +52,12 @@
     public static final String UNSUPPORTED_STUB_OPTION = "Unsupported stub option: ";
 
     /**
-     * @since Ant 1.9.11
+     * @since Ant 1.10.3
      */
     @Override
     protected boolean areIiopAndIdlSupported() {
         // actually I don't think Weblogic's rmic supports either, but
-        // we've accepted the flags prior to 1.9.11
+        // we've accepted the flags prior to 1.10.3
         return true;
     }
 
@@ -67,6 +66,7 @@
      * @return true if the compilation succeeded
      * @throws  BuildException on error
      */
+    @Override
     public boolean execute() throws BuildException {
         getRmic().log("Using WebLogic rmic", Project.MSG_VERBOSE);
         Commandline cmd = setupRmicCommand(new String[] {"-noexit"});
@@ -74,7 +74,7 @@
         AntClassLoader loader = null;
         try {
             // Create an instance of the rmic
-            Class c = null;
+            Class<?> c;
             if (getRmic().getClasspath() == null) {
                 c = Class.forName(WLRMIC_CLASSNAME);
             } else {
@@ -82,9 +82,8 @@
                     = getRmic().getProject().createClassLoader(getRmic().getClasspath());
                 c = Class.forName(WLRMIC_CLASSNAME, true, loader);
             }
-            Method doRmic = c.getMethod("main",
-                                        new Class [] {String[].class});
-            doRmic.invoke(null, new Object[] {cmd.getArguments()});
+            Method doRmic = c.getMethod("main", String[].class);
+            doRmic.invoke(null, (Object) cmd.getArguments());
             return true;
         } catch (ClassNotFoundException ex) {
             throw new BuildException(ERROR_NO_WLRMIC_ON_CLASSPATH, getRmic().getLocation());
@@ -106,6 +105,7 @@
      * Get the suffix for the rmic stub classes
      * @return the stub suffix
      */
+    @Override
     public String getStubClassSuffix() {
         return WL_RMI_STUB_SUFFIX;
     }
@@ -114,6 +114,7 @@
      * Get the suffix for the rmic skeleton classes
      * @return the skeleton suffix
      */
+    @Override
     public String getSkelClassSuffix() {
         return WL_RMI_SKEL_SUFFIX;
     }
@@ -124,6 +125,7 @@
      * @param compilerArgs the original compiler arguments
      * @return the filtered set.
      */
+    @Override
     protected String[] preprocessCompilerArgs(String[] compilerArgs) {
         return filterJvmCompilerArgs(compilerArgs);
     }
@@ -133,6 +135,7 @@
      * stub option is set, a warning is printed.
      * @return null, for no stub version
      */
+    @Override
     protected String addStubVersionOptions() {
         //handle the many different stub options.
         String stubVersion = getRmic().getStubVersion();
diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/XNewRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/XNewRmic.java
index 81e043e..7f5a6c8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/rmic/XNewRmic.java
+++ b/src/main/org/apache/tools/ant/taskdefs/rmic/XNewRmic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,8 +23,8 @@
  * Run rmic in a new process with -Xnew set.
  * This switches rmic to use a new compiler, one that doesn't work in-process
  * on ant on java1.6.
- * see: <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38732">
- * http://issues.apache.org/bugzilla/show_bug.cgi?id=38732</a>
+ * see: <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=38732">
+ * https://issues.apache.org/bugzilla/show_bug.cgi?id=38732</a>
  */
 public class XNewRmic extends ForkingSunRmic {
 
@@ -33,14 +33,11 @@
      */
     public static final String COMPILER_NAME = "xnew";
 
-    /** No-arg constructor. */
-    public XNewRmic() {
-    }
-
     /**
      * Create a normal command line, then with -Xnew at the front
      * @return a command line that hands off to thw
      */
+    @Override
     protected Commandline setupRmicCommand() {
         String[] options = new String[] {
                 "-Xnew"
diff --git a/src/main/org/apache/tools/ant/types/AbstractFileSet.java b/src/main/org/apache/tools/ant/types/AbstractFileSet.java
index f2764a5..a3c5d1b 100644
--- a/src/main/org/apache/tools/ant/types/AbstractFileSet.java
+++ b/src/main/org/apache/tools/ant/types/AbstractFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Stack;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -35,6 +36,7 @@
 import org.apache.tools.ant.types.selectors.DependSelector;
 import org.apache.tools.ant.types.selectors.DepthSelector;
 import org.apache.tools.ant.types.selectors.DifferentSelector;
+import org.apache.tools.ant.types.selectors.ExecutableSelector;
 import org.apache.tools.ant.types.selectors.ExtendSelector;
 import org.apache.tools.ant.types.selectors.FileSelector;
 import org.apache.tools.ant.types.selectors.FilenameSelector;
@@ -42,12 +44,16 @@
 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.PosixGroupSelector;
+import org.apache.tools.ant.types.selectors.PosixPermissionsSelector;
 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;
@@ -63,8 +69,8 @@
     implements Cloneable, SelectorContainer {
 
     private PatternSet defaultPatterns = new PatternSet();
-    private List<PatternSet> additionalPatterns = new ArrayList<PatternSet>();
-    private List<FileSelector> selectors = new ArrayList<FileSelector>();
+    private List<PatternSet> additionalPatterns = new ArrayList<>();
+    private List<FileSelector> selectors = new ArrayList<>();
 
     private File dir;
     private boolean fileAttributeUsed;
@@ -110,6 +116,7 @@
      * @param r the <code>Reference</code> to use.
      * @throws BuildException on error
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (dir != null || defaultPatterns.hasPatterns(getProject())) {
             throw tooManyAttributes();
@@ -492,14 +499,14 @@
             return getRef(p).getDirectoryScanner(p);
         }
         dieOnCircularReference();
-        DirectoryScanner ds = null;
+        final DirectoryScanner ds;
         synchronized (this) {
             if (directoryScanner != null && p == getProject()) {
                 ds = directoryScanner;
             } else {
                 if (dir == null) {
-                    throw new BuildException("No directory specified for "
-                                             + getDataTypeName() + ".");
+                    throw new BuildException("No directory specified for %s.",
+                        getDataTypeName());
                 }
                 if (!dir.exists() && errorOnMissingDir) {
                     throw new BuildException(dir.getAbsolutePath()
@@ -507,8 +514,8 @@
                                              .DOES_NOT_EXIST_POSTFIX);
                 }
                 if (!dir.isDirectory() && dir.exists()) {
-                    throw new BuildException(dir.getAbsolutePath()
-                                             + " is not a directory.");
+                    throw new BuildException("%s is not a directory.",
+                        dir.getAbsolutePath());
                 }
                 ds = new DirectoryScanner();
                 setupDirectoryScanner(ds, p);
@@ -566,11 +573,16 @@
     /**
      * Performs the check for circular references and returns the
      * referenced FileSet.
+     * This method can be overridden together with {@link ArchiveFileSet#getRef() getRef()}
+     * providing implementations containing the special support
+     * for FileSet references, which can be handled by all ArchiveFileSets.
+     * NB! This method must be overridden in subclasses such as FileSet and DirSet
+     * to distinguish between the data types.
      * @param p the current project
-     * @return the referenced FileSet
+     * @return the dereferenced object.
      */
     protected AbstractFileSet getRef(Project p) {
-        return (AbstractFileSet) getCheckedRef(p);
+        return getCheckedRef(AbstractFileSet.class, getDataTypeName(), p);
     }
 
     // SelectorContainer methods
@@ -580,12 +592,13 @@
      *
      * @return whether any selectors are in this container.
      */
+    @Override
     public synchronized boolean hasSelectors() {
         if (isReference()) {
             return getRef(getProject()).hasSelectors();
         }
         dieOnCircularReference();
-        return !(selectors.isEmpty());
+        return !selectors.isEmpty();
     }
 
     /**
@@ -598,15 +611,8 @@
             return getRef(getProject()).hasPatterns();
         }
         dieOnCircularReference();
-        if (defaultPatterns.hasPatterns(getProject())) {
-            return true;
-        }
-        for (PatternSet ps : additionalPatterns) {
-            if (ps.hasPatterns(getProject())) {
-                return true;
-            }
-        }
-        return false;
+        return defaultPatterns.hasPatterns(getProject())
+                || additionalPatterns.stream().anyMatch(ps -> ps.hasPatterns(getProject()));
     }
 
     /**
@@ -614,6 +620,7 @@
      *
      * @return the number of selectors in this container as an <code>int</code>.
      */
+    @Override
     public synchronized int selectorCount() {
         if (isReference()) {
             return getRef(getProject()).selectorCount();
@@ -627,13 +634,13 @@
      * @param p the current project
      * @return a <code>FileSelector[]</code> of the selectors in this container.
      */
+    @Override
     public synchronized FileSelector[] getSelectors(Project p) {
         if (isReference()) {
             return getRef(getProject()).getSelectors(p);
         }
         dieOnCircularReference(p);
-        return (FileSelector[]) (selectors.toArray(
-            new FileSelector[selectors.size()]));
+        return selectors.toArray(new FileSelector[0]);
     }
 
     /**
@@ -641,6 +648,7 @@
      *
      * @return an <code>Enumeration</code> of selectors.
      */
+    @Override
     public synchronized Enumeration<FileSelector> selectorElements() {
         if (isReference()) {
             return getRef(getProject()).selectorElements();
@@ -654,6 +662,7 @@
      *
      * @param selector the new <code>FileSelector</code> to add.
      */
+    @Override
     public synchronized void appendSelector(FileSelector selector) {
         if (isReference()) {
             throw noChildrenAllowed();
@@ -669,6 +678,7 @@
      * Add a "Select" selector entry on the selector list.
      * @param selector the <code>SelectSelector</code> to add.
      */
+    @Override
     public void addSelector(SelectSelector selector) {
         appendSelector(selector);
     }
@@ -677,6 +687,7 @@
      * Add an "And" selector entry on the selector list.
      * @param selector the <code>AndSelector</code> to add.
      */
+    @Override
     public void addAnd(AndSelector selector) {
         appendSelector(selector);
     }
@@ -685,6 +696,7 @@
      * Add an "Or" selector entry on the selector list.
      * @param selector the <code>OrSelector</code> to add.
      */
+    @Override
     public void addOr(OrSelector selector) {
         appendSelector(selector);
     }
@@ -693,6 +705,7 @@
      * Add a "Not" selector entry on the selector list.
      * @param selector the <code>NotSelector</code> to add.
      */
+    @Override
     public void addNot(NotSelector selector) {
         appendSelector(selector);
     }
@@ -701,6 +714,7 @@
      * Add a "None" selector entry on the selector list.
      * @param selector the <code>NoneSelector</code> to add.
      */
+    @Override
     public void addNone(NoneSelector selector) {
         appendSelector(selector);
     }
@@ -709,6 +723,7 @@
      * Add a majority selector entry on the selector list.
      * @param selector the <code>MajoritySelector</code> to add.
      */
+    @Override
     public void addMajority(MajoritySelector selector) {
         appendSelector(selector);
     }
@@ -717,6 +732,7 @@
      * Add a selector date entry on the selector list.
      * @param selector the <code>DateSelector</code> to add.
      */
+    @Override
     public void addDate(DateSelector selector) {
         appendSelector(selector);
     }
@@ -725,6 +741,7 @@
      * Add a selector size entry on the selector list.
      * @param selector the <code>SizeSelector</code> to add.
      */
+    @Override
     public void addSize(SizeSelector selector) {
         appendSelector(selector);
     }
@@ -733,6 +750,7 @@
      * Add a DifferentSelector entry on the selector list.
      * @param selector the <code>DifferentSelector</code> to add.
      */
+    @Override
     public void addDifferent(DifferentSelector selector) {
         appendSelector(selector);
     }
@@ -741,6 +759,7 @@
      * Add a selector filename entry on the selector list.
      * @param selector the <code>FilenameSelector</code> to add.
      */
+    @Override
     public void addFilename(FilenameSelector selector) {
         appendSelector(selector);
     }
@@ -749,6 +768,7 @@
      * Add a selector type entry on the selector list.
      * @param selector the <code>TypeSelector</code> to add.
      */
+    @Override
     public void addType(TypeSelector selector) {
         appendSelector(selector);
     }
@@ -757,6 +777,7 @@
      * Add an extended selector entry on the selector list.
      * @param selector the <code>ExtendSelector</code> to add.
      */
+    @Override
     public void addCustom(ExtendSelector selector) {
         appendSelector(selector);
     }
@@ -765,6 +786,7 @@
      * Add a contains selector entry on the selector list.
      * @param selector the <code>ContainsSelector</code> to add.
      */
+    @Override
     public void addContains(ContainsSelector selector) {
         appendSelector(selector);
     }
@@ -773,6 +795,7 @@
      * Add a present selector entry on the selector list.
      * @param selector the <code>PresentSelector</code> to add.
      */
+    @Override
     public void addPresent(PresentSelector selector) {
         appendSelector(selector);
     }
@@ -781,6 +804,7 @@
      * Add a depth selector entry on the selector list.
      * @param selector the <code>DepthSelector</code> to add.
      */
+    @Override
     public void addDepth(DepthSelector selector) {
         appendSelector(selector);
     }
@@ -789,6 +813,7 @@
      * Add a depends selector entry on the selector list.
      * @param selector the <code>DependSelector</code> to add.
      */
+    @Override
     public void addDepend(DependSelector selector) {
         appendSelector(selector);
     }
@@ -797,6 +822,7 @@
      * Add a regular expression selector entry on the selector list.
      * @param selector the <code>ContainsRegexpSelector</code> to add.
      */
+    @Override
     public void addContainsRegexp(ContainsRegexpSelector selector) {
         appendSelector(selector);
     }
@@ -804,8 +830,9 @@
     /**
      * Add the modified selector.
      * @param selector the <code>ModifiedSelector</code> to add.
-     * @since ant 1.6
+     * @since Ant 1.6
      */
+    @Override
     public void addModified(ModifiedSelector selector) {
         appendSelector(selector);
     }
@@ -819,10 +846,51 @@
     }
 
     /**
+     * @param e ExecutableSelector
+     * @since 1.10.0
+     */
+    public void addExecutable(ExecutableSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @param e SymlinkSelector
+     * @since 1.10.0
+     */
+    public void addSymlink(SymlinkSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @param o OwnedBySelector
+     * @since 1.10.0
+     */
+    public void addOwnedBy(OwnedBySelector o) {
+        appendSelector(o);
+    }
+
+    /**
+     * @param o PosixGroupSelector
+     * @since 1.10.4
+     */
+    public void addPosixGroup(PosixGroupSelector o) {
+        appendSelector(o);
+    }
+
+    /**
+     * @param o PosixPermissionsSelector
+     * @since 1.10.4
+     */
+    public void addPosixPermissions(PosixPermissionsSelector o) {
+        appendSelector(o);
+    }
+
+    /**
      * Add an arbitrary selector.
      * @param selector the <code>FileSelector</code> to add.
      * @since Ant 1.6
      */
+    @Override
     public void add(FileSelector selector) {
         appendSelector(selector);
     }
@@ -832,22 +900,13 @@
      *
      * @return a <code>String</code> of included filenames.
      */
+    @Override
     public String toString() {
         if (isReference()) {
             return getRef(getProject()).toString();
         }
         dieOnCircularReference();
-        DirectoryScanner ds = getDirectoryScanner(getProject());
-        String[] files = ds.getIncludedFiles();
-        StringBuffer sb = new StringBuffer();
-
-        for (int i = 0; i < files.length; i++) {
-            if (i > 0) {
-                sb.append(';');
-            }
-            sb.append(files[i]);
-        }
-        return sb.toString();
+        return String.join(";", getDirectoryScanner().getIncludedFiles());
     }
 
     /**
@@ -857,22 +916,20 @@
      * @return the cloned object
      * @since Ant 1.6
      */
+    @Override
     public synchronized Object clone() {
         if (isReference()) {
             return (getRef(getProject())).clone();
-        } else {
-            try {
-                AbstractFileSet fs = (AbstractFileSet) super.clone();
-                fs.defaultPatterns = (PatternSet) defaultPatterns.clone();
-                fs.additionalPatterns = new ArrayList<PatternSet>(additionalPatterns.size());
-                for (PatternSet ps : additionalPatterns) {
-                    fs.additionalPatterns.add((PatternSet) ps.clone());
-                }
-                fs.selectors = new ArrayList<FileSelector>(selectors);
-                return fs;
-            } catch (CloneNotSupportedException e) {
-                throw new BuildException(e);
-            }
+        }
+        try {
+            AbstractFileSet fs = (AbstractFileSet) super.clone();
+            fs.defaultPatterns = (PatternSet) defaultPatterns.clone();
+            fs.additionalPatterns = additionalPatterns.stream().map(PatternSet::clone)
+                    .map(PatternSet.class::cast).collect(Collectors.toList());
+            fs.selectors = new ArrayList<>(selectors);
+            return fs;
+        } catch (CloneNotSupportedException e) {
+            throw new BuildException(e);
         }
     }
 
@@ -914,13 +971,11 @@
         }
         dieOnCircularReference();
         PatternSet ps = (PatternSet) defaultPatterns.clone();
-        final int count = additionalPatterns.size();
-        for (int i = 0; i < count; i++) {
-            ps.append(additionalPatterns.get(i), p);
-        }
+        additionalPatterns.forEach(pat -> ps.append(pat, p));
         return ps;
     }
 
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -929,14 +984,9 @@
         if (isReference()) {
             super.dieOnCircularReference(stk, p);
         } else {
-            for (FileSelector fileSelector : selectors) {
-                if (fileSelector instanceof DataType) {
-                    pushAndInvokeCircularReferenceCheck((DataType) fileSelector, stk, p);
-                }
-            }
-            for (PatternSet ps : additionalPatterns) {
-                pushAndInvokeCircularReferenceCheck(ps, stk, p);
-            }
+            selectors.stream().filter(DataType.class::isInstance).map(DataType.class::cast)
+                    .forEach(type -> pushAndInvokeCircularReferenceCheck(type, stk, p));
+            additionalPatterns.forEach(ps -> pushAndInvokeCircularReferenceCheck(ps, stk, p));
             setChecked(true);
         }
     }
diff --git a/src/main/org/apache/tools/ant/types/AntFilterReader.java b/src/main/org/apache/tools/ant/types/AntFilterReader.java
index bdc1c31..ceda57a 100644
--- a/src/main/org/apache/tools/ant/types/AntFilterReader.java
+++ b/src/main/org/apache/tools/ant/types/AntFilterReader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,9 @@
  */
 package org.apache.tools.ant.types;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Stack;
-import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -31,7 +32,7 @@
 
     private String className;
 
-    private final Vector<Parameter> parameters = new Vector<Parameter>();
+    private final List<Parameter> parameters = new ArrayList<>();
 
     private Path classpath;
 
@@ -54,7 +55,7 @@
      */
     public String getClassName() {
         if (isReference()) {
-            return ((AntFilterReader) getCheckedRef()).getClassName();
+            return getRef().getClassName();
         }
         dieOnCircularReference();
         return className;
@@ -69,7 +70,7 @@
         if (isReference()) {
             throw noChildrenAllowed();
         }
-        parameters.addElement(param);
+        parameters.add(param);
     }
 
     /**
@@ -109,7 +110,7 @@
      */
     public Path getClasspath() {
         if (isReference()) {
-            ((AntFilterReader) getCheckedRef()).getClasspath();
+            getRef().getClasspath();
         }
         dieOnCircularReference();
         return classpath;
@@ -134,12 +135,10 @@
      */
     public Parameter[] getParams() {
         if (isReference()) {
-            ((AntFilterReader) getCheckedRef()).getParams();
+            getRef().getParams();
         }
         dieOnCircularReference();
-        Parameter[] params = new Parameter[parameters.size()];
-        parameters.copyInto(params);
-        return params;
+        return parameters.toArray(new Parameter[0]);
     }
 
     /**
@@ -174,4 +173,8 @@
             setChecked(true);
         }
     }
+
+    private AntFilterReader getRef() {
+        return getCheckedRef(AntFilterReader.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/ArchiveFileSet.java b/src/main/org/apache/tools/ant/types/ArchiveFileSet.java
index e9a0730..1082e9e 100644
--- a/src/main/org/apache/tools/ant/types/ArchiveFileSet.java
+++ b/src/main/org/apache/tools/ant/types/ArchiveFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -110,6 +110,7 @@
      * @param dir the directory for the fileset
      * @throws BuildException on error
      */
+    @Override
     public void setDir(File dir) throws BuildException {
         checkAttributesAllowed();
         if (src != null) {
@@ -188,32 +189,29 @@
      */
     public File getSrc() {
         if (isReference()) {
-            return ((ArchiveFileSet) getCheckedRef()).getSrc();
+            return getCheckedRef(ArchiveFileSet.class).getSrc();
         }
         dieOnCircularReference();
-        if (src != null) {
-            FileProvider fp = src.as(FileProvider.class);
-            if (fp != null) {
-                return fp.getFile();
-            }
+        if (src == null) {
+            return null;
         }
-        return null;
+        return src.asOptional(FileProvider.class).map(FileProvider::getFile).orElse(null);
     }
 
     /**
      * Performs the check for circular references and returns the
      * referenced object.
-     * This is an override which does not delegate to the superclass; instead it invokes
-     * {@link #getRef(Project)}, because that contains the special support for fileset
-     * references, which can be handled by all ArchiveFileSets.
-     * @param p the Ant Project instance against which to resolve references.
+     * This method must be overridden together with
+     * {@link AbstractFileSet#getRef(Project) getRef(Project)}
+     * providing implementations containing the special support
+     * for FileSet references, which can be handled by all ArchiveFileSets.
+     * NB! This method cannot be implemented in AbstractFileSet in order to allow
+     * FileSet and DirSet to implement it as a private method.
      * @return the dereferenced object.
      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
-     * @since Ant 1.8
      */
-    // TODO is the above true? AFAICT the calls look circular :/
-    protected Object getCheckedRef(Project p) {
-        return getRef(p);
+    protected AbstractFileSet getRef() {
+        return getCheckedRef(AbstractFileSet.class);
     }
 
     /**
@@ -224,7 +222,7 @@
      */
     public void setPrefix(String prefix) {
         checkArchiveAttributesAllowed();
-        if (!"".equals(prefix) && !"".equals(fullpath)) {
+        if (!prefix.isEmpty() && !fullpath.isEmpty()) {
             throw new BuildException(ERROR_PATH_AND_PREFIX);
         }
         this.prefix = prefix;
@@ -251,7 +249,7 @@
      */
     public void setFullpath(String fullpath) {
         checkArchiveAttributesAllowed();
-        if (!"".equals(prefix) && !"".equals(fullpath)) {
+        if (!prefix.isEmpty() && !fullpath.isEmpty()) {
             throw new BuildException(ERROR_PATH_AND_PREFIX);
         }
         this.fullpath = fullpath;
@@ -287,12 +285,8 @@
      */
     public String getEncoding() {
         if (isReference()) {
-            AbstractFileSet ref = getRef(getProject());
-            if (ref instanceof ArchiveFileSet) {
-                return ((ArchiveFileSet) ref).getEncoding();
-            } else {
-                return null;
-            }
+            AbstractFileSet ref = getRef();
+            return ref instanceof ArchiveFileSet ? ((ArchiveFileSet) ref).getEncoding() : null;
         }
         return encoding;
     }
@@ -310,6 +304,7 @@
      * @param p the project to use
      * @return a directory scanner
      */
+    @Override
     public DirectoryScanner getDirectoryScanner(Project p) {
         if (isReference()) {
             return getRef(p).getDirectoryScanner(p);
@@ -340,15 +335,15 @@
      * @return Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((ResourceCollection) (getRef(getProject()))).iterator();
+            return ((ResourceCollection) getRef()).iterator();
         }
         if (src == null) {
             return super.iterator();
         }
-        ArchiveScanner as = (ArchiveScanner) getDirectoryScanner(getProject());
-        return as.getResourceFiles(getProject());
+        return ((ArchiveScanner) getDirectoryScanner()).getResourceFiles(getProject());
     }
 
     /**
@@ -356,15 +351,15 @@
      * @return size of the collection as int.
      * @since Ant 1.7
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((ResourceCollection) (getRef(getProject()))).size();
+            return ((ResourceCollection) getRef()).size();
         }
         if (src == null) {
             return super.size();
         }
-        ArchiveScanner as = (ArchiveScanner) getDirectoryScanner(getProject());
-        return as.getIncludedFilesCount();
+        return getDirectoryScanner().getIncludedFilesCount();
     }
 
     /**
@@ -375,9 +370,10 @@
      * @return whether this is a filesystem-only resource collection.
      * @since Ant 1.7
      */
+    @Override
     public boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((ArchiveFileSet) getCheckedRef()).isFilesystemOnly();
+            return ((ArchiveFileSet) getRef()).isFilesystemOnly();
         }
         dieOnCircularReference();
         return src == null;
@@ -428,7 +424,7 @@
      */
     public boolean hasFileModeBeenSet() {
         if (isReference()) {
-            return ((ArchiveFileSet) getRef(getProject())).hasFileModeBeenSet();
+            return ((ArchiveFileSet) getRef()).hasFileModeBeenSet();
         }
         dieOnCircularReference();
         return fileModeHasBeenSet;
@@ -479,7 +475,7 @@
      */
     public boolean hasDirModeBeenSet() {
         if (isReference()) {
-            return ((ArchiveFileSet) getRef(getProject())).hasDirModeBeenSet();
+            return ((ArchiveFileSet) getRef()).hasDirModeBeenSet();
         }
         dieOnCircularReference();
         return dirModeHasBeenSet;
@@ -505,9 +501,10 @@
      * @return the cloned archiveFileSet
      * @since Ant 1.6
      */
+    @Override
     public Object clone() {
         if (isReference()) {
-            return getCheckedRef(ArchiveFileSet.class, getDataTypeName(), getProject()).clone();
+            return getCheckedRef(ArchiveFileSet.class).clone();
         }
         return super.clone();
     }
@@ -518,6 +515,7 @@
      * @return for file based archivefilesets, included files as a list
      * of semicolon-separated filenames. else just the name of the zip.
      */
+    @Override
     public String toString() {
         if (hasDir && getProject() != null) {
             return super.toString();
@@ -530,6 +528,7 @@
      * @return the prefix.
      * @deprecated since 1.7.
      */
+    @Deprecated
     public String getPrefix() {
         return prefix;
     }
@@ -539,6 +538,7 @@
      * @return the full pathname.
      * @deprecated since 1.7.
      */
+    @Deprecated
     public String getFullpath() {
         return fullpath;
     }
@@ -547,6 +547,7 @@
      * @return the file mode.
      * @deprecated since 1.7.
      */
+    @Deprecated
     public int getFileMode() {
         return fileMode;
     }
@@ -555,6 +556,7 @@
      * @return the dir mode.
      * @deprecated since 1.7.
      */
+    @Deprecated
     public int getDirMode() {
         return dirMode;
     }
@@ -577,6 +579,7 @@
         }
     }
 
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
diff --git a/src/main/org/apache/tools/ant/types/ArchiveScanner.java b/src/main/org/apache/tools/ant/types/ArchiveScanner.java
index db5a8d4..ead0005 100644
--- a/src/main/org/apache/tools/ant/types/ArchiveScanner.java
+++ b/src/main/org/apache/tools/ant/types/ArchiveScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -61,22 +61,22 @@
     /**
      * record list of all file zip entries
      */
-    private Map<String, Resource> fileEntries = new TreeMap<String, Resource>();
+    private Map<String, Resource> fileEntries = new TreeMap<>();
 
     /**
      * record list of all directory zip entries
      */
-    private Map<String, Resource> dirEntries = new TreeMap<String, Resource>();
+    private Map<String, Resource> dirEntries = new TreeMap<>();
 
     /**
      * record list of matching file zip entries
      */
-    private Map<String, Resource> matchFileEntries = new TreeMap<String, Resource>();
+    private Map<String, Resource> matchFileEntries = new TreeMap<>();
 
     /**
      * record list of matching directory zip entries
      */
-    private Map<String, Resource> matchDirEntries = new TreeMap<String, Resource>();
+    private Map<String, Resource> matchDirEntries = new TreeMap<>();
 
     /**
      * encoding of file names.
@@ -158,7 +158,7 @@
             return super.getIncludedFiles();
         }
         scanme();
-        return matchFileEntries.keySet().toArray(new String[matchFileEntries.size()]);
+        return matchFileEntries.keySet().toArray(new String[0]);
     }
 
     /**
@@ -187,7 +187,7 @@
             return super.getIncludedDirectories();
         }
         scanme();
-        return matchDirEntries.keySet().toArray(new String[matchDirEntries.size()]);
+        return matchDirEntries.keySet().toArray(new String[0]);
     }
 
     /**
@@ -256,9 +256,9 @@
      */
     public boolean match(String path) {
         String vpath = path;
-        if (path.length() > 0) {
-            vpath = path.replace('/', File.separatorChar).
-                replace('\\', File.separatorChar);
+        if (!path.isEmpty()) {
+            vpath = path.replace('/', File.separatorChar)
+                    .replace('\\', File.separatorChar);
             if (vpath.charAt(0) == File.separatorChar) {
                 vpath = vpath.substring(1);
             }
@@ -272,11 +272,12 @@
      * @return the resource
      * @since Ant 1.5.2
      */
+    @Override
     public Resource getResource(String name) {
         if (src == null) {
             return super.getResource(name);
         }
-        if (name.equals("")) {
+        if (name.isEmpty()) {
             // special case in ZIPs, we do not want this thing included
             return new Resource("", true, Long.MAX_VALUE, true);
         }
diff --git a/src/main/org/apache/tools/ant/types/Assertions.java b/src/main/org/apache/tools/ant/types/Assertions.java
index ce7091a..9422809 100644
--- a/src/main/org/apache/tools/ant/types/Assertions.java
+++ b/src/main/org/apache/tools/ant/types/Assertions.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -75,7 +75,7 @@
     /**
      * list of type BaseAssertion
      */
-    private ArrayList<BaseAssertion> assertionList = new ArrayList<BaseAssertion>();
+    private ArrayList<BaseAssertion> assertionList = new ArrayList<>();
 
 
     /**
@@ -117,7 +117,7 @@
      * @param ref the reference to use
      */
     public void setRefid(Reference ref) {
-        if (assertionList.size() > 0 || enableSystemAssertions != null) {
+        if (!assertionList.isEmpty() || enableSystemAssertions != null) {
             throw tooManyAttributes();
         }
         super.setRefid(ref);
@@ -130,13 +130,12 @@
     private Assertions getFinalReference() {
         if (getRefid() == null) {
             return this;
-        } else {
-            Object o = getRefid().getReferencedObject(getProject());
-            if (!(o instanceof Assertions)) {
-                throw new BuildException("reference is of wrong type");
-            }
-            return (Assertions) o;
         }
+        Object o = getRefid().getReferencedObject(getProject());
+        if (!(o instanceof Assertions)) {
+            throw new BuildException("reference is of wrong type");
+        }
+        return (Assertions) o;
     }
 
     /**
@@ -245,16 +244,16 @@
      * @return a cli
      * @throws CloneNotSupportedException if the super class does not support cloning
      */
+    @Override
     public Object clone() throws CloneNotSupportedException {
         Assertions that = (Assertions) super.clone();
-        that.assertionList = new ArrayList<BaseAssertion>(assertionList);
+        that.assertionList = new ArrayList<>(assertionList);
         return that;
     }
 
     /**
      * base class for our assertion elements.
      */
-
     public abstract static class BaseAssertion {
         private String packageName;
         private String className;
@@ -309,7 +308,7 @@
             if (getPackageName() != null && getClassName() != null) {
                 throw new BuildException("Both package and class have been set");
             }
-            StringBuffer command = new StringBuffer(getCommandPrefix());
+            StringBuilder command = new StringBuilder(getCommandPrefix());
             //see if it is a package or a class
             if (getPackageName() != null) {
                 //packages get a ... prefix
@@ -337,6 +336,7 @@
          * get the prefix used to begin the command; -ea or -da.
          * @return prefix
          */
+        @Override
         public String getCommandPrefix() {
             return "-ea";
         }
@@ -351,6 +351,7 @@
          * get the prefix used to begin the command; -ea or -da.
          * @return prefix
          */
+        @Override
         public String getCommandPrefix() {
             return "-da";
         }
diff --git a/src/main/org/apache/tools/ant/types/CharSet.java b/src/main/org/apache/tools/ant/types/CharSet.java
new file mode 100644
index 0000000..a965f5c
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/CharSet.java
@@ -0,0 +1,126 @@
+/*
+ *  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
+ *
+ *      https://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;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * EnumeratedAttribute implementation for Charset to use with encoding/charset attributes.
+ * @since Ant 1.10.6
+ */
+public class CharSet extends EnumeratedAttribute {
+
+    private static final List<String> VALUES = new ArrayList<>();
+
+    static {
+        for (Map.Entry<String, Charset> entry :  Charset.availableCharsets().entrySet()) {
+            VALUES.add(entry.getKey());
+            VALUES.addAll(entry.getValue().aliases());
+        }
+    }
+
+    /**
+     * Default constructor.
+     */
+    public CharSet() {
+    }
+
+    /**
+     * Construct a new CharSet with the specified value.
+     * @param value the EnumeratedAttribute value.
+     */
+    public CharSet(String value) {
+        setValue(value);
+    }
+
+    /**
+     * Get the default value as provided by Charset.
+     * @return the default value.
+     */
+    public static CharSet getDefault() {
+        return new CharSet(Charset.defaultCharset().name());
+    }
+
+    /**
+     * Convenience methood: get US-ASCII CharSet.
+     * @return the default value.
+     */
+    public static CharSet getAscii() {
+        return new CharSet(StandardCharsets.US_ASCII.name());
+    }
+
+    /**
+     * Convenience method: get UTF-8 CharSet.
+     * @return the default value.
+     */
+    public static CharSet getUtf8() {
+        return new CharSet(StandardCharsets.UTF_8.name());
+    }
+
+    /**
+     * Tell if CharSet values are aliases.
+     * @param cs CharSet to compare the value to.
+     * @return true if CharSet values are aliases.
+     */
+    public boolean equivalent(CharSet cs) {
+        return getCharset().name().equals(cs.getCharset().name());
+    }
+
+    /**
+     * Convert this enumerated type to a <code>Charset</code>.
+     * @return a <code>Charset</code> object.
+     */
+    public Charset getCharset() {
+        return Charset.forName(getValue());
+    }
+
+    /**
+     * Return the possible values.
+     * @return String[] of Charset names.
+     */
+    @Override
+    public String[] getValues() {
+        return VALUES.toArray(new String[0]);
+    }
+
+    /**
+     * Accept additional values for backwards compatibility
+     * (some java.io encoding names not available in java.nio)
+     * @param value the <code>String</code> value of the attribute
+     */
+    @Override
+    public final void setValue(final String value) {
+        String realValue = value;
+        if (value == null || value.isEmpty()) {
+           realValue = Charset.defaultCharset().name();
+       } else {
+           for (String v : Arrays.asList(value, value.toLowerCase(), value.toUpperCase())) {
+               if (VALUES.contains(v)) {
+                   realValue = v;
+                   break;
+               }
+           }
+        }
+        super.setValue(realValue);
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/Commandline.java b/src/main/org/apache/tools/ant/types/Commandline.java
index d4de028..9537112 100644
--- a/src/main/org/apache/tools/ant/types/Commandline.java
+++ b/src/main/org/apache/tools/ant/types/Commandline.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,11 +25,11 @@
 import java.util.List;
 import java.util.ListIterator;
 import java.util.StringTokenizer;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.taskdefs.condition.Os;
-import org.apache.tools.ant.util.StringUtils;
 
 /**
  * Commandline objects help handling command lines specifying processes to
@@ -58,19 +58,15 @@
     /**
      * The arguments of the command
      */
-    private List<Argument> arguments = new ArrayList<Argument>();
+    private List<Argument> arguments = new ArrayList<>();
 
     /**
      * the program to execute
      */
     private String executable = null;
 
-    protected static final String DISCLAIMER =
-        StringUtils.LINE_SEP
-        + "The \' characters around the executable and arguments are"
-        + StringUtils.LINE_SEP
-        + "not part of the command."
-        + StringUtils.LINE_SEP;
+    protected static final String DISCLAIMER = String.format(
+            "%nThe ' characters around the executable and arguments are%nnot part of the command.%n");
 
     /**
      * Create a command line from a string.
@@ -187,7 +183,7 @@
          *
          * @param other the argument to copy setting from
          *
-         * @since Ant 1.9.14
+         * @since Ant 1.10.6
          */
         public void copyFrom(Argument other) {
             this.parts = other.parts;
@@ -200,8 +196,7 @@
          * @return an array of strings.
          */
         public String[] getParts() {
-            if (parts == null || parts.length == 0
-                    || (prefix.length() == 0 && suffix.length() == 0)) {
+            if (parts == null || parts.length == 0 || (prefix.isEmpty() && suffix.isEmpty())) {
                 return parts;
             }
             String[] fullParts = new String[parts.length];
@@ -242,11 +237,9 @@
          */
         public int getPosition() {
             if (realPos == -1) {
-                realPos = (executable == null ? 0 : 1);
-                for (int i = 0; i < position; i++) {
-                    Argument arg = (Argument) arguments.get(i);
-                    realPos += arg.getParts().length;
-                }
+                realPos = (executable == null ? 0 : 1)
+                        + (int) arguments.stream().limit(position)
+                        .map(Argument::getParts).flatMap(Stream::of).count();
             }
             return realPos;
         }
@@ -346,7 +339,7 @@
      * @since Ant 1.9.7
      */
     public void setExecutable(String executable, boolean translateFileSeparator) {
-        if (executable == null || executable.length() == 0) {
+        if (executable == null || executable.isEmpty()) {
             return;
         }
         this.executable = translateFileSeparator
@@ -367,8 +360,8 @@
      * @param line an array of arguments to append.
      */
     public void addArguments(String[] line) {
-        for (String l : line) {
-            createArgument().setValue(l);
+        for (String argument : line) {
+            createArgument().setValue(argument);
         }
     }
 
@@ -377,9 +370,9 @@
      * @return the commandline as an array of strings.
      */
     public String[] getCommandline() {
-        final List<String> commands = new LinkedList<String>();
+        final List<String> commands = new LinkedList<>();
         addCommandToList(commands.listIterator());
-        return commands.toArray(new String[commands.size()]);
+        return commands.toArray(new String[0]);
     }
 
     /**
@@ -400,9 +393,9 @@
      * @return the arguments as an array of strings.
      */
     public String[] getArguments() {
-        List<String> result = new ArrayList<String>(arguments.size() * 2);
+        List<String> result = new ArrayList<>(arguments.size() * 2);
         addArgumentsToList(result.listIterator());
-        return result.toArray(new String[result.size()]);
+        return result.toArray(new String[0]);
     }
 
     /**
@@ -425,6 +418,7 @@
      * Return the command line as a string.
      * @return the command line.
      */
+    @Override
     public String toString() {
         return toString(getCommandline());
     }
@@ -442,13 +436,13 @@
      */
     public static String quoteArgument(String argument) {
         if (argument.contains("\"")) {
-            if (argument.contains("\'")) {
-                throw new BuildException("Can\'t handle single and double"
+            if (argument.contains("'")) {
+                throw new BuildException("Can't handle single and double"
                         + " quotes in same argument");
             }
             return '\'' + argument + '\'';
         }
-        if (argument.contains("\'") || argument.contains(" ")
+        if (argument.contains("'") || argument.contains(" ")
                 // WIN9x uses a bat file for executing commands
                 || (IS_WIN_9X && argument.contains(";"))) {
             return '\"' + argument + '\"';
@@ -470,11 +464,11 @@
         }
         // path containing one or more elements
         final StringBuilder result = new StringBuilder();
-        for (int i = 0; i < line.length; i++) {
-            if (i > 0) {
+        for (String argument : line) {
+            if (result.length() > 0) {
                 result.append(' ');
             }
-            result.append(quoteArgument(line[i]));
+            result.append(quoteArgument(argument));
         }
         return result.toString();
     }
@@ -486,7 +480,7 @@
      * An empty or null toProcess parameter results in a zero sized array.
      */
     public static String[] translateCommandline(String toProcess) {
-        if (toProcess == null || toProcess.length() == 0) {
+        if (toProcess == null || toProcess.isEmpty()) {
             //no command? no string
             return new String[0];
         }
@@ -496,8 +490,8 @@
         final int inQuote = 1;
         final int inDoubleQuote = 2;
         int state = normal;
-        final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
-        final ArrayList<String> result = new ArrayList<String>();
+        final StringTokenizer tok = new StringTokenizer(toProcess, "\"' ", true);
+        final ArrayList<String> result = new ArrayList<>();
         final StringBuilder current = new StringBuilder();
         boolean lastTokenHasBeenQuoted = false;
 
@@ -505,7 +499,7 @@
             String nextTok = tok.nextToken();
             switch (state) {
             case inQuote:
-                if ("\'".equals(nextTok)) {
+                if ("'".equals(nextTok)) {
                     lastTokenHasBeenQuoted = true;
                     state = normal;
                 } else {
@@ -521,12 +515,12 @@
                 }
                 break;
             default:
-                if ("\'".equals(nextTok)) {
+                if ("'".equals(nextTok)) {
                     state = inQuote;
                 } else if ("\"".equals(nextTok)) {
                     state = inDoubleQuote;
                 } else if (" ".equals(nextTok)) {
-                    if (lastTokenHasBeenQuoted || current.length() != 0) {
+                    if (lastTokenHasBeenQuoted || current.length() > 0) {
                         result.add(current.toString());
                         current.setLength(0);
                     }
@@ -537,13 +531,13 @@
                 break;
             }
         }
-        if (lastTokenHasBeenQuoted || current.length() != 0) {
+        if (lastTokenHasBeenQuoted || current.length() > 0) {
             result.add(current.toString());
         }
         if (state == inQuote || state == inDoubleQuote) {
             throw new BuildException("unbalanced quotes in " + toProcess);
         }
-        return result.toArray(new String[result.size()]);
+        return result.toArray(new String[0]);
     }
 
     /**
@@ -559,10 +553,11 @@
      * Generate a deep clone of the contained object.
      * @return a clone of the contained object
      */
+    @Override
     public Object clone() {
         try {
             Commandline c = (Commandline) super.clone();
-            c.arguments = new ArrayList<Argument>(arguments);
+            c.arguments = new ArrayList<>(arguments);
             return c;
         } catch (CloneNotSupportedException e) {
             throw new BuildException(e);
@@ -653,9 +648,7 @@
         if (args == null || args.length == 0) {
             return "";
         }
-        StringBuffer buf = new StringBuffer("Executing \'");
-        buf.append(args[0]);
-        buf.append("\'");
+        StringBuilder buf = new StringBuilder("Executing '").append(args[0]).append("'");
         if (args.length > 1) {
             buf.append(" with ");
             buf.append(describeArguments(args, 1));
@@ -690,14 +683,10 @@
         if (args == null || args.length <= offset) {
             return "";
         }
-        StringBuffer buf = new StringBuffer("argument");
-        if (args.length > offset) {
-            buf.append("s");
-        }
-        buf.append(":").append(StringUtils.LINE_SEP);
+        StringBuilder buf = new StringBuilder();
+        buf.append(String.format("argument%s:%n", args.length > offset ? "s" : ""));
         for (int i = offset; i < args.length; i++) {
-            buf.append("\'").append(args[i]).append("\'")
-                .append(StringUtils.LINE_SEP);
+            buf.append(String.format("'%s'%n", args[i]));
         }
         buf.append(DISCLAIMER);
         return buf.toString();
diff --git a/src/main/org/apache/tools/ant/types/CommandlineJava.java b/src/main/org/apache/tools/ant/types/CommandlineJava.java
index 1771e3a..4ad4cc5 100644
--- a/src/main/org/apache/tools/ant/types/CommandlineJava.java
+++ b/src/main/org/apache/tools/ant/types/CommandlineJava.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 
 package org.apache.tools.ant.types;
 
-import java.util.Enumeration;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
@@ -31,7 +30,7 @@
 
 /**
  * A representation of a Java command line that is
- * a composite of 2 <tt>Commandline</tt>s. One is used for the
+ * a composite of 2 <code>Commandline</code>s. One is used for the
  * vm/options and one for the classname/arguments. It provides
  * specific methods for a Java command line.
  *
@@ -82,7 +81,7 @@
         /** the system properties. */
         Properties sys = null;
         // CheckStyle:VisibilityModifier ON
-        private Vector<PropertySet> propertySets = new Vector<PropertySet>();
+        private Vector<PropertySet> propertySets = new Vector<>();
 
         /**
          * Get the properties as an array; this is an override of the
@@ -90,15 +89,15 @@
          * @return the array of definitions; may be null.
          * @throws BuildException on error.
          */
+        @Override
         public String[] getVariables() throws BuildException {
 
-            List<String> definitions = new LinkedList<String>();
+            List<String> definitions = new LinkedList<>();
             addDefinitionsToList(definitions.listIterator());
-            if (definitions.size() == 0) {
+            if (definitions.isEmpty()) {
                 return null;
-            } else {
-                return definitions.toArray(new String[definitions.size()]);
             }
+            return definitions.toArray(new String[0]);
         }
 
         /**
@@ -113,11 +112,8 @@
                 }
             }
             Properties propertySetProperties = mergePropertySets();
-            for (Enumeration<?> e = propertySetProperties.keys();
-                 e.hasMoreElements();) {
-                String key = (String) e.nextElement();
-                String value = propertySetProperties.getProperty(key);
-                listIt.add("-D" + key + "=" + value);
+            for (String key : propertySetProperties.stringPropertyNames()) {
+                listIt.add("-D" + key + "=" + propertySetProperties.getProperty(key));
             }
         }
 
@@ -140,10 +136,9 @@
             try {
                 sys = System.getProperties();
                 Properties p = new Properties();
-                for (Enumeration<?> e = sys.propertyNames(); e.hasMoreElements();) {
-                    String name = (String) e.nextElement();
+                for (String name : sys.stringPropertyNames()) {
                     String value = sys.getProperty(name);
-                    if (name != null && value != null) {
+                    if (value != null) {
                         p.put(name, value);
                     }
                 }
@@ -182,6 +177,7 @@
          * @exception CloneNotSupportedException for signature.
          */
         @SuppressWarnings("unchecked")
+        @Override
         public Object clone() throws CloneNotSupportedException {
             try {
                 SysProperties c = (SysProperties) super.clone();
@@ -329,7 +325,7 @@
     /**
      * Get the name of the jar to be run.
      * @return the pathname of the jar file to run via -jar option
-     * or <tt>null</tt> if there is no jar to run.
+     * or <code>null</code> if there is no jar to run.
      * @see #getClassname()
      */
     public String getJar() {
@@ -356,7 +352,7 @@
 
     /**
      * Get the name of the class to be run.
-     * @return the name of the class to run or <tt>null</tt> if there is no class.
+     * @return the name of the class to run or <code>null</code> if there is no class.
      * @see #getJar()
      */
     public String getClassname() {
@@ -366,12 +362,35 @@
                     return javaCommand.getExecutable();
                 case MODULE:
                     return parseClassFromModuleClassPair(javaCommand.getExecutable());
+                default:
             }
         }
         return null;
     }
 
     /**
+     * Set the source-file, to execute as single file source programs, a feature, available
+     * since Java 11.
+     *
+     * @param sourceFile The path to the source file
+     * @since Ant 1.10.5
+     */
+    public void setSourceFile(final String sourceFile) {
+        this.executableType = ExecutableType.SOURCE_FILE;
+        javaCommand.setExecutable(sourceFile);
+    }
+
+    /**
+     * @return Returns the source-file to execute, if this command line has
+     * been {@link #setSourceFile(String) configured for single file source program
+     * execution}. Else returns null.
+     * @since Ant 1.10.5
+     */
+    public String getSourceFile() {
+        return this.executableType == ExecutableType.SOURCE_FILE ? this.javaCommand.getExecutable() : null;
+    }
+
+    /**
      * Set the module to execute.
      * @param module  the module name.
      * @since 1.9.7
@@ -392,6 +411,7 @@
                     javaCommand.setExecutable(createModuleClassPair(module,
                             parseClassFromModuleClassPair(javaCommand.getExecutable())), false);
                     break;
+                default:
             }
         }
         executableType = ExecutableType.MODULE;
@@ -399,7 +419,7 @@
 
     /**
      * Get the name of the module to be run.
-     * @return the name of the module to run or <tt>null</tt> if there is no module.
+     * @return the name of the module to run or <code>null</code> if there is no module.
      * @see #getJar()
      * @see #getClassname()
      * @since 1.9.7
@@ -476,11 +496,11 @@
      */
     public String[] getCommandline() {
         //create the list
-        List<String> commands = new LinkedList<String>();
+        List<String> commands = new LinkedList<>();
         //fill it
         addCommandsToList(commands.listIterator());
         //convert to an array
-        return commands.toArray(new String[commands.size()]);
+        return commands.toArray(new String[0]);
     }
 
     /**
@@ -536,9 +556,11 @@
         } else if (executableType == ExecutableType.MODULE) {
             listIterator.add("-m");
         }
-        // this is the classname to run as well as its arguments.
+        // this is the classname/source-file to run as well as its arguments.
         // in case of ExecutableType.JAR, the executable is a jar file,
-        // in case of ExecutableType.MODULE, the executable is a module name, portentially including a class name.
+        // in case of ExecutableType.MODULE, the executable is a module name, potentially including a class name.
+        // in case of ExecutableType.SOURCE_FILE, the executable is a Java source file (ending in .java) or a shebang
+        // file containing Java source
         javaCommand.addCommandToList(listIterator);
     }
 
@@ -555,6 +577,7 @@
      * Get a string description.
      * @return the command line as a string.
      */
+    @Override
     public String toString() {
         return Commandline.toString(getCommandline());
     }
@@ -603,9 +626,10 @@
      * @return the total number of arguments in the java command line.
      * @see #getCommandline()
      * @deprecated since 1.7.
-     *             Please dont use this, it effectively creates the
+     *             Please don't use this, it effectively creates the
      *             entire command.
      */
+    @Deprecated
     public int size() {
         int size = getActualVMCommand().size() + javaCommand.size()
             + sysProperties.size();
@@ -714,6 +738,7 @@
      * @throws BuildException if anything went wrong.
      * @throws CloneNotSupportedException never.
      */
+    @Override
     public Object clone() throws CloneNotSupportedException {
         try {
             CommandlineJava c = (CommandlineJava) super.clone();
@@ -755,8 +780,8 @@
      * @since Ant 1.6
      */
     public boolean haveClasspath() {
-        Path fullClasspath = classpath != null ? classpath.concatSystemClasspath("ignore") : null;
-        return fullClasspath != null && fullClasspath.toString().trim().length() > 0;
+        Path fullClasspath = classpath == null ? null : classpath.concatSystemClasspath("ignore");
+        return fullClasspath != null && !fullClasspath.toString().trim().isEmpty();
     }
 
     /**
@@ -782,7 +807,7 @@
         Path fullClasspath = modulepath != null
                 ? modulepath.concatSystemClasspath("ignore") : null;
         return fullClasspath != null
-            && fullClasspath.toString().trim().length() > 0;
+            && !fullClasspath.toString().trim().isEmpty();
     }
 
     /**
@@ -792,8 +817,8 @@
      */
     public boolean haveUpgrademodulepath() {
         Path fullClasspath = upgrademodulepath != null
-            ? upgrademodulepath.concatSystemClasspath("ignore") : null;
-        return fullClasspath != null && fullClasspath.toString().trim().length() > 0;
+                ? upgrademodulepath.concatSystemClasspath("ignore") : null;
+        return fullClasspath != null && !fullClasspath.toString().trim().isEmpty();
     }
 
     /**
@@ -828,7 +853,7 @@
      * @since 1.7
      */
     private boolean isCloneVm() {
-        return cloneVm || "true".equals(System.getProperty("ant.build.clonevm"));
+        return cloneVm || Boolean.parseBoolean(System.getProperty("ant.build.clonevm"));
     }
 
     /**
@@ -886,6 +911,11 @@
         /**
          * Module execution.
          */
-        MODULE
+        MODULE,
+
+        /**
+         * Source file (introduced in Java 11)
+         */
+        SOURCE_FILE,
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/Comparison.java b/src/main/org/apache/tools/ant/types/Comparison.java
index a057d0d..28d7dbc 100644
--- a/src/main/org/apache/tools/ant/types/Comparison.java
+++ b/src/main/org/apache/tools/ant/types/Comparison.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/DTDLocation.java b/src/main/org/apache/tools/ant/types/DTDLocation.java
index 9fdeee2..b25b9f9 100644
--- a/src/main/org/apache/tools/ant/types/DTDLocation.java
+++ b/src/main/org/apache/tools/ant/types/DTDLocation.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,7 @@
  * <p>Helper class to handle the DTD nested element.  Instances of
  * this class correspond to the <code>PUBLIC</code> catalog entry type
  * of the <a
- * href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
+ * href="https://oasis-open.org/committees/entity/spec-2001-08-06.html">
  * OASIS "Open Catalog" standard</a>.</p>
  *
  * <p>Possible Future Enhancement: Bring the Ant element name into
diff --git a/src/main/org/apache/tools/ant/types/DataType.java b/src/main/org/apache/tools/ant/types/DataType.java
index f4306af..bac304c 100644
--- a/src/main/org/apache/tools/ant/types/DataType.java
+++ b/src/main/org/apache/tools/ant/types/DataType.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -114,7 +114,7 @@
         if (checked || !isReference()) {
             return;
         }
-        dieOnCircularReference(new IdentityStack<Object>(this), p);
+        dieOnCircularReference(new IdentityStack<>(this), p);
     }
 
     /**
@@ -196,24 +196,44 @@
     /**
      * Performs the check for circular references and returns the
      * referenced object.
+     * @param <T> required reference type
      * @return the dereferenced object.
      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
      * @since Ant 1.7
+     * @deprecated use getCheckedRef(Class)
      */
-    protected Object getCheckedRef() {
+    @Deprecated
+    protected <T> T getCheckedRef() {
         return getCheckedRef(getProject());
     }
 
     /**
      * Performs the check for circular references and returns the
      * referenced object.
+     * @param <T> required reference type
+     * @param requiredClass the class that this reference should be a subclass of.
+     * @return the dereferenced object.
+     * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
+     * @since Ant 1.10.6
+     */
+    protected <T> T getCheckedRef(final Class<T> requiredClass) {
+        return getCheckedRef(requiredClass, getDataTypeName(), getProject());
+    }
+
+    /**
+     * Performs the check for circular references and returns the
+     * referenced object.
+     * @param <T> required reference type
      * @param p the Ant Project instance against which to resolve references.
      * @return the dereferenced object.
      * @throws BuildException if the reference is invalid (circular ref, wrong class, etc).
      * @since Ant 1.7
+     * @deprecated use getCheckedRef(Class)
      */
-    protected Object getCheckedRef(Project p) {
-        return getCheckedRef(getClass(), getDataTypeName(), p);
+    @Deprecated
+    @SuppressWarnings("unchecked")
+    protected <T> T getCheckedRef(Project p) {
+        return getCheckedRef((Class<T>) getClass(), getDataTypeName(), p);
     }
 
     /**
@@ -250,18 +270,15 @@
             throw new BuildException("No Project specified");
         }
         dieOnCircularReference(project);
-        Object o = ref.getReferencedObject(project);
-        if (!(requiredClass.isAssignableFrom(o.getClass()))) {
-            log("Class " + displayName(o.getClass())
-                    + " is not a subclass of "
-                    + displayName(requiredClass),
-                    Project.MSG_VERBOSE);
-            String msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
-            throw new BuildException(msg);
+        T o = ref.getReferencedObject(project);
+        if (requiredClass.isAssignableFrom(o.getClass())) {
+            return o;
         }
-        @SuppressWarnings("unchecked")
-        final T result = (T) o;
-        return result;
+        log("Class " + displayName(o.getClass())
+                        + " is not a subclass of "
+                        + displayName(requiredClass),
+                Project.MSG_VERBOSE);
+        throw new BuildException(ref.getRefId() + " doesn't denote a " + dataTypeName);
     }
 
     /**
@@ -344,6 +361,7 @@
      * Basic DataType toString().
      * @return this DataType formatted as a String.
      */
+    @Override
     public String toString() {
         String d = getDescription();
         return d == null ? getDataTypeName() : getDataTypeName() + " " + d;
@@ -354,6 +372,7 @@
      * @return a shallow copy of this DataType.
      * @throws CloneNotSupportedException if there is a problem.
      */
+    @Override
     public Object clone() throws CloneNotSupportedException {
         DataType dt = (DataType) super.clone();
         dt.setDescription(getDescription());
diff --git a/src/main/org/apache/tools/ant/types/Description.java b/src/main/org/apache/tools/ant/types/Description.java
index d23f1d8..2446d41 100644
--- a/src/main/org/apache/tools/ant/types/Description.java
+++ b/src/main/org/apache/tools/ant/types/Description.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,9 +17,11 @@
  */
 package org.apache.tools.ant.types;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.Target;
@@ -51,7 +53,7 @@
      */
     public void addText(String text) {
 
-        ProjectHelper ph = getProject().getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+        ProjectHelper ph = getProject().getReference(MagicNames.REFID_PROJECT_HELPER);
         if (!(ph instanceof ProjectHelperImpl)) {
             // New behavior for delayed task creation. Description
             // will be evaluated in Project.getDescription()
@@ -90,27 +92,21 @@
         if (t == null) {
             return;
         }
-        for (Task task : findElementInTarget(project, t, "description")) {
-            if (!(task instanceof UnknownElement)) {
-                continue;
-            }
-            UnknownElement ue = ((UnknownElement) task);
-            String descComp = ue.getWrapper().getText().toString();
-            if (descComp != null) {
-                description.append(project.replaceProperties(descComp));
+        for (Task task : findElementInTarget(t, "description")) {
+            if (task instanceof UnknownElement) {
+                UnknownElement ue = (UnknownElement) task;
+                String descComp = ue.getWrapper().getText().toString();
+                if (descComp != null) {
+                    description.append(project.replaceProperties(descComp));
+                }
             }
         }
     }
 
-    private static List<Task> findElementInTarget(Project project,
-                                              Target t, String name) {
-        final List<Task> elems = new ArrayList<Task>();
-        for (Task task : t.getTasks()) {
-            if (name.equals(task.getTaskName())) {
-                elems.add(task);
-            }
-        }
-        return elems;
+    private static List<Task> findElementInTarget(Target t, String name) {
+        return Stream.of(t.getTasks())
+            .filter(task -> name.equals(task.getTaskName()))
+            .collect(Collectors.toList());
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/DirSet.java b/src/main/org/apache/tools/ant/types/DirSet.java
index 35c0231..a02d605 100644
--- a/src/main/org/apache/tools/ant/types/DirSet.java
+++ b/src/main/org/apache/tools/ant/types/DirSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,7 @@
 
 import java.util.Iterator;
 
-import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.resources.FileResourceIterator;
 
 /**
@@ -51,12 +51,12 @@
      * as this one.
      * @return the cloned dirset.
      */
+    @Override
     public Object clone() {
         if (isReference()) {
-            return ((DirSet) getRef(getProject())).clone();
-        } else {
-            return super.clone();
+            return getRef().clone();
         }
+        return super.clone();
     }
 
     /**
@@ -64,12 +64,13 @@
      * @return an Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((DirSet) getRef(getProject())).iterator();
+            return getRef().iterator();
         }
         return new FileResourceIterator(getProject(), getDir(getProject()),
-            getDirectoryScanner(getProject()).getIncludedDirectories());
+            getDirectoryScanner().getIncludedDirectories());
     }
 
     /**
@@ -77,11 +78,12 @@
      * @return number of elements as int.
      * @since Ant 1.7
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((DirSet) getRef(getProject())).size();
+            return getRef().size();
         }
-        return getDirectoryScanner(getProject()).getIncludedDirsCount();
+        return getDirectoryScanner().getIncludedDirsCount();
     }
 
     /**
@@ -89,6 +91,7 @@
      * @return true indicating that all elements will be FileResources.
      * @since Ant 1.7
      */
+    @Override
     public boolean isFilesystemOnly() {
         return true;
     }
@@ -98,18 +101,18 @@
      *
      * @return a <code>String</code> of included directories.
      */
+    @Override
     public String toString() {
-        DirectoryScanner ds = getDirectoryScanner(getProject());
-        String[] dirs = ds.getIncludedDirectories();
-        StringBuffer sb = new StringBuffer();
+        return String.join(";", getDirectoryScanner().getIncludedDirectories());
+    }
 
-        for (int i = 0; i < dirs.length; i++) {
-            if (i > 0) {
-                sb.append(';');
-            }
-            sb.append(dirs[i]);
-        }
-        return sb.toString();
+    @Override
+    protected AbstractFileSet getRef(Project p) {
+        return getCheckedRef(DirSet.class, getDataTypeName(), p);
+    }
+
+    private DirSet getRef() {
+        return getCheckedRef(DirSet.class);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/EnumeratedAttribute.java b/src/main/org/apache/tools/ant/types/EnumeratedAttribute.java
index 18603b2..0d5332f 100644
--- a/src/main/org/apache/tools/ant/types/EnumeratedAttribute.java
+++ b/src/main/org/apache/tools/ant/types/EnumeratedAttribute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,7 +46,7 @@
      * This is the only method a subclass needs to implement.
      *
      * @return an array holding all possible values of the enumeration.
-     * The order of elements must be fixed so that <tt>indexOfValue(String)</tt>
+     * The order of elements must be fixed so that <code>indexOfValue(String)</code>
      * always return the same index for the same value.
      */
     public abstract String[] getValues();
@@ -63,8 +63,8 @@
      * @return                  Configured EA
      * @throws BuildException   If the class could not be found or the value
      *                          is not valid for the given EA-class.
-     * @see <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=14831">
-     * http://issues.apache.org/bugzilla/show_bug.cgi?id=14831</a>
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=14831">
+     * https://issues.apache.org/bugzilla/show_bug.cgi?id=14831</a>
      */
     public static EnumeratedAttribute getInstance(
         Class<? extends EnumeratedAttribute> clazz,
@@ -73,9 +73,9 @@
             throw new BuildException(
                 "You have to provide a subclass from EnumeratedAttribute as clazz-parameter.");
         }
-        EnumeratedAttribute ea = null;
+        EnumeratedAttribute ea;
         try {
-            ea = clazz.newInstance();
+            ea = clazz.getDeclaredConstructor().newInstance();
         } catch (Exception e) {
             throw new BuildException(e);
         }
@@ -88,7 +88,7 @@
      * @param value the <code>String</code> value of the attribute
      * @throws BuildException if the value is not valid for the attribute
      */
-    public final void setValue(String value) throws BuildException {
+    public void setValue(String value) throws BuildException {
         int idx = indexOfValue(value);
         if (idx == -1) {
             throw new BuildException(value + " is not a legal value for this attribute");
@@ -146,6 +146,7 @@
      *
      * @return the string form of the value.
      */
+    @Override
     public String toString() {
         return getValue();
     }
diff --git a/src/main/org/apache/tools/ant/types/Environment.java b/src/main/org/apache/tools/ant/types/Environment.java
index 5bc6d79..15281a2 100644
--- a/src/main/org/apache/tools/ant/types/Environment.java
+++ b/src/main/org/apache/tools/ant/types/Environment.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -115,9 +115,7 @@
          */
         public String getContent() throws BuildException {
             validate();
-            StringBuffer sb = new StringBuffer(key.trim());
-            sb.append("=").append(value.trim());
-            return sb.toString();
+            return key.trim() + "=" + value.trim();
         }
 
         /**
@@ -126,8 +124,8 @@
          */
         public void validate() {
             if (key == null || value == null) {
-                throw new BuildException("key and value must be specified "
-                    + "for environment variables.");
+                throw new BuildException(
+                    "key and value must be specified for environment variables.");
             }
         }
     }
@@ -136,7 +134,7 @@
      * constructor
      */
     public Environment() {
-        variables = new Vector<Variable>();
+        variables = new Vector<>();
     }
 
     /**
@@ -155,14 +153,10 @@
      * @throws BuildException if any variable is misconfigured
      */
     public String[] getVariables() throws BuildException {
-        if (variables.size() == 0) {
+        if (variables.isEmpty()) {
             return null;
         }
-        String[] result = new String[variables.size()];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = ((Variable) variables.elementAt(i)).getContent();
-        }
-        return result;
+        return variables.stream().map(Variable::getContent).toArray(String[]::new);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/FileList.java b/src/main/org/apache/tools/ant/types/FileList.java
index c36ba6c..4c469b3 100644
--- a/src/main/org/apache/tools/ant/types/FileList.java
+++ b/src/main/org/apache/tools/ant/types/FileList.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,7 +37,7 @@
  */
 public class FileList extends DataType implements ResourceCollection {
 
-    private List<String> filenames = new ArrayList<String>();
+    private List<String> filenames = new ArrayList<>();
     private File dir;
 
     /**
@@ -68,8 +68,9 @@
      * @param r the reference to another filelist.
      * @exception BuildException if an error occurs.
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
-        if ((dir != null) || (filenames.size() != 0)) {
+        if (dir != null || !filenames.isEmpty()) {
             throw tooManyAttributes();
         }
         super.setRefid(r);
@@ -105,7 +106,7 @@
      */
     public void setFiles(String filenames) {
         checkAttributesAllowed();
-        if (filenames != null && filenames.length() > 0) {
+        if (filenames != null && !filenames.isEmpty()) {
             StringTokenizer tok = new StringTokenizer(
                 filenames, ", \t\n\r\f", false);
             while (tok.hasMoreTokens()) {
@@ -128,21 +129,11 @@
             throw new BuildException("No directory specified for filelist.");
         }
 
-        if (filenames.size() == 0) {
+        if (filenames.isEmpty()) {
             throw new BuildException("No files specified for filelist.");
         }
 
-        return filenames.toArray(new String[filenames.size()]);
-    }
-
-    /**
-     * Performs the check for circular references and returns the
-     * referenced FileList.
-     * @param p the current project
-     * @return the FileList represented by a referenced filelist.
-     */
-    protected FileList getRef(Project p) {
-        return (FileList) getCheckedRef(p);
+        return filenames.toArray(new String[0]);
     }
 
     /**
@@ -187,12 +178,13 @@
      * @return an Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return getRef(getProject()).iterator();
+            return getRef().iterator();
         }
         return new FileResourceIterator(getProject(), dir,
-            filenames.toArray(new String[filenames.size()]));
+            filenames.toArray(new String[0]));
     }
 
     /**
@@ -200,9 +192,10 @@
      * @return number of elements as int.
      * @since Ant 1.7
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((FileList) getRef(getProject())).size();
+            return getRef().size();
         }
         return filenames.size();
     }
@@ -212,8 +205,17 @@
      * @return true indicating that all elements will be FileResources.
      * @since Ant 1.7
      */
+    @Override
     public boolean isFilesystemOnly() {
         return true;
     }
 
+    private FileList getRef() {
+        return getCheckedRef(FileList.class);
+    }
+
+    private FileList getRef(Project p) {
+        return getCheckedRef(FileList.class, getDataTypeName(), p);
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/FileSet.java b/src/main/org/apache/tools/ant/types/FileSet.java
index c6d2127..7e01d10 100644
--- a/src/main/org/apache/tools/ant/types/FileSet.java
+++ b/src/main/org/apache/tools/ant/types/FileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,6 +20,7 @@
 
 import java.util.Iterator;
 
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.resources.FileResourceIterator;
 
 /**
@@ -49,12 +50,12 @@
      * as this one.
      * @return the cloned fileset
      */
+    @Override
     public Object clone() {
         if (isReference()) {
-            return ((FileSet) getRef(getProject())).clone();
-        } else {
-            return super.clone();
+            return getRef().clone();
         }
+        return super.clone();
     }
 
     /**
@@ -62,12 +63,13 @@
      * @return an Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((FileSet) getRef(getProject())).iterator();
+            return getRef().iterator();
         }
         return new FileResourceIterator(getProject(), getDir(getProject()),
-            getDirectoryScanner(getProject()).getIncludedFiles());
+            getDirectoryScanner().getIncludedFiles());
     }
 
     /**
@@ -75,11 +77,12 @@
      * @return number of elements as int.
      * @since Ant 1.7
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((FileSet) getRef(getProject())).size();
+            return getRef().size();
         }
-        return getDirectoryScanner(getProject()).getIncludedFilesCount();
+        return getDirectoryScanner().getIncludedFilesCount();
     }
 
     /**
@@ -87,8 +90,18 @@
      * @return true indicating that all elements will be FileResources.
      * @since Ant 1.7
      */
+    @Override
     public boolean isFilesystemOnly() {
         return true;
     }
 
+    @Override
+    protected AbstractFileSet getRef(Project p) {
+        return getCheckedRef(FileSet.class, getDataTypeName(), p);
+    }
+
+    private FileSet getRef() {
+        return getCheckedRef(FileSet.class);
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/FilterChain.java b/src/main/org/apache/tools/ant/types/FilterChain.java
index 6bad602..c03002d 100644
--- a/src/main/org/apache/tools/ant/types/FilterChain.java
+++ b/src/main/org/apache/tools/ant/types/FilterChain.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,7 +46,7 @@
  */
 public class FilterChain extends DataType {
 
-    private Vector<Object> filterReaders = new Vector<Object>();
+    private Vector<Object> filterReaders = new Vector<>();
 
     /**
      * Add an AntFilterReader filter.
@@ -68,7 +68,7 @@
      */
     public Vector<Object> getFilterReaders() {
         if (isReference()) {
-            return ((FilterChain) getCheckedRef()).getFilterReaders();
+            return getRef().getFilterReaders();
         }
         dieOnCircularReference();
         return filterReaders;
@@ -412,4 +412,8 @@
             setChecked(true);
         }
     }
+
+    private FilterChain getRef() {
+        return getCheckedRef(FilterChain.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/FilterSet.java b/src/main/org/apache/tools/ant/types/FilterSet.java
index 15352f2..6180580 100644
--- a/src/main/org/apache/tools/ant/types/FilterSet.java
+++ b/src/main/org/apache/tools/ant/types/FilterSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,8 @@
 package org.apache.tools.ant.types;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.util.Enumeration;
+import java.io.InputStream;
+import java.nio.file.Files;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.Properties;
@@ -28,7 +28,6 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.VectorSet;
 
 /**
@@ -113,12 +112,6 @@
     public class FiltersFile {
 
         /**
-         * Constructor for the FiltersFile object.
-         */
-        public FiltersFile() {
-        }
-
-        /**
          * Sets the file from which filters will be read.
          *
          * @param file the file from which filters will be read.
@@ -186,7 +179,7 @@
 
     private boolean recurse = true;
     private Hashtable<String, String> filterHash = null;
-    private Vector<File> filtersFiles = new Vector<File>();
+    private Vector<File> filtersFiles = new Vector<>();
     private OnMissing onMissingFiltersFile = OnMissing.FAIL;
     private boolean readingFiles = false;
 
@@ -195,7 +188,7 @@
     /**
      * List of ordered filters and filter files.
      */
-    private Vector<Filter> filters = new Vector<Filter>();
+    private Vector<Filter> filters = new Vector<>();
 
     /**
      * Default constructor.
@@ -225,7 +218,7 @@
             return getRef().getFilters();
         }
         dieOnCircularReference();
-        //silly hack to avoid stack overflow...
+        // silly hack to avoid stack overflow...
         if (!readingFiles) {
             readingFiles = true;
             for (File filtersFile : filtersFiles) {
@@ -243,7 +236,7 @@
      * @return the filterset from the reference.
      */
     protected FilterSet getRef() {
-        return getCheckedRef(FilterSet.class, "filterset");
+        return getCheckedRef(FilterSet.class);
     }
 
     /**
@@ -257,11 +250,8 @@
         }
         dieOnCircularReference();
         if (filterHash == null) {
-            filterHash = new Hashtable<String, String>(getFilters().size());
-            for (Enumeration<Filter> e = getFilters().elements(); e.hasMoreElements();) {
-               Filter filter = e.nextElement();
-               filterHash.put(filter.getToken(), filter.getValue());
-            }
+            filterHash = new Hashtable<>(getFilters().size());
+            getFilters().forEach(filter -> filterHash.put(filter.getToken(), filter.getValue()));
         }
         return filterHash;
     }
@@ -289,7 +279,7 @@
         if (isReference()) {
             throw tooManyAttributes();
         }
-        if (startOfToken == null || "".equals(startOfToken)) {
+        if (startOfToken == null || startOfToken.isEmpty()) {
             throw new BuildException("beginToken must not be empty");
         }
         this.startOfToken = startOfToken;
@@ -316,7 +306,7 @@
         if (isReference()) {
             throw tooManyAttributes();
         }
-        if (endOfToken == null || "".equals(endOfToken)) {
+        if (endOfToken == null || endOfToken.isEmpty()) {
             throw new BuildException("endToken must not be empty");
         }
         this.endOfToken = endOfToken;
@@ -356,39 +346,28 @@
      * @param filtersFile        the file from which filters are read.
      * @exception BuildException when the file cannot be read.
      */
-    public synchronized void readFiltersFromFile(File filtersFile) throws BuildException {
+    public synchronized void readFiltersFromFile(File filtersFile)
+        throws BuildException {
         if (isReference()) {
             throw tooManyAttributes();
         }
         if (!filtersFile.exists()) {
-           handleMissingFile("Could not read filters from file "
-                                     + filtersFile + " as it doesn't exist.");
+            handleMissingFile("Could not read filters from file " + filtersFile
+                + " as it doesn't exist.");
         }
         if (filtersFile.isFile()) {
-           log("Reading filters from " + filtersFile, Project.MSG_VERBOSE);
-           FileInputStream in = null;
-           try {
-              Properties props = new Properties();
-              in = new FileInputStream(filtersFile);
-              props.load(in);
-
-              Enumeration<?> e = props.propertyNames();
-              Vector<Filter> filts = getFilters();
-              while (e.hasMoreElements()) {
-                 String strPropName = (String) e.nextElement();
-                 String strValue = props.getProperty(strPropName);
-                 filts.addElement(new Filter(strPropName, strValue));
-              }
-           } catch (Exception ex) {
-              throw new BuildException("Could not read filters from file: "
-                  + filtersFile, ex);
-           } finally {
-              FileUtils.close(in);
-           }
+            log("Reading filters from " + filtersFile, Project.MSG_VERBOSE);
+            try (InputStream in = Files.newInputStream(filtersFile.toPath())) {
+                Properties props = new Properties();
+                props.load(in);
+                props.forEach((k, v) -> addFilter(new Filter((String) k, (String) v)));
+            } catch (Exception ex) {
+                throw new BuildException(
+                    "Could not read filters from file: " + filtersFile, ex);
+            }
         } else {
-           handleMissingFile(
-               "Must specify a file rather than a directory in "
-               + "the filtersfile attribute:" + filtersFile);
+            handleMissingFile("Must specify a file rather than a directory in "
+                + "the filtersfile attribute:" + filtersFile);
         }
         filterHash = null;
     }
@@ -469,7 +448,7 @@
             throw noChildrenAllowed();
         }
         Properties p = propertySet.getProperties();
-        Set<Map.Entry<Object,Object>> entries = p.entrySet();
+        Set<Map.Entry<Object, Object>> entries = p.entrySet();
         for (Map.Entry<Object, Object> entry : entries) {
             addFilter(new Filter(String.valueOf(entry.getKey()),
                                  String.valueOf(entry.getValue())));
@@ -482,7 +461,7 @@
      * @return Return true if there are filters in this set.
      */
     public synchronized boolean hasFilters() {
-        return getFilters().size() > 0;
+        return !getFilters().isEmpty();
     }
 
     /**
@@ -543,8 +522,6 @@
             try {
                 StringBuilder b = new StringBuilder();
                 int i = 0;
-                String token = null;
-                String value = null;
 
                 while (index > -1) {
                     //can't have zero-length token
@@ -553,11 +530,11 @@
                     if (endIndex == -1) {
                         break;
                     }
-                    token
-                        = line.substring(index + beginToken.length(), endIndex);
-                    b.append(line.substring(i, index));
+                    String token =
+                        line.substring(index + beginToken.length(), endIndex);
+                    b.append(line, i, index);
                     if (tokens.containsKey(token)) {
-                        value = tokens.get(token);
+                        String value = tokens.get(token);
                         if (recurse && !value.equals(token)) {
                             // we have another token, let's parse it.
                             value = replaceTokens(value, token);
@@ -601,7 +578,7 @@
         String beginToken = getBeginToken();
         String endToken = getEndToken();
         if (recurseDepth == 0) {
-            passedTokens = new VectorSet<String>();
+            passedTokens = new VectorSet<>();
         }
         recurseDepth++;
         if (passedTokens.contains(parent) && !duplicateToken) {
@@ -610,7 +587,7 @@
                 "Infinite loop in tokens. Currently known tokens : "
                 + passedTokens.toString() + "\nProblem token : " + beginToken
                 + parent + endToken + " called from " + beginToken
-                + passedTokens.lastElement().toString() + endToken);
+                + passedTokens.lastElement() + endToken);
             recurseDepth--;
             return parent;
         }
@@ -620,14 +597,14 @@
             passedTokens = null;
         } else if (duplicateToken) {
             // should always be the case...
-            if (passedTokens.size() > 0) {
+            if (!passedTokens.isEmpty()) {
                 value = passedTokens.remove(passedTokens.size() - 1);
-                if (passedTokens.size() == 0) {
+                if (passedTokens.isEmpty()) {
                     value = beginToken + value + endToken;
                     duplicateToken = false;
                 }
             }
-        } else if (passedTokens.size() > 0) {
+        } else if (!passedTokens.isEmpty()) {
             // remove last seen token when crawling out of recursion
             passedTokens.remove(passedTokens.size() - 1);
         }
diff --git a/src/main/org/apache/tools/ant/types/FilterSetCollection.java b/src/main/org/apache/tools/ant/types/FilterSetCollection.java
index 8afb963..9fb319d 100644
--- a/src/main/org/apache/tools/ant/types/FilterSetCollection.java
+++ b/src/main/org/apache/tools/ant/types/FilterSetCollection.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,7 +28,7 @@
  */
 public class FilterSetCollection {
 
-    private List<FilterSet> filterSets = new ArrayList<FilterSet>();
+    private List<FilterSet> filterSets = new ArrayList<>();
 
     /**
      * Constructor for a FilterSetCollection.
@@ -75,12 +75,7 @@
     * @return   Return true if there are filter in this set otherwise false.
     */
     public boolean hasFilters() {
-        for (FilterSet filterSet : filterSets) {
-            if (filterSet.hasFilters()) {
-                return true;
-            }
-        }
-        return false;
+        return filterSets.stream().anyMatch(FilterSet::hasFilters);
     }
 }
 
diff --git a/src/main/org/apache/tools/ant/types/FlexInteger.java b/src/main/org/apache/tools/ant/types/FlexInteger.java
index d757429..e71e137 100644
--- a/src/main/org/apache/tools/ant/types/FlexInteger.java
+++ b/src/main/org/apache/tools/ant/types/FlexInteger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,13 +41,14 @@
      * @return the integer value
      */
     public int intValue() {
-        return value.intValue();
+        return value;
     }
 
     /**
      * Overridden method to return the decimal value for display
      * @return a string version of the integer
      */
+    @Override
     public String toString() {
         return value.toString();
     }
diff --git a/src/main/org/apache/tools/ant/types/LogLevel.java b/src/main/org/apache/tools/ant/types/LogLevel.java
index a02b948..26c4d5c 100644
--- a/src/main/org/apache/tools/ant/types/LogLevel.java
+++ b/src/main/org/apache/tools/ant/types/LogLevel.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,6 +55,7 @@
      * @see EnumeratedAttribute#getValues
      * @return the strings allowed for the level attribute
      */
+    @Override
     public String[] getValues() {
         return new String[] {
             "error",
diff --git a/src/main/org/apache/tools/ant/types/Mapper.java b/src/main/org/apache/tools/ant/types/Mapper.java
index 925597f..bcb756c 100644
--- a/src/main/org/apache/tools/ant/types/Mapper.java
+++ b/src/main/org/apache/tools/ant/types/Mapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -87,7 +87,7 @@
                 if (m instanceof ContainerMapper) {
                     container = (ContainerMapper) m;
                 } else {
-                    throw new BuildException(String.valueOf(m)
+                    throw new BuildException(m
                         + " mapper implementation does not support nested mappers!");
                 }
             }
@@ -187,6 +187,7 @@
      * @param r the reference to another mapper
      * @throws BuildException if other attributes are set
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (type != null || from != null || to != null) {
             throw tooManyAttributes();
@@ -217,8 +218,7 @@
 
         if (type == null && classname == null && container == null) {
             throw new BuildException(
-                "nested mapper or "
-                + "one of the attributes type or classname is required");
+                    "nested mapper or one of the attributes type or classname is required");
         }
 
         if (container != null) {
@@ -231,7 +231,7 @@
         }
 
         try {
-            FileNameMapper m = getImplementationClass().newInstance();
+            FileNameMapper m = getImplementationClass().getDeclaredConstructor().newInstance();
             final Project p = getProject();
             if (p != null) {
                 p.setProjectReference(m);
@@ -276,7 +276,7 @@
      */
     @Deprecated
     protected Mapper getRef() {
-        return getCheckedRef(Mapper.class, getDataTypeName());
+        return getCheckedRef(Mapper.class);
     }
 
     /**
@@ -307,6 +307,7 @@
         /**
          * @return the filenamemapper names
          */
+        @Override
         public String[] getValues() {
             return new String[] {"identity", "flatten", "glob",
                                  "merge", "regexp", "package", "unpackage"};
diff --git a/src/main/org/apache/tools/ant/types/ModuleVersion.java b/src/main/org/apache/tools/ant/types/ModuleVersion.java
new file mode 100644
index 0000000..4335cb1
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/ModuleVersion.java
@@ -0,0 +1,150 @@
+/*
+ *  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
+ *
+ *      https://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;
+
+import java.util.Objects;
+
+/**
+ * Element describing the parts of a Java
+ * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/module/ModuleDescriptor.Version.html">module version</a>.
+ * The version number is required;  all other parts are optional.
+ *
+ * @since 1.10.6
+ */
+public class ModuleVersion {
+    /** Module version's required <em>version number</em>. */
+    private String number;
+
+    /** Module version's optional <em>pre-release version</em>. */
+    private String preRelease;
+
+    /** Module version's optional <em>build version</em>. */
+    private String build;
+
+    /**
+     * Returns this element's version number.
+     *
+     * @return version number
+     */
+    public String getNumber() {
+        return number;
+    }
+
+    /**
+     * Sets this element's required version number.  This cannot contain
+     * an ASCII hyphen ({@code -}) or plus ({@code +}), as those characters
+     * are used as delimiters in a complete module version string.
+     *
+     * @param number version number
+     * @throws NullPointerException if argument is {@code null}
+     * @throws IllegalArgumentException if argument contains {@code '-'}
+     *                                  or {@code '+'}
+     */
+    public void setNumber(final String number) {
+        Objects.requireNonNull(number, "Version number cannot be null.");
+        if (number.indexOf('-') >= 0 || number.indexOf('+') >= 0) {
+            throw new IllegalArgumentException(
+                "Version number cannot contain '-' or '+'.");
+        }
+        this.number = number;
+    }
+
+    /**
+     * Returns this element's pre-release version, if set.
+     *
+     * @return pre-release value, or {@code null}
+     */
+    public String getPreRelease() {
+        return preRelease;
+    }
+
+    /**
+     * Sets this element's pre-release version.  This can be any value
+     * which doesn't contain an ASCII plus ({@code +}).
+     *
+     * @param pre pre-release version, or {@code null}
+     *
+     * @throws IllegalArgumentException if argument contains "{@code +}"
+     */
+    public void setPreRelease(final String pre) {
+        if (pre != null && pre.indexOf('+') >= 0) {
+            throw new IllegalArgumentException(
+                "Version's pre-release cannot contain '+'.");
+        }
+        this.preRelease = pre;
+    }
+
+    /**
+     * Returns this element's build version, if set.
+     *
+     * @return build value, or {@code null}
+     */
+    public String getBuild() {
+        return build;
+    }
+
+    /**
+     * Sets this element's build version.  This can be any value, including
+     * {@code null}.
+     *
+     * @param build build version, or {@code null}
+     */
+    public void setBuild(final String build) {
+        this.build = build;
+    }
+
+    /**
+     * Snapshots this element's state and converts it to a string compliant
+     * with {@code ModuleDescriptor.Version}.
+     *
+     * @return Java module version string built from this object's properties
+     *
+     * @throws IllegalStateException if {@linkplain #getNumber() number}
+     *                               is {@code null}
+     */
+    public String toModuleVersionString() {
+        if (number == null) {
+            throw new IllegalStateException("Version number cannot be null.");
+        }
+
+        StringBuilder version = new StringBuilder(number);
+        if (preRelease != null || build != null) {
+            version.append('-').append(Objects.toString(preRelease, ""));
+        }
+        if (build != null) {
+            version.append('+').append(build);
+        }
+
+        return version.toString();
+    }
+
+    /**
+     * Returns a summary of this object's state, suitable for debugging.
+     *
+     * @return string form of this instance
+     */
+    @Override
+    public String toString() {
+        return getClass().getName() +
+            "[number=" + number +
+            ", preRelease=" + preRelease +
+            ", build=" + build +
+            "]";
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/Parameter.java b/src/main/org/apache/tools/ant/types/Parameter.java
index 6c16d2d..710a519 100644
--- a/src/main/org/apache/tools/ant/types/Parameter.java
+++ b/src/main/org/apache/tools/ant/types/Parameter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/Parameterizable.java b/src/main/org/apache/tools/ant/types/Parameterizable.java
index 7945a9a..a72ba66 100644
--- a/src/main/org/apache/tools/ant/types/Parameterizable.java
+++ b/src/main/org/apache/tools/ant/types/Parameterizable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,5 +27,5 @@
      *
      * @param parameters an array of name/type/value parameters.
      */
-    void setParameters(Parameter[] parameters);
+    void setParameters(Parameter... parameters);
 }
diff --git a/src/main/org/apache/tools/ant/types/Path.java b/src/main/org/apache/tools/ant/types/Path.java
index f2d4476..46d37bd 100644
--- a/src/main/org/apache/tools/ant/types/Path.java
+++ b/src/main/org/apache/tools/ant/types/Path.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,12 +20,13 @@
 
 import java.io.File;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.Stack;
-import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.MagicNames;
@@ -71,7 +72,6 @@
     public static Path systemClasspath = //NOSONAR
         new Path(null, System.getProperty("java.class.path"));
 
-
     /**
      * The system bootclasspath as a Path object.
      *
@@ -119,6 +119,7 @@
          * Create an iterator.
          * @return an iterator.
          */
+        @Override
         public Iterator<Resource> iterator() {
             return new FileResourceIterator(getProject(), null, parts);
         }
@@ -127,6 +128,7 @@
          * Check if this resource is only for filesystems.
          * @return true.
          */
+        @Override
         public boolean isFilesystemOnly() {
             return true;
         }
@@ -135,6 +137,7 @@
          * Get the number of resources.
          * @return the number of parts.
          */
+        @Override
         public int size() {
             return parts == null ? 0 : parts.length;
         }
@@ -194,6 +197,7 @@
      * @param r the reference to another Path
      * @throws BuildException on error
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (union != null) {
             throw tooManyAttributes();
@@ -343,9 +347,9 @@
             } else if (f.getParentFile() != null && f.getParentFile().exists()
                        && containsWildcards(f.getName())) {
                 setLocation(f);
-                log("adding " + f + " which contains wildcards and may not"
-                    + " do what you intend it to do depending on your OS or"
-                    + " version of Java", Project.MSG_VERBOSE);
+                log("adding " + f
+                    + " which contains wildcards and may not do what you intend it to do depending on your OS or version of Java",
+                    Project.MSG_VERBOSE);
             } else {
                 log("dropping " + f + " from path as it doesn't exist",
                     Project.MSG_VERBOSE);
@@ -372,7 +376,7 @@
      */
     public String[] list() {
         if (isReference()) {
-            return ((Path) getCheckedRef()).list();
+            return getRef().list();
         }
         return assertFilesystemOnly(union) == null
             ? new String[0] : union.list();
@@ -383,8 +387,9 @@
      * CLASSPATH or PATH environment variable definition.
      * @return a textual representation of the path.
      */
+    @Override
     public String toString() {
-        return isReference() ? getCheckedRef().toString()
+        return isReference() ? getRef().toString()
             : union == null ? "" : union.toString();
     }
 
@@ -395,13 +400,13 @@
      * @return an array of strings, one for each path element
      */
     public static String[] translatePath(Project project, String source) {
-        final Vector<String> result = new Vector<String>();
         if (source == null) {
             return new String[0];
         }
+        final List<String> result = new ArrayList<>();
         PathTokenizer tok = new PathTokenizer(source);
-        StringBuffer element = new StringBuffer();
         while (tok.hasMoreTokens()) {
+            StringBuffer element = new StringBuffer();
             String pathElement = tok.nextToken();
             try {
                 element.append(resolveFile(project, pathElement).getPath());
@@ -413,10 +418,9 @@
             for (int i = 0; i < element.length(); i++) {
                 translateFileSep(element, i);
             }
-            result.addElement(element.toString());
-            element = new StringBuffer();
+            result.add(element.toString());
         }
-        return result.toArray(new String[result.size()]);
+        return result.toArray(new String[0]);
     }
 
     /**
@@ -456,9 +460,10 @@
      * Fulfill the ResourceCollection contract.
      * @return number of elements as int.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
-            return ((Path) getCheckedRef()).size();
+            return getRef().size();
         }
         dieOnCircularReference();
         return union == null ? 0 : assertFilesystemOnly(union).size();
@@ -468,6 +473,7 @@
      * Clone this Path.
      * @return Path with shallowly cloned Resource children.
      */
+    @Override
     public Object clone() {
         try {
             Path result = (Path) super.clone();
@@ -485,6 +491,7 @@
      * @param p   the project to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -555,22 +562,22 @@
         if (o != null) {
             order = o;
         }
-        if (order.equals("only")) {
+        if ("only".equals(order)) {
             // only: the developer knows what (s)he is doing
             result.addExisting(p, true);
 
-        } else if (order.equals("first")) {
+        } else if ("first".equals(order)) {
             // first: developer could use a little help
             result.addExisting(p, true);
             result.addExisting(this);
 
-        } else if (order.equals("ignore")) {
+        } else if ("ignore".equals(order)) {
             // ignore: don't trust anyone
             result.addExisting(this);
 
         } else {
             // last: don't trust the developer
-            if (!order.equals("last")) {
+            if (!"last".equals(order)) {
                 log("invalid value for " + MagicNames.BUILD_SYSCLASSPATH
                     + ": " + order,
                     Project.MSG_WARN);
@@ -588,7 +595,7 @@
         if (JavaEnvUtils.isKaffe()) {
             // newer versions of Kaffe (1.1.1+) won't have this,
             // but this will be sorted by FileSet anyway.
-            File kaffeShare = new File(System.getProperty("java.home")
+            File kaffeShare = new File(JavaEnvUtils.getJavaHome()
                                        + File.separator + "share"
                                        + File.separator + "kaffe");
             if (kaffeShare.isDirectory()) {
@@ -605,57 +612,44 @@
             // TODO is this code still necessary? is there any 1.2+ port?
             // Pull in *.zip from packages directory
             FileSet msZipFiles = new FileSet();
-            msZipFiles.setDir(new File(System.getProperty("java.home")
-                + File.separator + "Packages"));
+            msZipFiles.setDir(new File(JavaEnvUtils.getJavaHome()
+                    + File.separator + "Packages"));
             msZipFiles.setIncludes("*.ZIP");
             addFileset(msZipFiles);
         } else {
             // JDK 1.2+ seems to set java.home to the JRE directory.
-            addExisting(new Path(null,
-                                 System.getProperty("java.home")
-                                 + File.separator + "lib"
-                                 + File.separator + "rt.jar"));
+            addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                    + File.separator + "lib" + File.separator + "rt.jar"));
             // Just keep the old version as well and let addExisting
             // sort it out.
-            addExisting(new Path(null,
-                                 System.getProperty("java.home")
-                                 + File.separator + "jre"
-                                 + File.separator + "lib"
-                                 + File.separator + "rt.jar"));
+            addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                    + File.separator + "jre" + File.separator + "lib"
+                    + File.separator + "rt.jar"));
 
             // Sun's and Apple's 1.4 have JCE and JSSE in separate jars.
             for (String secJar : Arrays.asList("jce", "jsse")) {
-                addExisting(new Path(null,
-                        System.getProperty("java.home")
-                                + File.separator + "lib"
-                                + File.separator + secJar + ".jar"));
-                addExisting(new Path(null,
-                        System.getProperty("java.home")
-                                + File.separator + ".."
-                                + File.separator + "Classes"
-                                + File.separator + secJar + ".jar"));
+                addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                        + File.separator + "lib"
+                        + File.separator + secJar + ".jar"));
+                addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                        + File.separator + ".." + File.separator + "Classes"
+                        + File.separator + secJar + ".jar"));
             }
 
             // IBM's 1.4 has rt.jar split into 4 smaller jars and a combined
             // JCE/JSSE in security.jar.
             for (String ibmJar : Arrays.asList("core", "graphics", "security", "server", "xml")) {
-                addExisting(new Path(null,
-                        System.getProperty("java.home")
-                                + File.separator + "lib"
-                                + File.separator + ibmJar + ".jar"));
+                addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                        + File.separator + "lib" + File.separator + ibmJar + ".jar"));
             }
 
             // Added for MacOS X
-            addExisting(new Path(null,
-                                 System.getProperty("java.home")
-                                 + File.separator + ".."
-                                 + File.separator + "Classes"
-                                 + File.separator + "classes.jar"));
-            addExisting(new Path(null,
-                                 System.getProperty("java.home")
-                                 + File.separator + ".."
-                                 + File.separator + "Classes"
-                                 + File.separator + "ui.jar"));
+            addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                    + File.separator + ".." + File.separator + "Classes"
+                    + File.separator + "classes.jar"));
+            addExisting(new Path(null, JavaEnvUtils.getJavaHome()
+                    + File.separator + ".." + File.separator + "Classes"
+                    + File.separator + "ui.jar"));
         }
     }
 
@@ -693,9 +687,10 @@
      * are added to this container while the Iterator is in use.
      * @return a "fail-fast" Iterator.
      */
+    @Override
     public final synchronized Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((Path) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         dieOnCircularReference();
         if (getPreserveBC()) {
@@ -709,9 +704,10 @@
      * Fulfill the ResourceCollection contract.
      * @return whether this is a filesystem-only resource collection.
      */
+    @Override
     public synchronized boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((Path) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         dieOnCircularReference();
         assertFilesystemOnly(union);
@@ -726,8 +722,8 @@
      */
     protected ResourceCollection assertFilesystemOnly(ResourceCollection rc) {
         if (rc != null && !(rc.isFilesystemOnly())) {
-            throw new BuildException(getDataTypeName()
-                + " allows only filesystem resources.");
+            throw new BuildException("%s allows only filesystem resources.",
+                getDataTypeName());
         }
         return rc;
     }
@@ -745,7 +741,7 @@
             return false;
         }
         try {
-            Method listMethod = getClass().getMethod("list", (Class[]) null);
+            Method listMethod = getClass().getMethod("list");
             return !listMethod.getDeclaringClass().equals(Path.class);
         } catch (Exception e) {
             //shouldn't happen, but
@@ -757,7 +753,7 @@
         if (preserveBC == null) {
             preserveBC = delegateIteratorToList() ? Boolean.TRUE : Boolean.FALSE;
         }
-        return preserveBC.booleanValue();
+        return preserveBC;
     }
 
     /**
@@ -768,4 +764,8 @@
         return path != null && (path.contains("*") || path.contains("?"));
     }
 
+    private Path getRef() {
+        return getCheckedRef(Path.class);
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/PatternSet.java b/src/main/org/apache/tools/ant/types/PatternSet.java
index 9763308..f2b186e 100644
--- a/src/main/org/apache/tools/ant/types/PatternSet.java
+++ b/src/main/org/apache/tools/ant/types/PatternSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,14 +23,16 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.StringTokenizer;
+import java.util.function.Predicate;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.PropertyHelper;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Named collection of include/exclude tags.
@@ -40,15 +42,15 @@
  *
  */
 public class PatternSet extends DataType implements Cloneable {
-    private List<NameEntry> includeList = new ArrayList<NameEntry>();
-    private List<NameEntry> excludeList = new ArrayList<NameEntry>();
-    private List<PatternFileNameEntry> includesFileList = new ArrayList<PatternFileNameEntry>();
-    private List<PatternFileNameEntry> excludesFileList = new ArrayList<PatternFileNameEntry>();
+    private List<NameEntry> includeList = new ArrayList<>();
+    private List<NameEntry> excludeList = new ArrayList<>();
+    private List<PatternFileNameEntry> includesFileList = new ArrayList<>();
+    private List<PatternFileNameEntry> excludesFileList = new ArrayList<>();
 
     /**
      * inner class to hold a name on list.  "If" and "Unless" attributes
      * may be used to invalidate the entry based on the existence of a
-     * property (typically set thru the use of the Available task)
+     * property (typically set through the use of the Available task)
      * or value of an expression.
      */
     public class NameEntry {
@@ -152,14 +154,15 @@
         /**
          * @return a printable form of this object.
          */
+        @Override
         public String toString() {
-            StringBuffer buf = new StringBuffer();
+            StringBuilder buf = new StringBuilder();
             if (name == null) {
                 buf.append("noname");
             } else {
                 buf.append(name);
             }
-            if ((ifCond != null) || (unlessCond != null)) {
+            if (ifCond != null || unlessCond != null) {
                 buf.append(":");
                 String connector = "";
 
@@ -180,7 +183,7 @@
 
     /**
      * Adds encoding support to {@link NameEntry}.
-     * @since Ant 1.9.12
+     * @since Ant 1.10.4
      */
     public class PatternFileNameEntry extends NameEntry {
         private String encoding;
@@ -191,8 +194,8 @@
          *
          * <p>
          * For a list of possible values see
-         * <a href="https://docs.oracle.com/javase/1.5.0/docs/guide/intl/encoding.doc.html">
-         * https://docs.oracle.com/javase/1.5.0/docs/guide/intl/encoding.doc.html</a>.
+         * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+         * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.
          * </p>
          *
          * @param encoding String
@@ -215,7 +218,7 @@
         public String toString() {
             String baseString = super.toString();
             return encoding == null ? baseString
-                : new StringBuilder(baseString).append(";encoding->").append(encoding).toString();
+                : baseString + ";encoding->" + encoding;
         }
     }
 
@@ -224,9 +227,11 @@
             setProject(p.getProject());
             addConfiguredPatternset(p);
         }
+        @Override
         public String[] getIncludePatterns(Project p) {
             return super.getExcludePatterns(p);
         }
+        @Override
         public String[] getExcludePatterns(Project p) {
             return super.getIncludePatterns(p);
         }
@@ -248,6 +253,7 @@
      * @param r the reference to another patternset.
      * @throws BuildException on error.
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (!includeList.isEmpty() || !excludeList.isEmpty()) {
             throw tooManyAttributes();
@@ -333,7 +339,7 @@
         if (isReference()) {
             throw tooManyAttributes();
         }
-        if (includes != null && includes.length() > 0) {
+        if (includes != null && !includes.isEmpty()) {
             StringTokenizer tok = new StringTokenizer(includes, ", ", false);
             while (tok.hasMoreTokens()) {
                 createInclude().setName(tok.nextToken());
@@ -351,7 +357,7 @@
         if (isReference()) {
             throw tooManyAttributes();
         }
-        if (excludes != null && excludes.length() > 0) {
+        if (excludes != null && !excludes.isEmpty()) {
             StringTokenizer tok = new StringTokenizer(excludes, ", ", false);
             while (tok.hasMoreTokens()) {
                 createExclude().setName(tok.nextToken());
@@ -410,30 +416,20 @@
     private void readPatterns(File patternfile, String encoding, List<NameEntry> patternlist, Project p)
             throws BuildException {
 
-        BufferedReader patternReader = null;
-        try {
-            // Get a FileReader
-            if (encoding == null) {
-                patternReader = new BufferedReader(new FileReader(patternfile));
-            } else {
-                patternReader = new BufferedReader(new InputStreamReader(new FileInputStream(patternfile), encoding));
-            }
+        try (Reader r = encoding == null ? new FileReader(patternfile)
+             : new InputStreamReader(new FileInputStream(patternfile), encoding);
+             BufferedReader patternReader = new BufferedReader(r)) {
 
             // Create one NameEntry in the appropriate pattern list for each
             // line in the file.
-            String line = patternReader.readLine();
-            while (line != null) {
-                if (line.length() > 0) {
-                    line = p.replaceProperties(line);
-                    addPatternToList(patternlist).setName(line);
-                }
-                line = patternReader.readLine();
-            }
+            patternReader.lines()
+                .filter(((Predicate<String>) String::isEmpty).negate())
+                .map(p::replaceProperties)
+                .forEach(line -> addPatternToList(patternlist).setName(line));
+
         } catch (IOException ioe)  {
             throw new BuildException("An error occurred while reading from pattern file: "
                     + patternfile, ioe);
-        } finally {
-            FileUtils.close(patternReader);
         }
     }
 
@@ -500,8 +496,8 @@
             return getRef(p).hasPatterns(p);
         }
         dieOnCircularReference(p);
-        return includesFileList.size() > 0 || excludesFileList.size() > 0
-                || includeList.size() > 0 || excludeList.size() > 0;
+        return !(includesFileList.isEmpty() && excludesFileList.isEmpty()
+            && includeList.isEmpty() && excludeList.isEmpty());
     }
 
     /**
@@ -509,31 +505,25 @@
      * referenced PatternSet.
      */
     private PatternSet getRef(Project p) {
-        return (PatternSet) getCheckedRef(p);
+        return getCheckedRef(PatternSet.class, getDataTypeName(), p);
     }
 
     /**
      * Convert a vector of NameEntry elements into an array of Strings.
      */
     private String[] makeArray(List<NameEntry> list, Project p) {
-        if (list.size() == 0) {
+        if (list.isEmpty()) {
             return null;
         }
-        ArrayList<String> tmpNames = new ArrayList<String>();
-        for (NameEntry ne : list) {
-            String pattern = ne.evalName(p);
-            if (pattern != null && pattern.length() > 0) {
-                tmpNames.add(pattern);
-            }
-        }
-        return tmpNames.toArray(new String[tmpNames.size()]);
+        return list.stream().map(ne -> ne.evalName(p)).filter(Objects::nonNull)
+            .filter(pattern -> !pattern.isEmpty()).toArray(String[]::new);
     }
 
     /**
      * Read includesfile ot excludesfile if not already done so.
      */
     private void readFiles(Project p) {
-        if (includesFileList.size() > 0) {
+        if (!includesFileList.isEmpty()) {
             for (PatternFileNameEntry ne : includesFileList) {
                 String fileName = ne.evalName(p);
                 if (fileName != null) {
@@ -547,7 +537,7 @@
             }
             includesFileList.clear();
         }
-        if (excludesFileList.size() > 0) {
+        if (!excludesFileList.isEmpty()) {
             for (PatternFileNameEntry ne : excludesFileList) {
                 String fileName = ne.evalName(p);
                 if (fileName != null) {
@@ -566,21 +556,24 @@
     /**
      * @return a printable form of this object.
      */
+    @Override
     public String toString() {
-        return "patternSet{ includes: " + includeList + " excludes: " + excludeList + " }";
+        return String.format("patternSet{ includes: %s excludes: %s }",
+            includeList, excludeList);
     }
 
     /**
      * @since Ant 1.6
      * @return a clone of this patternset.
      */
+    @Override
     public Object clone() {
         try {
             PatternSet ps = (PatternSet) super.clone();
-            ps.includeList = new ArrayList<NameEntry>(includeList);
-            ps.excludeList = new ArrayList<NameEntry>(excludeList);
-            ps.includesFileList = new ArrayList<PatternFileNameEntry>(includesFileList);
-            ps.excludesFileList = new ArrayList<PatternFileNameEntry>(excludesFileList);
+            ps.includeList = new ArrayList<>(includeList);
+            ps.excludeList = new ArrayList<>(excludeList);
+            ps.includesFileList = new ArrayList<>(includesFileList);
+            ps.excludesFileList = new ArrayList<>(excludesFileList);
             return ps;
         } catch (CloneNotSupportedException e) {
             throw new BuildException(e);
diff --git a/src/main/org/apache/tools/ant/types/Permissions.java b/src/main/org/apache/tools/ant/types/Permissions.java
index da805af..b61d9f6 100644
--- a/src/main/org/apache/tools/ant/types/Permissions.java
+++ b/src/main/org/apache/tools/ant/types/Permissions.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,8 +46,8 @@
  */
 public class Permissions {
 
-    private final List<Permission> grantedPermissions = new LinkedList<Permission>();
-    private final List<Permission> revokedPermissions = new LinkedList<Permission>();
+    private final List<Permission> grantedPermissions = new LinkedList<>();
+    private final List<Permission> revokedPermissions = new LinkedList<>();
     private java.security.Permissions granted = null;
     private SecurityManager origSm = null;
     private boolean active = false;
@@ -157,7 +157,7 @@
             final String name = permission.getName();
             final String actions = permission.getActions();
             final Constructor<? extends java.security.Permission> ctr = clazz.getConstructor(PARAMS);
-            return ctr.newInstance(new Object[] {name, actions});
+            return ctr.newInstance(name, actions);
         } catch (final Exception e) {
             // Let the UnresolvedPermission handle it.
             return new UnresolvedPermission(permission.getClassName(),
@@ -207,10 +207,7 @@
         public void checkPermission(final java.security.Permission perm) {
             if (active) {
                 if (delegateToOldSM && !perm.getName().equals("exitVM")) {
-                    boolean permOK = false;
-                    if (granted.implies(perm)) {
-                        permOK = true;
-                    }
+                    boolean permOK = granted.implies(perm);
                     checkRevoked(perm);
                     /*
                      if the permission was not explicitly granted or revoked
@@ -286,7 +283,7 @@
          */
         public void setActions(final String actions) {
             actionString = actions;
-            if (actions.length() > 0) {
+            if (!actions.isEmpty()) {
                 this.actions = parseActions(actions);
             }
         }
@@ -312,20 +309,16 @@
                     if (!perm.getName().startsWith(name.substring(0, name.length() - 1))) {
                         return false;
                     }
-                } else {
-                    if (!name.equals(perm.getName())) {
-                        return false;
-                    }
+                } else if (!name.equals(perm.getName())) {
+                    return false;
                 }
             }
             if (actions != null) {
                 final Set<String> as = parseActions(perm.getActions());
                 final int size = as.size();
                 as.removeAll(actions);
-                if (as.size() == size) {
-                    // None of the actions revoked, so all allowed.
-                    return false;
-                }
+                // If no actions removed, then all allowed
+                return as.size() != size;
             }
             return true;
         }
@@ -335,11 +328,11 @@
          * @param actions The actions to be parsed.
          */
         private Set<String> parseActions(final String actions) {
-            final Set<String> result = new HashSet<String>();
+            final Set<String> result = new HashSet<>();
             final StringTokenizer tk = new StringTokenizer(actions, ",");
             while (tk.hasMoreTokens()) {
                 final String item = tk.nextToken().trim();
-                if (!item.equals("")) {
+                if (!item.isEmpty()) {
                     result.add(item);
                 }
             }
diff --git a/src/main/org/apache/tools/ant/types/PropertySet.java b/src/main/org/apache/tools/ant/types/PropertySet.java
index f599204..b1b7d79 100644
--- a/src/main/org/apache/tools/ant/types/PropertySet.java
+++ b/src/main/org/apache/tools/ant/types/PropertySet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,22 +18,24 @@
 
 package org.apache.tools.ant.types;
 
+import java.util.AbstractMap;
 import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.Stack;
 import java.util.TreeMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.PropertyHelper;
 import org.apache.tools.ant.types.resources.MappedResource;
 import org.apache.tools.ant.types.resources.PropertyResource;
 import org.apache.tools.ant.util.FileNameMapper;
@@ -50,8 +52,8 @@
     private boolean dynamic = true;
     private boolean negate = false;
     private Set<String> cachedNames;
-    private List<PropertyRef> ptyRefs = new ArrayList<PropertyRef>();
-    private List<PropertySet> setRefs = new ArrayList<PropertySet>();
+    private List<PropertyRef> ptyRefs = new ArrayList<>();
+    private List<PropertySet> setRefs = new ArrayList<>();
     private Mapper mapper;
 
     /**
@@ -118,6 +120,7 @@
          * A debug toString().
          * @return a string version of this object.
          */
+        @Override
         public String toString() {
             return "name=" + name + ", regex=" + regex + ", prefix=" + prefix
                 + ", builtin=" + builtin;
@@ -273,18 +276,13 @@
     }
 
     /**
-     * Convert the system properties to a hashtable.
-     * Use propertynames to get the list of properties (including
+     * Convert the system properties to a Map.
+     * Use stringPropertyNames to get the list of properties (including
      * default ones).
      */
-    private Hashtable<String, Object> getAllSystemProperties() {
-        Hashtable<String, Object>  ret = new Hashtable<String, Object>();
-        for (Enumeration<?> e = System.getProperties().propertyNames();
-             e.hasMoreElements();) {
-            String name = (String) e.nextElement();
-            ret.put(name, System.getProperties().getProperty(name));
-        }
-        return ret;
+    private Map<String, Object> getAllSystemProperties() {
+        return System.getProperties().stringPropertyNames().stream()
+                .collect(Collectors.toMap(name -> name, name -> System.getProperties().getProperty(name), (a, b) -> b));
     }
 
     /**
@@ -312,7 +310,7 @@
 
         final Map<String, Object> effectiveProperties = getEffectiveProperties();
         final Set<String> propertyNames = getPropertyNames(effectiveProperties);
-        final Map<String, Object> result = new HashMap<String, Object>();
+        final Map<String, Object> result = new HashMap<>();
 
         //iterate through the names, get the matching values
         for (String name : propertyNames) {
@@ -338,7 +336,16 @@
 
     private Map<String, Object> getEffectiveProperties() {
         final Project prj = getProject();
-        final Map<String, Object> result = prj == null ? getAllSystemProperties() : prj.getProperties();
+        final Map<String, Object> result;
+        if (prj == null) {
+            result = getAllSystemProperties();
+        } else {
+            final PropertyHelper ph = PropertyHelper.getPropertyHelper(prj);
+            result = prj.getPropertyNames().stream()
+                .map(n -> new AbstractMap.SimpleImmutableEntry<>(n, ph.getProperty(n)))
+                .filter(kv -> kv.getValue() != null)
+                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+        }
         //quick & dirty, to make nested mapped p-sets work:
         for (PropertySet set : setRefs) {
             result.putAll(set.getPropertyMap());
@@ -349,7 +356,7 @@
     private Set<String> getPropertyNames(Map<String, Object> props) {
         Set<String> names;
         if (getDynamic() || cachedNames == null) {
-            names = new HashSet<String>();
+            names = new HashSet<>();
             addPropertyNames(names, props);
             // Add this PropertySet's nested PropertySets' property names.
             for (PropertySet set : setRefs) {
@@ -357,7 +364,7 @@
             }
             if (negate) {
                 //make a copy...
-                HashSet<String> complement = new HashSet<String>(props.keySet());
+                HashSet<String> complement = new HashSet<>(props.keySet());
                 complement.removeAll(names);
                 names = complement;
             }
@@ -403,17 +410,19 @@
                     }
                 }
             } else if (r.builtin != null) {
-
-                if (r.builtin.equals(BuiltinPropertySetName.ALL)) {
-                    names.addAll(props.keySet());
-                } else if (r.builtin.equals(BuiltinPropertySetName.SYSTEM)) {
-                    names.addAll(getAllSystemProperties().keySet());
-                } else if (r.builtin.equals(BuiltinPropertySetName
-                                              .COMMANDLINE)) {
-                    names.addAll(getProject().getUserProperties().keySet());
-                } else {
-                    throw new BuildException("Impossible: Invalid builtin "
-                                             + "attribute!");
+                switch (r.builtin) {
+                    case BuiltinPropertySetName.ALL:
+                        names.addAll(props.keySet());
+                        break;
+                    case BuiltinPropertySetName.SYSTEM:
+                        names.addAll(getAllSystemProperties().keySet());
+                        break;
+                    case BuiltinPropertySetName.COMMANDLINE:
+                        names.addAll(getProject().getUserProperties().keySet());
+                        break;
+                    default:
+                        throw new BuildException("Impossible: Invalid builtin "
+                                + "attribute!");
                 }
             } else {
                 throw new BuildException("Impossible: Invalid PropertyRef!");
@@ -427,7 +436,7 @@
      * @return the referenced PropertySet.
      */
     protected PropertySet getRef() {
-        return (PropertySet) getCheckedRef(PropertySet.class, "propertyset");
+        return getCheckedRef(PropertySet.class);
     }
 
     /**
@@ -437,6 +446,7 @@
      * @throws BuildException if another attribute was set, since
      *         refid and all other attributes are mutually exclusive.
      */
+    @Override
     public final void setRefid(Reference r) {
         if (!noAttributeSet) {
             throw tooManyAttributes();
@@ -475,6 +485,7 @@
         static final String SYSTEM = "system";
         static final String COMMANDLINE = "commandline";
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
             return new String[] {ALL, SYSTEM, COMMANDLINE};
         }
@@ -487,22 +498,14 @@
      * The output order is sorted according to the keys' <i>natural order</i>.
      * @return a string rep of this object.
      */
+    @Override
     public String toString() {
         if (isReference()) {
             return getRef().toString();
         }
         dieOnCircularReference();
-        StringBuilder b = new StringBuilder();
-        TreeMap<String, Object> sorted = new TreeMap<String, Object>(getPropertyMap());
-        for (Entry<String, Object> e : sorted.entrySet()) {
-            if (b.length() != 0) {
-                b.append(", ");
-            }
-            b.append(e.getKey());
-            b.append("=");
-            b.append(e.getValue());
-        }
-        return b.toString();
+        return new TreeMap<>(getPropertyMap()).entrySet().stream()
+                .map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(", "));
     }
 
     /**
@@ -510,35 +513,27 @@
      * @return an Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
             return getRef().iterator();
         }
         dieOnCircularReference();
-        final Set<String> names = getPropertyNames(getEffectiveProperties());
-
-        Mapper myMapper = getMapper();
-        final FileNameMapper m = myMapper == null ? null : myMapper.getImplementation();
-        final Iterator<String> iter = names.iterator();
-
-        return new Iterator<Resource>() {
-            public boolean hasNext() {
-                return iter.hasNext();
-            }
-            public Resource next() {
-                PropertyResource p = new PropertyResource(getProject(), iter.next());
-                return m == null ? (Resource) p : new MappedResource(p, m);
-            }
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
+        Stream<Resource> result = getPropertyNames(getEffectiveProperties())
+            .stream().map(name -> new PropertyResource(getProject(), name));
+        Optional<FileNameMapper> m =
+            Optional.ofNullable(getMapper()).map(Mapper::getImplementation);
+        if (m.isPresent()) {
+            result = result.map(p -> new MappedResource(p, m.get()));
+        }
+        return result.iterator();
     }
 
     /**
      * Fulfill the ResourceCollection contract.
      * @return the size of this ResourceCollection.
      */
+    @Override
     public int size() {
         return isReference() ? getRef().size() : getProperties().size();
     }
@@ -547,6 +542,7 @@
      * Fulfill the ResourceCollection contract.
      * @return whether this is a filesystem-only resource collection.
      */
+    @Override
     public boolean isFilesystemOnly() {
         if (isReference()) {
             return getRef().isFilesystemOnly();
@@ -555,6 +551,7 @@
         return false;
     }
 
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -567,8 +564,7 @@
                 pushAndInvokeCircularReferenceCheck(mapper, stk, p);
             }
             for (PropertySet propertySet : setRefs) {
-                pushAndInvokeCircularReferenceCheck(propertySet, stk,
-                                                    p);
+                pushAndInvokeCircularReferenceCheck(propertySet, stk, p);
             }
             setChecked(true);
         }
diff --git a/src/main/org/apache/tools/ant/types/Quantifier.java b/src/main/org/apache/tools/ant/types/Quantifier.java
index 76b88d6..b0868cc 100644
--- a/src/main/org/apache/tools/ant/types/Quantifier.java
+++ b/src/main/org/apache/tools/ant/types/Quantifier.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,12 @@
  */
 package org.apache.tools.ant.types;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+
 import org.apache.tools.ant.BuildException;
 
 /**
@@ -36,61 +42,84 @@
  * @since Ant 1.7
  */
 public class Quantifier extends EnumeratedAttribute {
-    private static final String[] VALUES
-        = new String[] {"all", "each", "every", "any", "some", "one",
-                        "majority", "most", "none"};
+    private static final String[] VALUES =
+            Stream.of(Predicate.values()).map(Predicate::getNames)
+                .flatMap(Collection::stream).toArray(String[]::new);
 
     /** ALL instance */
-    public static final Quantifier ALL = new Quantifier("all");
+    public static final Quantifier ALL = new Quantifier(Predicate.ALL);
+
     /** ANY instance */
-    public static final Quantifier ANY = new Quantifier("any");
+    public static final Quantifier ANY = new Quantifier(Predicate.ANY);
+
     /** ONE instance */
-    public static final Quantifier ONE = new Quantifier("one");
+    public static final Quantifier ONE = new Quantifier(Predicate.ONE);
+
     /** MAJORITY instance */
-    public static final Quantifier MAJORITY = new Quantifier("majority");
+    public static final Quantifier MAJORITY =
+        new Quantifier(Predicate.MAJORITY);
+
     /** NONE instance */
-    public static final Quantifier NONE = new Quantifier("none");
+    public static final Quantifier NONE = new Quantifier(Predicate.NONE);
 
-    private abstract static class Predicate {
+    private enum Predicate {
+        ALL("all", "each", "every") {
+            @Override
+            boolean eval(int t, int f) {
+                return f == 0;
+            }
+        },
+
+        ANY("any", "some") {
+            @Override
+            boolean eval(int t, int f) {
+                return t > 0;
+            }
+        },
+
+        ONE("one") {
+            @Override
+            boolean eval(int t, int f) {
+                return t == 1;
+            }
+        },
+
+        MAJORITY("majority", "most") {
+            @Override
+            boolean eval(int t, int f) {
+                return t > f;
+            }
+        },
+
+        NONE("none") {
+            @Override
+            boolean eval(int t, int f) {
+                return t == 0;
+            }
+        };
+
+        static Predicate get(String name) {
+            return Stream.of(values()).filter(p -> p.names.contains(name))
+                .findFirst()
+                .orElseThrow(() -> new IllegalArgumentException(name));
+        }
+
+        final Set<String> names;
+
+        Predicate(String primaryName, String... additionalNames) {
+            Set<String> names = new LinkedHashSet<>();
+            names.add(primaryName);
+            Collections.addAll(names, additionalNames);
+            this.names = Collections.unmodifiableSet(names);
+        }
+
+        Set<String> getNames() {
+            return names;
+        }
+
         abstract boolean eval(int t, int f);
     }
 
-    private static final Predicate ALL_PRED = new Predicate() {
-        boolean eval(int t, int f) { return f == 0; }
-    };
-
-    private static final Predicate ANY_PRED = new Predicate() {
-        boolean eval(int t, int f) { return t > 0; }
-    };
-
-    private static final Predicate ONE_PRED = new Predicate() {
-        boolean eval(int t, int f) { return t == 1; }
-    };
-
-    private static final Predicate MAJORITY_PRED = new Predicate() {
-        boolean eval(int t, int f) { return t > f; }
-    };
-
-    private static final Predicate NONE_PRED = new Predicate() {
-        boolean eval(int t, int f) { return t == 0; }
-    };
-
-    private static final Predicate[] PREDS = new Predicate[VALUES.length];
-
-    static {
-        // CheckStyle:MagicNumber OFF
-        PREDS[0] = ALL_PRED;
-        PREDS[1] = ALL_PRED;
-        PREDS[2] = ALL_PRED;
-        PREDS[3] = ANY_PRED;
-        PREDS[4] = ANY_PRED;
-        PREDS[5] = ONE_PRED;
-        PREDS[6] = MAJORITY_PRED;
-        PREDS[7] = MAJORITY_PRED;
-        PREDS[8] = NONE_PRED;
-        // CheckStyle:MagicNumber ON
-    }
-
     /**
      * Default constructor.
      */
@@ -105,10 +134,15 @@
         setValue(value);
     }
 
+    private Quantifier(Predicate impl) {
+        setValue(impl.getNames().iterator().next());
+    }
+
     /**
      * Return the possible values.
      * @return String[] of EnumeratedAttribute values.
      */
+    @Override
     public String[] getValues() {
         return VALUES;
     }
@@ -139,7 +173,7 @@
         if (index == -1) {
             throw new BuildException("Quantifier value not set.");
         }
-        return PREDS[index].eval(t, f);
+        return Predicate.get(VALUES[index]).eval(t, f);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/RedirectorElement.java b/src/main/org/apache/tools/ant/types/RedirectorElement.java
index b57afec..2315da2 100644
--- a/src/main/org/apache/tools/ant/types/RedirectorElement.java
+++ b/src/main/org/apache/tools/ant/types/RedirectorElement.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -85,13 +85,13 @@
     private Mapper errorMapper;
 
     /** input filter chains. */
-    private Vector<FilterChain> inputFilterChains = new Vector<FilterChain>();
+    private Vector<FilterChain> inputFilterChains = new Vector<>();
 
     /** output filter chains. */
-    private Vector<FilterChain> outputFilterChains = new Vector<FilterChain>();
+    private Vector<FilterChain> outputFilterChains = new Vector<>();
 
     /** error filter chains. */
-    private Vector<FilterChain> errorFilterChains = new Vector<FilterChain>();
+    private Vector<FilterChain> errorFilterChains = new Vector<>();
 
     /** The output encoding */
     private String outputEncoding;
@@ -464,16 +464,16 @@
         }
         dieOnCircularReference();
         if (alwaysLog != null) {
-            redirector.setAlwaysLog(alwaysLog.booleanValue());
+            redirector.setAlwaysLog(alwaysLog);
         }
         if (logError != null) {
-            redirector.setLogError(logError.booleanValue());
+            redirector.setLogError(logError);
         }
         if (append != null) {
-            redirector.setAppend(append.booleanValue());
+            redirector.setAppend(append);
         }
         if (createEmptyFiles != null) {
-            redirector.setCreateEmptyFiles(createEmptyFiles.booleanValue());
+            redirector.setCreateEmptyFiles(createEmptyFiles);
         }
         if (outputProperty != null) {
             redirector.setOutputProperty(outputProperty);
@@ -485,7 +485,7 @@
             redirector.setInputString(inputString);
         }
         if (logInputString != null) {
-            redirector.setLogInputString(logInputString.booleanValue());
+            redirector.setLogInputString(logInputString);
         }
         if (inputMapper != null) {
             String[] inputTargets = null;
@@ -529,13 +529,13 @@
                 redirector.setError(toFileArray(errorTargets));
             }
         }
-        if (inputFilterChains.size() > 0) {
+        if (!inputFilterChains.isEmpty()) {
             redirector.setInputFilterChains(inputFilterChains);
         }
-        if (outputFilterChains.size() > 0) {
+        if (!outputFilterChains.isEmpty()) {
             redirector.setOutputFilterChains(outputFilterChains);
         }
-        if (errorFilterChains.size() > 0) {
+        if (!errorFilterChains.isEmpty()) {
             redirector.setErrorFilterChains(errorFilterChains);
         }
         if (inputEncoding != null) {
@@ -572,13 +572,13 @@
             return null;
         }
         //remove any null elements
-        ArrayList<File> list = new ArrayList<File>(name.length);
+        ArrayList<File> list = new ArrayList<>(name.length);
         for (String n : name) {
             if (n != null) {
                 list.add(getProject().resolveFile(n));
             }
         }
-        return list.toArray(new File[list.size()]);
+        return list.toArray(new File[0]);
     }
 
     /**
@@ -588,6 +588,7 @@
      * @param p   the project to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -603,7 +604,6 @@
                     stk.pop();
                 }
             }
-            @SuppressWarnings("unchecked")
             final List<? extends List<FilterChain>> filterChainLists = Arrays
                     .<List<FilterChain>> asList(inputFilterChains, outputFilterChains,
                             errorFilterChains);
@@ -624,7 +624,7 @@
      * @return the referenced RedirectorElement.
      */
     private RedirectorElement getRef() {
-        return (RedirectorElement) getCheckedRef();
+        return getCheckedRef(RedirectorElement.class);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/Reference.java b/src/main/org/apache/tools/ant/types/Reference.java
index eefabcf..c357fa8 100644
--- a/src/main/org/apache/tools/ant/types/Reference.java
+++ b/src/main/org/apache/tools/ant/types/Reference.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -102,17 +102,18 @@
     /**
      * Resolve the reference, using the associated project if
      * it set, otherwise use the passed in project.
+     * @param <T> desired object type
      * @param fallback the fallback project to use if the project attribute of
      *                 reference is not set.
      * @return the dereferenced object.
      * @throws BuildException if the reference cannot be dereferenced.
      */
-    public Object getReferencedObject(Project fallback) throws BuildException {
+    public <T> T getReferencedObject(Project fallback) throws BuildException {
         if (refid == null) {
             throw new BuildException("No reference specified");
         }
 
-        Object o = project == null ? fallback.getReference(refid) : project.getReference(refid);
+        T o = project == null ? fallback.getReference(refid) : project.getReference(refid);
         if (o == null) {
             throw new BuildException("Reference " + refid + " not found.");
         }
@@ -122,11 +123,12 @@
     /**
      * Resolve the reference, looking in the associated project.
      * @see Project#getReference
+     * @param <T> desired object type
      * @return the dereferenced object.
      * @throws BuildException if the project is null or the reference cannot be dereferenced
      * @since Ant 1.6.3
      */
-    public Object getReferencedObject() throws BuildException {
+    public <T> T getReferencedObject() throws BuildException {
         if (project == null) {
             throw new BuildException("No project set on reference to " + refid);
         }
diff --git a/src/main/org/apache/tools/ant/types/RegularExpression.java b/src/main/org/apache/tools/ant/types/RegularExpression.java
index 18ee3f1..5054b52 100644
--- a/src/main/org/apache/tools/ant/types/RegularExpression.java
+++ b/src/main/org/apache/tools/ant/types/RegularExpression.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -69,12 +69,6 @@
     private String myPattern;
     private boolean setPatternPending = false;
 
-    /**
-     * default constructor
-     */
-    public RegularExpression() {
-    }
-
     private void init(Project p) {
         if (!alreadyInit) {
             this.regexp = FACTORY.newRegexp(p);
@@ -136,6 +130,6 @@
      * @return resolved RegularExpression instance
      */
     public RegularExpression getRef(Project p) {
-        return (RegularExpression) getCheckedRef(p);
+        return getCheckedRef(RegularExpression.class, getDataTypeName(), p);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/Resource.java b/src/main/org/apache/tools/ant/types/Resource.java
index 5bf9814..12563d4 100644
--- a/src/main/org/apache/tools/ant/types/Resource.java
+++ b/src/main/org/apache/tools/ant/types/Resource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,8 +21,9 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.math.BigInteger;
+import java.util.Collections;
 import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.util.Optional;
 
 import org.apache.tools.ant.types.resources.FileProvider;
 
@@ -140,7 +141,7 @@
      * @return the name of this resource.
      */
     public String getName() {
-        return isReference() ? ((Resource) getCheckedRef()).getName() : name;
+        return isReference() ? getRef().getName() : name;
     }
 
     /**
@@ -159,10 +160,10 @@
      */
     public boolean isExists() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).isExists();
+            return getRef().isExists();
         }
         //default true:
-        return exists == null || exists.booleanValue();
+        return exists == null || exists;
     }
 
     /**
@@ -186,12 +187,12 @@
      */
     public long getLastModified() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getLastModified();
+            return getRef().getLastModified();
         }
         if (!isExists() || lastmodified == null) {
             return UNKNOWN_DATETIME;
         }
-        long result = lastmodified.longValue();
+        long result = lastmodified;
         return result < UNKNOWN_DATETIME ? UNKNOWN_DATETIME : result;
     }
 
@@ -201,7 +202,7 @@
      */
     public void setLastModified(long lastmodified) {
         checkAttributesAllowed();
-        this.lastmodified = new Long(lastmodified);
+        this.lastmodified = lastmodified;
     }
 
     /**
@@ -210,10 +211,10 @@
      */
     public boolean isDirectory() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).isDirectory();
+            return getRef().isDirectory();
         }
         //default false:
-        return directory != null && directory.booleanValue();
+        return directory != null && directory;
     }
 
     /**
@@ -232,7 +233,7 @@
      */
     public void setSize(long size) {
         checkAttributesAllowed();
-        this.size = new Long(size > UNKNOWN_SIZE ? size : UNKNOWN_SIZE);
+        this.size = size > UNKNOWN_SIZE ? size : UNKNOWN_SIZE;
     }
 
     /**
@@ -243,10 +244,10 @@
      */
     public long getSize() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getSize();
+            return getRef().getSize();
         }
         return isExists()
-            ? (size != null ? size.longValue() : UNKNOWN_SIZE)
+            ? (size != null ? size : UNKNOWN_SIZE)
             : 0L;
     }
 
@@ -254,13 +255,13 @@
      * Clone this Resource.
      * @return copy of this.
      */
+    @Override
     public Object clone() {
         try {
             return super.clone();
         } catch (CloneNotSupportedException e) {
             throw new UnsupportedOperationException(
-                    "CloneNotSupportedException for a Resource caught. "
-                    + "Derived classes must support cloning.");
+                "CloneNotSupportedException for a Resource caught. Derived classes must support cloning.");
         }
     }
 
@@ -271,9 +272,10 @@
      *         is less than, equal to, or greater than the specified Resource.
      * @since Ant 1.6
      */
+    @Override
     public int compareTo(Resource other) {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).compareTo(other);
+            return getRef().compareTo(other);
         }
         return toString().compareTo(other.toString());
     }
@@ -284,12 +286,13 @@
      * @return true if the specified Object is equal to this Resource.
      * @since Ant 1.7
      */
+    @Override
     public boolean equals(Object other) {
         if (this == other) {
             return true;
         }
         if (isReference()) {
-            return getCheckedRef().equals(other);
+            return getRef().equals(other);
         }
         return other != null && other.getClass().equals(getClass())
             && compareTo((Resource) other) == 0;
@@ -300,9 +303,10 @@
      * @return hash code as int.
      * @since Ant 1.7
      */
+    @Override
     public int hashCode() {
         if (isReference()) {
-            return getCheckedRef().hashCode();
+            return getRef().hashCode();
         }
         String name = getName();
         return MAGIC * (name == null ? NULL_NAME : name.hashCode());
@@ -319,7 +323,7 @@
      */
     public InputStream getInputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getInputStream();
+            return getRef().getInputStream();
         }
         throw new UnsupportedOperationException();
     }
@@ -335,7 +339,7 @@
      */
     public OutputStream getOutputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getOutputStream();
+            return getRef().getOutputStream();
         }
         throw new UnsupportedOperationException();
     }
@@ -345,24 +349,10 @@
      * @return an Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
-        return isReference() ? ((Resource) getCheckedRef()).iterator()
-            : new Iterator<Resource>() {
-            private boolean done = false;
-            public boolean hasNext() {
-                return !done;
-            }
-            public Resource next() {
-                if (done) {
-                    throw new NoSuchElementException();
-                }
-                done = true;
-                return Resource.this;
-            }
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
+        return isReference() ? getRef().iterator()
+            : Collections.singleton(this).iterator();
     }
 
     /**
@@ -370,8 +360,9 @@
      * @return the size of this ResourceCollection.
      * @since Ant 1.7
      */
+    @Override
     public int size() {
-        return isReference() ? ((Resource) getCheckedRef()).size() : 1;
+        return isReference() ? getRef().size() : 1;
     }
 
     /**
@@ -379,8 +370,9 @@
      * @return whether this Resource is a FileProvider.
      * @since Ant 1.7
      */
+    @Override
     public boolean isFilesystemOnly() {
-        return (isReference() && ((Resource) getCheckedRef()).isFilesystemOnly())
+        return (isReference() && getRef().isFilesystemOnly())
             || this.as(FileProvider.class) != null;
     }
 
@@ -389,9 +381,10 @@
      * @return this Resource formatted as a String.
      * @since Ant 1.7
      */
+    @Override
     public String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
         String n = getName();
         return n == null ? "(anonymous)" : n;
@@ -405,7 +398,7 @@
      * @since Ant 1.7
      */
     public final String toLongString() {
-        return isReference() ? ((Resource) getCheckedRef()).toLongString()
+        return isReference() ? getRef().toLongString()
             : getDataTypeName() + " \"" + toString() + '"';
     }
 
@@ -413,6 +406,7 @@
      * Overrides the base version.
      * @param r the Reference to set.
      */
+    @Override
     public void setRefid(Reference r) {
         if (name != null
             || exists != null
@@ -443,4 +437,24 @@
     public <T> T as(Class<T> clazz) {
         return clazz.isAssignableFrom(getClass()) ? clazz.cast(this) : null;
     }
+
+    /**
+     * Return {@link #as(Class)} as an {@link Optional}.
+     * @param <T> desired type
+     * @param clazz a class
+     * @return {@link Optional} resource of a desired type
+     * @since Ant 1.10.2
+     */
+    public <T> Optional<T> asOptional(Class<T> clazz) {
+        return Optional.ofNullable(as(clazz));
+    }
+
+    /**
+     * Perform the check for circular references and return the
+     * referenced Resource.
+     * @return <code>Resource</code>.
+     */
+    protected Resource getRef() {
+        return getCheckedRef(Resource.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/ResourceCollection.java b/src/main/org/apache/tools/ant/types/ResourceCollection.java
index a82c8b5..34dab8a 100644
--- a/src/main/org/apache/tools/ant/types/ResourceCollection.java
+++ b/src/main/org/apache/tools/ant/types/ResourceCollection.java
@@ -1,50 +1,61 @@
 /*
- *  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.
- *
+ * 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
+ * https://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;
 
-import java.util.Iterator;
+import java.util.stream.Stream;
 
 /**
  * Interface describing a collection of Resources.
+ *
  * @since Ant 1.7
  */
 public interface ResourceCollection extends Iterable<Resource> {
 
     /**
-     * Gets the contents of this collection.
-     * @return all resources in the collection
-     */
-    Iterator<Resource> iterator();
-
-    /**
      * Learn the number of contained Resources.
+     *
      * @return number of elements as int.
      */
     int size();
 
     /**
      * Indicate whether this ResourceCollection is composed entirely of
-     * Resources accessible via local filesystem conventions. If true,
-     * all resources returned from this collection should
-     * respond with a {@link org.apache.tools.ant.types.resources.FileProvider}
-     * when asked via {@link Resource#as}.
+     * Resources accessible via local filesystem conventions. If true, all
+     * resources returned from this collection should respond with a
+     * {@link org.apache.tools.ant.types.resources.FileProvider} when asked via
+     * {@link Resource#as}.
+     *
      * @return whether this is a filesystem-only resource collection.
      */
     boolean isFilesystemOnly();
 
+    /**
+     * Return a {@link Stream} over this {@link ResourceCollection}.
+     * @return {@link Stream} of {@link Resource}
+     * @since Ant 1.10.2
+     */
+    default Stream<? extends Resource> stream() {
+        final Stream.Builder<Resource> b = Stream.builder();
+        forEach(b);
+        return b.build();
+    }
+
+    /**
+     * Learn whether this {@link ResourceCollection} is empty.
+     * @return boolean
+     */
+    default boolean isEmpty() {
+        return size() == 0;
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/ResourceFactory.java b/src/main/org/apache/tools/ant/types/ResourceFactory.java
index 515318e..ec2ef03 100644
--- a/src/main/org/apache/tools/ant/types/ResourceFactory.java
+++ b/src/main/org/apache/tools/ant/types/ResourceFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/ResourceLocation.java b/src/main/org/apache/tools/ant/types/ResourceLocation.java
index 0879154..59eabfe 100644
--- a/src/main/org/apache/tools/ant/types/ResourceLocation.java
+++ b/src/main/org/apache/tools/ant/types/ResourceLocation.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,7 +24,7 @@
  * <code>&lt;entity&gt;</code> nested elements.  These correspond to
  * the <code>PUBLIC</code> and <code>URI</code> catalog entry types,
  * respectively, as defined in the <a
- * href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
+ * href="https://oasis-open.org/committees/entity/spec-2001-08-06.html">
  * OASIS "Open Catalog" standard</a>.</p>
  *
  * <p>Possible Future Enhancements:</p>
diff --git a/src/main/org/apache/tools/ant/types/Substitution.java b/src/main/org/apache/tools/ant/types/Substitution.java
index 2b11da5..7197b35 100644
--- a/src/main/org/apache/tools/ant/types/Substitution.java
+++ b/src/main/org/apache/tools/ant/types/Substitution.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -71,6 +71,6 @@
      * @return the resolved reference
      */
     public Substitution getRef(Project p) {
-        return (Substitution) getCheckedRef(p);
+        return getCheckedRef(Substitution.class, getDataTypeName(), p);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/TarFileSet.java b/src/main/org/apache/tools/ant/types/TarFileSet.java
index 6446e9b..a95fca1 100644
--- a/src/main/org/apache/tools/ant/types/TarFileSet.java
+++ b/src/main/org/apache/tools/ant/types/TarFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -78,7 +78,7 @@
      */
     public String getUserName() {
         if (isReference()) {
-            return ((TarFileSet) getCheckedRef()).getUserName();
+            return ((TarFileSet) getRef()).getUserName();
         }
         return userName;
     }
@@ -106,7 +106,7 @@
      */
     public int getUid() {
         if (isReference()) {
-            return ((TarFileSet) getCheckedRef()).getUid();
+            return ((TarFileSet) getRef()).getUid();
         }
         return uid;
     }
@@ -134,7 +134,7 @@
      */
     public String getGroup() {
         if (isReference()) {
-            return ((TarFileSet) getCheckedRef()).getGroup();
+            return ((TarFileSet) getRef()).getGroup();
         }
         return groupName;
     }
@@ -162,7 +162,7 @@
      */
     public int getGid() {
         if (isReference()) {
-            return ((TarFileSet) getCheckedRef()).getGid();
+            return ((TarFileSet) getRef()).getGid();
         }
         return gid;
     }
@@ -178,6 +178,7 @@
      * Create a new scanner.
      * @return the created scanner.
      */
+    @Override
     protected ArchiveScanner newArchiveScanner() {
         TarScanner zs = new TarScanner();
         zs.setEncoding(getEncoding());
@@ -192,6 +193,7 @@
      * @param r the <code>Reference</code> to use.
      * @throws BuildException on error
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (userNameSet || userIdSet || groupNameSet || groupIdSet) {
             throw tooManyAttributes();
@@ -205,19 +207,30 @@
      * @param p the project to use
      * @return the abstract fileset instance
      */
+    @Override
     protected AbstractFileSet getRef(Project p) {
         dieOnCircularReference(p);
         Object o = getRefid().getReferencedObject(p);
         if (o instanceof TarFileSet) {
             return (AbstractFileSet) o;
-        } else if (o instanceof FileSet) {
+        }
+        if (o instanceof FileSet) {
             TarFileSet zfs = new TarFileSet((FileSet) o);
             configureFileSet(zfs);
             return zfs;
-        } else {
-            String msg = getRefid().getRefId() + " doesn\'t denote a tarfileset or a fileset";
-            throw new BuildException(msg);
         }
+        String msg = getRefid().getRefId() + " doesn't denote a tarfileset or a fileset";
+        throw new BuildException(msg);
+    }
+
+    /**
+     * A TarFileset accepts another TarFileSet or a FileSet as reference
+     * FileSets are often used by the war task for the lib attribute
+     * @return the abstract fileset instance
+     */
+    @Override
+    protected AbstractFileSet getRef() {
+        return getRef(getProject());
     }
 
     /**
@@ -226,6 +239,7 @@
      * specific attributes.
      * @param zfs the archive fileset to configure.
      */
+    @Override
     protected void configureFileSet(ArchiveFileSet zfs) {
         super.configureFileSet(zfs);
         if (zfs instanceof TarFileSet) {
@@ -242,12 +256,12 @@
      * as this one.
      * @return the cloned tarFileSet
      */
+    @Override
     public Object clone() {
         if (isReference()) {
-            return ((TarFileSet) getRef(getProject())).clone();
-        } else {
-            return super.clone();
+            return getRef().clone();
         }
+        return super.clone();
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/TarScanner.java b/src/main/org/apache/tools/ant/types/TarScanner.java
index a3c7f6d..1dca3ee 100644
--- a/src/main/org/apache/tools/ant/types/TarScanner.java
+++ b/src/main/org/apache/tools/ant/types/TarScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,6 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.resources.TarResource;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.tar.TarEntry;
 import org.apache.tools.tar.TarInputStream;
 
@@ -53,35 +52,30 @@
             Map<String, Resource> fileEntries, Map<String, Resource> matchFileEntries,
             Map<String, Resource> dirEntries, Map<String, Resource> matchDirEntries) {
 
-        TarEntry entry = null;
-        TarInputStream ti = null;
-
-        try {
+        try (TarInputStream ti = new TarInputStream(src.getInputStream(), encoding)) {
             try {
-                ti = new TarInputStream(src.getInputStream(), encoding);
-            } catch (IOException ex) {
-                throw new BuildException("problem opening " + srcFile, ex);
-            }
-            while ((entry = ti.getNextEntry()) != null) {
-                Resource r = new TarResource(src, entry);
-                String name = entry.getName();
-                if (entry.isDirectory()) {
-                    name = trimSeparator(name);
-                    dirEntries.put(name, r);
-                    if (match(name)) {
-                        matchDirEntries.put(name, r);
-                    }
-                } else {
-                    fileEntries.put(name, r);
-                    if (match(name)) {
-                        matchFileEntries.put(name, r);
+                TarEntry entry = null;
+                while ((entry = ti.getNextEntry()) != null) {
+                    Resource r = new TarResource(src, entry);
+                    String name = entry.getName();
+                    if (entry.isDirectory()) {
+                        name = trimSeparator(name);
+                        dirEntries.put(name, r);
+                        if (match(name)) {
+                            matchDirEntries.put(name, r);
+                        }
+                    } else {
+                        fileEntries.put(name, r);
+                        if (match(name)) {
+                            matchFileEntries.put(name, r);
+                        }
                     }
                 }
+            } catch (IOException ex) {
+                throw new BuildException("problem reading " + srcFile, ex);
             }
         } catch (IOException ex) {
-            throw new BuildException("problem reading " + srcFile, ex);
-        } finally {
-            FileUtils.close(ti);
+            throw new BuildException("problem opening " + srcFile, ex);
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/TimeComparison.java b/src/main/org/apache/tools/ant/types/TimeComparison.java
index 15c136e..67c4998 100644
--- a/src/main/org/apache/tools/ant/types/TimeComparison.java
+++ b/src/main/org/apache/tools/ant/types/TimeComparison.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/XMLCatalog.java b/src/main/org/apache/tools/ant/types/XMLCatalog.java
index c857bd8..92943fc 100644
--- a/src/main/org/apache/tools/ant/types/XMLCatalog.java
+++ b/src/main/org/apache/tools/ant/types/XMLCatalog.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,13 @@
 package org.apache.tools.ant.types;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.nio.file.Files;
 import java.util.Stack;
 import java.util.Vector;
 
@@ -50,21 +50,21 @@
 /**
  * <p>This data type provides a catalog of resource locations (such as
  * DTDs and XML entities), based on the <a
- * href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
+ * href="https://oasis-open.org/committees/entity/spec-2001-08-06.html">
  * OASIS "Open Catalog" standard</a>.  The catalog entries are used
  * both for Entity resolution and URI resolution, in accordance with
  * the {@link org.xml.sax.EntityResolver EntityResolver} and {@link
  * javax.xml.transform.URIResolver URIResolver} interfaces as defined
- * in the <a href="http://java.sun.com/xml/jaxp">Java API for XML
+ * in the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/xml/jaxp/index.html">Java API for XML
  * Processing Specification</a>.</p>
  *
  * <p>Resource locations can be specified either in-line or in
  * external catalog file(s), or both.  In order to use an external
  * catalog file, the xml-commons resolver library ("resolver.jar")
  * must be in your classpath.  External catalog files may be either <a
- * href="http://oasis-open.org/committees/entity/background/9401.html">
+ * href="https://oasis-open.org/committees/entity/background/9401.html">
  * plain text format</a> or <a
- * href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
+ * href="https://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
  * XML format</a>.  If the xml-commons resolver library is not found
  * in the classpath, external catalog files, specified in
  * <code>&lt;catalogpath&gt;</code> paths, will be ignored and a warning will
@@ -124,7 +124,7 @@
     //-- Fields ----------------------------------------------------------------
 
     /** Holds dtd/entity objects until needed. */
-    private Vector<ResourceLocation> elements = new Vector<ResourceLocation>();
+    private Vector<ResourceLocation> elements = new Vector<>();
 
     /**
      * Classpath in which to attempt to resolve resources.
@@ -353,6 +353,7 @@
      * @param r the reference to which this catalog instance is associated
      * @exception BuildException if this instance already has been configured.
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (!elements.isEmpty()) {
             throw tooManyAttributes();
@@ -369,6 +370,7 @@
      * @return the resolved entity.
      * @see org.xml.sax.EntityResolver#resolveEntity
      */
+    @Override
     public InputSource resolveEntity(String publicId, String systemId)
         throws SAXException, IOException {
 
@@ -400,6 +402,7 @@
      * @throws TransformerException if an error occurs.
      * @see javax.xml.transform.URIResolver#resolve
      */
+    @Override
     public Source resolve(String href, String base)
         throws TransformerException {
 
@@ -425,14 +428,14 @@
             // setEntityResolver (see setEntityResolver javadoc comment)
             //
             source = new SAXSource();
-            URL baseURL = null;
+            URL baseURL;
             try {
                 if (base == null) {
                     baseURL = FILE_UTILS.getFileURL(getProject().getBaseDir());
                 } else {
                     baseURL = new URL(base);
                 }
-                URL url = (uri.length() == 0 ? baseURL : new URL(baseURL, uri));
+                URL url = uri.isEmpty() ? baseURL : new URL(baseURL, uri);
                 source.setInputSource(new InputSource(url.toString()));
             } catch (MalformedURLException ex) {
                 // At this point we are probably in failure mode, but
@@ -445,6 +448,7 @@
         return source;
     }
 
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -470,7 +474,7 @@
         if (!isReference()) {
             return this;
         }
-        return getCheckedRef(XMLCatalog.class, "xmlcatalog");
+        return getCheckedRef(XMLCatalog.class);
     }
 
     /**
@@ -492,7 +496,7 @@
 
         if (catalogResolver == null) {
 
-            AntClassLoader loader = null;
+            AntClassLoader loader;
             // Memory-Leak in line below
             loader = getProject().createClassLoader(Path.systemClasspath);
 
@@ -518,7 +522,7 @@
                 // if it can see it - doesn't use the context loader.
                 clazz = Class.forName(APACHE_RESOLVER, true, baseResolverLoader);
 
-                Object obj  = clazz.newInstance();
+                Object obj  = clazz.getDeclaredConstructor().newInstance();
                 //
                 // Success!  The xml-commons resolver library is
                 // available, so use it.
@@ -551,10 +555,10 @@
      * inherit the EntityResolver of the original (although arguably
      * it should).  See below:</p>
      *
-     * <tt>"If an application wants to set the ErrorHandler or
+     * <code>"If an application wants to set the ErrorHandler or
      * EntityResolver for an XMLReader used during a transformation,
      * it should use a URIResolver to return the SAXSource which
-     * provides (with getXMLReader) a reference to the XMLReader"</tt>
+     * provides (with getXMLReader) a reference to the XMLReader"</code>
      *
      * <p>...quoted from page 118 of the Java API for XML
      * Processing 1.1 specification</p>
@@ -568,9 +572,7 @@
             spFactory.setNamespaceAware(true);
             try {
                 reader = spFactory.newSAXParser().getXMLReader();
-            } catch (ParserConfigurationException ex) {
-                throw new TransformerException(ex);
-            } catch (SAXException ex) {
+            } catch (ParserConfigurationException | SAXException ex) {
                 throw new TransformerException(ex);
             }
         }
@@ -587,19 +589,16 @@
      *         of the Resource or null if no such information is available.
      */
     private ResourceLocation findMatchingEntry(String publicId) {
-        for (ResourceLocation element : getElements()) {
-            if (element.getPublicId().equals(publicId)) {
-                return element;
-            }
-        }
-        return null;
+        return getElements().stream()
+            .filter(e -> e.getPublicId().equals(publicId)).findFirst()
+            .orElse(null);
     }
 
     /**
      * Utility method to remove trailing fragment from a URI.
      * For example,
-     * <code>http://java.sun.com/index.html#chapter1</code>
-     * would return <code>http://java.sun.com/index.html</code>.
+     * <code>https://java.sun.com/index.html#chapter1</code>
+     * would return <code>https://java.sun.com/index.html</code>.
      *
      * @param uri The URI to process.  It may or may not contain a
      *            fragment.
@@ -625,7 +624,7 @@
         String uri = matchingEntry.getLocation();
         // the following line seems to be necessary on Windows under JDK 1.2
         uri = uri.replace(File.separatorChar, '/');
-        URL baseURL = null;
+        URL baseURL;
 
         //
         // The ResourceLocation may specify a relative path for its
@@ -642,7 +641,6 @@
             }
         }
 
-        InputSource source = null;
         URL url = null;
         try {
             url = new URL(baseURL, uri);
@@ -667,14 +665,15 @@
             }
         }
 
-        if (url != null && url.getProtocol().equals("file")) {
+        InputSource source = null;
+        if (url != null && "file".equals(url.getProtocol())) {
             String fileName = FILE_UTILS.fromURI(url.toString());
             if (fileName != null) {
                 log("fileName " + fileName, Project.MSG_DEBUG);
                 File resFile = new File(fileName);
                 if (resFile.exists() && resFile.canRead()) {
                     try {
-                        source = new InputSource(new FileInputStream(resFile));
+                        source = new InputSource(Files.newInputStream(resFile.toPath()));
                         String sysid = JAXPUtils.getSystemId(resFile);
                         source.setSystemId(sysid);
                         log("catalog entry matched a readable file: '"
@@ -698,14 +697,13 @@
 
         InputSource source = null;
 
-        AntClassLoader loader = null;
         Path cp = classpath;
         if (cp != null) {
             cp = classpath.concatSystemClasspath("ignore");
         } else {
             cp = (new Path(getProject())).concatSystemClasspath("last");
         }
-        loader = getProject().createClassLoader(cp);
+        AntClassLoader loader = getProject().createClassLoader(cp);
 
         //
         // for classpath lookup we ignore the base directory
@@ -734,7 +732,7 @@
     private InputSource urlLookup(ResourceLocation matchingEntry) {
 
         String uri = matchingEntry.getLocation();
-        URL baseURL = null;
+        URL baseURL;
 
         //
         // The ResourceLocation may specify a relative url for its
@@ -751,15 +749,15 @@
             }
         }
 
-        InputSource source = null;
-        URL url = null;
+        URL url;
 
         try {
             url = new URL(baseURL, uri);
         } catch (MalformedURLException ex) {
-            // ignore
+            url = null;
         }
 
+        InputSource source = null;
         if (url != null) {
             try {
                 InputStream is = null;
@@ -789,10 +787,8 @@
      * the ExternalResolver strategy.
      */
     private interface CatalogResolver extends URIResolver, EntityResolver {
-
+        @Override
         InputSource resolveEntity(String publicId, String systemId);
-
-        Source resolve(String href, String base) throws TransformerException;
     }
 
     /**
@@ -809,6 +805,7 @@
                 Project.MSG_VERBOSE);
         }
 
+        @Override
         public InputSource resolveEntity(String publicId,
                                          String systemId) {
             InputSource result = null;
@@ -834,6 +831,7 @@
             return result;
         }
 
+        @Override
         public Source resolve(String href, String base)
             throws TransformerException {
 
@@ -922,21 +920,17 @@
             // in the classpath.
             //
             try {
-                setXMLCatalog =
-                    resolverImplClass.getMethod("setXMLCatalog",
-                                                new Class[] {XMLCatalog.class});
+                setXMLCatalog = resolverImplClass.getMethod("setXMLCatalog",
+                        XMLCatalog.class);
 
-                parseCatalog =
-                    resolverImplClass.getMethod("parseCatalog",
-                                                new Class[] {String.class});
+                parseCatalog = resolverImplClass.getMethod("parseCatalog",
+                        String.class);
 
-                resolveEntity =
-                    resolverImplClass.getMethod("resolveEntity",
-                                                new Class[] {String.class, String.class});
+                resolveEntity = resolverImplClass.getMethod("resolveEntity",
+                        String.class, String.class);
 
-                resolve =
-                    resolverImplClass.getMethod("resolve",
-                                                new Class[] {String.class, String.class});
+                resolve = resolverImplClass.getMethod("resolve",
+                        String.class, String.class);
             } catch (NoSuchMethodException ex) {
                 throw new BuildException(ex);
             }
@@ -945,14 +939,15 @@
                 Project.MSG_VERBOSE);
         }
 
+        @Override
         public InputSource resolveEntity(String publicId,
                                          String systemId) {
-            InputSource result = null;
 
             processExternalCatalogs();
 
             ResourceLocation matchingEntry = findMatchingEntry(publicId);
 
+            InputSource result;
             if (matchingEntry != null) {
 
                 log("Matching catalog entry found for publicId: '"
@@ -985,9 +980,8 @@
                 // this possibility.
                 //
                 try {
-                    result =
-                        (InputSource) resolveEntity.invoke(resolverImpl,
-                                                          new Object[] {publicId, systemId});
+                    result = (InputSource) resolveEntity.invoke(resolverImpl,
+                            new Object[] {publicId, systemId});
                 } catch (Exception ex) {
                     throw new BuildException(ex);
                 }
@@ -996,11 +990,12 @@
             return result;
         }
 
+        @Override
         public Source resolve(String href, String base)
             throws TransformerException {
 
-            SAXSource result = null;
-            InputSource source = null;
+            SAXSource result;
+            InputSource source;
 
             processExternalCatalogs();
 
@@ -1048,9 +1043,8 @@
                     result = new SAXSource(source);
                 } else {
                     try {
-                        result =
-                            (SAXSource) resolve.invoke(resolverImpl,
-                                                      new Object[] {href, base});
+                        result = (SAXSource) resolve.invoke(resolverImpl,
+                                new Object[] {href, base});
                     } catch (Exception ex) {
                         throw new BuildException(ex);
                     }
@@ -1072,9 +1066,8 @@
                     }
                 }
                 try {
-                    result =
-                        (SAXSource) resolve.invoke(resolverImpl,
-                                                  new Object[] {href, base});
+                    result = (SAXSource) resolve.invoke(resolverImpl,
+                            new Object[] {href, base});
                 } catch (Exception ex) {
                     throw new BuildException(ex);
                 }
@@ -1094,8 +1087,7 @@
             if (!externalCatalogsProcessed) {
 
                 try {
-                    setXMLCatalog.invoke(resolverImpl,
-                                         new Object[] {XMLCatalog.this});
+                    setXMLCatalog.invoke(resolverImpl, XMLCatalog.this);
                 } catch (Exception ex) {
                     throw new BuildException(ex);
                 }
@@ -1110,8 +1102,7 @@
                         File catFile = new File(catFileName);
                         log("Parsing " + catFile, Project.MSG_DEBUG);
                         try {
-                            parseCatalog.invoke(resolverImpl,
-                                    new Object[]{catFile.getPath()});
+                            parseCatalog.invoke(resolverImpl, catFile.getPath());
                         } catch (Exception ex) {
                             throw new BuildException(ex);
                         }
diff --git a/src/main/org/apache/tools/ant/types/ZipFileSet.java b/src/main/org/apache/tools/ant/types/ZipFileSet.java
index 24f0ccd..b49177f 100644
--- a/src/main/org/apache/tools/ant/types/ZipFileSet.java
+++ b/src/main/org/apache/tools/ant/types/ZipFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -58,6 +58,7 @@
      * Return a new archive scanner based on this one.
      * @return a new ZipScanner with the same encoding as this one.
      */
+    @Override
     protected ArchiveScanner newArchiveScanner() {
         ZipScanner zs = new ZipScanner();
         zs.setEncoding(getEncoding());
@@ -70,19 +71,30 @@
      * @param p the project to use
      * @return the abstract fileset instance
      */
+    @Override
     protected AbstractFileSet getRef(Project p) {
         dieOnCircularReference(p);
         Object o = getRefid().getReferencedObject(p);
         if (o instanceof ZipFileSet) {
             return (AbstractFileSet) o;
-        } else if (o instanceof FileSet) {
+        }
+        if (o instanceof FileSet) {
             ZipFileSet zfs = new ZipFileSet((FileSet) o);
             configureFileSet(zfs);
             return zfs;
-        } else {
-            String msg = getRefid().getRefId() + " doesn\'t denote a zipfileset or a fileset";
-            throw new BuildException(msg);
         }
+        String msg = getRefid().getRefId() + " doesn't denote a zipfileset or a fileset";
+        throw new BuildException(msg);
+    }
+
+    /**
+     * A ZipFileset accepts another ZipFileSet or a FileSet as reference
+     * FileSets are often used by the war task for the lib attribute
+     * @return the abstract fileset instance
+     */
+    @Override
+    protected AbstractFileSet getRef() {
+        return getRef(getProject());
     }
 
     /**
@@ -90,28 +102,12 @@
      * as this one.
      * @return the cloned zipFileSet
      */
+    @Override
     public Object clone() {
         if (isReference()) {
-            return ((ZipFileSet) getRef(getProject())).clone();
-        } else {
-            return super.clone();
+            return getRef().clone();
         }
-    }
-
-    /**
-     * A check attributes for zipFileSet.
-     * If there is a reference, and
-     * it is a ZipFileSet, the zip fileset attributes
-     * cannot be used.
-     */
-    private void checkZipFileSetAttributesAllowed() {
-        if (getProject() == null
-            || (isReference()
-                && (getRefid().getReferencedObject(
-                        getProject())
-                    instanceof ZipFileSet))) {
-            checkAttributesAllowed();
-        }
+        return super.clone();
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/ZipScanner.java b/src/main/org/apache/tools/ant/types/ZipScanner.java
index 0539222..317c4e2 100644
--- a/src/main/org/apache/tools/ant/types/ZipScanner.java
+++ b/src/main/org/apache/tools/ant/types/ZipScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,14 +20,13 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
 import java.util.Map;
 import java.util.zip.ZipException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.resources.FileProvider;
 import org.apache.tools.ant.types.resources.ZipResource;
-import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.ant.util.StreamUtils;
 import org.apache.tools.zip.ZipFile;
 
 /**
@@ -52,31 +51,17 @@
      * resources found inside the archive that matched all include
      * patterns and didn't match any exclude patterns.
      */
+    @Override
     protected void fillMapsFromArchive(Resource src, String encoding,
             Map<String, Resource> fileEntries, Map<String, Resource> matchFileEntries,
             Map<String, Resource> dirEntries, Map<String, Resource> matchDirEntries) {
-        ZipEntry entry = null;
-        ZipFile zf = null;
 
-        File srcFile = null;
-        FileProvider fp = src.as(FileProvider.class);
-        if (fp != null) {
-            srcFile = fp.getFile();
-        } else {
-            throw new BuildException("Only file provider resources are supported");
-        }
+        File srcFile = src.asOptional(FileProvider.class)
+            .map(FileProvider::getFile).orElseThrow(() -> new BuildException(
+                "Only file provider resources are supported"));
 
-        try {
-            try {
-                zf = new ZipFile(srcFile, encoding);
-            } catch (ZipException ex) {
-                throw new BuildException("Problem reading " + srcFile, ex);
-            } catch (IOException ex) {
-                throw new BuildException("Problem opening " + srcFile, ex);
-            }
-            Enumeration<ZipEntry> e = zf.getEntries();
-            while (e.hasMoreElements()) {
-                entry = e.nextElement();
+        try (ZipFile zf = new ZipFile(srcFile, encoding)) {
+            StreamUtils.enumerationAsStream(zf.getEntries()).forEach(entry -> {
                 Resource r = new ZipResource(srcFile, encoding, entry);
                 String name = entry.getName();
                 if (entry.isDirectory()) {
@@ -91,9 +76,11 @@
                         matchFileEntries.put(name, r);
                     }
                 }
-            }
-        } finally {
-            ZipFile.closeQuietly(zf);
+            });
+        } catch (ZipException ex) {
+            throw new BuildException("Problem reading " + srcFile, ex);
+        } catch (IOException ex) {
+            throw new BuildException("Problem opening " + srcFile, ex);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/org/apache/tools/ant/types/conditions/antlib.xml b/src/main/org/apache/tools/ant/types/conditions/antlib.xml
index 5643a2e..6a64582 100644
--- a/src/main/org/apache/tools/ant/types/conditions/antlib.xml
+++ b/src/main/org/apache/tools/ant/types/conditions/antlib.xml
@@ -9,7 +9,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/defaults.properties b/src/main/org/apache/tools/ant/types/defaults.properties
index 29771db..f93bf18 100644
--- a/src/main/org/apache/tools/ant/types/defaults.properties
+++ b/src/main/org/apache/tools/ant/types/defaults.properties
@@ -5,7 +5,7 @@
 # (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
+#     https://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,
@@ -30,7 +30,6 @@
 scriptfilter=org.apache.tools.ant.types.optional.ScriptFilter
 assertions=org.apache.tools.ant.types.Assertions
 concatfilter=org.apache.tools.ant.filters.ConcatFilter
-mavenrepository=org.apache.tools.ant.taskdefs.repository.MavenRepository
 scriptselector=org.apache.tools.ant.types.optional.ScriptSelector
 scriptmapper=org.apache.tools.ant.types.optional.ScriptMapper
 
@@ -94,6 +93,7 @@
 javaresource=org.apache.tools.ant.types.resources.JavaResource
 multirootfileset=org.apache.tools.ant.types.resources.MultiRootFileSet
 javaconstant=org.apache.tools.ant.types.resources.JavaConstantResource
+xzresource=org.apache.tools.ant.types.optional.xz.XzResource
 
 #tokenizer implementations
 linetokenizer=org.apache.tools.ant.util.LineTokenizer
diff --git a/src/main/org/apache/tools/ant/types/mappers/CutDirsMapper.java b/src/main/org/apache/tools/ant/types/mappers/CutDirsMapper.java
index 932f3ec..5ce22f4 100644
--- a/src/main/org/apache/tools/ant/types/mappers/CutDirsMapper.java
+++ b/src/main/org/apache/tools/ant/types/mappers/CutDirsMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,7 +29,7 @@
  * <p>This mapper was inspired by a user-list thread that mentioned
  * wget's --cut-dirs option.</p>
  *
- * @see <a href="http://mail-archives.apache.org/mod_mbox/ant-user/201009.mbox/%3C51772743BEA5D44A9EA5BF52AADDD6FB010E96F6@hammai008.delphi.local%3E">
+ * @see <a href="https://mail-archives.apache.org/mod_mbox/ant-user/201009.mbox/%3C51772743BEA5D44A9EA5BF52AADDD6FB010E96F6@hammai008.delphi.local%3E">
  * simplify copy with regexpmapper</a>
  */
 public class CutDirsMapper implements FileNameMapper {
@@ -47,6 +47,7 @@
      * Empty implementation.
      * @param ignore ignored.
      */
+    @Override
     public void setFrom(final String ignore) {
     }
 
@@ -54,10 +55,12 @@
      * Empty implementation.
      * @param ignore ignored.
      */
+    @Override
     public void setTo(final String ignore) {
     }
 
     /** {@inheritDoc}. */
+    @Override
     public String[] mapFileName(final String sourceFileName) {
         if (dirs <= 0) {
             throw new BuildException("dirs must be set to a positive number");
diff --git a/src/main/org/apache/tools/ant/types/mappers/FilterMapper.java b/src/main/org/apache/tools/ant/types/mappers/FilterMapper.java
index 9ef922e..7a1faa7 100644
--- a/src/main/org/apache/tools/ant/types/mappers/FilterMapper.java
+++ b/src/main/org/apache/tools/ant/types/mappers/FilterMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,6 +41,7 @@
      * @param from a string
      * @throws BuildException always
      */
+    @Override
     public void setFrom(String from) {
         throw new UnsupportedAttributeException(
             "filtermapper doesn't support the \"from\" attribute.", "from");
@@ -51,6 +52,7 @@
      * @param to a string
      * @throws BuildException always
      */
+    @Override
     public void setTo(String to) {
         throw new UnsupportedAttributeException(
             "filtermapper doesn't support the \"to\" attribute.", "to");
@@ -62,6 +64,7 @@
      * @return  a one-element array of converted filenames, or null if
      *          the filterchain returns an empty string.
      */
+    @Override
     public String[] mapFileName(String sourceFileName) {
         if (sourceFileName == null) {
             return null;
@@ -72,15 +75,14 @@
             helper.setBufferSize(BUFFER_SIZE);
             helper.setPrimaryReader(stringReader);
             helper.setProject(getProject());
-            Vector<FilterChain> filterChains = new Vector<FilterChain>();
+            Vector<FilterChain> filterChains = new Vector<>();
             filterChains.add(this);
             helper.setFilterChains(filterChains);
             String result = FileUtils.safeReadFully(helper.getAssembledReader());
-            if (result.length() == 0) {
+            if (result.isEmpty()) {
                 return null;
-            } else {
-                return new String[] {result};
             }
+            return new String[] {result};
         } catch (BuildException ex) {
             throw ex;
         } catch (Exception ex) {
diff --git a/src/main/org/apache/tools/ant/types/optional/AbstractScriptComponent.java b/src/main/org/apache/tools/ant/types/optional/AbstractScriptComponent.java
index 2028075..bbdaa01 100644
--- a/src/main/org/apache/tools/ant/types/optional/AbstractScriptComponent.java
+++ b/src/main/org/apache/tools/ant/types/optional/AbstractScriptComponent.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.util.ScriptManager;
 import org.apache.tools.ant.util.ScriptRunnerBase;
 import org.apache.tools.ant.util.ScriptRunnerHelper;
 
@@ -45,6 +46,7 @@
      * Set the project.
      * @param project the owner of this component.
      */
+    @Override
     public void setProject(Project project) {
         super.setProject(project);
         helper.setProjectComponent(this);
@@ -82,11 +84,20 @@
      *
      * @param manager the scripting manager.
      */
+    @Deprecated
     public void setManager(String manager) {
         helper.setManager(manager);
     }
 
     /**
+     * Set the script manager.
+     * @param manager
+     */
+    public void setManager(ScriptManager manager) {
+        helper.setManager(manager);
+    }
+
+    /**
      * Defines the language (required).
      *
      * @param language the scripting language name for the script.
@@ -155,4 +166,14 @@
     public void setSetBeans(boolean setBeans) {
         helper.setSetBeans(setBeans);
     }
+
+    /**
+     * Set the encoding of the script from an external file; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public void setEncoding(String encoding) {
+        helper.setEncoding(encoding);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/ScriptCondition.java b/src/main/org/apache/tools/ant/types/optional/ScriptCondition.java
index ee432b1..51972f7 100644
--- a/src/main/org/apache/tools/ant/types/optional/ScriptCondition.java
+++ b/src/main/org/apache/tools/ant/types/optional/ScriptCondition.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,10 +41,11 @@
      * @throws BuildException
      *          if an error occurs
      */
+    @Override
     public boolean eval() throws BuildException {
         initScriptRunner();
-        executeScript("ant_condition");
-        return getValue();
+        final Object result = getRunner().evaluateScript("ant_condition");
+        return result instanceof Boolean ? Boolean.TRUE.equals(result) : getValue();
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java b/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java
index 67d3cce..9e7455c 100644
--- a/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java
+++ b/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,6 +25,7 @@
 import org.apache.tools.ant.filters.TokenFilter;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.util.ScriptManager;
 import org.apache.tools.ant.util.ScriptRunnerBase;
 import org.apache.tools.ant.util.ScriptRunnerHelper;
 
@@ -53,6 +54,7 @@
      * Set the project.
      * @param project the owner of this component.
      */
+    @Override
     public void setProject(Project project) {
         super.setProject(project);
         helper.setProjectComponent(this);
@@ -105,6 +107,7 @@
      * @param token the token to be filtered
      * @return the filtered token
      */
+    @Override
     public String filter(String token) {
         init();
         setToken(token);
@@ -135,9 +138,19 @@
      *
      * @param manager the scripting manager.
      */
+    @Deprecated
     public void setManager(String manager) {
         helper.setManager(manager);
     }
+
+    /**
+     * Set the script manager.
+     * @param manager
+     */
+    public void setManager(ScriptManager manager) {
+        helper.setManager(manager);
+    }
+
     /**
      * Set the classpath to be used when searching for classes and resources.
      *
@@ -180,4 +193,14 @@
     public void setSetBeans(boolean setBeans) {
         helper.setSetBeans(setBeans);
     }
+
+    /**
+     * Set the encoding of the script from an external file; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public void setEncoding(String encoding) {
+        helper.setEncoding(encoding);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/ScriptMapper.java b/src/main/org/apache/tools/ant/types/optional/ScriptMapper.java
index 36347a7..92497b3 100644
--- a/src/main/org/apache/tools/ant/types/optional/ScriptMapper.java
+++ b/src/main/org/apache/tools/ant/types/optional/ScriptMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,8 +35,8 @@
      *
      * @param from a string.
      */
+    @Override
     public void setFrom(String from) {
-
     }
 
     /**
@@ -44,15 +44,15 @@
      *
      * @param to a string.
      */
+    @Override
     public void setTo(String to) {
-
     }
 
     /**
      * Reset the list of files
      */
     public void clear() {
-        files = new ArrayList<String>(1);
+        files = new ArrayList<>(1);
     }
 
     /**
@@ -77,15 +77,15 @@
      *         null if it does not.
      */
 
+    @Override
     public String[] mapFileName(String sourceFileName) {
         initScriptRunner();
         getRunner().addBean("source", sourceFileName);
         clear();
         executeScript("ant_mapper");
-        if (files.size() == 0) {
+        if (files.isEmpty()) {
             return null;
-        } else {
-            return files.toArray(new String[files.size()]);
         }
+        return files.toArray(new String[0]);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/ScriptSelector.java b/src/main/org/apache/tools/ant/types/optional/ScriptSelector.java
index 45e8784..dfc393a 100644
--- a/src/main/org/apache/tools/ant/types/optional/ScriptSelector.java
+++ b/src/main/org/apache/tools/ant/types/optional/ScriptSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,6 +24,7 @@
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 import org.apache.tools.ant.types.selectors.BaseSelector;
+import org.apache.tools.ant.util.ScriptManager;
 import org.apache.tools.ant.util.ScriptRunnerBase;
 import org.apache.tools.ant.util.ScriptRunnerHelper;
 
@@ -59,6 +60,7 @@
      * Set the project.
      * @param project the owner of this component.
      */
+    @Override
     public void setProject(Project project) {
         super.setProject(project);
         helper.setProjectComponent(this);
@@ -69,11 +71,20 @@
      *
      * @param manager the scripting manager.
      */
+    @Deprecated
     public void setManager(String manager) {
         helper.setManager(manager);
     }
 
     /**
+     * Set the script manager.
+     * @param manager
+     */
+    public void setManager(ScriptManager manager) {
+        helper.setManager(manager);
+    }
+
+    /**
      * Defines the language (required).
      *
      * @param language the scripting language name for the script.
@@ -166,6 +177,7 @@
      *
      * @return whether the file should be selected or not
      */
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
         init();
         setSelected(true);
@@ -220,4 +232,13 @@
         this.selected = selected;
     }
 
+    /**
+     * Set the encoding of the script from an external file; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public void setEncoding(String encoding) {
+        helper.setEncoding(encoding);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java b/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java
index 7fc8d3d..dc6d814 100644
--- a/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java
+++ b/src/main/org/apache/tools/ant/types/optional/depend/ClassfileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,12 +41,12 @@
      * classes which must be included in the fileset and which are the
      * starting point for the dependency search.
      */
-    private List<String> rootClasses = new ArrayList<String>();
+    private List<String> rootClasses = new ArrayList<>();
 
     /**
      * The list of filesets which contain root classes.
      */
-    private List<FileSet> rootFileSets = new ArrayList<FileSet>();
+    private List<FileSet> rootFileSets = new ArrayList<>();
 
     /**
      * Inner class used to contain info about root classes.
@@ -81,6 +81,16 @@
     }
 
     /**
+     * Create a ClassfileSet from another ClassfileSet.
+     *
+     * @param s the other classfileset.
+     */
+    protected ClassfileSet(ClassfileSet s) {
+        super(s);
+        rootClasses.addAll(s.rootClasses);
+    }
+
+    /**
      * Add a fileset to which contains a collection of root classes used to
      * drive the search from classes.
      *
@@ -93,16 +103,6 @@
     }
 
     /**
-     * Create a ClassfileSet from another ClassfileSet.
-     *
-     * @param s the other classfileset.
-     */
-    protected ClassfileSet(ClassfileSet s) {
-        super(s);
-        rootClasses.addAll(s.rootClasses);
-    }
-
-    /**
      * Set the root class attribute.
      *
      * @param rootClass the name of the root class.
@@ -118,6 +118,7 @@
      *
      * @return a dependency scanner.
      */
+    @Override
     public DirectoryScanner getDirectoryScanner(Project p) {
         if (isReference()) {
             return getRef(p).getDirectoryScanner(p);
@@ -125,7 +126,7 @@
         dieOnCircularReference(p);
         DirectoryScanner parentScanner = super.getDirectoryScanner(p);
         DependScanner scanner = new DependScanner(parentScanner);
-        final Vector<String> allRootClasses = new Vector<String>(rootClasses);
+        final Vector<String> allRootClasses = new Vector<>(rootClasses);
         for (FileSet additionalRootSet : rootFileSets) {
             DirectoryScanner additionalScanner
                 = additionalRootSet.getDirectoryScanner(p);
@@ -159,11 +160,12 @@
      *
      * @return a clone of the class file set.
      */
+    @Override
     public Object clone() {
-        return new ClassfileSet(isReference()
-            ? (ClassfileSet) (getRef(getProject())) : this);
+        return new ClassfileSet(isReference() ? getRef() : this);
     }
 
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p) {
         if (isChecked()) {
             return;
@@ -179,4 +181,8 @@
             setChecked(true);
         }
     }
+
+    private ClassfileSet getRef() {
+        return getCheckedRef(ClassfileSet.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/depend/DependScanner.java b/src/main/org/apache/tools/ant/types/optional/depend/DependScanner.java
index 27a1fdd..1977daf 100644
--- a/src/main/org/apache/tools/ant/types/optional/depend/DependScanner.java
+++ b/src/main/org/apache/tools/ant/types/optional/depend/DependScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,16 +18,17 @@
 package org.apache.tools.ant.types.optional.depend;
 
 import java.io.File;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.Set;
 import java.util.Vector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.StreamUtils;
 import org.apache.tools.ant.util.depend.DependencyAnalyzer;
 
-
 /**
  * DirectoryScanner for finding class dependencies.
  */
@@ -48,7 +49,7 @@
      */
     private Vector<String> included;
 
-    private Vector<File> additionalBaseDirs = new Vector<File>();
+    private Vector<File> additionalBaseDirs = new Vector<>();
 
     /**
      * The parent scanner which gives the basic set of files. Only files which
@@ -82,15 +83,13 @@
      *
      * @return the names of the files.
      */
+    @Override
     public String[] getIncludedFiles() {
-        String[] files = new String[getIncludedFilesCount()];
-        for (int i = 0; i < files.length; i++) {
-            files[i] = (String) included.elementAt(i);
-        }
-        return files;
+        return included.toArray(new String[getIncludedFilesCount()]);
     }
 
     /** {@inheritDoc}. */
+    @Override
     public synchronized int getIncludedFilesCount() {
         if (included == null) {
             throw new IllegalStateException();
@@ -103,12 +102,14 @@
      *
      * @exception IllegalStateException when basedir was set incorrectly.
      */
+    @Override
     public synchronized void scan() throws IllegalStateException {
-        included = new Vector<String>();
+        included = new Vector<>();
         String analyzerClassName = DEFAULT_ANALYZER_CLASS;
-        DependencyAnalyzer analyzer = null;
+        DependencyAnalyzer analyzer;
         try {
-            Class<? extends DependencyAnalyzer> analyzerClass = Class.forName(analyzerClassName)
+            Class<? extends DependencyAnalyzer> analyzerClass =
+                Class.forName(analyzerClassName)
                     .asSubclass(DependencyAnalyzer.class);
             analyzer = analyzerClass.newInstance();
         } catch (Exception e) {
@@ -116,37 +117,25 @@
                                      + analyzerClassName, e);
         }
         analyzer.addClassPath(new Path(null, basedir.getPath()));
-        for (Enumeration<File> e = additionalBaseDirs.elements(); e.hasMoreElements();) {
-            File additionalBaseDir = e.nextElement();
-            analyzer.addClassPath(new Path(null, additionalBaseDir.getPath()));
-        }
+        additionalBaseDirs.stream().map(File::getPath)
+            .map(p -> new Path(null, p)).forEach(analyzer::addClassPath);
 
-        for (Enumeration<String> e = rootClasses.elements(); e.hasMoreElements();) {
-            String rootClass = e.nextElement();
-            analyzer.addRootClass(rootClass);
-        }
-        Enumeration<String> e = analyzer.getClassDependencies();
+        rootClasses.forEach(analyzer::addRootClass);
 
-        String[] parentFiles = parentScanner.getIncludedFiles();
-        Hashtable<String, String> parentSet = new Hashtable<String, String>();
-        for (int i = 0; i < parentFiles.length; ++i) {
-            parentSet.put(parentFiles[i], parentFiles[i]);
-        }
-        while (e.hasMoreElements()) {
-            String classname = (String) e.nextElement();
-            String filename = classname.replace('.', File.separatorChar);
-            filename = filename + ".class";
-            File depFile = new File(basedir, filename);
-            if (depFile.exists() && parentSet.containsKey(filename)) {
-                // This is included
-                included.addElement(filename);
-            }
-        }
+        Set<String> parentSet = Stream.of(parentScanner.getIncludedFiles())
+            .collect(Collectors.toSet());
+
+        // This is included
+        StreamUtils.enumerationAsStream(analyzer.getClassDependencies())
+                .map(cName -> cName.replace('.', File.separatorChar) + ".class")
+                .filter(fName -> new File(basedir, fName).exists() && parentSet.contains(fName))
+                .forEach(fName -> included.addElement(fName));
     }
 
     /**
      * @see DirectoryScanner#addDefaultExcludes
      */
+    @Override
     public void addDefaultExcludes() {
     }
 
@@ -154,6 +143,7 @@
      * @see DirectoryScanner#getExcludedDirectories
      * {@inheritDoc}.
      */
+    @Override
     public String[] getExcludedDirectories() {
         return null;
     }
@@ -162,6 +152,7 @@
      * @see DirectoryScanner#getExcludedFiles
      * {@inheritDoc}.
      */
+    @Override
     public String[] getExcludedFiles() {
         return null;
     }
@@ -170,6 +161,7 @@
      * @see DirectoryScanner#getIncludedDirectories
      * {@inheritDoc}.
      */
+    @Override
     public String[] getIncludedDirectories() {
         return new String[0];
     }
@@ -178,6 +170,7 @@
      * @see DirectoryScanner#getIncludedDirsCount
      * {@inheritDoc}.
      */
+    @Override
     public int getIncludedDirsCount() {
         return 0;
     }
@@ -186,6 +179,7 @@
      * @see DirectoryScanner#getNotIncludedDirectories
      * {@inheritDoc}.
      */
+    @Override
     public String[] getNotIncludedDirectories() {
         return null;
     }
@@ -194,7 +188,7 @@
      * @see DirectoryScanner#getNotIncludedFiles
      * {@inheritDoc}.
      */
-    /** {@inheritDoc}. */
+    @Override
     public String[] getNotIncludedFiles() {
         return null;
     }
@@ -203,7 +197,7 @@
      * @see DirectoryScanner#setExcludes
      * {@inheritDoc}.
      */
-    /** {@inheritDoc}. */
+    @Override
     public void setExcludes(String[] excludes) {
     }
 
@@ -211,7 +205,7 @@
      * @see DirectoryScanner#setIncludes
      * {@inheritDoc}.
      */
-    /** {@inheritDoc}. */
+    @Override
     public void setIncludes(String[] includes) {
     }
 
@@ -219,7 +213,7 @@
      * @see DirectoryScanner#setCaseSensitive
      * {@inheritDoc}.
      */
-    /** {@inheritDoc}. */
+    @Override
     public void setCaseSensitive(boolean isCaseSensitive) {
     }
 
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Arc.java b/src/main/org/apache/tools/ant/types/optional/image/Arc.java
index ce29bfd..443a9fb 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Arc.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Arc.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -74,23 +74,24 @@
      * @todo refactor using an EnumeratedAttribute
      */
     public void setType(String strType) {
-        if (strType.equalsIgnoreCase("open")) {
+        if ("open".equalsIgnoreCase(strType)) {
             type = Arc2D.OPEN;
-        } else if (strType.equalsIgnoreCase("pie")) {
+        } else if ("pie".equalsIgnoreCase(strType)) {
             type = Arc2D.PIE;
-        } else if (strType.equalsIgnoreCase("chord")) {
+        } else if ("chord".equalsIgnoreCase(strType)) {
             type = Arc2D.CHORD;
         }
     }
 
     /** {@inheritDoc}. */
+    @Override
     public PlanarImage executeDrawOperation() {
         BufferedImage bi = new BufferedImage(width + (stroke_width * 2),
             height + (stroke_width * 2), BufferedImage.TYPE_4BYTE_ABGR_PRE);
 
-        Graphics2D graphics = (Graphics2D) bi.getGraphics();
+        Graphics2D graphics = bi.createGraphics();
 
-        if (!stroke.equals("transparent")) {
+        if (!"transparent".equalsIgnoreCase(stroke)) {
             BasicStroke bStroke = new BasicStroke(stroke_width);
             graphics.setColor(ColorMapper.getColorByName(stroke));
             graphics.setStroke(bStroke);
@@ -98,16 +99,13 @@
                 height, start, stop, type));
         }
 
-        if (!fill.equals("transparent")) {
+        if (!"transparent".equalsIgnoreCase(fill)) {
             graphics.setColor(ColorMapper.getColorByName(fill));
             graphics.fill(new Arc2D.Double(stroke_width, stroke_width,
                 width, height, start, stop, type));
         }
 
-
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 PlanarImage img = ((DrawOperation) instr).executeDrawOperation();
                 graphics.drawImage(img.getAsBufferedImage(), null, 0, 0);
@@ -115,7 +113,7 @@
                 PlanarImage image = ((TransformOperation) instr)
                     .executeTransformOperation(PlanarImage.wrapRenderedImage(bi));
                 bi = image.getAsBufferedImage();
-                graphics = (Graphics2D) bi.getGraphics();
+                graphics = bi.createGraphics();
             }
         }
         return PlanarImage.wrapRenderedImage(bi);
diff --git a/src/main/org/apache/tools/ant/types/optional/image/BasicShape.java b/src/main/org/apache/tools/ant/types/optional/image/BasicShape.java
index ee2113a..516f7e4 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/BasicShape.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/BasicShape.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/optional/image/ColorMapper.java b/src/main/org/apache/tools/ant/types/optional/image/ColorMapper.java
index 88e2871..d1351f4 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/ColorMapper.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/ColorMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,13 @@
 package org.apache.tools.ant.types.optional.image;
 
 import java.awt.Color;
+import java.util.Locale;
 
 /**
  *
  * @see org.apache.tools.ant.taskdefs.optional.image.Image
  */
 public final class ColorMapper {
-    /** private constructor for Utility class */
-    private ColorMapper() {
-    }
 
     /** black string */
     public static final String COLOR_BLACK = "black";
@@ -69,34 +67,42 @@
      * @todo refactor to use an EnumeratedAttribute (maybe?)
      */
     public static Color getColorByName(String colorName) {
-        if (colorName.equalsIgnoreCase(COLOR_BLACK)) {
-            return Color.black;
-        } else if (colorName.equalsIgnoreCase(COLOR_BLUE)) {
+        switch (colorName.toLowerCase(Locale.ENGLISH)) {
+        case COLOR_BLUE:
             return Color.blue;
-        } else if (colorName.equalsIgnoreCase(COLOR_CYAN)) {
+        case COLOR_CYAN:
             return Color.cyan;
-        } else if (colorName.equalsIgnoreCase(COLOR_DARKGRAY) || colorName.equalsIgnoreCase(COLOR_DARKGREY)) {
+        case COLOR_DARKGRAY:
+        case COLOR_DARKGREY:
             return Color.darkGray;
-        } else if (colorName.equalsIgnoreCase(COLOR_GRAY) || colorName.equalsIgnoreCase(COLOR_GREY)) {
+        case COLOR_GRAY:
+        case COLOR_GREY:
             return Color.gray;
-        } else if (colorName.equalsIgnoreCase(COLOR_LIGHTGRAY) || colorName.equalsIgnoreCase(COLOR_LIGHTGREY)) {
+        case COLOR_LIGHTGRAY:
+        case COLOR_LIGHTGREY:
             return Color.lightGray;
-        } else if (colorName.equalsIgnoreCase(COLOR_GREEN)) {
+        case COLOR_GREEN:
             return Color.green;
-        } else if (colorName.equalsIgnoreCase(COLOR_MAGENTA)) {
+        case COLOR_MAGENTA:
             return Color.magenta;
-        } else if (colorName.equalsIgnoreCase(COLOR_ORANGE)) {
+        case COLOR_ORANGE:
             return Color.orange;
-        } else if (colorName.equalsIgnoreCase(COLOR_PINK)) {
+        case COLOR_PINK:
             return Color.pink;
-        } else if (colorName.equalsIgnoreCase(COLOR_RED)) {
+        case COLOR_RED:
             return Color.red;
-        } else if (colorName.equalsIgnoreCase(COLOR_WHITE)) {
+        case COLOR_WHITE:
             return Color.white;
-        } else if (colorName.equalsIgnoreCase(COLOR_YELLOW)) {
+        case COLOR_YELLOW:
             return Color.yellow;
+        case COLOR_BLACK:
+        default:
+            return Color.black;
         }
-        return Color.black;
+    }
+
+    /** private constructor for Utility class */
+    private ColorMapper() {
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Draw.java b/src/main/org/apache/tools/ant/types/optional/image/Draw.java
index 2f097d5..3ffbea9 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Draw.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Draw.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -49,11 +49,13 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void addRectangle(Rectangle rect) {
         instructions.add(rect);
     }
 
     /** {@inheritDoc}. */
+    @Override
     public void addText(Text text) {
         instructions.add(text);
     }
@@ -75,13 +77,12 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public PlanarImage executeTransformOperation(PlanarImage image) {
         BufferedImage bi = image.getAsBufferedImage();
-        Graphics2D graphics = (Graphics2D) bi.getGraphics();
+        Graphics2D graphics = bi.createGraphics();
 
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 PlanarImage op = ((DrawOperation) instr).executeDrawOperation();
                 log("\tDrawing to x=" + xloc + " y=" + yloc);
@@ -92,11 +93,8 @@
                 BufferedImage child = op.getAsBufferedImage();
                 log("\tDrawing to x=" + xloc + " y=" + yloc);
                 graphics.drawImage(child, null, xloc, yloc);
-                PlanarImage.wrapRenderedImage(bi);
             }
         }
-        image = PlanarImage.wrapRenderedImage(bi);
-
-        return image;
+        return PlanarImage.wrapRenderedImage(bi);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/optional/image/DrawOperation.java b/src/main/org/apache/tools/ant/types/optional/image/DrawOperation.java
index e02d0c8..0e34f13 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/DrawOperation.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/DrawOperation.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Ellipse.java b/src/main/org/apache/tools/ant/types/optional/image/Ellipse.java
index 635d809..459d362 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Ellipse.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Ellipse.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -51,27 +51,25 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public PlanarImage executeDrawOperation() {
         BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
 
-        Graphics2D graphics = (Graphics2D) bi.getGraphics();
+        Graphics2D graphics = bi.createGraphics();
 
-        if (!stroke.equals("transparent")) {
+        if (!"transparent".equalsIgnoreCase(stroke)) {
             BasicStroke bStroke = new BasicStroke(stroke_width);
             graphics.setColor(ColorMapper.getColorByName(stroke));
             graphics.setStroke(bStroke);
             graphics.draw(new Ellipse2D.Double(0, 0, width, height));
         }
 
-        if (!fill.equals("transparent")) {
+        if (!"transparent".equalsIgnoreCase(fill)) {
             graphics.setColor(ColorMapper.getColorByName(fill));
             graphics.fill(new Ellipse2D.Double(0, 0, width, height));
         }
 
-
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 PlanarImage img = ((DrawOperation) instr).executeDrawOperation();
                 graphics.drawImage(img.getAsBufferedImage(), null, 0, 0);
@@ -79,7 +77,7 @@
                 PlanarImage image = ((TransformOperation) instr)
                     .executeTransformOperation(PlanarImage.wrapRenderedImage(bi));
                 bi = image.getAsBufferedImage();
-                graphics = (Graphics2D) bi.getGraphics();
+                graphics = bi.createGraphics();
             }
         }
         return PlanarImage.wrapRenderedImage(bi);
diff --git a/src/main/org/apache/tools/ant/types/optional/image/ImageOperation.java b/src/main/org/apache/tools/ant/types/optional/image/ImageOperation.java
index d72fe04..d1ac79a 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/ImageOperation.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/ImageOperation.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,7 +27,7 @@
  */
 public abstract class ImageOperation extends DataType {
      // CheckStyle:VisibilityModifier OFF - bc
-    protected Vector<ImageOperation> instructions = new Vector<ImageOperation>();
+    protected Vector<ImageOperation> instructions = new Vector<>();
      // CheckStyle:VisibilityModifier ON
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Rectangle.java b/src/main/org/apache/tools/ant/types/optional/image/Rectangle.java
index 836b6ca..7ed4d0e 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Rectangle.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Rectangle.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -68,41 +68,39 @@
     }
 
     /** {@inheritDoc}. */
+    @Override
     public PlanarImage executeDrawOperation() {
         log("\tCreating Rectangle w=" + width + " h=" + height + " arcw="
             + arcwidth + " arch=" + archeight);
         BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
 
-        Graphics2D graphics = (Graphics2D) bi.getGraphics();
+        Graphics2D graphics = bi.createGraphics();
 
-        if (!stroke.equals("transparent")) {
+        if (!"transparent".equalsIgnoreCase(stroke)) {
             BasicStroke bStroke = new BasicStroke(stroke_width);
             graphics.setColor(ColorMapper.getColorByName(stroke));
             graphics.setStroke(bStroke);
 
-            if ((arcwidth != 0) || (archeight != 0)) {
-                graphics.drawRoundRect(0, 0, width, height, arcwidth, archeight);
-            } else {
+            if (arcwidth == 0 && archeight == 0) {
                 graphics.drawRect(0, 0, width, height);
+            } else {
+                graphics.drawRoundRect(0, 0, width, height, arcwidth, archeight);
             }
         }
 
-        if (!fill.equals("transparent")) {
+        if (!"transparent".equalsIgnoreCase(fill)) {
             graphics.setColor(ColorMapper.getColorByName(fill));
-            if ((arcwidth != 0) || (archeight != 0)) {
+            if (arcwidth == 0 && archeight == 0) {
+                graphics.fillRect(stroke_width, stroke_width,
+                    width - (stroke_width * 2), height - (stroke_width * 2));
+            } else {
                 graphics.fillRoundRect(stroke_width, stroke_width,
                     width - (stroke_width * 2), height - (stroke_width * 2),
                     arcwidth, archeight);
-            } else {
-                graphics.fillRect(stroke_width, stroke_width,
-                    width - (stroke_width * 2), height - (stroke_width * 2));
             }
         }
 
-
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 PlanarImage img = ((DrawOperation) instr).executeDrawOperation();
                 graphics.drawImage(img.getAsBufferedImage(), null, 0, 0);
@@ -111,7 +109,7 @@
                     = ((TransformOperation) instr)
                     .executeTransformOperation(PlanarImage.wrapRenderedImage(bi));
                 bi = image.getAsBufferedImage();
-                graphics = (Graphics2D) bi.getGraphics();
+                graphics = bi.createGraphics();
             }
         }
         return PlanarImage.wrapRenderedImage(bi);
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Rotate.java b/src/main/org/apache/tools/ant/types/optional/image/Rotate.java
index 3d7a03a..d0090f1 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Rotate.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Rotate.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -67,24 +67,21 @@
      * @param image The image to perform the transformation on.
      * @return the transformed image.
      */
+    @Override
     public PlanarImage executeTransformOperation(PlanarImage image) {
-        BufferedImage bi = null;
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 // If this TransformOperation has DrawOperation children
                 // then Rotate the first child and return.
                 System.out.println("Exec'ing Draws");
                 PlanarImage op = ((DrawOperation) instr).executeDrawOperation();
-                image = performRotate(op);
-                return image;
-            } else if (instr instanceof TransformOperation) {
-                bi = image.getAsBufferedImage();
+                return performRotate(op);
+            }
+            if (instr instanceof TransformOperation) {
+                BufferedImage bi = image.getAsBufferedImage();
                 System.out.println("Exec'ing Transforms");
                 image = ((TransformOperation) instr)
                     .executeTransformOperation(PlanarImage.wrapRenderedImage(bi));
-                bi = image.getAsBufferedImage();
             }
         }
         System.out.println("Exec'ing as TransformOperation");
@@ -100,16 +97,14 @@
      *  ONE image.
      * @return the image.
      */
+    @Override
     public PlanarImage executeDrawOperation() {
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 // If this TransformOperation has DrawOperation children
                 // then Rotate the first child and return.
                 PlanarImage op = ((DrawOperation) instr).executeDrawOperation();
-                op = performRotate(op);
-                return op;
+                return performRotate(op);
             }
         }
         return null;
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Scale.java b/src/main/org/apache/tools/ant/types/optional/image/Scale.java
index 532694d..c5ffd36 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Scale.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Scale.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,8 +41,9 @@
     /** Enumerated class for proportions attribute. */
     public static class ProportionsAttribute extends EnumeratedAttribute {
         /** {@inheritDoc}. */
+        @Override
         public String[] getValues() {
-            return new String[] {"ignore", "width", "height", "cover", "fit"};
+            return new String[] { "ignore", "width", "height", "cover", "fit" };
         }
     }
 
@@ -76,16 +77,14 @@
      * @return the value converted from the width string.
      */
     public float getWidth() {
-        float width = 0.0F;
         int percIndex = widthStr.indexOf('%');
         if (percIndex > 0) {
-            width = Float.parseFloat(widthStr.substring(0, percIndex));
             xPercent = true;
+            float width = Float.parseFloat(widthStr.substring(0, percIndex));
             return width / HUNDRED;
-        } else {
-            xPercent = false;
-            return Float.parseFloat(widthStr);
         }
+        xPercent = false;
+        return Float.parseFloat(widthStr);
     }
 
     /**
@@ -95,13 +94,11 @@
     public float getHeight() {
         int percIndex = heightStr.indexOf('%');
         if (percIndex > 0) {
-            float height = Float.parseFloat(heightStr.substring(0, percIndex));
             yPercent = true;
-            return height / HUNDRED;
-        } else {
-            yPercent = false;
-            return Float.parseFloat(heightStr);
+            return Float.parseFloat(heightStr.substring(0, percIndex)) / HUNDRED;
         }
+        yPercent = false;
+        return Float.parseFloat(heightStr);
     }
 
     /**
@@ -116,10 +113,10 @@
         float yFl = getHeight();
 
         if (!xPercent) {
-            xFl = (xFl / image.getWidth());
+            xFl /= image.getWidth();
         }
         if (!yPercent) {
-            yFl = (yFl / image.getHeight());
+            yFl /= image.getHeight();
         }
 
         if ("width".equals(proportions)) {
@@ -134,8 +131,8 @@
             xFl = yFl;
         }
 
-        pb.add(new Float(xFl));
-        pb.add(new Float(yFl));
+        pb.add(Float.valueOf(xFl));
+        pb.add(Float.valueOf(yFl));
 
         log("\tScaling to " + (xFl * HUNDRED) + "% x "
             + (yFl * HUNDRED) + "%");
@@ -145,18 +142,16 @@
 
 
     /** {@inheritDoc}. */
+    @Override
     public PlanarImage executeTransformOperation(PlanarImage image) {
-        BufferedImage bi = null;
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 return performScale(image);
-            } else if (instr instanceof TransformOperation) {
-                bi = image.getAsBufferedImage();
+            }
+            if (instr instanceof TransformOperation) {
+                BufferedImage bi = image.getAsBufferedImage();
                 image = ((TransformOperation) instr)
                     .executeTransformOperation(PlanarImage.wrapRenderedImage(bi));
-                bi = image.getAsBufferedImage();
             }
         }
         return performScale(image);
@@ -164,10 +159,9 @@
 
 
     /** {@inheritDoc}. */
+    @Override
     public PlanarImage executeDrawOperation() {
-        final int size = instructions.size();
-        for (int i = 0; i < size; i++) {
-            ImageOperation instr = ((ImageOperation) instructions.elementAt(i));
+        for (ImageOperation instr : instructions) {
             if (instr instanceof DrawOperation) {
                 PlanarImage image = null;
                 // If this TransformOperation has DrawOperation children
diff --git a/src/main/org/apache/tools/ant/types/optional/image/Text.java b/src/main/org/apache/tools/ant/types/optional/image/Text.java
index ac18ed4..7f20693 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/Text.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/Text.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,7 +32,7 @@
 public class Text extends ImageOperation implements DrawOperation {
     private static final int DEFAULT_POINT = 10;
 
-    private String strText = "";
+    private String string = "";
     private String font = "Arial";
     private int point = DEFAULT_POINT;
     private boolean bold = false;
@@ -44,7 +44,7 @@
      * @param str the string to be used.
      */
     public void setString(String str) {
-        strText = str;
+        string = str;
     }
 
     /**
@@ -91,14 +91,15 @@
      * Draw the text.
      * @return the resultant image.
      */
+    @Override
     public PlanarImage executeDrawOperation() {
-        log("\tCreating Text \"" + strText + "\"");
+        log("\tCreating Text \"" + string + "\"");
 
         int width = 1;
         int height = 1;
 
         BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
-        Graphics2D graphics = (Graphics2D) bi.getGraphics();
+        Graphics2D graphics = bi.createGraphics();
         graphics.setRenderingHint(
             RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
         graphics.setRenderingHint(
@@ -106,11 +107,10 @@
         Font f = createFont();
         FontMetrics fmetrics = graphics.getFontMetrics(f);
         height = fmetrics.getMaxAscent() + fmetrics.getMaxDescent();
-        width = fmetrics.stringWidth(strText);
-
+        width = fmetrics.stringWidth(string);
 
         bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
-        graphics = (Graphics2D) bi.getGraphics();
+        graphics = bi.createGraphics();
 
         graphics.setRenderingHint(
             RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
@@ -119,9 +119,8 @@
 
         graphics.setFont(f);
         graphics.setColor(ColorMapper.getColorByName(color));
-        graphics.drawString(strText, 0, height - fmetrics.getMaxDescent());
-        PlanarImage image = PlanarImage.wrapRenderedImage(bi);
-        return image;
+        graphics.drawString(string, 0, height - fmetrics.getMaxDescent());
+        return PlanarImage.wrapRenderedImage(bi);
     }
 
     private Font createFont() {
diff --git a/src/main/org/apache/tools/ant/types/optional/image/TransformOperation.java b/src/main/org/apache/tools/ant/types/optional/image/TransformOperation.java
index 896e5d1..83220d2 100644
--- a/src/main/org/apache/tools/ant/types/optional/image/TransformOperation.java
+++ b/src/main/org/apache/tools/ant/types/optional/image/TransformOperation.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,6 +32,7 @@
     public abstract PlanarImage executeTransformOperation(PlanarImage img);
 
      /** {@inheritDoc}. */
+    @Override
     public void addRectangle(Rectangle instr) {
         instructions.add(instr);
     }
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Arc.java b/src/main/org/apache/tools/ant/types/optional/imageio/Arc.java
new file mode 100644
index 0000000..2a716ec
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Arc.java
@@ -0,0 +1,136 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.geom.Arc2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Draw an arc.
+ */
+public class Arc extends BasicShape implements DrawOperation {
+    private int start = 0;
+    private int stop = 0;
+    private ArcType type = ArcType.getDefault();
+
+    /**
+     * Set the start of the arc.
+     * @param start the start of the arc.
+     */
+    public void setStart(int start) {
+        this.start = start;
+    }
+
+    /**
+     * Set the stop of the arc.
+     * @param stop the stop of the arc.
+     */
+    public void setStop(int stop) {
+        this.stop = stop;
+    }
+
+    /**
+     * Set the type of arc.
+     * @param arcType the type to use - open, pie or chord.
+     */
+    public void setType(ArcType arcType) {
+        type = arcType;
+    }
+
+    /** {@inheritDoc}. */
+    @Override
+    public BufferedImage executeDrawOperation() {
+        BufferedImage bi = new BufferedImage(width + (strokeWidth * 2),
+            height + (strokeWidth * 2), BufferedImage.TYPE_4BYTE_ABGR_PRE);
+
+        Graphics2D graphics = bi.createGraphics();
+
+        if (!"transparent".equalsIgnoreCase(stroke)) {
+            BasicStroke bStroke = new BasicStroke(strokeWidth);
+            graphics.setColor(ColorMapper.getColorByName(stroke));
+            graphics.setStroke(bStroke);
+            graphics.draw(new Arc2D.Double(strokeWidth, strokeWidth, width,
+                height, start, stop, type.getIndex()));
+        }
+
+        if (!"transparent".equalsIgnoreCase(fill)) {
+            graphics.setColor(ColorMapper.getColorByName(fill));
+            graphics.fill(new Arc2D.Double(strokeWidth, strokeWidth,
+                width, height, start, stop, type.getIndex()));
+        }
+
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                BufferedImage img = ((DrawOperation) instr).executeDrawOperation();
+                graphics.drawImage(img, null, 0, 0);
+            } else if (instr instanceof TransformOperation) {
+                bi = ((TransformOperation) instr).executeTransformOperation(bi);
+                graphics = bi.createGraphics();
+            }
+        }
+        return bi;
+    }
+
+    public static class ArcType extends EnumeratedAttribute {
+
+        private static final List<String> VALUES = new ArrayList<>();
+
+        static {
+            VALUES.add(Arc2D.OPEN, "open");
+            VALUES.add(Arc2D.CHORD, "chord");
+            VALUES.add(Arc2D.PIE, "pie");
+        }
+
+        /**
+         * Constructor
+         */
+        public ArcType() {
+        }
+
+        /**
+         * Constructor using a string.
+         * @param value the value of the attribute
+         */
+        public ArcType(String value) {
+            setValue(value);
+        }
+
+        /**
+         * Get the default ArcType value.
+         * @return the default value.
+         */
+        public static ArcType getDefault() {
+            return new ArcType(VALUES.get(0));
+        }
+
+        /**
+         * @see EnumeratedAttribute#getValues()
+         * {@inheritDoc}.
+         */
+        @Override
+        public String[] getValues() {
+            return VALUES.toArray(new String[0]);
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/BasicShape.java b/src/main/org/apache/tools/ant/types/optional/imageio/BasicShape.java
new file mode 100644
index 0000000..7010e17
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/BasicShape.java
@@ -0,0 +1,70 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+
+/** Draw a basic shape */
+public abstract class BasicShape extends ImageOperation implements DrawOperation {
+    // CheckStyle:VisibilityModifier OFF - bc
+    protected int width = 0;
+    protected int height = 0;
+    protected int strokeWidth = 0;
+    protected String stroke = "black";
+    protected String fill = "transparent";
+    // CheckStyle:VisibilityModifier ON
+
+    /**
+     * Set the width.
+     * @param w the width of the shape.
+     */
+    public void setWidth(int w) {
+        width = w;
+    }
+
+    /**
+     * Set the height.
+     * @param h the height of the shape.
+     */
+    public void setHeight(int h) {
+        height = h;
+    }
+
+    /**
+     * Set the stroke width attribute.
+     * @param sw the value to use.
+     */
+    public void setStrokewidth(int sw) {
+        strokeWidth = sw;
+    }
+
+    /**
+     * Set the stroke attribute.
+     * @param col the color value to use.
+     */
+    public void setStroke(String col) {
+        stroke = col;
+    }
+
+    /**
+     * Set the fill attribute.
+     * @param col the color value to use.
+     */
+    public void setFill(String col) {
+        fill = col;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/ColorMapper.java b/src/main/org/apache/tools/ant/types/optional/imageio/ColorMapper.java
new file mode 100644
index 0000000..ba82ae2
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/ColorMapper.java
@@ -0,0 +1,108 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.Color;
+import java.util.Locale;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public final class ColorMapper {
+
+    /** black string */
+    public static final String COLOR_BLACK = "black";
+    /** blue string */
+    public static final String COLOR_BLUE = "blue";
+    /** cyan string */
+    public static final String COLOR_CYAN = "cyan";
+    /** black string */
+    public static final String COLOR_DARKGRAY = "darkgray";
+    /** gray string */
+    public static final String COLOR_GRAY = "gray";
+    /** lightgray string */
+    public static final String COLOR_LIGHTGRAY = "lightgray";
+    // Gotta at least put in the proper spelling :-P
+    /** darkgrey string */
+    public static final String COLOR_DARKGREY = "darkgrey";
+    /** grey string */
+    public static final String COLOR_GREY = "grey";
+    /** lightgrey string */
+    public static final String COLOR_LIGHTGREY = "lightgrey";
+    /** green string */
+    public static final String COLOR_GREEN = "green";
+    /** magenta string */
+    public static final String COLOR_MAGENTA = "magenta";
+    /** orange string */
+    public static final String COLOR_ORANGE = "orange";
+    /** pink string */
+    public static final String COLOR_PINK = "pink";
+    /** reg string */
+    public static final String COLOR_RED = "red";
+    /** white string */
+    public static final String COLOR_WHITE = "white";
+    /** yellow string */
+    public static final String COLOR_YELLOW = "yellow";
+
+    /**
+     * Convert a color name to a color value.
+     * @param colorName a string repr of the color.
+     * @return the color value.
+     * @todo refactor to use an EnumeratedAttribute (maybe?)
+     */
+    public static Color getColorByName(String colorName) {
+        switch (colorName.toLowerCase(Locale.ENGLISH)) {
+        case COLOR_BLUE:
+            return Color.blue;
+        case COLOR_CYAN:
+            return Color.cyan;
+        case COLOR_DARKGRAY:
+        case COLOR_DARKGREY:
+            return Color.darkGray;
+        case COLOR_GRAY:
+        case COLOR_GREY:
+            return Color.gray;
+        case COLOR_LIGHTGRAY:
+        case COLOR_LIGHTGREY:
+            return Color.lightGray;
+        case COLOR_GREEN:
+            return Color.green;
+        case COLOR_MAGENTA:
+            return Color.magenta;
+        case COLOR_ORANGE:
+            return Color.orange;
+        case COLOR_PINK:
+            return Color.pink;
+        case COLOR_RED:
+            return Color.red;
+        case COLOR_WHITE:
+            return Color.white;
+        case COLOR_YELLOW:
+            return Color.yellow;
+        case COLOR_BLACK:
+        default:
+            return Color.black;
+        }
+    }
+
+    /** private constructor for Utility class */
+    private ColorMapper() {
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Draw.java b/src/main/org/apache/tools/ant/types/optional/imageio/Draw.java
new file mode 100644
index 0000000..8b85e9e
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Draw.java
@@ -0,0 +1,98 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public class Draw extends TransformOperation {
+    private int xloc = 0;
+    private int yloc = 0;
+
+    /**
+     * Set the X location.
+     * @param x the value to use.
+     */
+    public void setXloc(int x) {
+        xloc = x;
+    }
+
+    /**
+     * Set the Y location.
+     * @param y the value to use.
+     */
+    public void setYloc(int y) {
+        yloc = y;
+    }
+
+    /**
+     * Add text to the operation.
+     * @param text the text to add.
+     */
+    public void addText(Text text) {
+        instructions.add(text);
+    }
+
+    /**
+     * Add a rectangle to the operation.
+     * @param rect the rectangle to add.
+     */
+    public void addRectangle(Rectangle rect) {
+        instructions.add(rect);
+    }
+
+    /**
+     * Add an ellipse.
+     * @param elip the ellipse to add.
+     */
+    public void addEllipse(Ellipse elip) {
+        instructions.add(elip);
+    }
+
+    /**
+     * Add an arc.
+     * @param arc the arc to add.
+     */
+    public void addArc(Arc arc) {
+        instructions.add(arc);
+    }
+
+    /** {@inheritDoc}. */
+    @Override
+    public BufferedImage executeTransformOperation(BufferedImage bi) {
+        Graphics2D graphics = bi.createGraphics();
+
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                BufferedImage op = ((DrawOperation) instr).executeDrawOperation();
+                log("\tDrawing to x=" + xloc + " y=" + yloc);
+                graphics.drawImage(op, null, xloc, yloc);
+            } else if (instr instanceof TransformOperation) {
+                BufferedImage child
+                    = ((TransformOperation) instr).executeTransformOperation(null);
+                log("\tDrawing to x=" + xloc + " y=" + yloc);
+                graphics.drawImage(child, null, xloc, yloc);
+            }
+        }
+        return bi;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/DrawOperation.java b/src/main/org/apache/tools/ant/types/optional/imageio/DrawOperation.java
new file mode 100644
index 0000000..fe28b7d
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/DrawOperation.java
@@ -0,0 +1,39 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Interface which represents an Operation which is "drawable", such
+ * as a Rectangle, Circle or Text.  The Operation is responsible for
+ * creating its own image buffer and drawing itself into it, then
+ * wrapping and returning it as a PlanarImage.  This allows multiple
+ * "drawable" objects to be nested.
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public interface DrawOperation {
+    /**
+     * Abstract method which is intended to create an image buffer
+     * and return it so it can be drawn into another object.  Use
+     * an Alpha channel for a "transparent" background.
+     * @return a planar image
+     */
+    BufferedImage executeDrawOperation();
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Ellipse.java b/src/main/org/apache/tools/ant/types/optional/imageio/Ellipse.java
new file mode 100644
index 0000000..00df24b
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Ellipse.java
@@ -0,0 +1,60 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Draw an ellipse.
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public class Ellipse extends BasicShape implements DrawOperation {
+    /** {@inheritDoc}. */
+    @Override
+    public BufferedImage executeDrawOperation() {
+        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
+
+        Graphics2D graphics = bi.createGraphics();
+
+        if (!"transparent".equalsIgnoreCase(stroke)) {
+            BasicStroke bStroke = new BasicStroke(strokeWidth);
+            graphics.setColor(ColorMapper.getColorByName(stroke));
+            graphics.setStroke(bStroke);
+            graphics.draw(new Ellipse2D.Double(0, 0, width, height));
+        }
+
+        if (!"transparent".equalsIgnoreCase(fill)) {
+            graphics.setColor(ColorMapper.getColorByName(fill));
+            graphics.fill(new Ellipse2D.Double(0, 0, width, height));
+        }
+
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                BufferedImage img = ((DrawOperation) instr).executeDrawOperation();
+                graphics.drawImage(img, null, 0, 0);
+            } else if (instr instanceof TransformOperation) {
+                bi = ((TransformOperation) instr).executeTransformOperation(bi);
+                graphics = bi.createGraphics();
+            }
+        }
+        return bi;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/ImageOperation.java b/src/main/org/apache/tools/ant/types/optional/imageio/ImageOperation.java
new file mode 100644
index 0000000..677ef2b
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/ImageOperation.java
@@ -0,0 +1,57 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import org.apache.tools.ant.types.DataType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public abstract class ImageOperation extends DataType {
+     // CheckStyle:VisibilityModifier OFF - bc
+    protected final List<ImageOperation> instructions = new ArrayList<>();
+     // CheckStyle:VisibilityModifier ON
+
+    /**
+     * Add a rotate to the operation.
+     * @param instr the rotate to add.
+     */
+    public void addRotate(Rotate instr) {
+        instructions.add(instr);
+    }
+
+    /**
+     * Add a draw to the operation.
+     * @param instr the draw to add.
+     */
+    public void addDraw(Draw instr) {
+        instructions.add(instr);
+    }
+
+    /**
+     * Add a scale to the operation.
+     * @param instr the scale to add.
+     */
+    public void addScale(Scale instr) {
+        instructions.add(instr);
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Rectangle.java b/src/main/org/apache/tools/ant/types/optional/imageio/Rectangle.java
new file mode 100644
index 0000000..53cb803
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Rectangle.java
@@ -0,0 +1,92 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public class Rectangle extends BasicShape implements DrawOperation {
+    private int arcwidth = 0;
+    private int archeight = 0;
+
+    /**
+     * Set the arc width.
+     * @param w the value to use.
+     */
+    public void setArcwidth(int w) {
+        arcwidth = w;
+    }
+
+    /**
+     * Set the arc height.
+     * @param h the value to use.
+     */
+    public void setArcheight(int h) {
+        archeight = h;
+    }
+
+    /** {@inheritDoc}. */
+    @Override
+    public BufferedImage executeDrawOperation() {
+        log("\tCreating Rectangle w=" + width + " h=" + height + " arcw="
+            + arcwidth + " arch=" + archeight);
+        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
+
+        Graphics2D graphics = bi.createGraphics();
+
+        if (!"transparent".equalsIgnoreCase(stroke)) {
+            BasicStroke bStroke = new BasicStroke(strokeWidth);
+            graphics.setColor(ColorMapper.getColorByName(stroke));
+            graphics.setStroke(bStroke);
+
+            if (arcwidth == 0 && archeight == 0) {
+                graphics.drawRect(0, 0, width, height);
+            } else {
+                graphics.drawRoundRect(0, 0, width, height, arcwidth, archeight);
+            }
+        }
+
+        if (!"transparent".equalsIgnoreCase(fill)) {
+            graphics.setColor(ColorMapper.getColorByName(fill));
+            if (arcwidth == 0 && archeight == 0) {
+                graphics.fillRect(strokeWidth, strokeWidth,
+                    width - (strokeWidth * 2), height - (strokeWidth * 2));
+            } else {
+                graphics.fillRoundRect(strokeWidth, strokeWidth,
+                    width - (strokeWidth * 2), height - (strokeWidth * 2),
+                    arcwidth, archeight);
+            }
+        }
+
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                BufferedImage img = ((DrawOperation) instr).executeDrawOperation();
+                graphics.drawImage(img, null, 0, 0);
+            } else if (instr instanceof TransformOperation) {
+                bi = ((TransformOperation) instr).executeTransformOperation(bi);
+                graphics = bi.createGraphics();
+            }
+        }
+        return bi;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Rotate.java b/src/main/org/apache/tools/ant/types/optional/imageio/Rotate.java
new file mode 100644
index 0000000..d95a9d2
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Rotate.java
@@ -0,0 +1,151 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import org.apache.tools.ant.Project;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.util.Arrays;
+
+/**
+ * ImageOperation to rotate an image by a certain degree
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public class Rotate extends TransformOperation implements DrawOperation {
+    private static final float HALF_CIRCLE = 180.0F;
+
+    private float angle = 0.0F;
+
+    /**
+     * Sets the angle of rotation in degrees.
+     * @param ang The angle at which to rotate the image
+     */
+    public void setAngle(String ang) {
+        angle = Float.parseFloat(ang) % (2 * HALF_CIRCLE);
+    }
+
+    /**
+     * Rotate an image.
+     * @param image the image to rotate.
+     * @return the rotated image.
+     */
+    public BufferedImage performRotate(BufferedImage image) {
+        // Float zero can be negative
+        if (Float.compare(Math.abs(angle), 0.0F) == 0) {
+            return image;
+        }
+
+        if (angle < 0) {
+            angle += 2 * HALF_CIRCLE;
+        }
+
+        // 180 degree rotation == flip the image vertically and horizontally
+        if (Float.compare(angle, HALF_CIRCLE) == 0) {
+            log("Flipping an image", Project.MSG_DEBUG);
+            AffineTransform tx = AffineTransform.getScaleInstance(-1, -1);
+            tx.translate(-image.getWidth(null), -image.getHeight(null));
+            AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
+            return op.filter(image, null);
+        }
+
+        AffineTransform tx = AffineTransform.getRotateInstance((float) (angle
+                * (Math.PI / HALF_CIRCLE)));
+        // Figure out the new bounding box
+        Rectangle2D box = getBoundingBox(image, tx);
+        AffineTransform translation = AffineTransform.getTranslateInstance(-box.getMinX(),
+                -box.getMinY());
+        tx.preConcatenate(translation);
+        BufferedImage rotatedImage = new BufferedImage((int) Math.round(box.getWidth()),
+                (int) Math.round(box.getHeight()), image.getType());
+        // Avoid black space around the rotated image
+        Graphics2D graphics = rotatedImage.createGraphics();
+        graphics.setPaint(new Color(image.getRGB(0, 0)));
+        graphics.fillRect(0, 0, rotatedImage.getWidth(), rotatedImage.getHeight());
+        graphics.dispose();
+        // Rotate
+        AffineTransformOp rotateOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
+        rotateOp.filter(image, rotatedImage);
+        return rotatedImage;
+    }
+
+    private Rectangle2D getBoundingBox(BufferedImage image, AffineTransform tx) {
+        int xmax = image.getWidth() - 1;
+        int ymax = image.getHeight() - 1;
+        Point2D[] corners = new Point2D.Double[4];
+        corners[0] = new Point2D.Double(0, 0);
+        corners[1] = new Point2D.Double(xmax, 0);
+        corners[2] = new Point2D.Double(xmax, ymax);
+        corners[3] = new Point2D.Double(0, ymax);
+        tx.transform(corners, 0, corners, 0, 4);
+
+        // Create bounding box of transformed corner points
+        Rectangle2D boundingBox = new Rectangle2D.Double();
+        Arrays.stream(corners, 0, 4).forEach(boundingBox::add);
+        return boundingBox;
+    }
+
+    /**
+     * Performs the image rotation when being handled as a TransformOperation.
+     * @param image The image to perform the transformation on.
+     * @return the transformed image.
+     */
+    @Override
+    public BufferedImage executeTransformOperation(BufferedImage image) {
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                // If this TransformOperation has DrawOperation children
+                // then Rotate the first child and return.
+                BufferedImage op = ((DrawOperation) instr).executeDrawOperation();
+                return performRotate(op);
+            }
+            if (instr instanceof TransformOperation) {
+                image = ((TransformOperation) instr).executeTransformOperation(image);
+            }
+        }
+        image = performRotate(image);
+        return image;
+    }
+
+    /**
+     *  Performs the image rotation when being handled as a DrawOperation.
+     *  It absolutely requires that there be a DrawOperation nested beneath it,
+     *  but only the FIRST DrawOperation will be handled since it can only return
+     *  ONE image.
+     * @return the image.
+     */
+    @Override
+    public BufferedImage executeDrawOperation() {
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                // If this TransformOperation has DrawOperation children
+                // then Rotate the first child and return.
+                BufferedImage op = ((DrawOperation) instr).executeDrawOperation();
+                return performRotate(op);
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Scale.java b/src/main/org/apache/tools/ant/types/optional/imageio/Scale.java
new file mode 100644
index 0000000..f2b45ed
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Scale.java
@@ -0,0 +1,170 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public class Scale extends TransformOperation implements DrawOperation {
+    private static final int HUNDRED = 100;
+
+    private String widthStr = "100%";
+    private String heightStr = "100%";
+    private boolean xPercent = true;
+    private boolean yPercent = true;
+    private String proportions = "ignore";
+
+    /** Enumerated class for proportions attribute. */
+    public static class ProportionsAttribute extends EnumeratedAttribute {
+        /** {@inheritDoc}. */
+        @Override
+        public String[] getValues() {
+            return new String[] { "ignore", "width", "height", "cover", "fit" };
+        }
+    }
+
+    /**
+     *  Sets the behaviour regarding the image proportions.
+     * @param pa the enumerated value.
+     */
+    public void setProportions(ProportionsAttribute pa) {
+        proportions = pa.getValue();
+    }
+
+    /**
+     * Sets the width of the image, either as an integer or a %.
+     * Defaults to 100%.
+     * @param width the value to use.
+     */
+    public void setWidth(String width) {
+        widthStr = width;
+    }
+
+    /**
+     *  Sets the height of the image, either as an integer or a %.  Defaults to 100%.
+     * @param height the value to use.
+     */
+    public void setHeight(String height) {
+        heightStr = height;
+    }
+
+    /**
+     * Get the width.
+     * @return the value converted from the width string.
+     */
+    public float getWidth() {
+        int percIndex = widthStr.indexOf('%');
+        if (percIndex > 0) {
+            xPercent = true;
+            float width = Float.parseFloat(widthStr.substring(0, percIndex));
+            return width / HUNDRED;
+        }
+        xPercent = false;
+        return Float.parseFloat(widthStr);
+    }
+
+    /**
+     * Get the height.
+     * @return the value converted from the height string.
+     */
+    public float getHeight() {
+        int percIndex = heightStr.indexOf('%');
+        if (percIndex > 0) {
+            yPercent = true;
+            return Float.parseFloat(heightStr.substring(0, percIndex)) / HUNDRED;
+        }
+        yPercent = false;
+        return Float.parseFloat(heightStr);
+    }
+
+    /**
+     * Scale an image.
+     * @param image the image to scale.
+     * @return the scaled image.
+     */
+    public BufferedImage performScale(BufferedImage image) {
+        float xFl = getWidth();
+        float yFl = getHeight();
+
+        if (!xPercent) {
+            xFl /= image.getWidth();
+        }
+        if (!yPercent) {
+            yFl /= image.getHeight();
+        }
+
+        if ("width".equals(proportions)) {
+            yFl = xFl;
+        } else if ("height".equals(proportions)) {
+            xFl = yFl;
+        } else if ("fit".equals(proportions)) {
+            yFl = Math.min(xFl, yFl);
+            xFl = yFl;
+        } else if ("cover".equals(proportions)) {
+            yFl = Math.max(xFl, yFl);
+            xFl = yFl;
+        }
+
+        log("\tScaling to " + (xFl * HUNDRED) + "% x "
+            + (yFl * HUNDRED) + "%");
+
+        AffineTransform tx = AffineTransform.getScaleInstance(xFl, yFl);
+        BufferedImage scaleImage = new BufferedImage((int) (xFl * image.getWidth()),
+                (int) (yFl * image.getHeight()), image.getType());
+        AffineTransformOp scaleOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
+        scaleOp.filter(image, scaleImage);
+        return scaleImage;
+    }
+
+    /** {@inheritDoc}. */
+    @Override
+    public BufferedImage executeTransformOperation(BufferedImage image) {
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                return performScale(image);
+            }
+            if (instr instanceof TransformOperation) {
+                image = ((TransformOperation) instr).executeTransformOperation(image);
+            }
+        }
+        return performScale(image);
+    }
+
+
+    /** {@inheritDoc}. */
+    @Override
+    public BufferedImage executeDrawOperation() {
+        for (ImageOperation instr : instructions) {
+            if (instr instanceof DrawOperation) {
+                BufferedImage image = null;
+                // If this TransformOperation has DrawOperation children
+                // then Rotate the first child and return.
+                performScale(image);
+                return image;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/Text.java b/src/main/org/apache/tools/ant/types/optional/imageio/Text.java
new file mode 100644
index 0000000..61a2fab
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/Text.java
@@ -0,0 +1,134 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public class Text extends ImageOperation implements DrawOperation {
+    private static final int DEFAULT_POINT = 10;
+
+    private String string = "";
+    private String font = "Arial";
+    private int point = DEFAULT_POINT;
+    private boolean bold = false;
+    private boolean italic = false;
+    private String color = "black";
+
+    /**
+     * Set the string to be used as text.
+     * @param str the string to be used.
+     */
+    public void setString(String str) {
+        string = str;
+    }
+
+    /**
+     * Set the font to be used to draw the text.
+     * @param f the font to be used.
+     */
+    public void setFont(String f) {
+        font = f;
+    }
+
+    /**
+     * Set the number of points to be used.
+     * @param p an integer value as a string.
+     */
+    public void setPoint(String p) {
+        point = Integer.parseInt(p);
+    }
+
+    /**
+     * Set the color of the text.
+     * @param c the color name.
+     */
+    public void setColor(String c) {
+        color = c;
+    }
+
+    /**
+     * @todo is this used?
+     * @param state not used at the moment.
+     */
+    public void setBold(boolean state) {
+        bold = state;
+    }
+
+    /**
+     * @todo is this used?
+     * @param state not used at the moment.
+     */
+    public void setItalic(boolean state) {
+        italic = state;
+    }
+
+    /**
+     * Draw the text.
+     * @return the resultant image.
+     */
+    @Override
+    public BufferedImage executeDrawOperation() {
+        log("\tCreating Text \"" + string + "\"");
+
+        int width = 1;
+        int height = 1;
+
+        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
+        Graphics2D graphics = bi.createGraphics();
+        graphics.setRenderingHint(
+            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(
+            RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+        Font f = createFont();
+        FontMetrics fmetrics = graphics.getFontMetrics(f);
+        height = fmetrics.getMaxAscent() + fmetrics.getMaxDescent();
+        width = fmetrics.stringWidth(string);
+
+        bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
+        graphics = bi.createGraphics();
+
+        graphics.setRenderingHint(
+            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(
+            RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+
+        graphics.setFont(f);
+        graphics.setColor(ColorMapper.getColorByName(color));
+        graphics.drawString(string, 0, height - fmetrics.getMaxDescent());
+        return bi;
+    }
+
+    private Font createFont() {
+        int style = Font.PLAIN;
+        if (bold) {
+            style |= Font.BOLD;
+        }
+        if (italic) {
+            style |= Font.ITALIC;
+        }
+        return new Font(font, style, point);
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/imageio/TransformOperation.java b/src/main/org/apache/tools/ant/types/optional/imageio/TransformOperation.java
new file mode 100644
index 0000000..d161b03
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/imageio/TransformOperation.java
@@ -0,0 +1,33 @@
+/*
+ *  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
+ *
+ *      https://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.optional.imageio;
+
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @see org.apache.tools.ant.taskdefs.optional.image.ImageIOTask
+ */
+public abstract class TransformOperation extends ImageOperation {
+    /**
+     * Performs the transformations.
+     * @param img The image to perform the transformation on.
+     * @return the transformed image.
+     */
+    public abstract BufferedImage executeTransformOperation(BufferedImage img);
+}
diff --git a/src/main/org/apache/tools/ant/types/optional/xz/XzResource.java b/src/main/org/apache/tools/ant/types/optional/xz/XzResource.java
new file mode 100644
index 0000000..f9093bc
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/optional/xz/XzResource.java
@@ -0,0 +1,82 @@
+/*
+ *  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
+ *
+ *      https://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.optional.xz;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.CompressedResource;
+import org.tukaani.xz.LZMA2Options;
+import org.tukaani.xz.XZInputStream;
+import org.tukaani.xz.XZOutputStream;
+
+/**
+ * A XZ compressed resource.
+ *
+ * <p>Wraps around another resource, delegates all queries to that
+ * other resource but uncompresses/compresses streams on the fly.</p>
+ *
+ * @since Ant 1.10.1
+ */
+public class XzResource extends CompressedResource {
+
+    /** A no-arg constructor */
+    public XzResource() {
+    }
+
+    /**
+     * Constructor with another resource to wrap.
+     * @param other the resource to wrap.
+     */
+    public XzResource(ResourceCollection other) {
+        super(other);
+    }
+
+    /**
+     * Decompress on the fly using java.util.zip.XZInputStream.
+     * @param in the stream to wrap.
+     * @return the wrapped stream.
+     * @throws IOException if there is a problem.
+     */
+    @Override
+    protected InputStream wrapStream(InputStream in) throws IOException {
+        return new XZInputStream(in);
+    }
+
+    /**
+     * Compress on the fly using java.util.zip.XZOutStream.
+     * @param out the stream to wrap.
+     * @return the wrapped stream.
+     * @throws IOException if there is a problem.
+     */
+     @Override
+    protected OutputStream wrapStream(OutputStream out) throws IOException {
+        return new XZOutputStream(out, new LZMA2Options());
+    }
+
+    /**
+     * Get the name of the compression method.
+     * @return the string "XZ".
+     */
+    @Override
+    protected String getCompressionName() {
+        return "XZ";
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/resolver/ApacheCatalog.java b/src/main/org/apache/tools/ant/types/resolver/ApacheCatalog.java
index 66ed7ff..de3c956 100644
--- a/src/main/org/apache/tools/ant/types/resolver/ApacheCatalog.java
+++ b/src/main/org/apache/tools/ant/types/resolver/ApacheCatalog.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -54,6 +54,7 @@
      *  will be a total of two ApacheCatalog instances, and so on.</p>
      * @return the catalog.
      */
+    @Override
     protected Catalog newCatalog() {
         final ApacheCatalog cat = (ApacheCatalog) super.newCatalog();
         cat.setResolver(resolver);
@@ -85,6 +86,7 @@
      *
      * @param entry The CatalogEntry to process.
      */
+    @Override
     public void addEntry(final CatalogEntry entry) {
 
         final int type = entry.getEntryType();
diff --git a/src/main/org/apache/tools/ant/types/resolver/ApacheCatalogResolver.java b/src/main/org/apache/tools/ant/types/resolver/ApacheCatalogResolver.java
index f036247..eed8aa5 100644
--- a/src/main/org/apache/tools/ant/types/resolver/ApacheCatalogResolver.java
+++ b/src/main/org/apache/tools/ant/types/resolver/ApacheCatalogResolver.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 package org.apache.tools.ant.types.resolver;
 
 import java.io.IOException;
-import java.net.MalformedURLException;
 import java.net.URL;
 
 import org.apache.tools.ant.BuildException;
@@ -41,9 +40,9 @@
  * <p>The {@link org.apache.tools.ant.types.resolver.ApacheCatalog
  * ApacheCatalog} class is used to parse external catalog files, which
  * can be in either <a
- * href="http://oasis-open.org/committees/entity/background/9401.html">
+ * href="https://oasis-open.org/committees/entity/background/9401.html">
  * plain text format</a> or <a
- * href="http://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
+ * href="https://www.oasis-open.org/committees/entity/spec-2001-08-06.html">
  * XML format</a>.</p>
  *
  * <p>For each entry found in an external catalog file, if any, an
@@ -104,7 +103,7 @@
 
         final Catalog catalog = getCatalog();
         if (!(catalog instanceof ApacheCatalog)) {
-            throw new BuildException("Wrong catalog type found: " + catalog.getClass().getName());
+            throw new BuildException("Wrong catalog type found: %s", catalog.getClass().getName());
         }
         final ApacheCatalog apacheCatalog = (ApacheCatalog) catalog;
 
@@ -113,9 +112,7 @@
 
         try {
             apacheCatalog.parseCatalog(file);
-        } catch (final MalformedURLException ex) {
-            throw new BuildException(ex);
-        } catch (final IOException ex) {
+        } catch (IOException ex) {
             throw new BuildException(ex);
         }
     }
diff --git a/src/main/org/apache/tools/ant/types/resolver/package.html b/src/main/org/apache/tools/ant/types/resolver/package.html
index 11b3c77..983044e 100644
--- a/src/main/org/apache/tools/ant/types/resolver/package.html
+++ b/src/main/org/apache/tools/ant/types/resolver/package.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -6,7 +7,7 @@
    (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
+       https://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,
@@ -14,22 +15,27 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
+<html lang="en">
+<head>
+  <title>Integration with xml-commons resolver</title>
+</head>
 <body>
 Ant integration with xml-commons resolver.
 
 <p>These classes enhance the <code>&lt;xmlcatalog&gt;</code> datatype
 to support external catalog files using the xml-commons resolver, in
 accordance with the
-<a href="http://oasis-open.org/committees/entity/spec-2001-08-06.html">
+<a href="https://oasis-open.org/committees/entity/spec-2001-08-06.html">
 OASIS "Open Catalog" standard</a>.  They will be used if and only if
 the xml-commons resolver library is available on the classpath.</p>
 
-@see <A HREF="http://xml.apache.org/commons">Apache xml-commons Project</A>
+@see <a href="https://xml.apache.org/commons">Apache xml-commons Project</a>
 
 @see org.apache.tools.ant.types.XMLCatalog
 @see org.apache.tools.ant.types.resolver.ApacheCatalogResolver
 @see org.apache.tools.ant.types.resolver.ApacheCatalog
 
-@author <A HREF="mailto:cstrong@arielpartners.com">Craeg Strong</A>
+@author <a href="mailto:cstrong@arielpartners.com">Craeg Strong</a>
 
 </body>
+</html>
diff --git a/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java b/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java
index 5805c7c..ad89993 100644
--- a/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -84,7 +84,7 @@
      */
     public Path getClasspath() {
         if (isReference()) {
-            return ((AbstractClasspathResource) getCheckedRef()).getClasspath();
+            return getRef().getClasspath();
         }
         dieOnCircularReference();
         return classpath;
@@ -96,7 +96,7 @@
      */
     public Reference getLoader() {
         if (isReference()) {
-            return ((AbstractClasspathResource) getCheckedRef()).getLoader();
+            return getRef().getLoader();
         }
         dieOnCircularReference();
         return loader;
@@ -151,17 +151,13 @@
      */
     public boolean isExists() {
         if (isReference()) {
-            return  ((Resource) getCheckedRef()).isExists();
+            return getRef().isExists();
         }
         dieOnCircularReference();
-        InputStream is = null;
-        try {
-            is = getInputStream();
+        try (InputStream is = getInputStream()) {
             return is != null;
         } catch (IOException ex) {
             return false;
-        } finally {
-            FileUtils.close(is);
         }
     }
 
@@ -173,7 +169,7 @@
      */
     public InputStream getInputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getInputStream();
+            return getRef().getInputStream();
         }
         dieOnCircularReference();
 
@@ -181,18 +177,21 @@
         return !classLoader.needsCleanup()
             ? openInputStream(classLoader.getLoader())
             : new FilterInputStream(openInputStream(classLoader.getLoader())) {
-                    public void close() throws IOException {
-                        FileUtils.close(in);
-                        classLoader.cleanup();
+                @Override
+                public void close() throws IOException {
+                    FileUtils.close(in);
+                    classLoader.cleanup();
+                }
+
+                @Override
+                protected void finalize() throws Throwable {
+                    try {
+                        close();
+                    } finally {
+                        super.finalize();
                     }
-                    protected void finalize() throws Throwable {
-                        try {
-                            close();
-                        } finally {
-                            super.finalize();
-                        }
-                    }
-                };
+                }
+            };
     }
 
     /**
@@ -204,10 +203,10 @@
      */
     protected ClassLoaderWithFlag getClassLoader() {
         ClassLoader cl = null;
-        boolean clNeedsCleanup = false;
         if (loader != null) {
-            cl = (ClassLoader) loader.getReferencedObject();
+            cl = loader.getReferencedObject();
         }
+        boolean clNeedsCleanup = false;
         if (cl == null) {
             if (getClasspath() != null) {
                 Path p = getClasspath().concatSystemClasspath("ignore");
@@ -253,6 +252,11 @@
         }
     }
 
+    @Override
+    protected AbstractClasspathResource getRef() {
+        return getCheckedRef(AbstractClasspathResource.class);
+    }
+
     public static class ClassLoaderWithFlag {
         private final ClassLoader loader;
         private final boolean cleanup;
@@ -261,8 +265,15 @@
             loader = l;
             cleanup = needsCleanup && l instanceof AntClassLoader;
         }
-        public ClassLoader getLoader() { return loader; }
-        public boolean needsCleanup() { return cleanup; }
+
+        public ClassLoader getLoader() {
+            return loader;
+        }
+
+        public boolean needsCleanup() {
+            return cleanup;
+        }
+
         public void cleanup() {
             if (cleanup) {
                 ((AntClassLoader) loader).cleanup();
diff --git a/src/main/org/apache/tools/ant/types/resources/AbstractResourceCollectionWrapper.java b/src/main/org/apache/tools/ant/types/resources/AbstractResourceCollectionWrapper.java
index 5e4c3a3..bf3c7c0 100644
--- a/src/main/org/apache/tools/ant/types/resources/AbstractResourceCollectionWrapper.java
+++ b/src/main/org/apache/tools/ant/types/resources/AbstractResourceCollectionWrapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,6 +20,7 @@
 import java.io.File;
 import java.util.Iterator;
 import java.util.Stack;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -85,9 +86,10 @@
      * Fulfill the ResourceCollection contract.
      * @return an Iterator of Resources.
      */
+    @Override
     public final synchronized Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((AbstractResourceCollectionWrapper) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         dieOnCircularReference();
         return new FailFast(this, createIterator());
@@ -107,9 +109,10 @@
      * Fulfill the ResourceCollection contract.
      * @return number of elements as int.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
-            return ((AbstractResourceCollectionWrapper) getCheckedRef()).size();
+            return getRef().size();
         }
         dieOnCircularReference();
         return getSize();
@@ -129,7 +132,7 @@
      */
     public synchronized boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         dieOnCircularReference();
 
@@ -182,24 +185,23 @@
     }
 
     /**
-     * Format this BaseResourceCollectionWrapper as a String.
+     * Format this AbstractResourceCollectionWrapper as a String.
      * @return a descriptive <code>String</code>.
      */
+    @Override
     public synchronized String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
-        if (getSize() == 0) {
+        if (isEmpty()) {
             return "";
         }
-        StringBuilder sb = new StringBuilder();
-        for (Resource resource : this) {
-            if (sb.length() > 0) {
-                sb.append(File.pathSeparatorChar);
-            }
-            sb.append(resource);
-        }
-        return sb.toString();
+        return stream().map(Object::toString)
+            .collect(Collectors.joining(File.pathSeparator));
+    }
+
+    private AbstractResourceCollectionWrapper getRef() {
+        return getCheckedRef(AbstractResourceCollectionWrapper.class);
     }
 
     private BuildException oneNested() {
diff --git a/src/main/org/apache/tools/ant/types/resources/AllButFirst.java b/src/main/org/apache/tools/ant/types/resources/AllButFirst.java
index ffa665f..f308da8 100644
--- a/src/main/org/apache/tools/ant/types/resources/AllButFirst.java
+++ b/src/main/org/apache/tools/ant/types/resources/AllButFirst.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,8 @@
  */
 package org.apache.tools.ant.types.resources;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.types.Resource;
 
@@ -36,25 +34,15 @@
      * Take all elements except for the first <code>count</code> elements.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
-        int ct = getValidCount();
-        Iterator<Resource> iter = getResourceCollection().iterator();
-        List<Resource> al = new ArrayList<Resource>();
-        for (int i = 0; i < ct && iter.hasNext(); i++) {
-            // discard
-            iter.next();
-        }
-        while (iter.hasNext()) {
-            al.add(iter.next());
-        }
-        return al;
+        return getResourceCollection().stream().skip(getValidCount())
+            .collect(Collectors.toList());
     }
 
     @Override
     public synchronized int size() {
-        int sz = getResourceCollection().size();
-        int ct = getValidCount();
-        return sz > ct ? sz - ct : 0;
+        return Math.max(getResourceCollection().size() - getValidCount(), 0);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/AllButLast.java b/src/main/org/apache/tools/ant/types/resources/AllButLast.java
index a1e6a98..43c37e7 100644
--- a/src/main/org/apache/tools/ant/types/resources/AllButLast.java
+++ b/src/main/org/apache/tools/ant/types/resources/AllButLast.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,11 @@
 package org.apache.tools.ant.types.resources;
 
 import java.util.Collection;
-import java.util.List;
+import java.util.Collections;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.types.Resource;
-import org.apache.tools.ant.util.CollectionUtils;
+import org.apache.tools.ant.types.ResourceCollection;
 
 /**
  * ResourceCollection that contains all resources of another
@@ -35,19 +36,20 @@
      * Take all elements except for the last <code>count</code> elements.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
         int ct = getValidCount();
-        List<Resource> result =
-            (List<Resource>) CollectionUtils.asCollection(getResourceCollection()
-                                                          .iterator());
-        return result.subList(0, result.size() - ct);
+        ResourceCollection nested = getResourceCollection();
+        if (ct > nested.size()) {
+            return Collections.emptyList();
+        }
+        return nested.stream().limit((long) nested.size() - ct)
+            .collect(Collectors.toList());
     }
 
     @Override
     public synchronized int size() {
-        int sz = getResourceCollection().size();
-        int ct = getValidCount();
-        return sz > ct ? sz - ct : 0;
+        return Math.max(getResourceCollection().size() - getValidCount(), 0);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/Appendable.java b/src/main/org/apache/tools/ant/types/resources/Appendable.java
index 14f4711..e77625a 100644
--- a/src/main/org/apache/tools/ant/types/resources/Appendable.java
+++ b/src/main/org/apache/tools/ant/types/resources/Appendable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/AppendableResourceCollection.java b/src/main/org/apache/tools/ant/types/resources/AppendableResourceCollection.java
new file mode 100644
index 0000000..cc7bd53
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/resources/AppendableResourceCollection.java
@@ -0,0 +1,38 @@
+/*
+ *  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
+ *
+ *      https://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.resources;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.ResourceCollection;
+
+/**
+ * Interface describing a collection of Resources, to which elements can be
+ * appended.
+ *
+ * @since Ant 1.10.10
+ */
+public interface AppendableResourceCollection extends ResourceCollection {
+    /**
+     Add a ResourceCollection to the container.
+     
+     @param c the ResourceCollection to add.
+     @throws BuildException on error.
+     @since Ant 1.10.10
+     */
+    void add(ResourceCollection c) throws BuildException;
+}
diff --git a/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java b/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java
index 2d87aa6..815a245 100644
--- a/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/ArchiveResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -103,12 +103,12 @@
     public void addConfigured(ResourceCollection a) {
         checkChildrenAllowed();
         if (archive != null) {
-            throw new BuildException("you must not specify more than one"
-                                     + " archive");
+            throw new BuildException(
+                "you must not specify more than one archive");
         }
         if (a.size() != 1) {
-            throw new BuildException("only single argument resource collections"
-                                     + " are supported as archives");
+            throw new BuildException(
+                "only single argument resource collections are supported as archives");
         }
         archive = a.iterator().next();
     }
@@ -118,17 +118,17 @@
      * @return the archive as a Resource.
      */
     public Resource getArchive() {
-        return isReference()
-            ? ((ArchiveResource) getCheckedRef()).getArchive() : archive;
+        return isReference() ? getRef().getArchive() : archive;
     }
 
     /**
      * Get the last modified date of this Resource.
      * @return the last modification date.
      */
+    @Override
     public long getLastModified() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getLastModified();
+            return getRef().getLastModified();
         }
         checkEntry();
         return super.getLastModified();
@@ -138,9 +138,10 @@
      * Get the size of this Resource.
      * @return the long size of this Resource.
      */
+    @Override
     public long getSize() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getSize();
+            return getRef().getSize();
         }
         checkEntry();
         return super.getSize();
@@ -150,9 +151,10 @@
      * Learn whether this Resource represents a directory.
      * @return boolean flag indicating whether the entry is a directory.
      */
+    @Override
     public boolean isDirectory() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).isDirectory();
+            return getRef().isDirectory();
         }
         checkEntry();
         return super.isDirectory();
@@ -162,9 +164,10 @@
      * Find out whether this Resource represents an existing Resource.
      * @return boolean existence flag.
      */
+    @Override
     public boolean isExists() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).isExists();
+            return getRef().isExists();
         }
         checkEntry();
         return super.isExists();
@@ -176,7 +179,7 @@
      */
     public int getMode() {
         if (isReference()) {
-            return ((ArchiveResource) getCheckedRef()).getMode();
+            return getRef().getMode();
         }
         checkEntry();
         return mode;
@@ -186,6 +189,7 @@
      * Overrides the super version.
      * @param r the Reference to set.
      */
+    @Override
     public void setRefid(Reference r) {
         if (archive != null || modeSet) {
             throw tooManyAttributes();
@@ -199,6 +203,7 @@
      * @return a negative integer, zero, or a positive integer as this Resource
      *         is less than, equal to, or greater than the specified Resource.
      */
+    @Override
     public int compareTo(Resource another) {
         return this.equals(another) ? 0 : super.compareTo(another);
     }
@@ -209,14 +214,15 @@
      * @return true if another is a Resource representing
      *              the same entry in the same archive.
      */
+    @Override
     public boolean equals(Object another) {
         if (this == another) {
             return true;
         }
         if (isReference()) {
-            return getCheckedRef().equals(another);
+            return getRef().equals(another);
         }
-        if (another == null || another.getClass() != getClass()) {
+        if (another == null || !another.getClass().equals(getClass())) {
             return false;
         }
         ArchiveResource r = (ArchiveResource) another;
@@ -228,6 +234,7 @@
      * Get the hash code for this Resource.
      * @return hash code as int.
      */
+    @Override
     public int hashCode() {
         return super.hashCode()
             * (getArchive() == null ? NULL_ARCHIVE : getArchive().hashCode());
@@ -237,8 +244,9 @@
      * Format this Resource as a String.
      * @return String representation of this Resource.
      */
+    @Override
     public String toString() {
-        return isReference() ? getCheckedRef().toString()
+        return isReference() ? getRef().toString()
             : getArchive().toString() + ':' + getName();
     }
 
@@ -260,10 +268,10 @@
             throw new BuildException("archive attribute not set");
         }
         if (!r.isExists()) {
-            throw new BuildException(r.toString() + " does not exist.");
+            throw new BuildException("%s does not exist.", r);
         }
         if (r.isDirectory()) {
-            throw new BuildException(r + " denotes a directory.");
+            throw new BuildException("%s denotes a directory.", r);
         }
         fetchEntry();
         haveEntry = true;
@@ -277,6 +285,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p) {
         if (isChecked()) {
             return;
@@ -290,4 +299,9 @@
             setChecked(true);
         }
     }
+
+    @Override
+    protected ArchiveResource getRef() {
+        return getCheckedRef(ArchiveResource.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/Archives.java b/src/main/org/apache/tools/ant/types/resources/Archives.java
index 24bfd28..56cf281 100644
--- a/src/main/org/apache/tools/ant/types/resources/Archives.java
+++ b/src/main/org/apache/tools/ant/types/resources/Archives.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Stack;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -31,7 +32,6 @@
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.TarFileSet;
 import org.apache.tools.ant.types.ZipFileSet;
-import org.apache.tools.ant.util.CollectionUtils;
 
 /**
  * A resource collection that treats all nested resources as archives
@@ -78,16 +78,13 @@
      *
      * @return int
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((Archives) getCheckedRef()).size();
+            return getRef().size();
         }
         dieOnCircularReference();
-        int total = 0;
-        for (final Iterator<ArchiveFileSet> i = grabArchives(); i.hasNext();) {
-            total += i.next().size();
-        }
-        return total;
+        return streamArchives().mapToInt(ArchiveFileSet::size).sum();
     }
 
     /**
@@ -97,15 +94,11 @@
      */
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((Archives) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         dieOnCircularReference();
-        final List<Resource> l = new LinkedList<Resource>();
-        for (final Iterator<ArchiveFileSet> i = grabArchives(); i.hasNext();) {
-            l.addAll(CollectionUtils
-                     .asCollection(i.next().iterator()));
-        }
-        return l.iterator();
+        return streamArchives().flatMap(ResourceCollection::stream)
+            .map(Resource.class::cast).iterator();
     }
 
     /**
@@ -113,9 +106,10 @@
      */
     public boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((Archives) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         dieOnCircularReference();
+        // TODO check each archive in turn?
         return false;
     }
 
@@ -126,8 +120,7 @@
      */
     @Override
     public void setRefid(final Reference r) {
-        if (zips.getResourceCollections().size() > 0
-            || tars.getResourceCollections().size() > 0) {
+        if (!zips.getResourceCollections().isEmpty() || !tars.getResourceCollections().isEmpty()) {
             throw tooManyAttributes();
         }
         super.setRefid(r);
@@ -160,14 +153,20 @@
      * @return Iterator&lt;ArchiveFileSet&gt;
      */
     protected Iterator<ArchiveFileSet> grabArchives() {
-        final List<ArchiveFileSet> l = new LinkedList<ArchiveFileSet>();
+        return streamArchives().iterator();
+    }
+
+    // TODO this is a pretty expensive operation and so the result
+    // should be cached.
+    private Stream<ArchiveFileSet> streamArchives() {
+        final List<ArchiveFileSet> l = new LinkedList<>();
         for (final Resource r : zips) {
             l.add(configureArchive(new ZipFileSet(), r));
         }
         for (final Resource r : tars) {
             l.add(configureArchive(new TarFileSet(), r));
         }
-        return l.iterator();
+        return l.stream();
     }
 
     /**
@@ -208,4 +207,8 @@
         }
     }
 
+    private Archives getRef() {
+        return getCheckedRef(Archives.class);
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/BCFileSet.java b/src/main/org/apache/tools/ant/types/resources/BCFileSet.java
index aa99a4a..7936690 100644
--- a/src/main/org/apache/tools/ant/types/resources/BCFileSet.java
+++ b/src/main/org/apache/tools/ant/types/resources/BCFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -47,9 +47,10 @@
      * @return an Iterator of Resources.
      * @since Ant 1.7
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((FileSet) getRef(getProject())).iterator();
+            return getRef().iterator();
         }
         FileResourceIterator result = new FileResourceIterator(getProject(), getDir());
         result.addFiles(getDirectoryScanner().getIncludedFiles());
@@ -62,12 +63,17 @@
      * @return number of elements as int.
      * @since Ant 1.7
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((FileSet) getRef(getProject())).size();
+            return getRef().size();
         }
         return getDirectoryScanner().getIncludedFilesCount()
             + getDirectoryScanner().getIncludedDirsCount();
     }
 
+    private FileSet getRef() {
+        return getCheckedRef(FileSet.class);
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/BZip2Resource.java b/src/main/org/apache/tools/ant/types/resources/BZip2Resource.java
index 3527bf3..29c9e56 100644
--- a/src/main/org/apache/tools/ant/types/resources/BZip2Resource.java
+++ b/src/main/org/apache/tools/ant/types/resources/BZip2Resource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -53,6 +53,7 @@
      * @return the wrapped stream.
      * @throws IOException if there is a problem.
      */
+    @Override
     protected InputStream wrapStream(InputStream in) throws IOException {
         for (char ch : MAGIC) {
             if (in.read() != ch) {
@@ -68,6 +69,7 @@
      * @return the wrapped stream.
      * @throws IOException if there is a problem.
      */
+    @Override
     protected OutputStream wrapStream(OutputStream out) throws IOException {
         for (char ch : MAGIC) {
             out.write(ch);
@@ -79,6 +81,7 @@
      * Get the name of the compression method.
      * @return the string "Bzip2".
      */
+    @Override
     protected String getCompressionName() {
         return "Bzip2";
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionContainer.java b/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionContainer.java
index c794aed..b066a5f 100644
--- a/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionContainer.java
+++ b/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionContainer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,6 +24,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Stack;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -36,8 +37,8 @@
  * @since Ant 1.7
  */
 public abstract class BaseResourceCollectionContainer
-        extends DataType implements ResourceCollection, Cloneable {
-    private List<ResourceCollection> rc = new ArrayList<ResourceCollection>();
+        extends DataType implements AppendableResourceCollection, Cloneable {
+    private List<ResourceCollection> rc = new ArrayList<>();
     private Collection<Resource> coll = null;
     private boolean cache = true;
 
@@ -45,7 +46,6 @@
      * Create a new BaseResourceCollectionContainer.
      */
     public BaseResourceCollectionContainer() {
-        // TODO Auto-generated constructor stub
     }
 
     /**
@@ -92,6 +92,7 @@
      * @param c the ResourceCollection to add.
      * @throws BuildException on error.
      */
+    @Override
     public synchronized void add(ResourceCollection c) throws BuildException {
         if (isReference()) {
             throw noChildrenAllowed();
@@ -121,9 +122,7 @@
             throw noChildrenAllowed();
         }
         try {
-            for (ResourceCollection resourceCollection : c) {
-                add(resourceCollection);
-            }
+            c.forEach(this::add);
         } catch (ClassCastException e) {
             throw new BuildException(e);
         }
@@ -135,9 +134,10 @@
      * are added to this container while the Iterator is in use.
      * @return a "fail-fast" Iterator.
      */
+    @Override
     public final synchronized Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((BaseResourceCollectionContainer) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         dieOnCircularReference();
         return new FailFast(this, cacheCollection().iterator());
@@ -147,9 +147,10 @@
      * Fulfill the ResourceCollection contract.
      * @return number of elements as int.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
-            return getCheckedRef(BaseResourceCollectionContainer.class, getDataTypeName()).size();
+            return getRef().size();
         }
         dieOnCircularReference();
         return cacheCollection().size();
@@ -159,27 +160,20 @@
      * Fulfill the ResourceCollection contract.
      * @return whether this is a filesystem-only resource collection.
      */
+    @Override
     public synchronized boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         dieOnCircularReference();
         //first the easy way, if all children are filesystem-only, return true:
-        boolean goEarly = true;
-        for (Iterator<ResourceCollection> i = rc.iterator(); goEarly && i.hasNext();) {
-            goEarly = i.next().isFilesystemOnly();
-        }
-        if (goEarly) {
+        if (rc.stream().allMatch(ResourceCollection::isFilesystemOnly)) {
             return true;
         }
         /* now check each Resource in case the child only
            lets through files from any children IT may have: */
-        for (Resource r : cacheCollection()) {
-            if (r.as(FileProvider.class) == null) {
-                return false;
-            }
-        }
-        return true;
+        return cacheCollection().stream()
+            .allMatch(r -> r.asOptional(FileProvider.class).isPresent());
     }
 
     /**
@@ -226,11 +220,12 @@
      * collections is shallowly cloned.
      * @return a cloned instance.
      */
+    @Override
     public Object clone() {
         try {
             BaseResourceCollectionContainer c
                 = (BaseResourceCollectionContainer) super.clone();
-            c.rc = new ArrayList<ResourceCollection>(rc);
+            c.rc = new ArrayList<>(rc);
             c.coll = null;
             return c;
         } catch (CloneNotSupportedException e) {
@@ -242,21 +237,20 @@
      * Format this BaseResourceCollectionContainer as a String.
      * @return a descriptive <code>String</code>.
      */
+    @Override
     public synchronized String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
-        if (cacheCollection().size() == 0) {
+        if (cacheCollection().isEmpty()) {
             return "";
         }
-        StringBuilder sb = new StringBuilder();
-        for (Resource resource : coll) {
-            if (sb.length() > 0) {
-                sb.append(File.pathSeparatorChar);
-            }
-            sb.append(resource);
-        }
-        return sb.toString();
+        return coll.stream().map(Object::toString)
+            .collect(Collectors.joining(File.pathSeparator));
+    }
+
+     private BaseResourceCollectionContainer getRef() {
+        return getCheckedRef(BaseResourceCollectionContainer.class);
     }
 
     private synchronized Collection<Resource> cacheCollection() {
diff --git a/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java b/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java
index 2734620..1aea45b 100644
--- a/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java
+++ b/src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionWrapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,10 +32,12 @@
 
     private Collection<Resource> coll = null;
 
+    @Override
     protected Iterator<Resource> createIterator() {
         return cacheCollection().iterator();
     }
 
+    @Override
     protected int getSize() {
         return cacheCollection().size();
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/CompressedResource.java b/src/main/org/apache/tools/ant/types/resources/CompressedResource.java
index 2c72c26..95610b3 100644
--- a/src/main/org/apache/tools/ant/types/resources/CompressedResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/CompressedResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -47,6 +47,7 @@
      * @return this Resource formatted as a String.
      * @since Ant 1.7
      */
+    @Override
     public String toString() {
         return getCompressionName() + " compressed " + super.toString();
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/ContentTransformingResource.java b/src/main/org/apache/tools/ant/types/resources/ContentTransformingResource.java
index 19e86b3..21b8690 100644
--- a/src/main/org/apache/tools/ant/types/resources/ContentTransformingResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/ContentTransformingResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,6 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * A resource that transforms the content of another resource.
@@ -58,9 +57,7 @@
     @Override
     public long getSize() {
         if (isExists()) {
-            InputStream in = null;
-            try {
-                in = getInputStream();
+            try (InputStream in = getInputStream()) {
                 final byte[] buf = new byte[BUFFER_SIZE];
                 int size = 0;
                 int readNow;
@@ -69,14 +66,11 @@
                 }
                 return size;
             } catch (final IOException ex) {
-                throw new BuildException("caught exception while reading "
-                                         + getName(), ex);
-            } finally {
-                FileUtils.close(in);
+                throw new BuildException(
+                    "caught exception while reading " + getName(), ex);
             }
-        } else {
-            return 0;
         }
+        return 0;
     }
 
     /**
@@ -120,24 +114,16 @@
     public <T> T as(final Class<T> clazz) {
         if (Appendable.class.isAssignableFrom(clazz)) {
             if (isAppendSupported()) {
-                final Appendable a =
-                    getResource().as(Appendable.class);
+                final Appendable a = getResource().as(Appendable.class);
                 if (a != null) {
-                    return clazz.cast(new Appendable() {
-                        public OutputStream getAppendOutputStream()
-                                throws IOException {
-                            OutputStream out = a.getAppendOutputStream();
-                            if (out != null) {
-                                out = wrapStream(out);
-                            }
-                            return out;
-                        }
+                    return clazz.cast((Appendable) () -> {
+                        OutputStream out = a.getAppendOutputStream();
+                        return out == null ? null : wrapStream(out);
                     });
                 }
             }
             return null;
         }
-
         return FileProvider.class.isAssignableFrom(clazz)
             ? null : getResource().as(clazz);
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/Difference.java b/src/main/org/apache/tools/ant/types/resources/Difference.java
index 3f3c983..ee61ca3 100644
--- a/src/main/org/apache/tools/ant/types/resources/Difference.java
+++ b/src/main/org/apache/tools/ant/types/resources/Difference.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,16 +38,17 @@
      * Calculate the difference of the nested ResourceCollections.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
         List<ResourceCollection> rcs = getResourceCollections();
         int size = rcs.size();
         if (size < 2) {
-            throw new BuildException("The difference of " + size
-                + " resource collection" + ((size == 1) ? "" : "s")
-                + " is undefined.");
+            throw new BuildException(
+                "The difference of %d resource %s is undefined.", size,
+                size == 1 ? "collection" : "collections");
         }
-        Set<Resource> hs = new HashSet<Resource>();
-        List<Resource> al = new ArrayList<Resource>();
+        Set<Resource> hs = new HashSet<>();
+        List<Resource> al = new ArrayList<>();
         for (ResourceCollection rc : rcs) {
             for (Resource r : rc) {
                 if (hs.add(r)) {
diff --git a/src/main/org/apache/tools/ant/types/resources/FailFast.java b/src/main/org/apache/tools/ant/types/resources/FailFast.java
index dc962bb..e9b3bf8 100644
--- a/src/main/org/apache/tools/ant/types/resources/FailFast.java
+++ b/src/main/org/apache/tools/ant/types/resources/FailFast.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,7 +32,7 @@
  * @since Ant 1.7
  */
 /*package-private*/ class FailFast implements Iterator<Resource> {
-    private static final WeakHashMap<Object, Set<FailFast>> MAP = new WeakHashMap<Object, Set<FailFast>>();
+    private static final WeakHashMap<Object, Set<FailFast>> MAP = new WeakHashMap<>();
 
     /**
      * Invalidate any in-use Iterators from the specified Object.
@@ -46,12 +46,7 @@
     }
 
     private static synchronized void add(FailFast f) {
-        Set<FailFast> s = MAP.get(f.parent);
-        if (s == null) {
-            s = new HashSet<FailFast>();
-            MAP.put(f.parent, s);
-        }
-        s.add(f);
+        MAP.computeIfAbsent(f.parent, k -> new HashSet<>()).add(f);
     }
 
     private static synchronized void remove(FailFast f) {
@@ -95,6 +90,7 @@
      * Fulfill the Iterator contract.
      * @return true if there are more elements.
      */
+    @Override
     public boolean hasNext() {
         if (wrapped == null) {
             return false;
@@ -108,6 +104,7 @@
      * @return the next element.
      * @throws NoSuchElementException if no more elements.
      */
+    @Override
     public Resource next() {
         if (wrapped == null || !wrapped.hasNext()) {
             throw new NoSuchElementException();
@@ -127,6 +124,7 @@
      * Fulfill the Iterator contract.
      * @throws UnsupportedOperationException always.
      */
+    @Override
     public void remove() {
         throw new UnsupportedOperationException();
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/FileProvider.java b/src/main/org/apache/tools/ant/types/resources/FileProvider.java
index aa28300..52f52a6 100644
--- a/src/main/org/apache/tools/ant/types/resources/FileProvider.java
+++ b/src/main/org/apache/tools/ant/types/resources/FileProvider.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/FileResource.java b/src/main/org/apache/tools/ant/types/resources/FileResource.java
index e967907..17ed7cc 100644
--- a/src/main/org/apache/tools/ant/types/resources/FileResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/FileResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,11 +18,10 @@
 package org.apache.tools.ant.types.resources;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -106,9 +105,10 @@
      * Get the file represented by this FileResource.
      * @return the File.
      */
+    @Override
     public File getFile() {
         if (isReference()) {
-            return ((FileResource) getCheckedRef()).getFile();
+            return getRef().getFile();
         }
         dieOnCircularReference();
         synchronized (this) {
@@ -139,7 +139,7 @@
      */
     public File getBaseDir() {
         if (isReference()) {
-            return ((FileResource) getCheckedRef()).getBaseDir();
+            return getRef().getBaseDir();
         }
         dieOnCircularReference();
         return baseDir;
@@ -149,6 +149,7 @@
      * Overrides the super version.
      * @param r the Reference to set.
      */
+    @Override
     public void setRefid(Reference r) {
         if (file != null || baseDir != null) {
             throw tooManyAttributes();
@@ -162,9 +163,10 @@
      * only will be returned.
      * @return the name of this resource.
      */
+    @Override
     public String getName() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getName();
+            return getRef().getName();
         }
         File b = getBaseDir();
         return b == null ? getNotNullFile().getName()
@@ -175,8 +177,9 @@
      * Learn whether this file exists.
      * @return true if this resource exists.
      */
+    @Override
     public boolean isExists() {
-        return isReference() ? ((Resource) getCheckedRef()).isExists()
+        return isReference() ? getRef().isExists()
             : getNotNullFile().exists();
     }
 
@@ -184,9 +187,10 @@
      * Get the modification time in milliseconds since 01.01.1970 .
      * @return 0 if the resource does not exist.
      */
+    @Override
     public long getLastModified() {
         return isReference()
-            ? ((Resource) getCheckedRef()).getLastModified()
+            ? getRef().getLastModified()
             : getNotNullFile().lastModified();
     }
 
@@ -194,8 +198,9 @@
      * Learn whether the resource is a directory.
      * @return boolean flag indicating if the resource is a directory.
      */
+    @Override
     public boolean isDirectory() {
-        return isReference() ? ((Resource) getCheckedRef()).isDirectory()
+        return isReference() ? getRef().isDirectory()
             : getNotNullFile().isDirectory();
     }
 
@@ -203,8 +208,9 @@
      * Get the size of this Resource.
      * @return the size, as a long, 0 if the Resource does not exist.
      */
+    @Override
     public long getSize() {
-        return isReference() ? ((Resource) getCheckedRef()).getSize()
+        return isReference() ? getRef().getSize()
             : getNotNullFile().length();
     }
 
@@ -213,10 +219,10 @@
      * @return an InputStream object.
      * @throws IOException if an error occurs.
      */
+    @Override
     public InputStream getInputStream() throws IOException {
-        return isReference()
-            ? ((Resource) getCheckedRef()).getInputStream()
-            : new FileInputStream(getNotNullFile());
+        return isReference() ? getRef().getInputStream()
+            : Files.newInputStream(getNotNullFile().toPath());
     }
 
     /**
@@ -227,9 +233,10 @@
      * @throws UnsupportedOperationException if OutputStreams are not
      *         supported for this Resource type.
      */
+    @Override
     public OutputStream getOutputStream() throws IOException {
         if (isReference()) {
-            return ((FileResource) getCheckedRef()).getOutputStream();
+            return getRef().getOutputStream();
         }
         return getOutputStream(false);
     }
@@ -237,9 +244,10 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public OutputStream getAppendOutputStream() throws IOException {
         if (isReference()) {
-            return ((FileResource) getCheckedRef()).getAppendOutputStream();
+            return getRef().getAppendOutputStream();
         }
         return getOutputStream(true);
     }
@@ -247,7 +255,8 @@
     private OutputStream getOutputStream(boolean append) throws IOException {
         File f = getNotNullFile();
         if (f.exists()) {
-            if (f.isFile() && !append) {
+            if (Files.isSymbolicLink(f.toPath()) && f.isFile() && !append) {
+                // https://bz.apache.org/bugzilla/show_bug.cgi?id=624
                 f.delete();
             }
         } else {
@@ -256,7 +265,7 @@
                 p.mkdirs();
             }
         }
-        return append ? new FileOutputStream(f.getAbsolutePath(), true) : new FileOutputStream(f);
+        return FileUtils.newOutputStream(f.toPath(), append);
     }
 
     /**
@@ -265,9 +274,10 @@
      * @return a negative integer, zero, or a positive integer as this FileResource
      *         is less than, equal to, or greater than the specified Resource.
      */
+    @Override
     public int compareTo(Resource another) {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).compareTo(another);
+            return getRef().compareTo(another);
         }
         if (this.equals(another)) {
             return 0;
@@ -294,12 +304,13 @@
      * @param another the other Object to compare.
      * @return true if another is a FileResource representing the same file.
      */
+    @Override
     public boolean equals(Object another) {
         if (this == another) {
             return true;
         }
         if (isReference()) {
-            return getCheckedRef().equals(another);
+            return getRef().equals(another);
         }
         if (another == null || !(another.getClass().equals(getClass()))) {
             return false;
@@ -314,9 +325,10 @@
      * Get the hash code for this Resource.
      * @return hash code as int.
      */
+    @Override
     public int hashCode() {
         if (isReference()) {
-            return getCheckedRef().hashCode();
+            return getRef().hashCode();
         }
         return MAGIC * (getFile() == null ? NULL_FILE : getFile().hashCode());
     }
@@ -325,9 +337,10 @@
      * Get the string representation of this Resource.
      * @return this FileResource formatted as a String.
      */
+    @Override
     public String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
         if (file == null) {
             return "(unbound file resource)";
@@ -340,9 +353,10 @@
      * Fulfill the ResourceCollection contract.
      * @return whether this Resource is a FileResource.
      */
+    @Override
     public boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((FileResource) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         dieOnCircularReference();
         return true;
@@ -352,9 +366,10 @@
      * Implement the Touchable interface.
      * @param modTime new last modification time.
      */
+    @Override
     public void touch(long modTime) {
         if (isReference()) {
-            ((FileResource) getCheckedRef()).touch(modTime);
+            getRef().touch(modTime);
             return;
         }
         if (!getNotNullFile().setLastModified(modTime)) {
@@ -383,6 +398,7 @@
      * @throws BuildException if desired
      * @since Ant1.8
      */
+    @Override
     public Resource getResource(String path) {
         File newfile = FILE_UTILS.resolveFile(getFile(), path);
         FileResource fileResource = new FileResource(newfile);
@@ -391,4 +407,9 @@
         }
         return fileResource;
     }
+
+    @Override
+    protected FileResource getRef() {
+        return getCheckedRef(FileResource.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/FileResourceIterator.java b/src/main/org/apache/tools/ant/types/resources/FileResourceIterator.java
index c1b5f7f..9cba71d 100644
--- a/src/main/org/apache/tools/ant/types/resources/FileResourceIterator.java
+++ b/src/main/org/apache/tools/ant/types/resources/FileResourceIterator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -117,6 +117,7 @@
      * Find out whether this FileResourceIterator has more elements.
      * @return whether there are more Resources to iterate over.
      */
+    @Override
     public boolean hasNext() {
         return pos < files.length;
     }
@@ -125,6 +126,7 @@
      * Get the next element from this FileResourceIterator.
      * @return the next Object.
      */
+    @Override
     public Resource next() {
         return nextResource();
     }
@@ -132,6 +134,7 @@
     /**
      * Not implemented.
      */
+    @Override
     public void remove() {
         throw new UnsupportedOperationException();
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/Files.java b/src/main/org/apache/tools/ant/types/resources/Files.java
index b341291..b7493f9 100644
--- a/src/main/org/apache/tools/ant/types/resources/Files.java
+++ b/src/main/org/apache/tools/ant/types/resources/Files.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -39,11 +40,8 @@
 public class Files extends AbstractSelectorContainer
     implements ResourceCollection {
 
-    private static final Iterator<Resource> EMPTY_ITERATOR
-        = Collections.<Resource>emptySet().iterator();
-
     private PatternSet defaultPatterns = new PatternSet();
-    private Vector<PatternSet> additionalPatterns = new Vector<PatternSet>();
+    private Vector<PatternSet> additionalPatterns = new Vector<>();
 
     private boolean useDefaultExcludes = true;
     private boolean caseSensitive = true;
@@ -82,6 +80,7 @@
      * @param r the <code>Reference</code> to use.
      * @throws BuildException if there is a problem.
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (hasPatterns(defaultPatterns)) {
             throw tooManyAttributes();
@@ -258,7 +257,7 @@
      * @return the defaultexclusions value.
      */
     public synchronized boolean getDefaultexcludes() {
-        return (isReference())
+        return isReference()
             ? getRef().getDefaultexcludes() : useDefaultExcludes;
     }
 
@@ -280,7 +279,7 @@
      * collection is case-sensitive.
      */
     public synchronized boolean isCaseSensitive() {
-        return (isReference())
+        return isReference()
             ? getRef().isCaseSensitive() : caseSensitive;
     }
 
@@ -302,7 +301,7 @@
      *         should be followed.
      */
     public synchronized boolean isFollowSymlinks() {
-        return (isReference())
+        return isReference()
             ? getRef().isFollowSymlinks() : followSymlinks;
     }
 
@@ -310,6 +309,7 @@
      * Fulfill the ResourceCollection contract.
      * @return an Iterator of Resources.
      */
+    @Override
     public synchronized Iterator<Resource> iterator() {
         if (isReference()) {
             return getRef().iterator();
@@ -319,7 +319,7 @@
         int fct = ds.getIncludedFilesCount();
         int dct = ds.getIncludedDirsCount();
         if (fct + dct == 0) {
-            return EMPTY_ITERATOR;
+            return Collections.emptyIterator();
         }
         FileResourceIterator result = new FileResourceIterator(getProject());
         if (fct > 0) {
@@ -335,6 +335,7 @@
      * Fulfill the ResourceCollection contract.
      * @return number of elements as int.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
             return getRef().size();
@@ -354,15 +355,8 @@
             return getRef().hasPatterns();
         }
         dieOnCircularReference();
-        if (hasPatterns(defaultPatterns)) {
-            return true;
-        }
-        for (PatternSet patternSet : additionalPatterns) {
-            if (hasPatterns(patternSet)) {
-                return true;
-            }
-        }
-        return false;
+        return hasPatterns(defaultPatterns)
+            || additionalPatterns.stream().anyMatch(this::hasPatterns);
     }
 
     /**
@@ -370,6 +364,7 @@
      *
      * @param selector the new <code>FileSelector</code> to add.
      */
+    @Override
     public synchronized void appendSelector(FileSelector selector) {
         if (isReference()) {
             throw noChildrenAllowed();
@@ -382,22 +377,13 @@
      * Format this Files collection as a String.
      * @return a descriptive <code>String</code>.
      */
+    @Override
     public String toString() {
         if (isReference()) {
             return getRef().toString();
         }
-        Iterator<Resource> i = iterator();
-        if (!i.hasNext()) {
-            return "";
-        }
-        StringBuffer sb = new StringBuffer();
-        while (i.hasNext()) {
-            if (sb.length() > 0) {
-                sb.append(File.pathSeparatorChar);
-            }
-            sb.append(i.next());
-        }
-        return sb.toString();
+        return isEmpty() ? "" : stream().map(Object::toString)
+            .collect(Collectors.joining(File.pathSeparator));
     }
 
     /**
@@ -405,13 +391,14 @@
      * (the list of selectors is a shallow clone of this instance's list).
      * @return a cloned Object.
      */
+    @Override
     public synchronized Object clone() {
         if (isReference()) {
             return getRef().clone();
         }
         Files f = (Files) super.clone();
         f.defaultPatterns = (PatternSet) defaultPatterns.clone();
-        f.additionalPatterns = new Vector<PatternSet>(additionalPatterns.size());
+        f.additionalPatterns = new Vector<>(additionalPatterns.size());
         for (PatternSet ps : additionalPatterns) {
             f.additionalPatterns.add((PatternSet) ps.clone());
         }
@@ -451,11 +438,7 @@
         dieOnCircularReference();
         PatternSet ps = new PatternSet();
         ps.append(defaultPatterns, p);
-        final int count = additionalPatterns.size();
-        for (int i = 0; i < count; i++) {
-            Object o = additionalPatterns.elementAt(i);
-            ps.append((PatternSet) o, p);
-        }
+        additionalPatterns.forEach(pat -> ps.append(pat, p));
         return ps;
     }
 
@@ -464,6 +447,7 @@
      * @return true indicating that all elements of a Files collection
      *              will be FileResources.
      */
+    @Override
     public boolean isFilesystemOnly() {
         return true;
     }
@@ -474,7 +458,7 @@
      * @return <code>FileCollection</code>.
      */
     protected Files getRef() {
-        return (Files) getCheckedRef();
+        return getCheckedRef(Files.class);
     }
 
     private synchronized void ensureDirectoryScannerSetup() {
diff --git a/src/main/org/apache/tools/ant/types/resources/First.java b/src/main/org/apache/tools/ant/types/resources/First.java
index ea9e7d0..22cab5f 100644
--- a/src/main/org/apache/tools/ant/types/resources/First.java
+++ b/src/main/org/apache/tools/ant/types/resources/First.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,8 @@
  */
 package org.apache.tools.ant.types.resources;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.types.Resource;
 
@@ -35,14 +33,10 @@
      * Take the first <code>count</code> elements.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
-        int ct = getValidCount();
-        Iterator<Resource> iter = getResourceCollection().iterator();
-        List<Resource> al = new ArrayList<Resource>(ct);
-        for (int i = 0; i < ct && iter.hasNext(); i++) {
-            al.add(iter.next());
-        }
-        return al;
+        return getResourceCollection().stream().limit(getValidCount())
+            .collect(Collectors.toList());
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/GZipResource.java b/src/main/org/apache/tools/ant/types/resources/GZipResource.java
index 3f95a69..707a20f 100644
--- a/src/main/org/apache/tools/ant/types/resources/GZipResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/GZipResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,8 @@
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
+import org.apache.tools.ant.types.ResourceCollection;
+
 /**
  * A GZip compressed resource.
  *
@@ -41,7 +43,7 @@
      * Constructor with another resource to wrap.
      * @param other the resource to wrap.
      */
-    public GZipResource(org.apache.tools.ant.types.ResourceCollection other) {
+    public GZipResource(ResourceCollection other) {
         super(other);
     }
 
@@ -51,6 +53,7 @@
      * @return the wrapped stream.
      * @throws IOException if there is a problem.
      */
+    @Override
     protected InputStream wrapStream(InputStream in) throws IOException {
         return new GZIPInputStream(in);
     }
@@ -61,7 +64,8 @@
      * @return the wrapped stream.
      * @throws IOException if there is a problem.
      */
-     protected OutputStream wrapStream(OutputStream out) throws IOException {
+    @Override
+    protected OutputStream wrapStream(OutputStream out) throws IOException {
         return new GZIPOutputStream(out);
     }
 
@@ -69,6 +73,7 @@
      * Get the name of the compression method.
      * @return the string "GZip".
      */
+    @Override
     protected String getCompressionName() {
         return "GZip";
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/ImmutableResourceException.java b/src/main/org/apache/tools/ant/types/resources/ImmutableResourceException.java
index 9dce715..599bfe0 100644
--- a/src/main/org/apache/tools/ant/types/resources/ImmutableResourceException.java
+++ b/src/main/org/apache/tools/ant/types/resources/ImmutableResourceException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/Intersect.java b/src/main/org/apache/tools/ant/types/resources/Intersect.java
index cdbeed0..945a15e 100644
--- a/src/main/org/apache/tools/ant/types/resources/Intersect.java
+++ b/src/main/org/apache/tools/ant/types/resources/Intersect.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,11 +22,14 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 
+
 /**
  * ResourceCollection representing the intersection
  * of multiple nested ResourceCollections.
@@ -38,27 +41,23 @@
      * Calculate the intersection of the nested ResourceCollections.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
         List<ResourceCollection> rcs = getResourceCollections();
         int size = rcs.size();
         if (size < 2) {
-            throw new BuildException("The intersection of " + size
-                + " resource collection" + ((size == 1) ? "" : "s")
-                + " is undefined.");
+            throw new BuildException(
+                "The intersection of %d resource %s is undefined.", size,
+                size == 1 ? "collection" : "collections");
         }
+
+        final Function<ResourceCollection, Set<Resource>> toSet =
+            c -> c.stream().collect(Collectors.toSet());
+
         Iterator<ResourceCollection> rc = rcs.iterator();
-        Set<Resource> s = new LinkedHashSet<Resource>(collect(rc.next()));
-        while (rc.hasNext()) {
-            s.retainAll(collect(rc.next()));
-        }
+        Set<Resource> s = new LinkedHashSet<>(toSet.apply(rc.next()));
+        rc.forEachRemaining(c -> s.retainAll(toSet.apply(c)));
         return s;
     }
 
-    private Set<Resource> collect(ResourceCollection rc) {
-        Set<Resource> result = new LinkedHashSet<Resource>();
-        for (Resource r : rc) {
-            result.add(r);
-        }
-        return result;
-    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java b/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java
index e8c8f02..c3e9258 100644
--- a/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/JavaConstantResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
 
 /**
  * A resource that is a java constant.
@@ -36,6 +37,7 @@
      * @return an open input stream for the resource
      * @throws IOException if an error occurs.
      */
+    @Override
     protected InputStream openInputStream(ClassLoader cl) throws IOException {
         String constant = getName();
         if (constant == null) {
@@ -46,7 +48,7 @@
             throw new IOException("No class name in " + constant);
         }
         String classname = constant.substring(0, index);
-        String fieldname = constant.substring(index + 1, constant.length());
+        String fieldname = constant.substring(index + 1);
         try {
             Class<?> clazz =
                 cl != null
@@ -54,7 +56,7 @@
                 : Class.forName(classname);
             Field field = clazz.getField(fieldname);
             String value = field.get(null).toString();
-            return new ByteArrayInputStream(value.getBytes("UTF-8"));
+            return new ByteArrayInputStream(value.getBytes(StandardCharsets.UTF_8));
         } catch (ClassNotFoundException e) {
             throw new IOException("Class not found:" + classname);
         } catch (NoSuchFieldException e) {
diff --git a/src/main/org/apache/tools/ant/types/resources/JavaResource.java b/src/main/org/apache/tools/ant/types/resources/JavaResource.java
index a927d3f..2603503 100644
--- a/src/main/org/apache/tools/ant/types/resources/JavaResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/JavaResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -79,20 +79,20 @@
      * Get the URL represented by this Resource.
      * @since Ant 1.8.0
      */
+    @Override
     public URL getURL() {
         if (isReference()) {
-            return ((JavaResource) getCheckedRef()).getURL();
+            return getRef().getURL();
         }
         AbstractClasspathResource.ClassLoaderWithFlag classLoader =
             getClassLoader();
         if (classLoader.getLoader() == null) {
             return ClassLoader.getSystemResource(getName());
-        } else {
-            try {
-                return classLoader.getLoader().getResource(getName());
-            } finally {
-                classLoader.cleanup();
-            }
+        }
+        try {
+            return classLoader.getLoader().getResource(getName());
+        } finally {
+            classLoader.cleanup();
         }
     }
 
@@ -103,9 +103,10 @@
      * JavaResource is less than, equal to, or greater than the
      * specified Resource.
      */
+    @Override
     public int compareTo(Resource another) {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).compareTo(another);
+            return getRef().compareTo(another);
         }
         if (another.getClass().equals(getClass())) {
             JavaResource otherjr = (JavaResource) another;
@@ -138,4 +139,8 @@
         return super.compareTo(another);
     }
 
+    @Override
+    protected JavaResource getRef() {
+        return getCheckedRef(JavaResource.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/Last.java b/src/main/org/apache/tools/ant/types/resources/Last.java
index 312271b..7e28d16 100644
--- a/src/main/org/apache/tools/ant/types/resources/Last.java
+++ b/src/main/org/apache/tools/ant/types/resources/Last.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,9 @@
  */
 package org.apache.tools.ant.types.resources;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -38,33 +37,29 @@
      * Take the last <code>count</code> elements.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
         int count = getValidCount();
         ResourceCollection rc = getResourceCollection();
-        int i = count;
-        Iterator<Resource> iter = rc.iterator();
         int size = rc.size();
-        for (; i < size; i++) {
-            iter.next();
-        }
+        int skip = Math.max(0, size - count);
 
-        List<Resource> al = new ArrayList<Resource>(count);
-        for (; iter.hasNext(); i++) {
-            al.add(iter.next());
-        }
-        int found = al.size();
+        List<Resource> result =
+            rc.stream().skip(skip).collect(Collectors.toList());
+
+        int found = result.size();
         if (found == count || (size < count && found == size)) {
-            return al;
+            return result;
         }
-
         //mismatch:
-        String msg = "Resource collection " + rc + " reports size " + size
-            + " but returns " + i + " elements.";
+        String msg = String.format(
+            "Resource collection %s reports size %d but returns %d elements.",
+            rc, size, found + skip);
 
         //size was understated -> too many results; warn and continue:
         if (found > count) {
             log(msg, Project.MSG_WARN);
-            return al.subList(found - count, found);
+            return result.subList(found - count, found);
         }
         //size was overstated; we missed some and are now in error-land:
         throw new BuildException(msg);
diff --git a/src/main/org/apache/tools/ant/types/resources/LazyResourceCollectionWrapper.java b/src/main/org/apache/tools/ant/types/resources/LazyResourceCollectionWrapper.java
index bdcc95d..b77d2d8 100644
--- a/src/main/org/apache/tools/ant/types/resources/LazyResourceCollectionWrapper.java
+++ b/src/main/org/apache/tools/ant/types/resources/LazyResourceCollectionWrapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.function.Supplier;
 
 import org.apache.tools.ant.types.Resource;
 
@@ -32,24 +33,23 @@
         AbstractResourceCollectionWrapper {
 
     /** List of cached resources */
-    private final List<Resource> cachedResources = new ArrayList<Resource>();
+    private final List<Resource> cachedResources = new ArrayList<>();
 
-    private FilteringIterator filteringIterator;
+    private Iterator<Resource> filteringIterator;
+
+    private final Supplier<Iterator<Resource>> filteringIteratorSupplier =
+        () -> new FilteringIterator(getResourceCollection().iterator());
 
     @Override
     protected Iterator<Resource> createIterator() {
-        Iterator<Resource> iterator;
         if (isCache()) {
             if (filteringIterator == null) {
                 // no worry of thread safety here, see function's contract
-                filteringIterator = new FilteringIterator(
-                        getResourceCollection().iterator());
+                filteringIterator = filteringIteratorSupplier.get();
             }
-            iterator = new CachedIterator(filteringIterator);
-        } else {
-            iterator = new FilteringIterator(getResourceCollection().iterator());
+            return new CachedIterator(filteringIterator);
         }
-        return iterator;
+        return filteringIteratorSupplier.get();
     }
 
     @Override
@@ -67,7 +67,7 @@
 
     /**
      * Specify if the resource should be filtered or not. This function should
-     * be overriden in order to define the filtering algorithm
+     * be overridden in order to define the filtering algorithm
      *
      * @param r resource considered for filtration
      * @return whether the resource should be filtered or not
@@ -84,10 +84,11 @@
 
         protected final Iterator<Resource> it;
 
-        public FilteringIterator(final Iterator<Resource> it) {
+        FilteringIterator(final Iterator<Resource> it) {
             this.it = it;
         }
 
+        @Override
         public boolean hasNext() {
             if (ended) {
                 return false;
@@ -105,6 +106,7 @@
             return true;
         }
 
+        @Override
         public Resource next() {
             if (!hasNext()) {
                 throw new UnsupportedOperationException();
@@ -114,9 +116,6 @@
             return r;
         }
 
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
     }
 
     /**
@@ -125,7 +124,7 @@
      */
     private class CachedIterator implements Iterator<Resource> {
 
-        int cusrsor = 0;
+        int cursor = 0;
 
         private final Iterator<Resource> it;
 
@@ -140,10 +139,11 @@
             this.it = it;
         }
 
+        @Override
         public boolean hasNext() {
             synchronized (cachedResources) {
                 // have we already cached the next entry ?
-                if (cachedResources.size() > cusrsor) {
+                if (cachedResources.size() > cursor) {
                     return true;
                 }
                 // does the wrapped iterator any more resource ?
@@ -157,6 +157,7 @@
             return true;
         }
 
+        @Override
         public Resource next() {
             // first check that we have some to deliver
             if (!hasNext()) {
@@ -165,10 +166,11 @@
             synchronized (cachedResources) {
                 // return the cached entry as hasNext should have put one for
                 // this iterator
-                return cachedResources.get(cusrsor++);
+                return cachedResources.get(cursor++);
             }
         }
 
+        @Override
         public void remove() {
             throw new UnsupportedOperationException();
         }
diff --git a/src/main/org/apache/tools/ant/types/resources/LogOutputResource.java b/src/main/org/apache/tools/ant/types/resources/LogOutputResource.java
index 9b48658..04ede6d 100644
--- a/src/main/org/apache/tools/ant/types/resources/LogOutputResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/LogOutputResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,6 +55,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public OutputStream getAppendOutputStream() throws IOException {
         return outputStream;
     }
@@ -62,6 +63,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public OutputStream getOutputStream() throws IOException {
         return outputStream;
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/MappedResource.java b/src/main/org/apache/tools/ant/types/resources/MappedResource.java
index c18cbf4..c6b167f 100644
--- a/src/main/org/apache/tools/ant/types/resources/MappedResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/MappedResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -108,7 +108,7 @@
     @Override
     public String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
         return getName();
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java b/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java
index 9df69cf..544c60b 100644
--- a/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java
+++ b/src/main/org/apache/tools/ant/types/resources/MappedResourceCollection.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,12 @@
 package org.apache.tools.ant.types.resources;
 
 import java.io.File;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.Objects;
 import java.util.Stack;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -122,10 +124,10 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((MappedResourceCollection) getCheckedRef())
-                .isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         checkInitialized();
         return false;
@@ -134,9 +136,10 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((MappedResourceCollection) getCheckedRef()).size();
+            return getRef().size();
         }
         checkInitialized();
         return cacheCollection().size();
@@ -145,9 +148,10 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((MappedResourceCollection) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         checkInitialized();
         return cacheCollection().iterator();
@@ -157,6 +161,7 @@
      * Overrides the base version.
      * @param r the Reference to set.
      */
+    @Override
     public void setRefid(Reference r) {
         if (nested != null || mapper != null) {
             throw tooManyAttributes();
@@ -168,6 +173,7 @@
      * Implement clone.  The nested resource collection and mapper are copied.
      * @return a cloned instance.
      */
+    @Override
     public Object clone() {
         try {
             MappedResourceCollection c =
@@ -188,6 +194,7 @@
      * @param p   the project to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -209,8 +216,9 @@
 
     private void checkInitialized() {
         if (nested == null) {
-            throw new BuildException("A nested resource collection element is"
-                                     + " required", getLocation());
+            throw new BuildException(
+                "A nested resource collection element is required",
+                getLocation());
         }
         dieOnCircularReference();
     }
@@ -223,46 +231,36 @@
     }
 
     private Collection<Resource> getCollection() {
-        Collection<Resource> collected = new ArrayList<Resource>();
         FileNameMapper m =
-            mapper != null ? mapper.getImplementation() : new IdentityMapper();
-        for (Resource r : nested) {
-            if (enableMultipleMappings) {
-                String[] n = m.mapFileName(r.getName());
-                if (n != null) {
-                    for (int i = 0; i < n.length; i++) {
-                        collected.add(new MappedResource(r,
-                                                         new MergingMapper(n[i]))
-                                      );
-                    }
-                }
-            } else {
-                collected.add(new MappedResource(r, m));
-            }
+            mapper == null ? new IdentityMapper() : mapper.getImplementation();
+
+        Stream<MappedResource> stream;
+        if (enableMultipleMappings) {
+            stream = nested.stream()
+                .flatMap(r -> Stream.of(m.mapFileName(r.getName()))
+                    .filter(Objects::nonNull)
+                    .map(MergingMapper::new)
+                    .map(mm -> new MappedResource(r, mm)));
+        } else {
+            stream = nested.stream().map(r -> new MappedResource(r, m));
         }
-        return collected;
+        return stream.collect(Collectors.toList());
     }
 
     /**
      * Format this resource collection as a String.
      * @return a descriptive <code>String</code>.
      */
+    @Override
     public String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
-        Iterator<Resource> i = iterator();
-        if (!i.hasNext()) {
-            return "";
-        }
-        StringBuffer sb = new StringBuffer();
-        while (i.hasNext()) {
-            if (sb.length() > 0) {
-                sb.append(File.pathSeparatorChar);
-            }
-            sb.append(i.next());
-        }
-        return sb.toString();
+        return isEmpty() ? "" : stream().map(Object::toString)
+            .collect(Collectors.joining(File.pathSeparator));
     }
 
+    private MappedResourceCollection getRef() {
+        return getCheckedRef(MappedResourceCollection.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/MultiRootFileSet.java b/src/main/org/apache/tools/ant/types/resources/MultiRootFileSet.java
index 1161558..d8a7c7f 100644
--- a/src/main/org/apache/tools/ant/types/resources/MultiRootFileSet.java
+++ b/src/main/org/apache/tools/ant/types/resources/MultiRootFileSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,7 +40,7 @@
 
     private SetType type = SetType.file;
     private boolean cache = true;
-    private List<File> baseDirs = new ArrayList<File>();
+    private List<File> baseDirs = new ArrayList<>();
     private Union union;
 
     @Override
@@ -79,9 +79,8 @@
         if (isReference()) {
             throw tooManyAttributes();
         }
-        if (dirs != null && dirs.length() > 0) {
-            final String[] ds = dirs.split(",");
-            for (final String d : ds) {
+        if (dirs != null && !dirs.isEmpty()) {
+            for (final String d : dirs.split(",")) {
                 baseDirs.add(getProject().resolveFile(d));
             }
         }
@@ -114,22 +113,22 @@
     @Override
     public Object clone() {
         if (isReference()) {
-            return ((MultiRootFileSet) getRef(getProject())).clone();
-        } else {
-            final MultiRootFileSet fs = (MultiRootFileSet) super.clone();
-            fs.baseDirs = new ArrayList<File>(baseDirs);
-            fs.union = null;
-            return fs;
+            return getRef().clone();
         }
+        final MultiRootFileSet fs = (MultiRootFileSet) super.clone();
+        fs.baseDirs = new ArrayList<>(baseDirs);
+        fs.union = null;
+        return fs;
     }
 
     /**
      * Fulfill the ResourceCollection contract.
      * @return an Iterator of Resources.
      */
+    @Override
     public Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((MultiRootFileSet) getRef(getProject())).iterator();
+            return getRef().iterator();
         }
         return merge().iterator();
     }
@@ -138,9 +137,10 @@
      * Fulfill the ResourceCollection contract.
      * @return number of elements as int.
      */
+    @Override
     public int size() {
         if (isReference()) {
-            return ((MultiRootFileSet) getRef(getProject())).size();
+            return getRef().size();
         }
         return merge().size();
     }
@@ -149,6 +149,7 @@
      * Always returns true.
      * @return true indicating that all elements will be FileResources.
      */
+    @Override
     public boolean isFilesystemOnly() {
         return true;
     }
@@ -161,11 +162,15 @@
     @Override
     public String toString() {
         if (isReference()) {
-            return ((MultiRootFileSet) getRef(getProject())).toString();
+            return getRef().toString();
         }
         return merge().toString();
     }
 
+    private MultiRootFileSet getRef() {
+        return getCheckedRef(MultiRootFileSet.class);
+    }
+
     private synchronized Union merge() {
         if (cache && union != null) {
             return union;
@@ -202,12 +207,14 @@
             setDir(dir);
         }
 
+        @Override
         public boolean isFilesystemOnly() {
             return true;
         }
 
+        @Override
         public Iterator<Resource> iterator() {
-            final DirectoryScanner ds = getDirectoryScanner(getProject());
+            final DirectoryScanner ds = getDirectoryScanner();
             String[] names = type == SetType.file
                 ? ds.getIncludedFiles()
                 : ds.getIncludedDirectories();
@@ -222,8 +229,9 @@
                                             names);
         }
 
+        @Override
         public int size() {
-            final DirectoryScanner ds = getDirectoryScanner(getProject());
+            final DirectoryScanner ds = getDirectoryScanner();
             int count = type == SetType.file
                 ? ds.getIncludedFilesCount()
                 : ds.getIncludedDirsCount();
diff --git a/src/main/org/apache/tools/ant/types/resources/PropertyResource.java b/src/main/org/apache/tools/ant/types/resources/PropertyResource.java
index a7cecb4..391f9bc 100644
--- a/src/main/org/apache/tools/ant/types/resources/PropertyResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/PropertyResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,6 +39,7 @@
         = Resource.getMagicNumber("PropertyResource".getBytes());
 
     private static final InputStream UNSET = new InputStream() {
+        @Override
         public int read() {
             return -1;
         }
@@ -66,7 +67,7 @@
      */
     public String getValue() {
         if (isReference()) {
-            return ((PropertyResource) getCheckedRef()).getValue();
+            return getRef().getValue();
         }
         Project p = getProject();
         return p == null ? null : p.getProperty(getName());
@@ -79,7 +80,7 @@
      */
     public Object getObjectValue() {
         if (isReference()) {
-            return ((PropertyResource) getCheckedRef()).getObjectValue();
+            return getRef().getObjectValue();
         }
         Project p = getProject();
         return p == null ? null : PropertyHelper.getProperty(p, getName());
@@ -89,6 +90,7 @@
      * Find out whether this Resource exists.
      * @return true if the Property is set, false otherwise.
      */
+    @Override
     public boolean isExists() {
         if (isReferenceOrProxy()) {
             return getReferencedOrProxied().isExists();
@@ -101,6 +103,7 @@
      * @return the size, as a long, 0 if the Resource does not exist (for
      *         compatibility with java.io.File), or UNKNOWN_SIZE if not known.
      */
+    @Override
     public long getSize() {
         if (isReferenceOrProxy()) {
             return getReferencedOrProxied().getSize();
@@ -115,17 +118,16 @@
      * @param o object to compare
      * @return true if equal to o
      */
+    @Override
     public boolean equals(Object o) {
-        if (super.equals(o)) {
-            return true;
-        }
-        return isReferenceOrProxy() && getReferencedOrProxied().equals(o);
+        return super.equals(o) || isReferenceOrProxy() && getReferencedOrProxied().equals(o);
     }
 
     /**
      * Get the hash code for this Resource.
      * @return hash code as int.
      */
+    @Override
     public int hashCode() {
         if (isReferenceOrProxy()) {
             return getReferencedOrProxied().hashCode();
@@ -136,6 +138,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public String toString() {
         if (isReferenceOrProxy()) {
             return getReferencedOrProxied().toString();
@@ -151,6 +154,7 @@
      * @throws UnsupportedOperationException if InputStreams are not
      *         supported for this Resource type.
      */
+    @Override
     public InputStream getInputStream() throws IOException {
         if (isReferenceOrProxy()) {
             return getReferencedOrProxied().getInputStream();
@@ -167,6 +171,7 @@
      * @throws UnsupportedOperationException if OutputStreams are not
      *         supported for this Resource type.
      */
+    @Override
     public OutputStream getOutputStream() throws IOException {
         if (isReferenceOrProxy()) {
             return getReferencedOrProxied().getOutputStream();
@@ -194,7 +199,7 @@
      */
     protected Resource getReferencedOrProxied() {
         if (isReference()) {
-            return (Resource) getCheckedRef(Resource.class, "resource");
+            return super.getRef();
         }
         Object o = getObjectValue();
         if (o instanceof Resource) {
@@ -203,4 +208,9 @@
         throw new IllegalStateException(
                 "This PropertyResource does not reference or proxy another Resource");
     }
+
+    @Override
+    protected PropertyResource getRef() {
+        return getCheckedRef(PropertyResource.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/ResourceDecorator.java b/src/main/org/apache/tools/ant/types/resources/ResourceDecorator.java
index 2d87fb1..bd72d55 100644
--- a/src/main/org/apache/tools/ant/types/resources/ResourceDecorator.java
+++ b/src/main/org/apache/tools/ant/types/resources/ResourceDecorator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -59,12 +59,12 @@
     public final void addConfigured(ResourceCollection a) {
         checkChildrenAllowed();
         if (resource != null) {
-            throw new BuildException("you must not specify more than one"
-                                     + " resource");
+            throw new BuildException(
+                "you must not specify more than one resource");
         }
         if (a.size() != 1) {
-            throw new BuildException("only single argument resource collections"
-                                     + " are supported");
+            throw new BuildException(
+                "only single argument resource collections are supported");
         }
         setChecked(false);
         resource = a.iterator().next();
@@ -205,7 +205,7 @@
      */
     protected final Resource getResource() {
         if (isReference()) {
-            return (Resource) getCheckedRef();
+            return getCheckedRef(Resource.class);
         }
         if (resource == null) {
             throw new BuildException("no resource specified");
@@ -238,6 +238,7 @@
      * @param name not used.
      * @throws BuildException always.
      */
+    @Override
     public void setName(String name) throws BuildException {
         throw new BuildException("you can't change the name of a "
                                  + getDataTypeName());
@@ -247,6 +248,7 @@
      * Set the exists attribute.
      * @param exists if true, this resource exists.
      */
+    @Override
     public void setExists(boolean exists) {
         throw new BuildException("you can't change the exists state of a "
                                  + getDataTypeName());
@@ -257,6 +259,7 @@
      * @param lastmodified not used.
      * @throws BuildException always.
      */
+    @Override
     public void setLastModified(long lastmodified) throws BuildException {
         throw new BuildException("you can't change the timestamp of a "
                                  + getDataTypeName());
@@ -267,6 +270,7 @@
      * @param directory not used.
      * @throws BuildException always.
      */
+    @Override
     public void setDirectory(boolean directory) throws BuildException {
         throw new BuildException("you can't change the directory state of a "
                                  + getDataTypeName());
@@ -277,6 +281,7 @@
      * @param size not used.
      * @throws BuildException always.
      */
+    @Override
     public void setSize(long size) throws BuildException {
         throw new BuildException("you can't change the size of a "
                                  + getDataTypeName());
diff --git a/src/main/org/apache/tools/ant/types/resources/ResourceList.java b/src/main/org/apache/tools/ant/types/resources/ResourceList.java
index 01adc53..9000af3 100644
--- a/src/main/org/apache/tools/ant/types/resources/ResourceList.java
+++ b/src/main/org/apache/tools/ant/types/resources/ResourceList.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Stack;
@@ -37,7 +38,6 @@
 import org.apache.tools.ant.types.Reference;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Reads a resource as text document and creates a resource for each
@@ -45,16 +45,12 @@
  * @since Ant 1.8.0
  */
 public class ResourceList extends DataType implements ResourceCollection {
-    private final Vector<FilterChain> filterChains = new Vector<FilterChain>();
-    private final ArrayList<ResourceCollection> textDocuments = new ArrayList<ResourceCollection>();
-    private final Union cachedResources = new Union();
-    private volatile boolean cached = false;
+    private final Vector<FilterChain> filterChains = new Vector<>();
+    private final ArrayList<ResourceCollection> textDocuments = new ArrayList<>();
+    private AppendableResourceCollection cachedResources = null;
     private String encoding = null;
     private File baseDir;
-
-    public ResourceList() {
-        cachedResources.setCache(true);
-    }
+    private boolean preserveDuplicates = false;
 
     /**
      * Adds a source.
@@ -88,8 +84,8 @@
      *
      * <p>
      * For a list of possible values see
-     * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">
-     * http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.
+     * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+     * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.
      * </p>
      *
      * @param encoding String
@@ -107,7 +103,7 @@
      * be considered relative to a certain base directory.
      *
      * @param baseDir the basedir
-     * @since Ant 1.9.12
+     * @since Ant 1.10.4
      */
     public final void setBasedir(File baseDir) {
         if (isReference()) {
@@ -117,16 +113,33 @@
     }
 
     /**
+     * Makes this <code>resourcelist</code> return all resources as
+     * many times as they are specified. Otherwise
+     * <code>resourcelist</code> will only return each resource, in the
+     * order they first appear.
+     *
+     * @param preserveDuplicates boolean
+     * @since Ant 1.10.10
+     */
+    public final void setPreserveDuplicates(boolean preserveDuplicates) {
+        if (isReference()) {
+            throw tooManyAttributes();
+        }
+        this.preserveDuplicates = preserveDuplicates;
+    }
+
+    /**
      * Makes this instance in effect a reference to another ResourceList
      * instance.
      *
      * @param r Reference
      */
+    @Override
     public void setRefid(Reference r) throws BuildException {
         if (encoding != null) {
             throw tooManyAttributes();
         }
-        if (filterChains.size() > 0 || textDocuments.size() > 0) {
+        if (!filterChains.isEmpty() || !textDocuments.isEmpty()) {
             throw noChildrenAllowed();
         }
         super.setRefid(r);
@@ -139,9 +152,10 @@
      *
      * @return a "fail-fast" Iterator.
      */
+    @Override
     public final synchronized Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((ResourceList) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         return cache().iterator();
     }
@@ -151,9 +165,10 @@
      *
      * @return number of elements as int.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
-            return ((ResourceList) getCheckedRef()).size();
+            return getRef().size();
         }
         return cache().size();
     }
@@ -163,9 +178,10 @@
      *
      * @return whether this is a filesystem-only resource collection.
      */
+    @Override
     public synchronized boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((ResourceList) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         return cache().isFilesystemOnly();
     }
@@ -178,6 +194,7 @@
      * @param p   the project to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -198,65 +215,62 @@
         }
     }
 
+    private ResourceList getRef() {
+        return getCheckedRef(ResourceList.class);
+    }
+
+    private AppendableResourceCollection newResourceCollection() {
+        if (preserveDuplicates) {
+            final Resources resources = new Resources();
+            resources.setCache(true);
+            return resources;
+        } else {
+            final Union union = new Union();
+            union.setCache(true);
+            return union;
+        }
+    }
+
     private synchronized ResourceCollection cache() {
-        if (!cached) {
+        if (cachedResources == null) {
             dieOnCircularReference();
-            for (ResourceCollection rc : textDocuments) {
-                for (Resource r : rc) {
-                    cachedResources.add(read(r));
-                }
-            }
-            cached = true;
+            this.cachedResources = newResourceCollection();
+            textDocuments.stream().flatMap(ResourceCollection::stream)
+                .map(this::read).forEach(cachedResources::add);
         }
         return cachedResources;
     }
 
     private ResourceCollection read(Resource r) {
-        BufferedInputStream bis = null;
-        try {
-            bis = new BufferedInputStream(r.getInputStream());
-            Reader input = null;
-            if (encoding == null) {
-                input = new InputStreamReader(bis);
-            } else {
-                input = new InputStreamReader(bis, encoding);
-            }
-            ChainReaderHelper crh = new ChainReaderHelper();
-            crh.setPrimaryReader(input);
-            crh.setFilterChains(filterChains);
-            crh.setProject(getProject());
-            Union streamResources = new Union();
-            BufferedReader reader = new BufferedReader(crh.getAssembledReader());
-            try {
-                streamResources.setCache(true);
-
-                String line = null;
-                while ((line = reader.readLine()) != null) {
-                    streamResources.add(parse(line));
-                }
-            } finally {
-                reader.close();
-            }
-
+        try (BufferedReader reader = new BufferedReader(open(r))) {
+            final AppendableResourceCollection streamResources = newResourceCollection();
+            reader.lines().map(this::parse).forEach(streamResources::add);
             return streamResources;
         } catch (final IOException ioe) {
             throw new BuildException("Unable to read resource " + r.getName()
                                      + ": " + ioe, ioe, getLocation());
-        } finally {
-            FileUtils.close(bis);
         }
     }
 
+    private Reader open(Resource r) throws IOException {
+        ChainReaderHelper crh = new ChainReaderHelper();
+        crh.setPrimaryReader(new InputStreamReader(
+            new BufferedInputStream(r.getInputStream()), encoding == null
+                ? Charset.defaultCharset() : Charset.forName(encoding)));
+        crh.setFilterChains(filterChains);
+        crh.setProject(getProject());
+        return crh.getAssembledReader();
+    }
+
     private Resource parse(final String line) {
-        PropertyHelper propertyHelper
-            = (PropertyHelper) PropertyHelper.getPropertyHelper(getProject());
+        PropertyHelper propertyHelper =
+            PropertyHelper.getPropertyHelper(getProject());
         Object expanded = propertyHelper.parseProperties(line);
         if (expanded instanceof Resource) {
             return (Resource) expanded;
         }
         String expandedLine = expanded.toString();
-        int colon = expandedLine.indexOf(":");
-        if (colon != -1) {
+        if (expandedLine.contains(":")) {
             // could be an URL or an absolute file on an OS with drives
             try {
                 return new URLResource(expandedLine);
@@ -274,4 +288,5 @@
         }
         return new FileResource(getProject(), expandedLine);
     }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/Resources.java b/src/main/org/apache/tools/ant/types/resources/Resources.java
index 1e029b2..b00f061 100644
--- a/src/main/org/apache/tools/ant/types/resources/Resources.java
+++ b/src/main/org/apache/tools/ant/types/resources/Resources.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,111 +20,109 @@
 
 import java.io.File;
 import java.util.AbstractCollection;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.Stack;
-import java.util.Vector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.DataType;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.util.CollectionUtils;
 
 /**
- * Generic ResourceCollection: Either stores nested ResourceCollections,
- * making no attempt to remove duplicates, or references another ResourceCollection.
+ * Generic {@link ResourceCollection}: Either stores nested {@link ResourceCollection}s,
+ * making no attempt to remove duplicates, or references another {@link ResourceCollection}.
  * @since Ant 1.7
  */
-public class Resources extends DataType implements ResourceCollection {
-    /** static empty ResourceCollection */
+public class Resources extends DataType implements AppendableResourceCollection {
+    /** {@code static} empty {@link ResourceCollection} */
     public static final ResourceCollection NONE = new ResourceCollection() {
+        @Override
         public boolean isFilesystemOnly() {
             return true;
         }
+        @Override
         public Iterator<Resource> iterator() {
             return EMPTY_ITERATOR;
         }
+        @Override
         public int size() {
             return 0;
         }
     };
 
-    /** static empty Iterator */
-    public static final Iterator<Resource> EMPTY_ITERATOR = new Iterator<Resource>() {
-        public Resource next() {
-            throw new NoSuchElementException();
-        }
-        public boolean hasNext() {
-            return false;
-        }
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    };
+    /** {@code static} empty {@link Iterator} */
+    public static final Iterator<Resource> EMPTY_ITERATOR = Collections.emptyIterator();
 
     private class MyCollection extends AbstractCollection<Resource> {
-        private Collection<Resource> cached;
+        private volatile Collection<Resource> cached;
 
-        MyCollection() {
-        }
+        @Override
         public int size() {
             return getCache().size();
         }
+        @Override
         public Iterator<Resource> iterator() {
             return getCache().iterator();
         }
         private synchronized Collection<Resource> getCache() {
-            Collection<Resource> coll = cached;
-            if (coll == null) {
-                coll = CollectionUtils.asCollection(new MyIterator());
-                if (cache) {
-                    cached = coll;
-                }
+            if (cached == null) {
+                cached = internalResources().collect(Collectors.toList());
             }
-            return coll;
-        }
-        private class MyIterator implements Iterator<Resource> {
-            private Iterator<ResourceCollection> rci = getNested().iterator();
-            private Iterator<Resource> ri = null;
-
-            public boolean hasNext() {
-                boolean result = ri != null && ri.hasNext();
-                while (!result && rci.hasNext()) {
-                    ri = ((ResourceCollection) rci.next()).iterator();
-                    result = ri.hasNext();
-                }
-                return result;
-            }
-            public Resource next() {
-                if (!hasNext()) {
-                    throw new NoSuchElementException();
-                }
-                return ri.next();
-            }
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
+            return cached;
         }
     }
 
-    private Vector<ResourceCollection> rc;
-    private Collection<Resource> coll;
-    private boolean cache = false;
+    private class MyIterator implements Iterator<Resource> {
+        private Iterator<ResourceCollection> rci = getNested().iterator();
+        private Iterator<Resource> ri;
+
+        @Override
+        public boolean hasNext() {
+            boolean result = ri != null && ri.hasNext();
+            while (!result && rci.hasNext()) {
+                ri = rci.next().iterator();
+                result = ri.hasNext();
+            }
+            return result;
+        }
+        @Override
+        public Resource next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            return ri.next();
+        }
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private List<ResourceCollection> rc;
+    private Optional<Collection<Resource>> cacheColl = Optional.empty();
+    private volatile boolean cache = false;
 
     /**
-     * Create a new Resources.
+     * Create a new {@link Resources}.
      */
     public Resources() {
     }
 
     /**
-     * Create a new Resources.
-     * @param project Project
+     * Create a new {@link Resources}.
+     * @param project {@link Project}
      * @since Ant 1.8
      */
     public Resources(Project project) {
@@ -133,17 +131,18 @@
 
     /**
      * Set whether to cache collections.
-     * @param b boolean cache flag.
+     * @param b {@code boolean} cache flag.
      * @since Ant 1.8.0
      */
-    public synchronized void setCache(boolean b) {
+    public void setCache(boolean b) {
         cache = b;
     }
 
     /**
-     * Add a ResourceCollection.
-     * @param c the ResourceCollection to add.
+     * Add a {@link ResourceCollection}.
+     * @param c the {@link ResourceCollection} to add.
      */
+    @Override
     public synchronized void add(ResourceCollection c) {
         if (isReference()) {
             throw noChildrenAllowed();
@@ -152,98 +151,84 @@
             return;
         }
         if (rc == null) {
-            rc = new Vector<ResourceCollection>();
+            rc = Collections.synchronizedList(new ArrayList<>());
         }
         rc.add(c);
         invalidateExistingIterators();
-        coll = null;
+        cacheColl = Optional.empty();
         setChecked(false);
     }
 
     /**
-     * Fulfill the ResourceCollection contract.
-     * @return an Iterator of Resources.
+     * Fulfill the {@link ResourceCollection} contract.
+     * @return an {@link Iterator} of {@link Resources}.
      */
+    @Override
     public synchronized Iterator<Resource> iterator() {
         if (isReference()) {
             return getRef().iterator();
         }
         validate();
-        return new FailFast(this, coll.iterator());
+        return new FailFast(this, cacheColl.map(Iterable::iterator).orElseGet(MyIterator::new));
     }
 
     /**
-     * Fulfill the ResourceCollection contract.
-     * @return number of elements as int.
+     * Fulfill the {@link ResourceCollection} contract.
+     * @return number of elements as {@code int}.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
             return getRef().size();
         }
         validate();
-        return coll.size();
+        return cacheColl.isPresent() ? cacheColl.get().size() : (int) internalResources().count();
     }
 
     /**
-     * Fulfill the ResourceCollection contract.
-     * @return true if all Resources represent files.
+     * Fulfill the {@link ResourceCollection} contract.
+     * @return {@code true} if all {@link Resource}s represent files.
      */
+    @Override
     public boolean isFilesystemOnly() {
         if (isReference()) {
             return getRef().isFilesystemOnly();
         }
         validate();
-
-        for (Iterator<ResourceCollection> i = getNested().iterator(); i.hasNext();) {
-            if (!i.next().isFilesystemOnly()) {
-                return false;
-            }
-        }
-        return true;
+        return getNested().stream().allMatch(ResourceCollection::isFilesystemOnly);
     }
 
     /**
-     * Format this <code>Resources</code> as a String.
+     * Format this <code>Resources</code> as a {@link String}.
      * @return a descriptive <code>String</code>.
      */
+    @Override
     public synchronized String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
         validate();
-        if (coll == null || coll.isEmpty()) {
-            return "";
-        }
-        StringBuffer sb = new StringBuffer();
-        for (Resource r : coll) {
-            if (sb.length() > 0) {
-                sb.append(File.pathSeparatorChar);
-            }
-            sb.append(r);
-        }
-        return sb.toString();
+        final Stream<?> stream = cache ? cacheColl.get().stream() : getNested().stream();
+        return stream.map(String::valueOf).collect(Collectors.joining(File.pathSeparator));
     }
 
     /**
-     * Overrides the version of DataType to recurse on all DataType
+     * Overrides the base implementation to recurse on all {@link DataType}
      * child elements that may have been added.
      * @param stk the stack of data types to use (recursively).
-     * @param p   the project to use to dereference the references.
+     * @param p   the {@link Project} to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
-        if (isChecked()) {
-            return;
-        }
         if (isReference()) {
             super.dieOnCircularReference(stk, p);
-        } else {
-            for (ResourceCollection resourceCollection : getNested()) {
-                if (resourceCollection instanceof DataType) {
-                    pushAndInvokeCircularReferenceCheck((DataType) resourceCollection, stk, p);
-                }
-            }
+            return;
+        }
+        if (!isChecked()) {
+            getNested().stream().filter(DataType.class::isInstance).map(DataType.class::cast)
+                .forEach(dt -> pushAndInvokeCircularReferenceCheck(dt, stk, p));
             setChecked(true);
         }
     }
@@ -256,20 +241,26 @@
     }
 
     /**
-     * Resolves references, allowing any ResourceCollection.
-     * @return the referenced ResourceCollection.
+     * Resolves references, allowing any {@link ResourceCollection}.
+     * @return the referenced {@link ResourceCollection}.
      */
     private ResourceCollection getRef() {
-        return (ResourceCollection) getCheckedRef(
-            ResourceCollection.class, "ResourceCollection");
+        return getCheckedRef(ResourceCollection.class);
     }
 
     private synchronized void validate() {
         dieOnCircularReference();
-        coll = (coll == null) ? new MyCollection() : coll;
+        if (cache && !cacheColl.isPresent()) {
+            cacheColl = Optional.of(new MyCollection());
+        }
     }
 
     private synchronized List<ResourceCollection> getNested() {
-        return rc == null ? Collections.<ResourceCollection> emptyList() : rc;
+        return rc == null ? Collections.emptyList() : rc;
+    }
+
+    private synchronized Stream<Resource> internalResources() {
+        return StreamSupport.stream(
+            Spliterators.spliteratorUnknownSize(new MyIterator(), Spliterator.NONNULL), false);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/Restrict.java b/src/main/org/apache/tools/ant/types/resources/Restrict.java
index 2ea1a86..e2acdb7 100644
--- a/src/main/org/apache/tools/ant/types/resources/Restrict.java
+++ b/src/main/org/apache/tools/ant/types/resources/Restrict.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,13 +39,9 @@
         /**
          * Restrict the nested ResourceCollection based on the nested selectors.
          */
+        @Override
         protected boolean filterResource(Resource r) {
-            for (Iterator<ResourceSelector> i = getSelectors(); i.hasNext();) {
-                if (!i.next().isSelected(r)) {
-                    return true;
-                }
-            }
-            return false;
+            return getResourceSelectors().stream().anyMatch(rsel -> !rsel.isSelected(r));
         }
     };
 
@@ -84,6 +80,7 @@
      * Add a ResourceSelector.
      * @param s the ResourceSelector to add.
      */
+    @Override
     public synchronized void add(ResourceSelector s) {
         if (s == null) {
             return;
@@ -96,9 +93,10 @@
      * Fulfill the ResourceCollection contract.
      * @return an Iterator of Resources.
      */
+    @Override
     public final synchronized Iterator<Resource> iterator() {
         if (isReference()) {
-            return ((Restrict) getCheckedRef()).iterator();
+            return getRef().iterator();
         }
         dieOnCircularReference();
         return w.iterator();
@@ -108,9 +106,10 @@
      * Fulfill the ResourceCollection contract.
      * @return number of elements as int.
      */
+    @Override
     public synchronized int size() {
         if (isReference()) {
-            return ((Restrict) getCheckedRef()).size();
+            return getRef().size();
         }
         dieOnCircularReference();
         return w.size();
@@ -120,9 +119,10 @@
      * Fulfill the ResourceCollection contract.
      * @return whether this is a filesystem-only resource collection.
      */
+    @Override
     public synchronized boolean isFilesystemOnly() {
         if (isReference()) {
-            return ((Restrict) getCheckedRef()).isFilesystemOnly();
+            return getRef().isFilesystemOnly();
         }
         dieOnCircularReference();
         return w.isFilesystemOnly();
@@ -132,14 +132,16 @@
      * Format this Restrict collection as a String.
      * @return the String value of this collection.
      */
+    @Override
     public synchronized String toString() {
         if (isReference()) {
-            return getCheckedRef().toString();
+            return getRef().toString();
         }
         dieOnCircularReference();
         return w.toString();
     }
 
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p) {
         if (isChecked()) {
             return;
@@ -153,4 +155,8 @@
             setChecked(true);
         }
     }
+
+    private Restrict getRef() {
+        return getCheckedRef(Restrict.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java b/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java
index 2992d5b..3ac3119 100644
--- a/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java
+++ b/src/main/org/apache/tools/ant/types/resources/SizeLimitCollection.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -50,10 +50,9 @@
      * Efficient size implementation.
      * @return int size
      */
+    @Override
     public synchronized int size() {
-        int sz = getResourceCollection().size();
-        int ct = getValidCount();
-        return sz < ct ? sz : ct;
+        return Math.min(getResourceCollection().size(), getValidCount());
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/resources/Sort.java b/src/main/org/apache/tools/ant/types/resources/Sort.java
index b4dc88c..46886d0 100644
--- a/src/main/org/apache/tools/ant/types/resources/Sort.java
+++ b/src/main/org/apache/tools/ant/types/resources/Sort.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,19 +18,15 @@
 package org.apache.tools.ant.types.resources;
 
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Stack;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.DataType;
 import org.apache.tools.ant.types.Resource;
-import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.resources.comparators.DelegatedResourceComparator;
 import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
-import org.apache.tools.ant.util.CollectionUtils;
 
 /**
  * ResourceCollection that sorts another ResourceCollection.
@@ -48,15 +44,10 @@
      * Sort the contained elements.
      * @return a Collection of Resources.
      */
+    @Override
     protected synchronized Collection<Resource> getCollection() {
-        ResourceCollection rc = getResourceCollection();
-        Iterator<Resource> iter = rc.iterator();
-        if (!(iter.hasNext())) {
-            return Collections.emptySet();
-        }
-        List<Resource> result = (List<Resource>) CollectionUtils.asCollection(iter);
-        Collections.sort(result, comp);
-        return result;
+        return getResourceCollection().stream().map(Resource.class::cast)
+            .sorted(comp).collect(Collectors.toList());
     }
 
     /**
@@ -80,6 +71,7 @@
      * @param p   the project to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
diff --git a/src/main/org/apache/tools/ant/types/resources/StringResource.java b/src/main/org/apache/tools/ant/types/resources/StringResource.java
index 9a52982..ede4154 100644
--- a/src/main/org/apache/tools/ant/types/resources/StringResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/StringResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -149,8 +149,8 @@
      */
     @Override
     public synchronized long getSize() {
-        return isReference() ? ((Resource) getCheckedRef()).getSize()
-                : getContent().length();
+        return isReference() ? getRef().getSize()
+            : getContent().length();
     }
 
     /**
@@ -161,7 +161,7 @@
     public synchronized int hashCode() { //NOSONAR
         // super.equals + super.compareTo are consistent with this implementation
         if (isReference()) {
-            return getCheckedRef().hashCode();
+            return getRef().hashCode();
         }
         return super.hashCode() * STRING_MAGIC;
     }
@@ -188,7 +188,7 @@
     @Override
     public synchronized InputStream getInputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getInputStream();
+            return getRef().getInputStream();
         }
         String content = getContent();
         if (content == null) {
@@ -209,7 +209,7 @@
     @Override
     public synchronized OutputStream getOutputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getOutputStream();
+            return getRef().getOutputStream();
         }
         if (getValue() != null) {
             throw new ImmutableResourceException();
@@ -237,19 +237,9 @@
         return getValue();
     }
 
-    /**
-     * This method is only for use by our private helper output stream.
-     * It contains specific logic for expanding properties.
-     * @param output the output
-     */
-    private void setValueFromOutputStream(String output) {
-        String value;
-        if (getProject() != null) {
-            value = getProject().replaceProperties(output);
-        } else {
-            value = output;
-        }
-        setValue(value);
+    @Override
+    protected StringResource getRef() {
+        return getCheckedRef(StringResource.class);
     }
 
     private class StringResourceFilterOutputStream extends FilterOutputStream {
@@ -266,7 +256,18 @@
             String result = encoding == null
                     ? baos.toString() : baos.toString(encoding);
 
-            StringResource.this.setValueFromOutputStream(result);
+            setValueFromOutputStream(result);
         }
+
+        private void setValueFromOutputStream(String output) {
+            String value;
+            if (getProject() != null) {
+                value = getProject().replaceProperties(output);
+            } else {
+                value = output;
+            }
+            setValue(value);
+        }
+
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/TarResource.java b/src/main/org/apache/tools/ant/types/resources/TarResource.java
index 3011406..2c44401 100644
--- a/src/main/org/apache/tools/ant/types/resources/TarResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/TarResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,8 +38,8 @@
 
     private String userName = "";
     private String groupName = "";
-    private int    uid;
-    private int    gid;
+    private long   uid;
+    private long   gid;
     private byte   linkFlag = TarConstants.LF_NORMAL;
     private String linkName = "";
 
@@ -77,13 +77,14 @@
      * @throws IOException if the tar file cannot be opened,
      *         or the entry cannot be read.
      */
+    @Override
     public InputStream getInputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getInputStream();
+            return getRef().getInputStream();
         }
         Resource archive = getArchive();
         final TarInputStream i = new TarInputStream(archive.getInputStream());
-        TarEntry te = null;
+        TarEntry te;
         while ((te = i.getNextEntry()) != null) {
             if (te.getName().equals(getName())) {
                 return i;
@@ -103,9 +104,10 @@
      * @throws UnsupportedOperationException if OutputStreams are not
      *         supported for this Resource type.
      */
+    @Override
     public OutputStream getOutputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getOutputStream();
+            return getRef().getOutputStream();
         }
         throw new UnsupportedOperationException(
             "Use the tar task for tar output.");
@@ -116,7 +118,7 @@
      */
     public String getUserName() {
         if (isReference()) {
-            return ((TarResource) getCheckedRef()).getUserName();
+            return getRef().getUserName();
         }
         checkEntry();
         return userName;
@@ -127,7 +129,7 @@
      */
     public String getGroup() {
         if (isReference()) {
-            return ((TarResource) getCheckedRef()).getGroup();
+            return getRef().getGroup();
         }
         checkEntry();
         return groupName;
@@ -135,29 +137,47 @@
 
     /**
      * @return the uid for the tar entry
+     * @since 1.10.4
      */
-    public int getUid() {
+    public long getLongUid() {
         if (isReference()) {
-            return ((TarResource) getCheckedRef()).getUid();
+            return getRef().getLongUid();
         }
         checkEntry();
         return uid;
     }
 
     /**
-     * @return the gid for the tar entry
+     * @return the uid for the tar entry
      */
-    public int getGid() {
+    @Deprecated
+    public int getUid() {
+        return (int) getLongUid();
+    }
+
+    /**
+     * @return the gid for the tar entry
+     * @since 1.10.4
+     */
+    public long getLongGid() {
         if (isReference()) {
-            return ((TarResource) getCheckedRef()).getGid();
+            return getRef().getLongGid();
         }
         checkEntry();
         return gid;
     }
 
     /**
+     * @return the uid for the tar entry
+     */
+    @Deprecated
+    public int getGid() {
+        return (int) getLongGid();
+    }
+
+    /**
      * @return the link "name" (=path) of this entry; an empty string if this is no link
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public String getLinkName() {
         return linkName;
@@ -165,7 +185,7 @@
 
     /**
      * @return the link "flag" (=type) of this entry
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public byte getLinkFlag() {
         return linkFlag;
@@ -174,11 +194,10 @@
     /**
      * fetches information from the named entry inside the archive.
      */
+    @Override
     protected void fetchEntry() {
         Resource archive = getArchive();
-        TarInputStream i = null;
-        try {
-            i = new TarInputStream(archive.getInputStream());
+        try (TarInputStream i = new TarInputStream(archive.getInputStream())) {
             TarEntry te = null;
             while ((te = i.getNextEntry()) != null) {
                 if (te.getName().equals(getName())) {
@@ -189,12 +208,15 @@
         } catch (IOException e) {
             log(e.getMessage(), Project.MSG_DEBUG);
             throw new BuildException(e);
-        } finally {
-            FileUtils.close(i);
         }
         setEntry(null);
     }
 
+    @Override
+    protected TarResource getRef() {
+        return getCheckedRef(TarResource.class);
+    }
+
     private void setEntry(TarEntry e) {
         if (e == null) {
             setExists(false);
@@ -208,8 +230,8 @@
         setMode(e.getMode());
         userName = e.getUserName();
         groupName = e.getGroupName();
-        uid = e.getUserId();
-        gid = e.getGroupId();
+        uid = e.getLongUserId();
+        gid = e.getLongGroupId();
         linkName = e.getLinkName();
         linkFlag = e.getLinkFlag();
     }
diff --git a/src/main/org/apache/tools/ant/types/resources/Tokens.java b/src/main/org/apache/tools/ant/types/resources/Tokens.java
index 458f8c1..387f8a3 100644
--- a/src/main/org/apache/tools/ant/types/resources/Tokens.java
+++ b/src/main/org/apache/tools/ant/types/resources/Tokens.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,11 @@
 
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 import java.util.Stack;
 
 import org.apache.tools.ant.BuildException;
@@ -31,7 +32,6 @@
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.util.ConcatResourceInputStream;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.LineTokenizer;
 import org.apache.tools.ant.util.Tokenizer;
 
@@ -51,38 +51,31 @@
      */
     protected synchronized Collection<Resource> getCollection() {
         ResourceCollection rc = getResourceCollection();
-        if (rc.size() == 0) {
+        if (rc.isEmpty()) {
             return Collections.emptySet();
         }
         if (tokenizer == null) {
             tokenizer = new LineTokenizer();
         }
-        ConcatResourceInputStream cat = new ConcatResourceInputStream(rc);
-        cat.setManagingComponent(this);
-
-        InputStreamReader rdr = null;
-        try {
-            if (encoding == null) {
-                rdr = new InputStreamReader(cat);
-            } else {
-                try {
-                    rdr = new InputStreamReader(cat, encoding);
-                } catch (UnsupportedEncodingException e) {
-                    throw new BuildException(e);
-                }
-            }
-            ArrayList<Resource> result = new ArrayList<Resource>();
-            for (String s = tokenizer.getToken(rdr); s != null; s = tokenizer.getToken(rdr)) {
-                StringResource resource = new StringResource(s);
+        try (ConcatResourceInputStream cat = new ConcatResourceInputStream(rc);
+                InputStreamReader rdr = new InputStreamReader(cat,
+                    encoding == null ? Charset.defaultCharset()
+                        : Charset.forName(encoding))) {
+            cat.setManagingComponent(this);
+            List<Resource> result = new ArrayList<>();
+            for (String s = tokenizer.getToken(rdr); s != null; s =
+                tokenizer.getToken(rdr)) {
+                // do not send the Project to the constructor of StringResource, since
+                // the semantics of that constructor clearly state that property value
+                // replacement takes place on the passed string value. We don't want
+                // that to happen.
+                final StringResource resource = new StringResource(s);
                 resource.setProject(getProject());
                 result.add(resource);
             }
             return result;
         } catch (IOException e) {
             throw new BuildException("Error reading tokens", e);
-        } finally {
-            FileUtils.close(rdr);
-            FileUtils.close(cat);
         }
     }
 
@@ -117,6 +110,7 @@
      * @param p   the project to use to dereference the references.
      * @throws BuildException on error.
      */
+    @Override
     protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
diff --git a/src/main/org/apache/tools/ant/types/resources/Touchable.java b/src/main/org/apache/tools/ant/types/resources/Touchable.java
index 3a54a69..c6d720d 100644
--- a/src/main/org/apache/tools/ant/types/resources/Touchable.java
+++ b/src/main/org/apache/tools/ant/types/resources/Touchable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/URLProvider.java b/src/main/org/apache/tools/ant/types/resources/URLProvider.java
index 81bb669..b8f029f 100644
--- a/src/main/org/apache/tools/ant/types/resources/URLProvider.java
+++ b/src/main/org/apache/tools/ant/types/resources/URLProvider.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/URLResource.java b/src/main/org/apache/tools/ant/types/resources/URLResource.java
index 643ec00..1772b45 100644
--- a/src/main/org/apache/tools/ant/types/resources/URLResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/URLResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -143,7 +143,7 @@
      */
     public synchronized URL getURL() {
         if (isReference()) {
-            return ((URLResource) getCheckedRef()).getURL();
+            return getRef().getURL();
         }
         if (url == null) {
             if (baseURL != null) {
@@ -180,10 +180,10 @@
      */
     public synchronized String getName() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getName();
+            return getRef().getName();
         }
         String name = getURL().getFile();
-        return "".equals(name) ? name : name.substring(1);
+        return name.isEmpty() ? name : name.substring(1);
     }
 
     /**
@@ -192,7 +192,7 @@
      */
     public synchronized String toString() {
         return isReference()
-            ? getCheckedRef().toString() : String.valueOf(getURL());
+            ? getRef().toString() : String.valueOf(getURL());
     }
 
     /**
@@ -201,7 +201,7 @@
      */
     public synchronized boolean isExists() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).isExists();
+            return getRef().isExists();
         }
         return isExists(false);
     }
@@ -262,16 +262,12 @@
      */
     public synchronized long getLastModified() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getLastModified();
+            return getRef().getLastModified();
         }
         if (!isExists(false)) {
             return UNKNOWN_DATETIME;
         }
-        return withConnection(new ConnectionUser() {
-                public long useConnection(URLConnection c) {
-                    return conn.getLastModified();
-                }
-            }, UNKNOWN_DATETIME);
+        return withConnection(c -> conn.getLastModified(), UNKNOWN_DATETIME);
     }
 
     /**
@@ -280,7 +276,7 @@
      */
     public synchronized boolean isDirectory() {
         return isReference()
-            ? ((Resource) getCheckedRef()).isDirectory()
+            ? getRef().isDirectory()
             : getName().endsWith("/");
     }
 
@@ -291,16 +287,12 @@
      */
     public synchronized long getSize() {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getSize();
+            return getRef().getSize();
         }
         if (!isExists(false)) {
             return 0L;
         }
-        return withConnection(new ConnectionUser() {
-                public long useConnection(URLConnection c) {
-                    return conn.getContentLength();
-                }
-            }, UNKNOWN_SIZE);
+        return withConnection(c -> conn.getContentLength(), UNKNOWN_SIZE);
     }
 
     /**
@@ -313,15 +305,15 @@
             return true;
         }
         if (isReference()) {
-            return getCheckedRef().equals(another);
+            return getRef().equals(another);
         }
         if (another == null || another.getClass() != getClass()) {
             return false;
         }
-        URLResource otheru = (URLResource) another;
+        URLResource other = (URLResource) another;
         return getURL() == null
-            ? otheru.getURL() == null
-            : getURL().equals(otheru.getURL());
+            ? other.getURL() == null
+            : getURL().equals(other.getURL());
     }
 
     /**
@@ -330,7 +322,7 @@
      */
     public synchronized int hashCode() {
         if (isReference()) {
-            return getCheckedRef().hashCode();
+            return getRef().hashCode();
         }
         return MAGIC * ((getURL() == null) ? NULL_URL : getURL().hashCode());
     }
@@ -345,7 +337,7 @@
      */
     public synchronized InputStream getInputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getInputStream();
+            return getRef().getInputStream();
         }
         connect();
         try {
@@ -366,7 +358,7 @@
      */
     public synchronized OutputStream getOutputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getOutputStream();
+            return getRef().getOutputStream();
         }
         connect();
         try {
@@ -409,6 +401,11 @@
         }
     }
 
+    @Override
+    protected URLResource getRef() {
+        return getCheckedRef(URLResource.class);
+    }
+
     /**
      * Closes the URL connection if:
      * - it is opened (i.e. the field conn is not null)
diff --git a/src/main/org/apache/tools/ant/types/resources/Union.java b/src/main/org/apache/tools/ant/types/resources/Union.java
index 5b07395..7cf71ee 100644
--- a/src/main/org/apache/tools/ant/types/resources/Union.java
+++ b/src/main/org/apache/tools/ant/types/resources/Union.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,12 +17,12 @@
  */
 package org.apache.tools.ant.types.resources;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.Resource;
@@ -82,10 +82,9 @@
      */
     public String[] list() {
         if (isReference()) {
-            return getCheckedRef(Union.class, getDataTypeName()).list();
+            return getRef().list();
         }
-        final Collection<String> result = getAllToStrings();
-        return result.toArray(new String[result.size()]);
+        return streamResources().map(Object::toString).toArray(String[]::new);
     }
 
     /**
@@ -94,16 +93,16 @@
      */
     public Resource[] listResources() {
         if (isReference()) {
-            return getCheckedRef(Union.class, getDataTypeName()).listResources();
+            return getRef().listResources();
         }
-        final Collection<Resource> result = getAllResources();
-        return result.toArray(new Resource[result.size()]);
+        return streamResources().toArray(Resource[]::new);
     }
 
     /**
      * Unify the contained Resources.
      * @return a Collection of Resources.
      */
+    @Override
     protected Collection<Resource> getCollection() {
         return getAllResources();
     }
@@ -118,7 +117,8 @@
     @Deprecated
     @SuppressWarnings("unchecked")
     protected <T> Collection<T> getCollection(boolean asString) { // TODO untypable
-        return asString ? (Collection<T>) getAllToStrings() : (Collection<T>) getAllResources();
+        return asString ? (Collection<T>) getAllToStrings()
+            : (Collection<T>) getAllResources();
     }
 
     /**
@@ -126,12 +126,8 @@
      * @return Collection&lt;String&gt;
      */
     protected Collection<String> getAllToStrings() {
-        final Set<Resource> allResources = getAllResources();
-        final ArrayList<String> result = new ArrayList<String>(allResources.size());
-        for (Resource r : allResources) {
-            result.add(r.toString());
-        }
-        return result;
+        return streamResources(Object::toString)
+            .collect(Collectors.toCollection(LinkedHashSet::new));
     }
 
     /**
@@ -139,19 +135,21 @@
      * @return Set&lt;Resource&gt;
      */
     protected Set<Resource> getAllResources() {
-        final List<ResourceCollection> resourceCollections = getResourceCollections();
-        if (resourceCollections.isEmpty()) {
-            return Collections.emptySet();
-        }
-        final LinkedHashSet<Resource> result = new LinkedHashSet<Resource>(
-                resourceCollections.size() * 2);
-        for (ResourceCollection resourceCollection : resourceCollections) {
-            for (Resource r : resourceCollection) {
-                result.add(r);
-            }
-        }
-        return result;
+        return streamResources()
+            .collect(Collectors.toCollection(LinkedHashSet::new));
     }
 
-}
+    private Union getRef() {
+        return getCheckedRef(Union.class);
+    }
 
+    private Stream<? extends Resource> streamResources() {
+        return streamResources(Function.identity());
+    }
+
+    private <T> Stream<? extends T> streamResources(
+        Function<? super Resource, ? extends T> mapper) {
+        return getResourceCollections().stream()
+            .flatMap(ResourceCollection::stream).map(mapper).distinct();
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/resources/ZipResource.java b/src/main/org/apache/tools/ant/types/resources/ZipResource.java
index 1dec546..bc84e81 100644
--- a/src/main/org/apache/tools/ant/types/resources/ZipResource.java
+++ b/src/main/org/apache/tools/ant/types/resources/ZipResource.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,7 +26,6 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.Reference;
-import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.zip.ZipEntry;
@@ -106,7 +105,7 @@
      */
     public String getEncoding() {
         return isReference()
-            ? ((ZipResource) getCheckedRef()).getEncoding() : encoding;
+            ? getRef().getEncoding() : encoding;
     }
 
     /**
@@ -128,28 +127,9 @@
      */
     public InputStream getInputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getInputStream();
+            return getRef().getInputStream();
         }
-        final ZipFile z = new ZipFile(getZipfile(), getEncoding());
-        ZipEntry ze = z.getEntry(getName());
-        if (ze == null) {
-            z.close();
-            throw new BuildException("no entry " + getName() + " in "
-                                     + getArchive());
-        }
-        return new FilterInputStream(z.getInputStream(ze)) {
-            public void close() throws IOException {
-                FileUtils.close(in);
-                z.close();
-            }
-            protected void finalize() throws Throwable {
-                try {
-                    close();
-                } finally {
-                    super.finalize();
-                }
-            }
-        };
+        return getZipEntryStream(new ZipFile(getZipfile(), getEncoding()), getName());
     }
 
     /**
@@ -162,7 +142,7 @@
      */
     public OutputStream getOutputStream() throws IOException {
         if (isReference()) {
-            return ((Resource) getCheckedRef()).getOutputStream();
+            return getRef().getOutputStream();
         }
         throw new UnsupportedOperationException(
             "Use the zip task for zip output.");
@@ -175,7 +155,7 @@
      */
     public ZipExtraField[] getExtraFields() {
         if (isReference()) {
-            return ((ZipResource) getCheckedRef()).getExtraFields();
+            return getRef().getExtraFields();
         }
         checkEntry();
         if (extras == null) {
@@ -194,6 +174,36 @@
     }
 
     /**
+     * Return an InputStream for reading the contents of a ZipEntry
+     * with autoclose.
+     * @param zipFile a org.apache.tools.zip.ZipFile
+     * @param zipEntry String a name of a zip entry
+     * @return an InputStream object
+     * @throws IOException if the entry cannot be read
+     */
+    public static InputStream getZipEntryStream(ZipFile zipFile,
+                                                String zipEntry) throws IOException {
+        ZipEntry ze = zipFile.getEntry(zipEntry);
+        if (ze == null) {
+            zipFile.close();
+            throw new BuildException("no entry " + zipEntry + " in " + zipFile.getName());
+        }
+        return new FilterInputStream(zipFile.getInputStream(ze)) {
+            public void close() throws IOException {
+                FileUtils.close(in);
+                zipFile.close();
+            }
+            protected void finalize() throws Throwable {
+                try {
+                    close();
+                } finally {
+                    super.finalize();
+                }
+            }
+        };
+    }
+
+    /**
      * fetches information from the named entry inside the archive.
      */
     protected void fetchEntry() {
@@ -209,6 +219,11 @@
         }
     }
 
+    @Override
+    protected ZipResource getRef() {
+        return getCheckedRef(ZipResource.class);
+    }
+
     private void setEntry(ZipEntry e) {
         if (e == null) {
             setExists(false);
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Content.java b/src/main/org/apache/tools/ant/types/resources/comparators/Content.java
index 07dd315..414a8bc 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Content.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Content.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Date.java b/src/main/org/apache/tools/ant/types/resources/comparators/Date.java
index b6be66b..765eb01 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Date.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Date.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,8 @@
  */
 package org.apache.tools.ant.types.resources.comparators;
 
+import java.util.Comparator;
+
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -32,14 +34,8 @@
      *         argument is less than, equal to, or greater than the second.
      */
     protected int resourceCompare(Resource foo, Resource bar) {
-        long diff = foo.getLastModified() - bar.getLastModified();
-        if (diff > 0) {
-            return +1;
-        } else if (diff < 0) {
-            return -1;
-        } else {
-            return 0;
-        }
+        return Comparator.comparingLong(Resource::getLastModified).compare(foo,
+            bar);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/DelegatedResourceComparator.java b/src/main/org/apache/tools/ant/types/resources/comparators/DelegatedResourceComparator.java
index aa2f55a..34069a9 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/DelegatedResourceComparator.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/DelegatedResourceComparator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,7 +17,7 @@
  */
 package org.apache.tools.ant.types.resources.comparators;
 
-import java.util.Iterator;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Stack;
 import java.util.Vector;
@@ -47,53 +47,48 @@
         if (c == null) {
             return;
         }
-        resourceComparators = (resourceComparators == null) ? new Vector<ResourceComparator>() : resourceComparators;
+        resourceComparators = (resourceComparators == null) ? new Vector<>() : resourceComparators;
         resourceComparators.add(c);
         setChecked(false);
     }
 
     /**
      * Equality method based on the vector of resources,
-     * or if a reference, the referredto object.
+     * or if a reference, the referred to object.
      * @param o the object to check against.
      * @return true if there is equality.
      */
+    @Override
     public synchronized boolean equals(Object o) {
         if (o == this) {
             return true;
         }
         if (isReference()) {
-            return getCheckedRef().equals(o);
+            return getRef().equals(o);
         }
-        if (!(o instanceof DelegatedResourceComparator)) {
-            return false;
+        if (o instanceof DelegatedResourceComparator) {
+            List<ResourceComparator> ov = ((DelegatedResourceComparator) o).resourceComparators;
+            return resourceComparators == null ? ov == null : resourceComparators.equals(ov);
         }
-        List<ResourceComparator> ov = ((DelegatedResourceComparator) o).resourceComparators;
-        return resourceComparators == null ? ov == null : resourceComparators.equals(ov);
+        return false;
     }
 
     /**
      * Hashcode based on the rules for equality.
      * @return a hashcode.
      */
+    @Override
     public synchronized int hashCode() {
         if (isReference()) {
-            return getCheckedRef().hashCode();
+            return getRef().hashCode();
         }
         return resourceComparators == null ? 0 : resourceComparators.hashCode();
     }
 
     /** {@inheritDoc} */
+    @Override
     protected synchronized int resourceCompare(Resource foo, Resource bar) {
-        //if no nested, natural order:
-        if (resourceComparators == null || resourceComparators.isEmpty()) {
-            return foo.compareTo(bar);
-        }
-        int result = 0;
-        for (Iterator<ResourceComparator> i = resourceComparators.iterator(); result == 0 && i.hasNext();) {
-            result = i.next().resourceCompare(foo, bar);
-        }
-        return result;
+        return composite(resourceComparators).compare(foo, bar);
     }
 
     /**
@@ -103,6 +98,7 @@
      * @param p   the Project to resolve against.
      * @throws BuildException on error.
      */
+    @Override
     protected void dieOnCircularReference(Stack<Object> stk, Project p)
         throws BuildException {
         if (isChecked()) {
@@ -111,15 +107,32 @@
         if (isReference()) {
             super.dieOnCircularReference(stk, p);
         } else {
-            if (!(resourceComparators == null || resourceComparators.isEmpty())) {
+            if (resourceComparators != null && !resourceComparators.isEmpty()) {
                 for (ResourceComparator resourceComparator : resourceComparators) {
                     if (resourceComparator instanceof DataType) {
-                        pushAndInvokeCircularReferenceCheck((DataType) resourceComparator, stk,
-                                                            p);
+                        pushAndInvokeCircularReferenceCheck(resourceComparator, stk, p);
                     }
                 }
             }
             setChecked(true);
         }
     }
+
+    private DelegatedResourceComparator getRef() {
+        return getCheckedRef(DelegatedResourceComparator.class);
+    }
+
+    private static Comparator<Resource> composite(List<? extends Comparator<Resource>> foo) {
+        Comparator<Resource> result = null;
+        if (foo != null) {
+            for (Comparator<Resource> comparator : foo) {
+                if (result == null) {
+                    result = comparator;
+                    continue;
+                }
+                result = result.thenComparing(comparator);
+            }
+        }
+        return result == null ? Comparator.naturalOrder() : result;
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Exists.java b/src/main/org/apache/tools/ant/types/resources/comparators/Exists.java
index 5832150..0f5d82a 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Exists.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Exists.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,8 @@
  */
 package org.apache.tools.ant.types.resources.comparators;
 
+import java.util.Comparator;
+
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -33,11 +35,7 @@
      *         argument is less than, equal to, or greater than the second.
      */
     protected int resourceCompare(Resource foo, Resource bar) {
-        boolean f = foo.isExists();
-        if (f == bar.isExists()) {
-            return 0;
-        }
-        return f ? 1 : -1;
+        return Comparator.comparing(Resource::isExists).compare(foo, bar);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/FileSystem.java b/src/main/org/apache/tools/ant/types/resources/comparators/FileSystem.java
index 7eafeb9..782bec1 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/FileSystem.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/FileSystem.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,9 @@
 package org.apache.tools.ant.types.resources.comparators;
 
 import java.io.File;
+import java.util.Comparator;
+import java.util.Objects;
+import java.util.function.Function;
 
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.resources.FileProvider;
@@ -36,25 +39,33 @@
      * @param bar the second Resource.
      * @return a negative integer, zero, or a positive integer as the first
      *         argument is less than, equal to, or greater than the second.
-     * @throws ClassCastException if either resource is not an instance of FileResource.
+     * @throws ClassCastException if either resource is not capable of
+     *         exposing a {@link FileProvider}
      */
     protected int resourceCompare(Resource foo, Resource bar) {
-        FileProvider fooFP = foo.as(FileProvider.class);
-        if (fooFP == null) {
-            throw new ClassCastException(foo.getClass()
-                                         + " doesn't provide files");
-        }
-        File foofile = fooFP.getFile();
-        FileProvider barFP = bar.as(FileProvider.class);
-        if (barFP == null) {
-            throw new ClassCastException(bar.getClass()
-                                         + " doesn't provide files");
-        }
-        File barfile = barFP.getFile();
-        return foofile.equals(barfile) ? 0
-            : FILE_UTILS.isLeadingPath(foofile, barfile) ? -1
-            : FILE_UTILS.normalize(foofile.getAbsolutePath()).compareTo(
-                FILE_UTILS.normalize(barfile.getAbsolutePath()));
+        return compare(file(foo), file(bar));
     }
 
+    private File file(Resource r) {
+        return r.asOptional(FileProvider.class)
+            .orElseThrow(() -> new ClassCastException(
+                r.getClass() + " doesn't provide files"))
+            .getFile();
+    }
+
+    private int compare(File f1, File f2) {
+        if (Objects.equals(f1, f2)) {
+            return 0;
+        }
+        if (FILE_UTILS.isLeadingPath(f1, f2)) {
+            return -1;
+        }
+        if (FILE_UTILS.isLeadingPath(f2, f1)) {
+            return 1;
+        }
+        return Comparator
+            .comparing(((Function<File, String>) File::getAbsolutePath)
+                .andThen(FILE_UTILS::normalize))
+            .compare(f1, f2);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Name.java b/src/main/org/apache/tools/ant/types/resources/comparators/Name.java
index d048ac0..b177aba 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Name.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Name.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/ResourceComparator.java b/src/main/org/apache/tools/ant/types/resources/comparators/ResourceComparator.java
index 3bfc9c7..acef707 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/ResourceComparator.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/ResourceComparator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,10 +36,10 @@
      *         argument is less than, equal to, or greater than the second.
      * @throws ClassCastException if either argument is null.
      */
+    @Override
     public final int compare(Resource foo, Resource bar) {
         dieOnCircularReference();
-        ResourceComparator c =
-            isReference() ? (ResourceComparator) getCheckedRef() : this;
+        ResourceComparator c = isReference() ? getRef() : this;
         return c.resourceCompare(foo, bar);
     }
 
@@ -48,23 +48,22 @@
      * @param o the Object to compare against.
      * @return true if the specified Object equals this one.
      */
+    @Override
     public boolean equals(Object o) {
         if (isReference()) {
-            return getCheckedRef().equals(o);
+            return getRef().equals(o);
         }
-        if (o == null) {
-            return false;
-        }
-        return o == this || o.getClass().equals(getClass());
+        return o != null && (o == this || o.getClass().equals(getClass()));
     }
 
     /**
      * Hashcode based on the rules for equality.
      * @return a hashcode.
      */
+    @Override
     public synchronized int hashCode() {
         if (isReference()) {
-            return getCheckedRef().hashCode();
+            return getRef().hashCode();
         }
         return getClass().hashCode();
     }
@@ -78,4 +77,7 @@
      */
     protected abstract int resourceCompare(Resource foo, Resource bar);
 
+    private ResourceComparator getRef() {
+        return getCheckedRef(ResourceComparator.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java b/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java
index 5da3ebb..d32cfa9 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,11 +17,12 @@
  */
 package org.apache.tools.ant.types.resources.comparators;
 
+import java.util.Comparator;
+import java.util.Optional;
 import java.util.Stack;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
-import org.apache.tools.ant.types.DataType;
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -69,8 +70,8 @@
      *         argument is greater than, equal to, or less than the second.
      */
     protected int resourceCompare(Resource foo, Resource bar) {
-        return -1 * (nested == null
-            ? foo.compareTo(bar) : nested.compare(foo, bar));
+        return Optional.<Comparator<Resource>> ofNullable(nested)
+            .orElseGet(Comparator::naturalOrder).reversed().compare(foo, bar);
     }
 
     protected void dieOnCircularReference(Stack<Object> stk, Project p)
@@ -82,10 +83,10 @@
             super.dieOnCircularReference(stk, p);
         } else {
             if (nested != null) {
-                pushAndInvokeCircularReferenceCheck((DataType) nested, stk,
-                                                    p);
+                pushAndInvokeCircularReferenceCheck(nested, stk, p);
             }
             setChecked(true);
         }
     }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Size.java b/src/main/org/apache/tools/ant/types/resources/comparators/Size.java
index b94f250..8638974 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Size.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Size.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,8 @@
  */
 package org.apache.tools.ant.types.resources.comparators;
 
+import java.util.Comparator;
+
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -32,8 +34,7 @@
      *         argument is less than, equal to, or greater than the second.
      */
     protected int resourceCompare(Resource foo, Resource bar) {
-        long diff = foo.getSize() - bar.getSize();
-        return diff > 0 ? 1 : (diff == 0 ? 0 : -1);
+        return Comparator.comparingLong(Resource::getSize).compare(foo, bar);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Type.java b/src/main/org/apache/tools/ant/types/resources/comparators/Type.java
index 6c082ef..65fe82a 100644
--- a/src/main/org/apache/tools/ant/types/resources/comparators/Type.java
+++ b/src/main/org/apache/tools/ant/types/resources/comparators/Type.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,8 @@
  */
 package org.apache.tools.ant.types.resources.comparators;
 
+import java.util.Comparator;
+
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -34,11 +36,7 @@
      *         argument is less than, equal to, or greater than the second.
      */
     protected int resourceCompare(Resource foo, Resource bar) {
-        boolean f = foo.isDirectory();
-        if (f == bar.isDirectory()) {
-            return 0;
-        }
-        return f ? 1 : -1;
+        return Comparator.comparing(Resource::isDirectory).compare(foo, bar);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/And.java b/src/main/org/apache/tools/ant/types/resources/selectors/And.java
index 409ed66..7292f4f 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/And.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/And.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,6 @@
  */
 package org.apache.tools.ant.types.resources.selectors;
 
-import java.util.Iterator;
-
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -37,7 +35,7 @@
      * Convenience constructor.
      * @param r the ResourceSelector[] to add.
      */
-    public And(ResourceSelector[] r) {
+    public And(ResourceSelector... r) {
         super(r);
     }
 
@@ -47,12 +45,7 @@
      * @return whether the Resource was selected.
      */
     public boolean isSelected(Resource r) {
-        for (Iterator<ResourceSelector> i = getSelectors(); i.hasNext();) {
-            if (!i.next().isSelected(r)) {
-                return false;
-            }
-        }
-        return true;
+        return getResourceSelectors().stream().allMatch(s -> s.isSelected(r));
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Compare.java b/src/main/org/apache/tools/ant/types/resources/selectors/Compare.java
index f345c27..ce879d8 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Compare.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Compare.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,9 +37,6 @@
  */
 public class Compare extends DataType implements ResourceSelector {
 
-    private static final String ONE_CONTROL_MESSAGE
-        = " the <control> element should be specified exactly once.";
-
     private DelegatedResourceComparator comp = new DelegatedResourceComparator();
     private Quantifier against = Quantifier.ALL;
 
@@ -103,7 +100,7 @@
     /** {@inheritDoc} */
     public synchronized boolean isSelected(Resource r) {
         if (isReference()) {
-            return ((ResourceSelector) getCheckedRef()).isSelected(r);
+            return getRef().isSelected(r);
         }
         if (control == null) {
             throw oneControl();
@@ -143,7 +140,12 @@
         }
     }
 
+    private ResourceSelector getRef() {
+        return getCheckedRef(ResourceSelector.class);
+    }
+
     private BuildException oneControl() {
-        return new BuildException(super.toString() + ONE_CONTROL_MESSAGE);
+        return new BuildException("%s the <control> element should be specified exactly once.",
+                super.toString());
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Date.java b/src/main/org/apache/tools/ant/types/resources/selectors/Date.java
index 0719a18..6356bf6 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Date.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Date.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -51,7 +51,7 @@
      * @param m the number of millis.
      */
     public synchronized void setMillis(long m) {
-        millis = new Long(m);
+        millis = m;
     }
 
     /**
@@ -59,7 +59,7 @@
      * @return long number of millis since 1970.
      */
     public synchronized long getMillis() {
-        return millis == null ? -1L : millis.longValue();
+        return millis == null ? -1L : millis;
     }
 
     /**
@@ -144,18 +144,18 @@
             try {
                 long m = df.parse(dateTime).getTime();
                 if (m < 0) {
-                    throw new BuildException("Date of " + dateTime
-                        + " results in negative milliseconds value"
-                        + " relative to epoch (January 1, 1970, 00:00:00 GMT).");
+                    throw new BuildException(
+                        "Date of %s results in negative milliseconds value relative to epoch (January 1, 1970, 00:00:00 GMT).",
+                        dateTime);
                 }
                 setMillis(m);
             } catch (ParseException pe) {
-                throw new BuildException("Date of " + dateTime
-                        + " Cannot be parsed correctly. It should be in '"
-                        + p + "' format.");
+                throw new BuildException(
+                    "Date of %s Cannot be parsed correctly. It should be in '%s' format.",
+                    dateTime, p);
             }
         }
-        return when.evaluate(r.getLastModified(), millis.longValue(), granularity);
+        return when.evaluate(r.getLastModified(), millis, granularity);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Exists.java b/src/main/org/apache/tools/ant/types/resources/selectors/Exists.java
index 1b498bc..7050a25 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Exists.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Exists.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/InstanceOf.java b/src/main/org/apache/tools/ant/types/resources/selectors/InstanceOf.java
index 39b3108..f5f2200 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/InstanceOf.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/InstanceOf.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -110,13 +110,12 @@
         if (type != null) {
             if (project == null) {
                 throw new BuildException(
-                    "No project set for InstanceOf ResourceSelector; "
-                    + "the type attribute is invalid.");
+                    "No project set for InstanceOf ResourceSelector; the type attribute is invalid.");
             }
             AntTypeDefinition d = ComponentHelper.getComponentHelper(
                 project).getDefinition(ProjectHelper.genComponentName(uri, type));
             if (d == null) {
-                throw new BuildException("type " + type + " not found.");
+                throw new BuildException("type %s not found.",type);
             }
             try {
                 c = d.innerGetTypeClass();
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Majority.java b/src/main/org/apache/tools/ant/types/resources/selectors/Majority.java
index 5a7a95c..f85d0dc 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Majority.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Majority.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,16 +17,14 @@
  */
 package org.apache.tools.ant.types.resources.selectors;
 
-import java.util.Iterator;
-
 import org.apache.tools.ant.types.Resource;
 
 /**
  * Majority ResourceSelector.
  * @since Ant 1.7
  */
-public class Majority
-    extends ResourceSelectorContainer implements ResourceSelector {
+public class Majority extends ResourceSelectorContainer
+    implements ResourceSelector {
 
     private boolean tie = true;
 
@@ -40,7 +38,7 @@
      * Convenience constructor.
      * @param r the ResourceSelector[] to add.
      */
-    public Majority(ResourceSelector[] r) {
+    public Majority(ResourceSelector... r) {
         super(r);
     }
 
@@ -64,8 +62,8 @@
         boolean even = count % 2 == 0;
         int threshold = count / 2;
 
-        for (Iterator<ResourceSelector> i = getSelectors(); i.hasNext();) {
-            if (i.next().isSelected(r)) {
+        for (ResourceSelector rs : getResourceSelectors()) {
+            if (rs.isSelected(r)) {
                 ++passed;
                 if (passed > threshold || (even && tie && passed == threshold)) {
                     return true;
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Name.java b/src/main/org/apache/tools/ant/types/resources/selectors/Name.java
index 5a4da15..c887748 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Name.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Name.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -126,20 +126,19 @@
             return true;
         }
         String s = r.toString();
-        return s.equals(n) ? false : matches(s);
+        return !s.equals(n) && matches(s);
     }
 
     private boolean matches(String name) {
         if (pattern != null) {
             return SelectorUtils.match(modify(pattern), modify(name), cs);
-        } else {
-            if (reg == null) {
-                reg = new RegularExpression();
-                reg.setPattern(regex);
-                expression = reg.getRegexp(project);
-            }
-            return expression.matches(modify(name), RegexpUtil.asOptions(cs));
         }
+        if (reg == null) {
+            reg = new RegularExpression();
+            reg.setPattern(regex);
+            expression = reg.getRegexp(project);
+        }
+        return expression.matches(modify(name), RegexpUtil.asOptions(cs));
     }
 
     private String modify(String s) {
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/None.java b/src/main/org/apache/tools/ant/types/resources/selectors/None.java
index 0de8623..d38bc6f 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/None.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/None.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,6 @@
  */
 package org.apache.tools.ant.types.resources.selectors;
 
-import java.util.Iterator;
-
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -38,7 +36,7 @@
      * Convenience constructor.
      * @param r the ResourceSelector[] to add.
      */
-    public None(ResourceSelector[] r) {
+    public None(ResourceSelector... r) {
         super(r);
     }
 
@@ -48,12 +46,7 @@
      * @return whether the Resource was selected.
      */
     public boolean isSelected(Resource r) {
-        for (Iterator<ResourceSelector> i = getSelectors(); i.hasNext();) {
-            if (i.next().isSelected(r)) {
-                return false;
-            }
-        }
-        return true;
+        return getResourceSelectors().stream().noneMatch(s -> s.isSelected(r));
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Not.java b/src/main/org/apache/tools/ant/types/resources/selectors/Not.java
index dc67da1..5b1eb7b 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Not.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Not.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Or.java b/src/main/org/apache/tools/ant/types/resources/selectors/Or.java
index b22303a..979ddc8 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Or.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Or.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,6 @@
  */
 package org.apache.tools.ant.types.resources.selectors;
 
-import java.util.Iterator;
-
 import org.apache.tools.ant.types.Resource;
 
 /**
@@ -37,7 +35,7 @@
      * Convenience constructor.
      * @param r the ResourceSelector[] to add.
      */
-    public Or(ResourceSelector[] r) {
+    public Or(ResourceSelector... r) {
         super(r);
     }
 
@@ -47,12 +45,7 @@
      * @return whether the Resource was selected.
      */
     public boolean isSelected(Resource r) {
-        for (Iterator<ResourceSelector> i = getSelectors(); i.hasNext();) {
-            if (i.next().isSelected(r)) {
-                return true;
-            }
-        }
-        return false;
+        return getResourceSelectors().stream().anyMatch(s -> s.isSelected(r));
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java b/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java
index 37151ec..c210d17 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelectorContainer.java b/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelectorContainer.java
index 19e0140..ee78728 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelectorContainer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,7 +33,7 @@
  */
 public class ResourceSelectorContainer extends DataType {
 
-    private final List<ResourceSelector> resourceSelectors = new ArrayList<ResourceSelector>();
+    private final List<ResourceSelector> resourceSelectors = new ArrayList<>();
 
     /**
      * Default constructor.
@@ -43,11 +43,11 @@
 
     /**
      * Construct a new ResourceSelectorContainer with the specified array of selectors.
-     * @param rs the ResourceSelector[] to add.
+     * @param resourceSelectors the ResourceSelector[] to add.
      */
-    public ResourceSelectorContainer(ResourceSelector[] rs) {
-        for (int i = 0; i < rs.length; i++) {
-            add(rs[i]);
+    public ResourceSelectorContainer(ResourceSelector... resourceSelectors) {
+        for (ResourceSelector rsel : resourceSelectors) {
+            add(rsel);
         }
     }
 
@@ -72,7 +72,7 @@
      */
     public boolean hasSelectors() {
         if (isReference()) {
-            return ((ResourceSelectorContainer) getCheckedRef()).hasSelectors();
+            return getRef().hasSelectors();
         }
         dieOnCircularReference();
         return !resourceSelectors.isEmpty();
@@ -84,7 +84,7 @@
      */
     public int selectorCount() {
         if (isReference()) {
-            return ((ResourceSelectorContainer) getCheckedRef()).selectorCount();
+            return getRef().selectorCount();
         }
         dieOnCircularReference();
         return resourceSelectors.size();
@@ -96,10 +96,21 @@
      */
     public Iterator<ResourceSelector> getSelectors() {
         if (isReference()) {
-            return ((ResourceSelectorContainer) getCheckedRef()).getSelectors();
+            return getRef().getSelectors();
+        }
+        return getResourceSelectors().iterator();
+    }
+
+    /**
+     * Get the configured {@link ResourceSelector}s as a {@link List}.
+     * @return {@link List} of {@link ResourceSelector}
+     */
+    public List<ResourceSelector> getResourceSelectors() {
+        if (isReference()) {
+            return getRef().getResourceSelectors();
         }
         dieOnCircularReference();
-        return Collections.unmodifiableList(resourceSelectors).iterator();
+        return Collections.unmodifiableList(resourceSelectors);
     }
 
     /**
@@ -125,4 +136,7 @@
         }
     }
 
+    private ResourceSelectorContainer getRef() {
+        return getCheckedRef(ResourceSelectorContainer.class);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Size.java b/src/main/org/apache/tools/ant/types/resources/selectors/Size.java
index 4d6c87e..baeb6df 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Size.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Size.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/resources/selectors/Type.java b/src/main/org/apache/tools/ant/types/resources/selectors/Type.java
index 65d4a57..d08916a 100644
--- a/src/main/org/apache/tools/ant/types/resources/selectors/Type.java
+++ b/src/main/org/apache/tools/ant/types/resources/selectors/Type.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
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..8ebad85 100644
--- a/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,13 @@
 
 package org.apache.tools.ant.types.selectors;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Stack;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -36,18 +40,20 @@
 public abstract class AbstractSelectorContainer extends DataType
     implements Cloneable, SelectorContainer {
 
-    private Vector<FileSelector> selectorsList = new Vector<FileSelector>();
+    private List<FileSelector> selectorsList =
+        Collections.synchronizedList(new ArrayList<>());
 
     /**
      * Indicates whether there are any selectors here.
      * @return true if there are selectors
      */
+    @Override
     public boolean hasSelectors() {
         if (isReference()) {
-            return ((AbstractSelectorContainer) getCheckedRef()).hasSelectors();
+            return getRef().hasSelectors();
         }
         dieOnCircularReference();
-        return !(selectorsList.isEmpty());
+        return !selectorsList.isEmpty();
     }
 
     /**
@@ -56,7 +62,7 @@
      */
     public int selectorCount() {
         if (isReference()) {
-            return ((AbstractSelectorContainer) getCheckedRef()).selectorCount();
+            return getRef().selectorCount();
         }
         dieOnCircularReference();
         return selectorsList.size();
@@ -69,13 +75,10 @@
      */
     public FileSelector[] getSelectors(Project p) {
         if (isReference()) {
-            return ((AbstractSelectorContainer) getCheckedRef(p))
-                .getSelectors(p);
+            return getRef(p).getSelectors(p);
         }
         dieOnCircularReference(p);
-        FileSelector[] result = new FileSelector[selectorsList.size()];
-        selectorsList.copyInto(result);
-        return result;
+        return selectorsList.toArray(new FileSelector[0]);
     }
 
     /**
@@ -84,11 +87,10 @@
      */
     public Enumeration<FileSelector> selectorElements() {
         if (isReference()) {
-            return ((AbstractSelectorContainer) getCheckedRef())
-                .selectorElements();
+            return getRef().selectorElements();
         }
         dieOnCircularReference();
-        return selectorsList.elements();
+        return Collections.enumeration(selectorsList);
     }
 
     /**
@@ -99,18 +101,8 @@
      * @return comma separated list of Selectors contained in this one
      */
     public String toString() {
-        StringBuilder buf = new StringBuilder();
-        Enumeration<FileSelector> e = selectorElements();
-        if (e.hasMoreElements()) {
-            while (e.hasMoreElements()) {
-                buf.append(e.nextElement().toString());
-                if (e.hasMoreElements()) {
-                    buf.append(", ");
-                }
-            }
-        }
-
-        return buf.toString();
+        return selectorsList.stream().map(Object::toString)
+            .collect(Collectors.joining(", "));
     }
 
     /**
@@ -122,7 +114,7 @@
         if (isReference()) {
             throw noChildrenAllowed();
         }
-        selectorsList.addElement(selector);
+        selectorsList.add(selector);
         setChecked(false);
     }
 
@@ -144,16 +136,11 @@
      */
     public void validate() {
         if (isReference()) {
-            ((AbstractSelectorContainer) getCheckedRef()).validate();
+            getRef().validate();
         }
         dieOnCircularReference();
-        Enumeration<FileSelector> e = selectorElements();
-        while (e.hasMoreElements()) {
-            Object o = e.nextElement();
-            if (o instanceof BaseSelector) {
-                ((BaseSelector) o).validate();
-            }
-        }
+        selectorsList.stream().filter(BaseSelector.class::isInstance)
+            .map(BaseSelector.class::cast).forEach(BaseSelector::validate);
     }
 
 
@@ -313,6 +300,46 @@
     }
 
     /**
+     * @param e ExecutableSelector
+     * @since 1.10.0
+     */
+    public void addExecutable(ExecutableSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @param e SymlinkSelector
+     * @since 1.10.0
+     */
+    public void addSymlink(SymlinkSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @param o OwnedBySelector
+     * @since 1.10.0
+     */
+    public void addOwnedBy(OwnedBySelector o) {
+        appendSelector(o);
+    }
+
+    /**
+     * @param o PosixGroupSelector
+     * @since 1.10.4
+     */
+    public void addPosixGroup(PosixGroupSelector o) {
+        appendSelector(o);
+    }
+
+    /**
+     * @param o PosixPermissionsSelector
+     * @since 1.10.4
+     */
+    public void addPosixPermissions(PosixPermissionsSelector o) {
+        appendSelector(o);
+    }
+
+    /**
      * add an arbitrary selector
      * @param selector the selector to add
      * @since Ant 1.6
@@ -337,17 +364,31 @@
         }
     }
 
+    /**
+     * Clone the selector container.
+     * @return a deep clone of a selector container.
+     */
     public synchronized Object clone() {
         if (isReference()) {
-            return ((AbstractSelectorContainer) getCheckedRef()).clone();
+            return getRef().clone();
         }
         try {
             AbstractSelectorContainer sc =
                 (AbstractSelectorContainer) super.clone();
-            sc.selectorsList = new Vector<FileSelector>(selectorsList);
+            sc.selectorsList = new Vector<>(selectorsList);
             return sc;
         } catch (CloneNotSupportedException e) {
             throw new BuildException(e);
         }
     }
+
+
+    private AbstractSelectorContainer getRef(Project p) {
+        return getCheckedRef(AbstractSelectorContainer.class, getDataTypeName(), p);
+    }
+
+    private AbstractSelectorContainer getRef() {
+        return getCheckedRef(AbstractSelectorContainer.class);
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/AndSelector.java b/src/main/org/apache/tools/ant/types/selectors/AndSelector.java
index c8e96a0..b8ef846 100644
--- a/src/main/org/apache/tools/ant/types/selectors/AndSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/AndSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.stream.Stream;
 
 /**
  * This selector has a collection of other selectors, all of which have to
@@ -30,12 +30,6 @@
 public class AndSelector extends BaseSelectorContainer {
 
     /**
-     * Default constructor.
-     */
-    public AndSelector() {
-    }
-
-    /**
      * @return a string representation of the selector
      */
     public String toString() {
@@ -60,14 +54,8 @@
      */
     public boolean isSelected(File basedir, String filename, File file) {
         validate();
-        Enumeration<FileSelector> e = selectorElements();
-
-        while (e.hasMoreElements()) {
-            if (!e.nextElement().isSelected(basedir, filename, file)) {
-                return false;
-            }
-        }
-        return true;
+        return Stream.of(getSelectors(getProject()))
+            .allMatch(s -> s.isSelected(basedir, filename, file));
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseExtendSelector.java b/src/main/org/apache/tools/ant/types/selectors/BaseExtendSelector.java
index f17ca02..3ceb641 100644
--- a/src/main/org/apache/tools/ant/types/selectors/BaseExtendSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/BaseExtendSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,9 +30,8 @@
  *
  * @since 1.5
  */
-public abstract class BaseExtendSelector
-        extends BaseSelector
-        implements ExtendFileSelector {
+public abstract class BaseExtendSelector extends BaseSelector
+    implements ExtendFileSelector {
 
     // CheckStyle:VisibilityModifier OFF - bc
 
@@ -42,18 +41,13 @@
     // CheckStyle:VisibilityModifier ON
 
     /**
-     * Default constructor.
-     */
-    public BaseExtendSelector() {
-    }
-
-    /**
      * Set all the Parameters for this custom selector, collected by
      * the ExtendSelector class.
      *
      * @param parameters the complete set of parameters for this selector
      */
-    public void setParameters(Parameter[] parameters) {
+    @Override
+    public void setParameters(Parameter... parameters) {
         this.parameters = parameters;
     }
 
diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java b/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java
index 28e0556..79650a3 100644
--- a/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,12 +37,6 @@
     private Throwable cause;
 
     /**
-     * Do nothing constructor.
-     */
-    public BaseSelector() {
-    }
-
-    /**
      * Allows all selectors to indicate a setup error. Note that only
      * the first error message is recorded.
      *
@@ -77,7 +71,6 @@
         return errmsg;
     }
 
-
     /**
      * <p>Subclasses can override this method to provide checking of their
      * state. So long as they call validate() from isSelected(), this will
@@ -87,11 +80,10 @@
      */
     public void verifySettings() {
         if (isReference()) {
-            ((BaseSelector) getCheckedRef()).verifySettings();
+            getRef().verifySettings();
         }
     }
 
-
     /**
      * Subclasses can use this to throw the requisite exception
      * in isSelected() in the case of an error condition.
@@ -122,6 +114,9 @@
     public abstract boolean isSelected(File basedir, String filename,
                                        File file);
 
+    private BaseSelector getRef() {
+        return getCheckedRef(BaseSelector.class);
+    }
 }
 
 
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..fcf4413 100644
--- a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,9 +19,12 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Stack;
-import java.util.Vector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -36,13 +39,7 @@
 public abstract class BaseSelectorContainer extends BaseSelector
         implements SelectorContainer {
 
-    private Vector<FileSelector> selectorsList = new Vector<FileSelector>();
-
-    /**
-     * Default constructor.
-     */
-    public BaseSelectorContainer() {
-    }
+    private List<FileSelector> selectorsList = Collections.synchronizedList(new ArrayList<>());
 
     /**
      * Indicates whether there are any selectors here.
@@ -50,7 +47,7 @@
      */
     public boolean hasSelectors() {
         dieOnCircularReference();
-        return !(selectorsList.isEmpty());
+        return !selectorsList.isEmpty();
     }
 
     /**
@@ -69,9 +66,7 @@
      */
     public FileSelector[] getSelectors(Project p) {
         dieOnCircularReference();
-        FileSelector[] result = new FileSelector[selectorsList.size()];
-        selectorsList.copyInto(result);
-        return result;
+        return selectorsList.toArray(new FileSelector[0]);
     }
 
     /**
@@ -80,7 +75,7 @@
      */
     public Enumeration<FileSelector> selectorElements() {
         dieOnCircularReference();
-        return selectorsList.elements();
+        return Collections.enumeration(selectorsList);
     }
 
     /**
@@ -92,15 +87,8 @@
      */
     public String toString() {
         dieOnCircularReference();
-        StringBuilder buf = new StringBuilder();
-        Enumeration<FileSelector> e = selectorElements();
-        while (e.hasMoreElements()) {
-            buf.append(e.nextElement().toString());
-            if (e.hasMoreElements()) {
-                buf.append(", ");
-            }
-        }
-        return buf.toString();
+        return selectorsList.stream().map(Object::toString)
+            .collect(Collectors.joining(", "));
     }
 
     /**
@@ -109,7 +97,7 @@
      * @param selector the new selector to add
      */
     public void appendSelector(FileSelector selector) {
-        selectorsList.addElement(selector);
+        selectorsList.add(selector);
         setChecked(false);
     }
 
@@ -136,16 +124,10 @@
         if (errmsg != null) {
             throw new BuildException(errmsg);
         }
-        Enumeration<FileSelector> e = selectorElements();
-        while (e.hasMoreElements()) {
-            Object o = e.nextElement();
-            if (o instanceof BaseSelector) {
-                ((BaseSelector) o).validate();
-            }
-        }
+        selectorsList.stream().filter(BaseSelector.class::isInstance)
+            .map(BaseSelector.class::cast).forEach(BaseSelector::validate);
     }
 
-
     /**
      * Method that each selector will implement to create their selection
      * behaviour. This is what makes SelectorContainer abstract.
@@ -157,8 +139,7 @@
      * @return whether the file should be selected or not
      */
     public abstract boolean isSelected(File basedir, String filename,
-                                       File file);
-
+        File file);
 
     /* Methods below all add specific selectors */
 
@@ -316,6 +297,46 @@
     }
 
     /**
+     * @param e ExecutableSelector
+     * @since 1.10.0
+     */
+    public void addExecutable(ExecutableSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @param e SymlinkSelector
+     * @since 1.10.0
+     */
+    public void addSymlink(SymlinkSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @param o OwnedBySelector
+     * @since 1.10.0
+     */
+    public void addOwnedBy(OwnedBySelector o) {
+        appendSelector(o);
+    }
+
+    /**
+     * @param o PosixGroupSelector
+     * @since 1.10.4
+     */
+    public void addPosixGroup(PosixGroupSelector o) {
+        appendSelector(o);
+    }
+
+    /**
+     * @param o PosixPermissionsSelector
+     * @since 1.10.4
+     */
+    public void addPosixPermissions(PosixPermissionsSelector 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/ContainsRegexpSelector.java b/src/main/org/apache/tools/ant/types/selectors/ContainsRegexpSelector.java
index 5b03e53..82f3f8b 100644
--- a/src/main/org/apache/tools/ant/types/selectors/ContainsRegexpSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/ContainsRegexpSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,12 +41,6 @@
 public class ContainsRegexpSelector extends BaseExtendSelector
         implements ResourceSelector {
 
-    private String userProvidedExpression = null;
-    private RegularExpression myRegExp = null;
-    private Regexp myExpression = null;
-    private boolean caseSensitive = true;
-    private boolean multiLine = false;
-    private boolean singleLine = false;
     /** Key to used for parameterized custom selector */
     public static final String EXPRESSION_KEY = "expression";
     /** Parameter name for the casesensitive attribute. */
@@ -56,21 +50,19 @@
     /** Parameter name for the singleline attribute. */
     private static final String SL_KEY = "singleline";
 
-    /**
-     * Creates a new <code>ContainsRegexpSelector</code> instance.
-     */
-    public ContainsRegexpSelector() {
-    }
+    private String userProvidedExpression = null;
+    private RegularExpression myRegExp = null;
+    private Regexp myExpression = null;
+    private boolean caseSensitive = true;
+    private boolean multiLine = false;
+    private boolean singleLine = false;
 
     /**
      * @return a string describing this object
      */
     public String toString() {
-        StringBuilder buf = new StringBuilder(
-                "{containsregexpselector expression: ");
-        buf.append(userProvidedExpression);
-        buf.append("}");
-        return buf.toString();
+        return String.format("{containsregexpselector expression: %s}",
+            userProvidedExpression);
     }
 
     /**
@@ -116,7 +108,7 @@
      *
      * @param parameters the complete set of parameters for this selector
      */
-    public void setParameters(Parameter[] parameters) {
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -165,11 +157,7 @@
      * @return whether the Resource is selected or not
      */
     public boolean isSelected(Resource r) {
-        String teststr = null;
-        BufferedReader in = null;
-
         // throw BuildException on error
-
         validate();
 
         if (r.isDirectory()) {
@@ -182,40 +170,25 @@
             myExpression = myRegExp.getRegexp(getProject());
         }
 
-        try {
-            in = new BufferedReader(new InputStreamReader(r.getInputStream())); //NOSONAR
-        } catch (Exception e) {
-            throw new BuildException("Could not get InputStream from "
-                    + r.toLongString(), e);
-        }
-        boolean success = false;
-        try {
-            teststr = in.readLine();
-
-            while (teststr != null) {
-
-                if (myExpression.matches(teststr,
-                                         RegexpUtil.asOptions(caseSensitive,
-                                                              multiLine,
-                                                              singleLine))) {
-                    return true;
-                }
-                teststr = in.readLine();
-            }
-            success = true;
-            return false;
-        } catch (IOException ioe) {
-            throw new BuildException("Could not read " + r.toLongString());
-        } finally {
+        try (BufferedReader in =
+            new BufferedReader(new InputStreamReader(r.getInputStream()))) {
             try {
-                in.close();
-            } catch (Exception e) {
-                if (success) {
-                    throw new BuildException("Could not close " //NOSONAR
-                                             + r.toLongString());
+                String teststr = in.readLine();
+
+                while (teststr != null) {
+                    if (myExpression.matches(teststr, RegexpUtil
+                        .asOptions(caseSensitive, multiLine, singleLine))) {
+                        return true;
+                    }
+                    teststr = in.readLine();
                 }
+                return false;
+            } catch (IOException ioe) {
+                throw new BuildException("Could not read " + r.toLongString());
             }
+        } catch (IOException e) {
+            throw new BuildException(
+                "Could not get InputStream from " + r.toLongString(), e);
         }
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/types/selectors/ContainsSelector.java b/src/main/org/apache/tools/ant/types/selectors/ContainsSelector.java
index be149d0..662c7bf 100644
--- a/src/main/org/apache/tools/ant/types/selectors/ContainsSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/ContainsSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,6 +22,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.nio.charset.Charset;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -29,7 +30,6 @@
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
-import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Selector that filters files/resources based on whether they contain a
@@ -39,10 +39,6 @@
  */
 public class ContainsSelector extends BaseExtendSelector implements ResourceSelector {
 
-    private String contains = null;
-    private boolean casesensitive = true;
-    private boolean ignorewhitespace = false;
-    private String encoding = null;
     /** Key to used for parameterized custom selector */
     public static final String EXPRESSION_KEY = "expression";
     /** Used for parameterized custom selector */
@@ -52,26 +48,17 @@
     /** Used for parameterized custom selector */
     public static final String WHITESPACE_KEY = "ignorewhitespace";
 
-
-    /**
-     * Creates a new <code>ContainsSelector</code> instance.
-     *
-     */
-    public ContainsSelector() {
-    }
+    private String contains = null;
+    private boolean casesensitive = true;
+    private boolean ignorewhitespace = false;
+    private String encoding = null;
 
     /**
      * @return a string describing this object
      */
     public String toString() {
-        StringBuilder buf = new StringBuilder("{containsselector text: ");
-        buf.append('"').append(contains).append('"');
-        buf.append(" casesensitive: ");
-        buf.append(casesensitive ? "true" : "false");
-        buf.append(" ignorewhitespace: ");
-        buf.append(ignorewhitespace ? "true" : "false");
-        buf.append("}");
-        return buf.toString();
+        return String.format("{containsselector text: \"%s\" casesensitive: %s ignorewhitespace: %s}",
+                contains, casesensitive, ignorewhitespace);
     }
 
     /**
@@ -117,7 +104,7 @@
      *
      * @param parameters the complete set of parameters for this selector
      */
-    public void setParameters(Parameter[] parameters) {
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -169,11 +156,10 @@
      * @return whether the Resource is selected.
      */
     public boolean isSelected(Resource r) {
-
         // throw BuildException on error
         validate();
 
-        if (r.isDirectory() || contains.length() == 0) {
+        if (r.isDirectory() || contains.isEmpty()) {
             return true;
         }
 
@@ -184,38 +170,30 @@
         if (ignorewhitespace) {
             userstr = SelectorUtils.removeWhitespace(userstr);
         }
-        BufferedReader in = null;
-        try {
-            if (encoding != null) {
-                in = new BufferedReader(new InputStreamReader(r.getInputStream(), encoding)); //NOSONAR
-            }   else {
-                in = new BufferedReader(new InputStreamReader(r.getInputStream())); //NOSONAR
+        try (BufferedReader in = new BufferedReader(
+            new InputStreamReader(r.getInputStream(), encoding == null
+                ? Charset.defaultCharset() : Charset.forName(encoding)))) {
+            try {
+                String teststr = in.readLine();
+                while (teststr != null) {
+                    if (!casesensitive) {
+                        teststr = teststr.toLowerCase();
+                    }
+                    if (ignorewhitespace) {
+                        teststr = SelectorUtils.removeWhitespace(teststr);
+                    }
+                    if (teststr.contains(userstr)) {
+                        return true;
+                    }
+                    teststr = in.readLine();
+                }
+                return false;
+            } catch (IOException ioe) {
+                throw new BuildException("Could not read " + r.toLongString());
             }
-        } catch (Exception e) {
-            throw new BuildException("Could not get InputStream from "
-                    + r.toLongString(), e);
-        }
-        try {
-            String teststr = in.readLine();
-            while (teststr != null) {
-                if (!casesensitive) {
-                    teststr = teststr.toLowerCase();
-                }
-                if (ignorewhitespace) {
-                    teststr = SelectorUtils.removeWhitespace(teststr);
-                }
-                if (teststr.contains(userstr)) {
-                    return true;
-                }
-                teststr = in.readLine();
-            }
-            return false;
-        } catch (IOException ioe) {
-            throw new BuildException("Could not read " + r.toLongString());
-        } finally {
-            FileUtils.close(in);
+        } catch (IOException e) {
+            throw new BuildException(
+                "Could not get InputStream from " + r.toLongString(), e);
         }
     }
-
 }
-
diff --git a/src/main/org/apache/tools/ant/types/selectors/DateSelector.java b/src/main/org/apache/tools/ant/types/selectors/DateSelector.java
index bcbf11c..269c071 100644
--- a/src/main/org/apache/tools/ant/types/selectors/DateSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/DateSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,16 +36,6 @@
  */
 public class DateSelector extends BaseExtendSelector {
 
-    /** Utilities used for file operations */
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
-    private long millis = -1;
-    private String dateTime = null;
-    private boolean includeDirs = false;
-    private long granularity = FILE_UTILS.getFileTimestampGranularity();
-    private String pattern;
-    private TimeComparison when = TimeComparison.EQUAL;
-
     /** Key to used for parameterized custom selector */
     public static final String MILLIS_KEY = "millis";
     /** Key to used for parameterized custom selector */
@@ -59,13 +49,15 @@
     /** Key to used for parameterized custom selector */
     public static final String PATTERN_KEY = "pattern";
 
-    /**
-     * Creates a new <code>DateSelector</code> instance.
-     *
-     */
-    public DateSelector() {
-        granularity = FILE_UTILS.getFileTimestampGranularity();
-    }
+    /** Utilities used for file operations */
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
+    private long millis = -1;
+    private String dateTime = null;
+    private boolean includeDirs = false;
+    private long granularity = FILE_UTILS.getFileTimestampGranularity();
+    private String pattern;
+    private TimeComparison when = TimeComparison.EQUAL;
 
     /**
      * @return a string describing this object
@@ -74,8 +66,7 @@
         StringBuilder buf = new StringBuilder("{dateselector date: ");
         buf.append(dateTime);
         buf.append(" compare: ").append(when.getValue());
-        buf.append(" granularity: ");
-        buf.append(granularity);
+        buf.append(" granularity: ").append(granularity);
         if (pattern != null) {
             buf.append(" pattern: ").append(pattern);
         }
@@ -166,7 +157,7 @@
      *
      * @param parameters the complete set of parameters for this selector.
      */
-    public void setParameters(Parameter[] parameters) {
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -239,9 +230,7 @@
      * @return whether the file is selected.
      */
     public boolean isSelected(File basedir, String filename, File file) {
-
         validate();
-
         return (file.isDirectory() && !includeDirs)
             || when.evaluate(file.lastModified(), millis, granularity);
     }
diff --git a/src/main/org/apache/tools/ant/types/selectors/DependSelector.java b/src/main/org/apache/tools/ant/types/selectors/DependSelector.java
index 01ac237..81e49ef 100644
--- a/src/main/org/apache/tools/ant/types/selectors/DependSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/DependSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,14 +31,6 @@
 public class DependSelector extends MappingSelector {
 
     /**
-     * Creates a new <code>DependSelector</code> instance.
-     *
-     */
-    public DependSelector() {
-
-    }
-
-    /**
      * @return a string describing this object
      */
     public String toString() {
@@ -48,8 +40,7 @@
         } else {
             buf.append(targetdir.getName());
         }
-        buf.append(" granularity: ");
-        buf.append(granularity);
+        buf.append(" granularity: ").append(granularity);
         if (map != null) {
             buf.append(" mapper: ");
             buf.append(map.toString());
@@ -61,7 +52,6 @@
         return buf.toString();
     }
 
-
     /**
      * this test is our selection test that compared the file with the destfile
      * @param srcfile the source file
@@ -69,9 +59,7 @@
      * @return true if destination is out of date
      */
     public boolean selectionTest(File srcfile, File destfile) {
-        boolean selected = SelectorUtils.isOutOfDate(srcfile, destfile,
-                granularity);
-        return selected;
+        return SelectorUtils.isOutOfDate(srcfile, destfile, granularity);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/DepthSelector.java b/src/main/org/apache/tools/ant/types/selectors/DepthSelector.java
index a8a14d3..2076be9 100644
--- a/src/main/org/apache/tools/ant/types/selectors/DepthSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/DepthSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,6 +32,11 @@
  */
 public class DepthSelector extends BaseExtendSelector {
 
+    /** Used for parameterized custom selector */
+    public static final String MIN_KEY = "min";
+    /** Used for parameterized custom selector */
+    public static final String MAX_KEY = "max";
+
     // CheckStyle:VisibilityModifier OFF - bc
 
     /** min attribute */
@@ -41,28 +46,11 @@
 
     // CheckStyle:VisibilityModifier ON
 
-    /** Used for parameterized custom selector */
-    public static final String MIN_KEY = "min";
-    /** Used for parameterized custom selector */
-    public static final String MAX_KEY = "max";
-
-    /**
-     * Creates a new <code>DepthSelector</code> instance.
-     *
-     */
-    public DepthSelector() {
-    }
-
     /**
      * @return a string describing this object
      */
     public String toString() {
-        StringBuilder buf = new StringBuilder("{depthselector min: ");
-        buf.append(min);
-        buf.append(" max: ");
-        buf.append(max);
-        buf.append("}");
-        return buf.toString();
+        return "{depthselector min: " + min + " max: " + max + "}";
     }
 
     /**
@@ -89,7 +77,7 @@
      *
      * @param parameters the complete set of parameters for this selector
      */
-    public void setParameters(Parameter[] parameters) {
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -121,8 +109,7 @@
      */
     public void verifySettings() {
         if (min < 0 && max < 0) {
-            setError("You must set at least one of the min or the "
-                    + "max levels.");
+            setError("You must set at least one of the min or the max levels.");
         }
         if (max < min && max > -1) {
             setError("The maximum depth is lower than the minimum.");
@@ -150,19 +137,17 @@
         // If you felt daring, you could cache the basedir absolute path
         String absBase = basedir.getAbsolutePath();
         String absFile = file.getAbsolutePath();
-        StringTokenizer tokBase = new StringTokenizer(absBase,
-                File.separator);
-        StringTokenizer tokFile = new StringTokenizer(absFile,
-                File.separator);
+        StringTokenizer tokBase = new StringTokenizer(absBase, File.separator);
+        StringTokenizer tokFile = new StringTokenizer(absFile, File.separator);
         while (tokFile.hasMoreTokens()) {
             String filetoken = tokFile.nextToken();
             if (tokBase.hasMoreTokens()) {
                 String basetoken = tokBase.nextToken();
                 // Sanity check. Ditch it if you want faster performance
                 if (!basetoken.equals(filetoken)) {
-                    throw new BuildException("File " + filename
-                            + " does not appear within " + absBase
-                            + "directory");
+                    throw new BuildException(
+                        "File %s does not appear within %s directory", filename,
+                        absBase);
                 }
             } else {
                 depth += 1;
@@ -172,14 +157,9 @@
             }
         }
         if (tokBase.hasMoreTokens()) {
-            throw new BuildException("File " + filename
-                + " is outside of " + absBase + "directory tree");
+            throw new BuildException("File %s is outside of %s directory tree",
+                filename, absBase);
         }
-        if (min > -1 && depth < min) {
-            return false;
-        }
-        return true;
+        return min <= -1 || depth >= min;
     }
-
 }
-
diff --git a/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java b/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java
index 9c076fa..d183032 100644
--- a/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/DifferentSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -55,7 +55,6 @@
     private boolean ignoreFileTimes = true;
     private boolean ignoreContents = false;
 
-
     /**
      * This flag tells the selector to ignore file times in the comparison
      * @param ignoreFileTimes if true ignore file times
@@ -63,6 +62,7 @@
     public void setIgnoreFileTimes(boolean ignoreFileTimes) {
         this.ignoreFileTimes = ignoreFileTimes;
     }
+
     /**
      * This flag tells the selector to ignore contents
      * @param ignoreContents if true ignore contents
@@ -71,6 +71,7 @@
     public void setIgnoreContents(boolean ignoreContents) {
         this.ignoreContents = ignoreContents;
     }
+
     /**
      * this test is our selection test that compared the file with the destfile
      * @param srcfile the source file
@@ -100,16 +101,15 @@
                 return true;
             }
         }
-        if (!ignoreContents) {
-            //here do a bulk comparison
-            try {
-                return !FILE_UTILS.contentEquals(srcfile, destfile);
-            } catch (IOException e) {
-                throw new BuildException("while comparing " + srcfile + " and "
-                        + destfile, e);
-            }
-        } else {
+        if (ignoreContents) {
             return false;
         }
+        //here do a bulk comparison
+        try {
+            return !FILE_UTILS.contentEquals(srcfile, destfile);
+        } catch (IOException e) {
+            throw new BuildException(
+                "while comparing " + srcfile + " and " + destfile, e);
+        }
     }
 }
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..db5c6a5
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/ExecutableSelector.java
@@ -0,0 +1,40 @@
+/*
+ *  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
+ *
+ *      https://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.io.File;
+import java.nio.file.Files;
+
+/**
+ * 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 {
+
+    public boolean isSelected(File basedir, String filename, File file) {
+        return file != null && Files.isExecutable(file.toPath());
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/ExtendFileSelector.java b/src/main/org/apache/tools/ant/types/selectors/ExtendFileSelector.java
index fe97406..411cafd 100644
--- a/src/main/org/apache/tools/ant/types/selectors/ExtendFileSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/ExtendFileSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/ExtendSelector.java b/src/main/org/apache/tools/ant/types/selectors/ExtendSelector.java
index af8c920..3da62fd 100644
--- a/src/main/org/apache/tools/ant/types/selectors/ExtendSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/ExtendSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,10 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
-import java.util.Vector;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -37,16 +40,11 @@
 
     private String classname = null;
     private FileSelector dynselector = null;
-    private Vector<Parameter> paramVec = new Vector<Parameter>();
+    private List<Parameter> parameters =
+        Collections.synchronizedList(new ArrayList<>());
     private Path classpath = null;
 
     /**
-     * Default constructor.
-     */
-    public ExtendSelector() {
-    }
-
-    /**
      * Sets the classname of the custom selector.
      *
      * @param classname is the class which implements this selector
@@ -59,9 +57,9 @@
      * Instantiates the identified custom selector class.
      */
     public void selectorCreate() {
-        if (classname != null && classname.length() > 0) {
+        if (classname != null && !classname.isEmpty()) {
             try {
-                Class<?> c = null;
+                Class<?> c;
                 if (classpath == null) {
                     c = Class.forName(classname);
                 } else {
@@ -70,7 +68,7 @@
                             = getProject().createClassLoader(classpath);
                     c = Class.forName(classname, true, al);
                 }
-                dynselector = c.asSubclass(FileSelector.class).newInstance();
+                dynselector = c.asSubclass(FileSelector.class).getDeclaredConstructor().newInstance();
                 final Project p = getProject();
                 if (p != null) {
                     p.setProjectReference(dynselector);
@@ -78,7 +76,8 @@
             } catch (ClassNotFoundException cnfexcept) {
                 setError("Selector " + classname
                     + " not initialized, no such class");
-            } catch (InstantiationException iexcept) {
+            } catch (InstantiationException | NoSuchMethodException
+                    | InvocationTargetException iexcept) {
                 setError("Selector " + classname
                     + " not initialized, could not create class");
             } catch (IllegalAccessException iaexcept) {
@@ -96,10 +95,9 @@
      * @param p The new Parameter object
      */
     public void addParam(Parameter p) {
-        paramVec.addElement(p);
+        parameters.add(p);
     }
 
-
     /**
      * Set the classpath to load the classname specified using an attribute.
      * @param classpath the classpath to use
@@ -166,13 +164,12 @@
         } else if (dynselector == null) {
             setError("Internal Error: The custom selector was not created");
         } else if (!(dynselector instanceof ExtendFileSelector)
-                    && (paramVec.size() > 0)) {
-            setError("Cannot set parameters on custom selector that does not "
-                    + "implement ExtendFileSelector");
+                    && !parameters.isEmpty()) {
+            setError(
+                "Cannot set parameters on custom selector that does not implement ExtendFileSelector");
         }
     }
 
-
     /**
      * Allows the custom selector to choose whether to select a file. This
      * is also where the Parameters are passed to the custom selector,
@@ -188,14 +185,12 @@
     public boolean isSelected(File basedir, String filename, File file)
             throws BuildException {
         validate();
-        if (paramVec.size() > 0 && dynselector instanceof ExtendFileSelector) {
-            Parameter[] paramArray = new Parameter[paramVec.size()];
-            paramVec.copyInto(paramArray);
+        if (!parameters.isEmpty() && dynselector instanceof ExtendFileSelector) {
             // We know that dynselector must be non-null if no error message
-            ((ExtendFileSelector) dynselector).setParameters(paramArray);
+            ((ExtendFileSelector) dynselector).setParameters(
+                parameters.toArray(new Parameter[0]));
         }
         return dynselector.isSelected(basedir, filename, file);
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/types/selectors/FileSelector.java b/src/main/org/apache/tools/ant/types/selectors/FileSelector.java
index 614a970..f2c25b2 100644
--- a/src/main/org/apache/tools/ant/types/selectors/FileSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/FileSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,13 +21,16 @@
 import java.io.File;
 
 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;
 
 /**
  * This is the interface to be used by all selectors.
  *
  * @since 1.5
  */
-public interface FileSelector {
+public interface FileSelector extends ResourceSelector {
 
     /**
      * Method that each selector will implement to create their
@@ -44,5 +47,15 @@
     boolean isSelected(File basedir, String filename, File file)
             throws BuildException;
 
+    /**
+     * Implement a basic {@link Resource} selection that delegates to this
+     * {@link FileSelector}.
+     * @param r resource
+     * @return whether the resource is selected
+     */
+    default boolean isSelected(Resource r) {
+        return r.asOptional(FileProvider.class).map(FileProvider::getFile)
+                .map(f -> isSelected(null, null, f)).orElse(false);
+    }
 }
 
diff --git a/src/main/org/apache/tools/ant/types/selectors/FilenameSelector.java b/src/main/org/apache/tools/ant/types/selectors/FilenameSelector.java
index ec34e23..aaaace6 100644
--- a/src/main/org/apache/tools/ant/types/selectors/FilenameSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/FilenameSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,12 +32,6 @@
  * @since 1.5
  */
 public class FilenameSelector extends BaseExtendSelector {
-
-    private String pattern = null;
-    private String regex = null;
-    private boolean casesensitive = true;
-
-    private boolean negated = false;
     /** Used for parameterized custom selector */
     public static final String NAME_KEY = "name";
     /** Used for parameterized custom selector */
@@ -47,18 +41,17 @@
     /** Used for parameterized custom selector */
     public static final String REGEX_KEY = "regex";
 
+    private String pattern = null;
+    private String regex = null;
+    private boolean casesensitive = true;
+
+    private boolean negated = false;
+
     // caches for performance reasons
     private RegularExpression reg;
     private Regexp expression;
 
     /**
-     * Creates a new <code>FilenameSelector</code> instance.
-     *
-     */
-    public FilenameSelector() {
-    }
-
-    /**
      * @return a string describing this object
      */
     public String toString() {
@@ -129,7 +122,7 @@
      *
      * @param parameters the complete set of parameters for this selector
      */
-    public void setParameters(Parameter[] parameters) {
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -178,18 +171,16 @@
     public boolean isSelected(File basedir, String filename, File file) {
         validate();
         if (pattern != null) {
-            return (SelectorUtils.matchPath(pattern, filename,
-                                            casesensitive) == !(negated));
-        } else {
-            if (reg == null) {
-                reg = new RegularExpression();
-                reg.setPattern(regex);
-                expression = reg.getRegexp(getProject());
-            }
-            int options = RegexpUtil.asOptions(casesensitive);
-            return expression.matches(filename, options) == !negated;
+            return SelectorUtils.matchPath(pattern, filename,
+                casesensitive) == !(negated);
         }
+        if (reg == null) {
+            reg = new RegularExpression();
+            reg.setPattern(regex);
+            expression = reg.getRegexp(getProject());
+        }
+        int options = RegexpUtil.asOptions(casesensitive);
+        return expression.matches(filename, options) == !negated;
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/types/selectors/MajoritySelector.java b/src/main/org/apache/tools/ant/types/selectors/MajoritySelector.java
index 842258f..33a88c9 100644
--- a/src/main/org/apache/tools/ant/types/selectors/MajoritySelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/MajoritySelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.Collections;
 
 /**
  * This selector is here just to shake up your thinking a bit. Don't get
@@ -37,12 +37,6 @@
     private boolean allowtie = true;
 
     /**
-     * Default constructor.
-     */
-    public MajoritySelector() {
-    }
-
-    /**
      * @return a string describing this object
      */
     public String toString() {
@@ -81,11 +75,9 @@
         validate();
         int yesvotes = 0;
         int novotes = 0;
-        Enumeration<FileSelector> e = selectorElements();
 
-        while (e.hasMoreElements()) {
-            if (e.nextElement().isSelected(basedir,
-                    filename, file)) {
+        for (FileSelector fs : Collections.list(selectorElements())) {
+            if (fs.isSelected(basedir, filename, file)) {
                 yesvotes++;
             } else {
                 novotes++;
@@ -93,7 +85,8 @@
         }
         if (yesvotes > novotes) {
             return true;
-        } else if (novotes > yesvotes) {
+        }
+        if (novotes > yesvotes) {
             return false;
         }
         // At this point, we know we have a tie.
diff --git a/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java b/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java
index 9360740..a05b963 100644
--- a/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/MappingSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -45,15 +45,6 @@
     // CheckStyle:VisibilityModifier ON
 
     /**
-     * Creates a new <code>MappingSelector</code> instance.
-     *
-     */
-    public MappingSelector() {
-        granularity = (int) FILE_UTILS.getFileTimestampGranularity();
-    }
-
-
-    /**
      * The name of the file or directory which is checked for out-of-date
      * files.
      *
@@ -140,8 +131,7 @@
         String destname = destfiles[0];
         File destfile = FILE_UTILS.resolveFile(targetdir, destname);
 
-        boolean selected = selectionTest(file, destfile);
-        return selected;
+        return selectionTest(file, destfile);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/selectors/NoneSelector.java b/src/main/org/apache/tools/ant/types/selectors/NoneSelector.java
index 536b5b5..304356d 100644
--- a/src/main/org/apache/tools/ant/types/selectors/NoneSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/NoneSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.stream.Stream;
 
 /**
  * This selector has a collection of other selectors. All of those selectors
@@ -31,12 +31,6 @@
 public class NoneSelector extends BaseSelectorContainer {
 
     /**
-     * Default constructor.
-     */
-    public NoneSelector() {
-    }
-
-    /**
      * @return a string representation of the selector
      */
     public String toString() {
@@ -61,15 +55,8 @@
      */
     public boolean isSelected(File basedir, String filename, File file) {
         validate();
-        Enumeration<FileSelector> e = selectorElements();
-
-        while (e.hasMoreElements()) {
-            if (e.nextElement().isSelected(basedir, filename, file)) {
-                return false;
-            }
-        }
-        return true;
+        return Stream.of(getSelectors(getProject()))
+            .noneMatch(s -> s.isSelected(basedir, filename, file));
     }
 
 }
-
diff --git a/src/main/org/apache/tools/ant/types/selectors/NotSelector.java b/src/main/org/apache/tools/ant/types/selectors/NotSelector.java
index 71c3940..7153640 100644
--- a/src/main/org/apache/tools/ant/types/selectors/NotSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/NotSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -64,8 +64,8 @@
      */
     public void verifySettings() {
         if (selectorCount() != 1) {
-            setError("One and only one selector is allowed within the "
-                + "<not> tag");
+            setError(
+                "One and only one selector is allowed within the <not> tag");
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/types/selectors/OrSelector.java b/src/main/org/apache/tools/ant/types/selectors/OrSelector.java
index b077744..c3bb8a1 100644
--- a/src/main/org/apache/tools/ant/types/selectors/OrSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/OrSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
-import java.util.Enumeration;
+import java.util.stream.Stream;
 
 /**
  * This selector has a collection of other selectors, any of which have to
@@ -30,12 +30,6 @@
 public class OrSelector extends BaseSelectorContainer {
 
     /**
-     * Default constructor.
-     */
-    public OrSelector() {
-    }
-
-    /**
      * @return a string representation of the selector
      */
     public String toString() {
@@ -60,15 +54,8 @@
      */
     public boolean isSelected(File basedir, String filename, File file) {
         validate();
-        Enumeration<FileSelector> e = selectorElements();
-
-        // First, check that all elements are correctly configured
-        while (e.hasMoreElements()) {
-            if (e.nextElement().isSelected(basedir, filename, file)) {
-                return true;
-            }
-        }
-        return false;
+        return Stream.of(getSelectors(getProject()))
+            .anyMatch(s -> s.isSelected(basedir, filename, file));
     }
 
 }
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..4f71277
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
@@ -0,0 +1,79 @@
+/*
+ *  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
+ *
+ *      https://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.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.attribute.UserPrincipal;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * 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 UnsupportedOperationException}
+ * the file in question is not included.</p>
+ *
+ * @since Ant 1.10.0
+ */
+public class OwnedBySelector implements FileSelector {
+
+    private String owner;
+
+    private boolean followSymlinks = true;
+
+    /**
+     * Sets the user name to look for.
+     * @param owner the user name
+     */
+    public void setOwner(String owner) {
+        this.owner = owner;
+    }
+
+    /**
+     * Sets the "follow symbolic links" option.
+     * @param followSymlinks whether or not symbolic links should be followed.
+     */
+    public void setFollowSymlinks(boolean followSymlinks) {
+        this.followSymlinks = followSymlinks;
+    }
+
+    @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 = followSymlinks ? Files.getOwner(file.toPath())
+                        : Files.getOwner(file.toPath(), LinkOption.NOFOLLOW_LINKS);
+                return user != null && owner.equals(user.getName());
+            } catch (UnsupportedOperationException | IOException ex) {
+                // => not the expected owner
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java b/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java
new file mode 100644
index 0000000..83107c8
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java
@@ -0,0 +1,77 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFileAttributes;
+
+/**
+ * A selector that selects files based on their POSIX group.
+ *
+ * <p>Group is defined in terms of {@link java.nio.file.Files#readAttributes}
+ * group attribute as provided by {@link java.nio.file.attribute.PosixFileAttributes},
+ * this means the selector will accept any file that exists and has the given
+ * group attribute.</p>
+ *
+ * @since Ant 1.10.4
+ */
+public class PosixGroupSelector implements FileSelector {
+
+    private String group;
+
+    private boolean followSymlinks = true;
+
+    /**
+     * Sets the group name to look for.
+     * @param group the group name
+     */
+    public void setGroup(String group) {
+        this.group = group;
+    }
+
+    /**
+     * Sets the "follow symbolic links" option.
+     * @param followSymlinks whether or not symbolic links should be followed.
+     */
+    public void setFollowSymlinks(boolean followSymlinks) {
+        this.followSymlinks = followSymlinks;
+    }
+
+    @Override
+    public boolean isSelected(File basedir, String filename, File file) {
+        if (group == null) {
+            throw new BuildException("the group attribute is required");
+        }
+        try {
+            GroupPrincipal actualGroup = followSymlinks ? Files.readAttributes(file.toPath(),
+                    PosixFileAttributes.class).group() : Files.readAttributes(file.toPath(),
+                    PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS).group();
+            return actualGroup != null && actualGroup.getName().equals(group);
+        } catch (IOException e) {
+            // => not the expected group
+        }
+        return false;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java b/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java
new file mode 100644
index 0000000..69f9c03
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java
@@ -0,0 +1,87 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.PermissionUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.attribute.PosixFilePermissions;
+
+/**
+ * A selector that selects files based on their POSIX permissions.
+ *
+ * <p>Permissions are defined in terms of {@link
+ * java.nio.file.Files#getPosixFilePermissions}, this means the selector will accept
+ * any file that exists and has given POSIX permissions.</p>
+ *
+ * @since Ant 1.10.4
+ */
+public class PosixPermissionsSelector implements FileSelector {
+
+    private String permissions;
+
+    private boolean followSymlinks = true;
+
+    /**
+     * Sets the permissions to look for.
+     * @param permissions the permissions string (rwxrwxrwx or octal)
+     */
+    public void setPermissions(String permissions) {
+        if (permissions.length() == 3 && permissions.matches("^[0-7]+$")) {
+            this.permissions = PosixFilePermissions.toString(
+                    PermissionUtils.permissionsFromMode(Integer.parseInt(permissions, 8)));
+            return;
+        }
+
+        try {
+            this.permissions = PosixFilePermissions.toString(PosixFilePermissions.fromString(permissions));
+        } catch (IllegalArgumentException ex) {
+            throw new BuildException("the permissions attribute " + permissions
+                    + " is invalid", ex);
+        }
+    }
+
+    /**
+     * Sets the "follow symbolic links" flag.
+     * @param followSymlinks whether or not symbolic links should be followed.
+     */
+    public void setFollowSymlinks(boolean followSymlinks) {
+        this.followSymlinks = followSymlinks;
+    }
+
+    @Override
+    public boolean isSelected(File basedir, String filename, File file) {
+        if (permissions == null) {
+            throw new BuildException("the permissions attribute is required");
+        }
+        try {
+            return PosixFilePermissions.toString(followSymlinks
+                    ? Files.getPosixFilePermissions(file.toPath())
+                    : Files.getPosixFilePermissions(file.toPath(), LinkOption.NOFOLLOW_LINKS))
+                    .equals(permissions);
+        } catch (IOException e) {
+            // => not the expected permissions
+        }
+        return false;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/PresentSelector.java b/src/main/org/apache/tools/ant/types/selectors/PresentSelector.java
index 725b31e..96695e4 100644
--- a/src/main/org/apache/tools/ant/types/selectors/PresentSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/PresentSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -42,13 +42,6 @@
     private boolean destmustexist = true;
 
     /**
-     * Creates a new <code>PresentSelector</code> instance.
-     *
-     */
-    public PresentSelector() {
-    }
-
-    /**
      * @return a string describing this object
      */
     @Override
diff --git a/src/main/org/apache/tools/ant/types/selectors/ReadableSelector.java b/src/main/org/apache/tools/ant/types/selectors/ReadableSelector.java
index b0c527c..ba5beac 100644
--- a/src/main/org/apache/tools/ant/types/selectors/ReadableSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/ReadableSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,10 +20,6 @@
 
 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 readable files.
  *
@@ -33,17 +29,11 @@
  *
  * @since Ant 1.8.0
  */
-public class ReadableSelector implements FileSelector, ResourceSelector {
+public class ReadableSelector implements FileSelector {
 
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
         return file != null && file.canRead();
     }
 
-    public boolean isSelected(Resource r) {
-        FileProvider fp = r.as(FileProvider.class);
-        if (fp != null) {
-            return isSelected(null, null, fp.getFile());
-        }
-        return false;
-    }
 }
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectSelector.java b/src/main/org/apache/tools/ant/types/selectors/SelectSelector.java
index 2089012..1d7e637 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SelectSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SelectSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,16 +40,10 @@
     private Object unlessCondition;
 
     /**
-     * Default constructor.
-     */
-    public SelectSelector() {
-    }
-
-    /**
      * @return a string describing this object
      */
     public String toString() {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         if (hasSelectors()) {
             buf.append("{select");
             if (ifCondition != null) {
@@ -72,14 +66,14 @@
      * referenced Selector.
      */
     private SelectSelector getRef() {
-        Object o = getCheckedRef(this.getClass(), "SelectSelector");
-        return (SelectSelector) o;
+        return getCheckedRef(SelectSelector.class);
     }
 
     /**
      * Indicates whether there are any selectors here.
      * @return whether any selectors are in this container
      */
+    @Override
     public boolean hasSelectors() {
         if (isReference()) {
             return getRef().hasSelectors();
@@ -91,6 +85,7 @@
      * Gives the count of the number of selectors in this container
      * @return the number of selectors in this container
      */
+    @Override
     public int selectorCount() {
         if (isReference()) {
             return getRef().selectorCount();
@@ -103,6 +98,7 @@
      * @param p the current project
      * @return an array of selectors in this container
      */
+    @Override
     public FileSelector[] getSelectors(Project p) {
         if (isReference()) {
             return getRef().getSelectors(p);
@@ -114,6 +110,7 @@
      * Returns an enumerator for accessing the set of selectors.
      * @return an enumerator that goes through each of the selectors
      */
+    @Override
     public Enumeration<FileSelector> selectorElements() {
         if (isReference()) {
             return getRef().selectorElements();
@@ -126,6 +123,7 @@
      *
      * @param selector the new selector to add
      */
+    @Override
     public void appendSelector(FileSelector selector) {
         if (isReference()) {
             throw noChildrenAllowed();
@@ -138,11 +136,11 @@
      * Makes sure that there is only one entry, sets an error message if
      * not.
      */
+    @Override
     public void verifySettings() {
         int cnt = selectorCount();
         if (cnt < 0 || cnt > 1) {
-            setError("Only one selector is allowed within the "
-                + "<selector> tag");
+            setError("Only one selector is allowed within the <selector> tag");
         }
     }
 
@@ -212,20 +210,17 @@
      * can use
      * @return whether the file should be selected or not
      */
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
         validate();
 
         // Deal with if and unless properties first
-        if (!(passesConditions())) {
+        if (!passesConditions()) {
             return false;
         }
 
         Enumeration<FileSelector> e = selectorElements();
-        if (!e.hasMoreElements()) {
-            return true;
-        }
-        FileSelector f = e.nextElement();
-        return f.isSelected(basedir, filename, file);
+        return !e.hasMoreElements() || e.nextElement().isSelected(basedir, filename, file);
     }
 }
 
diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
index 47e4e4f..2107454 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorScanner.java b/src/main/org/apache/tools/ant/types/selectors/SelectorScanner.java
index df9f8a4..757339d 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SelectorScanner.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SelectorScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
index 9b37490..a6af9bc 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -153,20 +153,10 @@
             strIdxStart++;
         }
 
-        // CheckStyle:SimplifyBooleanReturnCheck OFF
-        // Check turned off as the code needs the comments for the various
-        // code paths.
-        if (strIdxStart > strIdxEnd) {
-            // String is exhausted
-            return true;
-        } else if (patIdxStart > patIdxEnd) {
-            // String not exhausted, but pattern is. Failure.
-            return false;
-        } else {
-            // pattern now holds ** while string is not exhausted
-            // this will generate false positives but we can live with that.
-            return true;
-        }
+        // Fail if string is not exhausted or pattern is exhausted
+        // Otherwise the pattern now holds ** while string is not exhausted
+        // this will generate false positives but we can live with that.
+        return strIdxStart > strIdxEnd || patIdxStart <= patIdxEnd;
     }
 
     /**
@@ -245,11 +235,10 @@
                 }
             }
             return true;
-        } else {
-            if (patIdxStart > patIdxEnd) {
-                // String not exhausted, but pattern is. Failure.
-                return false;
-            }
+        }
+        if (patIdxStart > patIdxEnd) {
+            // String not exhausted, but pattern is. Failure.
+            return false;
         }
 
         // up to last '**'
@@ -293,19 +282,17 @@
             int strLength = (strIdxEnd - strIdxStart + 1);
             int foundIdx = -1;
             strLoop:
-                        for (int i = 0; i <= strLength - patLength; i++) {
-                            for (int j = 0; j < patLength; j++) {
-                                String subPat = tokenizedPattern[patIdxStart + j + 1];
-                                String subStr = strDirs[strIdxStart + i + j];
-                                if (!match(subPat, subStr, isCaseSensitive)) {
-                                    continue strLoop;
-                                }
-                            }
-
-                            foundIdx = strIdxStart + i;
-                            break;
-                        }
-
+            for (int i = 0; i <= strLength - patLength; i++) {
+                for (int j = 0; j < patLength; j++) {
+                    String subPat = tokenizedPattern[patIdxStart + j + 1];
+                    String subStr = strDirs[strIdxStart + i + j];
+                    if (!match(subPat, subStr, isCaseSensitive)) {
+                        continue strLoop;
+                    }
+                }
+                foundIdx = strIdxStart + i;
+                break;
+            }
             if (foundIdx == -1) {
                 return false;
             }
@@ -315,11 +302,10 @@
         }
 
         for (int i = patIdxStart; i <= patIdxEnd; i++) {
-            if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
+            if (!DEEP_TREE_MATCH.equals(tokenizedPattern[i])) {
                 return false;
             }
         }
-
         return true;
     }
 
@@ -382,10 +368,8 @@
             }
             for (int i = 0; i <= patIdxEnd; i++) {
                 char ch = patArr[i];
-                if (ch != '?') {
-                    if (different(caseSensitive, ch, strArr[i])) {
-                        return false; // Character mismatch
-                    }
+                if (ch != '?' && different(caseSensitive, ch, strArr[i])) {
+                    return false; // Character mismatch
                 }
             }
             return true; // String matches against pattern
@@ -401,10 +385,9 @@
             if (ch == '*' || strIdxStart > strIdxEnd) {
                 break;
             }
-            if (ch != '?') {
-                if (different(caseSensitive, ch, strArr[strIdxStart])) {
-                    return false; // Character mismatch
-                }
+            if (ch != '?'
+                && different(caseSensitive, ch, strArr[strIdxStart])) {
+                return false; // Character mismatch
             }
             patIdxStart++;
             strIdxStart++;
@@ -421,10 +404,8 @@
             if (ch == '*' || strIdxStart > strIdxEnd) {
                 break;
             }
-            if (ch != '?') {
-                if (different(caseSensitive, ch, strArr[strIdxEnd])) {
-                    return false; // Character mismatch
-                }
+            if (ch != '?' && different(caseSensitive, ch, strArr[strIdxEnd])) {
+                return false; // Character mismatch
             }
             patIdxEnd--;
             strIdxEnd--;
@@ -459,14 +440,11 @@
             for (int i = 0; i <= strLength - patLength; i++) {
                 for (int j = 0; j < patLength; j++) {
                     char ch = patArr[patIdxStart + j + 1];
-                    if (ch != '?') {
-                        if (different(caseSensitive, ch,
-                                      strArr[strIdxStart + i + j])) {
-                            continue strLoop;
-                        }
+                    if (ch != '?' && different(caseSensitive, ch,
+                        strArr[strIdxStart + i + j])) {
+                        continue strLoop;
                     }
                 }
-
                 foundIdx = strIdxStart + i;
                 break;
             }
@@ -474,7 +452,6 @@
             if (foundIdx == -1) {
                 return false;
             }
-
             patIdxStart = patIdxTmp;
             strIdxStart = foundIdx + patLength;
         }
@@ -522,7 +499,7 @@
      * @since Ant 1.6
      */
     public static Vector<String> tokenizePath(String path, String separator) {
-        Vector<String> ret = new Vector<String>();
+        Vector<String> ret = new Vector<>();
         if (FileUtils.isAbsolutePath(path)) {
             String[] s = FILE_UTILS.dissect(path);
             ret.add(s[0]);
@@ -538,7 +515,8 @@
     /**
      * Same as {@link #tokenizePath tokenizePath} but hopefully faster.
      */
-    /*package*/ static String[] tokenizePathAsArray(String path) {
+    /* package */
+    static String[] tokenizePathAsArray(String path) {
         String root = null;
         if (FileUtils.isAbsolutePath(path)) {
             String[] s = FILE_UTILS.dissect(path);
@@ -600,16 +578,8 @@
      * @return whether the target is out of date
      */
     public static boolean isOutOfDate(File src, File target, int granularity) {
-        if (!src.exists()) {
-            return false;
-        }
-        if (!target.exists()) {
-            return true;
-        }
-        if ((src.lastModified() - granularity) > target.lastModified()) {
-            return true;
-        }
-        return false;
+        return src.exists() && (!target.exists()
+                || (src.lastModified() - granularity) > target.lastModified());
     }
 
     /**
@@ -663,7 +633,7 @@
      * @return a String that has had all whitespace removed.
      */
     public static String removeWhitespace(String input) {
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         if (input != null) {
             StringTokenizer st = new StringTokenizer(input);
             while (st.hasMoreTokens()) {
@@ -679,7 +649,7 @@
      * @return true if the string contains at least a star or a question mark
      */
     public static boolean hasWildcards(String input) {
-        return (input.indexOf('*') != -1 || input.indexOf('?') != -1);
+        return input.contains("*") || input.contains("?");
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/types/selectors/SignedSelector.java b/src/main/org/apache/tools/ant/types/selectors/SignedSelector.java
index cd51502..40f4095 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SignedSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SignedSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -48,6 +48,7 @@
      * @param file     path to file to be selected
      * @return whether the file should be selected or not
      */
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
         if (file.isDirectory()) {
             return false; // Quick return: directories cannot be signed
diff --git a/src/main/org/apache/tools/ant/types/selectors/SizeSelector.java b/src/main/org/apache/tools/ant/types/selectors/SizeSelector.java
index 6f8d2d8..e37fa2c 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SizeSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SizeSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -62,24 +62,14 @@
     private Comparison when = Comparison.EQUAL;
 
     /**
-     * Creates a new <code>SizeSelector</code> instance.
-     *
-     */
-    public SizeSelector() {
-    }
-
-    /**
      * Returns a <code>String</code> object representing the specified
      * SizeSelector. This is "{sizeselector value: " + &lt;"compare",
      * "less", "more", "equal"&gt; + "}".
      * @return a string describing this object
      */
     public String toString() {
-        StringBuilder buf = new StringBuilder("{sizeselector value: ");
-        buf.append(sizelimit);
-        buf.append("compare: ").append(when.getValue());
-        buf.append("}");
-        return buf.toString();
+        return String.format("{sizeselector value: %d compare: %s}",
+                sizelimit, when.getValue());
     }
 
     /**
@@ -164,7 +154,8 @@
      *
      * @param parameters the complete set of parameters for this selector.
      */
-    public void setParameters(Parameter[] parameters) {
+    @Override
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -220,6 +211,7 @@
      * @param file A File object for this filename.
      * @return whether the file should be selected or not.
      */
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
 
         // throw BuildException on error
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..e9b552c
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/SymlinkSelector.java
@@ -0,0 +1,39 @@
+/*
+ *  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
+ *
+ *      https://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.io.File;
+import java.nio.file.Files;
+
+/**
+ * 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 {
+
+    public boolean isSelected(File basedir, String filename, File file) {
+        return file != null && Files.isSymbolicLink(file.toPath());
+    }
+
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java b/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java
index cd0770b..a92d7e4 100644
--- a/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java
+++ b/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,12 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.SymbolicLinkUtils;
 
 /**
  * Container for a path that has been split into its components.
@@ -38,9 +40,6 @@
 
     /** Helper. */
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    /** Helper. */
-    private static final SymbolicLinkUtils SYMLINK_UTILS =
-        SymbolicLinkUtils.getSymbolicLinkUtils();
     /** iterations for case-sensitive scanning. */
     private static final boolean[] CS_SCAN_ONLY = new boolean[] {true};
     /** iterations for non-case-sensitive scanning. */
@@ -65,9 +64,8 @@
      * @param child the child, must not contain the file separator
      */
     public TokenizedPath(TokenizedPath parent, String child) {
-        if (parent.path.length() > 0
-            && parent.path.charAt(parent.path.length() - 1)
-               != File.separatorChar) {
+        if (!parent.path.isEmpty()
+            && parent.path.charAt(parent.path.length() - 1) != File.separatorChar) {
             path = parent.path + File.separatorChar + child;
         } else {
             path = parent.path + child;
@@ -142,22 +140,16 @@
      */
     public boolean isSymlink(File base) {
         for (String token : tokenizedPath) {
-            try {
-                if ((base != null
-                     && SYMLINK_UTILS.isSymbolicLink(base, token))
-                    ||
-                    (base == null
-                     && SYMLINK_UTILS.isSymbolicLink(token))
-                    ) {
-                    return true;
-                }
-                base = new File(base, token);
-            } catch (java.io.IOException ioe) {
-                String msg = "IOException caught while checking "
-                    + "for links, couldn't get canonical path!";
-                // will be caught and redirected to Ant's logging system
-                System.err.println(msg);
+            final Path pathToTraverse;
+            if (base == null) {
+                pathToTraverse = Paths.get(token);
+            } else {
+                pathToTraverse = Paths.get(base.toPath().toString(), token);
             }
+            if (Files.isSymbolicLink(pathToTraverse)) {
+                return true;
+            }
+            base = new File(base, token);
         }
         return false;
     }
@@ -194,8 +186,8 @@
             }
             String[] files = base.list();
             if (files == null) {
-                throw new BuildException("IO error scanning directory "
-                                         + base.getAbsolutePath());
+                throw new BuildException("IO error scanning directory %s",
+                    base.getAbsolutePath());
             }
             boolean found = false;
             boolean[] matchCase = cs ? CS_SCAN_ONLY : CS_THEN_NON_CS;
diff --git a/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java b/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java
index 2f1be2f..192572b 100644
--- a/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java
+++ b/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,12 +19,14 @@
 package org.apache.tools.ant.types.selectors;
 
 import java.io.File;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 /**
- * Provides reusable path pattern matching.  PathPattern is preferable
- * to equivalent SelectorUtils methods if you need to execute multiple
- * matching with the same pattern because here the pattern itself will
- * be parsed only once.
+ * Provides reusable path pattern matching. {@link TokenizedPattern}
+ * is preferable to equivalent {@link SelectorUtils} methods if you need to
+ * execute multiple matching with the same pattern because here the pattern
+ * itself will be parsed only once.
  * @see SelectorUtils#matchPath(String, String)
  * @see SelectorUtils#matchPath(String, String, boolean)
  * @since 1.8.0
@@ -41,10 +43,9 @@
     private final String[] tokenizedPattern;
 
     /**
-    * Initialize the PathPattern by parsing it.
-    * @param pattern The pattern to match against. Must not be
-    *                <code>null</code>.
-    */
+     * Initialize the {@link TokenizedPattern} by parsing it.
+     * @param pattern The pattern to match against. Must not be {@code null}.
+     */
     public TokenizedPattern(String pattern) {
         this(pattern, SelectorUtils.tokenizePathAsArray(pattern));
     }
@@ -57,13 +58,13 @@
     /**
      * Tests whether or not a given path matches a given pattern.
      *
-     * @param path    The path to match, as a String. Must not be
-     *                <code>null</code>.
+     * @param path    The path to match, as a {@link String}. Must not be
+     *                {@code null}.
      * @param isCaseSensitive Whether or not matching should be performed
      *                        case sensitively.
      *
-     * @return <code>true</code> if the pattern matches against the string,
-     *         or <code>false</code> otherwise.
+     * @return {@code true} if the pattern matches against the string,
+     *         or {@code false} otherwise.
      */
     public boolean matchPath(TokenizedPath path, boolean isCaseSensitive) {
         return SelectorUtils.matchPath(tokenizedPattern, path.getTokens(),
@@ -74,9 +75,9 @@
      * Tests whether or not this pattern matches the start of
      * a path.
      *
-     * @param path TokenizedPath
-     * @param caseSensitive boolean
-     * @return boolean
+     * @param path {@link TokenizedPath}
+     * @param caseSensitive {@code boolean}
+     * @return {@code boolean}
      */
     public boolean matchStartOf(TokenizedPath path,
                                 boolean caseSensitive) {
@@ -85,34 +86,45 @@
     }
 
     /**
-     * @return The pattern String
+     * {@inheritDoc}
+     *
+     * @return The pattern {@link String}
      */
     public String toString() {
         return pattern;
     }
 
+    /**
+     * Get the pattern.
+     *
+     * @return {@link String}
+     */
     public String getPattern() {
         return pattern;
     }
 
     /**
-     * true if the original patterns are equal.
+     * {@inheritDoc}
+     * {@code true} if the original patterns are equal.
      *
-     * @param o Object
+     * @param o {@link Object}
      */
     public boolean equals(Object o) {
         return o instanceof TokenizedPattern
             && pattern.equals(((TokenizedPattern) o).pattern);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public int hashCode() {
         return pattern.hashCode();
     }
 
     /**
-     * The depth (or length) of a pattern.
+     * Get the depth (or length) of a pattern.
      *
-     * @return int
+     * @return {@code int}
      */
     public int depth() {
         return tokenizedPattern.length;
@@ -121,21 +133,16 @@
     /**
      * Does the tokenized pattern contain the given string?
      *
-     * @param pat String
-     * @return boolean
+     * @param pat {@link String}
+     * @return {@code boolean}
      */
     public boolean containsPattern(String pat) {
-        for (int i = 0; i < tokenizedPattern.length; i++) {
-            if (tokenizedPattern[i].equals(pat)) {
-                return true;
-            }
-        }
-        return false;
+        return Stream.of(tokenizedPattern).anyMatch(Predicate.isEqual(pat));
     }
 
     /**
-     * Returns a new TokenizedPath where all tokens of this pattern to
-     * the right containing wildcards have been removed
+     * Returns a new {@link TokenizedPath} where all tokens of this pattern to
+     * the right containing wildcards have been removed.
      *
      * @return the leftmost part of the pattern without wildcards
      */
@@ -161,10 +168,10 @@
     }
 
     /**
-     * true if the last token equals the given string.
+     * Learn whether the last token equals the given string.
      *
-     * @param s String
-     * @return boolean
+     * @param s {@link String}
+     * @return {@code boolean}
      */
     public boolean endsWith(String s) {
         return tokenizedPattern.length > 0
@@ -174,21 +181,21 @@
     /**
      * Returns a new pattern without the last token of this pattern.
      *
-     * @return TokenizedPattern
+     * @return {@link TokenizedPattern}
      */
     public TokenizedPattern withoutLastToken() {
         if (tokenizedPattern.length == 0) {
             throw new IllegalStateException("can't strip a token from nothing");
-        } else if (tokenizedPattern.length == 1) {
-            return EMPTY_PATTERN;
-        } else {
-            String toStrip = tokenizedPattern[tokenizedPattern.length - 1];
-            int index = pattern.lastIndexOf(toStrip);
-            String[] tokens = new String[tokenizedPattern.length - 1];
-            System.arraycopy(tokenizedPattern, 0, tokens, 0,
-                             tokenizedPattern.length - 1);
-            return new TokenizedPattern(pattern.substring(0, index), tokens);
         }
+        if (tokenizedPattern.length == 1) {
+            return EMPTY_PATTERN;
+        }
+        String toStrip = tokenizedPattern[tokenizedPattern.length - 1];
+        int index = pattern.lastIndexOf(toStrip);
+        String[] tokens = new String[tokenizedPattern.length - 1];
+        System.arraycopy(tokenizedPattern, 0, tokens, 0,
+                         tokenizedPattern.length - 1);
+        return new TokenizedPattern(pattern.substring(0, index), tokens);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/TypeSelector.java b/src/main/org/apache/tools/ant/types/selectors/TypeSelector.java
index a9d8186..fb29948 100644
--- a/src/main/org/apache/tools/ant/types/selectors/TypeSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/TypeSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,26 +30,16 @@
  */
 public class TypeSelector extends BaseExtendSelector {
 
-    private String type = null;
-
     /** Key to used for parameterized custom selector */
     public static final String TYPE_KEY = "type";
 
-    /**
-     * Creates a new <code>TypeSelector</code> instance.
-     *
-     */
-    public TypeSelector() {
-    }
+    private String type = null;
 
     /**
      * @return a string describing this object
      */
     public String toString() {
-        StringBuilder buf = new StringBuilder("{typeselector type: ");
-        buf.append(type);
-        buf.append("}");
-        return buf.toString();
+        return "{typeselector type: " + type + "}";
     }
 
     /**
@@ -66,7 +56,8 @@
      *
      * @param parameters the complete set of parameters for this selector
      */
-    public void setParameters(Parameter[] parameters) {
+    @Override
+    public void setParameters(Parameter... parameters) {
         super.setParameters(parameters);
         if (parameters != null) {
             for (Parameter parameter : parameters) {
@@ -87,6 +78,7 @@
      * means that the pattern attribute has been set.
      *
      */
+    @Override
     public void verifySettings() {
         if (type == null) {
             setError("The type attribute is required");
@@ -102,6 +94,7 @@
      * @param file is a java.io.File object the selector can use
      * @return whether the file should be selected or not
      */
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
 
         // throw BuildException on error
@@ -109,9 +102,8 @@
 
         if (file.isDirectory()) {
             return type.equals(FileType.DIR);
-        } else {
-            return type.equals(FileType.FILE);
         }
+        return type.equals(FileType.FILE);
     }
 
     /**
@@ -126,10 +118,10 @@
         /**
          * @return the values as an array of strings
          */
+        @Override
         public String[] getValues() {
             return new String[]{FILE, DIR};
         }
     }
 
-
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/WritableSelector.java b/src/main/org/apache/tools/ant/types/selectors/WritableSelector.java
index 6ffd571..a85c91c 100644
--- a/src/main/org/apache/tools/ant/types/selectors/WritableSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/WritableSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,10 +20,6 @@
 
 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 writable files.
  *
@@ -33,14 +29,11 @@
  *
  * @since Ant 1.8.0
  */
-public class WritableSelector implements FileSelector, ResourceSelector {
+public class WritableSelector implements FileSelector {
 
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
         return file != null && file.canWrite();
     }
 
-    public boolean isSelected(Resource r) {
-        FileProvider fp = r.as(FileProvider.class);
-        return fp != null && isSelected(null, null, fp.getFile());
-    }
 }
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java
index 82e043b..15395cd 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java
index 13c74c2..6eeaa62 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ChecksumAlgorithm.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ChecksumAlgorithm.java
index d497f14..4b4a148 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ChecksumAlgorithm.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ChecksumAlgorithm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
+import java.nio.file.Files;
 import java.security.NoSuchAlgorithmException;
 import java.util.Locale;
 import java.util.zip.Adler32;
@@ -105,6 +105,7 @@
      * This algorithm supports only CRC and Adler.
      * @return <i>true</i> if all is ok, otherwise <i>false</i>.
      */
+    @Override
     public boolean isValid() {
         return "CRC".equals(algorithm) || "ADLER".equals(algorithm);
     }
@@ -115,26 +116,22 @@
      * @param file    File object for which the value should be evaluated.
      * @return        The value for that file
      */
+    @Override
     public String getValue(File file) {
         initChecksum();
-        String rval = null;
 
-        try {
-            if (file.canRead()) {
-                 checksum.reset();
-                 FileInputStream fis = new FileInputStream(file);
-                 CheckedInputStream check = new CheckedInputStream(fis, checksum);
-                 BufferedInputStream in = new BufferedInputStream(check);
-                 while (in.read() != -1) {
-                     // Read the file
-                 }
-                 rval = Long.toString(check.getChecksum().getValue());
-                 in.close();
+        if (file.canRead()) {
+            checksum.reset();
+            try (CheckedInputStream check = new CheckedInputStream(
+                new BufferedInputStream(Files.newInputStream(file.toPath())), checksum)) {
+                // Read the file
+                while (check.read() != -1) {
+                }
+                return Long.toString(check.getChecksum().getValue());
+            } catch (Exception ignored) {
             }
-        } catch (Exception e) {
-            rval = null;
         }
-        return rval;
+        return null;
     }
 
 
@@ -142,11 +139,8 @@
      * Override Object.toString().
      * @return some information about this algorithm.
      */
+    @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder();
-        buf.append("<ChecksumAlgorithm:");
-        buf.append("algorithm=").append(algorithm);
-        buf.append(">");
-        return buf.toString();
+        return String.format("<ChecksumAlgorithm:algorithm=%s>", algorithm);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/DigestAlgorithm.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/DigestAlgorithm.java
index 988a256..617e550 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/DigestAlgorithm.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/DigestAlgorithm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,8 @@
 
 
 import java.io.File;
-import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
 import java.security.DigestInputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -116,13 +117,11 @@
             return;
         }
 
-        if ((provider != null) && !"".equals(provider) && !"null".equals(provider)) {
+        if (provider != null && !provider.isEmpty() && !"null".equals(provider)) {
             try {
                 messageDigest = MessageDigest.getInstance(algorithm, provider);
-            } catch (NoSuchAlgorithmException noalgo) {
-                throw new BuildException(noalgo);
-            } catch (NoSuchProviderException noprovider) {
-                throw new BuildException(noprovider);
+            } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+                throw new BuildException(e);
             }
         } else {
             try {
@@ -141,69 +140,47 @@
      * This algorithm supports only MD5 and SHA.
      * @return <i>true</i> if all is ok, otherwise <i>false</i>.
      */
+    @Override
     public boolean isValid() {
         return "SHA".equals(algorithm) || "MD5".equals(algorithm);
     }
 
-
     /**
      * Computes a value for a file content with the specified digest algorithm.
      * @param file    File object for which the value should be evaluated.
      * @return        The value for that file
      */
     // implementation adapted from ...taskdefs.Checksum, thanks to Magesh for hint
+    @Override
     public String getValue(File file) {
         if (!file.canRead()) {
             return null;
         }
         initMessageDigest();
-        String checksum = null;
-        try {
-            FileInputStream fis = null;
-
-            byte[] buf = new byte[readBufferSize];
-            try {
-                messageDigest.reset();
-                fis = new FileInputStream(file);
-                DigestInputStream dis = new DigestInputStream(fis,
-                                                              messageDigest);
-                while (dis.read(buf, 0, readBufferSize) != -1) {
-                    // do nothing
-                }
-                dis.close();
-                fis.close();
-                fis = null;
-                byte[] fileDigest = messageDigest.digest();
-                StringBuffer checksumSb = new StringBuffer();
-                for (int i = 0; i < fileDigest.length; i++) {
-                    String hexStr
-                        = Integer.toHexString(BYTE_MASK & fileDigest[i]);
-                    if (hexStr.length() < 2) {
-                        checksumSb.append("0");
-                    }
-                    checksumSb.append(hexStr);
-                }
-                checksum = checksumSb.toString();
-            } catch (Exception e) {
-                return null;
+        byte[] buf = new byte[readBufferSize];
+        messageDigest.reset();
+        try (DigestInputStream dis = new DigestInputStream(Files.newInputStream(file.toPath()),
+                messageDigest)) {
+            // read the whole stream
+            while (dis.read(buf, 0, readBufferSize) != -1) {
             }
-        } catch (Exception e) {
+            StringBuilder checksumSb = new StringBuilder();
+            for (byte digestByte : messageDigest.digest()) {
+                checksumSb.append(String.format("%02x", BYTE_MASK & digestByte));
+            }
+            return checksumSb.toString();
+        } catch (IOException ignored) {
             return null;
         }
-        return checksum;
     }
 
-
     /**
      * Override Object.toString().
      * @return some information about this algorithm.
      */
+    @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder();
-        buf.append("<DigestAlgorithm:");
-        buf.append("algorithm=").append(algorithm);
-        buf.append(";provider=").append(provider);
-        buf.append(">");
-        return buf.toString();
+        return String.format("<DigestAlgorithm:algorithm=%s;provider=%s>",
+            algorithm, provider);
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/EqualComparator.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/EqualComparator.java
index 94fb935..be00aa2 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/EqualComparator.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/EqualComparator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/HashvalueAlgorithm.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/HashvalueAlgorithm.java
index ab8849d..3ce8913 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/HashvalueAlgorithm.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/HashvalueAlgorithm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -53,18 +53,14 @@
      // Because the content is only read the file will not be damaged. I tested
      // with JPG, ZIP and PDF as binary files.
     public String getValue(File file) {
-        Reader r = null;
-        try {
-            if (!file.canRead()) {
-                return null;
-            }
-            r = new FileReader(file);
+        if (!file.canRead()) {
+            return null;
+        }
+        try (Reader r = new FileReader(file)) {
             int hash = FileUtils.readFully(r).hashCode();
             return Integer.toString(hash);
         } catch (Exception e) {
             return null;
-        } finally {
-            FileUtils.close(r);
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/LastModifiedAlgorithm.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/LastModifiedAlgorithm.java
index af8358a..a1f4c60 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/LastModifiedAlgorithm.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/LastModifiedAlgorithm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java
index 306099c..80bf4a6 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,9 +21,10 @@
 
 // Java
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Vector;
+import java.util.List;
 
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildException;
@@ -53,16 +54,16 @@
  * <p>The ModifiedSelector is implemented as a <b>CoreSelector</b> and uses default
  * values for all its attributes therefore the simplest example is</p><pre>
  *   &lt;copy todir="dest"&gt;
- *       &lt;filelist dir="src"&gt;
+ *       &lt;fileset dir="src"&gt;
  *           &lt;modified/&gt;
- *       &lt;/filelist&gt;
+ *       &lt;/fileset&gt;
  *   &lt;/copy&gt;
  * </pre>
  *
  * <p>The same example rewritten as CoreSelector with setting the all values
  * (same as defaults are) would be</p><pre>
  *   &lt;copy todir="dest"&gt;
- *       &lt;filelist dir="src"&gt;
+ *       &lt;fileset dir="src"&gt;
  *           &lt;modified update="true"
  *                     cache="propertyfile"
  *                     algorithm="digest"
@@ -70,13 +71,13 @@
  *               &lt;param name="cache.cachefile"     value="cache.properties"/&gt;
  *               &lt;param name="algorithm.algorithm" value="MD5"/&gt;
  *           &lt;/modified&gt;
- *       &lt;/filelist&gt;
+ *       &lt;/fileset&gt;
  *   &lt;/copy&gt;
  * </pre>
  *
  * <p>And the same rewritten as CustomSelector would be</p><pre>
  *   &lt;copy todir="dest"&gt;
- *       &lt;filelist dir="src"&gt;
+ *       &lt;fileset dir="src"&gt;
  *           &lt;custom class="org.apache.tools.ant.type.selectors.ModifiedSelector"&gt;
  *               &lt;param name="update"     value="true"/&gt;
  *               &lt;param name="cache"      value="propertyfile"/&gt;
@@ -85,7 +86,7 @@
  *               &lt;param name="cache.cachefile"     value="cache.properties"/&gt;
  *               &lt;param name="algorithm.algorithm" value="MD5"/&gt;
  *           &lt;/custom&gt;
- *       &lt;/filelist&gt;
+ *       &lt;/fileset&gt;
  *   &lt;/copy&gt;
  * </pre>
  *
@@ -114,7 +115,7 @@
  * comparison.</p>
  *
  * <p>A useful scenario for this selector is inside a build environment
- * for homepage generation (e.g. with <a href="http://forrest.apache.org/">
+ * for homepage generation (e.g. with <a href="https://forrest.apache.org/">
  * Apache Forrest</a>).</p><pre>
  * &lt;target name="generate-and-upload-site"&gt;
  *     &lt;echo&gt; generate the site using forrest &lt;/echo&gt;
@@ -209,7 +210,8 @@
      * Parameter vector with parameters for later initialization.
      * @see #configure
      */
-    private Vector<Parameter> configParameter = new Vector<Parameter>();
+    private List<Parameter> configParameter =
+        Collections.synchronizedList(new ArrayList<>());
 
     /**
      * Parameter vector with special parameters for later initialization.
@@ -217,7 +219,8 @@
      * These parameters are used <b>after</b> the parameters with the pattern '*'.
      * @see #configure
      */
-    private Vector<Parameter> specialParameter = new Vector<Parameter>();
+    private List<Parameter> specialParameter =
+        Collections.synchronizedList(new ArrayList<>());
 
     /** The classloader of this class. */
     private ClassLoader myClassLoader = null;
@@ -238,6 +241,7 @@
 
 
     /** Overrides BaseSelector.verifySettings(). */
+    @Override
     public void verifySettings() {
         configure();
         if (cache == null) {
@@ -283,7 +287,7 @@
         //
         Project p = getProject();
         String filename = "cache.properties";
-        File cachefile = null;
+        File cachefile;
         if (p != null) {
             // normal use inside Ant
             cachefile = new File(p.getBaseDir(), filename);
@@ -303,14 +307,14 @@
         // -----  Set the main attributes, pattern '*'  -----
         //
         for (Parameter parameter : configParameter) {
-            if (parameter.getName().indexOf(".") > 0) {
+            if (parameter.getName().indexOf('.') > 0) {
                 // this is a *.* parameter for later use
                 specialParameter.add(parameter);
             } else {
                 useParameter(parameter);
             }
         }
-        configParameter = new Vector<Parameter>();
+        configParameter.clear();
 
         // specify the algorithm classname
         if (algoName != null) {
@@ -324,17 +328,15 @@
             } else if ("lastmodified".equals(algoName.getValue())) {
                 algorithm = new LastModifiedAlgorithm();
             }
+        } else if (algorithmClass != null) {
+            // use Algorithm specified by classname
+            algorithm = loadClass(
+                algorithmClass,
+                "is not an Algorithm.",
+                Algorithm.class);
         } else {
-            if (algorithmClass != null) {
-                // use Algorithm specified by classname
-                algorithm = loadClass(
-                    algorithmClass,
-                    "is not an Algorithm.",
-                    Algorithm.class);
-            } else {
-                // nothing specified - use default
-                algorithm = defaultAlgorithm;
-            }
+            // nothing specified - use default
+            algorithm = defaultAlgorithm;
         }
 
         // specify the cache classname
@@ -343,14 +345,12 @@
             if ("propertyfile".equals(cacheName.getValue())) {
                 cache = new PropertiesfileCache();
             }
+        } else if (cacheClass != null) {
+            // use Cache specified by classname
+            cache = loadClass(cacheClass, "is not a Cache.", Cache.class);
         } else {
-            if (cacheClass != null) {
-                // use Cache specified by classname
-                cache = loadClass(cacheClass, "is not a Cache.", Cache.class);
-            } else {
-                // nothing specified - use default
-                cache = defaultCache;
-            }
+            // nothing specified - use default
+            cache = defaultCache;
         }
 
         // specify the comparator classname
@@ -366,26 +366,22 @@
                 // Have to think about lazy initialization here...  JHM
                 // comparator = new java.text.RuleBasedCollator();
             }
+        } else if (comparatorClass != null) {
+            // use Algorithm specified by classname
+            @SuppressWarnings("unchecked")
+            Comparator<? super String> localComparator = loadClass(
+                comparatorClass, "is not a Comparator.", Comparator.class);
+            comparator = localComparator;
         } else {
-            if (comparatorClass != null) {
-                // use Algorithm specified by classname
-                @SuppressWarnings("unchecked")
-                Comparator<? super String> localComparator = loadClass(comparatorClass, "is not a Comparator.", Comparator.class);
-                comparator = localComparator;
-            } else {
-                // nothing specified - use default
-                comparator = defaultComparator;
-            }
+            // nothing specified - use default
+            comparator = defaultComparator;
         }
 
         //
         // -----  Set the special attributes, pattern '*.*'  -----
         //
-        for (Iterator<Parameter> itSpecial = specialParameter.iterator(); itSpecial.hasNext();) {
-            Parameter par = itSpecial.next();
-            useParameter(par);
-        }
-        specialParameter = new Vector<Parameter>();
+        specialParameter.forEach(this::useParameter);
+        specialParameter.clear();
     }
 
 
@@ -404,21 +400,21 @@
         try {
             // load the specified class
             ClassLoader cl = getClassLoader();
-            Class<?> clazz = null;
+            Class<?> clazz;
             if (cl != null) {
                 clazz = cl.loadClass(classname);
             } else {
                 clazz = Class.forName(classname);
             }
 
-            Object rv = clazz.newInstance();
+            Object rv = clazz.getDeclaredConstructor().newInstance();
 
             if (!type.isInstance(rv)) {
-                throw new BuildException("Specified class (" + classname + ") " + msg);
+                throw new BuildException("Specified class (%s) %s", classname, msg);
             }
             return (T) rv;
         } catch (ClassNotFoundException e) {
-            throw new BuildException("Specified class (" + classname + ") not found.");
+            throw new BuildException("Specified class (%s) not found.", classname);
         } catch (Exception e) {
             throw new BuildException(e);
         }
@@ -435,6 +431,7 @@
      * @return whether the resource is selected
      * @see ResourceSelector#isSelected(Resource)
      */
+    @Override
     public boolean isSelected(Resource resource) {
         if (resource.isFilesystemOnly()) {
             // We have a 'resourced' file, so reconvert it and use
@@ -444,30 +441,29 @@
             String filename = fileResource.getName();
             File basedir = fileResource.getBaseDir();
             return isSelected(basedir, filename, file);
-        } else {
-            try {
-                // How to handle non-file-Resources? I copy temporarily the
-                // resource to a file and use the file-implementation.
-                FileUtils fu = FileUtils.getFileUtils();
-                File tmpFile = fu.createTempFile(getProject(), "modified-", ".tmp", null, true, false);
-                Resource tmpResource = new FileResource(tmpFile);
-                ResourceUtils.copyResource(resource, tmpResource);
-                boolean isSelected = isSelected(tmpFile.getParentFile(),
-                                                tmpFile.getName(),
-                                                resource.toLongString());
-                tmpFile.delete();
-                return isSelected;
-            } catch (UnsupportedOperationException uoe) {
-                log("The resource '"
-                  + resource.getName()
-                  + "' does not provide an InputStream, so it is not checked. "
-                  + "According to 'selres' attribute value it is "
-                  + ((selectResourcesWithoutInputStream) ? "" : " not")
-                  + "selected.", Project.MSG_INFO);
-                return selectResourcesWithoutInputStream;
-            } catch (Exception e) {
-                throw new BuildException(e);
-            }
+        }
+        try {
+            // How to handle non-file-Resources? I copy temporarily the
+            // resource to a file and use the file-implementation.
+            FileUtils fu = FileUtils.getFileUtils();
+            File tmpFile = fu.createTempFile(getProject(), "modified-", ".tmp", null, true, false);
+            Resource tmpResource = new FileResource(tmpFile);
+            ResourceUtils.copyResource(resource, tmpResource);
+            boolean isSelected = isSelected(tmpFile.getParentFile(),
+                                            tmpFile.getName(),
+                                            resource.toLongString());
+            tmpFile.delete();
+            return isSelected;
+        } catch (UnsupportedOperationException uoe) {
+            log("The resource '"
+              + resource.getName()
+              + "' does not provide an InputStream, so it is not checked. "
+              + "According to 'selres' attribute value it is "
+              + ((selectResourcesWithoutInputStream) ? "" : " not")
+              + "selected.", Project.MSG_INFO);
+            return selectResourcesWithoutInputStream;
+        } catch (Exception e) {
+            throw new BuildException(e);
         }
     }
 
@@ -480,11 +476,11 @@
      * @param file as described in BaseExtendSelector
      * @return as described in BaseExtendSelector
      */
+    @Override
     public boolean isSelected(File basedir, String filename, File file) {
         return isSelected(basedir, filename, file.getAbsolutePath());
     }
 
-
     /**
      * The business logic of this selector for use as ResourceSelector of
      * FileSelector.
@@ -492,7 +488,7 @@
      * @param basedir as described in BaseExtendSelector
      * @param filename as described in BaseExtendSelector
      * @param cacheKey the name for the key for storing the hashvalue
-     * @return <tt>true</tt> if the file is selected otherwise <tt>false</tt>
+     * @return <code>true</code> if the file is selected otherwise <code>false</code>
      */
     private boolean isSelected(File basedir, String filename, String cacheKey) {
         validate();
@@ -507,7 +503,7 @@
         String cachedValue = String.valueOf(cache.get(f.getAbsolutePath()));
         String newValue = algorithm.getValue(f);
 
-        boolean rv = (comparator.compare(cachedValue, newValue) != 0);
+        boolean rv = comparator.compare(cachedValue, newValue) != 0;
 
         // Maybe update the cache
         if (update && rv) {
@@ -517,7 +513,6 @@
                 saveCache();
             }
         }
-
         return rv;
     }
 
@@ -697,11 +692,10 @@
      * @see #addParam(String,Object)
      * @param parameters the parameters to set.
      */
-    public void setParameters(Parameter[] parameters) {
+    @Override
+    public void setParameters(Parameter... parameters) {
         if (parameters != null) {
-            for (int i = 0; i < parameters.length; i++) {
-                configParameter.add(parameters[i]);
-            }
+            Collections.addAll(configParameter, parameters);
         }
     }
 
@@ -735,23 +729,11 @@
             cn.setValue(value);
             setComparator(cn);
         } else if ("update".equals(key)) {
-            boolean updateValue =
-                ("true".equalsIgnoreCase(value))
-                ? true
-                : false;
-            setUpdate(updateValue);
+            setUpdate("true".equalsIgnoreCase(value));
         } else if ("delayupdate".equals(key)) {
-            boolean updateValue =
-                ("true".equalsIgnoreCase(value))
-                ? true
-                : false;
-            setDelayUpdate(updateValue);
+            setDelayUpdate("true".equalsIgnoreCase(value));
         } else if ("seldirs".equals(key)) {
-            boolean sdValue =
-                ("true".equalsIgnoreCase(value))
-                ? true
-                : false;
-            setSeldirs(sdValue);
+            setSeldirs("true".equalsIgnoreCase(value));
         } else if (key.startsWith(CACHE_PREFIX)) {
             String name = key.substring(CACHE_PREFIX.length());
             tryToSetAParameter(cache, name, value);
@@ -780,7 +762,7 @@
             = IntrospectionHelper.getHelper(prj, obj.getClass());
         try {
             iHelper.setAttribute(prj, obj, name, value);
-        } catch (org.apache.tools.ant.BuildException e) {
+        } catch (BuildException e) {
             // no-op
         }
     }
@@ -793,15 +775,10 @@
      * Override Object.toString().
      * @return information about this selector
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer("{modifiedselector");
-        buf.append(" update=").append(update);
-        buf.append(" seldirs=").append(selectDirectories);
-        buf.append(" cache=").append(cache);
-        buf.append(" algorithm=").append(algorithm);
-        buf.append(" comparator=").append(comparator);
-        buf.append("}");
-        return buf.toString();
+        return String.format("{modifiedselector update=%s seldirs=%s cache=%s algorithm=%s comparator=%s}",
+                update, selectDirectories, cache, algorithm, comparator);
     }
 
 
@@ -811,7 +788,8 @@
     /**
      * Signals that the last target has finished.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void buildFinished(BuildEvent event) {
         if (getDelayUpdate()) {
             saveCache();
@@ -822,7 +800,8 @@
     /**
      * Signals that a target has finished.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void targetFinished(BuildEvent event) {
         if (getDelayUpdate()) {
             saveCache();
@@ -833,7 +812,8 @@
     /**
      * Signals that a task has finished.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void taskFinished(BuildEvent event) {
         if (getDelayUpdate()) {
             saveCache();
@@ -844,7 +824,8 @@
     /**
      * Signals that a build has started.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void buildStarted(BuildEvent event) {
         // no-op
     }
@@ -853,7 +834,8 @@
     /**
      * Signals that a target is starting.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void targetStarted(BuildEvent event) {
         // no-op
     }
@@ -863,7 +845,8 @@
     /**
      * Signals that a task is starting.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void taskStarted(BuildEvent event) {
         // no-op
     }
@@ -872,7 +855,8 @@
     /**
      * Signals a message logging event.
      * @param event received BuildEvent
-    */
+     */
+    @Override
     public void messageLogged(BuildEvent event) {
         // no-op
     }
@@ -907,6 +891,7 @@
          * {@inheritDoc}
          * @see EnumeratedAttribute#getValues()
          */
+        @Override
         public String[] getValues() {
             return new String[] {"propertyfile"};
         }
@@ -937,6 +922,7 @@
          * {@inheritDoc}
          * @see EnumeratedAttribute#getValues()
          */
+        @Override
         public String[] getValues() {
             return new String[] {"hashvalue", "digest", "checksum", "lastmodified"};
         }
@@ -967,6 +953,7 @@
          * {@inheritDoc}
          * @see EnumeratedAttribute#getValues()
          */
+        @Override
         public String[] getValues() {
             return new String[] {"equal", "rule"};
         }
diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/PropertiesfileCache.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/PropertiesfileCache.java
index c856d56..a09e765 100644
--- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/PropertiesfileCache.java
+++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/PropertiesfileCache.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,12 +22,9 @@
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.util.Enumeration;
+import java.nio.file.Files;
 import java.util.Iterator;
 import java.util.Properties;
-import java.util.Vector;
 
 
 /**
@@ -119,6 +116,7 @@
      * This cache is valid if the cachefile is set.
      * @return true if all is ok false otherwise
      */
+    @Override
     public boolean isValid() {
         return (cachefile != null);
     }
@@ -130,13 +128,12 @@
     /**
      * Load the cache from underlying properties file.
      */
+    @Override
     public void load() {
-        if ((cachefile != null) && cachefile.isFile() && cachefile.canRead()) {
-            try {
-                BufferedInputStream bis = new BufferedInputStream(
-                    new FileInputStream(cachefile));
+        if (cachefile != null && cachefile.isFile() && cachefile.canRead()) {
+            try (BufferedInputStream bis = new BufferedInputStream(
+                Files.newInputStream(cachefile.toPath()))) {
                 cache.load(bis);
-                bis.close();
             } catch (Exception e) {
                 e.printStackTrace(); //NOSONAR
             }
@@ -153,17 +150,16 @@
      * implementation checks the existence of entries before creating the file
      * for performance optimisation.
      */
+    @Override
     public void save() {
         if (!cacheDirty) {
             return;
         }
-        if ((cachefile != null) && cache.propertyNames().hasMoreElements()) {
-            try {
-                BufferedOutputStream bos = new BufferedOutputStream(
-                      new FileOutputStream(cachefile));
+        if (cachefile != null && cache.propertyNames().hasMoreElements()) {
+            try (BufferedOutputStream bos = new BufferedOutputStream(
+                Files.newOutputStream(cachefile.toPath()))) {
                 cache.store(bos, null);
                 bos.flush();
-                bos.close();
             } catch (Exception e) {
                 e.printStackTrace(); //NOSONAR
             }
@@ -172,6 +168,7 @@
     }
 
     /** Deletes the cache and its underlying file. */
+    @Override
     public void delete() {
         cache = new Properties();
         cachefile.delete();
@@ -184,6 +181,7 @@
      * @param key the key
      * @return the stored value
      */
+    @Override
     public Object get(Object key) {
         if (!cacheLoaded) {
             load();
@@ -200,6 +198,7 @@
      * @param key the key
      * @param value the value
      */
+    @Override
     public void put(Object key, Object value) {
         cache.put(String.valueOf(key), String.valueOf(value));
         cacheDirty = true;
@@ -209,13 +208,9 @@
      * Returns an iterator over the keys in the cache.
      * @return An iterator over the keys.
      */
+    @Override
     public Iterator<String> iterator() {
-        Vector<String> v = new Vector<String>();
-        Enumeration<?> en = cache.propertyNames();
-        while (en.hasMoreElements()) {
-            v.add(en.nextElement().toString());
-        }
-        return v.iterator();
+        return cache.stringPropertyNames().iterator();
     }
 
 
@@ -226,12 +221,9 @@
      * Override Object.toString().
      * @return information about this cache
      */
+    @Override
     public String toString() {
-        StringBuffer buf = new StringBuffer();
-        buf.append("<PropertiesfileCache:");
-        buf.append("cachefile=").append(cachefile);
-        buf.append(";noOfEntries=").append(cache.size());
-        buf.append(">");
-        return buf.toString();
+        return String.format("<PropertiesfileCache:cachefile=%s;noOfEntries=%d>",
+                cachefile, cache.size());
     }
 }
diff --git a/src/main/org/apache/tools/ant/types/spi/Provider.java b/src/main/org/apache/tools/ant/types/spi/Provider.java
index f73b019..9ec652c 100644
--- a/src/main/org/apache/tools/ant/types/spi/Provider.java
+++ b/src/main/org/apache/tools/ant/types/spi/Provider.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,8 +25,8 @@
  * This class corresponds to the nested element
  * &lt;provider type="type"&gt; in the &lt;service type=""&gt;
  * nested element of the jar task.
- * @see <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=31520">
- * http://issues.apache.org/bugzilla/show_bug.cgi?id=31520</a>
+ * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=31520">
+ * https://issues.apache.org/bugzilla/show_bug.cgi?id=31520</a>
  */
 public class Provider extends ProjectComponent {
     private String type;
@@ -55,7 +55,7 @@
                 "classname attribute must be set for provider element",
                 getLocation());
         }
-        if (type.length() == 0) {
+        if (type.isEmpty()) {
             throw new BuildException(
                 "Invalid empty classname", getLocation());
         }
diff --git a/src/main/org/apache/tools/ant/types/spi/Service.java b/src/main/org/apache/tools/ant/types/spi/Service.java
index 96c8e4e..b68cd8b 100644
--- a/src/main/org/apache/tools/ant/types/spi/Service.java
+++ b/src/main/org/apache/tools/ant/types/spi/Service.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,12 @@
 package org.apache.tools.ant.types.spi;
 
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.ProjectComponent;
@@ -32,11 +31,11 @@
 /**
  * ANT Jar-Task SPI extension
  *
- * @see <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=31520">
- * http://issues.apache.org/bugzilla/show_bug.cgi?id=31520</a>
+ * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=31520">
+ * https://issues.apache.org/bugzilla/show_bug.cgi?id=31520</a>
  */
 public class Service extends ProjectComponent {
-    private List<Provider> providerList = new ArrayList<Provider>();
+    private List<Provider> providerList = new ArrayList<>();
     private String type;
 
     /**
@@ -83,14 +82,9 @@
      * @throws IOException if there is an error.
      */
     public InputStream getAsStream() throws IOException {
-        ByteArrayOutputStream arrayOut = new ByteArrayOutputStream();
-        Writer writer = new OutputStreamWriter(arrayOut, "UTF-8");
-        for (Provider provider : providerList) {
-            writer.write(provider.getClassName());
-            writer.write("\n");
-        }
-        writer.close();
-        return new ByteArrayInputStream(arrayOut.toByteArray());
+        return new ByteArrayInputStream(
+            providerList.stream().map(Provider::getClassName)
+                .collect(Collectors.joining("\n")).getBytes(StandardCharsets.UTF_8));
     }
 
     /**
@@ -103,11 +97,11 @@
                 "type attribute must be set for service element",
                 getLocation());
         }
-        if (type.length() == 0) {
+        if (type.isEmpty()) {
             throw new BuildException(
                 "Invalid empty type classname", getLocation());
         }
-        if (providerList.size() == 0) {
+        if (providerList.isEmpty()) {
             throw new BuildException(
                 "provider attribute or nested provider element must be set!",
                 getLocation());
diff --git a/src/main/org/apache/tools/ant/util/Base64Converter.java b/src/main/org/apache/tools/ant/util/Base64Converter.java
index 4f62b03..781e3fd 100644
--- a/src/main/org/apache/tools/ant/util/Base64Converter.java
+++ b/src/main/org/apache/tools/ant/util/Base64Converter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/ChainedMapper.java b/src/main/org/apache/tools/ant/util/ChainedMapper.java
index 6e07aa6..6f5ee7e 100644
--- a/src/main/org/apache/tools/ant/util/ChainedMapper.java
+++ b/src/main/org/apache/tools/ant/util/ChainedMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,8 @@
 
 package org.apache.tools.ant.util;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
 
 /**
  * A <code>ContainerMapper</code> that chains the results of the first
@@ -32,32 +30,17 @@
 public class ChainedMapper extends ContainerMapper {
 
     /** {@inheritDoc}. */
+    @Override
     public String[] mapFileName(String sourceFileName) {
-        List inputs = new ArrayList();
-        List results = new ArrayList();
-        // we do this even if the sourceFileName is null. Some
+        // we invoke the chain even if the sourceFileName is null. Some
         // resources have a null name and users may use a mapper like
         // MergeMapper to provide a name for it.
-        results.add(sourceFileName);
-        FileNameMapper mapper = null;
-
-        for (Iterator mIter = getMappers().iterator(); mIter.hasNext();) {
-            mapper = (FileNameMapper) (mIter.next());
-            if (mapper != null) {
-                inputs.clear();
-                inputs.addAll(results);
-                results.clear();
-
-                for (Iterator it = inputs.iterator(); it.hasNext();) {
-                    String[] mapped = mapper.mapFileName((String) (it.next()));
-                    if (mapped != null) {
-                        results.addAll(Arrays.asList(mapped));
-                    }
-                }
-            }
-        }
-        return (results.size() == 0) ? null
-            : (String[]) results.toArray(new String[results.size()]);
+        String[] result = getMappers().stream()
+            .filter(Objects::nonNull)
+            .reduce(new String[] { sourceFileName }, (i, m) -> Stream.of(i)
+                .map(m::mapFileName).filter(Objects::nonNull).flatMap(Stream::of).toArray(String[]::new),
+                (i, o) -> o);
+        return result == null || result.length == 0 ? null : result;
     }
 }
 
diff --git a/src/main/org/apache/tools/ant/util/ClasspathUtils.java b/src/main/org/apache/tools/ant/util/ClasspathUtils.java
index 8b24610..e14ed3e 100644
--- a/src/main/org/apache/tools/ant/util/ClasspathUtils.java
+++ b/src/main/org/apache/tools/ant/util/ClasspathUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,6 +25,9 @@
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
 // CheckStyle:HideUtilityClassConstructorCheck OFF - bc
 
 /**
@@ -107,8 +110,9 @@
         String pathId = ref.getRefId();
         Object path = p.getReference(pathId);
         if (!(path instanceof Path)) {
-            throw new BuildException("The specified classpathref " + pathId
-                    + " does not reference a Path.");
+            throw new BuildException(
+                "The specified classpathref %s does not reference a Path.",
+                pathId);
         }
         String loaderId = MagicNames.REFID_CLASSPATH_LOADER_PREFIX + pathId;
         return getClassLoaderForPath(p, (Path) path, loaderId, reverseLoader);
@@ -174,8 +178,9 @@
         if (loaderId != null && reuseLoader) {
             Object reusedLoader = p.getReference(loaderId);
             if (reusedLoader != null && !(reusedLoader instanceof ClassLoader)) {
-                throw new BuildException("The specified loader id " + loaderId
-                        + " does not reference a class loader");
+                throw new BuildException(
+                    "The specified loader id %s does not reference a class loader",
+                    loaderId);
             }
             cl = (ClassLoader) reusedLoader;
         }
@@ -232,6 +237,7 @@
      * <p>This uses the userDefinedLoader to load the specified class,
      * and then makes an instance using the default no-argument constructor.</p>
      *
+     * @param <T> desired type
      * @param className the full qualified class name to load.
      * @param userDefinedLoader the classloader to use.
      * @param expectedType the Class that the result should be assignment
@@ -241,14 +247,19 @@
      * @throws BuildException when loading or instantiation failed.
      * @since Ant 1.7
      */
-    public static Object newInstance(String className, ClassLoader userDefinedLoader,
-            Class expectedType) {
+    public static <T> T newInstance(String className, ClassLoader userDefinedLoader,
+            Class<T> expectedType) {
         try {
-            Class clazz = Class.forName(className, true, userDefinedLoader);
-            Object o = clazz.newInstance();
+            @SuppressWarnings("unchecked")
+            Class<T> clazz = (Class<T>) Class.forName(className, true, userDefinedLoader);
+            if (Modifier.isAbstract(clazz.getModifiers())) {
+                throw new BuildException("Abstract class " + className);
+            }
+            T o = clazz.getDeclaredConstructor().newInstance();
             if (!expectedType.isInstance(o)) {
-                throw new BuildException("Class of unexpected Type: " + className + " expected :"
-                        + expectedType);
+                throw new BuildException(
+                    "Class of unexpected Type: %s expected : %s", className,
+                    expectedType);
             }
             return o;
         } catch (ClassNotFoundException e) {
@@ -256,7 +267,7 @@
         } catch (InstantiationException e) {
             throw new BuildException("Could not instantiate " + className
                     + ". Specified class should have a no " + "argument constructor.", e);
-        } catch (IllegalAccessException e) {
+        } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
             throw new BuildException("Could not instantiate " + className
                     + ". Specified class should have a " + "public constructor.", e);
         } catch (LinkageError e) {
@@ -284,6 +295,9 @@
         return p.getProperty(REUSE_LOADER_REF) != null;
     }
 
+    private ClasspathUtils() {
+    }
+
     /**
      * Delegate that helps out any specific ProjectComponent that needs
      * dynamic classloading.
@@ -455,7 +469,5 @@
             return reverseLoader;
         }
 
-        //TODO no methods yet for getClassname
-        //TODO no method for newInstance using a reverse-classloader
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/CollectionUtils.java b/src/main/org/apache/tools/ant/util/CollectionUtils.java
index d0ee552..e957835 100644
--- a/src/main/org/apache/tools/ant/util/CollectionUtils.java
+++ b/src/main/org/apache/tools/ant/util/CollectionUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,9 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 // CheckStyle:HideUtilityClassConstructorCheck OFF - bc
 
@@ -34,6 +36,7 @@
  *
  * @since Ant 1.5
  */
+@Deprecated
 public class CollectionUtils {
 
     @SuppressWarnings("rawtypes")
@@ -50,15 +53,7 @@
      */
     @Deprecated
     public static boolean equals(Vector<?> v1, Vector<?> v2) {
-        if (v1 == v2) {
-            return true;
-        }
-
-        if (v1 == null || v2 == null) {
-            return false;
-        }
-
-        return v1.equals(v2);
+        return Objects.equals(v1, v2);
     }
 
     /**
@@ -86,20 +81,10 @@
             return false;
         }
 
-        Enumeration<?> e1 = d1.keys();
-        while (e1.hasMoreElements()) {
-            Object key = e1.nextElement();
-            Object value1 = d1.get(key);
-            Object value2 = d2.get(key);
-            if (value2 == null || !value1.equals(value2)) {
-                return false;
-            }
-        }
-
         // don't need the opposite check as the Dictionaries have the
         // same size, so we've also covered all keys of d2 already.
-
-        return true;
+        return StreamUtils.enumerationAsStream(d1.keys())
+                .allMatch(key -> d1.get(key).equals(d2.get(key)));
     }
 
     /**
@@ -109,16 +94,11 @@
      * @param c collection to transform
      * @return string representation of the collection
      * @since Ant 1.8.0
+     * @deprecated use stream().collect(Collectors.joining(","))
      */
+    @Deprecated
     public static String flattenToString(Collection<?> c) {
-        final StringBuilder sb = new StringBuilder();
-        for (Object o : c) {
-            if (sb.length() != 0) {
-                sb.append(",");
-            }
-            sb.append(o);
-        }
-        return sb.toString();
+        return c.stream().map(String::valueOf).collect(Collectors.joining(","));
     }
 
     /**
@@ -131,25 +111,22 @@
      * @deprecated since 1.6.x.
      */
     @Deprecated
-    public static <K, V> void putAll(Dictionary<? super K, ? super V> m1, Dictionary<? extends K, ? extends V> m2) {
-        for (Enumeration<? extends K> it = m2.keys(); it.hasMoreElements();) {
-            K key = it.nextElement();
-            m1.put(key, m2.get(key));
-        }
+    public static <K, V> void putAll(Dictionary<? super K, ? super V> m1,
+        Dictionary<? extends K, ? extends V> m2) {
+        StreamUtils.enumerationAsStream(m2.keys()).forEach(key -> m1.put(key, m2.get(key)));
     }
 
     /**
      * An empty enumeration.
      * @since Ant 1.6
      */
+    @Deprecated
     public static final class EmptyEnumeration<E> implements Enumeration<E> {
-        /** Constructor for the EmptyEnumeration */
-        public EmptyEnumeration() {
-        }
 
         /**
          * @return false always.
          */
+        @Override
         public boolean hasMoreElements() {
             return false;
         }
@@ -158,6 +135,7 @@
          * @return nothing.
          * @throws NoSuchElementException always.
          */
+        @Override
         public E nextElement() throws NoSuchElementException {
             throw new NoSuchElementException();
         }
@@ -171,9 +149,12 @@
      * @param <E> element type
      * @return an enumeration representing e1 followed by e2.
      * @since Ant 1.6.3
+     * @deprecated use Stream.concat(Collections.list(e1).stream(), Collections.list(e2).stream())
+     *                 .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::enumeration))
      */
+    @Deprecated
     public static <E> Enumeration<E> append(Enumeration<E> e1, Enumeration<E> e2) {
-        return new CompoundEnumeration<E>(e1, e2);
+        return new CompoundEnumeration<>(e1, e2);
     }
 
     /**
@@ -181,12 +162,16 @@
      * @param iter the Iterator to adapt.
      * @param <E> element type
      * @return an Enumeration.
+     * @deprecated use Collections.enumeration()
      */
+    @Deprecated
     public static <E> Enumeration<E> asEnumeration(final Iterator<E> iter) {
         return new Enumeration<E>() {
+            @Override
             public boolean hasMoreElements() {
                 return iter.hasNext();
             }
+            @Override
             public E nextElement() {
                 return iter.next();
             }
@@ -198,15 +183,20 @@
      * @param e the Enumeration to adapt.
      * @param <E> element type
      * @return an Iterator.
+     * @deprecated use Collections.list(e).iterator()
      */
+    @Deprecated
     public static <E> Iterator<E> asIterator(final Enumeration<E> e) {
         return new Iterator<E>() {
+            @Override
             public boolean hasNext() {
                 return e.hasMoreElements();
             }
+            @Override
             public E next() {
                 return e.nextElement();
             }
+            @Override
             public void remove() {
                 throw new UnsupportedOperationException();
             }
@@ -220,12 +210,12 @@
      * @param <T> element type
      * @return the collection
      * @since Ant 1.8.0
+     * @deprecated instantiate a list and use forEachRemaining(list::add)
      */
+    @Deprecated
     public static <T> Collection<T> asCollection(final Iterator<? extends T> iter) {
-        List<T> l = new ArrayList<T>();
-        while (iter.hasNext()) {
-            l.add(iter.next());
-        }
+        List<T> l = new ArrayList<>();
+        iter.forEachRemaining(l::add);
         return l;
     }
 
@@ -238,16 +228,17 @@
             this.e2 = e2;
         }
 
+        @Override
         public boolean hasMoreElements() {
             return e1.hasMoreElements() || e2.hasMoreElements();
         }
 
+        @Override
         public E nextElement() throws NoSuchElementException {
             if (e1.hasMoreElements()) {
                 return e1.nextElement();
-            } else {
-                return e2.nextElement();
             }
+            return e2.nextElement();
         }
 
     }
@@ -261,18 +252,11 @@
      * @return frequency
      * @since Ant 1.8.0
      */
+    @Deprecated
     public static int frequency(Collection<?> c, Object o) {
-        // same as Collections.frequency introduced with JDK 1.5
-        int freq = 0;
-        if (c != null) {
-            for (Iterator<?> i = c.iterator(); i.hasNext();) {
-                Object test = i.next();
-                if (o == null ? test == null : o.equals(test)) {
-                    freq++;
-                }
-            }
-        }
-        return freq;
+        return c == null ? 0 : Collections.frequency(c, o);
     }
 
+    private CollectionUtils() {
+    }
 }
diff --git a/src/main/org/apache/tools/ant/util/CompositeMapper.java b/src/main/org/apache/tools/ant/util/CompositeMapper.java
index d04a5fc..eff02b4 100644
--- a/src/main/org/apache/tools/ant/util/CompositeMapper.java
+++ b/src/main/org/apache/tools/ant/util/CompositeMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,8 @@
  */
 package org.apache.tools.ant.util;
 
-import java.util.Iterator;
-import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.stream.Stream;
 
 /**
  * A <code>ContainerMapper</code> that unites the results of its constituent
@@ -28,23 +28,9 @@
 
     /** {@inheritDoc}. */
     public String[] mapFileName(String sourceFileName) {
-        LinkedHashSet results = new LinkedHashSet();
-
-        FileNameMapper mapper = null;
-        for (Iterator mIter = getMappers().iterator(); mIter.hasNext();) {
-            mapper = (FileNameMapper) (mIter.next());
-            if (mapper != null) {
-                String[] mapped = mapper.mapFileName(sourceFileName);
-                if (mapped != null) {
-                    for (int i = 0; i < mapped.length; i++) {
-                        results.add(mapped[i]);
-                    }
-                }
-            }
-        }
-        return (results.size() == 0) ? null
-            : (String[]) results.toArray(new String[results.size()]);
+        String[] result = getMappers().stream().filter(Objects::nonNull)
+            .map(m -> m.mapFileName(sourceFileName)).filter(Objects::nonNull)
+            .flatMap(Stream::of).toArray(String[]::new);
+        return result.length == 0 ? null : result;
     }
-
 }
-
diff --git a/src/main/org/apache/tools/ant/util/ConcatFileInputStream.java b/src/main/org/apache/tools/ant/util/ConcatFileInputStream.java
index 22dcb7f..f164271 100644
--- a/src/main/org/apache/tools/ant/util/ConcatFileInputStream.java
+++ b/src/main/org/apache/tools/ant/util/ConcatFileInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,9 +20,9 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectComponent;
@@ -55,6 +55,7 @@
      * Close the stream.
      * @throws IOException if there is an error.
      */
+    @Override
     public void close() throws IOException {
         closeCurrent();
         eof = true;
@@ -65,6 +66,7 @@
      * @return the byte (0 - 255) or -1 if this is the end of the stream.
      * @throws IOException if there is an error.
      */
+    @Override
     public int read() throws IOException {
         int result = readCurrent();
         if (result == EOF && !eof) {
@@ -119,7 +121,7 @@
             log("Opening " + file[index], Project.MSG_VERBOSE);
             try {
                 currentStream = new BufferedInputStream(
-                    new FileInputStream(file[index]));
+                    Files.newInputStream(file[index].toPath()));
             } catch (IOException eyeOhEx) {
                 log("Failed to open " + file[index], Project.MSG_ERR);
                 throw eyeOhEx;
diff --git a/src/main/org/apache/tools/ant/util/ConcatResourceInputStream.java b/src/main/org/apache/tools/ant/util/ConcatResourceInputStream.java
index 6c68747..1f0a164 100644
--- a/src/main/org/apache/tools/ant/util/ConcatResourceInputStream.java
+++ b/src/main/org/apache/tools/ant/util/ConcatResourceInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -71,6 +71,7 @@
      * Close the stream.
      * @throws IOException if there is an error.
      */
+    @Override
      public void close() throws IOException {
         closeCurrent();
         eof = true;
@@ -81,6 +82,7 @@
      * @return the byte (0 - 255) or -1 if this is the end of the stream.
      * @throws IOException if there is an error.
      */
+    @Override
     public int read() throws IOException {
         if (eof) {
             return EOF;
@@ -122,7 +124,7 @@
     private void nextResource() throws IOException {
         closeCurrent();
         while (iter.hasNext()) {
-            Resource r = (Resource) iter.next();
+            Resource r = iter.next();
             if (!r.isExists()) {
                 continue;
             }
diff --git a/src/main/org/apache/tools/ant/util/ContainerMapper.java b/src/main/org/apache/tools/ant/util/ContainerMapper.java
index 990ee14..a818f24 100644
--- a/src/main/org/apache/tools/ant/util/ContainerMapper.java
+++ b/src/main/org/apache/tools/ant/util/ContainerMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,6 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 
 import org.apache.tools.ant.types.Mapper;
@@ -32,7 +31,7 @@
  */
 public abstract class ContainerMapper implements FileNameMapper {
 
-    private List mappers = new ArrayList();
+    private List<FileNameMapper> mappers = new ArrayList<>();
 
     /**
      * Add a <code>Mapper</code>.
@@ -69,9 +68,8 @@
             && ((ContainerMapper) fileNameMapper).contains(this))) {
             throw new IllegalArgumentException(
                 "Circular mapper containment condition detected");
-        } else {
-            mappers.add(fileNameMapper);
         }
+        mappers.add(fileNameMapper);
     }
 
     /**
@@ -81,21 +79,23 @@
      * @return <code>boolean</code>.
      */
     protected synchronized boolean contains(FileNameMapper fileNameMapper) {
-        boolean foundit = false;
-        for (Iterator iter = mappers.iterator(); iter.hasNext() && !foundit;) {
-            FileNameMapper next = (FileNameMapper) (iter.next());
-            foundit = (next == fileNameMapper
-                || (next instanceof ContainerMapper
-                && ((ContainerMapper) next).contains(fileNameMapper)));
+        for (FileNameMapper m : mappers) {
+            if (m == fileNameMapper) {
+                return true;
+            }
+            if (m instanceof ContainerMapper
+                && ((ContainerMapper) m).contains(fileNameMapper)) {
+                return true;
+            }
         }
-        return foundit;
+        return false;
     }
 
     /**
      * Get the <code>List</code> of <code>FileNameMapper</code>s.
      * @return <code>List</code>.
      */
-    public synchronized List getMappers() {
+    public synchronized List<FileNameMapper> getMappers() {
         return Collections.unmodifiableList(mappers);
     }
 
@@ -103,6 +103,7 @@
      * Empty implementation.
      * @param ignore ignored.
      */
+    @Override
     public void setFrom(String ignore) {
         //Empty
     }
@@ -111,6 +112,7 @@
      * Empty implementation.
      * @param ignore ignored.
      */
+    @Override
     public void setTo(String ignore) {
         //Empty
     }
diff --git a/src/main/org/apache/tools/ant/util/DOMElementWriter.java b/src/main/org/apache/tools/ant/util/DOMElementWriter.java
index 78a893b..fe2c11a 100644
--- a/src/main/org/apache/tools/ant/util/DOMElementWriter.java
+++ b/src/main/org/apache/tools/ant/util/DOMElementWriter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,9 +23,11 @@
 import java.io.OutputStreamWriter;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
@@ -68,7 +70,7 @@
     /**
      * Map (URI to prefix) of known namespaces.
      */
-    private HashMap nsPrefixMap = new HashMap();
+    private Map<String, String> nsPrefixMap = new HashMap<>();
 
     /**
      * Number of generated prefix to use next.
@@ -78,7 +80,7 @@
     /**
      * Map (Element to URI) of namespaces defined on a given element.
      */
-    private HashMap nsURIByElement = new HashMap();
+    private Map<Element, List<String>> nsURIByElement = new HashMap<>();
 
     /**
      * Whether namespaces should be ignored for elements and attributes.
@@ -150,8 +152,6 @@
         this.namespacePolicy = namespacePolicy;
     }
 
-    private static String lSep = System.getProperty("line.separator");
-
     // CheckStyle:VisibilityModifier OFF - bc
     /**
      * Don't try to be too smart but at least recognize the predefined
@@ -171,7 +171,7 @@
      * @throws IOException if an error happens while writing to the stream.
      */
     public void write(Element root, OutputStream out) throws IOException {
-        Writer wri = new OutputStreamWriter(out, "UTF8");
+        Writer wri = new OutputStreamWriter(out, StandardCharsets.UTF_8);
         writeXMLDeclaration(wri);
         write(root, wri, 0, "  ");
         wri.flush();
@@ -218,7 +218,7 @@
                 case Node.ELEMENT_NODE:
                     hasChildElements = true;
                     if (i == 0) {
-                        out.write(lSep);
+                        out.write(System.lineSeparator());
                     }
                     write((Element) child, out, indent + 1, indentWith);
                     break;
@@ -249,7 +249,7 @@
                     out.write("<?");
                     out.write(child.getNodeName());
                     String data = child.getNodeValue();
-                    if (data != null && data.length() > 0) {
+                    if (data != null && !data.isEmpty()) {
                         out.write(' ');
                         out.write(data);
                     }
@@ -305,7 +305,7 @@
         out.write("<");
         if (namespacePolicy.qualifyElements) {
             String uri = getNamespaceURI(element);
-            String prefix = (String) nsPrefixMap.get(uri);
+            String prefix = nsPrefixMap.get(uri);
             if (prefix == null) {
                 if (nsPrefixMap.isEmpty()) {
                     // steal default namespace
@@ -316,7 +316,7 @@
                 nsPrefixMap.put(uri, prefix);
                 addNSDefinition(element, uri);
             }
-            if (!"".equals(prefix)) {
+            if (!prefix.isEmpty()) {
                 out.write(prefix);
                 out.write(":");
             }
@@ -330,7 +330,7 @@
             out.write(" ");
             if (namespacePolicy.qualifyAttributes) {
                 String uri = getNamespaceURI(attr);
-                String prefix = (String) nsPrefixMap.get(uri);
+                String prefix = nsPrefixMap.get(uri);
                 if (prefix == null) {
                     prefix = NS + (nextPrefix++);
                     nsPrefixMap.put(uri, prefix);
@@ -346,14 +346,12 @@
         }
 
         // write namespace declarations
-        ArrayList al = (ArrayList) nsURIByElement.get(element);
-        if (al != null) {
-            Iterator iter = al.iterator();
-            while (iter.hasNext()) {
-                String uri = (String) iter.next();
-                String prefix = (String) nsPrefixMap.get(uri);
+        List<String> uris = nsURIByElement.get(element);
+        if (uris != null) {
+            for (String uri : uris) {
+                String prefix = nsPrefixMap.get(uri);
                 out.write(" xmlns");
-                if (!"".equals(prefix)) {
+                if (!prefix.isEmpty()) {
                     out.write(":");
                     out.write(prefix);
                 }
@@ -367,8 +365,7 @@
             out.write(">");
         } else {
             removeNSDefinitions(element);
-            out.write(" />");
-            out.write(lSep);
+            out.write(String.format(" />%n"));
             out.flush();
         }
     }
@@ -400,16 +397,15 @@
         out.write("</");
         if (namespacePolicy.qualifyElements) {
             String uri = getNamespaceURI(element);
-            String prefix = (String) nsPrefixMap.get(uri);
-            if (prefix != null && !"".equals(prefix)) {
+            String prefix = nsPrefixMap.get(uri);
+            if (prefix != null && !prefix.isEmpty()) {
                 out.write(prefix);
                 out.write(":");
             }
             removeNSDefinitions(element);
         }
         out.write(element.getTagName());
-        out.write(">");
-        out.write(lSep);
+        out.write(String.format(">%n"));
         out.flush();
     }
 
@@ -435,10 +431,8 @@
     }
 
     private String encode(final String value, final boolean encodeWhitespace) {
-        final int len = value.length();
-        final StringBuffer sb = new StringBuffer(len);
-        for (int i = 0; i < len; i++) {
-            final char c = value.charAt(i);
+        final StringBuilder sb = new StringBuilder(value.length());
+        for (final char c : value.toCharArray()) {
             switch (c) {
             case '<':
                 sb.append("&lt;");
@@ -482,10 +476,10 @@
      * <code>&amp;#x5d;&amp;#x5d;&amp;gt;</code>.</p>
      *
      * <p>See XML 1.0 2.2 <a
-     * href="http://www.w3.org/TR/1998/REC-xml-19980210#charsets">
-     * http://www.w3.org/TR/1998/REC-xml-19980210#charsets</a> and
+     * href="https://www.w3.org/TR/1998/REC-xml-19980210#charsets">
+     * https://www.w3.org/TR/1998/REC-xml-19980210#charsets</a> and
      * 2.7 <a
-     * href="http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p>
+     * href="https://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">https://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p>
      * @param value the value to be encoded.
      * @return the encoded value.
      */
@@ -508,10 +502,10 @@
      * <code>&amp;#x5d;&amp;#x5d;&amp;gt;</code>.</p>
      *
      * <p>See XML 1.0 2.2 <a
-     * href="http://www.w3.org/TR/1998/REC-xml-19980210#charsets">
-     * http://www.w3.org/TR/1998/REC-xml-19980210#charsets</a> and
+     * href="https://www.w3.org/TR/1998/REC-xml-19980210#charsets">
+     * https://www.w3.org/TR/1998/REC-xml-19980210#charsets</a> and
      * 2.7 <a
-     * href="http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p>
+     * href="https://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">https://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p>
      * @param value the value to be encoded.
      * @param out where to write the encoded data to.
      * @throws IOException if data cannot be written
@@ -523,13 +517,12 @@
         while (prevEnd < len) {
             final int end = (cdataEndPos < 0 ? len : cdataEndPos);
             // Write out stretches of legal characters in the range [prevEnd, end).
-            for (int prevLegalCharPos = prevEnd; prevLegalCharPos < end;/*empty*/) {
-                int illegalCharPos;
-                for (illegalCharPos = prevLegalCharPos; true; ++illegalCharPos) {
-                    if (illegalCharPos >= end
-                        || !isLegalCharacter(value.charAt(illegalCharPos))) {
-                        break;
-                    }
+            int prevLegalCharPos = prevEnd;
+            while (prevLegalCharPos < end) {
+                int illegalCharPos = prevLegalCharPos;
+                while (illegalCharPos < end
+                        && isLegalCharacter(value.charAt(illegalCharPos))) {
+                    ++illegalCharPos;
                 }
                 out.write(value, prevLegalCharPos, illegalCharPos - prevLegalCharPos);
                 prevLegalCharPos = illegalCharPos + 1;
@@ -551,7 +544,7 @@
      * @return true if it is an entity.
      */
     public boolean isReference(String ent) {
-        if (!(ent.charAt(0) == '&') || !ent.endsWith(";")) {
+        if (ent.charAt(0) != '&' || !ent.endsWith(";")) {
             return false;
         }
 
@@ -588,55 +581,59 @@
      * Is the given character allowed inside an XML document?
      *
      * <p>See XML 1.0 2.2 <a
-     * href="http://www.w3.org/TR/1998/REC-xml-19980210#charsets">
-     * http://www.w3.org/TR/1998/REC-xml-19980210#charsets</a>.</p>
+     * href="https://www.w3.org/TR/1998/REC-xml-19980210#charsets">
+     * https://www.w3.org/TR/1998/REC-xml-19980210#charsets</a>.</p>
      * @param c the character to test.
      * @return true if the character is allowed.
      * @since 1.10, Ant 1.5
      */
     public boolean isLegalCharacter(final char c) {
+        return isLegalXmlCharacter(c);
+    }
+
+    /**
+     * Is the given character allowed inside an XML document?
+     *
+     * <p>See XML 1.0 2.2 <a
+     * href="https://www.w3.org/TR/1998/REC-xml-19980210#charsets">
+     * https://www.w3.org/TR/1998/REC-xml-19980210#charsets</a>.</p>
+     * @param c the character to test.
+     * @return true if the character is allowed.
+     * @since 1.10.10
+     */
+    public static boolean isLegalXmlCharacter(final char c) {
         // CheckStyle:MagicNumber OFF
         if (c == 0x9 || c == 0xA || c == 0xD) {
             return true;
-        } else if (c < 0x20) {
+        }
+        if (c < 0x20) {
             return false;
-        } else if (c <= 0xD7FF) {
-            return true;
-        } else if (c < 0xE000) {
-            return false;
-        } else if (c <= 0xFFFD) {
+        }
+        if (c <= 0xD7FF) {
             return true;
         }
+        if (c < 0xE000) {
+            return false;
+        }
+        return c <= 0xFFFD;
         // CheckStyle:MagicNumber ON
-        return false;
     }
 
     private void removeNSDefinitions(Element element) {
-        ArrayList al = (ArrayList) nsURIByElement.get(element);
-        if (al != null) {
-            Iterator iter = al.iterator();
-            while (iter.hasNext()) {
-                nsPrefixMap.remove(iter.next());
-            }
+        List<String> uris = nsURIByElement.get(element);
+        if (uris != null) {
+            uris.forEach(nsPrefixMap::remove);
             nsURIByElement.remove(element);
         }
     }
 
     private void addNSDefinition(Element element, String uri) {
-        ArrayList al = (ArrayList) nsURIByElement.get(element);
-        if (al == null) {
-            al = new ArrayList();
-            nsURIByElement.put(element, al);
-        }
-        al.add(uri);
+        nsURIByElement.computeIfAbsent(element, e -> new ArrayList<>())
+            .add(uri);
     }
 
     private static String getNamespaceURI(Node n) {
         String uri = n.getNamespaceURI();
-        if (uri == null) {
-            // FIXME: Is "No Namespace is Empty Namespace" really OK?
-            uri = "";
-        }
-        return uri;
+        return uri == null ? "" : uri;
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/DOMUtils.java b/src/main/org/apache/tools/ant/util/DOMUtils.java
index db00213..a784f2a 100644
--- a/src/main/org/apache/tools/ant/util/DOMUtils.java
+++ b/src/main/org/apache/tools/ant/util/DOMUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -160,4 +160,7 @@
         Element e = createChildElement(parent, name);
         appendCDATA(e, content);
     }
+
+    private DOMUtils() {
+    }
 }
diff --git a/src/main/org/apache/tools/ant/util/DateUtils.java b/src/main/org/apache/tools/ant/util/DateUtils.java
index b63e098..bf92bf5 100644
--- a/src/main/org/apache/tools/ant/util/DateUtils.java
+++ b/src/main/org/apache/tools/ant/util/DateUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,8 +31,8 @@
 
 /**
  * Helper methods to deal with date/time formatting with a specific
- * defined format (<a href="http://www.w3.org/TR/NOTE-datetime">ISO8601</a>)
- * or a plurialization correct elapsed time in minutes and seconds.
+ * defined format (<a href="https://www.w3.org/TR/NOTE-datetime">ISO8601</a>)
+ * or a correct pluralization of elapsed time in minutes and seconds.
  *
  * @since Ant 1.5
  *
@@ -45,19 +45,19 @@
     private static final int TEN = 10;
     /**
      * ISO8601-like pattern for date-time. It does not support timezone.
-     *  <tt>yyyy-MM-ddTHH:mm:ss</tt>
+     *  <code>yyyy-MM-ddTHH:mm:ss</code>
      */
     public static final String ISO8601_DATETIME_PATTERN
             = "yyyy-MM-dd'T'HH:mm:ss";
 
     /**
-     * ISO8601-like pattern for date. <tt>yyyy-MM-dd</tt>
+     * ISO8601-like pattern for date. <code>yyyy-MM-dd</code>
      */
     public static final String ISO8601_DATE_PATTERN
             = "yyyy-MM-dd";
 
     /**
-     * ISO8601-like pattern for time.  <tt>HH:mm:ss</tt>
+     * ISO8601-like pattern for time.  <code>HH:mm:ss</code>
      */
     public static final String ISO8601_TIME_PATTERN
             = "HH:mm:ss";
@@ -68,12 +68,12 @@
      * some other code is using the format in parallel.
      * Deprecated since ant 1.8
      */
+    @Deprecated
     public static final DateFormat DATE_HEADER_FORMAT
         = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ", Locale.US);
 
-    private static final DateFormat DATE_HEADER_FORMAT_INT
-    = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ", Locale.US);
-
+    private static final DateFormat DATE_HEADER_FORMAT_INT =
+        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ", Locale.US);
 
 // code from Magesh moved from DefaultLogger and slightly modified
     private static final MessageFormat MINUTE_SECONDS
@@ -95,29 +95,19 @@
      * Provides a thread-local US-style date format. Exactly as used by
      * {@code <touch>}, to minute precision:
      * {@code SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US)}
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public static final ThreadLocal<DateFormat> EN_US_DATE_FORMAT_MIN =
-        new ThreadLocal<DateFormat>() {
-            @Override
-            protected DateFormat initialValue() {
-                return new SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US);
-            }
-        };
+            ThreadLocal.withInitial(() -> new SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US));
 
     /**
      * Provides a thread-local US-style date format. Exactly as used by
      * {@code <touch>}, to second precision:
      * {@code SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", Locale.US)}
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public static final ThreadLocal<DateFormat> EN_US_DATE_FORMAT_SEC =
-        new ThreadLocal<DateFormat>() {
-            @Override
-            protected DateFormat initialValue() {
-                return new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", Locale.US);
-            }
-        };
+            ThreadLocal.withInitial(() -> new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", Locale.US));
 
     static {
         MINUTE_SECONDS.setFormat(0, MINUTES_FORMAT);
@@ -167,8 +157,7 @@
     public static String formatElapsedTime(long millis) {
         long seconds = millis / ONE_SECOND;
         long minutes = seconds / ONE_MINUTE;
-        Object[] args = {new Long(minutes), new Long(seconds % ONE_MINUTE)};
-        return MINUTE_SECONDS.format(args);
+        return MINUTE_SECONDS.format(new Object[]{minutes, seconds % ONE_MINUTE});
     }
 
     /**
@@ -188,7 +177,7 @@
      * Calculate the phase of the moon for a given date.
      *
      * <p>Code heavily influenced by hacklib.c in <a
-     * href="http://www.nethack.org/">Nethack</a></p>
+     * href="https://www.nethack.org/">Nethack</a></p>
      *
      * <p>The Algorithm:
      *
@@ -245,7 +234,7 @@
                                   cal.get(Calendar.DAY_OF_MONTH),
                                   cal.get(Calendar.DAY_OF_WEEK),
                                   cal.get(Calendar.MILLISECOND));
-        StringBuffer tzMarker = new StringBuffer(offset < 0 ? "-" : "+");
+        StringBuilder tzMarker = new StringBuilder(offset < 0 ? "-" : "+");
         offset = Math.abs(offset);
         int hours = offset / (ONE_HOUR * ONE_MINUTE * ONE_SECOND);
         int minutes = offset / (ONE_MINUTE * ONE_SECOND) - ONE_HOUR * hours;
@@ -329,14 +318,12 @@
         }
     }
 
-    final private static ThreadLocal<DateFormat> iso8601WithTimeZone =
-        new ThreadLocal<DateFormat>() {
-            @Override protected DateFormat initialValue() {
+    private static final ThreadLocal<DateFormat> iso8601WithTimeZone =
+            ThreadLocal.withInitial(() -> {
               // An arbitrary easy-to-read format to normalize to.
               return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
-            }
-        };
-    final private static Pattern iso8601normalizer = Pattern.compile(
+            });
+    private static final Pattern iso8601normalizer = Pattern.compile(
         "^(\\d{4,}-\\d{2}-\\d{2})[Tt ]" +           // yyyy-MM-dd
         "(\\d{2}:\\d{2}(:\\d{2}(\\.\\d{3})?)?) ?" + // HH:mm:ss.SSS
         "(?:Z|([+-]\\d{2})(?::?(\\d{2}))?)?$");     // Z
@@ -355,7 +342,7 @@
      * @param dateStr String
      * @return Date
      * @throws ParseException if date string does not match ISO 8601
-     * @since Ant 1.9.10
+     * @since Ant 1.10.2
      */
     public static Date parseLenientDateTime(String dateStr) throws ParseException {
         try {
diff --git a/src/main/org/apache/tools/ant/util/DeweyDecimal.java b/src/main/org/apache/tools/ant/util/DeweyDecimal.java
index 003f140..cc42117 100644
--- a/src/main/org/apache/tools/ant/util/DeweyDecimal.java
+++ b/src/main/org/apache/tools/ant/util/DeweyDecimal.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,8 @@
 package org.apache.tools.ant.util;
 
 import java.util.StringTokenizer;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * Utility class to contain version numbers in "Dewey Decimal"
@@ -54,15 +56,15 @@
         final StringTokenizer tokenizer = new StringTokenizer(string, ".", true);
         final int size = tokenizer.countTokens();
 
-        components = new int[ (size + 1) / 2 ];
+        components = new int[(size + 1) / 2];
 
         for (int i = 0; i < components.length; i++) {
             final String component = tokenizer.nextToken();
-            if (component.length() == 0) {
+            if (component.isEmpty()) {
                 throw new NumberFormatException("Empty component in string");
             }
 
-            components[ i ] = Integer.parseInt(component);
+            components[i] = Integer.parseInt(component);
 
             //Strip '.' token
             if (tokenizer.hasMoreTokens()) {
@@ -92,7 +94,7 @@
      * @return the value of component at index
      */
     public int get(final int index) {
-        return components[ index ];
+        return components[index];
     }
 
     /**
@@ -106,8 +108,8 @@
         final int max = Math.max(other.components.length, components.length);
 
         for (int i = 0; i < max; i++) {
-            final int component1 = (i < components.length) ? components[ i ] : 0;
-            final int component2 = (i < other.components.length) ? other.components[ i ] : 0;
+            final int component1 = (i < components.length) ? components[i] : 0;
+            final int component2 = (i < other.components.length) ? other.components[i] : 0;
 
             if (component2 != component1) {
                 return false;
@@ -150,8 +152,8 @@
         final int max = Math.max(other.components.length, components.length);
 
         for (int i = 0; i < max; i++) {
-            final int component1 = (i < components.length) ? components[ i ] : 0;
-            final int component2 = (i < other.components.length) ? other.components[ i ] : 0;
+            final int component1 = (i < components.length) ? components[i] : 0;
+            final int component2 = (i < other.components.length) ? other.components[i] : 0;
 
             if (component2 > component1) {
                 return false;
@@ -175,8 +177,8 @@
         final int max = Math.max(other.components.length, components.length);
 
         for (int i = 0; i < max; i++) {
-            final int component1 = (i < components.length) ? components[ i ] : 0;
-            final int component2 = (i < other.components.length) ? other.components[ i ] : 0;
+            final int component1 = (i < components.length) ? components[i] : 0;
+            final int component2 = (i < other.components.length) ? other.components[i] : 0;
 
             if (component2 > component1) {
                 return false;
@@ -195,16 +197,8 @@
      * @return the string representation of DeweyDecimal.
      */
     @Override public String toString() {
-        final StringBuffer sb = new StringBuffer();
-
-        for (int i = 0; i < components.length; i++) {
-            if (i != 0) {
-                sb.append('.');
-            }
-            sb.append(components[ i ]);
-        }
-
-        return sb.toString();
+        return IntStream.of(components).mapToObj(Integer::toString)
+            .collect(Collectors.joining("."));
     }
 
     /**
@@ -214,11 +208,12 @@
      * @return result
      * @see java.lang.Comparable#compareTo(Object)
      */
+    @Override
     public int compareTo(DeweyDecimal other) {
         final int max = Math.max(other.components.length, components.length);
         for (int i = 0; i < max; i++) {
-            final int component1 = (i < components.length) ? components[ i ] : 0;
-            final int component2 = (i < other.components.length) ? other.components[ i ] : 0;
+            final int component1 = (i < components.length) ? components[i] : 0;
+            final int component2 = (i < other.components.length) ? other.components[i] : 0;
             if (component1 != component2) {
                 return component1 - component2;
             }
diff --git a/src/main/org/apache/tools/ant/util/FileNameMapper.java b/src/main/org/apache/tools/ant/util/FileNameMapper.java
index ec85f9d..cac480f 100644
--- a/src/main/org/apache/tools/ant/util/FileNameMapper.java
+++ b/src/main/org/apache/tools/ant/util/FileNameMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/FileTokenizer.java b/src/main/org/apache/tools/ant/util/FileTokenizer.java
index 2807aa4..8535bfe 100644
--- a/src/main/org/apache/tools/ant/util/FileTokenizer.java
+++ b/src/main/org/apache/tools/ant/util/FileTokenizer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,6 +34,7 @@
      * @return the complete input
      * @throws IOException if error reading
      */
+    @Override
     public String getToken(Reader in) throws IOException {
         return FileUtils.readFully(in);
     }
@@ -42,6 +43,7 @@
      * Return the intra-token string
      * @return an empty string always
      */
+    @Override
     public String getPostToken() {
         return "";
     }
diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java
index 0c932e9..0deecaa 100644
--- a/src/main/org/apache/tools/ant/util/FileUtils.java
+++ b/src/main/org/apache/tools/ant/util/FileUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,16 +31,28 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.channels.Channel;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.EnumSet;
 import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
 import java.util.Random;
 import java.util.Stack;
 import java.util.StringTokenizer;
 import java.util.Vector;
 import java.util.jar.JarFile;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.MagicNames;
@@ -48,6 +60,7 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.launch.Locator;
 import org.apache.tools.ant.taskdefs.condition.Os;
+import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.FilterSetCollection;
 import org.apache.tools.ant.types.resources.FileResource;
 
@@ -92,13 +105,25 @@
      */
     public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1;
 
+    private static final FileAttribute<?>[] TMPFILE_ATTRIBUTES =
+        new FileAttribute[] {
+            PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ,
+                PosixFilePermission.OWNER_WRITE))
+        };
+    private static final FileAttribute<?>[] TMPDIR_ATTRIBUTES =
+        new FileAttribute[] {
+            PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ,
+                PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE))
+        };
+    private static final FileAttribute<?>[] NO_TMPFILE_ATTRIBUTES = new FileAttribute[0];
+
     /**
      * A one item cache for fromUri.
      * fromUri is called for each element when parsing ant build
      * files. It is a costly operation. This just caches the result
      * of the last call.
      */
-    private Object cacheFromUriLock = new Object();
+    private final Object cacheFromUriLock = new Object();
     private String cacheFromUriRequest = null;
     private String cacheFromUriResponse = null;
 
@@ -110,6 +135,7 @@
      *             Use getFileUtils instead,
      * FileUtils do not have state.
      */
+    @Deprecated
     public static FileUtils newFileUtils() {
         return new FileUtils();
     }
@@ -273,7 +299,7 @@
      * @since Ant 1.5
      */
     public void copyFile(String sourceFile, String destFile,
-                         FilterSetCollection filters, Vector filterChains,
+                         FilterSetCollection filters, Vector<FilterChain> filterChains,
                          boolean overwrite, boolean preserveLastModified,
                          String encoding, Project project) throws IOException {
         copyFile(new File(sourceFile), new File(destFile), filters, filterChains, overwrite,
@@ -303,7 +329,7 @@
      * @since Ant 1.6
      */
     public void copyFile(String sourceFile, String destFile,
-                         FilterSetCollection filters, Vector filterChains,
+                         FilterSetCollection filters, Vector<FilterChain> filterChains,
                          boolean overwrite, boolean preserveLastModified,
                          String inputEncoding, String outputEncoding,
                          Project project) throws IOException {
@@ -438,7 +464,7 @@
      * @since Ant 1.5
      */
     public void copyFile(File sourceFile, File destFile,
-                         FilterSetCollection filters, Vector filterChains,
+                         FilterSetCollection filters, Vector<FilterChain> filterChains,
                          boolean overwrite, boolean preserveLastModified,
                          String encoding, Project project) throws IOException {
         copyFile(sourceFile, destFile, filters, filterChains,
@@ -474,7 +500,7 @@
      * @since Ant 1.6
      */
     public void copyFile(File sourceFile, File destFile,
-            FilterSetCollection filters, Vector filterChains,
+            FilterSetCollection filters, Vector<FilterChain> filterChains,
             boolean overwrite, boolean preserveLastModified,
             String inputEncoding, String outputEncoding,
             Project project) throws IOException {
@@ -512,7 +538,7 @@
      * @since Ant 1.8
      */
     public void copyFile(File sourceFile, File destFile,
-                         FilterSetCollection filters, Vector filterChains,
+                         FilterSetCollection filters, Vector<FilterChain> filterChains,
                          boolean overwrite, boolean preserveLastModified,
                          boolean append,
                          String inputEncoding, String outputEncoding,
@@ -552,7 +578,7 @@
      * @since Ant 1.8.2
      */
     public void copyFile(File sourceFile, File destFile,
-                         FilterSetCollection filters, Vector filterChains,
+                         FilterSetCollection filters, Vector<FilterChain> filterChains,
                          boolean overwrite, boolean preserveLastModified,
                          boolean append,
                          String inputEncoding, String outputEncoding,
@@ -629,7 +655,7 @@
      * @since Ant 1.7
      */
     public static boolean isContextRelativePath(String filename) {
-        if (!(ON_DOS || ON_NETWARE) || filename.length() == 0) {
+        if (!(ON_DOS || ON_NETWARE) || filename.isEmpty()) {
             return false;
         }
         char sep = File.separatorChar;
@@ -653,19 +679,19 @@
      * @since Ant 1.6.3
      */
     public static boolean isAbsolutePath(String filename) {
-        int len = filename.length();
-        if (len == 0) {
+        if (filename.isEmpty()) {
             return false;
         }
+        int len = filename.length();
         char sep = File.separatorChar;
         filename = filename.replace('/', sep).replace('\\', sep);
         char c = filename.charAt(0);
-        if (!(ON_DOS || ON_NETWARE)) {
-            return (c == sep);
+        if (!ON_DOS && !ON_NETWARE) {
+            return c == sep;
         }
         if (c == sep) {
             // CheckStyle:MagicNumber OFF
-            if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) {
+            if (!ON_DOS || len <= 4 || filename.charAt(1) != sep) {
                 return false;
             }
             // CheckStyle:MagicNumber ON
@@ -696,16 +722,16 @@
      * @see PathTokenizer
      */
     public static String translatePath(String toProcess) {
-        if (toProcess == null || toProcess.length() == 0) {
+        if (toProcess == null || toProcess.isEmpty()) {
             return "";
         }
-        StringBuffer path = new StringBuffer(toProcess.length() + EXPAND_SPACE);
+        StringBuilder path = new StringBuilder(toProcess.length() + EXPAND_SPACE);
         PathTokenizer tokenizer = new PathTokenizer(toProcess);
         while (tokenizer.hasMoreTokens()) {
             String pathComponent = tokenizer.nextToken();
             pathComponent = pathComponent.replace('/', File.separatorChar);
             pathComponent = pathComponent.replace('\\', File.separatorChar);
-            if (path.length() != 0) {
+            if (path.length() > 0) {
                 path.append(File.pathSeparatorChar);
             }
             path.append(pathComponent);
@@ -737,7 +763,7 @@
      * @throws java.lang.NullPointerException if path is null.
      */
     public File normalize(final String path) {
-        Stack s = new Stack();
+        Stack<String> s = new Stack<>();
         String[] dissect = dissect(path);
         s.push(dissect[0]);
 
@@ -757,7 +783,7 @@
                 s.push(thisToken);
             }
         }
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         final int size = s.size();
         for (int i = 0; i < size; i++) {
             if (i > 1) {
@@ -785,7 +811,7 @@
         if (!isAbsolutePath(path)) {
             throw new BuildException(path + " is not an absolute path");
         }
-        String root = null;
+        String root;
         int colon = path.indexOf(':');
         if (colon > 0 && (ON_DOS || ON_NETWARE)) {
 
@@ -796,7 +822,7 @@
             //remove the initial separator; the root has it.
             next = (ca[next] == sep) ? next + 1 : next;
 
-            StringBuffer sbPath = new StringBuffer();
+            final StringBuilder sbPath = new StringBuilder();
             // Eliminate consecutive slashes after the drive spec:
             for (int i = next; i < ca.length; i++) {
                 if (ca[i] != sep || ca[i - 1] != sep) {
@@ -838,7 +864,7 @@
                 && !name.regionMatches(true, name.length() - 4, ".DIR", 0, 4);
         // CheckStyle:MagicNumber ON
         String device = null;
-        StringBuffer directory = null;
+        StringBuilder directory = null;
         String file = null;
 
         int index = 0;
@@ -851,14 +877,14 @@
             device = path.substring(1, index++);
         }
         if (isDirectory) {
-            directory = new StringBuffer(path.substring(index).replace(File.separatorChar, '.'));
+            directory = new StringBuilder(path.substring(index).replace(File.separatorChar, '.'));
         } else {
-            int dirEnd = path.lastIndexOf(File.separatorChar, path.length());
+            int dirEnd = path.lastIndexOf(File.separatorChar);
             if (dirEnd == -1 || dirEnd < index) {
                 file = path.substring(index);
             } else {
-                directory = new StringBuffer(path.substring(index, dirEnd).
-                                             replace(File.separatorChar, '.'));
+                directory = new StringBuilder(path.substring(index, dirEnd)
+                        .replace(File.separatorChar, '.'));
                 index = dirEnd + 1;
                 if (path.length() > index) {
                     file = path.substring(index);
@@ -884,6 +910,10 @@
      * yield a different file name.
      * </p>
      *
+     * <p>If the filesystem where the temporary file is created
+     * supports POSIX permissions, the file will only be readable and
+     * writable by the current user.</p>
+     *
      * @param prefix file name prefix.
      * @param suffix
      *            file extension; include the '.'.
@@ -895,6 +925,7 @@
      * boolean, boolean) instead.
      * @return a File reference to the new, nonexistent temporary file.
      */
+    @Deprecated
     public File createTempFile(String prefix, String suffix, File parentDir) {
         return createTempFile(prefix, suffix, parentDir, false, false);
     }
@@ -906,6 +937,10 @@
      * exist before this method was invoked, any subsequent invocation
      * of this method will yield a different file name.</p>
      *
+     * <p>If the filesystem where the temporary file is created
+     * supports POSIX permissions, the file will only be readable and
+     * writable by the current user.</p>
+     *
      * @param prefix file name prefix.
      * @param suffix file extension; include the '.'.
      * @param parentDir Directory to create the temporary file in;
@@ -919,16 +954,15 @@
      *
      * @return a File reference to the new temporary file.
      * @since Ant 1.7.1
-     * @deprecated since Ant 1.9.15 use createTempFile(Project, String, String, File,
+     * @deprecated since Ant 1.10.8 use createTempFile(Project, String, String, File,
      * boolean, boolean) instead.
      */
+    @Deprecated
     public File createTempFile(String prefix, String suffix, File parentDir,
             boolean deleteOnExit, boolean createFile) {
         return createTempFile(null, prefix, suffix, parentDir, deleteOnExit, createFile);
     }
 
-    private static final String NULL_PLACEHOLDER = "null";
-
     /**
      * Create a temporary file in a given directory.
      *
@@ -936,6 +970,10 @@
      * exist before this method was invoked, any subsequent invocation
      * of this method will yield a different file name.</p>
      *
+     * <p>If the filesystem where the temporary file is created
+     * supports POSIX permissions, the file will only be readable and
+     * writable by the current user.</p>
+     *
      * @param project reference to the current Ant project.
      * @param prefix file name prefix.
      * @param suffix file extension; include the '.'.
@@ -955,25 +993,48 @@
      */
     public File createTempFile(final Project project, String prefix, String suffix,
             final File parentDir, final boolean deleteOnExit, final boolean createFile) {
-        File result = null;
-        final String parent;
+        File result;
+        String p = null;
         if (parentDir != null) {
-            parent = parentDir.getPath();
+            p = parentDir.getPath();
         } else if (project != null && project.getProperty(MagicNames.TMPDIR) != null) {
-            parent = project.getProperty(MagicNames.TMPDIR);
-        } else {
-            parent = System.getProperty("java.io.tmpdir");
+            p = project.getProperty(MagicNames.TMPDIR);
+        } else if (project != null && deleteOnExit) {
+            if (project.getProperty(MagicNames.AUTO_TMPDIR) != null) {
+                p = project.getProperty(MagicNames.AUTO_TMPDIR);
+            } else {
+                final Path systemTempDirPath =
+                    new File(System.getProperty("java.io.tmpdir")).toPath();
+                final PosixFileAttributeView systemTempDirPosixAttributes =
+                    Files.getFileAttributeView(systemTempDirPath, PosixFileAttributeView.class);
+                if (systemTempDirPosixAttributes != null) {
+                    // no reason to create an extra temp dir if we cannot set permissions
+                    try {
+                        final File projectTempDir = Files.createTempDirectory(systemTempDirPath,
+                            "ant", TMPDIR_ATTRIBUTES)
+                            .toFile();
+                        projectTempDir.deleteOnExit();
+                        p = projectTempDir.getAbsolutePath();
+                        project.setProperty(MagicNames.AUTO_TMPDIR, p);
+                    } catch (IOException ex) {
+                        // silently fall back to system temp directory
+                    }
+                }
+            }
         }
-        if (prefix == null) {
-            prefix = NULL_PLACEHOLDER;
-        }
-        if (suffix == null) {
-            suffix = NULL_PLACEHOLDER;
-        }
+        final String parent = p != null ? p : System.getProperty("java.io.tmpdir");
+
+        prefix = String.valueOf(prefix);
+        suffix = String.valueOf(suffix);
 
         if (createFile) {
             try {
-                result = File.createTempFile(prefix, suffix, new File(parent));
+                final Path parentPath = new File(parent).toPath();
+                final PosixFileAttributeView parentPosixAttributes =
+                    Files.getFileAttributeView(parentPath, PosixFileAttributeView.class);
+                result = Files.createTempFile(parentPath, prefix, suffix,
+                    parentPosixAttributes != null ? TMPFILE_ATTRIBUTES : NO_TMPFILE_ATTRIBUTES)
+                    .toFile();
             } catch (IOException e) {
                 throw new BuildException("Could not create tempfile in "
                         + parent, e);
@@ -1004,6 +1065,10 @@
      * yield a different file name.
      * </p>
      *
+     * <p>If the filesystem where the temporary file is created
+     * supports POSIX permissions, the file will only be readable and
+     * writable by the current user.</p>
+     *
      * @param prefix file name prefix.
      * @param suffix
      *            file extension; include the '.'.
@@ -1017,6 +1082,7 @@
      * boolean, boolean) instead.
      * @return a File reference to the new, nonexistent temporary file.
      */
+    @Deprecated
     public File createTempFile(String prefix, String suffix,
             File parentDir, boolean deleteOnExit) {
         return createTempFile(prefix, suffix, parentDir, deleteOnExit, false);
@@ -1062,8 +1128,9 @@
      * @since 1.10
      * @deprecated since 1.7. Just use {@link File#getParentFile} directly.
      */
+    @Deprecated
     public File getParentFile(File f) {
-        return (f == null) ? null : f.getParentFile();
+        return f == null ? null : f.getParentFile();
     }
 
     /**
@@ -1092,20 +1159,19 @@
     public static String readFully(Reader rdr, int bufferSize)
         throws IOException {
         if (bufferSize <= 0) {
-            throw new IllegalArgumentException("Buffer size must be greater "
-                                               + "than 0");
+            throw new IllegalArgumentException(
+                "Buffer size must be greater than 0");
         }
         final char[] buffer = new char[bufferSize];
         int bufferLength = 0;
-        StringBuffer textBuffer = null;
+        StringBuilder textBuffer = new StringBuilder();
         while (bufferLength != -1) {
             bufferLength = rdr.read(buffer);
             if (bufferLength > 0) {
-                textBuffer = (textBuffer == null) ? new StringBuffer() : textBuffer;
-                textBuffer.append(new String(buffer, 0, bufferLength));
+                textBuffer.append(buffer, 0, bufferLength);
             }
         }
-        return (textBuffer == null) ? null : textBuffer.toString();
+        return (textBuffer.length() == 0) ? null : textBuffer.toString();
     }
 
     /**
@@ -1166,15 +1232,15 @@
      * @return true if the file is a symbolic link.
      * @throws IOException on error.
      * @since Ant 1.5
-     * @deprecated use SymbolicLinkUtils instead
+     * @deprecated use {@link Files#isSymbolicLink(Path)} instead
      */
-    public boolean isSymbolicLink(File parent, String name)
+    @Deprecated
+    public boolean isSymbolicLink(final File parent, final String name)
         throws IOException {
-        SymbolicLinkUtils u = SymbolicLinkUtils.getSymbolicLinkUtils();
         if (parent == null) {
-            return u.isSymbolicLink(name);
+            return Files.isSymbolicLink(Paths.get(name));
         }
-        return u.isSymbolicLink(parent, name);
+        return Files.isSymbolicLink(Paths.get(parent.toPath().toString(), name));
     }
 
     /**
@@ -1247,7 +1313,7 @@
      * @param resolveSymlinks whether symbolic links shall be resolved
      * prior to comparing the paths.
      * @return true if path starts with leading; false otherwise.
-     * @since Ant 1.9.13
+     * @since Ant 1.10.5
      * @throws IOException if resolveSymlinks is true and invoking
      * getCanonicaPath on either argument throws an exception
      */
@@ -1277,7 +1343,7 @@
      *
      * <p>The coding of the output is the same as what File.toURI().toASCIIString() produces</p>
      *
-     * See <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
+     * See <a href="https://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
      * which makes some mention of how
      * characters not supported by URI Reference syntax should be escaped.
      *
@@ -1350,10 +1416,21 @@
         if (f1 == null || f2 == null) {
             return false;
         }
+        return fileNameEquals(f1, f2) || isSameFile(f1, f2);
+    }
+
+    private boolean isSameFile(File f1, File f2) throws IOException {
+        if (f1.exists()) {
+            try {
+                return f2.exists() && Files.isSameFile(f1.toPath(), f2.toPath());
+            } catch (NoSuchFileException e) {
+                // file has been removed between exists check and isSameFile?
+                return false;
+            }
+        }
         File f1Normalized = normalize(f1.getAbsolutePath());
         File f2Normalized = normalize(f2.getAbsolutePath());
-        return f1Normalized.equals(f2Normalized)
-            || f1Normalized.getCanonicalFile().equals(f2Normalized
+        return f1Normalized.getCanonicalFile().equals(f2Normalized
                                                       .getCanonicalFile());
     }
 
@@ -1454,11 +1531,8 @@
             return false;
         }
         final String localFileName = localFile.getName();
-        FilenameFilter ff = new FilenameFilter () {
-            public boolean accept(File dir, String name) {
-                return name.equalsIgnoreCase(localFileName) && (!name.equals(localFileName));
-            }
-        };
+        FilenameFilter ff = (dir, name) -> name.equalsIgnoreCase(localFileName)
+            && (!name.equals(localFileName));
         String[] names = localFile.getParentFile().list(ff);
         return names != null && names.length == 1;
     }
@@ -1527,13 +1601,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);
     }
 
     /**
@@ -1543,13 +1611,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);
     }
 
     /**
@@ -1559,13 +1621,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);
     }
 
     /**
@@ -1575,13 +1631,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);
     }
 
     /**
@@ -1592,13 +1642,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);
     }
 
     /**
@@ -1615,7 +1659,6 @@
                     JarURLConnection juc = (JarURLConnection) conn;
                     JarFile jf = juc.getJarFile();
                     jf.close();
-                    jf = null;
                 } else if (conn instanceof HttpURLConnection) {
                     ((HttpURLConnection) conn).disconnect();
                 }
@@ -1626,6 +1669,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.
@@ -1699,7 +1760,6 @@
         if (0 < toPathStack.length && 0 < fromPathStack.length) {
             if (!fromPathStack[0].equals(toPathStack[0])) {
                 // not the same device (would be "" on Linux/Unix)
-
                 return getPath(Arrays.asList(toPathStack));
             }
         } else {
@@ -1707,17 +1767,14 @@
             return getPath(Arrays.asList(toPathStack));
         }
 
-        int minLength = Math.min(fromPathStack.length, toPathStack.length);
-        int same = 1; // Used outside the for loop
-
         // get index of parts which are equal
-        for (;
-             same < minLength && fromPathStack[same].equals(toPathStack[same]);
-             same++) {
-            // Do nothing
+        int minLength = Math.min(fromPathStack.length, toPathStack.length);
+        int same = 1;
+        while (same < minLength && fromPathStack[same].equals(toPathStack[same])) {
+            same++;
         }
 
-        List relativePathStack = new ArrayList();
+        List<String> relativePathStack = new ArrayList<>();
 
         // if "from" part is longer, fill it up with ".."
         // to reach path which is equal to both paths
@@ -1726,9 +1783,7 @@
         }
 
         // fill it up path with parts which were not equal
-        for (int i = same; i < toPathStack.length; i++) {
-            relativePathStack.add(toPathStack[i]);
-        }
+        relativePathStack.addAll(Arrays.asList(toPathStack).subList(same, toPathStack.length));
 
         return getPath(relativePathStack);
     }
@@ -1755,7 +1810,7 @@
      *
      * @since Ant 1.7
      */
-    public static String getPath(List pathStack) {
+    public static String getPath(List<String> pathStack) {
         // can safely use '/' because Windows understands '/' as separator
         return getPath(pathStack, '/');
     }
@@ -1769,18 +1824,8 @@
      *
      * @since Ant 1.7
      */
-    public static String getPath(final List pathStack, final char separatorChar) {
-        final StringBuffer buffer = new StringBuffer();
-
-        final Iterator iter = pathStack.iterator();
-        if (iter.hasNext()) {
-            buffer.append(iter.next());
-        }
-        while (iter.hasNext()) {
-            buffer.append(separatorChar);
-            buffer.append(iter.next());
-        }
-        return buffer.toString();
+    public static String getPath(final List<String> pathStack, final char separatorChar) {
+        return pathStack.stream().collect(Collectors.joining(Character.toString(separatorChar)));
     }
 
     /**
@@ -1794,6 +1839,7 @@
     public String getDefaultEncoding() {
         InputStreamReader is = new InputStreamReader(
             new InputStream() { //NOSONAR
+                @Override
                 public int read() {
                     return -1;
                 }
@@ -1804,4 +1850,80 @@
             close(is);
         }
     }
+
+    /**
+     * Opens a new OutputStream for the given Path.
+     * @param path the path of the file
+     * @param append whether to append to or a replace an existing file
+     * @return a stream ready to write to the file
+     * @throws IOException if stream creation fails
+     * @since Ant 1.10.2
+     */
+    public static OutputStream newOutputStream(Path path, boolean append) throws IOException {
+        if (append) {
+            return Files.newOutputStream(path, StandardOpenOption.CREATE, StandardOpenOption.APPEND,
+                StandardOpenOption.WRITE);
+        } else {
+            return Files.newOutputStream(path);
+        }
+    }
+
+    /**
+     * Tries to determine the case sensitivity of the filesystem corresponding to the
+     * {@code path}. While doing so, this method might create a temporary file under
+     * the directory represented by the {@code path}, if it's a directory or in the
+     * parent directory of the {@code path}, if it's a file.
+     * <p>
+     * This method works on a best effort basis and will return an {@link Optional#empty()}
+     * if it cannot determine the case sensitivity, either due to exception or for any other
+     * reason.
+     * </p>
+     * @param path The path whose filesystem case sensitivity needs to be checked
+     * @return Returns true if the filesystem corresponding to the passed {@code path}
+     *          is case sensitive. Else returns false. If the case sensitivity
+     *          cannot be determined for whatever reason, this method returns an
+     *          {@link Optional#empty()}
+     * @throws IllegalArgumentException If the passed path is null
+     * @since Ant 1.10.6
+     */
+    public static Optional<Boolean> isCaseSensitiveFileSystem(final Path path) {
+        if (path == null) {
+            throw new IllegalArgumentException("Path cannot be null");
+        }
+        final String mixedCaseFileNamePrefix = "aNt";
+        Path mixedCaseTmpFile = null;
+        boolean caseSensitive;
+        try {
+            if (Files.isRegularFile(path)) {
+                mixedCaseTmpFile = Files.createTempFile(path.getParent(), mixedCaseFileNamePrefix, null);
+            } else if (Files.isDirectory(path)) {
+                mixedCaseTmpFile = Files.createTempFile(path, mixedCaseFileNamePrefix, null);
+            } else {
+                // we can only do our tricks to figure out whether the filesystem is
+                // case sensitive, only if the path is a directory or a file.
+                // In other cases (like the path being non-existent), we don't
+                // have a way to determine that detail
+                return Optional.empty();
+            }
+            final Path lowerCasePath = Paths.get(mixedCaseTmpFile.toString().toLowerCase(Locale.US));
+            try {
+                caseSensitive = !Files.isSameFile(mixedCaseTmpFile, lowerCasePath);
+            } catch (NoSuchFileException nsfe) {
+                // a NSFE implies that the "lowerCasePath" file wasn't considered to be present
+                // even if the different cased file exists. That effectively means this is a
+                // case sensitive filesystem
+                caseSensitive = true;
+            }
+        } catch (IOException ioe) {
+            System.err.println("Could not determine the case sensitivity of the " +
+                    "filesystem for path " + path + " due to " + ioe);
+            return Optional.empty();
+        } finally {
+            // delete the tmp file
+            if (mixedCaseTmpFile != null) {
+                FileUtils.delete(mixedCaseTmpFile.toFile());
+            }
+        }
+        return Optional.of(caseSensitive);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/util/FirstMatchMapper.java b/src/main/org/apache/tools/ant/util/FirstMatchMapper.java
index b0e47f2..6a0c5d0 100644
--- a/src/main/org/apache/tools/ant/util/FirstMatchMapper.java
+++ b/src/main/org/apache/tools/ant/util/FirstMatchMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,7 +17,7 @@
  */
 package org.apache.tools.ant.util;
 
-import java.util.Iterator;
+import java.util.Objects;
 
 /**
  * A <code>ContainerMapper</code> that returns the results of its
@@ -28,17 +28,11 @@
 public class FirstMatchMapper extends ContainerMapper {
 
     /** {@inheritDoc}. */
+    @Override
     public String[] mapFileName(String sourceFileName) {
-        for (Iterator iter = getMappers().iterator(); iter.hasNext();) {
-            FileNameMapper mapper = (FileNameMapper) iter.next();
-            if (mapper != null) {
-                String[] mapped = mapper.mapFileName(sourceFileName);
-                if (mapped != null) {
-                    return mapped;
-                }
-            }
-        }
-        return null;
+        return getMappers().stream().filter(Objects::nonNull)
+            .map(m -> m.mapFileName(sourceFileName)).filter(Objects::nonNull)
+            .findFirst().orElse(null);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/util/FlatFileNameMapper.java b/src/main/org/apache/tools/ant/util/FlatFileNameMapper.java
index 04d58be..ac24790 100644
--- a/src/main/org/apache/tools/ant/util/FlatFileNameMapper.java
+++ b/src/main/org/apache/tools/ant/util/FlatFileNameMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,8 @@
 
 package org.apache.tools.ant.util;
 
+import java.io.File;
+
 /**
  * Implementation of FileNameMapper that always returns the source
  * file name without any leading directory information.
@@ -32,6 +34,7 @@
      * Ignored.
      * @param from ignored.
      */
+    @Override
     public void setFrom(String from) {
     }
 
@@ -39,6 +42,7 @@
      * Ignored.
      * @param to ignored.
      */
+    @Override
     public void setTo(String to) {
     }
 
@@ -48,8 +52,9 @@
      * @param sourceFileName the name to map.
      * @return the file name in a one-element array.
      */
+    @Override
     public String[] mapFileName(String sourceFileName) {
         return sourceFileName == null ? null
-            : new String[] {new java.io.File(sourceFileName).getName()};
+            : new String[] {new File(sourceFileName).getName()};
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/GlobPatternMapper.java b/src/main/org/apache/tools/ant/util/GlobPatternMapper.java
index a0f0ca9..9a63703 100644
--- a/src/main/org/apache/tools/ant/util/GlobPatternMapper.java
+++ b/src/main/org/apache/tools/ant/util/GlobPatternMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -108,42 +108,42 @@
      * Sets the &quot;from&quot; pattern. Required.
      * @param from a string
      */
+    @Override
     public void setFrom(String from) {
-        if (from != null) {
-            int index = from.lastIndexOf("*");
-            if (index == -1) {
-                fromPrefix = from;
-                fromPostfix = "";
-            } else {
-                fromPrefix = from.substring(0, index);
-                fromPostfix = from.substring(index + 1);
-                fromContainsStar = true;
-            }
-            prefixLength = fromPrefix.length();
-            postfixLength = fromPostfix.length();
-        } else {
+        if (from == null) {
             throw new BuildException("this mapper requires a 'from' attribute");
         }
+        int index = from.lastIndexOf('*');
+        if (index < 0) {
+            fromPrefix = from;
+            fromPostfix = "";
+        } else {
+            fromPrefix = from.substring(0, index);
+            fromPostfix = from.substring(index + 1);
+            fromContainsStar = true;
+        }
+        prefixLength = fromPrefix.length();
+        postfixLength = fromPostfix.length();
     }
 
     /**
      * Sets the &quot;to&quot; pattern. Required.
      * @param to a string
      */
+    @Override
     public void setTo(String to) {
-        if (to != null) {
-            int index = to.lastIndexOf("*");
-            if (index == -1) {
-                toPrefix = to;
-                toPostfix = "";
-            } else {
-                toPrefix = to.substring(0, index);
-                toPostfix = to.substring(index + 1);
-                toContainsStar = true;
-            }
-        } else {
+        if (to == null) {
             throw new BuildException("this mapper requires a 'to' attribute");
         }
+        int index = to.lastIndexOf('*');
+        if (index < 0) {
+            toPrefix = to;
+            toPostfix = "";
+        } else {
+            toPrefix = to.substring(0, index);
+            toPostfix = to.substring(index + 1);
+            toContainsStar = true;
+        }
     }
 
     /**
@@ -153,6 +153,7 @@
      * @param sourceFileName the filename to map
      * @return a list of converted filenames
      */
+    @Override
     public String[] mapFileName(String sourceFileName) {
         if (sourceFileName == null) {
             return null;
@@ -198,7 +199,7 @@
             name = name.toLowerCase();
         }
         if (handleDirSep) {
-            if (name.indexOf('\\') != -1) {
+            if (name.contains("\\")) {
                 name = name.replace('\\', '/');
             }
         }
diff --git a/src/main/org/apache/tools/ant/util/IdentityMapper.java b/src/main/org/apache/tools/ant/util/IdentityMapper.java
index 9bae6c2..3bee9d8 100644
--- a/src/main/org/apache/tools/ant/util/IdentityMapper.java
+++ b/src/main/org/apache/tools/ant/util/IdentityMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,6 +31,7 @@
      * Ignored.
      * @param from ignored.
      */
+    @Override
     public void setFrom(String from) {
     }
 
@@ -38,6 +39,7 @@
      * Ignored.
      * @param to ignored.
      */
+    @Override
     public void setTo(String to) {
     }
 
@@ -46,7 +48,8 @@
      * @param sourceFileName the name to map.
      * @return the source filename in a one-element array.
      */
-    public String[] mapFileName(final String sourceFileName) {
+    @Override
+    public String[] mapFileName(String sourceFileName) {
         if (sourceFileName == null) {
             // The FileNameMapper#mapFileName contract states that:
             // "if the given rule doesn't apply to the source file,
diff --git a/src/main/org/apache/tools/ant/util/IdentityStack.java b/src/main/org/apache/tools/ant/util/IdentityStack.java
index ba435b1..b39ff4f 100644
--- a/src/main/org/apache/tools/ant/util/IdentityStack.java
+++ b/src/main/org/apache/tools/ant/util/IdentityStack.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,7 +41,7 @@
         if (s instanceof IdentityStack) {
             return (IdentityStack<E>) s;
         }
-        IdentityStack<E> result = new IdentityStack<E>();
+        IdentityStack<E> result = new IdentityStack<>();
         if (s != null) {
             result.addAll(s);
         }
@@ -70,6 +70,7 @@
      * @return true if the stack contains the object.
      * @see java.util.Vector#contains(Object)
      */
+    @Override
     public synchronized boolean contains(Object o) {
         return indexOf(o) >= 0;
     }
@@ -81,6 +82,7 @@
      * @return the position of the object, -1 if not found.
      * @see java.util.Vector#indexOf(Object, int)
      */
+    @Override
     public synchronized int indexOf(Object o, int pos) {
         final int size = size();
         for (int i = pos; i < size; i++) {
@@ -98,6 +100,7 @@
      * @return the position of the object, -1 if not found.
      * @see java.util.Vector#indexOf(Object, int)
      */
+    @Override
     public synchronized int lastIndexOf(Object o, int pos) {
         for (int i = pos; i >= 0; i--) {
             if (get(i) == o) {
@@ -107,22 +110,25 @@
         return -1;
     }
 
+    @Override
     public synchronized boolean removeAll(Collection<?> c) {
-        if (!(c instanceof Set)) {
-            c = new HashSet(c);
+        if (!(c instanceof Set<?>)) {
+            c = new HashSet<>(c);
         }
         return super.removeAll(c);
     }
 
-    public synchronized boolean retainAll(Collection c) {
-        if (!(c instanceof Set)) {
-            c = new HashSet(c);
+    @Override
+    public synchronized boolean retainAll(Collection<?> c) {
+        if (!(c instanceof Set<?>)) {
+            c = new HashSet<>(c);
         }
         return super.retainAll(c);
     }
 
+    @Override
     public synchronized boolean containsAll(Collection<?> c) {
-        IdentityHashMap map = new IdentityHashMap();
+        IdentityHashMap<Object, Boolean> map = new IdentityHashMap<>();
         for (Object e : this) {
             map.put(e, Boolean.TRUE);
         }
diff --git a/src/main/org/apache/tools/ant/util/JAXPUtils.java b/src/main/org/apache/tools/ant/util/JAXPUtils.java
index 76460ae..b10a954 100644
--- a/src/main/org/apache/tools/ant/util/JAXPUtils.java
+++ b/src/main/org/apache/tools/ant/util/JAXPUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -232,9 +232,8 @@
         Exception nested = e.getException();
         if (nested != null) {
             return new BuildException(nested);
-        } else {
-            return new BuildException(e);
         }
+        return new BuildException(e);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/util/JavaEnvUtils.java b/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
index 060bb04..899c714 100644
--- a/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
+++ b/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,9 +37,6 @@
  */
 public final class JavaEnvUtils {
 
-    private JavaEnvUtils() {
-    }
-
     /** Are we on a DOS-based system */
     private static final boolean IS_DOS = Os.isFamily("dos");
     /** Are we on Novell NetWare */
@@ -130,6 +127,42 @@
      * @since Ant 1.9.8
      */
     public static final int VERSION_9 = 90;
+    
+    /**
+     * Version constant for Java 10
+     * @since Ant 1.10.7
+     */
+    public static final String JAVA_10 = "10";
+    /**
+     * Number Version constant for Java 10
+     * @since Ant 1.10.7
+     */
+    public static final int VERSION_10 = 100;
+
+    /**
+     * Version constant for Java 11
+     * @since Ant 1.10.7
+     */
+    public static final String JAVA_11 = "11";
+    /**
+     * Number Version constant for Java 11
+     * @since Ant 1.10.7
+     */
+    public static final int VERSION_11 = 110;
+    
+    /**
+     * Version constant for Java 12
+     * @since Ant 1.10.7
+     */
+    
+    public static final String JAVA_12 = "12";
+    /**
+     * Number Version constant for Java 12
+     * @since Ant 1.10.7
+     */
+    public static final int VERSION_12 = 120;
+    
+    
 
     /** Whether this is the Kaffe VM */
     private static boolean kaffeDetected;
@@ -146,47 +179,16 @@
     /** array of packages in the runtime */
     private static Vector<String> jrePackages;
 
+    private JavaEnvUtils() {
+    }
 
     static {
 
-        // Determine the Java version by looking at available classes
-        // java.net.Proxy was introduced in JDK 1.5
-        // java.lang.CharSequence was introduced in JDK 1.4
-        // java.lang.StrictMath was introduced in JDK 1.3
-        // java.lang.ThreadLocal was introduced in JDK 1.2
-        // java.lang.Void was introduced in JDK 1.1
-        // Count up version until a NoClassDefFoundError ends the try
-
         try {
-            javaVersion = JAVA_1_0;
-            javaVersionNumber = VERSION_1_0;
-            Class.forName("java.lang.Void");
-            javaVersion = JAVA_1_1;
-            javaVersionNumber++;
-            Class.forName("java.lang.ThreadLocal");
-            javaVersion = JAVA_1_2;
-            javaVersionNumber++;
-            Class.forName("java.lang.StrictMath");
-            javaVersion = JAVA_1_3;
-            javaVersionNumber++;
-            Class.forName("java.lang.CharSequence");
-            javaVersion = JAVA_1_4;
-            javaVersionNumber++;
-            Class.forName("java.net.Proxy");
-            javaVersion = JAVA_1_5;
-            javaVersionNumber++;
-            Class.forName("java.net.CookieStore");
-            javaVersion = JAVA_1_6;
-            javaVersionNumber++;
-            Class.forName("java.nio.file.FileSystem");
-            javaVersion = JAVA_1_7;
-            javaVersionNumber++;
-            Class.forName("java.lang.reflect.Executable");
+        	// only java 1.8 up supported.
             javaVersion = JAVA_1_8;
-            javaVersionNumber++;
+            javaVersionNumber = VERSION_1_8;
             Class.forName("java.lang.module.ModuleDescriptor");
-            javaVersion = JAVA_9;
-            javaVersionNumber = VERSION_9;
             // at least Java9 and this should properly support the purely numeric version property
             String v = System.getProperty("java.specification.version");
             DeweyDecimal pv = new DeweyDecimal(v);
@@ -273,8 +275,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
@@ -288,8 +290,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.
@@ -303,7 +305,7 @@
      * Checks whether the current Java VM is Kaffe.
      * @return true if the current Java VM is Kaffe.
      * @since Ant 1.6.3
-     * @see <a href="http://www.kaffe.org/">http://www.kaffe.org/</a>
+     * @see <a href="https://github.com/kaffe/kaffe">https://github.com/kaffe/kaffe</a>
      */
     public static boolean isKaffe() {
         return kaffeDetected;
@@ -463,97 +465,60 @@
      */
 
     private static void buildJrePackages() {
-        jrePackages = new Vector<String>();
-        if (isAtLeastJavaVersion(JAVA_1_1)) {
-            //things like sun.reflection, sun.misc, sun.net
-            jrePackages.addElement("sun");
-            jrePackages.addElement("java");
-            jrePackages.addElement("javax");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_2)) {
-            jrePackages.addElement("com.sun.java");
-            jrePackages.addElement("com.sun.image");
-            // are there any here that we forgot?
-        }
-        if (isAtLeastJavaVersion(JAVA_1_3)) {
-            jrePackages.addElement("org.omg");
-            jrePackages.addElement("com.sun.corba");
-            jrePackages.addElement("com.sun.jndi");
-            jrePackages.addElement("com.sun.media");
-            jrePackages.addElement("com.sun.naming");
-            jrePackages.addElement("com.sun.org.omg");
-            jrePackages.addElement("com.sun.rmi");
-            jrePackages.addElement("sunw.io");
-            jrePackages.addElement("sunw.util");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_4)) {
-            if (javaVersionNumber == VERSION_1_4) {
-                jrePackages.addElement("org.apache.crimson");
-                jrePackages.addElement("org.apache.xalan");
-                jrePackages.addElement("org.apache.xml");
-                jrePackages.addElement("org.apache.xpath");
-            }
-            jrePackages.addElement("org.ietf.jgss");
-            jrePackages.addElement("org.w3c.dom");
-            jrePackages.addElement("org.xml.sax");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_5)) {
-            //In Java1.5, the apache stuff moved.
-            jrePackages.addElement("com.sun.org.apache");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_7)) {
-            jrePackages.addElement("jdk");
-        }
-    }
+    	// do we still need this? As we only support java 1.8 upwards this would be the fixed list
+		// is this list correct for java 9 and above?
+		jrePackages = new Vector<>();
+		jrePackages.addElement("sun");
+		jrePackages.addElement("java");
+		jrePackages.addElement("javax");
+		jrePackages.addElement("com.sun.java");
+		jrePackages.addElement("com.sun.image");
+		jrePackages.addElement("org.omg");
+		jrePackages.addElement("com.sun.corba");
+		jrePackages.addElement("com.sun.jndi");
+		jrePackages.addElement("com.sun.media");
+		jrePackages.addElement("com.sun.naming");
+		jrePackages.addElement("com.sun.org.omg");
+		jrePackages.addElement("com.sun.rmi");
+		jrePackages.addElement("sunw.io");
+		jrePackages.addElement("sunw.util");
+		jrePackages.addElement("org.ietf.jgss");
+		jrePackages.addElement("org.w3c.dom");
+		jrePackages.addElement("org.xml.sax");
+		jrePackages.addElement("com.sun.org.apache");
+		jrePackages.addElement("jdk");
+	}
 
     /**
      * Testing helper method; kept here for unification of changes.
      * @return a list of test classes depending on the java version.
      */
     public static Vector<String> getJrePackageTestCases() {
-        Vector<String> tests = new Vector<String>();
-        tests.addElement("java.lang.Object");
-        if (isAtLeastJavaVersion(JAVA_1_1)) {
-            //things like sun.reflection, sun.misc, sun.net
-            tests.addElement("sun.reflect.SerializationConstructorAccessorImpl");
-            tests.addElement("sun.net.www.http.HttpClient");
-            tests.addElement("sun.audio.AudioPlayer");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_2)) {
-            tests.addElement("javax.accessibility.Accessible");
-            tests.addElement("sun.misc.BASE64Encoder");
-            tests.addElement("com.sun.image.codec.jpeg.JPEGCodec");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_3)) {
-            tests.addElement("org.omg.CORBA.Any");
-            tests.addElement("com.sun.corba.se.internal.corba.AnyImpl");
-            tests.addElement("com.sun.jndi.ldap.LdapURL");
-            tests.addElement("com.sun.media.sound.Printer");
-            tests.addElement("com.sun.naming.internal.VersionHelper");
-            tests.addElement("com.sun.org.omg.CORBA.Initializer");
-            tests.addElement("sunw.io.Serializable");
-            tests.addElement("sunw.util.EventListener");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_4)) {
-            tests.addElement("sun.audio.AudioPlayer");
-            if (javaVersionNumber == VERSION_1_4) {
-                // only for 1.4, not for higher versions
-                tests.addElement("org.apache.crimson.parser.ContentModel");
-                tests.addElement("org.apache.xalan.processor.ProcessorImport");
-                tests.addElement("org.apache.xml.utils.URI");
-                tests.addElement("org.apache.xpath.XPathFactory");
-            }
-            tests.addElement("org.ietf.jgss.Oid");
-            tests.addElement("org.w3c.dom.Attr");
-            tests.addElement("org.xml.sax.XMLReader");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_5)) {
-            tests.addElement("com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl");
-        }
-        if (isAtLeastJavaVersion(JAVA_1_7)) {
-            tests.addElement("jdk.net.Sockets");
-        }
-        return tests;
+    	// do we still need this? As we only support java 1.8 upwards this would be the fixed list
+		// is this list correct for java 9 and above?
+        Vector<String> tests = new Vector<>();
+		tests.addElement("java.lang.Object");
+		tests.addElement("sun.reflect.SerializationConstructorAccessorImpl");
+		tests.addElement("sun.net.www.http.HttpClient");
+		tests.addElement("sun.audio.AudioPlayer");
+		tests.addElement("javax.accessibility.Accessible");
+		tests.addElement("sun.misc.BASE64Encoder");
+		tests.addElement("com.sun.image.codec.jpeg.JPEGCodec");
+		tests.addElement("org.omg.CORBA.Any");
+		tests.addElement("com.sun.corba.se.internal.corba.AnyImpl");
+		tests.addElement("com.sun.jndi.ldap.LdapURL");
+		tests.addElement("com.sun.media.sound.Printer");
+		tests.addElement("com.sun.naming.internal.VersionHelper");
+		tests.addElement("com.sun.org.omg.CORBA.Initializer");
+		tests.addElement("sunw.io.Serializable");
+		tests.addElement("sunw.util.EventListener");
+		tests.addElement("sun.audio.AudioPlayer");
+		tests.addElement("org.ietf.jgss.Oid");
+		tests.addElement("org.w3c.dom.Attr");
+		tests.addElement("org.xml.sax.XMLReader");
+		tests.addElement("com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl");
+		tests.addElement("jdk.net.Sockets");
+		return tests;
     }
     /**
      * get a vector of strings of packages built into
@@ -578,15 +543,11 @@
     public static File createVmsJavaOptionFile(String[] cmds)
             throws IOException {
         File script = FILE_UTILS.createTempFile(null, "ANT", ".JAVA_OPTS", null, false, true);
-        BufferedWriter out = null;
-        try {
-            out = new BufferedWriter(new FileWriter(script));
-            for (int i = 0; i < cmds.length; i++) {
-                out.write(cmds[i]);
+        try (BufferedWriter out = new BufferedWriter(new FileWriter(script))) {
+            for (String cmd : cmds) {
+                out.write(cmd);
                 out.newLine();
             }
-        } finally {
-            FileUtils.close(out);
         }
         return script;
     }
diff --git a/src/main/org/apache/tools/ant/util/KeepAliveInputStream.java b/src/main/org/apache/tools/ant/util/KeepAliveInputStream.java
index 58332b5..1890516 100644
--- a/src/main/org/apache/tools/ant/util/KeepAliveInputStream.java
+++ b/src/main/org/apache/tools/ant/util/KeepAliveInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,7 @@
 import java.io.InputStream;
 
 /**
- * Class that can be used to wrap <tt>System.in</tt>
+ * Class that can be used to wrap <code>System.in</code>
  * without getting anxious about any client closing the stream.
  *
  * <p>
diff --git a/src/main/org/apache/tools/ant/util/KeepAliveOutputStream.java b/src/main/org/apache/tools/ant/util/KeepAliveOutputStream.java
index 352b0ba..d10cb3c 100644
--- a/src/main/org/apache/tools/ant/util/KeepAliveOutputStream.java
+++ b/src/main/org/apache/tools/ant/util/KeepAliveOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,7 @@
 import java.io.PrintStream;
 
 /**
- * Class that can be used to wrap <tt>System.out</tt> and <tt>System.err</tt>
+ * Class that can be used to wrap <code>System.out</code> and <code>System.err</code>
  * without getting anxious about any client closing the stream.
  *
  * <p>
diff --git a/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java b/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
index 2771073..fbdb6b9 100644
--- a/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
+++ b/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,6 @@
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -28,15 +27,19 @@
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.PushbackReader;
+import java.io.Serializable;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 
 /**
  * <p>A Properties collection which preserves comments and whitespace
  * present in the input stream from which it was loaded.</p>
- * <p>The class defers the usual work of the <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>
+ * <p>The class defers the usual work of the <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">java.util.Properties</a>
  * class to there, but it also keeps track of the contents of the
  * input stream from which it was loaded (if applicable), so that it can
  * write out the properties in as close a form as possible to the input.</p>
@@ -78,19 +81,21 @@
  * although the key-value pair <code>beta=two</code> is removed.</p>
  */
 public class LayoutPreservingProperties extends Properties {
-    private String LS = StringUtils.LINE_SEP;
+    private static final long serialVersionUID = 1L;
+
+    private String eol = System.lineSeparator();
 
     /**
      * Logical lines have escaping and line continuation taken care
      * of. Comments and blank lines are logical lines; they are not
      * removed.
      */
-    private ArrayList logicalLines = new ArrayList();
+    private List<LogicalLine> logicalLines = new ArrayList<>();
 
     /**
      * Position in the <code>logicalLines</code> list, keyed by property name.
      */
-    private HashMap keyedPairLines = new HashMap();
+    private Map<String, Integer> keyedPairLines = new HashMap<>();
 
     /**
      * Flag to indicate that, when we remove a property from the file, we
@@ -141,7 +146,7 @@
     @Override
     public void load(final InputStream inStream) throws IOException {
         final String s = readLines(inStream);
-        final byte[] ba = s.getBytes(ResourceUtils.ISO_8859_1);
+        final byte[] ba = s.getBytes(StandardCharsets.ISO_8859_1);
         final ByteArrayInputStream bais = new ByteArrayInputStream(ba);
         super.load(bais);
     }
@@ -175,14 +180,14 @@
         value = escapeValue(value);
 
         if (keyedPairLines.containsKey(key)) {
-            final Integer i = (Integer) keyedPairLines.get(key);
-            final Pair p = (Pair) logicalLines.get(i.intValue());
+            final Integer i = keyedPairLines.get(key);
+            final Pair p = (Pair) logicalLines.get(i);
             p.setValue(value);
         } else {
             key = escapeName(key);
             final Pair p = new Pair(key, value);
             p.setNew(true);
-            keyedPairLines.put(key, new Integer(logicalLines.size()));
+            keyedPairLines.put(key, logicalLines.size());
             logicalLines.add(p);
         }
     }
@@ -197,12 +202,12 @@
     @Override
     public Object remove(final Object key) {
         final Object obj = super.remove(key);
-        final Integer i = (Integer) keyedPairLines.remove(key);
+        final Integer i = keyedPairLines.remove(key);
         if (null != i) {
             if (removeComments) {
-                removeCommentsEndingAt(i.intValue());
+                removeCommentsEndingAt(i);
             }
-            logicalLines.set(i.intValue(), null);
+            logicalLines.set(i, null);
         }
         return obj;
     }
@@ -211,14 +216,14 @@
     public Object clone() {
         final LayoutPreservingProperties dolly =
             (LayoutPreservingProperties) super.clone();
-        dolly.keyedPairLines = (HashMap) this.keyedPairLines.clone();
-        dolly.logicalLines = (ArrayList) this.logicalLines.clone();
+        dolly.keyedPairLines = new HashMap<>(this.keyedPairLines);
+        dolly.logicalLines = new ArrayList<>(this.logicalLines);
         final int size = dolly.logicalLines.size();
         for (int j = 0; j < size; j++) {
-            final LogicalLine line = (LogicalLine) dolly.logicalLines.get(j);
+            final LogicalLine line = dolly.logicalLines.get(j);
             if (line instanceof Pair) {
                 final Pair p = (Pair) line;
-                dolly.logicalLines.set(j, p.clone());
+                dolly.logicalLines.set(j, (Pair) p.clone());
             }
             // no reason to clone other lines are they are immutable
         }
@@ -232,9 +237,7 @@
      */
     public void listLines(final PrintStream out) {
         out.println("-- logical lines --");
-        final Iterator i = logicalLines.iterator();
-        while (i.hasNext()) {
-            final LogicalLine line = (LogicalLine) i.next();
+        for (LogicalLine line : logicalLines) {
             if (line instanceof Blank) {
                 out.println("blank:   \"" + line + "\"");
             } else if (line instanceof Comment) {
@@ -251,20 +254,20 @@
      * @throws IOException if save fails
      */
     public void saveAs(final File dest) throws IOException {
-        final FileOutputStream fos = new FileOutputStream(dest);
+        final OutputStream fos = Files.newOutputStream(dest.toPath());
         store(fos, null);
         fos.close();
     }
 
     @Override
     public void store(final OutputStream out, final String header) throws IOException {
-        final OutputStreamWriter osw = new OutputStreamWriter(out, ResourceUtils.ISO_8859_1);
+        final OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.ISO_8859_1);
 
         int skipLines = 0;
         final int totalLines = logicalLines.size();
 
         if (header != null) {
-            osw.write("#" + header + LS);
+            osw.write("#" + header + eol);
             if (totalLines > 0
                 && logicalLines.get(0) instanceof Comment
                 && header.equals(logicalLines.get(0).toString().substring(1))) {
@@ -286,22 +289,20 @@
                 // not an existing date comment
             }
         }
-        osw.write("#" + DateUtils.getDateForHeader() + LS);
+        osw.write("#" + DateUtils.getDateForHeader() + eol);
 
         boolean writtenSep = false;
-        for (final Iterator i = logicalLines.subList(skipLines, totalLines).iterator();
-             i.hasNext();) {
-            final LogicalLine line = (LogicalLine) i.next();
+        for (LogicalLine line : logicalLines.subList(skipLines, totalLines)) {
             if (line instanceof Pair) {
-                if (((Pair)line).isNew()) {
+                if (((Pair) line).isNew()) {
                     if (!writtenSep) {
-                        osw.write(LS);
+                        osw.write(eol);
                         writtenSep = true;
                     }
                 }
-                osw.write(line.toString() + LS);
+                osw.write(line.toString() + eol);
             } else if (line != null) {
-                osw.write(line.toString() + LS);
+                osw.write(line.toString() + eol);
             }
         }
         osw.close();
@@ -315,10 +316,10 @@
      * @param is the stream from which to read the data
      */
     private String readLines(final InputStream is) throws IOException {
-        final InputStreamReader isr = new InputStreamReader(is, ResourceUtils.ISO_8859_1);
+        final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.ISO_8859_1);
         final PushbackReader pbr = new PushbackReader(isr, 1);
 
-        if (logicalLines.size() > 0) {
+        if (!logicalLines.isEmpty()) {
             // we add a blank line for spacing
             logicalLines.add(new Blank());
         }
@@ -328,17 +329,17 @@
 
         boolean continuation = false;
         boolean comment = false;
-        final StringBuffer fileBuffer = new StringBuffer();
-        final StringBuffer logicalLineBuffer = new StringBuffer();
+        final StringBuilder fileBuffer = new StringBuilder();
+        final StringBuilder logicalLineBuffer = new StringBuilder();
         while (s != null) {
-            fileBuffer.append(s).append(LS);
+            fileBuffer.append(s).append(eol);
 
             if (continuation) {
                 // put in the line feed that was removed
                 s = "\n" + s;
             } else {
                 // could be a comment, if first non-whitespace is a # or !
-                comment = s.matches("^( |\t|\f)*(#|!).*");
+                comment = s.matches("^[ \t\f]*[#!].*");
             }
 
             // continuation if not a comment and the line ends is an
@@ -350,10 +351,10 @@
             logicalLineBuffer.append(s);
 
             if (!continuation) {
-                LogicalLine line = null;
+                LogicalLine line;
                 if (comment) {
                     line = new Comment(logicalLineBuffer.toString());
-                } else if (logicalLineBuffer.toString().trim().length() == 0) {
+                } else if (logicalLineBuffer.toString().trim().isEmpty()) {
                     line = new Blank();
                 } else {
                     line = new Pair(logicalLineBuffer.toString());
@@ -363,7 +364,7 @@
                         // the new one
                         remove(key);
                     }
-                    keyedPairLines.put(key, Integer.valueOf(logicalLines.size()));
+                    keyedPairLines.put(key, logicalLines.size());
                 }
                 logicalLines.add(line);
                 logicalLineBuffer.setLength(0);
@@ -385,12 +386,12 @@
      * @since Ant 1.8.2
      */
     private String readFirstLine(final PushbackReader r) throws IOException {
-        final StringBuffer sb = new StringBuffer(80);
+        final StringBuilder sb = new StringBuilder(80);
         int ch = r.read();
         boolean hasCR = false;
         // when reaching EOF before the first EOL, assume native line
         // feeds
-        LS = StringUtils.LINE_SEP;
+        eol = System.lineSeparator();
 
         while (ch >= 0) {
             if (hasCR && ch != '\n') {
@@ -400,10 +401,10 @@
             }
 
             if (ch == '\r') {
-                LS = "\r";
+                eol = "\r";
                 hasCR = true;
             } else if (ch == '\n') {
-                LS = hasCR ? "\r\n" : "\n";
+                eol = hasCR ? "\r\n" : "\n";
                 break;
             } else {
                 sb.append((char) ch);
@@ -435,7 +436,7 @@
     /**
      * Unescape the string according to the rules for a Properties
      * file, as laid out in the docs for <a
-     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
+     * href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">java.util.Properties</a>.
      * @param s the string to unescape (coming from the source file)
      * @return the unescaped string
      */
@@ -455,13 +456,14 @@
         final char[] ch = new char[s.length() + 1];
         s.getChars(0, s.length(), ch, 0);
         ch[s.length()] = '\n';
-        final StringBuffer buffy = new StringBuffer(s.length());
+        final StringBuilder buffy = new StringBuilder(s.length());
         for (int i = 0; i < ch.length; i++) {
             char c = ch[i];
             if (c == '\n') {
                 // we have hit out end-of-string marker
                 break;
-            } else if (c == '\\') {
+            }
+            if (c == '\\') {
                 // possibly an escape sequence
                 c = ch[++i];
                 if (c == 'n') {
@@ -501,7 +503,7 @@
     /**
      * Escape the string <code>s</code> according to the rules in the
      * docs for <a
-     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
+     * href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">java.util.Properties</a>.
      * @param s the string to escape
      * @return the escaped string
      */
@@ -512,7 +514,7 @@
     /**
      * Escape the string <code>s</code> according to the rules in the
      * docs for <a
-     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
+     * href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">java.util.Properties</a>.
      * This method escapes all the whitespace, not just the stuff at
      * the beginning.
      * @param s the string to escape
@@ -525,7 +527,7 @@
     /**
      * Escape the string <code>s</code> according to the rules in the
      * docs for <a
-     * href="http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html">java.util.Properties</a>.
+     * href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">java.util.Properties</a>.
      * @param s the string to escape
      * @param escapeAllSpaces if <code>true</code> the method escapes
      * all the spaces, if <code>false</code>, it escapes only the
@@ -541,7 +543,7 @@
         s.getChars(0, s.length(), ch, 0);
         final String forEscaping = "\t\f\r\n\\:=#!";
         final String escaped = "tfrn\\:=#!";
-        final StringBuffer buffy = new StringBuffer(s.length());
+        final StringBuilder buffy = new StringBuilder(s.length());
         boolean leadingSpace = true;
         for (final char c : ch) {
             if (c == ' ') {
@@ -553,7 +555,7 @@
             }
             final int p = forEscaping.indexOf(c);
             if (p != -1) {
-                buffy.append("\\").append(escaped.substring(p, p + 1));
+                buffy.append("\\").append(escaped, p, p + 1);
             } else if (c < 0x0020 || c > 0x007e) {
                 buffy.append(escapeUnicode(c));
             } else {
@@ -571,7 +573,7 @@
      */
     private String escapeUnicode(final char ch) {
         return "\\" + UnicodeUtil.EscapeUnicode(ch);
-        }
+    }
 
     /**
      * Remove the comments in the leading up the {@link #logicalLines}
@@ -618,7 +620,9 @@
     /**
      * A logical line of the properties input stream.
      */
-    private abstract static class LogicalLine {
+    private abstract static class LogicalLine implements Serializable {
+        private static final long serialVersionUID = 1L;
+
         private String text;
 
         public LogicalLine(final String text) {
@@ -639,6 +643,8 @@
      * A blank line of the input stream.
      */
     private static class Blank extends LogicalLine {
+        private static final long serialVersionUID = 1L;
+
         public Blank() {
             super("");
         }
@@ -648,6 +654,8 @@
      * A comment line of the input stream.
      */
     private class Comment extends LogicalLine {
+        private static final long serialVersionUID = 1L;
+
         public Comment(final String text) {
             super(text);
         }
@@ -659,6 +667,8 @@
      * line.
      */
     private static class Pair extends LogicalLine implements Cloneable {
+        private static final long serialVersionUID = 1L;
+
         private String name;
         private String value;
         private boolean added;
@@ -676,6 +686,7 @@
             return name;
         }
 
+        @SuppressWarnings("unused")
         public String getValue() {
             return value;
         }
@@ -711,10 +722,10 @@
             if (pos == -1) {
                 // trim leading whitespace only
                 name = text;
-                value = null;
+                setValue(null);
             } else {
                 name = text.substring(0, pos);
-                value = text.substring(pos + 1, text.length());
+                setValue(text.substring(pos + 1));
             }
             // trim leading whitespace only
             name = stripStart(name, " \t\f");
diff --git a/src/main/org/apache/tools/ant/util/LazyFileOutputStream.java b/src/main/org/apache/tools/ant/util/LazyFileOutputStream.java
index 7e5bf78..127dd4b 100644
--- a/src/main/org/apache/tools/ant/util/LazyFileOutputStream.java
+++ b/src/main/org/apache/tools/ant/util/LazyFileOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,9 @@
 package org.apache.tools.ant.util;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Class that delays opening the output file until the first bytes
@@ -31,7 +31,7 @@
  */
 public class LazyFileOutputStream extends OutputStream {
 
-    private FileOutputStream fos;
+    private OutputStream fos;
     private File file;
     private boolean append;
     private boolean alwaysCreate;
@@ -107,6 +107,7 @@
      * Close the file.
      * @throws IOException if there is an error.
      */
+    @Override
     public synchronized void close() throws IOException {
         if (alwaysCreate && !closed) {
             ensureOpened();
@@ -122,6 +123,7 @@
      * @param b the bytearray to write.
      * @throws IOException if there is a problem.
      */
+    @Override
     public void write(byte[] b) throws IOException {
         write(b, 0, b.length);
     }
@@ -133,6 +135,7 @@
      * @param len    the number of bytes to write.
      * @throws IOException if there is a problem.
      */
+    @Override
     public synchronized void write(byte[] b, int offset, int len)
         throws IOException {
         ensureOpened();
@@ -144,6 +147,7 @@
      * @param b the byte to write.
      * @throws IOException if there is a problem.
      */
+    @Override
     public synchronized void write(int b) throws IOException {
         ensureOpened();
         fos.write(b);
@@ -155,7 +159,7 @@
         }
 
         if (!opened) {
-            fos = new FileOutputStream(file.getAbsolutePath(), append);
+            fos = FileUtils.newOutputStream(file.toPath(), append);
             opened = true;
         }
     }
diff --git a/src/main/org/apache/tools/ant/util/LazyHashtable.java b/src/main/org/apache/tools/ant/util/LazyHashtable.java
index 1df953c..bc48ca6 100644
--- a/src/main/org/apache/tools/ant/util/LazyHashtable.java
+++ b/src/main/org/apache/tools/ant/util/LazyHashtable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,7 +28,8 @@
  *
  * @since Ant 1.6
  */
-public class LazyHashtable extends Hashtable {
+@Deprecated
+public class LazyHashtable<K, V> extends Hashtable<K, V> {
     // CheckStyle:VisibilityModifier OFF - bc
     protected boolean initAllDone = false;
     // CheckStyle:VisibilityModifier OFF - bc
@@ -54,7 +55,7 @@
      * Get a enumeration over the elements.
      * @return an enumeration.
      */
-    public Enumeration elements() {
+    public Enumeration<V> elements() {
         initAll();
         return super.elements();
     }
@@ -110,7 +111,7 @@
      * Get an enumeration over the keys.
      * @return an enumeration.
      */
-    public Enumeration keys() {
+    public Enumeration<K> keys() {
         initAll();
         return super.keys();
     }
diff --git a/src/main/org/apache/tools/ant/util/LeadPipeInputStream.java b/src/main/org/apache/tools/ant/util/LeadPipeInputStream.java
index 0081912..13dd3aa 100644
--- a/src/main/org/apache/tools/ant/util/LeadPipeInputStream.java
+++ b/src/main/org/apache/tools/ant/util/LeadPipeInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -81,6 +81,7 @@
      * @return the byte (0 to 255) or -1 if there are no more.
      * @throws IOException if there is an error.
      */
+    @Override
     public synchronized int read() throws IOException {
         int result = -1;
         try {
diff --git a/src/main/org/apache/tools/ant/util/LineOrientedOutputStream.java b/src/main/org/apache/tools/ant/util/LineOrientedOutputStream.java
index 073a89f..e7c9e9f 100644
--- a/src/main/org/apache/tools/ant/util/LineOrientedOutputStream.java
+++ b/src/main/org/apache/tools/ant/util/LineOrientedOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -53,7 +53,7 @@
     @Override
     public final void write(int cc) throws IOException {
         final byte c = (byte) cc;
-        if ((c == LF) || (c == CR)) {
+        if (c == LF || c == CR) {
             if (!skip) {
               processBuffer();
             }
diff --git a/src/main/org/apache/tools/ant/util/LineOrientedOutputStreamRedirector.java b/src/main/org/apache/tools/ant/util/LineOrientedOutputStreamRedirector.java
index 48bad5c..8d86718 100644
--- a/src/main/org/apache/tools/ant/util/LineOrientedOutputStreamRedirector.java
+++ b/src/main/org/apache/tools/ant/util/LineOrientedOutputStreamRedirector.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,11 +34,6 @@
 
     private OutputStream stream;
 
-    // these should be in the ASCII range and hopefully are single bytes
-    // (for LF and CR respectively) for any encoding thrown at this class
-    private static final byte[] EOL =
-        System.getProperty("line.separator").getBytes();
-
     public LineOrientedOutputStreamRedirector(OutputStream stream) {
         this.stream = stream;
     }
@@ -46,12 +41,12 @@
     @Override
     protected void processLine(byte[] b) throws IOException {
         stream.write(b);
-        stream.write(EOL);
+        stream.write(System.lineSeparator().getBytes());
     }
 
     @Override
     protected void processLine(String line) throws IOException {
-        stream.write((line + System.getProperty("line.separator")).getBytes());
+        stream.write(String.format("%s%n", line).getBytes());
     }
 
     @Override
diff --git a/src/main/org/apache/tools/ant/util/LineTokenizer.java b/src/main/org/apache/tools/ant/util/LineTokenizer.java
index 778606d..d6b1f63 100644
--- a/src/main/org/apache/tools/ant/util/LineTokenizer.java
+++ b/src/main/org/apache/tools/ant/util/LineTokenizer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -54,19 +54,19 @@
      * @exception IOException if an error occurs reading
      */
     public String getToken(Reader in) throws IOException {
-        int ch = -1;
-        if (pushed != NOT_A_CHAR) {
+        int ch;
+        if (pushed == NOT_A_CHAR) {
+            ch = in.read();
+        } else {
             ch = pushed;
             pushed = NOT_A_CHAR;
-        } else {
-            ch = in.read();
         }
         if (ch == -1) {
             return null;
         }
 
         lineEnd = "";
-        StringBuffer line = new StringBuffer();
+        StringBuilder line = new StringBuilder();
 
         int state = 0;
         while (ch != -1) {
@@ -104,11 +104,9 @@
     /**
      * @return the line ending character(s) for the current line
      */
+    @Override
     public String getPostToken() {
-        if (includeDelims) {
-            return "";
-        }
-        return lineEnd;
+        return includeDelims ? "" : lineEnd;
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/util/LinkedHashtable.java b/src/main/org/apache/tools/ant/util/LinkedHashtable.java
index 73fc83c..98d0c86 100644
--- a/src/main/org/apache/tools/ant/util/LinkedHashtable.java
+++ b/src/main/org/apache/tools/ant/util/LinkedHashtable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 package org.apache.tools.ant.util;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.LinkedHashMap;
@@ -43,89 +44,106 @@
     private final LinkedHashMap<K, V> map;
 
     public LinkedHashtable() {
-        map = new LinkedHashMap<K, V>();
+        map = new LinkedHashMap<>();
     }
 
     public LinkedHashtable(int initialCapacity) {
-        map = new LinkedHashMap<K, V>(initialCapacity);
+        map = new LinkedHashMap<>(initialCapacity);
     }
 
     public LinkedHashtable(int initialCapacity, float loadFactor) {
-        map = new LinkedHashMap<K, V>(initialCapacity, loadFactor);
+        map = new LinkedHashMap<>(initialCapacity, loadFactor);
     }
 
     public LinkedHashtable(Map<K, V> m) {
-        map = new LinkedHashMap<K, V>(m);
+        map = new LinkedHashMap<>(m);
     }
 
     public synchronized void clear() {
         map.clear();
     }
 
+    @Override
     public boolean contains(Object value) {
         return containsKey(value);
     }
 
+    @Override
     public synchronized boolean containsKey(Object value) {
         return map.containsKey(value);
     }
 
+    @Override
     public synchronized boolean containsValue(Object value) {
         return map.containsValue(value);
     }
 
+    @Override
     public Enumeration<V> elements() {
-        return CollectionUtils.asEnumeration(values().iterator());
+        return Collections.enumeration(values());
     }
 
+    @Override
     public synchronized Set<Map.Entry<K, V>> entrySet() {
         return map.entrySet();
     }
 
+    @Override
     public synchronized boolean equals(Object o) {
         return map.equals(o);
     }
 
+    @Override
     public synchronized V get(Object k) {
         return map.get(k);
     }
 
+    @Override
     public synchronized int hashCode() {
         return map.hashCode();
     }
 
+    @Override
     public synchronized boolean isEmpty() {
         return map.isEmpty();
     }
 
+    @Override
     public Enumeration<K> keys() {
-        return CollectionUtils.asEnumeration(keySet().iterator());
+        return Collections.enumeration(keySet());
     }
 
+    @Override
     public synchronized Set<K> keySet() {
         return map.keySet();
     }
 
+    @Override
     public synchronized V put(K k, V v) {
         return map.put(k, v);
     }
 
+    @Override
     public synchronized void putAll(Map<? extends K, ? extends V> m) {
         map.putAll(m);
     }
 
+    @Override
     public synchronized V remove(Object k) {
         return map.remove(k);
     }
 
+    @Override
     public synchronized int size() {
         return map.size();
     }
 
+    @Override
     public synchronized String toString() {
         return map.toString();
     }
 
+    @Override
     public synchronized Collection<V> values() {
         return map.values();
     }
diff --git a/src/main/org/apache/tools/ant/util/LoaderUtils.java b/src/main/org/apache/tools/ant/util/LoaderUtils.java
index e0514f6..affa713 100644
--- a/src/main/org/apache/tools/ant/util/LoaderUtils.java
+++ b/src/main/org/apache/tools/ant/util/LoaderUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -94,7 +94,7 @@
      *
      * @since Ant 1.6
      */
-    public static File getClassSource(Class c) {
+    public static File getClassSource(Class<?> c) {
         return normalizeSource(Locator.getClassSource(c));
     }
 
@@ -130,7 +130,7 @@
      * Check if a classloader has a classname resource.
      * @param loader the classloader to look it.
      * @param className the name of the class to look for.
-     * @return true if the classexists, false otherwise
+     * @return true if the class exists, false otherwise
      * @since Ant 1.7.0.
      */
     public static boolean classExists(ClassLoader loader, String className) {
diff --git a/src/main/org/apache/tools/ant/util/MergingMapper.java b/src/main/org/apache/tools/ant/util/MergingMapper.java
index d61ae30..b13bd10 100644
--- a/src/main/org/apache/tools/ant/util/MergingMapper.java
+++ b/src/main/org/apache/tools/ant/util/MergingMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -46,6 +46,7 @@
      * Ignored.
      * @param from ignored.
      */
+    @Override
     public void setFrom(String from) {
     }
 
@@ -53,6 +54,7 @@
      * Sets the name of the merged file.
      * @param to the name of the merged file.
      */
+    @Override
     public void setTo(String to) {
         mergedFile = new String[] {to};
     }
@@ -62,6 +64,7 @@
      * @param sourceFileName ignored.
      * @return a one-element array containing the merged filename.
      */
+    @Override
     public String[] mapFileName(String sourceFileName) {
         return mergedFile;
     }
diff --git a/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java b/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java
index a69d031..0c5f90a 100644
--- a/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java
+++ b/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -38,12 +38,7 @@
             if (c <= MAX_ASCII) {
                 sb.append(c);
             } else {
-                sb.append("\\u");
-                String encoded = Integer.toHexString(c);
-                for (int i = encoded.length(); i < 4; i++) {
-                    sb.append("0");
-                }
-                sb.append(encoded);
+                sb.append(String.format("\\u%04x", (int) c));
             }
         }
         return sb.toString();
diff --git a/src/main/org/apache/tools/ant/util/NullOutputStream.java b/src/main/org/apache/tools/ant/util/NullOutputStream.java
new file mode 100644
index 0000000..c8e9898
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/NullOutputStream.java
@@ -0,0 +1,55 @@
+/*
+ *  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
+ *
+ *      https://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.OutputStream;
+
+/**
+ * OutputStream that completely discards all data written to it.
+ *
+ * @since Ant 1.10.10
+ */
+public class NullOutputStream extends OutputStream {
+
+    /**
+     * Shared instance which is safe to use concurrently as the stream
+     * doesn't hold any state at all.
+     */
+    public static NullOutputStream INSTANCE = new NullOutputStream();
+
+    private NullOutputStream() { }
+
+    /**
+     * Doesn't do anything.
+     */
+    @Override
+    public void write(byte[] b) { }
+
+    /**
+     * Doesn't do anything.
+     */
+    @Override
+    public void write(byte[] b, int off, int len) { }
+
+    /**
+     * Doesn't do anything.
+     */
+    @Override
+    public void write(int i) { }
+}
diff --git a/src/main/org/apache/tools/ant/util/OutputStreamFunneler.java b/src/main/org/apache/tools/ant/util/OutputStreamFunneler.java
index 9b4cef3..76134c8 100644
--- a/src/main/org/apache/tools/ant/util/OutputStreamFunneler.java
+++ b/src/main/org/apache/tools/ant/util/OutputStreamFunneler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -44,6 +44,7 @@
             }
         }
 
+        @Override
         public void flush() throws IOException {
             synchronized (OutputStreamFunneler.this) {
                 dieIfClosed();
@@ -51,6 +52,7 @@
             }
         }
 
+        @Override
         public void write(int b) throws IOException {
             synchronized (OutputStreamFunneler.this) {
                 dieIfClosed();
@@ -58,6 +60,7 @@
             }
         }
 
+        @Override
         public void write(byte[] b) throws IOException {
             synchronized (OutputStreamFunneler.this) {
                 dieIfClosed();
@@ -65,6 +68,7 @@
             }
         }
 
+        @Override
         public void write(byte[] b, int off, int len) throws IOException {
             synchronized (OutputStreamFunneler.this) {
                 dieIfClosed();
@@ -72,6 +76,7 @@
             }
         }
 
+        @Override
         public void close() throws IOException {
             release(this);
         }
diff --git a/src/main/org/apache/tools/ant/util/PackageNameMapper.java b/src/main/org/apache/tools/ant/util/PackageNameMapper.java
index 3025667..9b5993c 100644
--- a/src/main/org/apache/tools/ant/util/PackageNameMapper.java
+++ b/src/main/org/apache/tools/ant/util/PackageNameMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -37,6 +37,7 @@
      *@param  name  Source filename
      *@return       Replaced variable part
      */
+    @Override
     protected String extractVariablePart(String name) {
         String var = name.substring(prefixLength,
                 name.length() - postfixLength);
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..1e50217
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/PermissionUtils.java
@@ -0,0 +1,246 @@
+/*
+ *  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
+ *
+ *      https://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 permissions 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 r 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.
+     * @throws IOException if something goes wrong
+     */
+    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 r 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
+     * @throws IOException if something goes wrong
+     */
+    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}.
+         *
+         * @param p Path
+         * @return FileType
+         * @throws IOException if file attributes cannot be read
+         */
+        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}.
+         *
+         * @param r Resource
+         * @return FileType
+         */
+        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/ProcessUtil.java b/src/main/org/apache/tools/ant/util/ProcessUtil.java
index 58086f3..5ecc8a8 100644
--- a/src/main/org/apache/tools/ant/util/ProcessUtil.java
+++ b/src/main/org/apache/tools/ant/util/ProcessUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/PropertyOutputStream.java b/src/main/org/apache/tools/ant/util/PropertyOutputStream.java
index 59a1b7e..8b128f0 100644
--- a/src/main/org/apache/tools/ant/util/PropertyOutputStream.java
+++ b/src/main/org/apache/tools/ant/util/PropertyOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,15 @@
 package org.apache.tools.ant.util;
 
 import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
 
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.resources.PropertyResource;
 
 /**
- * Exception thrown when an attempt is made to get an OutputStream
- * from an immutable Resource.
+ * {@link OutputStream} that writes an Ant property.
  * @since Ant 1.7
+ * @see PropertyResource#getOutputStream()
  */
 public class PropertyOutputStream extends ByteArrayOutputStream {
     private Project project;
@@ -58,6 +60,7 @@
     /**
      * Close the PropertyOutputStream, storing the property.
      */
+    @Override
     public void close() {
         if (project != null && property != null) {
             String s = new String(toByteArray());
diff --git a/src/main/org/apache/tools/ant/util/ProxySetup.java b/src/main/org/apache/tools/ant/util/ProxySetup.java
index ea69e72..81b529b 100644
--- a/src/main/org/apache/tools/ant/util/ProxySetup.java
+++ b/src/main/org/apache/tools/ant/util/ProxySetup.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -95,7 +95,7 @@
      * is set, use that instead. Else set to "true".
      */
     public void enableProxies() {
-        if (!(getSystemProxySetting() != null)) {
+        if (getSystemProxySetting() == null) {
             String proxies = owner.getProperty(USE_SYSTEM_PROXIES);
             if (proxies == null || Project.toBoolean(proxies)) {
                 proxies = "true";
diff --git a/src/main/org/apache/tools/ant/util/ReaderInputStream.java b/src/main/org/apache/tools/ant/util/ReaderInputStream.java
index 21733b6..ff2eb63 100644
--- a/src/main/org/apache/tools/ant/util/ReaderInputStream.java
+++ b/src/main/org/apache/tools/ant/util/ReaderInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,23 +20,68 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.util.Objects;
 
 /**
  * Adapts a <code>Reader</code> as an <code>InputStream</code>.
- * Adapted from <code>StringInputStream</code>.
- *
+ * <p>This is a stripped down version of {@code org.apache.commons.io.input.ReaderInputStream} of Apache Commons IO 2.7.</p>
  */
 public class ReaderInputStream extends InputStream {
-    private static final int BYTE_MASK = 0xFF;
+    private static final int EOF = -1;
+    private static final int DEFAULT_BUFFER_SIZE = 1024;
 
-    /** Source Reader */
-    private Reader in;
+    private final Reader reader;
+    private final CharsetEncoder encoder;
 
-    private String encoding = System.getProperty("file.encoding");
+    /**
+     * CharBuffer used as input for the decoder. It should be reasonably
+     * large as we read data from the underlying Reader into this buffer.
+     */
+    private final CharBuffer encoderIn;
 
-    private byte[] slack;
+    /**
+     * ByteBuffer used as output for the decoder. This buffer can be small
+     * as it is only used to transfer data from the decoder to the
+     * buffer provided by the caller.
+     */
+    private final ByteBuffer encoderOut;
 
-    private int begin;
+    private CoderResult lastCoderResult;
+    private boolean endOfInput;
+
+    /**
+     * Construct a new {@link ReaderInputStream}.
+     *
+     * @param reader the target {@link Reader}
+     * @param encoder the charset encoder
+     * @since 1.10.9
+     */
+    public ReaderInputStream(final Reader reader, final CharsetEncoder encoder) {
+        this(reader, encoder, DEFAULT_BUFFER_SIZE);
+    }
+
+    /**
+     * Construct a new {@link ReaderInputStream}.
+     *
+     * @param reader the target {@link Reader}
+     * @param encoder the charset encoder
+     * @param bufferSize the size of the input buffer in number of characters
+     * @since 1.10.9
+     */
+    public ReaderInputStream(final Reader reader, final CharsetEncoder encoder, final int bufferSize) {
+        this.reader = reader;
+        this.encoder = encoder;
+        this.encoderIn = CharBuffer.allocate(bufferSize);
+        this.encoderIn.flip();
+        this.encoderOut = ByteBuffer.allocate(128);
+        this.encoderOut.flip();
+    }
 
     /**
      * Construct a <code>ReaderInputStream</code>
@@ -45,7 +90,7 @@
      * @param reader   <code>Reader</code>.  Must not be <code>null</code>.
      */
     public ReaderInputStream(Reader reader) {
-        in = reader;
+        this(reader, Charset.defaultCharset());
     }
 
     /**
@@ -57,149 +102,129 @@
      * @param encoding   non-null <code>String</code> encoding.
      */
     public ReaderInputStream(Reader reader, String encoding) {
-        this(reader);
-        if (encoding == null) {
-            throw new IllegalArgumentException("encoding must not be null");
-        } else {
-            this.encoding = encoding;
-        }
+        this(reader, Charset.forName(encoding));
     }
 
     /**
-     * Reads from the <code>Reader</code>, returning the same value.
+     * Construct a <code>ReaderInputStream</code>
+     * for the specified <code>Reader</code>,
+     * with the specified encoding.
      *
-     * @return the value of the next character in the <code>Reader</code>.
-     *
-     * @exception IOException if the original <code>Reader</code> fails to be read
+     * @param reader     non-null <code>Reader</code>.
+     * @param charset    non-null <code>Charset</code> charset.
+     * @since Ant 1.10.6
      */
-    public synchronized int read() throws IOException {
-        if (in == null) {
-            throw new IOException("Stream Closed");
-        }
+    public ReaderInputStream(Reader reader, Charset charset) {
+        this(reader,
+             charset.newEncoder()
+                 .onMalformedInput(CodingErrorAction.REPLACE)
+                 .onUnmappableCharacter(CodingErrorAction.REPLACE));
+    }
 
-        byte result;
-        if (slack != null && begin < slack.length) {
-            result = slack[begin];
-            if (++begin == slack.length) {
-                slack = null;
-            }
-        } else {
-            byte[] buf = new byte[1];
-            if (read(buf, 0, 1) <= 0) {
-                return -1;
+    /**
+     * Fills the internal char buffer from the reader.
+     *
+     * @throws IOException
+     *             If an I/O error occurs
+     */
+    private void fillBuffer() throws IOException {
+        if (!endOfInput && (lastCoderResult == null || lastCoderResult.isUnderflow())) {
+            encoderIn.compact();
+            final int position = encoderIn.position();
+            // We don't use Reader#read(CharBuffer) here because it is more efficient
+            // to write directly to the underlying char array (the default implementation
+            // copies data to a temporary char array).
+            final int c = reader.read(encoderIn.array(), position, encoderIn.remaining());
+            if (c == EOF) {
+                endOfInput = true;
             } else {
-                result = buf[0];
+                encoderIn.position(position+c);
             }
+            encoderIn.flip();
         }
-        return result & BYTE_MASK;
+        encoderOut.compact();
+        lastCoderResult = encoder.encode(encoderIn, encoderOut, endOfInput);
+        encoderOut.flip();
     }
 
     /**
-     * Reads from the <code>Reader</code> into a byte array
+     * Read the specified number of bytes into an array.
      *
-     * @param b  the byte array to read into
-     * @param off the offset in the byte array
-     * @param len the length in the byte array to fill
-     * @return the actual number read into the byte array, -1 at
-     *         the end of the stream
-     * @exception IOException if an error occurs
+     * @param array the byte array to read into
+     * @param off the offset to start reading bytes into
+     * @param len the number of bytes to read
+     * @return the number of bytes read or <code>-1</code>
+     *         if the end of the stream has been reached
+     * @throws IOException if an I/O error occurs
      */
-    public synchronized int read(byte[] b, int off, int len)
-        throws IOException {
-        if (in == null) {
-            throw new IOException("Stream Closed");
+    @Override
+    public int read(final byte[] array, int off, int len) throws IOException {
+        Objects.requireNonNull(array, "array");
+        if (len < 0 || off < 0 || (off + len) > array.length) {
+            throw new IndexOutOfBoundsException("Array Size=" + array.length +
+                    ", offset=" + off + ", length=" + len);
         }
+        int read = 0;
         if (len == 0) {
-            return 0;
+            return 0; // Always return 0 if len == 0
         }
-        while (slack == null) {
-            char[] buf = new char[len]; // might read too much
-            int n = in.read(buf);
-            if (n == -1) {
-                return -1;
-            }
-            if (n > 0) {
-                slack = new String(buf, 0, n).getBytes(encoding);
-                begin = 0;
+        while (len > 0) {
+            if (encoderOut.hasRemaining()) {
+                final int c = Math.min(encoderOut.remaining(), len);
+                encoderOut.get(array, off, c);
+                off += c;
+                len -= c;
+                read += c;
+            } else {
+                fillBuffer();
+                if (endOfInput && !encoderOut.hasRemaining()) {
+                    break;
+                }
             }
         }
-
-        if (len > slack.length - begin) {
-            len = slack.length - begin;
-        }
-
-        System.arraycopy(slack, begin, b, off, len);
-
-        begin += len;
-        if (begin >= slack.length) {
-            slack = null;
-        }
-
-        return len;
+        return read == 0 && endOfInput ? EOF : read;
     }
 
     /**
-     * Marks the read limit of the Reader.
+     * Read the specified number of bytes into an array.
      *
-     * @param limit the maximum limit of bytes that can be read before the
-     *              mark position becomes invalid
+     * @param b the byte array to read into
+     * @return the number of bytes read or <code>-1</code>
+     *         if the end of the stream has been reached
+     * @throws IOException if an I/O error occurs
      */
-    public synchronized void mark(final int limit) {
-        try {
-            in.mark(limit);
-        } catch (IOException ioe) {
-            throw new RuntimeException(ioe.getMessage()); //NOSONAR
-        }
-    }
-
-
-    /**
-     * @return   the current number of bytes ready for reading
-     * @exception IOException if an error occurs
-     */
-    public synchronized int available() throws IOException {
-        if (in == null) {
-            throw new IOException("Stream Closed");
-        }
-        if (slack != null) {
-            return slack.length - begin;
-        }
-        if (in.ready()) {
-            return 1;
-        }
-        return 0;
+    @Override
+    public int read(final byte[] b) throws IOException {
+        return read(b, 0, b.length);
     }
 
     /**
-     * @return false - mark is not supported
-     */
-    public boolean markSupported() {
-        return false;   // would be imprecise
-    }
-
-    /**
-     * Resets the Reader.
+     * Read a single byte.
      *
-     * @exception IOException if the Reader fails to be reset
+     * @return either the byte read or <code>-1</code> if the end of the stream
+     *         has been reached
+     * @throws IOException if an I/O error occurs
      */
-    public synchronized void reset() throws IOException {
-        if (in == null) {
-            throw new IOException("Stream Closed");
+    @Override
+    public int read() throws IOException {
+        for (;;) {
+            if (encoderOut.hasRemaining()) {
+                return encoderOut.get() & 0xFF;
+            }
+            fillBuffer();
+            if (endOfInput && !encoderOut.hasRemaining()) {
+                return EOF;
+            }
         }
-        slack = null;
-        in.reset();
     }
 
     /**
-     * Closes the Reader.
-     *
-     * @exception IOException if the original Reader fails to be closed
+     * Close the stream. This method will cause the underlying {@link Reader}
+     * to be closed.
+     * @throws IOException if an I/O error occurs
      */
-    public synchronized void close() throws IOException {
-        if (in != null) {
-            in.close();
-            slack = null;
-            in = null;
-        }
+    @Override
+    public void close() throws IOException {
+        reader.close();
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/ReflectUtil.java b/src/main/org/apache/tools/ant/util/ReflectUtil.java
index bc62fa0..ad88a86 100644
--- a/src/main/org/apache/tools/ant/util/ReflectUtil.java
+++ b/src/main/org/apache/tools/ant/util/ReflectUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,8 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.BuildException;
 
@@ -61,16 +63,16 @@
 
     /**
      * Call a method on the object with no parameters.
+     * @param <T> desired type
      * @param obj  the object to invoke the method on.
      * @param methodName the name of the method to call
      * @return the object returned by the method
      */
-    public static Object invoke(Object obj, String methodName) {
+    @SuppressWarnings("unchecked")
+    public static <T> T invoke(Object obj, String methodName) {
         try {
-            Method method;
-            method = obj.getClass().getMethod(
-                        methodName, (Class[]) null);
-            return method.invoke(obj, (Object[]) null);
+            Method method = obj.getClass().getMethod(methodName);
+            return (T) method.invoke(obj);
         } catch (Exception t) {
             throwBuildException(t);
             return null; // NotReached
@@ -81,16 +83,16 @@
      * Call a method on the object with no parameters.
      * Note: Unlike the invoke method above, this
      * calls class or static methods, not instance methods.
+     * @param <T> desired type
      * @param obj  the object to invoke the method on.
      * @param methodName the name of the method to call
      * @return the object returned by the method
      */
-    public static Object invokeStatic(Object obj, String methodName) {
+    @SuppressWarnings("unchecked")
+    public static <T> T invokeStatic(Object obj, String methodName) {
         try {
-            Method method;
-            method = ((Class<?>) obj).getMethod(
-                    methodName, (Class[]) null);
-            return method.invoke(obj, (Object[]) null);
+            Method method = ((Class<?>) obj).getMethod(methodName);
+            return (T) method.invoke(obj);
         } catch (Exception t) {
             throwBuildException(t);
             return null; // NotReached
@@ -99,19 +101,19 @@
 
     /**
      * Call a method on the object with one argument.
+     * @param <T> desired type
      * @param obj  the object to invoke the method on.
      * @param methodName the name of the method to call
      * @param argType    the type of argument.
      * @param arg        the value of the argument.
      * @return the object returned by the method
      */
-    public static Object invoke(
+    @SuppressWarnings("unchecked")
+    public static <T> T invoke(
         Object obj, String methodName, Class<?> argType, Object arg) {
         try {
-            Method method;
-            method = obj.getClass().getMethod(
-                methodName, new Class[] {argType});
-            return method.invoke(obj, new Object[] {arg});
+            Method method = obj.getClass().getMethod(methodName, argType);
+            return (T) method.invoke(obj, arg);
         } catch (Exception t) {
             throwBuildException(t);
             return null; // NotReached
@@ -120,6 +122,7 @@
 
     /**
      * Call a method on the object with two argument.
+     * @param <T> desired type
      * @param obj  the object to invoke the method on.
      * @param methodName the name of the method to call
      * @param argType1   the type of the first argument.
@@ -128,14 +131,14 @@
      * @param arg2       the value of the second argument.
      * @return the object returned by the method
      */
-    public static Object invoke(
+    @SuppressWarnings("unchecked")
+    public static <T> T invoke(
         Object obj, String methodName, Class<?> argType1, Object arg1,
         Class<?> argType2, Object arg2) {
         try {
-            Method method;
-            method = obj.getClass().getMethod(
-                methodName, new Class[] {argType1, argType2});
-            return method.invoke(obj, new Object[] {arg1, arg2});
+            Method method =
+                obj.getClass().getMethod(methodName, argType1, argType2);
+            return (T) method.invoke(obj, arg1, arg2);
         } catch (Exception t) {
             throwBuildException(t);
             return null; // NotReached
@@ -144,17 +147,19 @@
 
     /**
      * Get the value of a field in an object.
+     * @param <T> desired type
      * @param obj the object to look at.
      * @param fieldName the name of the field in the object.
      * @return the value of the field.
      * @throws BuildException if there is an error.
      */
-    public static Object getField(Object obj, String fieldName)
+    @SuppressWarnings("unchecked")
+    public static <T> T getField(Object obj, String fieldName)
         throws BuildException {
         try {
             Field field = obj.getClass().getDeclaredField(fieldName);
             field.setAccessible(true);
-            return field.get(obj);
+            return (T) field.get(obj);
         } catch (Exception t) {
             throwBuildException(t);
             return null; // NotReached
@@ -163,7 +168,7 @@
 
     /**
      * A method to convert an invocationTargetException to
-     * a buildexception and throw it.
+     * a BuildException and throw it.
      * @param t the invocation target exception.
      * @throws BuildException the converted exception.
      */
@@ -174,7 +179,7 @@
 
     /**
      * A method to convert an invocationTargetException to
-     * a buildexception.
+     * a BuildException.
      * @param t the invocation target exception.
      * @return the converted exception.
      * @since ant 1.7.1
@@ -187,9 +192,8 @@
                 return (BuildException) t2;
             }
             return new BuildException(t2);
-        } else {
-            return new BuildException(t);
         }
+        return new BuildException(t);
     }
 
     /**
@@ -203,15 +207,10 @@
     public static boolean respondsTo(Object o, String methodName)
         throws BuildException {
         try {
-            Method[] methods = o.getClass().getMethods();
-            for (int i = 0; i < methods.length; i++) {
-                if (methods[i].getName().equals(methodName)) {
-                    return true;
-                }
-            }
-            return false;
+            return Stream.of(o.getClass().getMethods()).map(Method::getName)
+                .anyMatch(Predicate.isEqual(methodName));
         } catch (Exception t) {
             throw toBuildException(t);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/org/apache/tools/ant/util/ReflectWrapper.java b/src/main/org/apache/tools/ant/util/ReflectWrapper.java
index e34363e..6c9e0b4 100644
--- a/src/main/org/apache/tools/ant/util/ReflectWrapper.java
+++ b/src/main/org/apache/tools/ant/util/ReflectWrapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,6 +28,7 @@
 
 public class ReflectWrapper {
     private Object obj;
+
     /**
      * Construct a wrapped object using the no arg constructor.
      * @param loader the classloader to use to construct the class.
@@ -35,11 +36,9 @@
      */
     public ReflectWrapper(ClassLoader loader, String name) {
         try {
-            Class clazz;
-            clazz = Class.forName(name, true, loader);
-            Constructor constructor;
-            constructor = clazz.getConstructor((Class[]) null);
-            obj = constructor.newInstance((Object[]) null);
+            Class<?> clazz = Class.forName(name, true, loader);
+            Constructor<?> constructor = clazz.getConstructor();
+            obj = constructor.newInstance();
         } catch (Exception t) {
             ReflectUtil.throwBuildException(t);
         }
@@ -54,35 +53,39 @@
     }
 
     /**
+     * @param <T> desired type
      * @return the wrapped object.
      */
-    public Object getObject() {
-        return obj;
+    @SuppressWarnings("unchecked")
+    public <T> T getObject() {
+        return (T) obj;
     }
 
     /**
      * Call a method on the object with no parameters.
+     * @param <T> desired type
      * @param methodName the name of the method to call
      * @return the object returned by the method
      */
-    public Object invoke(String methodName) {
+    public <T> T invoke(String methodName) {
         return ReflectUtil.invoke(obj, methodName);
     }
 
     /**
      * Call a method on the object with one argument.
+     * @param <T> desired type
      * @param methodName the name of the method to call
      * @param argType    the type of argument.
      * @param arg        the value of the argument.
      * @return the object returned by the method
      */
-    public Object invoke(
-        String methodName, Class argType, Object arg) {
+    public <T> T invoke(String methodName, Class<?> argType, Object arg) {
         return ReflectUtil.invoke(obj, methodName, argType, arg);
     }
 
     /**
      * Call a method on the object with one argument.
+     * @param <T> desired type
      * @param methodName the name of the method to call
      * @param argType1   the type of the first argument.
      * @param arg1       the value of the first argument.
@@ -90,10 +93,9 @@
      * @param arg2       the value of the second argument.
      * @return the object returned by the method
      */
-    public Object invoke(
-        String methodName, Class argType1, Object arg1,
-        Class argType2, Object arg2) {
-        return ReflectUtil.invoke(
-            obj, methodName, argType1, arg1, argType2, arg2);
+    public <T> T invoke(String methodName, Class<?> argType1, Object arg1,
+        Class<?> argType2, Object arg2) {
+        return ReflectUtil.invoke(obj, methodName, argType1, arg1, argType2,
+            arg2);
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/RegexpPatternMapper.java b/src/main/org/apache/tools/ant/util/RegexpPatternMapper.java
index 599b7ef..144722a 100644
--- a/src/main/org/apache/tools/ant/util/RegexpPatternMapper.java
+++ b/src/main/org/apache/tools/ant/util/RegexpPatternMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,7 @@
 
 package org.apache.tools.ant.util;
 
-import java.util.Vector;
+import java.util.List;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.util.regexp.RegexpMatcher;
@@ -77,19 +77,19 @@
      * @param from the from pattern.
      * @throws BuildException on error.
      */
+    @Override
     public void setFrom(String from) throws BuildException {
-        if (from != null) {
-            try {
-                reg.setPattern(from);
-            } catch (NoClassDefFoundError e) {
-                // depending on the implementation the actual RE won't
-                // get instantiated in the constructor.
-                throw new BuildException("Cannot load regular expression matcher",
-                                         e);
-            }
-        } else {
+        if (from == null) {
             throw new BuildException("this mapper requires a 'from' attribute");
         }
+        try {
+            reg.setPattern(from);
+        } catch (NoClassDefFoundError e) {
+            // depending on the implementation the actual RE won't
+            // get instantiated in the constructor.
+            throw new BuildException("Cannot load regular expression matcher",
+                e);
+        }
     }
 
     /**
@@ -97,12 +97,12 @@
      * @param to the to pattern.
      * @throws BuildException on error.
      */
+    @Override
     public void setTo(String to) {
-        if (to != null) {
-            this.to = to.toCharArray();
-        } else {
+        if (to == null) {
             throw new BuildException("this mapper requires a 'to' attribute");
         }
+        this.to = to.toCharArray();
     }
 
     /**
@@ -113,6 +113,7 @@
      * @return a one-element array containing the translated file or
      *         null if the to pattern did not match
      */
+    @Override
     public String[] mapFileName(String sourceFileName) {
         if (sourceFileName == null) {
             return null;
@@ -136,7 +137,7 @@
      * @return the translated file name.
      */
     protected String replaceReferences(String source) {
-        Vector v = reg.getGroups(source, regexpOptions);
+        List<String> v = reg.getGroups(source, regexpOptions);
 
         result.setLength(0);
         for (int i = 0; i < to.length; i++) {
@@ -144,7 +145,7 @@
                 if (++i < to.length) {
                     int value = Character.digit(to[i], DECIMAL);
                     if (value > -1) {
-                        result.append((String) v.elementAt(value));
+                        result.append(v.get(value));
                     } else {
                         result.append(to[i]);
                     }
diff --git a/src/main/org/apache/tools/ant/util/ResourceUtils.java b/src/main/org/apache/tools/ant/util/ResourceUtils.java
index c3b80d2..e284def 100644
--- a/src/main/org/apache/tools/ant/util/ResourceUtils.java
+++ b/src/main/org/apache/tools/ant/util/ResourceUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,8 +21,6 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -30,12 +28,15 @@
 import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.file.StandardOpenOption;
 import java.util.Arrays;
 import java.util.Vector;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.filters.util.ChainReaderHelper;
+import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.FilterSetCollection;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
@@ -68,8 +69,10 @@
     /**
      * Name of charset "ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1".
      *
+     * @deprecated use StandardCharsets.ISO_8859_1
      * @since Ant 1.8.1
      */
+    @Deprecated
     public static final String ISO_8859_1 = "ISO-8859-1";
 
     private static final long MAX_IO_CHUNK_SIZE = 16 * 1024 * 1024L; // 16 MB
@@ -143,24 +146,8 @@
                                                             final ResourceFactory targets,
                                                             final long granularity) {
         logFuture(logTo, source, granularity);
-        final ResourceSelectorProvider p =
-            new ResourceSelectorProvider() {
-                public ResourceSelector
-                    getTargetSelectorForSource(final Resource sr) {
-                    return new ResourceSelector() {
-                        public boolean isSelected(final Resource target) {
-                            /* Extra I/O, probably wasted:
-                               if (target.isDirectory()) {
-                               return false;
-                               }
-                            */
-                            return SelectorUtils.isOutOfDate(sr, target,
-                                                             granularity);
-                        }
-                    };
-                }
-            };
-        return selectSources(logTo, source, mapper, targets, p);
+        return selectSources(logTo, source, mapper, targets,
+            sr -> target -> SelectorUtils.isOutOfDate(sr, target, granularity));
     }
 
     /**
@@ -182,7 +169,7 @@
                                                    final FileNameMapper mapper,
                                                    final ResourceFactory targets,
                                                    final ResourceSelectorProvider selector) {
-        if (source.size() == 0) {
+        if (source.isEmpty()) {
             logTo.log("No sources found.", Project.MSG_VERBOSE);
             return Resources.NONE;
         }
@@ -191,8 +178,10 @@
         final Union result = new Union();
         for (final Resource sr : source) {
             String srName = sr.getName();
-            srName = srName == null
-                ? srName : srName.replace('/', File.separatorChar);
+            if (srName != null) {
+                srName = srName.replace('/', File.separatorChar);
+            }
+
 
             String[] targetnames = null;
             try {
@@ -202,7 +191,7 @@
                     Project.MSG_VERBOSE);
             }
             if (targetnames == null || targetnames.length == 0) {
-                logTo.log(sr + " skipped - don\'t know how to handle it",
+                logTo.log(sr + " skipped - don't know how to handle it",
                       Project.MSG_VERBOSE);
                 continue;
             }
@@ -222,7 +211,7 @@
                 result.add(sr);
                 final Resource t = r.iterator().next();
                 logTo.log(sr.getName() + " added as " + t.getName()
-                    + (t.isExists() ? " is outdated." : " doesn\'t exist."),
+                    + (t.isExists() ? " is outdated." : " doesn't exist."),
                     Project.MSG_VERBOSE);
                 continue;
             }
@@ -300,7 +289,7 @@
      * @since Ant 1.7
      */
     public static void copyResource(final Resource source, final Resource dest,
-                             final FilterSetCollection filters, final Vector filterChains,
+                             final FilterSetCollection filters, final Vector<FilterChain> filterChains,
                              final boolean overwrite, final boolean preserveLastModified,
                              final String inputEncoding, final String outputEncoding,
                              final Project project)
@@ -337,7 +326,7 @@
      * @since Ant 1.8
      */
     public static void copyResource(final Resource source, final Resource dest,
-                            final FilterSetCollection filters, final Vector filterChains,
+                            final FilterSetCollection filters, final Vector<FilterChain> filterChains,
                             final boolean overwrite, final boolean preserveLastModified,
                                     final boolean append,
                             final String inputEncoding, final String outputEncoding,
@@ -377,52 +366,46 @@
      * @since Ant 1.8.2
      */
     public static void copyResource(final Resource source, final Resource dest,
-                            final FilterSetCollection filters, final Vector filterChains,
+                            final FilterSetCollection filters, final Vector<FilterChain> filterChains,
                             final boolean overwrite, final boolean preserveLastModified,
                                     final boolean append,
                                     final String inputEncoding, final String outputEncoding,
                                     final Project project, final boolean force)
         throws IOException {
-        if (!(overwrite || SelectorUtils.isOutOfDate(source, dest, FileUtils.getFileUtils()
-                .getFileTimestampGranularity()))) {
+        if (!overwrite && !SelectorUtils.isOutOfDate(source, dest,
+                FileUtils.getFileUtils().getFileTimestampGranularity())) {
             return;
         }
         final boolean filterSetsAvailable = (filters != null
                                              && filters.hasFilters());
         final boolean filterChainsAvailable = (filterChains != null
-                                               && filterChains.size() > 0);
-        String effectiveInputEncoding = null;
-        if (source instanceof StringResource) {
-            effectiveInputEncoding = ((StringResource) source).getEncoding();
-        } else {
-            effectiveInputEncoding = inputEncoding;
-        }
-        File destFile = null;
-        if (dest.as(FileProvider.class) != null) {
-            destFile = dest.as(FileProvider.class).getFile();
-        }
+                                               && !filterChains.isEmpty());
+        final String effectiveInputEncoding = source.asOptional(StringResource.class)
+            .map(StringResource::getEncoding).orElse(inputEncoding);
+
+        File destFile = dest.asOptional(FileProvider.class).map(FileProvider::getFile).orElse(null);
+
         if (destFile != null && destFile.isFile() && !destFile.canWrite()) {
             if (!force) {
                 throw new ReadOnlyTargetFileException(destFile);
-            } else if (!FILE_UTILS.tryHardToDelete(destFile)) {
-                throw new IOException("failed to delete read-only "
-                                      + "destination file " + destFile);
+            }
+            if (!FILE_UTILS.tryHardToDelete(destFile)) {
+                throw new IOException(
+                    "failed to delete read-only destination file " + destFile);
             }
         }
-
         if (filterSetsAvailable) {
             copyWithFilterSets(source, dest, filters, filterChains,
-                               filterChainsAvailable, append,
-                               effectiveInputEncoding, outputEncoding,
-                               project);
+                               append, effectiveInputEncoding,
+                               outputEncoding, project);
         } else if (filterChainsAvailable
                    || (effectiveInputEncoding != null
                        && !effectiveInputEncoding.equals(outputEncoding))
                    || (effectiveInputEncoding == null && outputEncoding != null)) {
             copyWithFilterChainsOrTranscoding(source, dest, filterChains,
-                                              filterChainsAvailable, append,
-                                              effectiveInputEncoding,
-                                              outputEncoding, project);
+                                              append, effectiveInputEncoding,
+                                              outputEncoding,
+                                              project);
         } else {
             boolean copied = false;
             if (source.as(FileProvider.class) != null
@@ -449,10 +432,8 @@
             }
         }
         if (preserveLastModified) {
-            final Touchable t = dest.as(Touchable.class);
-            if (t != null) {
-                setLastModified(t, source.getLastModified());
-            }
+            dest.asOptional(Touchable.class)
+                .ifPresent(t -> setLastModified(t, source.getLastModified()));
         }
     }
     // CheckStyle:ParameterNumberCheck ON
@@ -530,7 +511,7 @@
         }
         final boolean e1 = r1.isExists();
         final boolean e2 = r2.isExists();
-        if (!(e1 || e2)) {
+        if (!e1 && !e2) {
             return 0;
         }
         if (e1 != e2) {
@@ -560,9 +541,8 @@
         if (fileProvider instanceof FileResource || fileProvider == null) {
             return (FileResource) fileProvider;
         }
-        final FileResource result = new FileResource(fileProvider.getFile());
-        result.setProject(Project.getProject(fileProvider));
-        return result;
+        return new FileResource(Project.getProject(fileProvider),
+            fileProvider.getFile());
     }
 
     /**
@@ -581,11 +561,9 @@
      * @since Ant 1.7
      */
     private static int binaryCompare(final Resource r1, final Resource r2) throws IOException {
-        InputStream in1 = null;
-        InputStream in2 = null;
-        try {
-            in1 = new BufferedInputStream(r1.getInputStream());
-            in2 = new BufferedInputStream(r2.getInputStream());
+        try (InputStream in1 = new BufferedInputStream(r1.getInputStream());
+                InputStream in2 =
+                    new BufferedInputStream(r2.getInputStream())) {
 
             for (int b1 = in1.read(); b1 != -1; b1 = in1.read()) {
                 final int b2 = in2.read();
@@ -594,9 +572,6 @@
                 }
             }
             return in2.read() == -1 ? 0 : -1;
-        } finally {
-            FileUtils.close(in1);
-            FileUtils.close(in2);
         }
     }
 
@@ -611,11 +586,10 @@
      * @since Ant 1.7
      */
     private static int textCompare(final Resource r1, final Resource r2) throws IOException {
-        BufferedReader in1 = null;
-        BufferedReader in2 = null;
-        try {
-            in1 = new BufferedReader(new InputStreamReader(r1.getInputStream()));
-            in2 = new BufferedReader(new InputStreamReader(r2.getInputStream()));
+        try (BufferedReader in1 =
+            new BufferedReader(new InputStreamReader(r1.getInputStream()));
+                BufferedReader in2 = new BufferedReader(
+                    new InputStreamReader(r2.getInputStream()))) {
 
             String expected = in1.readLine();
             while (expected != null) {
@@ -629,9 +603,6 @@
                 expected = in1.readLine();
             }
             return in2.readLine() == null ? 0 : -1; //NOSONAR
-        } finally {
-            FileUtils.close(in1);
-            FileUtils.close(in2);
         }
     }
 
@@ -658,10 +629,9 @@
 
     private static void copyWithFilterSets(final Resource source, final Resource dest,
                                            final FilterSetCollection filters,
-                                           final Vector filterChains,
-                                           final boolean filterChainsAvailable,
-                                           final boolean append, final String inputEncoding,
-                                           final String outputEncoding,
+                                           final Vector<FilterChain> filterChains,
+                                           final boolean append,
+                                           final String inputEncoding, final String outputEncoding,
                                            final Project project)
         throws IOException {
 
@@ -671,59 +641,49 @@
             return;
         }
 
-        BufferedReader in = null;
-        BufferedWriter out = null;
-        try {
-            InputStreamReader isr = null;
-            if (inputEncoding == null) {
-                isr = new InputStreamReader(source.getInputStream());
-            } else {
-                isr = new InputStreamReader(source.getInputStream(),
-                                            inputEncoding);
-            }
-            in = new BufferedReader(isr);
-            final OutputStream os = getOutputStream(dest, append, project);
-            OutputStreamWriter osw;
-            if (outputEncoding == null) {
-                osw = new OutputStreamWriter(os);
-            } else {
-                osw = new OutputStreamWriter(os, outputEncoding);
-            }
-            out = new BufferedWriter(osw);
-            if (filterChainsAvailable) {
-                final ChainReaderHelper crh = new ChainReaderHelper();
-                crh.setBufferSize(FileUtils.BUF_SIZE);
-                crh.setPrimaryReader(in);
-                crh.setFilterChains(filterChains);
-                crh.setProject(project);
-                final Reader rdr = crh.getAssembledReader();
-                in = new BufferedReader(rdr);
-            }
+        try (Reader in = filterWith(project, inputEncoding, filterChains,
+                source.getInputStream());
+             BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
+                     getOutputStream(dest, append, project),
+                     charsetFor(outputEncoding)))) {
+
             final LineTokenizer lineTokenizer = new LineTokenizer();
             lineTokenizer.setIncludeDelims(true);
-            String newline = null;
             String line = lineTokenizer.getToken(in);
             while (line != null) {
-                if (line.length() == 0) {
+                if (line.isEmpty()) {
                     // this should not happen, because the lines are
                     // returned with the end of line delimiter
                     out.newLine();
                 } else {
-                    newline = filters.replaceTokens(line);
-                    out.write(newline);
+                    out.write(filters.replaceTokens(line));
                 }
                 line = lineTokenizer.getToken(in);
             }
-        } finally {
-            FileUtils.close(out);
-            FileUtils.close(in);
         }
     }
 
+    private static Reader filterWith(Project project, String encoding,
+        Vector<FilterChain> filterChains, InputStream input) {
+        Reader r = new InputStreamReader(input, charsetFor(encoding));
+        if (filterChains != null && !filterChains.isEmpty()) {
+            final ChainReaderHelper crh = new ChainReaderHelper();
+            crh.setBufferSize(FileUtils.BUF_SIZE);
+            crh.setPrimaryReader(r);
+            crh.setFilterChains(filterChains);
+            crh.setProject(project);
+            r = crh.getAssembledReader();
+        }
+        return new BufferedReader(r);
+    }
+
+    private static Charset charsetFor(String encoding) {
+        return encoding == null ? Charset.defaultCharset() : Charset.forName(encoding);
+    }
+
     private static void copyWithFilterChainsOrTranscoding(final Resource source,
                                                           final Resource dest,
-                                                          final Vector filterChains,
-                                                          final boolean filterChainsAvailable,
+                                                          final Vector<FilterChain> filterChains,
                                                           final boolean append,
                                                           final String inputEncoding,
                                                           final String outputEncoding,
@@ -736,34 +696,11 @@
             return;
         }
 
-        BufferedReader in = null;
-        BufferedWriter out = null;
-        try {
-            InputStreamReader isr = null;
-            if (inputEncoding == null) {
-                isr = new InputStreamReader(source.getInputStream());
-            } else {
-                isr = new InputStreamReader(source.getInputStream(),
-                                            inputEncoding);
-            }
-            in = new BufferedReader(isr);
-            final OutputStream os = getOutputStream(dest, append, project);
-            OutputStreamWriter osw;
-            if (outputEncoding == null) {
-                osw = new OutputStreamWriter(os);
-            } else {
-                osw = new OutputStreamWriter(os, outputEncoding);
-            }
-            out = new BufferedWriter(osw);
-            if (filterChainsAvailable) {
-                final ChainReaderHelper crh = new ChainReaderHelper();
-                crh.setBufferSize(FileUtils.BUF_SIZE);
-                crh.setPrimaryReader(in);
-                crh.setFilterChains(filterChains);
-                crh.setProject(project);
-                final Reader rdr = crh.getAssembledReader();
-                in = new BufferedReader(rdr);
-            }
+        try (Reader in = filterWith(project, inputEncoding, filterChains,
+                source.getInputStream());
+             BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
+                     getOutputStream(dest, append, project),
+                     charsetFor(outputEncoding)))) {
             final char[] buffer = new char[FileUtils.BUF_SIZE];
             while (true) {
                 final int nRead = in.read(buffer, 0, buffer.length);
@@ -772,10 +709,8 @@
                 }
                 out.write(buffer, 0, nRead);
             }
-        } finally {
-            FileUtils.close(out);
-            FileUtils.close(in);
         }
+
     }
 
     private static void copyUsingFileChannels(final File sourceFile,
@@ -794,30 +729,20 @@
                                   + " for " + destFile);
         }
 
-        FileInputStream in = null;
-        FileOutputStream out = null;
-        FileChannel srcChannel = null;
-        FileChannel destChannel = null;
-
-        try {
-            in = new FileInputStream(sourceFile);
-            out = new FileOutputStream(destFile);
-
-            srcChannel = in.getChannel();
-            destChannel = out.getChannel();
-
+        try (FileChannel srcChannel =
+            FileChannel.open(sourceFile.toPath(), StandardOpenOption.READ);
+                FileChannel destChannel = FileChannel.open(destFile.toPath(),
+                    StandardOpenOption.CREATE,
+                    StandardOpenOption.TRUNCATE_EXISTING,
+                    StandardOpenOption.WRITE)) {
             long position = 0;
             final long count = srcChannel.size();
             while (position < count) {
-                final long chunk = Math.min(MAX_IO_CHUNK_SIZE, count - position);
+                final long chunk =
+                    Math.min(MAX_IO_CHUNK_SIZE, count - position);
                 position +=
                     destChannel.transferFrom(srcChannel, position, chunk);
             }
-        } finally {
-            FileUtils.close(srcChannel);
-            FileUtils.close(destChannel);
-            FileUtils.close(out);
-            FileUtils.close(in);
         }
     }
 
@@ -830,12 +755,8 @@
             log(project, "Skipping (self) copy of " + source +  " to " + dest);
             return;
         }
-
-        InputStream in = null;
-        OutputStream out = null;
-        try {
-            in = source.getInputStream();
-            out = getOutputStream(dest, append, project);
+        try (InputStream in = source.getInputStream();
+             OutputStream out = getOutputStream(dest, append, project)) {
 
             final byte[] buffer = new byte[FileUtils.BUF_SIZE];
             int count = 0;
@@ -843,9 +764,6 @@
                 out.write(buffer, 0, count);
                 count = in.read(buffer, 0, buffer.length);
             } while (count != -1);
-        } finally {
-            FileUtils.close(out);
-            FileUtils.close(in);
         }
     }
 
@@ -872,14 +790,9 @@
             return false;
         }
         final FileProvider fileResource1 = resource1.as(FileProvider.class);
-        if (fileResource1 == null) {
-            return false;
-        }
         final FileProvider fileResource2 = resource2.as(FileProvider.class);
-        if (fileResource2 == null) {
-            return false;
-        }
-        return FileUtils.getFileUtils().areSame(fileResource1.getFile(), fileResource2.getFile());
+        return fileResource1 != null && fileResource2 != null
+                && FileUtils.getFileUtils().areSame(fileResource1.getFile(), fileResource2.getFile());
     }
 
     private static void log(final Project project, final String message) {
diff --git a/src/main/org/apache/tools/ant/util/RetryHandler.java b/src/main/org/apache/tools/ant/util/RetryHandler.java
index dd62bc2..7d9b44b 100644
--- a/src/main/org/apache/tools/ant/util/RetryHandler.java
+++ b/src/main/org/apache/tools/ant/util/RetryHandler.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/Retryable.java b/src/main/org/apache/tools/ant/util/Retryable.java
index 537244a..c48e807 100644
--- a/src/main/org/apache/tools/ant/util/Retryable.java
+++ b/src/main/org/apache/tools/ant/util/Retryable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/ScriptFixBSFPath.java b/src/main/org/apache/tools/ant/util/ScriptFixBSFPath.java
index ca76e56..6e4db9c 100644
--- a/src/main/org/apache/tools/ant/util/ScriptFixBSFPath.java
+++ b/src/main/org/apache/tools/ant/util/ScriptFixBSFPath.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 
 
 /**
@@ -31,7 +32,7 @@
  */
 public class ScriptFixBSFPath {
     private static final String UTIL_OPTIONAL_PACKAGE
-        = "org.apache.tools.ant.util.optional";
+        = MagicNames.ANT_CORE_PACKAGE + ".util.optional";
 
     private static final String BSF_PACKAGE = "org.apache.bsf";
     private static final String BSF_MANAGER = BSF_PACKAGE + ".BSFManager";
@@ -56,9 +57,9 @@
             "xslt",       "org.apache.xpath.objects.XObject"};
 
     /** A map of languages for which the engine in located in bsf */
-    private static final Map BSF_LANGUAGE_MAP = new HashMap();
+    private static final Map<String, String> BSF_LANGUAGE_MAP = new HashMap<>();
     static {
-        for (int i = 0; i < BSF_LANGUAGES.length; i = i + 2) {
+        for (int i = 0; i < BSF_LANGUAGES.length; i += 2) {
             BSF_LANGUAGE_MAP.put(BSF_LANGUAGES[i], BSF_LANGUAGES[i + 1]);
         }
     }
@@ -109,7 +110,7 @@
         boolean needMoveRunner = (bsfSource == null);
 
         // Check for location of language
-        String languageClassName = (String) BSF_LANGUAGE_MAP.get(language);
+        String languageClassName = BSF_LANGUAGE_MAP.get(language);
 
         // Check if need to need to move bsf
         boolean needMoveBsf =
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/main/org/apache/tools/ant/util/ScriptManager.java
similarity index 79%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/main/org/apache/tools/ant/util/ScriptManager.java
index 9d6fcba..fa3fc0f 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/main/org/apache/tools/ant/util/ScriptManager.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,12 @@
  *  limitations under the License.
  *
  */
+package org.apache.tools.ant.util;
+
 /**
+ * Script manager {@code enum}.
+ * @since Ant 1.10.13
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
-}
+public enum ScriptManager {
+    auto, bsf, javax;
+}
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/util/ScriptRunner.java b/src/main/org/apache/tools/ant/util/ScriptRunner.java
index 544db55..cb81a3f 100644
--- a/src/main/org/apache/tools/ant/util/ScriptRunner.java
+++ b/src/main/org/apache/tools/ant/util/ScriptRunner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java b/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
index 42df9a2..dee11a9 100644
--- a/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
+++ b/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,14 +19,13 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
@@ -34,6 +33,8 @@
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.PropertyResource;
+import org.apache.tools.ant.types.resources.StringResource;
 
 /**
  * This is a common abstract base case for script runners.
@@ -51,6 +52,11 @@
     /** Script content */
     private String script = "";
 
+    private String encoding;
+
+    /** Enable script compilation. */
+    private boolean compiled;
+
     /** Project this runner is used in */
     private Project project;
 
@@ -58,7 +64,7 @@
     private ClassLoader scriptLoader;
 
     /** Beans to be provided to the script */
-    private Map beans = new HashMap();
+    private final Map<String, Object> beans = new HashMap<>();
 
     /**
      * Add a list of named objects to the list to be exported to the script
@@ -66,19 +72,17 @@
      * @param dictionary a map of objects to be placed into the script context
      *        indexed by String names.
      */
-    public void addBeans(Map dictionary) {
-        for (Iterator i = dictionary.keySet().iterator(); i.hasNext();) {
-            String key = (String) i.next();
+    public void addBeans(Map<String, ?> dictionary) {
+        dictionary.forEach((k, v) -> {
             try {
-                Object val = dictionary.get(key);
-                addBean(key, val);
+                addBean(k, v);
             } catch (BuildException ex) {
                 // The key is in the dictionary but cannot be retrieved
                 // This is usually due references that refer to tasks
                 // that have not been taskdefed in the current run.
                 // Ignore
             }
-        }
+        });
     }
 
     /**
@@ -88,14 +92,8 @@
      * @param bean the object to be stored in the script context.
      */
     public void addBean(String key, Object bean) {
-        boolean isValid = key.length() > 0
-            && Character.isJavaIdentifierStart(key.charAt(0));
-
-        for (int i = 1; isValid && i < key.length(); i++) {
-            isValid = Character.isJavaIdentifierPart(key.charAt(i));
-        }
-
-        if (isValid) {
+        if (!key.isEmpty() && Character.isJavaIdentifierStart(key.charAt(0))
+                && key.chars().skip(1).allMatch(Character::isJavaIdentifierPart)) {
             beans.put(key, bean);
         }
     }
@@ -104,7 +102,7 @@
      * Get the beans used for the script.
      * @return the map of beans.
      */
-    protected Map getBeans() {
+    protected Map<String, Object> getBeans() {
         return beans;
     }
 
@@ -187,6 +185,33 @@
     }
 
     /**
+     * Whether to use script compilation if available.
+     * @since Ant 1.10.2
+     * @param compiled if true, compile the script if possible.
+     */
+    public final void setCompiled(boolean compiled) {
+        this.compiled = compiled;
+    }
+
+    /**
+     * Get the compiled attribute.
+     * @since Ant 1.10.2
+     * @return the attribute.
+     */
+    public final boolean getCompiled() {
+        return compiled;
+    }
+
+    /**
+     * Set encoding of the script from an external file; optional.
+     * @since Ant 1.10.2
+     * @param encoding  encoding of the external file containing the script source.
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
      * Load the script from an external file; optional.
      * @param file the file containing the script source.
      */
@@ -195,32 +220,33 @@
         if (!file.exists()) {
             throw new BuildException("file " + filename + " not found.");
         }
-        try {
-            readSource(new FileReader(file), filename);
-        } catch (FileNotFoundException e) {
+
+        try (InputStream in = Files.newInputStream(file.toPath())) {
+            final Charset charset = null == encoding ? Charset.defaultCharset()
+                : Charset.forName(encoding);
+
+            readSource(in, filename, charset);
+        } catch (IOException e) {
             //this can only happen if the file got deleted a short moment ago
-            throw new BuildException("file " + filename + " not found.");
+            throw new BuildException("file " + filename + " not found.", e);
         }
     }
 
     /**
      * Read some source in from the given reader
-     * @param reader the input stream to pass into a buffered reader.
+     * @param in the input stream to pass into a buffered reader.
      * @param name the name to use in error messages
+     * @param charset the encoding for the reader, may be null.
      */
-    private void readSource(Reader reader, String name) {
-        BufferedReader in = null;
-        try {
-            in = new BufferedReader(reader);
-            script += FileUtils.safeReadFully(in);
+    private void readSource(InputStream in, String name, Charset charset) {
+        try (Reader reader =
+            new BufferedReader(new InputStreamReader(in, charset))) {
+            script += FileUtils.safeReadFully(reader);
         } catch (IOException ex) {
             throw new BuildException("Failed to read " + name, ex);
-        } finally {
-            FileUtils.close(in);
         }
     }
 
-
     /**
      * Add a resource to the source list.
      * @since Ant 1.7.1
@@ -228,17 +254,24 @@
      * @throws BuildException if the resource cannot be read
      */
     public void loadResource(Resource sourceResource) {
+        if (sourceResource instanceof StringResource) {
+            script += ((StringResource) sourceResource).getValue();
+            return;
+        }
+        if (sourceResource instanceof PropertyResource) {
+            script += ((PropertyResource) sourceResource).getValue();
+            return;
+        }
+
         String name = sourceResource.toLongString();
-        InputStream in = null;
-        try {
-            in = sourceResource.getInputStream();
+        try (InputStream in = sourceResource.getInputStream()) {
+            readSource(in, name, Charset.defaultCharset());
         } catch (IOException e) {
             throw new BuildException("Failed to open " + name, e);
         } catch (UnsupportedOperationException e) {
             throw new BuildException(
-                "Failed to open " + name + " -it is not readable", e);
+                "Failed to open " + name + " - it is not readable", e);
         }
-        readSource(new InputStreamReader(in), name);
     }
 
     /**
@@ -248,9 +281,7 @@
      * @throws BuildException if a resource cannot be read
      */
     public void loadResources(ResourceCollection collection) {
-        for (Resource resource : collection) {
-            loadResource(resource);
-        }
+        collection.forEach(this::loadResource);
     }
 
     /**
@@ -301,8 +332,10 @@
      */
     public void bindToComponent(ProjectComponent component) {
         project = component.getProject();
-        addBeans(project.getProperties());
-        addBeans(project.getUserProperties());
+
+        final Map<String, Object> effectiveProperties = new HashMap<>();
+        project.getPropertyNames().forEach(n -> effectiveProperties.put(n, project.getProperty(n)));
+        addBeans(effectiveProperties);
         addBeans(project.getCopyOfTargets());
         addBeans(project.getCopyOfReferences());
         addBean("project", project);
@@ -326,8 +359,7 @@
      */
     protected void checkLanguage() {
         if (language == null) {
-            throw new BuildException(
-                "script language must be specified");
+            throw new BuildException("script language must be specified");
         }
     }
 
@@ -356,5 +388,4 @@
         Thread.currentThread().setContextClassLoader(
                  origLoader);
     }
-
 }
diff --git a/src/main/org/apache/tools/ant/util/ScriptRunnerCreator.java b/src/main/org/apache/tools/ant/util/ScriptRunnerCreator.java
index bf3c2c9..d9f14f7 100644
--- a/src/main/org/apache/tools/ant/util/ScriptRunnerCreator.java
+++ b/src/main/org/apache/tools/ant/util/ScriptRunnerCreator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,7 +17,16 @@
  */
 package org.apache.tools.ant.util;
 
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 
 /**
@@ -25,23 +34,74 @@
  * create a ScriptRunner based on a classloader and on a language.
  */
 public class ScriptRunnerCreator {
-    private static final String AUTO = "auto";
-    private static final String OATAU = "org.apache.tools.ant.util";
-    private static final String UTIL_OPT = OATAU + ".optional";
+    private static class ScriptRunnerFactory {
+        final String managerClass;
+        final String runnerClass;
+        
+        ScriptRunnerFactory(String managerClass, String runnerClass) {
+            this.managerClass = managerClass;
+            this.runnerClass = runnerClass;
+        }
 
-    private static final String BSF = "bsf";
+        boolean validateManager(Project project, String language, ClassLoader scriptLoader) {
+            try {
+                Class.forName(managerClass, true, scriptLoader);
+                return true;
+            } catch (Exception ex) {
+                return false;
+            }
+        }
+
+        ScriptRunnerBase getRunner(Project project, String language, ClassLoader scriptLoader) {
+            if (!validateManager(project, language, scriptLoader)) {
+                return null;
+            }
+            final ScriptRunnerBase runner;
+            try {
+                runner = Class.forName(runnerClass, true, scriptLoader)
+                    .asSubclass(ScriptRunnerBase.class).getDeclaredConstructor().newInstance();
+
+                runner.setProject(project);
+            } catch (Exception ex) {
+                throw ReflectUtil.toBuildException(ex);
+            }
+            runner.setLanguage(language);
+            runner.setScriptClassLoader(scriptLoader);
+            return runner;
+        }
+    }
+
+    private static final Map<ScriptManager, ScriptRunnerFactory> RUNNER_FACTORIES;
+
+    private static final String UTIL_OPT = MagicNames.ANT_CORE_PACKAGE + ".util.optional";
+
     private static final String BSF_PACK = "org.apache.bsf";
     private static final String BSF_MANAGER = BSF_PACK + ".BSFManager";
     private static final String BSF_RUNNER = UTIL_OPT + ".ScriptRunner";
 
-    private static final String JAVAX = "javax";
     private static final String JAVAX_MANAGER = "javax.script.ScriptEngineManager";
     private static final String JAVAX_RUNNER = UTIL_OPT + ".JavaxScriptRunner";
 
-    private Project     project;
-    private String      manager;
-    private String      language;
-    private ClassLoader scriptLoader = null;
+    static {
+        final Map<ScriptManager, ScriptRunnerFactory> m = new EnumMap<>(ScriptManager.class);
+        
+        m.put(ScriptManager.bsf, new ScriptRunnerFactory(BSF_MANAGER, BSF_RUNNER) {
+            @Override
+            boolean validateManager(Project project, String language, ClassLoader scriptLoader) {
+                if (scriptLoader.getResource(LoaderUtils.classNameToResource(BSF_MANAGER)) == null) {
+                    return false;
+                }
+                new ScriptFixBSFPath().fixClassLoader(scriptLoader, language);
+                return true;
+            }
+        });
+
+        m.put(ScriptManager.javax, new ScriptRunnerFactory(JAVAX_MANAGER, JAVAX_RUNNER));
+
+        RUNNER_FACTORIES = Collections.unmodifiableMap(m);
+    }
+
+    private Project project;
 
     /**
      * Constructor for creator.
@@ -58,17 +118,29 @@
      * @param classLoader  the classloader to use
      * @return the created script runner.
      * @throws BuildException if unable to create the ScriptRunner.
+     * @deprecated Use {@link #createRunner(ScriptManager,String,ClassLoader)} instead
      */
-    public synchronized ScriptRunnerBase createRunner(
-        String manager, String language, ClassLoader classLoader) {
-        this.manager      = manager;
-        this.language     = language;
-        this.scriptLoader = classLoader;
+    @Deprecated
+    public synchronized ScriptRunnerBase createRunner(String manager, String language,
+        ClassLoader classLoader) {
+        return createRunner(ScriptManager.valueOf(manager), language, classLoader);
+    }
+
+    /**
+     * Create a ScriptRunner.
+     * @param manager      the {@link ScriptManager}
+     * @param language     the language.
+     * @param classLoader  the classloader to use
+     * @return the created script runner.
+     * @throws BuildException if unable to create the ScriptRunner.
+     */
+    public synchronized ScriptRunnerBase createRunner(ScriptManager manager, String language,
+        ClassLoader classLoader) {
 
         if (language == null) {
             throw new BuildException("script language must be specified");
         }
-        if (!manager.equals(AUTO) && !manager.equals(JAVAX) && !manager.equals(BSF)) {
+        if (manager == null) {
             throw new BuildException("Unsupported language prefix " + manager);
         }
 
@@ -76,64 +148,17 @@
         // This version does not check if the scriptManager
         // supports the language.
 
-        ScriptRunnerBase ret = null;
-        ret = createRunner(BSF, BSF_MANAGER, BSF_RUNNER);
-        if (ret == null) {
-            ret = createRunner(JAVAX, JAVAX_MANAGER, JAVAX_RUNNER);
-        }
-        if (ret != null) {
-            return ret;
-        }
-        if (JAVAX.equals(manager)) {
-            throw new BuildException(
-                    "Unable to load the script engine manager " + "(" + JAVAX_MANAGER + ")");
-        }
-        if (BSF.equals(manager)) {
-            throw new BuildException(
-                    "Unable to load the BSF script engine manager " + "(" + BSF_MANAGER + ")");
-        }
-        throw new BuildException("Unable to load a script engine manager "
-                + "(" + BSF_MANAGER + " or " + JAVAX_MANAGER + ")");
-    }
-
-    /**
-     * Create a script runner if the scriptManager matches the passed
-     * in manager.
-     * This checks if the script manager exists in the scriptLoader
-     * classloader and if so it creates and returns the script runner.
-     * @param checkManager check if the manager matches this value.
-     * @param managerClass the name of the script manager class.
-     * @param runnerClass   the name of ant's script runner for this manager.
-     * @return the script runner class.
-     * @throws BuildException if there is a problem creating the runner class.
-     */
-    private ScriptRunnerBase createRunner(
-        String checkManager, String managerClass, String runnerClass) {
-        ScriptRunnerBase runner = null;
-        if (!manager.equals(AUTO) && !manager.equals(checkManager)) {
-            return null;
-        }
-        if (managerClass.equals(BSF_MANAGER)) {
-            if (scriptLoader.getResource(LoaderUtils.classNameToResource(managerClass)) == null) {
-                return null;
-            }
-            new ScriptFixBSFPath().fixClassLoader(scriptLoader, language);
+        final Set<ScriptManager> managers;
+        if (manager == ScriptManager.auto) {
+            managers = EnumSet.complementOf(EnumSet.of(ScriptManager.auto));
         } else {
-            try {
-                Class.forName(managerClass, true, scriptLoader);
-            } catch (Exception ex) {
-                return null;
-            }
+            managers = EnumSet.of(manager);
         }
-        try {
-            runner = (ScriptRunnerBase) Class.forName(
-                    runnerClass, true, scriptLoader).newInstance();
-            runner.setProject(project);
-        } catch (Exception ex) {
-            throw ReflectUtil.toBuildException(ex);
-        }
-        runner.setLanguage(language);
-        runner.setScriptClassLoader(scriptLoader);
-        return runner;
+        return managers.stream().map(RUNNER_FACTORIES::get)
+            .map(f -> f.getRunner(project, language, classLoader)).filter(Objects::nonNull)
+            .findFirst()
+            .orElseThrow(() -> new BuildException(
+                managers.stream().map(RUNNER_FACTORIES::get).map(f -> f.managerClass).collect(
+                    Collectors.joining("|", "Unable to load script engine manager (", ")"))));
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java b/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
index e25811d..e97f425 100644
--- a/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
+++ b/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,9 +31,11 @@
 public class ScriptRunnerHelper {
     private ClasspathUtils.Delegate cpDelegate = null;
     private File    srcFile;
-    private String  manager = "auto";
+    private String  encoding;
     private String  language;
     private String  text;
+    private ScriptManager manager = ScriptManager.auto;
+    private boolean compiled = false;
     private boolean setBeans = true;
     private ProjectComponent projectComponent;
     private ClassLoader scriptLoader = null;
@@ -53,6 +55,12 @@
      */
     public ScriptRunnerBase getScriptRunner() {
         ScriptRunnerBase runner = getRunner();
+        runner.setCompiled(compiled);
+
+        if (encoding != null) {
+            // set it first, because runner.setSrc() loads immediately the file
+            runner.setEncoding(encoding);
+        }
         if (srcFile != null) {
             runner.setSrc(srcFile);
         }
@@ -108,6 +116,34 @@
     }
 
     /**
+     * Get the external script file; optional.
+     * @return the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public File getSrc() {
+        return srcFile;
+    }
+
+    /**
+     * Set the encoding of the script from an external file; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
+     * Get the external file encoding.
+     * @return the encoding of the file containing the script source.
+     * @since Ant 1.10.2
+     */
+    public String getEncoding() {
+        return encoding;
+    }
+
+    /**
      * Add script text.
      *
      * @param text a component of the script text to be added.
@@ -121,8 +157,17 @@
      *
      * @param manager the scripting manager - "bsf" or "javax" or "auto"
      */
+    @Deprecated
     public void setManager(String manager) {
-        this.manager = manager;
+        setManager(manager == null ? null : ScriptManager.valueOf(manager));
+    }
+
+    /**
+     * Set the manager.
+     * @param manager
+     */
+    public void setManager(ScriptManager manager) {
+        this.manager = manager == null ? ScriptManager.auto : manager;
     }
 
     /**
@@ -143,6 +188,28 @@
     }
 
     /**
+     * Enable the compilation of the script if possible.
+     * If this is true and the compilation feature is available in
+     * the script engine, the script is compiled before the first
+     * evaluation, and should be cached for future evaluations.
+     * Otherwise, the script is evaluated each time.
+     * The default is false.
+     *
+     * @param compiled the value to set.
+     */
+    public void setCompiled(boolean compiled) {
+        this.compiled = compiled;
+    }
+
+    /**
+     * Get the compilation feature.
+     * @return the compilation feature.
+     */
+    public boolean getCompiled() {
+        return this.compiled;
+    }
+
+    /**
      * Set the setbeans attribute.
      * If this is true, &lt;script&gt; will create variables in the
      * script instance for all
diff --git a/src/main/org/apache/tools/ant/util/SourceFileScanner.java b/src/main/org/apache/tools/ant/util/SourceFileScanner.java
index c79f034..6c0dd89 100644
--- a/src/main/org/apache/tools/ant/util/SourceFileScanner.java
+++ b/src/main/org/apache/tools/ant/util/SourceFileScanner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,7 @@
 package org.apache.tools.ant.util;
 
 import java.io.File;
-import java.util.Vector;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.Resource;
@@ -90,28 +90,21 @@
                              FileNameMapper mapper, long granularity) {
         // record destdir for later use in getResource
         this.destDir = destDir;
-        Vector v = new Vector();
-        for (int i = 0; i < files.length; i++) {
-            final String name = files[i];
-            v.addElement(new FileResource(srcDir, name) {
+
+        Resource[] sourceResources =
+            Stream.of(files).map(f -> new FileResource(srcDir, f) {
+                @Override
                 public String getName() {
-                    return name;
+                    return f;
                 }
-            });
-        }
-        Resource[] sourceresources = new Resource[v.size()];
-        v.copyInto(sourceresources);
+            }).toArray(Resource[]::new);
 
         // build the list of sources which are out of date with
         // respect to the target
-        Resource[] outofdate =
-            ResourceUtils.selectOutOfDateSources(task, sourceresources,
-                                                 mapper, this, granularity);
-        String[] result = new String[outofdate.length];
-        for (int counter = 0; counter < outofdate.length; counter++) {
-            result[counter] = outofdate[counter].getName();
-        }
-        return result;
+        return Stream
+            .of(ResourceUtils.selectOutOfDateSources(task, sourceResources,
+                mapper, this, granularity))
+            .map(Resource::getName).toArray(String[]::new);
     }
 
     /**
@@ -150,12 +143,8 @@
      */
     public File[] restrictAsFiles(String[] files, File srcDir, File destDir,
                                   FileNameMapper mapper, long granularity) {
-        String[] res = restrict(files, srcDir, destDir, mapper, granularity);
-        File[] result = new File[res.length];
-        for (int i = 0; i < res.length; i++) {
-            result[i] = new File(srcDir, res[i]);
-        }
-        return result;
+        return Stream.of(restrict(files, srcDir, destDir, mapper, granularity))
+            .map(name -> new File(srcDir, name)).toArray(File[]::new);
     }
 
     /**
@@ -165,6 +154,7 @@
      *
      * @since Ant 1.5.2
      */
+    @Override
     public Resource getResource(String name) {
         return new FileResource(destDir, name);
     }
diff --git a/src/main/org/apache/tools/ant/util/SplitClassLoader.java b/src/main/org/apache/tools/ant/util/SplitClassLoader.java
index 9857755..e97393d 100644
--- a/src/main/org/apache/tools/ant/util/SplitClassLoader.java
+++ b/src/main/org/apache/tools/ant/util/SplitClassLoader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -45,9 +45,10 @@
 
     // forceLoadClass is not convenient here since it would not
     // properly deal with inner classes of these classes.
-    protected synchronized Class loadClass(String classname, boolean resolve)
+    @Override
+    protected synchronized Class<?> loadClass(String classname, boolean resolve)
         throws ClassNotFoundException {
-        Class theClass = findLoadedClass(classname);
+        Class<?> theClass = findLoadedClass(classname);
         if (theClass != null) {
             return theClass;
         }
@@ -57,9 +58,8 @@
                 resolveClass(theClass);
             }
             return theClass;
-        } else {
-            return super.loadClass(classname, resolve);
         }
+        return super.loadClass(classname, resolve);
     }
 
     private boolean isSplit(String classname) {
diff --git a/src/main/org/apache/tools/ant/util/StreamUtils.java b/src/main/org/apache/tools/ant/util/StreamUtils.java
new file mode 100644
index 0000000..16190dc
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/StreamUtils.java
@@ -0,0 +1,66 @@
+/*
+ *  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
+ *
+ *      https://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.Enumeration;
+import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+public class StreamUtils {
+    /**
+     * Turn Enumeration into a Stream
+     *
+     * @param <T> Enumeration type
+     * @param e Enumeration
+     * @return Stream
+     */
+    public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
+        return StreamSupport.stream(
+                new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED) {
+                    public boolean tryAdvance(Consumer<? super T> action) {
+                        if (e.hasMoreElements()) {
+                            action.accept(e.nextElement());
+                            return true;
+                        }
+                        return false;
+                    }
+                    public void forEachRemaining(Consumer<? super T> action) {
+                        while (e.hasMoreElements()) {
+                            action.accept(e.nextElement());
+                        }
+                    }
+                }, false);
+    }
+
+    /**
+     * Turn Iterator into a Stream
+     *
+     * @param <T> Iterator type
+     * @param i Iterator
+     * @return Stream
+     */
+    public static <T> Stream<T> iteratorAsStream(Iterator<T> i) {
+        return StreamSupport.stream(
+                Spliterators.spliteratorUnknownSize(i, Spliterator.ORDERED),
+                false);
+    }
+}
diff --git a/src/main/org/apache/tools/ant/util/StringTokenizer.java b/src/main/org/apache/tools/ant/util/StringTokenizer.java
index 1e3a8a9..3857915 100644
--- a/src/main/org/apache/tools/ant/util/StringTokenizer.java
+++ b/src/main/org/apache/tools/ant/util/StringTokenizer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -96,18 +96,18 @@
         }
         boolean inToken = true;
         intraString = "";
-        StringBuffer word = new StringBuffer();
-        StringBuffer padding = new StringBuffer();
+        StringBuilder word = new StringBuilder();
+        StringBuilder padding = new StringBuilder();
         while (ch != -1) {
             char c = (char) ch;
             boolean isDelim = isDelim(c);
             if (inToken) {
                 if (isDelim) {
                     if (delimsAreTokens) {
-                        if (word.length() == 0) {
-                            word.append(c);
-                        } else {
+                        if (word.length() > 0) {
                             pushed = ch;
+                        } else {
+                            word.append(c);
                         }
                         break;
                     }
@@ -116,13 +116,11 @@
                 } else {
                     word.append(c);
                 }
+            } else if (isDelim) {
+                padding.append(c);
             } else {
-                if (isDelim) {
-                    padding.append(c);
-                } else {
-                    pushed = ch;
-                    break;
-                }
+                pushed = ch;
+                break;
             }
             ch = in.read();
         }
@@ -136,6 +134,7 @@
     /**
      * @return the intratoken string
      */
+    @Override
     public String getPostToken() {
         return suppressDelims || includeDelims ? "" : intraString;
     }
diff --git a/src/main/org/apache/tools/ant/util/StringUtils.java b/src/main/org/apache/tools/ant/util/StringUtils.java
index a387821..ea3da96 100644
--- a/src/main/org/apache/tools/ant/util/StringUtils.java
+++ b/src/main/org/apache/tools/ant/util/StringUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -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;
 
@@ -41,11 +45,12 @@
     }
 
     /** the line separator for this OS */
-    public static final String LINE_SEP = System.getProperty("line.separator");
+    @Deprecated
+    public static final String LINE_SEP = System.lineSeparator();
 
     /**
      * Splits up a string into a list of lines. It is equivalent
-     * to <tt>split(data, '\n')</tt>.
+     * to <code>split(data, '\n')</code>.
      * @param data the string to split up into lines.
      * @return the list of lines available in the string.
      */
@@ -61,7 +66,7 @@
      * @return the list of elements.
      */
     public static Vector<String> split(String data, int ch) {
-        Vector<String> elems = new Vector<String>();
+        Vector<String> elems = new Vector<>();
         int pos = -1;
         int i = 0;
         while ((pos = data.indexOf(ch, i)) != -1) {
@@ -124,7 +129,7 @@
         // implementation is ok though does allocation/copying
         // StringBuffer.toString().endsWith() does massive memory
         // allocation/copying on JDK 1.5
-        // See http://issues.apache.org/bugzilla/show_bug.cgi?id=37169
+        // See https://issues.apache.org/bugzilla/show_bug.cgi?id=37169
         int endIndex = suffix.length() - 1;
         int bufferIndex = buffer.length() - 1;
         while (endIndex >= 0) {
@@ -149,7 +154,7 @@
      * @since Ant 1.7
      */
     public static String resolveBackSlash(String input) {
-        StringBuffer b = new StringBuffer();
+        StringBuilder b = new StringBuilder();
         boolean backSlashSeen = false;
         for (final char c : input.toCharArray()) {
             if (!backSlashSeen) {
@@ -161,19 +166,19 @@
             } else {
                 switch (c) {
                     case '\\':
-                        b.append((char) '\\');
+                        b.append('\\');
                         break;
                     case 'n':
-                        b.append((char) '\n');
+                        b.append('\n');
                         break;
                     case 'r':
-                        b.append((char) '\r');
+                        b.append('\r');
                         break;
                     case 't':
-                        b.append((char) '\t');
+                        b.append('\t');
                         break;
                     case 'f':
-                        b.append((char) '\f');
+                        b.append('\f');
                         break;
                     case 's':
                         b.append(" \t\n\r\f");
@@ -251,9 +256,8 @@
     public static String removeSuffix(String string, String suffix) {
         if (string.endsWith(suffix)) {
             return string.substring(0, string.length() - suffix.length());
-        } else {
-            return string;
         }
+        return string;
     }
 
     /**
@@ -266,8 +270,55 @@
     public static String removePrefix(String string, String prefix) {
         if (string.startsWith(prefix)) {
             return string.substring(prefix.length());
-        } else {
-            return string;
         }
+        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(String::valueOf)
+            .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);
+    }
+
+    /**
+     * @param inputString String to trim
+     * @return null if the input string is null or empty or contain only empty spaces.
+     * It returns the input string without leading and trailing spaces otherwise.
+     *
+     */
+    public static String trimToNull(String inputString) {
+        if (inputString == null) {
+            return null;
+        }
+        String tmpString = inputString.trim();
+        return tmpString.isEmpty() ? null : tmpString;
+    }
+
 }
diff --git a/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java b/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
index 26d25e6..7a5f7ed 100644
--- a/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
+++ b/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
 import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
@@ -32,15 +31,18 @@
  * a symbolic link based on the absent support for them in Java.
  *
  * @since Ant 1.8.0
+ * @deprecated Starting Ant 1.10.2, this class is now deprecated in favour
+ *              of the Java {@link java.nio.file.Files} APIs introduced in
+ *              Java 7, for dealing with symbolic links
  */
+@Deprecated
 public class SymbolicLinkUtils {
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
     /**
      * Shared instance.
      */
-    private static final SymbolicLinkUtils PRIMARY_INSTANCE =
-        new SymbolicLinkUtils();
+    private static final SymbolicLinkUtils PRIMARY_INSTANCE = new SymbolicLinkUtils();
 
     /**
      * Method to retrieve The SymbolicLinkUtils, which is shared by
@@ -177,11 +179,7 @@
         final File f = new File(parent, name);
         if (!f.exists()) {
             final String localName = f.getName();
-            final String[] c = parent.list(new FilenameFilter() {
-                    public boolean accept(final File d, final String n) {
-                        return localName.equals(n);
-                    }
-                });
+            final String[] c = parent.list((d, n) -> localName.equals(n));
             return c != null && c.length > 0;
         }
         return false;
@@ -296,8 +294,7 @@
                 }
             }
         } else {
-            Execute.runCommand(task,
-                               new String[] {"rm", link.getAbsolutePath()});
+            Execute.runCommand(task, "rm", link.getAbsolutePath());
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/util/TaskLogger.java b/src/main/org/apache/tools/ant/util/TaskLogger.java
index 9ce5c51..a709d47 100644
--- a/src/main/org/apache/tools/ant/util/TaskLogger.java
+++ b/src/main/org/apache/tools/ant/util/TaskLogger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/TeeOutputStream.java b/src/main/org/apache/tools/ant/util/TeeOutputStream.java
index eb8da3f..999d09f 100644
--- a/src/main/org/apache/tools/ant/util/TeeOutputStream.java
+++ b/src/main/org/apache/tools/ant/util/TeeOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,6 +43,7 @@
      * Close both output streams.
      * @throws IOException on error.
      */
+    @Override
     public void close() throws IOException {
         try {
             left.close();
@@ -55,6 +56,7 @@
      * Flush both output streams.
      * @throws IOException on error
      */
+    @Override
     public void flush() throws IOException {
         left.flush();
         right.flush();
@@ -65,6 +67,7 @@
      * @param b an array of bytes.
      * @throws IOException on error.
      */
+    @Override
     public void write(byte[] b) throws IOException {
         left.write(b);
         right.write(b);
@@ -77,6 +80,7 @@
      * @param len   the number of bytes to write.
      * @throws IOException on error.
      */
+    @Override
     public void write(byte[] b, int off, int len) throws IOException {
         left.write(b, off, len);
         right.write(b, off, len);
@@ -87,9 +91,9 @@
      * @param b the byte to write.
      * @throws IOException on error.
      */
+    @Override
     public void write(int b) throws IOException {
         left.write(b);
         right.write(b);
     }
 }
-
diff --git a/src/main/org/apache/tools/ant/util/TimeoutObserver.java b/src/main/org/apache/tools/ant/util/TimeoutObserver.java
index c142d3c..cd28793 100644
--- a/src/main/org/apache/tools/ant/util/TimeoutObserver.java
+++ b/src/main/org/apache/tools/ant/util/TimeoutObserver.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/Tokenizer.java b/src/main/org/apache/tools/ant/util/Tokenizer.java
index 25f8965..7376568 100644
--- a/src/main/org/apache/tools/ant/util/Tokenizer.java
+++ b/src/main/org/apache/tools/ant/util/Tokenizer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/UUEncoder.java b/src/main/org/apache/tools/ant/util/UUEncoder.java
index b0c6737..80274d6 100644
--- a/src/main/org/apache/tools/ant/util/UUEncoder.java
+++ b/src/main/org/apache/tools/ant/util/UUEncoder.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,7 @@
 import java.io.PrintStream;
 
 /**
- * UUEncoding of an input stream placed into an outputstream.
+ * UUEncoding of an input stream placed into an OutputStream.
  * This class is meant to be a drop in replacement for
  * sun.misc.UUEncoder, which was previously used by Ant.
  * The uuencode algorithm code has been copied from the
@@ -87,11 +87,11 @@
         writer.flush();
     }
 
-    private void encodeBegin() throws IOException {
+    private void encodeBegin() {
         encodeString("begin " + DEFAULT_MODE + " " + name + "\n");
     }
 
-    private void encodeEnd() throws IOException {
+    private void encodeEnd() {
         encodeString(" \nend\n");
     }
 
diff --git a/src/main/org/apache/tools/ant/util/UnPackageNameMapper.java b/src/main/org/apache/tools/ant/util/UnPackageNameMapper.java
index 1777279..5d04f9d 100644
--- a/src/main/org/apache/tools/ant/util/UnPackageNameMapper.java
+++ b/src/main/org/apache/tools/ant/util/UnPackageNameMapper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,6 +39,7 @@
      *@param  name  Source filename
      *@return       Replaced variable part
      */
+    @Override
     protected String extractVariablePart(String name) {
         String var = name.substring(prefixLength,
                 name.length() - postfixLength);
diff --git a/src/main/org/apache/tools/ant/util/UnicodeUtil.java b/src/main/org/apache/tools/ant/util/UnicodeUtil.java
index 86199d4..f055491 100644
--- a/src/main/org/apache/tools/ant/util/UnicodeUtil.java
+++ b/src/main/org/apache/tools/ant/util/UnicodeUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/VectorSet.java b/src/main/org/apache/tools/ant/util/VectorSet.java
index db13129..e68a9f6 100644
--- a/src/main/org/apache/tools/ant/util/VectorSet.java
+++ b/src/main/org/apache/tools/ant/util/VectorSet.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,11 +40,15 @@
 public final class VectorSet<E> extends Vector<E> {
     private static final long serialVersionUID = 1L;
 
-    private final HashSet<E> set = new HashSet<E>();
+    private final HashSet<E> set = new HashSet<>();
 
-    public VectorSet() { super(); }
+    public VectorSet() {
+        super();
+    }
 
-    public VectorSet(int initialCapacity) { super(initialCapacity); }
+    public VectorSet(int initialCapacity) {
+        super(initialCapacity);
+    }
 
     public VectorSet(int initialCapacity, int capacityIncrement) {
         super(initialCapacity, capacityIncrement);
@@ -52,12 +56,11 @@
 
     public VectorSet(Collection<? extends E> c) {
         if (c != null) {
-            for (E e : c) {
-                add(e);
-            }
+            this.addAll(c);
         }
     }
 
+    @Override
     public synchronized boolean add(E o) {
         if (!set.contains(o)) {
             doAdd(size(), o);
@@ -70,6 +73,7 @@
      * This implementation may not add the element at the given index
      * if it is already contained in the collection.
      */
+    @Override
     public void add(int index, E o) {
         doAdd(index, o);
     }
@@ -89,10 +93,12 @@
         }
     }
 
+    @Override
     public synchronized void addElement(E o) {
         doAdd(size(), o);
     }
 
+    @Override
     public synchronized boolean addAll(Collection<? extends E> c) {
         boolean changed = false;
         for (E e : c) {
@@ -105,8 +111,9 @@
      * This implementation may not add all elements at the given index
      * if any of them are already contained in the collection.
      */
+    @Override
     public synchronized boolean addAll(int index, Collection<? extends E> c) {
-        LinkedList toAdd = new LinkedList();
+        LinkedList<E> toAdd = new LinkedList<>();
         for (E e : c) {
             if (set.add(e)) {
                 toAdd.add(e);
@@ -128,11 +135,13 @@
         return true;
     }
 
+    @Override
     public synchronized void clear() {
         super.clear();
         set.clear();
     }
 
+    @Override
     public Object clone() {
         @SuppressWarnings("unchecked")
         final VectorSet<E> vs = (VectorSet<E>) super.clone();
@@ -140,24 +149,29 @@
         return vs;
     }
 
+    @Override
     public synchronized boolean contains(Object o) {
         return set.contains(o);
     }
 
+    @Override
     public synchronized boolean containsAll(Collection<?> c) {
         return set.containsAll(c);
     }
 
+    @Override
     public void insertElementAt(E o, int index) {
         doAdd(index, o);
     }
 
+    @Override
     public synchronized E remove(int index) {
         E o = get(index);
         remove(o);
         return o;
     }
 
+    @Override
     public boolean remove(Object o) {
         return doRemove(o);
     }
@@ -177,6 +191,7 @@
         return false;
     }
 
+    @Override
     public synchronized boolean removeAll(Collection<?> c) {
         boolean changed = false;
         for (Object o : c) {
@@ -185,30 +200,35 @@
         return changed;
     }
 
+    @Override
     public synchronized void removeAllElements() {
         set.clear();
         super.removeAllElements();
     }
 
+    @Override
     public boolean removeElement(Object o) {
         return doRemove(o);
     }
 
+    @Override
     public synchronized void removeElementAt(int index) {
         remove(get(index));
     }
 
+    @Override
     public synchronized void removeRange(final int fromIndex, int toIndex) {
         while (toIndex > fromIndex) {
             remove(--toIndex);
         }
     }
 
+    @Override
     public synchronized boolean retainAll(Collection<?> c) {
         if (!(c instanceof Set)) {
-            c = new HashSet<Object>(c);
+            c = new HashSet<>(c);
         }
-        LinkedList<E> l = new LinkedList<E>();
+        LinkedList<E> l = new LinkedList<>();
         for (E o : this) {
             if (!c.contains(o)) {
                 l.addLast(o);
@@ -221,6 +241,7 @@
         return false;
     }
 
+    @Override
     public synchronized E set(int index, E o) {
         E orig = get(index);
         if (set.add(o)) {
@@ -235,6 +256,7 @@
         return orig;
     }
 
+    @Override
     public void setElementAt(E o, int index) {
         set(index, o);
     }
diff --git a/src/main/org/apache/tools/ant/util/Watchdog.java b/src/main/org/apache/tools/ant/util/Watchdog.java
index 318b526..6244f25 100644
--- a/src/main/org/apache/tools/ant/util/Watchdog.java
+++ b/src/main/org/apache/tools/ant/util/Watchdog.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,9 @@
 
 package org.apache.tools.ant.util;
 
-import java.util.Enumeration;
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Generalization of <code>ExecuteWatchdog</code>
@@ -31,19 +32,22 @@
  */
 public class Watchdog implements Runnable {
 
-    private Vector observers = new Vector(1);
-    private long timeout = -1;
-    /**
-     * marked as volatile to stop the compiler caching values or (in java1.5+,
-     * reordering access)
-     */
-    private volatile boolean stopped = false;
     /**
      * Error string.
      * {@value}
      */
     public static final String ERROR_INVALID_TIMEOUT = "timeout less than 1.";
 
+    private List<TimeoutObserver> observers =
+        Collections.synchronizedList(new ArrayList<>(1));
+    private long timeout = -1;
+
+    /**
+     * marked as volatile to stop the compiler caching values or (in java1.5+,
+     * reordering access)
+     */
+    private volatile boolean stopped = false;
+
     /**
      * Constructor for Watchdog.
      * @param timeout the timeout to use in milliseconds (must be &gt;= 1).
@@ -60,8 +64,7 @@
      * @param to the timeout observer to add.
      */
     public void addTimeoutObserver(TimeoutObserver to) {
-        //no need to synchronize, as Vector is always synchronized
-        observers.addElement(to);
+        observers.add(to);
     }
 
     /**
@@ -69,8 +72,7 @@
      * @param to the timeout observer to remove.
      */
     public void removeTimeoutObserver(TimeoutObserver to) {
-        //no need to synchronize, as Vector is always synchronized
-        observers.removeElement(to);
+        observers.remove(to);
     }
 
     /**
@@ -78,10 +80,7 @@
      * This happens in the watchdog thread.
      */
     protected final void fireTimeoutOccured() {
-        Enumeration e = observers.elements();
-        while (e.hasMoreElements()) {
-            ((TimeoutObserver) e.nextElement()).timeoutOccured(this);
-        }
+        observers.forEach(o -> o.timeoutOccured(this));
     }
 
     /**
@@ -108,6 +107,7 @@
      * if the stop flag has not been set when the wait has returned or
      * has been interrupted, the watch dog listeners are informed.
      */
+    @Override
     public synchronized void run() {
         long now = System.currentTimeMillis();
         final long until = now + timeout;
diff --git a/src/main/org/apache/tools/ant/util/WeakishReference.java b/src/main/org/apache/tools/ant/util/WeakishReference.java
index 816ee4e..f395f1d 100644
--- a/src/main/org/apache/tools/ant/util/WeakishReference.java
+++ b/src/main/org/apache/tools/ant/util/WeakishReference.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,6 +34,7 @@
  * @deprecated deprecated 1.7; will be removed in Ant1.8
  *             Just use {@link java.lang.ref.WeakReference} directly.
  */
+@Deprecated
 public class WeakishReference  {
 
 
@@ -47,7 +48,7 @@
      * @see java.lang.ref.WeakReference
      */
     WeakishReference(Object reference) {
-        this.weakref = new WeakReference<Object>(reference);
+        this.weakref = new WeakReference<>(reference);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/util/WorkerAnt.java b/src/main/org/apache/tools/ant/util/WorkerAnt.java
index b22be50..5c3894b 100644
--- a/src/main/org/apache/tools/ant/util/WorkerAnt.java
+++ b/src/main/org/apache/tools/ant/util/WorkerAnt.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/XMLFragment.java b/src/main/org/apache/tools/ant/util/XMLFragment.java
index 36a6158..b692028 100644
--- a/src/main/org/apache/tools/ant/util/XMLFragment.java
+++ b/src/main/org/apache/tools/ant/util/XMLFragment.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -74,9 +74,10 @@
      * @param qName the qualified name of the nested element
      * @return an object that the element is applied to
      */
+    @Override
     public Object createDynamicElement(String uri, String name, String qName) {
-        Element e = null;
-        if (uri.equals("")) {
+        Element e;
+        if (uri.isEmpty()) {
             e = doc.createElement(name);
         } else {
             e = doc.createElementNS(uri, qName);
@@ -93,7 +94,7 @@
     private void addText(Node n, String s) {
         s = getProject().replaceProperties(s);
         //only text nodes that are non null after property expansion are added
-        if (s != null && !s.trim().equals("")) {
+        if (s != null && !s.trim().isEmpty()) {
             Text t = doc.createTextNode(s.trim());
             n.appendChild(t);
         }
@@ -124,9 +125,10 @@
          * @param qName the qualified name of the attribute
          * @param value the value of the attribute
          */
+        @Override
         public void setDynamicAttribute(
             String uri, String name, String qName, String value) {
-            if (uri.equals("")) {
+            if (uri.isEmpty()) {
                 e.setAttribute(name, value);
             } else {
                 e.setAttributeNS(uri, qName, value);
@@ -140,9 +142,10 @@
          * @param qName the qualified name of the nested element
          * @return an object that the element is applied to
          */
+        @Override
         public Object createDynamicElement(String uri, String name, String qName) {
             Element e2 = null;
-            if (uri.equals("")) {
+            if (uri.isEmpty()) {
                 e2 = doc.createElement(name);
             } else {
                 e2 = doc.createElementNS(uri, qName);
diff --git a/src/main/org/apache/tools/ant/util/XmlConstants.java b/src/main/org/apache/tools/ant/util/XmlConstants.java
index d8eaa02..aa0d5b3 100644
--- a/src/main/org/apache/tools/ant/util/XmlConstants.java
+++ b/src/main/org/apache/tools/ant/util/XmlConstants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,8 +19,8 @@
 
 /**
  * XML Parser constants, all kept in one place for ease of reuse
- * @see <a href="http://xml.apache.org/xerces-j/features.html">Xerces features</a>
- * @see <a href="http://xml.apache.org/xerces-j/properties.html">Xerces properties</a>
+ * @see <a href="https://xml.apache.org/xerces-j/features.html">Xerces features</a>
+ * @see <a href="https://xml.apache.org/xerces-j/properties.html">Xerces properties</a>
  * @see <a href=
  * "http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description"
  * >SAX.</a>
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 a6e81f4..448e8b9 100644
--- a/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java
+++ b/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -42,7 +42,7 @@
     private Path classPath = new Path(null);
 
     /** The list of root classes */
-    private final Vector<String> rootClasses = new VectorSet<String>();
+    private final Vector<String> rootClasses = new VectorSet<>();
 
     /** true if dependencies have been determined */
     private boolean determined = false;
@@ -68,6 +68,7 @@
      * @param closure true if dependencies should be traversed to determine
      *      indirect dependencies.
      */
+    @Override
     public void setClosure(boolean closure) {
         this.closure = closure;
     }
@@ -79,10 +80,11 @@
      *
      * @return an enumeration of File instances.
      */
+    @Override
     public Enumeration<File> getFileDependencies() {
         if (!supportsFileDependencies()) {
-            throw new BuildException("File dependencies are not supported "
-                + "by this analyzer");
+            throw new BuildException(
+                "File dependencies are not supported by this analyzer");
         }
         if (!determined) {
             determineDependencies(fileDependencies, classDependencies);
@@ -97,6 +99,7 @@
      * @return an enumeration of Strings, each being the name of a Java
      *      class in dot notation.
      */
+    @Override
     public Enumeration<String> getClassDependencies() {
         if (!determined) {
             determineDependencies(fileDependencies, classDependencies);
@@ -112,6 +115,7 @@
      *         class or null if the class could not be found.
      * @exception IOException if the files in the classpath cannot be read.
      */
+    @Override
     public File getClassContainer(String classname) throws IOException {
         String classLocation = classname.replace('.', '/') + ".class";
         // we look through the classpath elements. If the element is a dir
@@ -127,6 +131,7 @@
      *         source or null if the source for the class could not be found.
      * @exception IOException if the files in the sourcepath cannot be read.
      */
+    @Override
     public File getSourceContainer(String classname) throws IOException {
         String sourceLocation = classname.replace('.', '/') + ".java";
 
@@ -144,6 +149,7 @@
      * @param sourcePath The Path instance specifying the source path
      *      elements.
      */
+    @Override
     public void addSourcePath(Path sourcePath) {
         if (sourcePath == null) {
             return;
@@ -160,6 +166,7 @@
      *
      * @param classPath the Path instance specifying the classpath elements
      */
+    @Override
     public void addClassPath(Path classPath) {
         if (classPath == null) {
             return;
@@ -176,6 +183,7 @@
      *
      * @param className the name of the class in Java dot notation.
      */
+    @Override
     public void addRootClass(String className) {
         if (className == null) {
             return;
@@ -192,6 +200,7 @@
      * @param name the name of the aspect being configured
      * @param info the configuration info.
      */
+    @Override
     public void config(String name, Object info) {
         // do nothing by default
     }
@@ -200,11 +209,12 @@
      * Reset the dependency list. This will reset the determined
      * dependencies and the also list of root classes.
      */
+    @Override
     public void reset() {
         rootClasses.removeAllElements();
         determined = false;
-        fileDependencies = new Vector<File>();
-        classDependencies = new Vector<String>();
+        fileDependencies = new Vector<>();
+        classDependencies = new Vector<>();
     }
 
     /**
@@ -268,16 +278,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/main/org/apache/tools/ant/util/depend/DependencyAnalyzer.java b/src/main/org/apache/tools/ant/util/depend/DependencyAnalyzer.java
index 1415e2e..d82a17b 100644
--- a/src/main/org/apache/tools/ant/util/depend/DependencyAnalyzer.java
+++ b/src/main/org/apache/tools/ant/util/depend/DependencyAnalyzer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/depend/bcel/AncestorAnalyzer.java b/src/main/org/apache/tools/ant/util/depend/bcel/AncestorAnalyzer.java
index 613bc77..932203d 100644
--- a/src/main/org/apache/tools/ant/util/depend/bcel/AncestorAnalyzer.java
+++ b/src/main/org/apache/tools/ant/util/depend/bcel/AncestorAnalyzer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -16,11 +16,14 @@
  *
  */
 package org.apache.tools.ant.util.depend.bcel;
+
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.Vector;
+
 import org.apache.bcel.classfile.ClassParser;
 import org.apache.bcel.classfile.JavaClass;
 import org.apache.tools.ant.BuildException;
@@ -61,33 +64,29 @@
      * @param classes a vector to be populated with the names of the
      *      dependency classes.
      */
+    @Override
     protected void determineDependencies(Vector<File> files, Vector<String> classes) {
         // we get the root classes and build up a set of
         // classes upon which they depend
-        Hashtable<String, String> dependencies = new Hashtable<String, String>();
-        Hashtable<File, File> containers = new Hashtable<File, File>();
-        Hashtable<String, String> toAnalyze = new Hashtable<String, String>();
-        Hashtable<String, String> nextAnalyze = new Hashtable<String, String>();
-
-        for (Enumeration<String> e = getRootClasses(); e.hasMoreElements();) {
-            String classname = e.nextElement();
-            toAnalyze.put(classname, classname);
-        }
+        Set<String> dependencies = new HashSet<>();
+        Set<File> containers = new HashSet<>();
+        Set<String> toAnalyze = new HashSet<>(Collections.list(getRootClasses()));
+        Set<String> nextAnalyze = new HashSet<>();
 
         int count = 0;
         int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
-        while (toAnalyze.size() != 0 && count++ < maxCount) {
+        while (!toAnalyze.isEmpty() && count++ < maxCount) {
             nextAnalyze.clear();
-            for (String classname : toAnalyze.keySet()) {
-                dependencies.put(classname, classname);
+            for (String classname : toAnalyze) {
+                dependencies.add(classname);
                 try {
                     File container = getClassContainer(classname);
                     if (container == null) {
                         continue;
                     }
-                    containers.put(container, container);
+                    containers.add(container);
 
-                    ClassParser parser = null;
+                    ClassParser parser;
                     if (container.getName().endsWith(".class")) {
                         parser = new ClassParser(container.getPath());
                     } else {
@@ -96,18 +95,16 @@
                     }
 
                     JavaClass javaClass = parser.parse();
-                    String[] interfaces = javaClass.getInterfaceNames();
-                    for (int i = 0; i < interfaces.length; ++i) {
-                        String interfaceName = interfaces[i];
-                        if (!dependencies.containsKey(interfaceName)) {
-                            nextAnalyze.put(interfaceName, interfaceName);
+                    for (String interfaceName : javaClass.getInterfaceNames()) {
+                        if (!dependencies.contains(interfaceName)) {
+                            nextAnalyze.add(interfaceName);
                         }
                     }
 
                     if (javaClass.isClass()) {
                         String superClass = javaClass.getSuperclassName();
-                        if (!dependencies.containsKey(superClass)) {
-                            nextAnalyze.put(superClass, superClass);
+                        if (!dependencies.contains(superClass)) {
+                            nextAnalyze.add(superClass);
                         }
                     }
                 } catch (IOException ioe) {
@@ -115,20 +112,15 @@
                 }
             }
 
-            Hashtable<String, String> temp = toAnalyze;
-            toAnalyze = nextAnalyze;
-            nextAnalyze = temp;
+            toAnalyze.clear();
+            toAnalyze.addAll(nextAnalyze);
         }
 
-        files.removeAllElements();
-        for (File f : containers.keySet()) {
-            files.add(f);
-        }
+        files.clear();
+        files.addAll(containers);
 
-        classes.removeAllElements();
-        for (String dependency : dependencies.keySet()) {
-            classes.add(dependency);
-        }
+        classes.clear();
+        classes.addAll(dependencies);
     }
 
     /**
@@ -136,6 +128,7 @@
      *
      * @return true if the analyzer provides dependency file information.
      */
+    @Override
     protected boolean supportsFileDependencies() {
         return true;
     }
diff --git a/src/main/org/apache/tools/ant/util/depend/bcel/DependencyVisitor.java b/src/main/org/apache/tools/ant/util/depend/bcel/DependencyVisitor.java
index d31d453..db1069b 100644
--- a/src/main/org/apache/tools/ant/util/depend/bcel/DependencyVisitor.java
+++ b/src/main/org/apache/tools/ant/util/depend/bcel/DependencyVisitor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,10 @@
  */
 package org.apache.tools.ant.util.depend.bcel;
 
+import java.util.Collections;
 import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.StringTokenizer;
 
 import org.apache.bcel.classfile.ConstantClass;
@@ -35,7 +37,7 @@
  */
 public class DependencyVisitor extends EmptyVisitor {
     /** The collected dependencies */
-    private final Hashtable<String, String> dependencies = new Hashtable<String, String>();
+    private final Set<String> dependencies = new HashSet<>();
     /**
      * The current class's constant pool - used to determine class names
      * from class references.
@@ -49,7 +51,7 @@
      *      visited classes depend.
      */
     public Enumeration<String> getDependencies() {
-        return dependencies.keys();
+        return Collections.enumeration(dependencies);
     }
 
     /** Clear the current set of collected dependencies. */
@@ -62,6 +64,7 @@
      *
      * @param constantPool the constant pool of the class being visited.
      */
+    @Override
     public void visitConstantPool(final ConstantPool constantPool) {
         this.constantPool = constantPool;
     }
@@ -71,6 +74,7 @@
      *
      * @param constantClass the constantClass entry for the class reference
      */
+    @Override
     public void visitConstantClass(final ConstantClass constantClass) {
         final String classname
              = constantClass.getConstantValue(constantPool).toString();
@@ -84,18 +88,19 @@
      *
      * @param obj the name and type reference being visited.
      */
+    @Override
     public void visitConstantNameAndType(final ConstantNameAndType obj) {
         final String name = obj.getName(constantPool);
-        if (obj.getSignature(constantPool).equals("Ljava/lang/Class;")
+        if ("Ljava/lang/Class;".equals(obj.getSignature(constantPool))
                 && name.startsWith("class$")) {
             String classname
                 = name.substring("class$".length()).replace('$', '.');
             // does the class have a package structure
-            final int index = classname.lastIndexOf(".");
+            final int index = classname.lastIndexOf('.');
             if (index > 0) {
                 char start;
                 // check if the package structure is more than 1 level deep
-                final int index2 = classname.lastIndexOf(".", index - 1);
+                final int index2 = classname.lastIndexOf('.', index - 1);
                 if (index2 != -1) {
                     // class name has more than 1 package level 'com.company.Class'
                     start = classname.charAt(index2 + 1);
@@ -105,21 +110,16 @@
                 }
                 // Check to see if it's an inner class 'com.company.Class$Inner'
                 // CheckStyle:MagicNumber OFF
-                if ((start > 0x40) && (start < 0x5B)) {
+                if (start > 0x40 && start < 0x5B) {
                     // first letter of the previous segment of the class name 'Class'
                     // is upper case ascii. so according to the spec it's an inner class
                     classname = classname.substring(0, index) + "$"
                         + classname.substring(index + 1);
-                    addClass(classname);
-                } else {
-                    // Add the class in dotted notation 'com.company.Class'
-                    addClass(classname);
                 }
                 // CheckStyle:MagicNumber ON
-            } else {
-                // Add a class with no package 'Class'
-                addClass(classname);
             }
+            // Add the class, with or without the package name
+            addClass(classname);
         }
     }
 
@@ -128,6 +128,7 @@
      *
      * @param field the field being visited
      */
+    @Override
     public void visitField(final Field field) {
         addClasses(field.getSignature());
     }
@@ -137,6 +138,7 @@
      *
      * @param javaClass the class being visited.
      */
+    @Override
     public void visitJavaClass(final JavaClass javaClass) {
         addClass(javaClass.getClassName());
     }
@@ -146,9 +148,10 @@
      *
      * @param method the method being visited.
      */
+    @Override
     public void visitMethod(final Method method) {
         final String signature = method.getSignature();
-        final int pos = signature.indexOf(")");
+        final int pos = signature.indexOf(')');
         addClasses(signature.substring(1, pos));
         addClasses(signature.substring(pos + 1));
     }
@@ -159,7 +162,7 @@
      * @param classname the class to be added to the list of dependencies.
      */
     void addClass(final String classname) {
-        dependencies.put(classname, classname);
+        dependencies.add(classname);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/util/depend/bcel/FullAnalyzer.java b/src/main/org/apache/tools/ant/util/depend/bcel/FullAnalyzer.java
index 3bd6c75..08c360f 100644
--- a/src/main/org/apache/tools/ant/util/depend/bcel/FullAnalyzer.java
+++ b/src/main/org/apache/tools/ant/util/depend/bcel/FullAnalyzer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -16,15 +16,19 @@
  *
  */
 package org.apache.tools.ant.util.depend.bcel;
+
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.Vector;
+
 import org.apache.bcel.classfile.ClassParser;
 import org.apache.bcel.classfile.DescendingVisitor;
 import org.apache.bcel.classfile.JavaClass;
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.StreamUtils;
 import org.apache.tools.ant.util.depend.AbstractAnalyzer;
 
 /**
@@ -60,31 +64,28 @@
      * @param classes a vector to be populated with the names of the
      *      dependency classes.
      */
+    @Override
     protected void determineDependencies(Vector<File> files, Vector<String> classes) {
         // we get the root classes and build up a set of
         // classes upon which they depend
-        Hashtable<String, String> dependencies = new Hashtable<String, String>();
-        Hashtable<File, File> containers = new Hashtable<File, File>();
-        Hashtable<String, String> toAnalyze = new Hashtable<String, String>();
-        for (Enumeration<String> e = getRootClasses(); e.hasMoreElements();) {
-            String classname = e.nextElement();
-            toAnalyze.put(classname, classname);
-        }
+        Set<String> dependencies = new HashSet<>();
+        Set<File> containers = new HashSet<>();
+        Set<String> toAnalyze = new HashSet<>(Collections.list(getRootClasses()));
 
         int count = 0;
         int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
-        while (toAnalyze.size() != 0 && count++ < maxCount) {
+        while (!toAnalyze.isEmpty() && count++ < maxCount) {
             DependencyVisitor dependencyVisitor = new DependencyVisitor();
-            for (String classname : toAnalyze.keySet()) {
-                dependencies.put(classname, classname);
+            for (String classname : toAnalyze) {
+                dependencies.add(classname);
                 try {
                     File container = getClassContainer(classname);
                     if (container == null) {
                         continue;
                     }
-                    containers.put(container, container);
+                    containers.add(container);
 
-                    ClassParser parser = null;
+                    ClassParser parser;
                     if (container.getName().endsWith(".class")) {
                         parser = new ClassParser(container.getPath());
                     } else {
@@ -102,26 +103,17 @@
             }
 
             toAnalyze.clear();
-
             // now recover all the dependencies collected and add to the list.
-            Enumeration<String> depsEnum = dependencyVisitor.getDependencies();
-            while (depsEnum.hasMoreElements()) {
-                String className = depsEnum.nextElement();
-                if (!dependencies.containsKey(className)) {
-                    toAnalyze.put(className, className);
-                }
-            }
+            StreamUtils.enumerationAsStream(dependencyVisitor.getDependencies())
+                    .filter(className -> !dependencies.contains(className))
+                    .forEach(toAnalyze::add);
         }
 
-        files.removeAllElements();
-        for (File f : containers.keySet()) {
-            files.add(f);
-        }
+        files.clear();
+        files.addAll(containers);
 
-        classes.removeAllElements();
-        for (String dependency : dependencies.keySet()) {
-            classes.add(dependency);
-        }
+        classes.clear();
+        classes.addAll(dependencies);
     }
 
     /**
@@ -129,6 +121,7 @@
      *
      * @return true if the analyzer provides dependency file information.
      */
+    @Override
     protected boolean supportsFileDependencies() {
         return true;
     }
diff --git a/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java b/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java
index 4fb4341..1a22726 100644
--- a/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java
+++ b/src/main/org/apache/tools/ant/util/facade/FacadeTaskHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,6 +20,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.Path;
@@ -37,7 +39,7 @@
     /**
      * Command line arguments.
      */
-    private List<ImplementationSpecificArgument> args = new ArrayList<ImplementationSpecificArgument>();
+    private List<ImplementationSpecificArgument> args = new ArrayList<>();
 
     /**
      * The explicitly chosen implementation.
@@ -126,17 +128,10 @@
      * @return an array of command line arguments.
      */
     public String[] getArgs() {
-        List<String> tmp = new ArrayList<String>(args.size());
-        for (ImplementationSpecificArgument arg : args) {
-            String[] curr = arg.getParts(getImplementation());
-            if (curr != null) {
-                for (int i = 0; i < curr.length; i++) {
-                    tmp.add(curr[i]);
-                }
-            }
-        }
-        String[] res = new String[tmp.size()];
-        return (String[]) tmp.toArray(res);
+        String implementation = getImplementation();
+        return args.stream().map(arg -> arg.getParts(implementation))
+            .filter(Objects::nonNull).flatMap(Stream::of)
+            .toArray(String[]::new);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/util/facade/ImplementationSpecificArgument.java b/src/main/org/apache/tools/ant/util/facade/ImplementationSpecificArgument.java
index ba7f14a..8a7d039 100644
--- a/src/main/org/apache/tools/ant/util/facade/ImplementationSpecificArgument.java
+++ b/src/main/org/apache/tools/ant/util/facade/ImplementationSpecificArgument.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,11 +30,6 @@
 public class ImplementationSpecificArgument extends Commandline.Argument {
     private String impl;
 
-    /** Constructor for ImplementationSpecificArgument. */
-    public ImplementationSpecificArgument() {
-        super();
-    }
-
     /**
      * Set the implementation this argument is for.
      * @param impl the implementation this command line argument is for.
@@ -54,8 +49,7 @@
     public final String[] getParts(String chosenImpl) {
         if (impl == null || impl.equals(chosenImpl)) {
             return super.getParts();
-        } else {
-            return new String[0];
         }
+        return new String[0];
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/java15/ProxyDiagnostics.java b/src/main/org/apache/tools/ant/util/java15/ProxyDiagnostics.java
index e7412d6..8ff0f21 100644
--- a/src/main/org/apache/tools/ant/util/java15/ProxyDiagnostics.java
+++ b/src/main/org/apache/tools/ant/util/java15/ProxyDiagnostics.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,8 +25,6 @@
 import java.net.SocketAddress;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.Iterator;
-import java.util.List;
 
 import org.apache.tools.ant.BuildException;
 
@@ -40,12 +38,10 @@
  */
 public class ProxyDiagnostics {
 
-    private String destination;
-
     private URI destURI;
 
     /** {@value} */
-    public static final String DEFAULT_DESTINATION = "http://ant.apache.org/";
+    public static final String DEFAULT_DESTINATION = "https://ant.apache.org/";
 
     /**
      * create a diagnostics binding for a specific URI
@@ -53,7 +49,6 @@
      * @throws BuildException if the URI is malformed.
      */
     public ProxyDiagnostics(String destination) {
-        this.destination = destination;
         try {
             this.destURI = new URI(destination);
         } catch (URISyntaxException e) {
@@ -73,36 +68,34 @@
      * Get the diagnostics for proxy information.
      * @return the information.
      */
+    @Override
     public String toString() {
         ProxySelector selector = ProxySelector.getDefault();
-        List list = selector.select(destURI);
-        StringBuffer result = new StringBuffer();
-        Iterator proxies = list.listIterator();
-        while (proxies.hasNext()) {
-            Proxy proxy = (Proxy) proxies.next();
+        StringBuilder result = new StringBuilder();
+        for (Proxy proxy : selector.select(destURI)) {
             SocketAddress address = proxy.address();
             if (address == null) {
                 result.append("Direct connection\n");
-            } else {
-                result.append(proxy.toString());
-                if (address instanceof InetSocketAddress) {
-                    InetSocketAddress ina = (InetSocketAddress) address;
-                    result.append(' ');
-                    result.append(ina.getHostName());
-                    result.append(':');
-                    result.append(ina.getPort());
-                    if (ina.isUnresolved()) {
-                        result.append(" [unresolved]");
-                    } else {
-                        InetAddress addr = ina.getAddress();
-                        result.append(" [");
-                        result.append(addr.getHostAddress());
-                        result.append(']');
-                    }
-                }
-                result.append('\n');
+                continue;
             }
+            result.append(proxy);
+            if (address instanceof InetSocketAddress) {
+                InetSocketAddress ina = (InetSocketAddress) address;
+                result.append(' ');
+                result.append(ina.getHostName());
+                result.append(':');
+                result.append(ina.getPort());
+                if (ina.isUnresolved()) {
+                    result.append(" [unresolved]");
+                } else {
+                    InetAddress addr = ina.getAddress();
+                    result.append(" [");
+                    result.append(addr.getHostAddress());
+                    result.append(']');
+                }
+            }
+            result.append('\n');
         }
         return result.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java b/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
index 7a5cfa4..591744e 100644
--- a/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
+++ b/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,10 +18,25 @@
 
 package org.apache.tools.ant.util.optional;
 
-import java.util.Iterator;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleBindings;
 
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.ReflectWrapper;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.apache.tools.ant.util.ScriptRunnerBase;
 
 /**
@@ -29,19 +44,22 @@
  * @since Ant 1.7.0
  */
 public class JavaxScriptRunner extends ScriptRunnerBase {
-    private ReflectWrapper engine;
+    private ScriptEngine keptEngine;
+    private CompiledScript compiledScript;
 
     /**
      * Get the name of the manager prefix.
      * @return "javax"
      */
+    @Override
     public String getManagerName() {
         return "javax";
     }
 
     /** {@inheritDoc}. */
+    @Override
     public boolean supportsLanguage() {
-        if (engine != null) {
+        if (keptEngine != null) {
             return true;
         }
         checkLanguage();
@@ -63,6 +81,7 @@
      *
      * @exception BuildException if something goes wrong executing the script.
      */
+    @Override
     public void executeScript(String execName) throws BuildException {
         evaluateScript(execName);
     }
@@ -79,28 +98,61 @@
         checkLanguage();
         ClassLoader origLoader = replaceContextLoader();
         try {
-            ReflectWrapper engine = createEngine();
+            if (getCompiled()) {
+                final String compiledScriptRefName =
+                    String.format("%s.%s.%d.%d", MagicNames.SCRIPT_CACHE,
+                        getLanguage(), Objects.hashCode(getScript()),
+                        Objects.hashCode(getClass().getClassLoader()));
+
+                if (null == compiledScript) {
+                    compiledScript = getProject().getReference(compiledScriptRefName);
+                }
+                if (null == compiledScript) {
+                    final ScriptEngine engine = createEngine();
+                    if (engine == null) {
+                        throw new BuildException(
+                            "Unable to create javax script engine for %s",
+                            getLanguage());
+                    }
+                    if (engine instanceof Compilable) {
+                        getProject().log("compile script " + execName,
+                            Project.MSG_VERBOSE);
+
+                        compiledScript =
+                            ((Compilable) engine).compile(getScript());
+                    } else {
+                        getProject().log(
+                            "script compilation not available for " + execName,
+                            Project.MSG_VERBOSE);
+                        compiledScript = null;
+                    }
+                    getProject().addReference(compiledScriptRefName,
+                        compiledScript);
+                }
+                if (null != compiledScript) {
+                    final Bindings bindings = new SimpleBindings();
+
+                    applyBindings(bindings::put);
+
+                    getProject().log(
+                        "run compiled script " + compiledScriptRefName,
+                        Project.MSG_DEBUG);
+
+                    return compiledScript.eval(bindings);
+                }
+            }
+
+            ScriptEngine engine = createEngine();
             if (engine == null) {
                 throw new BuildException(
                     "Unable to create javax script engine for "
-                    + getLanguage());
+                        + getLanguage());
             }
-            for (Iterator i = getBeans().keySet().iterator(); i.hasNext();) {
-                String key = (String) i.next();
-                Object value = getBeans().get(key);
-                if ("FX".equalsIgnoreCase(getLanguage())) {
-                    engine.invoke(
-                        "put", String.class, key
-                        + ":" + value.getClass().getName(),
-                        Object.class, value);
-                } else {
-                    engine.invoke(
-                        "put", String.class, key,
-                        Object.class, value);
-                }
-            }
-            // execute the script
-            return engine.invoke("eval", String.class, getScript());
+
+            applyBindings(engine::put);
+
+            return engine.eval(getScript());
+
         } catch (BuildException be) {
             //catch and rethrow build exceptions
 
@@ -114,7 +166,7 @@
             Throwable t = be;
             Throwable te = be.getCause();
             if (te != null) {
-                if  (te instanceof BuildException) {
+                if (te instanceof BuildException) {
                     throw (BuildException) te;
                 } else {
                     t = te;
@@ -126,22 +178,64 @@
         }
     }
 
-    private ReflectWrapper createEngine() {
-        if (engine != null) {
-            return engine;
+    private void applyBindings(BiConsumer<String, Object> target) {
+        Map<String, Object> source = getBeans();
+
+        if ("FX".equalsIgnoreCase(getLanguage())) {
+            source = source.entrySet().stream()
+                .collect(Collectors.toMap(e -> String.format("%s:%s", e.getKey(),
+                        e.getValue().getClass().getName()), Map.Entry::getValue));
         }
-        ReflectWrapper manager = new ReflectWrapper(
-            getClass().getClassLoader(), "javax.script.ScriptEngineManager");
-        Object e = manager.invoke(
-            "getEngineByName", String.class, getLanguage());
-        if (e == null) {
-            return null;
+        source.forEach(target);
+    }
+
+    private ScriptEngine createEngine() {
+        if (keptEngine != null) {
+            return keptEngine;
         }
-        ReflectWrapper ret = new ReflectWrapper(e);
-        if (getKeepEngine()) {
-            this.engine = ret;
+        if (languageIsJavaScript()) {
+            maybeEnableNashornCompatibility();
         }
-        return ret;
+        final ScriptEngine result =
+            new ScriptEngineManager().getEngineByName(getLanguage());
+        if (result == null && JavaEnvUtils.isAtLeastJavaVersion("15")
+            && languageIsJavaScript()) {
+            getProject()
+                .log("Java 15 has removed Nashorn, you must provide an engine "
+                     + "for running JavaScript yourself. "
+                     + "GraalVM JavaScript currently is the preferred option.",
+                     Project.MSG_WARN);
+        }
+        maybeApplyGraalJsProperties(result);
+        if (result != null && getKeepEngine()) {
+            this.keptEngine = result;
+        }
+        return result;
+    }
+
+    private static final String DROP_GRAAL_SECURITY_RESTRICTIONS = "polyglot.js.allowAllAccess";
+
+    private void maybeApplyGraalJsProperties(final ScriptEngine engine) {
+        if (engine != null && engine.getClass().getName().contains("Graal")) {
+            engine.getBindings(ScriptContext.ENGINE_SCOPE)
+                .put(DROP_GRAAL_SECURITY_RESTRICTIONS, true);
+        }
+    }
+
+    private static final String ENABLE_NASHORN_COMPAT_IN_GRAAL = "polyglot.js.nashorn-compat";
+
+    private void maybeEnableNashornCompatibility() {
+        if (getProject() != null) {
+            System.setProperty(ENABLE_NASHORN_COMPAT_IN_GRAAL,
+                Project.toBoolean(getProject().getProperty(MagicNames.DISABLE_NASHORN_COMPAT))
+                ? "false" : "true");
+        }
+    }
+
+    private final static List<String> JS_LANGUAGES = Arrays.asList("js", "javascript");
+
+    private boolean languageIsJavaScript() {
+        return JS_LANGUAGES.contains(getLanguage());
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java b/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java
index e704ab2..4df8ef0 100644
--- a/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java
+++ b/src/main/org/apache/tools/ant/util/optional/NoExitSecurityManager.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,6 +36,7 @@
      * This throws an ExitException(status) exception.
      * @param status the exit status
      */
+    @Override
     public void checkExit(int status) {
         throw new ExitException(status);
     }
@@ -45,6 +46,7 @@
      * This does nothing.
      * @param perm the requested permission.
      */
+    @Override
     public void checkPermission(Permission perm) {
         // no permission here
     }
diff --git a/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java b/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java
index 45c3ede..da0db83 100644
--- a/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java
+++ b/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,8 +17,7 @@
  */
 package org.apache.tools.ant.util.optional;
 
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.Map;
 
 import org.apache.bsf.BSFEngine;
 import org.apache.bsf.BSFException;
@@ -49,6 +48,7 @@
      * Get the name of the manager prefix.
      * @return "bsf"
      */
+    @Override
     public String getManagerName() {
         return "bsf";
     }
@@ -57,10 +57,11 @@
      * Check if bsf supports the language.
      * @return true if bsf can create an engine for this language.
      */
+    @Override
     public boolean supportsLanguage() {
-        Hashtable table = (Hashtable) ReflectUtil.getField(
-            new BSFManager(), "registeredEngines");
-        String engineClassName = (String) table.get(getLanguage());
+        Map<String, String> table =
+            ReflectUtil.getField(new BSFManager(), "registeredEngines");
+        String engineClassName = table.get(getLanguage());
         if (engineClassName == null) {
             getProject().log(
                 "This is no BSF engine class for language '"
@@ -87,6 +88,7 @@
      * @param execName the name that will be passed to BSF for this script execution.
      * @exception BuildException if something goes wrong executing the script.
      */
+    @Override
     public void executeScript(String execName) throws BuildException {
         checkLanguage();
         ClassLoader origLoader = replaceContextLoader();
@@ -113,6 +115,7 @@
      * @return the result of the evaluation
      * @exception BuildException if something goes wrong executing the script.
      */
+    @Override
     public Object evaluateScript(String execName) throws BuildException {
         checkLanguage();
         ClassLoader origLoader = replaceContextLoader();
@@ -145,8 +148,7 @@
     }
 
     private void declareBeans(BSFManager m) throws BSFException {
-        for (Iterator i = getBeans().keySet().iterator(); i.hasNext();) {
-            String key = (String) i.next();
+        for (String key : getBeans().keySet()) {
             Object value = getBeans().get(key);
             if (value != null) {
                 m.declareBean(key, value, value.getClass());
diff --git a/src/main/org/apache/tools/ant/util/optional/WeakishReference12.java b/src/main/org/apache/tools/ant/util/optional/WeakishReference12.java
index 4cd1278..d50ce77 100644
--- a/src/main/org/apache/tools/ant/util/optional/WeakishReference12.java
+++ b/src/main/org/apache/tools/ant/util/optional/WeakishReference12.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,6 +30,7 @@
  * WeakishReference(Object) constructor, and both that and this are thin
  * facades on the underlying no-longer-abstract base class.
  */
+@Deprecated
 public class WeakishReference12 extends WeakishReference.HardReference  {
 
 
diff --git a/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java b/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java
index 5c43376..a5b2994 100644
--- a/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java
+++ b/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,15 +40,10 @@
     // CheckStyle:VisibilityModifier ON
 
     /**
-     * Constructor for JakartaOroMatcher.
-     */
-    public JakartaOroMatcher() {
-    }
-
-    /**
      * Set the regexp pattern from the String description.
      * @param pattern the pattern to match
      */
+    @Override
     public void setPattern(final String pattern) {
         this.pattern = pattern;
     }
@@ -57,6 +52,7 @@
      * Get a String representation of the regexp pattern
      * @return the pattern
      */
+    @Override
     public String getPattern() {
         return this.pattern;
     }
@@ -71,8 +67,7 @@
         throws BuildException {
         try {
             // compute the compiler options based on the input options first
-            final Pattern p = compiler.compile(pattern, getCompilerOptions(options));
-            return p;
+            return compiler.compile(pattern, getCompilerOptions(options));
         } catch (final Exception e) {
             throw new BuildException(e);
         }
@@ -84,6 +79,7 @@
      * @return true if the pattern matches
      * @throws BuildException on error
      */
+    @Override
     public boolean matches(final String argument) throws BuildException {
         return matches(argument, MATCH_DEFAULT);
     }
@@ -95,10 +91,10 @@
      * @return true if the pattern matches
      * @throws BuildException on error
      */
+    @Override
     public boolean matches(final String input, final int options)
         throws BuildException {
-        final Pattern p = getCompiledPattern(options);
-        return matcher.contains(input, p);
+        return matcher.contains(input, getCompiledPattern(options));
     }
 
     /**
@@ -112,7 +108,8 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    public Vector getGroups(final String argument) throws BuildException {
+    @Override
+    public Vector<String> getGroups(final String argument) throws BuildException {
         return getGroups(argument, MATCH_DEFAULT);
     }
 
@@ -127,12 +124,13 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    public Vector getGroups(final String input, final int options)
+    @Override
+    public Vector<String> getGroups(final String input, final int options)
         throws BuildException {
         if (!matches(input, options)) {
             return null;
         }
-        final Vector v = new Vector();
+        final Vector<String> v = new Vector<>();
         final MatchResult mr = matcher.getMatch();
         final int cnt = mr.groups();
         for (int i = 0; i < cnt; i++) {
@@ -141,7 +139,7 @@
             if (match == null) {
                 match = "";
             }
-            v.addElement(match);
+            v.add(match);
         }
         return v;
     }
diff --git a/src/main/org/apache/tools/ant/util/regexp/JakartaOroRegexp.java b/src/main/org/apache/tools/ant/util/regexp/JakartaOroRegexp.java
index 32cebeb..09e125d 100644
--- a/src/main/org/apache/tools/ant/util/regexp/JakartaOroRegexp.java
+++ b/src/main/org/apache/tools/ant/util/regexp/JakartaOroRegexp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,11 +29,6 @@
 
     private static final int DECIMAL = 10;
 
-    /** Constructor for JakartaOroRegexp */
-    public JakartaOroRegexp() {
-        super();
-    }
-
     /**
      * Perform a substitution on the regular expression.
      * @param input The string to substitute on
@@ -45,7 +40,7 @@
     public String substitute(final String input, final String argument, final int options)
         throws BuildException {
         // translate \1 to $1 so that the Perl5Substitution will work
-        final StringBuffer subst = new StringBuffer();
+        final StringBuilder subst = new StringBuilder();
         for (int i = 0; i < argument.length(); i++) {
             char c = argument.charAt(i);
             if (c == '$') {
@@ -56,7 +51,7 @@
                     c = argument.charAt(i);
                     final int value = Character.digit(c, DECIMAL);
                     if (value > -1) {
-                        subst.append("$").append(value);
+                        subst.append('$').append(value);
                     } else {
                         subst.append(c);
                     }
@@ -87,12 +82,8 @@
      * @return the oro substitution options
      */
     protected int getSubsOptions(final int options) {
-        final boolean replaceAll = RegexpUtil.hasFlag(options, REPLACE_ALL);
-        int subsOptions = 1;
-        if (replaceAll) {
-            subsOptions = Util.SUBSTITUTE_ALL;
-        }
-        return subsOptions;
+        return RegexpUtil.hasFlag(options, REPLACE_ALL) ? Util.SUBSTITUTE_ALL
+            : 1;
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpMatcher.java b/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpMatcher.java
index 3e14415..b4b4202 100644
--- a/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpMatcher.java
+++ b/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpMatcher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,6 +35,7 @@
      * Set the regexp pattern from the String description.
      * @param pattern the pattern to match
      */
+    @Override
     public void setPattern(String pattern) {
         this.pattern = pattern;
     }
@@ -43,6 +44,7 @@
      * Get a String representation of the regexp pattern
      * @return the pattern
      */
+    @Override
     public String getPattern() {
         return pattern;
     }
@@ -72,6 +74,7 @@
      * @return true if the pattern matches
      * @throws BuildException on error
      */
+    @Override
     public boolean matches(String argument) throws BuildException {
         return matches(argument, MATCH_DEFAULT);
     }
@@ -83,6 +86,7 @@
      * @return true if the pattern matches
      * @throws BuildException on error
      */
+    @Override
     public boolean matches(String input, int options)
         throws BuildException {
         return matches(input, getCompiledPattern(options));
@@ -103,7 +107,8 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    public Vector getGroups(String argument) throws BuildException {
+    @Override
+    public Vector<String> getGroups(String argument) throws BuildException {
         return getGroups(argument, MATCH_DEFAULT);
     }
 
@@ -118,13 +123,14 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    public Vector getGroups(String input, int options)
+    @Override
+    public Vector<String> getGroups(String input, int options)
         throws BuildException {
         RE reg = getCompiledPattern(options);
         if (!matches(input, reg)) {
             return null;
         }
-        Vector v = new Vector();
+        Vector<String> v = new Vector<>();
         int cnt = reg.getParenCount();
         for (int i = 0; i < cnt; i++) {
             String match = reg.getParen(i);
@@ -132,7 +138,7 @@
             if (match == null) {
                 match = "";
             }
-            v.addElement(match);
+            v.add(match);
         }
         return v;
     }
diff --git a/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpRegexp.java b/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpRegexp.java
index cdb6de9..22f14ee 100644
--- a/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpRegexp.java
+++ b/src/main/org/apache/tools/ant/util/regexp/JakartaRegexpRegexp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,11 +29,6 @@
 
     private static final int DECIMAL = 10;
 
-    /** Constructor for JakartaRegexpRegexp */
-    public JakartaRegexpRegexp() {
-        super();
-    }
-
     /**
      * Convert ant regexp substitution option to apache regex options.
      *
@@ -56,12 +51,13 @@
      * @return the result of the operation
      * @throws BuildException on error
      */
+    @Override
     public String substitute(String input, String argument, int options)
         throws BuildException {
-        Vector v = getGroups(input, options);
+        Vector<String> v = getGroups(input, options);
 
         // replace \1 with the corresponding group
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         for (int i = 0; i < argument.length(); i++) {
             char c = argument.charAt(i);
             if (c == '\\') {
@@ -69,7 +65,7 @@
                     c = argument.charAt(i);
                     int value = Character.digit(c, DECIMAL);
                     if (value > -1) {
-                        result.append((String) v.elementAt(value));
+                        result.append(v.elementAt(value));
                     } else {
                         result.append(c);
                     }
@@ -81,10 +77,8 @@
                 result.append(c);
             }
         }
-        argument = result.toString();
-
         RE reg = getCompiledPattern(options);
         int sOptions = getSubsOptions(options);
-        return reg.subst(input, argument, sOptions);
+        return reg.subst(input, result.toString(), sOptions);
     }
 }
diff --git a/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcher.java b/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcher.java
index 8c241d4..4d9c439 100644
--- a/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcher.java
+++ b/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,14 +34,11 @@
 
     private String pattern;
 
-    /** Constructor for JakartaOroRegexp */
-    public Jdk14RegexpMatcher() {
-    }
-
     /**
      * Set the regexp pattern from the String description.
      * @param pattern the pattern to match
      */
+    @Override
     public void setPattern(String pattern) {
         this.pattern = pattern;
     }
@@ -51,6 +48,7 @@
      * @return the pattern
      * @throws BuildException on error
      */
+    @Override
     public String getPattern() {
         return pattern;
     }
@@ -63,10 +61,8 @@
      */
     protected Pattern getCompiledPattern(int options)
         throws BuildException {
-        int cOptions = getCompilerOptions(options);
         try {
-            Pattern p = Pattern.compile(this.pattern, cOptions);
-            return p;
+            return Pattern.compile(this.pattern, getCompilerOptions(options));
         } catch (PatternSyntaxException e) {
             throw new BuildException(e);
         }
@@ -78,6 +74,7 @@
      * @return true if the pattern matches
      * @throws BuildException on error
      */
+    @Override
     public boolean matches(String argument) throws BuildException {
         return matches(argument, MATCH_DEFAULT);
     }
@@ -89,11 +86,11 @@
      * @return true if the pattern matches
      * @throws BuildException on error
      */
+    @Override
     public boolean matches(String input, int options)
         throws BuildException {
         try {
-            Pattern p = getCompiledPattern(options);
-            return p.matcher(input).find();
+            return getCompiledPattern(options).matcher(input).find();
         } catch (Exception e) {
             throw new BuildException(e);
         }
@@ -110,7 +107,8 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    public Vector getGroups(String argument) throws BuildException {
+    @Override
+    public Vector<String> getGroups(String argument) throws BuildException {
         return getGroups(argument, MATCH_DEFAULT);
     }
 
@@ -125,14 +123,15 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    public Vector getGroups(String input, int options)
+    @Override
+    public Vector<String> getGroups(String input, int options)
         throws BuildException {
         Pattern p = getCompiledPattern(options);
         Matcher matcher = p.matcher(input);
         if (!matcher.find()) {
             return null;
         }
-        Vector v = new Vector();
+        Vector<String> v = new Vector<>();
         int cnt = matcher.groupCount();
         for (int i = 0; i <= cnt; i++) {
             String match = matcher.group(i);
@@ -140,7 +139,7 @@
             if (match == null) {
                 match = "";
             }
-            v.addElement(match);
+            v.add(match);
         }
         return v;
     }
diff --git a/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java b/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java
index de0054f..b1939a0 100644
--- a/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java
+++ b/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,11 +29,6 @@
 
     private static final int DECIMAL = 10;
 
-    /** Constructor for Jdk14RegexpRegexp */
-    public Jdk14RegexpRegexp() {
-        super();
-    }
-
     /**
      * Convert ant regexp substitution option to jdk1.4 options.
      *
@@ -56,10 +51,11 @@
      * @return the result of the operation
      * @throws BuildException on error
      */
+    @Override
     public String substitute(String input, String argument, int options)
         throws BuildException {
         // translate \1 to $(1) so that the Matcher will work
-        StringBuffer subst = new StringBuffer();
+        StringBuilder subst = new StringBuilder();
         for (int i = 0; i < argument.length(); i++) {
             char c = argument.charAt(i);
             if (c == '$') {
@@ -70,7 +66,7 @@
                     c = argument.charAt(i);
                     int value = Character.digit(c, DECIMAL);
                     if (value > -1) {
-                        subst.append("$").append(value);
+                        subst.append('$').append(value);
                     } else {
                         subst.append(c);
                     }
@@ -82,7 +78,6 @@
                 subst.append(c);
             }
         }
-        argument = subst.toString();
 
         int sOptions = getSubsOptions(options);
         Pattern p = getCompiledPattern(options);
@@ -90,15 +85,12 @@
 
         Matcher m = p.matcher(input);
         if (RegexpUtil.hasFlag(sOptions, REPLACE_ALL)) {
-            sb.append(m.replaceAll(argument));
+            sb.append(m.replaceAll(subst.toString()));
+        } else if (m.find()) {
+            m.appendReplacement(sb, subst.toString());
+            m.appendTail(sb);
         } else {
-            boolean res = m.find();
-            if (res) {
-                m.appendReplacement(sb, argument);
-                m.appendTail(sb);
-            } else {
-                sb.append(input);
-            }
+            sb.append(input);
         }
         return sb.toString();
     }
diff --git a/src/main/org/apache/tools/ant/util/regexp/Regexp.java b/src/main/org/apache/tools/ant/util/regexp/Regexp.java
index 1c7816a..33226b6 100644
--- a/src/main/org/apache/tools/ant/util/regexp/Regexp.java
+++ b/src/main/org/apache/tools/ant/util/regexp/Regexp.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpFactory.java b/src/main/org/apache/tools/ant/util/regexp/RegexpFactory.java
index 7077a21..b7fc3cd 100644
--- a/src/main/org/apache/tools/ant/util/regexp/RegexpFactory.java
+++ b/src/main/org/apache/tools/ant/util/regexp/RegexpFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,10 +30,6 @@
  */
 public class RegexpFactory extends RegexpMatcherFactory {
 
-    /** Constructor for RegexpFactory */
-    public RegexpFactory() {
-    }
-
     /***
      * Create a new regular expression matcher instance.
      * @return the matcher instance
@@ -51,7 +47,7 @@
      * @throws BuildException on error
      */
     public Regexp newRegexp(Project p) throws BuildException {
-        String systemDefault = null;
+        String systemDefault;
         if (p == null) {
             systemDefault = System.getProperty(MagicNames.REGEXP_IMPL);
         } else {
@@ -78,8 +74,8 @@
      * @see RegexpMatcherFactory#createInstance(String)
      */
     protected Regexp createRegexpInstance(String classname) throws BuildException {
-        return (Regexp) ClasspathUtils.newInstance(classname, RegexpFactory.class.getClassLoader(),
-                Regexp.class);
+        return ClasspathUtils.newInstance(classname,
+            RegexpFactory.class.getClassLoader(), Regexp.class);
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java
index 7938d8b..3754577 100644
--- a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java
+++ b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -83,7 +83,7 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    Vector getGroups(String argument) throws BuildException;
+    Vector<String> getGroups(String argument) throws BuildException;
 
     /***
      * Does this regular expression match the input, given
@@ -105,6 +105,6 @@
      * @return the vector of groups
      * @throws BuildException on error
      */
-    Vector getGroups(String input, int options) throws BuildException;
+    Vector<String> getGroups(String input, int options) throws BuildException;
 
 }
diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java
index 4f2082d..ebf3423 100644
--- a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java
+++ b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,10 +33,6 @@
  */
 public class RegexpMatcherFactory {
 
-    /** Constructor for RegexpMatcherFactory. */
-    public RegexpMatcherFactory() {
-    }
-
     /***
      * Create a new regular expression instance.
      * @return the matcher
@@ -54,7 +50,7 @@
      * @throws BuildException on error
      */
     public RegexpMatcher newRegexpMatcher(Project p) throws BuildException {
-        String systemDefault = null;
+        String systemDefault;
         if (p == null) {
             systemDefault = System.getProperty(MagicNames.REGEXP_IMPL);
         } else {
@@ -78,8 +74,8 @@
      * @exception BuildException if an error occurs
      */
     protected RegexpMatcher createInstance(String className) throws BuildException {
-        return (RegexpMatcher) ClasspathUtils.newInstance(className, RegexpMatcherFactory.class
-                .getClassLoader(), RegexpMatcher.class);
+        return ClasspathUtils.newInstance(className,
+            RegexpMatcherFactory.class.getClassLoader(), RegexpMatcher.class);
     }
 
     /**
diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java b/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java
index 18fb95a..4a0b3a7 100644
--- a/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java
+++ b/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,7 +33,7 @@
      * @return true if the flag is set
      */
     public static boolean hasFlag(int options, int flag) {
-        return ((options & flag) > 0);
+        return (options & flag) > 0;
     }
 
     /**
@@ -44,7 +44,7 @@
      * @return the options with the flag unset
      */
     public static int removeFlag(int options, int flag) {
-        return (options & (0xFFFFFFFF - flag));
+        return options & (0xFFFFFFFF - flag);
     }
 
     /**
@@ -62,10 +62,10 @@
     public static int asOptions(String flags) {
         int options = RegexpMatcher.MATCH_DEFAULT;
         if (flags != null) {
-            options = asOptions(flags.indexOf('i') == -1,
-                                flags.indexOf('m') != -1,
-                                flags.indexOf('s') != -1);
-            if (flags.indexOf('g') != -1) {
+            options = asOptions(!flags.contains("i"),
+                    flags.contains("m"),
+                    flags.contains("s"));
+            if (flags.contains("g")) {
                 options |= Regexp.REPLACE_ALL;
             }
         }
@@ -96,13 +96,13 @@
                                 boolean singleLine) {
         int options = RegexpMatcher.MATCH_DEFAULT;
         if (!caseSensitive) {
-            options = options | RegexpMatcher.MATCH_CASE_INSENSITIVE;
+            options |= RegexpMatcher.MATCH_CASE_INSENSITIVE;
         }
         if (multiLine) {
-            options = options | RegexpMatcher.MATCH_MULTILINE;
+            options |= RegexpMatcher.MATCH_MULTILINE;
         }
         if (singleLine) {
-            options = options | RegexpMatcher.MATCH_SINGLELINE;
+            options |= RegexpMatcher.MATCH_SINGLELINE;
         }
         return options;
     }
diff --git a/src/main/org/apache/tools/bzip2/BZip2Constants.java b/src/main/org/apache/tools/bzip2/BZip2Constants.java
index df32d95..9f6dce5 100644
--- a/src/main/org/apache/tools/bzip2/BZip2Constants.java
+++ b/src/main/org/apache/tools/bzip2/BZip2Constants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/bzip2/BlockSort.java b/src/main/org/apache/tools/bzip2/BlockSort.java
index e2aaf37..01439e1 100644
--- a/src/main/org/apache/tools/bzip2/BlockSort.java
+++ b/src/main/org/apache/tools/bzip2/BlockSort.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
@@ -52,7 +52,7 @@
  * ssCommons Compre
  * </pre>
  *
- * <p>Which results in a new text "ss romooCCmmpnse", in adition the
+ * <p>Which results in a new text "ss romooCCmmpnse", in addition the
  * index of the first line that contained the original text is kept -
  * in this case it is 1.  The idea is that in a long English text all
  * permutations that start with "he" are likely suffixes of a "the" and
@@ -63,14 +63,14 @@
  * <p>For more information see for example:</p>
  * <ul>
  *   <li><a
- *   href="http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-124.pdf">Burrows,
+ *   href="https://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-124.pdf">Burrows,
  *   M. and Wheeler, D.: A Block-sorting Lossless Data Compression
  *   Algorithm</a></li>
  *   <li><a href="http://webglimpse.net/pubs/suffix.pdf">Manber, U. and
  *   Myers, G.: Suffix arrays: A new method for on-line string
  *   searches</a></li>
  *   <li><a
- *   href="http://www.cs.tufts.edu/~nr/comp150fp/archive/bob-sedgewick/fast-strings.pdf">Bentley,
+ *   href="https://www.cs.tufts.edu/~nr/comp150fp/archive/bob-sedgewick/fast-strings.pdf">Bentley,
  *   J.L. and Sedgewick, R.: Fast Algorithms for Sorting and Searching
  *   Strings</a></li>
  * </ul>
@@ -117,6 +117,7 @@
 
     private static final int FALLBACK_QSORT_STACK_SIZE = 100;
 
+    @SuppressWarnings("unused")
     private static final int STACK_SIZE =
         QSORT_STACK_SIZE < FALLBACK_QSORT_STACK_SIZE
         ? FALLBACK_QSORT_STACK_SIZE : QSORT_STACK_SIZE;
@@ -523,7 +524,7 @@
 
         /*-- LBZ2: the log(N) loop --*/
         H = 1;
-        while (true) {
+        do {
 
             j = 0;
             for (i = 0; i < nblock; i++) {
@@ -572,10 +573,7 @@
             }
 
             H *= 2;
-            if (H > nblock || nNotDone == 0) {
-                break;
-            }
-        }
+        } while (H <= nblock && nNotDone != 0);
     }
 
 /*---------------------------------------------*/
@@ -651,7 +649,7 @@
                         if (onceRun) {
                             fmap[j] = a;
                             if ((j -= h) <= mj) { //NOSONAR
-                                break HAMMER;
+                                break;
                             }
                         } else {
                             onceRun = true;
@@ -670,7 +668,7 @@
                                         if (block[i1 + 5] == block[i2 + 5]) {
                                             if (block[(i1 += 6)] == block[(i2 += 6)]) { //NOSONAR
                                                 int x = lastShadow;
-                                                X: while (x > 0) {
+                                                while (x > 0) {
                                                     x -= 4;
 
                                                     if (block[i1 + 1] == block[i2 + 1]) {
@@ -688,7 +686,6 @@
                                                                                         i2 -= lastPlus1;
                                                                                     }
                                                                                     workDoneShadow++;
-                                                                                    continue X;
                                                                                 } else if ((quadrant[i1 + 3] > quadrant[i2 + 3])) {
                                                                                     continue HAMMER;
                                                                                 } else {
@@ -731,39 +728,25 @@
                                                     }
 
                                                 }
-                                                break HAMMER;
+                                                break;
                                             } // while x > 0
-                                            else {
-                                                if ((block[i1] & 0xff) > (block[i2] & 0xff)) {
-                                                    continue HAMMER;
-                                                } else {
-                                                    break HAMMER;
-                                                }
+                                            else if ((block[i1] & 0xff) <= (block[i2] & 0xff)) {
+                                                break;
                                             }
-                                        } else if ((block[i1 + 5] & 0xff) > (block[i2 + 5] & 0xff)) {
-                                            continue HAMMER;
-                                        } else {
-                                            break HAMMER;
+                                        } else if ((block[i1 + 5] & 0xff) <= (block[i2 + 5] & 0xff)) {
+                                            break;
                                         }
-                                    } else if ((block[i1 + 4] & 0xff) > (block[i2 + 4] & 0xff)) {
-                                        continue HAMMER;
-                                    } else {
-                                        break HAMMER;
+                                    } else if ((block[i1 + 4] & 0xff) <= (block[i2 + 4] & 0xff)) {
+                                        break;
                                     }
-                                } else if ((block[i1 + 3] & 0xff) > (block[i2 + 3] & 0xff)) {
-                                    continue HAMMER;
-                                } else {
-                                    break HAMMER;
+                                } else if ((block[i1 + 3] & 0xff) <= (block[i2 + 3] & 0xff)) {
+                                    break;
                                 }
-                            } else if ((block[i1 + 2] & 0xff) > (block[i2 + 2] & 0xff)) {
-                                continue HAMMER;
-                            } else {
-                                break HAMMER;
+                            } else if ((block[i1 + 2] & 0xff) <= (block[i2 + 2] & 0xff)) {
+                                break;
                             }
-                        } else if ((block[i1 + 1] & 0xff) > (block[i2 + 1] & 0xff)) {
-                            continue HAMMER;
-                        } else {
-                            break HAMMER;
+                        } else if ((block[i1 + 1] & 0xff) <= (block[i2 + 1] & 0xff)) {
+                            break;
                         }
 
                     } // HAMMER
diff --git a/src/main/org/apache/tools/bzip2/CBZip2InputStream.java b/src/main/org/apache/tools/bzip2/CBZip2InputStream.java
index 7563a40..8dfbfc6 100644
--- a/src/main/org/apache/tools/bzip2/CBZip2InputStream.java
+++ b/src/main/org/apache/tools/bzip2/CBZip2InputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,11 +32,11 @@
  *
  * <p>The decompression requires large amounts of memory. Thus you
  * should call the {@link #close() close()} method as soon as
- * possible, to force <tt>CBZip2InputStream</tt> to release the
+ * possible, to force <code>CBZip2InputStream</code> to release the
  * allocated memory.  See {@link CBZip2OutputStream
  * CBZip2OutputStream} for information about memory usage.</p>
  *
- * <p><tt>CBZip2InputStream</tt> reads bytes from the compressed
+ * <p><code>CBZip2InputStream</code> reads bytes from the compressed
  * source stream via the single byte {@link java.io.InputStream#read()
  * read()} method exclusively. Thus you should consider to use a
  * buffered source stream.</p>
@@ -74,7 +74,7 @@
 
     private int currentChar = -1;
 
-    private static final int EOF                  = 0;
+    private static final int EOF               = 0;
     private static final int START_BLOCK_STATE = 1;
     private static final int RAND_PART_A_STATE = 2;
     private static final int RAND_PART_B_STATE = 3;
@@ -85,8 +85,10 @@
 
     private int currentState = START_BLOCK_STATE;
 
-    private int storedBlockCRC, storedCombinedCRC;
-    private int computedBlockCRC, computedCombinedCRC;
+    private int storedBlockCRC;
+    private int storedCombinedCRC;
+    private int computedBlockCRC;
+    private int computedCombinedCRC;
 
     // Variables used by setup* methods exclusively
 
@@ -112,7 +114,7 @@
      * concatenated .bz2 files.
      *
      * <p>Although BZip2 headers are marked with the magic
-     * <tt>"Bz"</tt> this constructor expects the next byte in the
+     * <code>"Bz"</code> this constructor expects the next byte in the
      * stream to be the first one after the magic.  Thus callers have
      * to skip the first two bytes. Otherwise this constructor will
      * throw an exception. </p>
@@ -121,7 +123,7 @@
      * @throws IOException
      *  if the stream content is malformed or an I/O error occurs.
      * @throws NullPointerException
-     *  if <tt>in == null</tt>
+     *  if <code>in == null</code>
      */
     public CBZip2InputStream(final InputStream in) throws IOException {
         this(in, false);
@@ -132,7 +134,7 @@
      * read from the specified stream.
      *
      * <p>Although BZip2 headers are marked with the magic
-     * <tt>"Bz"</tt> this constructor expects the next byte in the
+     * <code>"Bz"</code> this constructor expects the next byte in the
      * stream to be the first one after the magic.  Thus callers have
      * to skip the first two bytes. Otherwise this constructor will
      * throw an exception. </p>
@@ -147,7 +149,7 @@
      * @throws IOException
      *             if the stream content is malformed or an I/O error occurs.
      * @throws NullPointerException
-     *             if <tt>in == null</tt>
+     *             if <code>in == null</code>
      */
     public CBZip2InputStream(final InputStream in,
                              final boolean decompressConcatenated)
@@ -286,7 +288,7 @@
         }
 
         int blockSize = this.in.read();
-        if ((blockSize < '1') || (blockSize > '9')) {
+        if (blockSize < '1' || blockSize > '9') {
             throw new IOException("Stream is not BZip2 formatted: illegal "
                                   + "blocksize " + (char) blockSize);
         }
@@ -359,7 +361,7 @@
         }
     }
 
-    private void endBlock() throws IOException {
+    private void endBlock() {
         this.computedBlockCRC = this.crc.getFinalCRC();
 
         // A bad CRC is considered a fatal error.
@@ -660,7 +662,7 @@
         int minLens_zt  = minLens[zt];
 
         while (nextSym != eob) {
-            if ((nextSym == RUNA) || (nextSym == RUNB)) {
+            if (nextSym == RUNA || nextSym == RUNB) {
                 int s = -1;
 
                 for (int n = 1; true; n <<= 1) {
@@ -853,7 +855,7 @@
             tt[cftab[ll8[i] & 0xff]++] = i;
         }
 
-        if ((this.origPtr < 0) || (this.origPtr >= tt.length)) {
+        if (this.origPtr < 0 || this.origPtr >= tt.length) {
             throw new IOException("stream corrupted");
         }
 
@@ -983,7 +985,7 @@
         }
     }
 
-    private static final class Data extends Object {
+    private static final class Data {
 
         // (with blockSize 900k)
         final boolean[] inUse   = new boolean[256];                                   //      256 byte
@@ -1037,7 +1039,7 @@
             // it can happen, if the compressor mixed small and large
             // blocks.  Normally only the last block will be smaller
             // than others.
-            if ((ttShadow == null) || (ttShadow.length < length)) {
+            if (ttShadow == null || ttShadow.length < length) {
                 this.tt = ttShadow = new int[length];
             }
 
@@ -1046,7 +1048,7 @@
 
     }
 
-    private static void reportCRCError() throws IOException {
+    private static void reportCRCError() {
         // The clean way would be to throw an exception.
         //throw new IOException("crc error");
 
diff --git a/src/main/org/apache/tools/bzip2/CBZip2OutputStream.java b/src/main/org/apache/tools/bzip2/CBZip2OutputStream.java
index a5ca068..37cfe32 100644
--- a/src/main/org/apache/tools/bzip2/CBZip2OutputStream.java
+++ b/src/main/org/apache/tools/bzip2/CBZip2OutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,7 +34,7 @@
  * <p>
  * The compression requires large amounts of memory. Thus you should call the
  * {@link #close() close()} method as soon as possible, to force
- * <tt>CBZip2OutputStream</tt> to release the allocated memory.
+ * <code>CBZip2OutputStream</code> to release the allocated memory.
  * </p>
  *
  * <p>You can shrink the amount of allocated memory and maybe raise
@@ -57,62 +57,62 @@
  * &lt;code&gt;65k + (5 * blocksize)&lt;/code&gt;.
  * </pre>
  *
- * <table border="1">
+ * <table style="border:1px solid black">
  * <caption>Memory usage by blocksize</caption>
  * <tr>
- * <th align="right">Blocksize</th>
- * <th align="right">Compression<br>memory usage</th>
- * <th align="right">Decompression<br>memory usage</th>
+ * <th style="text-align:right">Blocksize</th>
+ * <th style="text-align:right">Compression<br>memory usage</th>
+ * <th style="text-align:right">Decompression<br>memory usage</th>
  * </tr>
  * <tr>
- * <td align="right">100k</td>
- * <td align="right">1300k</td>
- * <td align="right">565k</td>
+ * <td style="text-align:right">100k</td>
+ * <td style="text-align:right">1300k</td>
+ * <td style="text-align:right">565k</td>
  * </tr>
  * <tr>
- * <td align="right">200k</td>
- * <td align="right">2200k</td>
- * <td align="right">1065k</td>
+ * <td style="text-align:right">200k</td>
+ * <td style="text-align:right">2200k</td>
+ * <td style="text-align:right">1065k</td>
  * </tr>
  * <tr>
- * <td align="right">300k</td>
- * <td align="right">3100k</td>
- * <td align="right">1565k</td>
+ * <td style="text-align:right">300k</td>
+ * <td style="text-align:right">3100k</td>
+ * <td style="text-align:right">1565k</td>
  * </tr>
  * <tr>
- * <td align="right">400k</td>
- * <td align="right">4000k</td>
- * <td align="right">2065k</td>
+ * <td style="text-align:right">400k</td>
+ * <td style="text-align:right">4000k</td>
+ * <td style="text-align:right">2065k</td>
  * </tr>
  * <tr>
- * <td align="right">500k</td>
- * <td align="right">4900k</td>
- * <td align="right">2565k</td>
+ * <td style="text-align:right">500k</td>
+ * <td style="text-align:right">4900k</td>
+ * <td style="text-align:right">2565k</td>
  * </tr>
  * <tr>
- * <td align="right">600k</td>
- * <td align="right">5800k</td>
- * <td align="right">3065k</td>
+ * <td style="text-align:right">600k</td>
+ * <td style="text-align:right">5800k</td>
+ * <td style="text-align:right">3065k</td>
  * </tr>
  * <tr>
- * <td align="right">700k</td>
- * <td align="right">6700k</td>
- * <td align="right">3565k</td>
+ * <td style="text-align:right">700k</td>
+ * <td style="text-align:right">6700k</td>
+ * <td style="text-align:right">3565k</td>
  * </tr>
  * <tr>
- * <td align="right">800k</td>
- * <td align="right">7600k</td>
- * <td align="right">4065k</td>
+ * <td style="text-align:right">800k</td>
+ * <td style="text-align:right">7600k</td>
+ * <td style="text-align:right">4065k</td>
  * </tr>
  * <tr>
- * <td align="right">900k</td>
- * <td align="right">8500k</td>
- * <td align="right">4565k</td>
+ * <td style="text-align:right">900k</td>
+ * <td style="text-align:right">8500k</td>
+ * <td style="text-align:right">4565k</td>
  * </tr>
  * </table>
  *
  * <p>
- * For decompression <tt>CBZip2InputStream</tt> allocates less memory if the
+ * For decompression <code>CBZip2InputStream</code> allocates less memory if the
  * bzipped input is smaller than one block.
  * </p>
  *
@@ -129,12 +129,12 @@
     implements BZip2Constants {
 
     /**
-     * The minimum supported blocksize <tt> == 1</tt>.
+     * The minimum supported blocksize <code> == 1</code>.
      */
     public static final int MIN_BLOCKSIZE = 1;
 
     /**
-     * The maximum supported blocksize <tt> == 9</tt>.
+     * The maximum supported blocksize <code> == 9</code>.
      */
     public static final int MAX_BLOCKSIZE = 9;
 
@@ -564,10 +564,10 @@
      *
      * @param inputLength
      *            The length of the data which will be compressed by
-     *            <tt>CBZip2OutputStream</tt>.
+     *            <code>CBZip2OutputStream</code>.
      * @return The blocksize, between {@link #MIN_BLOCKSIZE} and
      *         {@link #MAX_BLOCKSIZE} both inclusive. For a negative
-     *         <tt>inputLength</tt> this method returns <tt>MAX_BLOCKSIZE</tt>
+     *         <code>inputLength</code> this method returns <code>MAX_BLOCKSIZE</code>
      *         always.
      */
     public static int chooseBlockSize(long inputLength) {
@@ -576,11 +576,11 @@
     }
 
     /**
-     * Constructs a new <tt>CBZip2OutputStream</tt> with a blocksize of 900k.
+     * Constructs a new <code>CBZip2OutputStream</code> with a blocksize of 900k.
      *
      * <p>
      * <b>Attention: </b>The caller is responsible to write the two BZip2 magic
-     * bytes <tt>"BZ"</tt> to the specified stream prior to calling this
+     * bytes <code>"BZ"</code> to the specified stream prior to calling this
      * constructor.
      * </p>
      *
@@ -597,11 +597,11 @@
     }
 
     /**
-     * Constructs a new <tt>CBZip2OutputStream</tt> with specified blocksize.
+     * Constructs a new <code>CBZip2OutputStream</code> with specified blocksize.
      *
      * <p>
      * <b>Attention: </b>The caller is responsible to write the two BZip2 magic
-     * bytes <tt>"BZ"</tt> to the specified stream prior to calling this
+     * bytes <code>"BZ"</code> to the specified stream prior to calling this
      * constructor.
      * </p>
      *
@@ -1008,18 +1008,17 @@
             int ge = gs - 1;
             int aFreq = 0;
 
-            for (final int a = alphaSize - 1; (aFreq < tFreq) && (ge < a);) {
+            while (aFreq < tFreq && ge < alphaSize - 1) {
                 aFreq += mtfFreq[++ge];
             }
 
-            if ((ge > gs) && (nPart != nGroups) && (nPart != 1)
-                && (((nGroups - nPart) & 1) != 0)) {
+            if (ge > gs && nPart != nGroups && nPart != 1 && (nGroups - nPart & 1) != 0) {
                 aFreq -= mtfFreq[ge--];
             }
 
             final byte[] len_np = len[nPart - 1];
             for (int v = alphaSize; --v >= 0;) {
-                if ((v >= gs) && (v <= ge)) {
+                if (v >= gs && v <= ge) {
                     len_np[v] = LESSER_ICOST;
                 } else {
                     len_np[v] = GREATER_ICOST;
@@ -1211,6 +1210,7 @@
             for (int j = 16; --j >= 0;) {
                 if (inUse[i16 + j]) {
                     inUse16[i] = true;
+                    break;
                 }
             }
         }
@@ -1513,7 +1513,7 @@
         this.nMTF = wr + 1;
     }
 
-    static final class Data extends Object {
+    static final class Data {
 
         // with blockSize 900k
         /* maps unsigned byte => "does it occur in block" */
diff --git a/src/main/org/apache/tools/bzip2/CRC.java b/src/main/org/apache/tools/bzip2/CRC.java
index 0d4ada9..9fbb038 100644
--- a/src/main/org/apache/tools/bzip2/CRC.java
+++ b/src/main/org/apache/tools/bzip2/CRC.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/mail/ErrorInQuitException.java b/src/main/org/apache/tools/mail/ErrorInQuitException.java
index 6f78a14..8069322 100644
--- a/src/main/org/apache/tools/mail/ErrorInQuitException.java
+++ b/src/main/org/apache/tools/mail/ErrorInQuitException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,12 +25,14 @@
  *
  * <p>This seems to happen with some version of MS Exchange that
  * doesn't respond with a 221 code immediately.  See <a
- * href="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=5273">Bug
+ * href="https://bz.apache.org/bugzilla/show_bug.cgi?id=5273">Bug
  * report 5273</a>.</p>
  *
  */
 public class ErrorInQuitException extends IOException {
 
+    private static final long serialVersionUID = 1L;
+
     /**
      * Initialise from an IOException
      *
diff --git a/src/main/org/apache/tools/mail/MailMessage.java b/src/main/org/apache/tools/mail/MailMessage.java
index 0906fde..48b1550 100644
--- a/src/main/org/apache/tools/mail/MailMessage.java
+++ b/src/main/org/apache/tools/mail/MailMessage.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,7 +32,8 @@
 import java.io.PrintStream;
 import java.net.InetAddress;
 import java.net.Socket;
-import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Vector;
 
 /**
@@ -113,23 +114,23 @@
     private String from;
 
     /** list of email addresses to reply to */
-    private Vector<String> replyto = new Vector<String>();
+    private final Vector<String> replyto = new Vector<>();
 
     /** list of email addresses to send to */
-    private Vector<String> to = new Vector<String>();
+    private final Vector<String> to = new Vector<>();
 
     /** list of email addresses to cc to */
-    private Vector<String> cc = new Vector<String>();
+    private final Vector<String> cc = new Vector<>();
 
     /** headers to send in the mail */
-    private Vector<String> headersKeys = new Vector<String>();
-    private Vector<String> headersValues = new Vector<String>();
+    private final Map<String, String> headers = new LinkedHashMap<>();
 
     private MailPrintStream out;
 
     private SmtpResponseReader in;
 
     private Socket socket;
+
     private static final int OK_READY = 220;
     private static final int OK_HELO = 250;
     private static final int OK_FROM = 250;
@@ -144,7 +145,7 @@
      * Use localhost as the mail server with port 25.
      *
      * @exception IOException if there's any problem contacting the mail server
-    */
+     */
     public MailMessage() throws IOException {
         this(DEFAULT_HOST, DEFAULT_PORT);
     }
@@ -253,14 +254,13 @@
 
     /**
      * Sets the named header to the given value.  RFC 822 provides the rules for
-     * what text may constitute a header name and value.
+     * what text may constitue a header name and value.
      * @param name name of the header
      * @param value contents of the header
      */
     public void setHeader(String name, String value) {
         // Blindly trust the user doesn't set any invalid headers
-        headersKeys.add(name);
-        headersValues.add(value);
+        headers.put(name, value);
     }
 
     /**
@@ -273,12 +273,13 @@
      * @exception IOException if there's any problem reported by the mail server
      * @see org.apache.tools.ant.taskdefs.email.Message
      */
-     public PrintStream getPrintStream() throws IOException {
+    public PrintStream getPrintStream() throws IOException {
         setFromHeader();
         setReplyToHeader();
         setToHeader();
         setCcHeader();
-        setHeader("X-Mailer", "org.apache.tools.mail.MailMessage (ant.apache.org)");
+        setHeader("X-Mailer",
+            "org.apache.tools.mail.MailMessage (ant.apache.org)");
         sendData();
         flushHeaders();
         return out;
@@ -309,29 +310,16 @@
         }
     }
 
-    String vectorToList(Vector v) {
-        StringBuffer buf = new StringBuffer();
-        Enumeration e = v.elements();
-        while (e.hasMoreElements()) {
-            buf.append(e.nextElement());
-            if (e.hasMoreElements()) {
-                buf.append(", ");
-            }
-        }
-        return buf.toString();
+    String vectorToList(Vector<String> v) {
+        return String.join(", ", v);
     }
 
-    void flushHeaders() {
-         // RFC 822 s4.1:
+    void flushHeaders() throws IOException {
+        // RFC 822 s4.1:
         //   "Header fields are NOT required to occur in any particular order,
         //    except that the message body MUST occur AFTER the headers"
         // (the same section specifies a recommended order, which we ignore)
-        final int size = headersKeys.size();
-        for (int i = 0; i < size; i++) {
-            String name = headersKeys.elementAt(i);
-            String value = headersValues.elementAt(i);
-            out.println(name + ": " + value);
-        }
+        headers.forEach((k, v) -> out.printf("%s: %s%n", k, v));
         out.println();
         out.flush();
     }
@@ -364,12 +352,12 @@
             if (c == '(') {
                 paramDepth++;
                 if (start == 0) {
-                    end = i;  // support "address (name)"
+                    end = i; // support "address (name)"
                 }
             } else if (c == ')') {
                 paramDepth--;
                 if (end == 0) {
-                    start = i + 1;  // support "(name) address"
+                    start = i + 1; // support "(name) address"
                 }
             } else if (paramDepth == 0 && c == '<') {
                 start = i + 1;
@@ -389,7 +377,8 @@
 
     void connect() throws IOException {
         socket = new Socket(host, port);
-        out = new MailPrintStream(new BufferedOutputStream(socket.getOutputStream()));
+        out = new MailPrintStream(
+            new BufferedOutputStream(socket.getOutputStream()));
         in = new SmtpResponseReader(socket.getInputStream());
         getReady();
     }
@@ -398,14 +387,15 @@
         String response = in.getResponse();
         int[] ok = {OK_READY};
         if (!isResponseOK(response, ok)) {
-            throw new IOException("Didn't get introduction from server: " + response);
+            throw new IOException(
+                "Didn't get introduction from server: " + response);
         }
     }
 
     void sendHelo() throws IOException {
-        String local = InetAddress.getLocalHost().getHostName();
+        String local = InetAddress.getLocalHost().getCanonicalHostName();
         int[] ok = {OK_HELO};
-         send("HELO " + local, ok);
+        send("HELO " + local, ok);
     }
 
     void sendFrom(String from) throws IOException {
@@ -425,7 +415,7 @@
 
     void sendDot() throws IOException {
         int[] ok = {OK_DOT};
-        send("\r\n.", ok);  // make sure dot is on new line
+        send("\r\n.", ok); // make sure dot is on new line
     }
 
     void sendQuit() throws IOException {
@@ -438,11 +428,11 @@
     }
 
     void send(String msg, int[] ok) throws IOException {
-        out.rawPrint(msg + "\r\n");  // raw supports <CRLF>.<CRLF>
+        out.rawPrint(msg + "\r\n"); // raw supports <CRLF>.<CRLF>
         String response = in.getResponse();
         if (!isResponseOK(response, ok)) {
-            throw new IOException("Unexpected reply to command: "
-                                  + msg + ": " + response);
+            throw new IOException(
+                "Unexpected reply to command: " + msg + ": " + response);
         }
     }
 
@@ -456,7 +446,7 @@
         return false;
     }
 
-    void disconnect() {
+    void disconnect() throws IOException {
         if (out != null) {
             out.close();
         }
@@ -486,17 +476,18 @@
     private int lastChar;
 
     public MailPrintStream(OutputStream out) {
-        super(out, true);  // deprecated, but email is byte-oriented
+        super(out, true); // deprecated, but email is byte-oriented
     }
 
     // Mac does \n\r, but that's tough to distinguish from Windows \r\n\r\n.
     // Don't tackle that problem right now.
+    @Override
     public void write(int b) {
         if (b == '\n' && lastChar != '\r') {
-            rawWrite('\r');  // ensure always \r\n
+            rawWrite('\r'); // ensure always \r\n
             rawWrite(b);
         } else if (b == '.' && lastChar == '\n') {
-            rawWrite('.');  // add extra dot
+            rawWrite('.'); // add extra dot
             rawWrite(b);
         } else {
             rawWrite(b);
@@ -504,6 +495,7 @@
         lastChar = b;
     }
 
+    @Override
     public void write(byte[] buf, int off, int len) {
         for (int i = 0; i < len; i++) {
             write(buf[off + i]);
diff --git a/src/main/org/apache/tools/mail/SmtpResponseReader.java b/src/main/org/apache/tools/mail/SmtpResponseReader.java
index 8178a86..f93ca6b 100644
--- a/src/main/org/apache/tools/mail/SmtpResponseReader.java
+++ b/src/main/org/apache/tools/mail/SmtpResponseReader.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,7 +35,6 @@
     // CheckStyle:VisibilityModifier OFF - bc
     protected BufferedReader reader = null;
     // CheckStyle:VisibilityModifier ON
-    private StringBuffer result = new StringBuffer();
 
     /**
      * Wrap this input stream.
@@ -54,17 +53,17 @@
      * @throws IOException on error.
      */
     public String getResponse() throws IOException {
-        result.setLength(0);
+        StringBuilder result = new StringBuilder();
         String line = reader.readLine();
         // CheckStyle:MagicNumber OFF
         if (line != null && line.length() >= 3) {
-            result.append(line.substring(0, 3));
+            result.append(line, 0, 3);
             result.append(" ");
         }
         // CheckStyle:MagicNumber ON
 
         while (line != null) {
-            append(line);
+            appendTo(result, line);
             if (!hasMoreLines(line)) {
                 break;
             }
@@ -95,11 +94,10 @@
     /**
      * Append the text from this line of the response.
      */
-    private void append(String line) {
+    private static void appendTo(StringBuilder target, String line) {
         // CheckStyle:MagicNumber OFF
         if (line.length() > 4) {
-            result.append(line.substring(4));
-            result.append(" ");
+            target.append(line.substring(4)).append(' ');
         }
         // CheckStyle:MagicNumber ON
     }
diff --git a/src/main/org/apache/tools/tar/TarArchiveSparseEntry.java b/src/main/org/apache/tools/tar/TarArchiveSparseEntry.java
index 2e76fb6..afc3905 100644
--- a/src/main/org/apache/tools/tar/TarArchiveSparseEntry.java
+++ b/src/main/org/apache/tools/tar/TarArchiveSparseEntry.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
diff --git a/src/main/org/apache/tools/tar/TarBuffer.java b/src/main/org/apache/tools/tar/TarBuffer.java
index 252d88c..fcea511 100644
--- a/src/main/org/apache/tools/tar/TarBuffer.java
+++ b/src/main/org/apache/tools/tar/TarBuffer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -270,12 +270,12 @@
                 if (offset == 0) {
                     // Ensure that we do not read gigabytes of zeros
                     // for a corrupt tar file.
-                    // See http://issues.apache.org/bugzilla/show_bug.cgi?id=39924
+                    // See https://issues.apache.org/bugzilla/show_bug.cgi?id=39924
                     return false;
                 }
                 // However, just leaving the unread portion of the buffer dirty does
                 // cause problems in some cases.  This problem is described in
-                // http://issues.apache.org/bugzilla/show_bug.cgi?id=29877
+                // https://issues.apache.org/bugzilla/show_bug.cgi?id=29877
                 //
                 // The solution is to fill the unused portion of the buffer with zeros.
 
diff --git a/src/main/org/apache/tools/tar/TarConstants.java b/src/main/org/apache/tools/tar/TarConstants.java
index 06d0fac..56362f7 100644
--- a/src/main/org/apache/tools/tar/TarConstants.java
+++ b/src/main/org/apache/tools/tar/TarConstants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -252,7 +252,7 @@
      */
     byte LF_GNUTYPE_SPARSE = (byte) 'S';
 
-    // See "http://www.opengroup.org/onlinepubs/009695399/utilities/pax.html#tag_04_100_13_02"
+    // See "https://www.opengroup.org/onlinepubs/009695399/utilities/pax.html#tag_04_100_13_02"
 
     /**
      * Identifies the entry as a Pax extended header.
diff --git a/src/main/org/apache/tools/tar/TarEntry.java b/src/main/org/apache/tools/tar/TarEntry.java
index af0db02..a47b256 100644
--- a/src/main/org/apache/tools/tar/TarEntry.java
+++ b/src/main/org/apache/tools/tar/TarEntry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,7 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 import java.util.Locale;
 
@@ -343,10 +343,7 @@
      */
     @Override
     public boolean equals(Object it) {
-        if (it == null || getClass() != it.getClass()) {
-            return false;
-        }
-        return equals((TarEntry) it);
+        return it != null && getClass() == it.getClass() && equals((TarEntry) it);
     }
 
     /**
@@ -377,7 +374,7 @@
      * @return This entry's name.
      */
     public String getName() {
-        return name.toString();
+        return name;
     }
 
     /**
@@ -402,7 +399,7 @@
      * Get this entry's link flag.
      *
      * @return This entry's link flag.
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public byte getLinkFlag() {
         return linkFlag;
@@ -412,7 +409,7 @@
      * Set this entry's link flag.
      *
      * @param link the link flag to use.
-     * @since 1.9.17
+     * @since 1.10.12
      */
     public void setLinkFlag(byte linkFlag) {
         this.linkFlag = linkFlag;
@@ -424,7 +421,7 @@
      * @return This entry's link name.
      */
     public String getLinkName() {
-        return linkName.toString();
+        return linkName;
     }
 
     /**
@@ -445,7 +442,7 @@
      */
     @Deprecated
     public int getUserId() {
-        return (int) (userId & 0xffffffff);
+        return (int) userId;
     }
 
     /**
@@ -486,7 +483,7 @@
      */
     @Deprecated
     public int getGroupId() {
-        return (int) (groupId & 0xffffffff);
+        return (int) groupId;
     }
 
     /**
@@ -524,7 +521,7 @@
      * @return This entry's user name.
      */
     public String getUserName() {
-        return userName.toString();
+        return userName;
     }
 
     /**
@@ -542,7 +539,7 @@
      * @return This entry's group name.
      */
     public String getGroupName() {
-        return groupName.toString();
+        return groupName;
     }
 
     /**
@@ -765,15 +762,7 @@
             return file.isDirectory();
         }
 
-        if (linkFlag == LF_DIR) {
-            return true;
-        }
-
-        if (getName().endsWith("/")) {
-            return true;
-        }
-
-        return false;
+        return linkFlag == LF_DIR || getName().endsWith("/");
     }
 
     /**
@@ -781,13 +770,8 @@
      * @return <i>true</i> if it is a 'normal' file
      */
     public boolean isFile() {
-        if (file != null) {
-            return file.isFile();
-        }
-        if (linkFlag == LF_OLDNORM || linkFlag == LF_NORMAL) {
-            return true;
-        }
-        return !getName().endsWith("/");
+        return file != null ? file.isFile()
+                : linkFlag == LF_OLDNORM || linkFlag == LF_NORMAL || !getName().endsWith("/");
     }
 
     /**
@@ -1029,9 +1013,9 @@
                 // SunOS tar -E does not add / to directory names, so fix
                 // up to be consistent
                 if (isDirectory() && !name.endsWith("/")) {
-                    name = name + "/";
+                    name += "/";
                 }
-                if (prefix.length() > 0) {
+                if (!prefix.isEmpty()) {
                     name = prefix + "/" + name;
                 }
             }
@@ -1108,13 +1092,7 @@
      */
     private static boolean matchAsciiBuffer(String expected, byte[] buffer,
                                             int offset, int length) {
-        byte[] buffer1;
-        try {
-            buffer1 = expected.getBytes("ASCII");
-        } catch (UnsupportedEncodingException e) {
-            // Should not happen
-            throw new RuntimeException(e); //NOSONAR
-        }
+        byte[] buffer1 = expected.getBytes(StandardCharsets.US_ASCII);
         return isEqual(buffer1, 0, buffer1.length, buffer, offset, length,
                        false);
     }
diff --git a/src/main/org/apache/tools/tar/TarInputStream.java b/src/main/org/apache/tools/tar/TarInputStream.java
index 966835e..71e4cc0 100644
--- a/src/main/org/apache/tools/tar/TarInputStream.java
+++ b/src/main/org/apache/tools/tar/TarInputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,9 +28,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import org.apache.tools.zip.ZipEncoding;
 import org.apache.tools.zip.ZipEncodingHelper;
@@ -295,9 +295,7 @@
         try {
             currEntry = new TarEntry(headerBuf, encoding);
         } catch (IllegalArgumentException e) {
-            IOException ioe = new IOException("Error detected parsing the header");
-            ioe.initCause(e);
-            throw ioe;
+            throw new IOException("Error detected parsing the header", e);
         }
         if (debug) {
             System.err.println("TarInputStream: SET CURRENTRY '"
@@ -421,7 +419,7 @@
     }
 
     Map<String, String> parsePaxHeaders(InputStream i) throws IOException {
-        Map<String, String> headers = new HashMap<String, String>();
+        Map<String, String> headers = new HashMap<>();
         // Format is "length keyword=value\n";
         while (true) { // get length
             int ch;
@@ -455,7 +453,7 @@
                             byte[] rest = bos.toByteArray();
                             // Drop trailing NL
                             String value = new String(rest, 0,
-                                                      restLen - 1, "UTF-8");
+                                                      restLen - 1, StandardCharsets.UTF_8);
                             headers.put(keyword, value);
                             break;
                         }
@@ -485,31 +483,40 @@
          * uid,uname
          * SCHILY.devminor, SCHILY.devmajor: don't have setters/getters for those
          */
-        for (Entry<String, String> ent : headers.entrySet()) {
-            String key = ent.getKey();
-            String val = ent.getValue();
-            if ("path".equals(key)) {
-                currEntry.setName(val);
-            } else if ("linkpath".equals(key)) {
-                currEntry.setLinkName(val);
-            } else if ("gid".equals(key)) {
-                currEntry.setGroupId(Long.parseLong(val));
-            } else if ("gname".equals(key)) {
-                currEntry.setGroupName(val);
-            } else if ("uid".equals(key)) {
-                currEntry.setUserId(Long.parseLong(val));
-            } else if ("uname".equals(key)) {
-                currEntry.setUserName(val);
-            } else if ("size".equals(key)) {
-                currEntry.setSize(Long.parseLong(val));
-            } else if ("mtime".equals(key)) {
-                currEntry.setModTime((long) (Double.parseDouble(val) * 1000));
-            } else if ("SCHILY.devminor".equals(key)) {
-                currEntry.setDevMinor(Integer.parseInt(val));
-            } else if ("SCHILY.devmajor".equals(key)) {
-                currEntry.setDevMajor(Integer.parseInt(val));
+        headers.forEach((key, val) -> {
+            switch (key) {
+                case "path":
+                    currEntry.setName(val);
+                    break;
+                case "linkpath":
+                    currEntry.setLinkName(val);
+                    break;
+                case "gid":
+                    currEntry.setGroupId(Long.parseLong(val));
+                    break;
+                case "gname":
+                    currEntry.setGroupName(val);
+                    break;
+                case "uid":
+                    currEntry.setUserId(Long.parseLong(val));
+                    break;
+                case "uname":
+                    currEntry.setUserName(val);
+                    break;
+                case "size":
+                    currEntry.setSize(Long.parseLong(val));
+                    break;
+                case "mtime":
+                    currEntry.setModTime((long) (Double.parseDouble(val) * 1000));
+                    break;
+                case "SCHILY.devminor":
+                    currEntry.setDevMinor(Integer.parseInt(val));
+                    break;
+                case "SCHILY.devmajor":
+                    currEntry.setDevMajor(Integer.parseInt(val));
+                    break;
             }
-        }
+        });
     }
 
     /**
diff --git a/src/main/org/apache/tools/tar/TarOutputStream.java b/src/main/org/apache/tools/tar/TarOutputStream.java
index d055caa..76460e9 100644
--- a/src/main/org/apache/tools/tar/TarOutputStream.java
+++ b/src/main/org/apache/tools/tar/TarOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,6 +28,8 @@
 import java.io.OutputStream;
 import java.io.StringWriter;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
@@ -282,13 +284,13 @@
         if (finished) {
             throw new IOException("Stream has already been finished");
         }
-        Map<String, String> paxHeaders = new HashMap<String, String>();
+        Map<String, String> paxHeaders = new HashMap<>();
         final String entryName = entry.getName();
         boolean paxHeaderContainsPath = handleLongName(entry, entryName, paxHeaders, "path",
                                                        TarConstants.LF_GNUTYPE_LONGNAME, "file name");
 
         final String linkName = entry.getLinkName();
-        boolean paxHeaderContainsLinkPath = linkName != null && linkName.length() > 0
+        boolean paxHeaderContainsLinkPath = linkName != null && !linkName.isEmpty()
             && handleLongName(entry, linkName, paxHeaders, "linkpath",
                               TarConstants.LF_GNUTYPE_LONGLINK, "link name");
 
@@ -500,7 +502,7 @@
                 + 3 /* blank, equals and newline */
                 + 2 /* guess 9 < actual length < 100 */;
             String line = len + " " + key + "=" + value + "\n";
-            int actualLength = line.getBytes("UTF-8").length;
+            int actualLength = line.getBytes(StandardCharsets.UTF_8).length;
             while (len != actualLength) {
                 // Adjust for cases where length < 10 or > 100
                 // or where UTF-8 encoding isn't a single octet
@@ -509,11 +511,11 @@
                 // first pass so we'd need a second.
                 len = actualLength;
                 line = len + " " + key + "=" + value + "\n";
-                actualLength = line.getBytes("UTF-8").length;
+                actualLength = line.getBytes(StandardCharsets.UTF_8).length;
             }
             w.write(line);
         }
-        byte[] data = w.toString().getBytes("UTF-8");
+        byte[] data = w.toString().getBytes(StandardCharsets.UTF_8);
         pex.setSize(data.length);
         putNextEntry(pex);
         write(data);
@@ -536,9 +538,7 @@
      * An EOF record consists of a record of all zeros.
      */
     private void writeEOFRecord() throws IOException {
-        for (int i = 0; i < recordBuf.length; ++i) {
-            recordBuf[i] = 0;
-        }
+        Arrays.fill(recordBuf, (byte) 0);
 
         buffer.writeRecord(recordBuf);
     }
diff --git a/src/main/org/apache/tools/tar/TarUtils.java b/src/main/org/apache/tools/tar/TarUtils.java
index fcd0c4e..b6e12c4 100644
--- a/src/main/org/apache/tools/tar/TarUtils.java
+++ b/src/main/org/apache/tools/tar/TarUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -62,8 +62,7 @@
             }
 
             public String decode(final byte[] buffer) {
-                final int length = buffer.length;
-                final StringBuilder result = new StringBuilder(length);
+                final StringBuilder result = new StringBuilder(buffer.length);
 
                 for (final byte b : buffer) {
                     if (b == 0) { // Trailing null
diff --git a/src/main/org/apache/tools/zip/AbstractUnicodeExtraField.java b/src/main/org/apache/tools/zip/AbstractUnicodeExtraField.java
index 0f236d4..109b173 100644
--- a/src/main/org/apache/tools/zip/AbstractUnicodeExtraField.java
+++ b/src/main/org/apache/tools/zip/AbstractUnicodeExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,7 @@
 
 package org.apache.tools.zip;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.zip.CRC32;
 import java.util.zip.ZipException;
 
@@ -51,12 +51,7 @@
         crc32.update(bytes, off, len);
         nameCRC32 = crc32.getValue();
 
-        try {
-            unicodeName = text.getBytes("UTF-8");
-        } catch (final UnsupportedEncodingException e) {
-            throw new RuntimeException("FATAL: UTF-8 encoding not supported.", //NOSONAR
-                                       e);
-        }
+        unicodeName = text.getBytes(StandardCharsets.UTF_8);
     }
 
     /**
diff --git a/src/main/org/apache/tools/zip/AsiExtraField.java b/src/main/org/apache/tools/zip/AsiExtraField.java
index 3f70aee..fdd81c6 100644
--- a/src/main/org/apache/tools/zip/AsiExtraField.java
+++ b/src/main/org/apache/tools/zip/AsiExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -241,7 +241,7 @@
      * @since 1.1
      */
     public boolean isLink() {
-        return getLinkedFile().length() != 0;
+        return !getLinkedFile().isEmpty();
     }
 
     /**
diff --git a/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java b/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java
index 738ed62..617474c 100644
--- a/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java
+++ b/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/ExtraFieldUtils.java b/src/main/org/apache/tools/zip/ExtraFieldUtils.java
index 18bb850..ab9a32e 100644
--- a/src/main/org/apache/tools/zip/ExtraFieldUtils.java
+++ b/src/main/org/apache/tools/zip/ExtraFieldUtils.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.zip;
 
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -41,7 +42,7 @@
     private static final Map<ZipShort, Class<?>> implementations;
 
     static {
-        implementations = new ConcurrentHashMap<ZipShort, Class<?>>();
+        implementations = new ConcurrentHashMap<>();
         register(AsiExtraField.class);
         register(JarMarker.class);
         register(UnicodePathExtraField.class);
@@ -60,14 +61,19 @@
      */
     public static void register(Class<?> c) {
         try {
-            ZipExtraField ze = (ZipExtraField) c.newInstance();
+            ZipExtraField ze = (ZipExtraField) c.getDeclaredConstructor().newInstance();
             implementations.put(ze.getHeaderId(), c);
         } catch (ClassCastException cc) {
-            throw new RuntimeException(c + " doesn\'t implement ZipExtraField"); //NOSONAR
+            throw new RuntimeException(c + " doesn't implement ZipExtraField"); //NOSONAR
         } catch (InstantiationException ie) {
             throw new RuntimeException(c + " is not a concrete class"); //NOSONAR
         } catch (IllegalAccessException ie) {
-            throw new RuntimeException(c + "\'s no-arg constructor is not public"); //NOSONAR
+            throw new RuntimeException(c + "'s no-arg constructor is not public"); //NOSONAR
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(c + "'s no-arg constructor not found"); //NOSONAR
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException(c + "'s no-arg constructor threw an exception:"
+                    + e.getMessage()); //NOSONAR
         }
     }
 
@@ -84,7 +90,16 @@
         throws InstantiationException, IllegalAccessException {
         Class<?> c = implementations.get(headerId);
         if (c != null) {
-            return (ZipExtraField) c.newInstance();
+            // wrap extra exceptions to preserve method signature
+            try {
+                return (ZipExtraField) c.getDeclaredConstructor().newInstance();
+            } catch (InvocationTargetException e) {
+                throw (InstantiationException)
+                        new InstantiationException().initCause(e.getTargetException());
+            } catch (NoSuchMethodException e) {
+                throw (InstantiationException)
+                        new InstantiationException().initCause(e);
+            }
         }
         UnrecognizedExtraField u = new UnrecognizedExtraField();
         u.setHeaderId(headerId);
@@ -133,7 +148,7 @@
     public static ZipExtraField[] parse(byte[] data, boolean local,
                                         UnparseableExtraField onUnparseableData)
         throws ZipException {
-        List<ZipExtraField> v = new ArrayList<ZipExtraField>();
+        List<ZipExtraField> v = new ArrayList<>();
         int start = 0;
         LOOP:
         while (start <= data.length - WORD) {
@@ -174,10 +189,8 @@
                         .parseFromCentralDirectoryData(data, start + WORD, length);
                 }
                 v.add(ze);
-            } catch (InstantiationException ie) {
+            } catch (InstantiationException | IllegalAccessException ie) {
                 throw new ZipException(ie.getMessage());
-            } catch (IllegalAccessException iae) {
-                throw new ZipException(iae.getMessage());
             }
             start += (length + WORD);
         }
diff --git a/src/main/org/apache/tools/zip/FallbackZipEncoding.java b/src/main/org/apache/tools/zip/FallbackZipEncoding.java
index 7e0f315..19a5a0f 100644
--- a/src/main/org/apache/tools/zip/FallbackZipEncoding.java
+++ b/src/main/org/apache/tools/zip/FallbackZipEncoding.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
diff --git a/src/main/org/apache/tools/zip/GeneralPurposeBit.java b/src/main/org/apache/tools/zip/GeneralPurposeBit.java
index f5f353c..8821749 100644
--- a/src/main/org/apache/tools/zip/GeneralPurposeBit.java
+++ b/src/main/org/apache/tools/zip/GeneralPurposeBit.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -151,7 +151,7 @@
      * @param buf the output buffer
      * @param offset
      *         The offset within the output buffer of the first byte to be written.
-     *         must be non-negative and no larger than <tt>buf.length-2</tt>
+     *         must be non-negative and no larger than <code>buf.length-2</code>
      */
     public void encode(byte[] buf, int offset) {
         ZipShort.putShort((dataDescriptorFlag ? DATA_DESCRIPTOR_FLAG : 0)
@@ -189,14 +189,15 @@
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof GeneralPurposeBit)) {
-            return false;
+        if (o instanceof GeneralPurposeBit) {
+            GeneralPurposeBit g = (GeneralPurposeBit) o;
+            return g.encryptionFlag == encryptionFlag
+                    && g.strongEncryptionFlag == strongEncryptionFlag
+                    && g.languageEncodingFlag == languageEncodingFlag
+                    && g.dataDescriptorFlag == dataDescriptorFlag;
         }
-        GeneralPurposeBit g = (GeneralPurposeBit) o;
-        return g.encryptionFlag == encryptionFlag
-            && g.strongEncryptionFlag == strongEncryptionFlag
-            && g.languageEncodingFlag == languageEncodingFlag
-            && g.dataDescriptorFlag == dataDescriptorFlag;
+
+        return false;
     }
 
     @Override
diff --git a/src/main/org/apache/tools/zip/JarMarker.java b/src/main/org/apache/tools/zip/JarMarker.java
index c063353..be967e0 100644
--- a/src/main/org/apache/tools/zip/JarMarker.java
+++ b/src/main/org/apache/tools/zip/JarMarker.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/NioZipEncoding.java b/src/main/org/apache/tools/zip/NioZipEncoding.java
index f566615..e2f5d62 100644
--- a/src/main/org/apache/tools/zip/NioZipEncoding.java
+++ b/src/main/org/apache/tools/zip/NioZipEncoding.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
@@ -102,8 +102,8 @@
             }
         }
 
-        out.limit(out.position());
-        out.rewind();
+        ZipEncodingHelper.prepareBufferForRead(out);
+
         return out;
     }
 
diff --git a/src/main/org/apache/tools/zip/Simple8BitZipEncoding.java b/src/main/org/apache/tools/zip/Simple8BitZipEncoding.java
index 789c045..629f0b6 100644
--- a/src/main/org/apache/tools/zip/Simple8BitZipEncoding.java
+++ b/src/main/org/apache/tools/zip/Simple8BitZipEncoding.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
@@ -26,19 +26,19 @@
 import java.util.List;
 
 /**
- * This ZipEncoding implementation implements a simple 8bit character
- * set, which mets the following restrictions:
+ * This ZipEncoding implementation implements a simple 8 bit character
+ * set, which meets the following restrictions:
  *
  * <ul>
  * <li>Characters 0x0000 to 0x007f are encoded as the corresponding
  *        byte values 0x00 to 0x7f.</li>
- * <li>All byte codes from 0x80 to 0xff are mapped to a unique unicode
+ * <li>All byte codes from 0x80 to 0xff are mapped to a unique Unicode
  *       character in the range 0x0080 to 0x7fff. (No support for
  *       UTF-16 surrogates)
  * </ul>
  *
  * <p>These restrictions most notably apply to the most prominent
- * omissions of java-1.4's {@link java.nio.charset.Charset Charset}
+ * omissions of Java 1.4 {@link java.nio.charset.Charset Charset}
  * implementation, Cp437 and Cp850.</p>
  *
  * <p>The methods of this class are reentrant.</p>
@@ -103,7 +103,7 @@
     public Simple8BitZipEncoding(final char[] highChars) {
         this.highChars = highChars.clone();
         final List<Simple8BitChar> temp =
-            new ArrayList<Simple8BitChar>(this.highChars.length);
+                new ArrayList<>(this.highChars.length);
 
         byte code = 127;
 
@@ -247,8 +247,7 @@
             }
         }
 
-        out.limit(out.position());
-        out.rewind();
+        ZipEncodingHelper.prepareBufferForRead(out);
         return out;
     }
 
diff --git a/src/main/org/apache/tools/zip/UnicodeCommentExtraField.java b/src/main/org/apache/tools/zip/UnicodeCommentExtraField.java
index 62be2a3..70a34d2 100644
--- a/src/main/org/apache/tools/zip/UnicodeCommentExtraField.java
+++ b/src/main/org/apache/tools/zip/UnicodeCommentExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,7 +24,7 @@
  * <p>Stores the UTF-8 version of the file comment as stored in the
  * central directory header.</p>
  *
- * <p>See <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
+ * <p>See <a href="https://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  * APPNOTE.TXT, section 4.6.8</a>.</p>
  *
  */
diff --git a/src/main/org/apache/tools/zip/UnicodePathExtraField.java b/src/main/org/apache/tools/zip/UnicodePathExtraField.java
index 7638edd..16496a8 100644
--- a/src/main/org/apache/tools/zip/UnicodePathExtraField.java
+++ b/src/main/org/apache/tools/zip/UnicodePathExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,7 +24,7 @@
  * <p>Stores the UTF-8 version of the file name field as stored in the
  * local header and central directory header.</p>
  *
- * <p>See <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
+ * <p>See <a href="https://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  * APPNOTE.TXT, section 4.6.9</a>.</p>
  */
 public class UnicodePathExtraField extends AbstractUnicodeExtraField {
diff --git a/src/main/org/apache/tools/zip/UnixStat.java b/src/main/org/apache/tools/zip/UnixStat.java
index 0863759..17fac41 100644
--- a/src/main/org/apache/tools/zip/UnixStat.java
+++ b/src/main/org/apache/tools/zip/UnixStat.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/UnparseableExtraFieldData.java b/src/main/org/apache/tools/zip/UnparseableExtraFieldData.java
index 5c1a8d0..3063827 100644
--- a/src/main/org/apache/tools/zip/UnparseableExtraFieldData.java
+++ b/src/main/org/apache/tools/zip/UnparseableExtraFieldData.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
@@ -22,7 +22,7 @@
  * Wrapper for extra field data that doesn't conform to the recommended format of header-tag + size + data.
  *
  * <p>The header-id is artificial (and not listed as a known ID in
- * <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">APPNOTE.TXT</a>).
+ * <a href="https://www.pkware.com/documents/casestudies/APPNOTE.TXT">APPNOTE.TXT</a>).
  * Since it isn't used anywhere except to satisfy the
  * ZipExtraField contract it shouldn't matter anyway.</p>
  *
diff --git a/src/main/org/apache/tools/zip/UnrecognizedExtraField.java b/src/main/org/apache/tools/zip/UnrecognizedExtraField.java
index 0e4262d..277332f 100644
--- a/src/main/org/apache/tools/zip/UnrecognizedExtraField.java
+++ b/src/main/org/apache/tools/zip/UnrecognizedExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/UnsupportedZipFeatureException.java b/src/main/org/apache/tools/zip/UnsupportedZipFeatureException.java
index 34e2117..d9fbd24 100644
--- a/src/main/org/apache/tools/zip/UnsupportedZipFeatureException.java
+++ b/src/main/org/apache/tools/zip/UnsupportedZipFeatureException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.zip;
 
+import java.io.Serializable;
 import java.util.zip.ZipException;
 
 /**
@@ -66,7 +67,7 @@
      * ZIP Features that may or may not be supported.
      */
     @SuppressWarnings("serial")
-    public static class Feature implements java.io.Serializable {
+    public static class Feature implements Serializable {
         /**
          * The entry is encrypted.
          */
diff --git a/src/main/org/apache/tools/zip/Zip64ExtendedInformationExtraField.java b/src/main/org/apache/tools/zip/Zip64ExtendedInformationExtraField.java
index 40a4e4b..dd58b62 100644
--- a/src/main/org/apache/tools/zip/Zip64ExtendedInformationExtraField.java
+++ b/src/main/org/apache/tools/zip/Zip64ExtendedInformationExtraField.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
@@ -27,7 +27,7 @@
  * Holds size and other extended information for entries that use Zip64
  * features.
  *
- * <p>See <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
+ * <p>See <a href="https://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  * APPNOTE.TXT, section 4.5.3</a>.</p>
  *
  * <p>Currently Ant doesn't support encrypting the
diff --git a/src/main/org/apache/tools/zip/Zip64Mode.java b/src/main/org/apache/tools/zip/Zip64Mode.java
index 30d9f1c..0107804 100644
--- a/src/main/org/apache/tools/zip/Zip64Mode.java
+++ b/src/main/org/apache/tools/zip/Zip64Mode.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/Zip64RequiredException.java b/src/main/org/apache/tools/zip/Zip64RequiredException.java
index f7fb779..4a66b64 100644
--- a/src/main/org/apache/tools/zip/Zip64RequiredException.java
+++ b/src/main/org/apache/tools/zip/Zip64RequiredException.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/ZipConstants.java b/src/main/org/apache/tools/zip/ZipConstants.java
index 83ae956..c36c801 100644
--- a/src/main/org/apache/tools/zip/ZipConstants.java
+++ b/src/main/org/apache/tools/zip/ZipConstants.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/ZipEightByteInteger.java b/src/main/org/apache/tools/zip/ZipEightByteInteger.java
index ca29160..4a2f93c 100644
--- a/src/main/org/apache/tools/zip/ZipEightByteInteger.java
+++ b/src/main/org/apache/tools/zip/ZipEightByteInteger.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -207,10 +207,8 @@
      */
     @Override
     public boolean equals(Object o) {
-        if (o == null || !(o instanceof ZipEightByteInteger)) {
-            return false;
-        }
-        return value.equals(((ZipEightByteInteger) o).getValue());
+        return o instanceof ZipEightByteInteger
+                && value.equals(((ZipEightByteInteger) o).getValue());
     }
 
     /**
diff --git a/src/main/org/apache/tools/zip/ZipEncoding.java b/src/main/org/apache/tools/zip/ZipEncoding.java
index 1e0034a..5a9fd03 100644
--- a/src/main/org/apache/tools/zip/ZipEncoding.java
+++ b/src/main/org/apache/tools/zip/ZipEncoding.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
diff --git a/src/main/org/apache/tools/zip/ZipEncodingHelper.java b/src/main/org/apache/tools/zip/ZipEncodingHelper.java
index b9d4447..be6b0ec 100644
--- a/src/main/org/apache/tools/zip/ZipEncodingHelper.java
+++ b/src/main/org/apache/tools/zip/ZipEncodingHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.zip;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.UnsupportedCharsetException;
@@ -66,8 +67,7 @@
     private static final Map<String, SimpleEncodingHolder> simpleEncodings;
 
     static {
-        final Map<String, SimpleEncodingHolder> se =
-            new HashMap<String, SimpleEncodingHolder>();
+        final Map<String, SimpleEncodingHolder> se = new HashMap<>();
 
         final char[] cp437_high_chars =
             new char[] {0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0,
@@ -148,15 +148,25 @@
      *
      */
     static ByteBuffer growBuffer(final ByteBuffer b, final int newCapacity) {
-        b.limit(b.position());
-        b.rewind();
-
+    	prepareBufferForRead(b);
         final int c2 = b.capacity() * 2;
         final ByteBuffer on = ByteBuffer.allocate(c2 < newCapacity ? newCapacity : c2);
 
         on.put(b);
         return on;
     }
+    
+    /**
+     * Prepares a buffer to be read after writing.
+     * 
+     * @param b The buffer
+     */
+    static void prepareBufferForRead(final Buffer b) {
+    	// ByteBuffer has overridden methods in java 11 but not in java 8 
+    	// so the Buffer is significant to get java 8 compatible classes
+    	b.limit(b.position());
+    	b.rewind();
+    }
 
 
     /**
diff --git a/src/main/org/apache/tools/zip/ZipEntry.java b/src/main/org/apache/tools/zip/ZipEntry.java
index 4d619d3..a1afbda 100644
--- a/src/main/org/apache/tools/zip/ZipEntry.java
+++ b/src/main/org/apache/tools/zip/ZipEntry.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.zip.ZipException;
 
 /**
@@ -30,7 +31,7 @@
  * access to the internal and external file attributes.
  *
  * <p>The extra data is expected to follow the recommendation of
- * <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">APPNOTE.txt</a>:</p>
+ * <a href="https://www.pkware.com/documents/casestudies/APPNOTE.TXT">APPNOTE.txt</a>:</p>
  * <ul>
  *   <li>the extra byte array consists of a sequence of extra fields</li>
  *   <li>each extra fields starts by a two byte header id followed by
@@ -168,7 +169,7 @@
     }
 
     /**
-     * Overwrite clone.
+     * Override clone.
      *
      * @return a cloned copy of this ZipEntry
      * @since 1.1
@@ -307,7 +308,7 @@
      * @since 1.1
      */
     public void setExtraFields(final ZipExtraField[] fields) {
-        List<ZipExtraField> newFields = new ArrayList<ZipExtraField>();
+        List<ZipExtraField> newFields = new ArrayList<>();
         for (ZipExtraField field : fields) {
             if (field instanceof UnparseableExtraFieldData) {
                 unparseableExtra = (UnparseableExtraFieldData) field;
@@ -315,7 +316,7 @@
                 newFields.add(field);
             }
         }
-        extraFields = newFields.toArray(new ZipExtraField[newFields.size()]);
+        extraFields = newFields.toArray(new ZipExtraField[0]);
         setExtra();
     }
 
@@ -455,18 +456,18 @@
      */
     public void removeExtraField(final ZipShort type) {
         if (extraFields == null) {
-            throw new java.util.NoSuchElementException();
+            throw new NoSuchElementException();
         }
-        List<ZipExtraField> newResult = new ArrayList<ZipExtraField>();
+        List<ZipExtraField> newResult = new ArrayList<>();
         for (ZipExtraField extraField : extraFields) {
             if (!type.equals(extraField.getHeaderId())) {
                 newResult.add(extraField);
             }
         }
         if (extraFields.length == newResult.size()) {
-            throw new java.util.NoSuchElementException();
+            throw new NoSuchElementException();
         }
-        extraFields = newResult.toArray(new ZipExtraField[newResult.size()]);
+        extraFields = newResult.toArray(new ZipExtraField[0]);
         setExtra();
     }
 
@@ -475,7 +476,7 @@
      */
     public void removeUnparseableExtraFieldData() {
         if (unparseableExtra == null) {
-            throw new java.util.NoSuchElementException();
+            throw new NoSuchElementException();
         }
         unparseableExtra = null;
         setExtra();
@@ -485,7 +486,7 @@
      * Looks up an extra field by its header id.
      *
      * @param type ZipShort
-     * @return null if no such field exists.
+     * @return {@code null} if no such field exists.
      */
     public ZipExtraField getExtraField(final ZipShort type) {
         if (extraFields != null) {
@@ -501,7 +502,7 @@
     /**
      * Looks up extra field data that couldn't be parsed correctly.
      *
-     * @return null if no such field exists.
+     * @return {@code null} if no such field exists.
      */
     public UnparseableExtraFieldData getUnparseableExtraFieldData() {
         return unparseableExtra;
@@ -545,7 +546,7 @@
     /**
      * Sets the central directory part of extra fields.
      *
-     * @param b boolean
+     * @param b {@code boolean}
      */
     public void setCentralDirectoryExtra(final byte[] b) {
         try {
@@ -586,7 +587,7 @@
      *
      * @param size the size to use
      * @deprecated since 1.7.
-     *             Use setCompressedSize directly.
+     *             Use {@link #setCompressedSize(long)} directly.
      * @since 1.2
      */
     @Deprecated
@@ -608,7 +609,7 @@
     /**
      * Is this entry a directory?
      *
-     * @return true if the entry is a directory
+     * @return {@code true} if the entry is a directory
      * @since 1.10
      */
     @Override
@@ -744,8 +745,7 @@
                     addExtraField(element);
                 } else {
                     if (local
-                        || !(existing
-                             instanceof CentralDirectoryParsingZipExtraField)) {
+                        || !(existing instanceof CentralDirectoryParsingZipExtraField)) {
                         final byte[] b = element.getLocalFileDataData();
                         existing.parseFromLocalFileData(b, 0, b.length);
                     } else {
@@ -759,13 +759,17 @@
         }
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Get last modified time as {@link Date}.
+     *
+     * @return {@link Date}
+     */
     public Date getLastModifiedDate() {
         return new Date(getTime());
     }
 
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
+    /**
+     * {@inheritDoc}
      */
     @Override
     public boolean equals(final Object obj) {
diff --git a/src/main/org/apache/tools/zip/ZipExtraField.java b/src/main/org/apache/tools/zip/ZipExtraField.java
index 649fca0..e17a07b 100644
--- a/src/main/org/apache/tools/zip/ZipExtraField.java
+++ b/src/main/org/apache/tools/zip/ZipExtraField.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/main/org/apache/tools/zip/ZipFile.java b/src/main/org/apache/tools/zip/ZipFile.java
index 1eccb2c..8806ae7 100644
--- a/src/main/org/apache/tools/zip/ZipFile.java
+++ b/src/main/org/apache/tools/zip/ZipFile.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,10 +35,10 @@
 import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 import java.util.zip.Inflater;
 import java.util.zip.InflaterInputStream;
 import java.util.zip.ZipException;
@@ -86,13 +86,13 @@
      * List of entries in the order they appear inside the central
      * directory.
      */
-    private final List<ZipEntry> entries = new LinkedList<ZipEntry>();
+    private final List<ZipEntry> entries = new LinkedList<>();
 
     /**
      * Maps String to list of ZipEntrys, name -> actual entries.
      */
     private final Map<String, LinkedList<ZipEntry>> nameMap =
-        new HashMap<String, LinkedList<ZipEntry>>(HASH_SIZE);
+        new HashMap<>(HASH_SIZE);
 
     private static final class OffsetEntry {
         private long headerOffset = -1;
@@ -103,7 +103,8 @@
      * The encoding to use for filenames and the file comment.
      *
      * <p>For a list of possible values see <a
-     * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.
+     * href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+     * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.
      * Defaults to the platform's default character encoding.</p>
      */
     private final String encoding;
@@ -241,6 +242,7 @@
      * Closes the archive.
      * @throws IOException if an error occurs closing the archive.
      */
+    @Override
     public void close() throws IOException {
         // this flag is only written here and read in finalize() which
         // can never be run in parallel.
@@ -288,9 +290,8 @@
      * @since Ant 1.9.0
      */
     public Enumeration<ZipEntry> getEntriesInPhysicalOrder() {
-        final ZipEntry[] allEntries = entries.toArray(new ZipEntry[0]);
-        Arrays.sort(allEntries, OFFSET_COMPARATOR);
-        return Collections.enumeration(Arrays.asList(allEntries));
+        return entries.stream().sorted(OFFSET_COMPARATOR).collect(Collectors
+            .collectingAndThen(Collectors.toList(), Collections::enumeration));
     }
 
     /**
@@ -322,7 +323,7 @@
     public Iterable<ZipEntry> getEntries(final String name) {
         final List<ZipEntry> entriesOfThatName = nameMap.get(name);
         return entriesOfThatName != null ? entriesOfThatName
-            : Collections.<ZipEntry>emptyList();
+            : Collections.emptyList();
     }
 
     /**
@@ -335,12 +336,11 @@
      * @since 1.9.2
      */
     public Iterable<ZipEntry> getEntriesInPhysicalOrder(final String name) {
-        ZipEntry[] entriesOfThatName = new ZipEntry[0];
         if (nameMap.containsKey(name)) {
-            entriesOfThatName = nameMap.get(name).toArray(entriesOfThatName);
-            Arrays.sort(entriesOfThatName, OFFSET_COMPARATOR);
+            return nameMap.get(name).stream().sorted(OFFSET_COMPARATOR)
+                .collect(Collectors.toList());
         }
-        return Arrays.asList(entriesOfThatName);
+        return Collections.emptyList();
     }
 
     /**
@@ -396,6 +396,10 @@
         }
     }
 
+    public String getName() {
+        return archiveName;
+    }
+
     /**
      * Ensures that the close method of this zipfile is called when
      * there are no more references to it.
@@ -405,8 +409,8 @@
     protected void finalize() throws Throwable {
         try {
             if (!closed) {
-                System.err.println("Cleaning up unclosed ZipFile for archive "
-                                   + archiveName);
+                System.err.printf("Cleaning up unclosed %s for archive %s%n",
+                    getClass().getSimpleName(), archiveName);
                 close();
             }
         } finally {
@@ -452,8 +456,7 @@
      */
     private Map<ZipEntry, NameAndComment> populateFromCentralDirectory()
         throws IOException {
-        final HashMap<ZipEntry, NameAndComment> noUTF8Flag =
-            new HashMap<ZipEntry, NameAndComment>();
+        final Map<ZipEntry, NameAndComment> noUTF8Flag = new HashMap<>();
 
         positionAtCentralDirectory();
 
@@ -461,8 +464,8 @@
         long sig = ZipLong.getValue(WORD_BUF);
 
         if (sig != CFH_SIG && startsWithLocalFileHeader()) {
-            throw new IOException("central directory is empty, can't expand"
-                                  + " corrupt archive.");
+            throw new IOException(
+                "central directory is empty, can't expand corrupt archive.");
         }
 
         while (sig == CFH_SIG) {
@@ -474,7 +477,7 @@
     }
 
     /**
-     * Reads an individual entry of the central directory, creats an
+     * Reads an individual entry of the central directory, creates an
      * ZipEntry from it and adds it to the global maps.
      *
      * @param noUTF8Flag map used to collect entries that don't have
@@ -753,8 +756,8 @@
         archive.seek(ZipEightByteInteger.getLongValue(DWORD_BUF));
         archive.readFully(WORD_BUF);
         if (!Arrays.equals(WORD_BUF, ZipOutputStream.ZIP64_EOCD_SIG)) {
-            throw new ZipException("archive's ZIP64 end of central "
-                                   + "directory locator is corrupt.");
+            throw new ZipException(
+                "archive's ZIP64 end of central directory locator is corrupt.");
         }
         skipBytes(ZIP64_EOCD_CFD_LOCATOR_OFFSET
                   - WORD /* signature has already been read */);
@@ -789,7 +792,7 @@
 
     /**
      * Searches the archive backwards from minDistance to maxDistance
-     * for the given signature, positions the RandomaccessFile right
+     * for the given signature, positions the RandomAccessFile right
      * at the signature if it has been found.
      */
     private boolean tryToLocateSignature(final long minDistanceFromEnd,
@@ -867,10 +870,10 @@
     private void resolveLocalFileHeaderData(final Map<ZipEntry, NameAndComment>
                                             entriesWithoutUTF8Flag)
         throws IOException {
-        for (final Iterator<ZipEntry> it = entries.iterator(); it.hasNext();) {
+        for (ZipEntry zipEntry : entries) {
             // entries is filled in populateFromCentralDirectory and
             // never modified
-            final Entry ze = (Entry) it.next();
+            final Entry ze = (Entry) zipEntry;
             final OffsetEntry offsetEntry = ze.getOffsetEntry();
             final long offset = offsetEntry.headerOffset;
             archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH);
@@ -882,8 +885,8 @@
             while (lenToSkip > 0) {
                 final int skipped = archive.skipBytes(lenToSkip);
                 if (skipped <= 0) {
-                    throw new IOException("failed to skip file name in"
-                                          + " local file header");
+                    throw new IOException(
+                        "failed to skip file name in local file header");
                 }
                 lenToSkip -= skipped;
             }
@@ -909,11 +912,7 @@
             }
 
             final String name = ze.getName();
-            LinkedList<ZipEntry> entriesOfThatName = nameMap.get(name);
-            if (entriesOfThatName == null) {
-                entriesOfThatName = new LinkedList<ZipEntry>();
-                nameMap.put(name, entriesOfThatName);
-            }
+            LinkedList<ZipEntry> entriesOfThatName = nameMap.computeIfAbsent(name, k -> new LinkedList<>());
             entriesOfThatName.addLast(ze);
         }
     }
@@ -976,7 +975,7 @@
             if (len > remaining) {
                 len = (int) remaining;
             }
-            int ret = -1;
+            int ret;
             synchronized (archive) {
                 archive.seek(loc);
                 ret = archive.read(b, off, len);
@@ -1014,25 +1013,22 @@
      *
      * @since Ant 1.9.0
      */
-    private final Comparator<ZipEntry> OFFSET_COMPARATOR =
-        new Comparator<ZipEntry>() {
-        public int compare(final ZipEntry e1, final ZipEntry e2) {
-            if (e1 == e2) {
-                return 0;
-            }
-
-            final Entry ent1 = e1 instanceof Entry ? (Entry) e1 : null;
-            final Entry ent2 = e2 instanceof Entry ? (Entry) e2 : null;
-            if (ent1 == null) {
-                return 1;
-            }
-            if (ent2 == null) {
-                return -1;
-            }
-            final long val = (ent1.getOffsetEntry().headerOffset
-                        - ent2.getOffsetEntry().headerOffset);
-            return val == 0 ? 0 : val < 0 ? -1 : +1;
+    private final Comparator<ZipEntry> OFFSET_COMPARATOR = (e1, e2) -> {
+        if (e1 == e2) {
+            return 0;
         }
+
+        final Entry ent1 = e1 instanceof Entry ? (Entry) e1 : null;
+        final Entry ent2 = e2 instanceof Entry ? (Entry) e2 : null;
+        if (ent1 == null) {
+            return 1;
+        }
+        if (ent2 == null) {
+            return -1;
+        }
+        final long val = (ent1.getOffsetEntry().headerOffset
+                    - ent2.getOffsetEntry().headerOffset);
+        return val == 0 ? 0 : val < 0 ? -1 : +1;
     };
 
     /**
diff --git a/src/main/org/apache/tools/zip/ZipLong.java b/src/main/org/apache/tools/zip/ZipLong.java
index 5932f84..2142eff 100644
--- a/src/main/org/apache/tools/zip/ZipLong.java
+++ b/src/main/org/apache/tools/zip/ZipLong.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -124,7 +124,7 @@
      * @param buf the output buffer
      * @param  offset
      *         The offset within the output buffer of the first byte to be written.
-     *         must be non-negative and no larger than <tt>buf.length-4</tt>
+     *         must be non-negative and no larger than <code>buf.length-4</code>
      */
     public static void putLong(long value, byte[] buf, int offset) {
         buf[offset++] = (byte) ((value & BYTE_MASK));
@@ -168,10 +168,7 @@
      */
     @Override
     public boolean equals(Object o) {
-        if (o == null || !(o instanceof ZipLong)) {
-            return false;
-        }
-        return value == ((ZipLong) o).getValue();
+        return o instanceof ZipLong && value == ((ZipLong) o).getValue();
     }
 
     /**
diff --git a/src/main/org/apache/tools/zip/ZipOutputStream.java b/src/main/org/apache/tools/zip/ZipOutputStream.java
index ef850ee..9e216d8 100644
--- a/src/main/org/apache/tools/zip/ZipOutputStream.java
+++ b/src/main/org/apache/tools/zip/ZipOutputStream.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,12 +31,12 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
+import java.nio.file.Files;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
@@ -196,7 +196,7 @@
      *
      * @since 1.1
      */
-    private final List<ZipEntry> entries = new LinkedList<ZipEntry>();
+    private final List<ZipEntry> entries = new LinkedList<>();
 
     /**
      * CRC instance to avoid parsing DEFLATED data twice.
@@ -247,13 +247,14 @@
      *
      * @since 1.1
      */
-    private final Map<ZipEntry, Long> offsets = new HashMap<ZipEntry, Long>();
+    private final Map<ZipEntry, Long> offsets = new HashMap<>();
 
     /**
      * The encoding to use for filenames and the file comment.
      *
      * <p>For a list of possible values see <a
-     * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.
+     * href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+     * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.
      * Defaults to the platform's default character encoding.</p>
      *
      * @since 1.3
@@ -325,6 +326,11 @@
     private final Calendar calendarInstance = Calendar.getInstance();
 
     /**
+     * Temporary buffer used for the {@link #write(int)} method.
+     */
+    private final byte[] oneByte = new byte[1];
+
+    /**
      * Creates a new ZIP OutputStream filtering the underlying stream.
      * @param out the outputstream to zip
      * @since 1.1
@@ -343,22 +349,22 @@
      */
     public ZipOutputStream(File file) throws IOException {
         super(null);
-        RandomAccessFile _raf = null;
+        RandomAccessFile ranf = null;
         try {
-            _raf = new RandomAccessFile(file, "rw");
-            _raf.setLength(0);
+            ranf = new RandomAccessFile(file, "rw");
+            ranf.setLength(0);
         } catch (IOException e) {
-            if (_raf != null) {
+            if (ranf != null) {
                 try {
-                    _raf.close();
+                    ranf.close();
                 } catch (IOException inner) { // NOPMD
                     // ignore
                 }
-                _raf = null;
+                ranf = null;
             }
-            out = new FileOutputStream(file);
+            out = Files.newOutputStream(file.toPath());
         }
-        raf = _raf;
+        raf = ranf;
     }
 
     /**
@@ -379,7 +385,8 @@
      * The encoding to use for filenames and the file comment.
      *
      * <p>For a list of possible values see <a
-     * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.
+     * href="https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html">
+     * https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html</a>.
      * Defaults to the platform's default character encoding.</p>
      * @param encoding the encoding value
      * @since 1.3
@@ -488,7 +495,8 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Finish writing the archive.
+     *
      * @throws Zip64RequiredException if the archive's size exceeds 4
      * GByte or there are more than 65535 entries inside the archive
      * and {@link #setUseZip64} is {@link Zip64Mode#Never}.
@@ -721,7 +729,8 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Put the specified entry into the archive.
+     *
      * @throws Zip64RequiredException if the entry's uncompressed or
      * compressed size is known to exceed 4 GByte and {@link #setUseZip64}
      * is {@link Zip64Mode#Never}.
@@ -900,6 +909,19 @@
     }
 
     /**
+     * Writes a byte to ZIP entry.
+     *
+     * @param b the byte to write
+     * @throws IOException on error
+     * @since Ant 1.10.10
+     */
+    @Override
+    public void write(int b) throws IOException {
+        oneByte[0] = (byte) (b & 0xff);
+        write(oneByte, 0, 1);
+    }
+
+    /**
      * Writes bytes to ZIP entry.
      *
      * @param b the byte array to write
@@ -1151,20 +1173,16 @@
         }
 
         String comm = ze.getComment();
-        if (comm != null && !"".equals(comm)) {
+        if (comm == null || comm.isEmpty()) {
+            return;
+        }
 
-            boolean commentEncodable = zipEncoding.canEncode(comm);
-
-            if (createUnicodeExtraFields == UnicodeExtraFieldPolicy.ALWAYS
-                || !commentEncodable) {
-                ByteBuffer commentB = getEntryEncoding(ze).encode(comm);
-                ze.addExtraField(new UnicodeCommentExtraField(comm,
-                                                              commentB.array(),
-                                                              commentB.arrayOffset(),
-                                                              commentB.limit()
-                                                              - commentB.position())
-                                 );
-            }
+        if (createUnicodeExtraFields == UnicodeExtraFieldPolicy.ALWAYS
+            || !zipEncoding.canEncode(comm)) {
+            ByteBuffer commentB = getEntryEncoding(ze).encode(comm);
+            ze.addExtraField(new UnicodeCommentExtraField(comm,
+                    commentB.array(), commentB.arrayOffset(),
+                    commentB.limit() - commentB.position()));
         }
     }
 
diff --git a/src/main/org/apache/tools/zip/ZipShort.java b/src/main/org/apache/tools/zip/ZipShort.java
index ccbca3d..e4f65b1 100644
--- a/src/main/org/apache/tools/zip/ZipShort.java
+++ b/src/main/org/apache/tools/zip/ZipShort.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -76,7 +76,7 @@
      * @param buf the output buffer
      * @param  offset
      *         The offset within the output buffer of the first byte to be written.
-     *         must be non-negative and no larger than <tt>buf.length-2</tt>
+     *         must be non-negative and no larger than <code>buf.length-2</code>
      */
     public static void putShort(int value, byte[] buf, int offset) {
         buf[offset] = (byte) (value & BYTE_MASK);
@@ -133,10 +133,7 @@
      */
     @Override
     public boolean equals(Object o) {
-        if (o == null || !(o instanceof ZipShort)) {
-            return false;
-        }
-        return value == ((ZipShort) o).getValue();
+        return o instanceof ZipShort && value == ((ZipShort) o).getValue();
     }
 
     /**
diff --git a/src/main/org/apache/tools/zip/ZipUtil.java b/src/main/org/apache/tools/zip/ZipUtil.java
index ff35ca4..217eda8 100644
--- a/src/main/org/apache/tools/zip/ZipUtil.java
+++ b/src/main/org/apache/tools/zip/ZipUtil.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -65,7 +65,7 @@
      * @param buf the output buffer
      * @param offset
      *         The offset within the output buffer of the first byte to be written.
-     *         must be non-negative and no larger than <tt>buf.length-4</tt>
+     *         must be non-negative and no larger than <code>buf.length-4</code>
      */
     public static void toDosTime(long t, byte[] buf, int offset) {
         toDosTime(Calendar.getInstance(), t, buf, offset);
diff --git a/src/resources/org/apache/tools/ant/types/resources/comparators/antlib.xml b/src/resources/org/apache/tools/ant/types/resources/comparators/antlib.xml
index ae61b9d..04fd293 100644
--- a/src/resources/org/apache/tools/ant/types/resources/comparators/antlib.xml
+++ b/src/resources/org/apache/tools/ant/types/resources/comparators/antlib.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml b/src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml
index 0d0e502..333b458 100644
--- a/src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml
+++ b/src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/script/ant b/src/script/ant
index 20951f4..b3b4c0a 100644
--- a/src/script/ant
+++ b/src/script/ant
@@ -7,7 +7,7 @@
 # (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
+#     https://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,
@@ -368,6 +368,12 @@
     ant_sys_opts="-Djikes.class.path=\"$JIKESPATH\""
   fi
 fi
+# Run "java -XshowSettings:properties" and check the output for "java.specification.version" value
+JAVA_SPEC_VERSION=`"$JAVACMD" -XshowSettings:properties 2>&1 | grep "java.specification.version = " | tr -d '[:space:]'`
+if [ "$JAVA_SPEC_VERSION" = "java.specification.version=18" ] || [ "$JAVA_SPEC_VERSION" = "java.specification.version=19" ]; then
+  # set security manager property to allow calls to System.setSecurityManager() at runtime
+  ANT_OPTS="$ANT_OPTS -Djava.security.manager=allow"
+fi
 ant_exec_command="exec \"\$JAVACMD\" $ANT_OPTS -classpath \"\$LOCALCLASSPATH\" -Dant.home=\"\$ANT_HOME\" -Dant.library.dir=\"\$ANT_LIB\" $ant_sys_opts org.apache.tools.ant.launch.Launcher $ANT_ARGS -cp \"\$CLASSPATH\""
 if $ant_exec_debug; then
   # using printf to avoid echo line continuation and escape interpretation confusion
diff --git a/src/script/ant.bat b/src/script/ant.bat
index a13cabc..58dc3db 100755
--- a/src/script/ant.bat
+++ b/src/script/ant.bat
@@ -7,7 +7,7 @@
 REM  (the "License"); you may not use this file except in compliance with
 REM  the License.  You may obtain a copy of the License at
 REM
-REM      http://www.apache.org/licenses/LICENSE-2.0
+REM      https://www.apache.org/licenses/LICENSE-2.0
 REM
 REM  Unless required by applicable law or agreed to in writing, software
 REM  distributed under the License is distributed on an "AS IS" BASIS,
@@ -117,11 +117,26 @@
 if "%JAVA_HOME%" == "" goto noJavaHome
 if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
 if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java.exe
-goto checkJikes
+goto setSecurityManagerOpt
 
 :noJavaHome
 if "%_JAVACMD%" == "" set _JAVACMD=java.exe
 
+:setSecurityManagerOpt
+setlocal EnableDelayedExpansion
+"!_JAVACMD!" -XshowSettings:properties 2>&1 | find "java.specification.version = 18" >nul 2>&1
+if !errorlevel! EQU 0 (
+    rem This is Java 18, so set -Djava.security.manager=allow
+    set JAVA_SECMGR_OPT=-Djava.security.manager=allow
+) else (
+    "!_JAVACMD!" -XshowSettings:properties 2>&1 | find "java.specification.version = 19" >nul 2>&1
+    if !errorlevel! EQU 0 (
+        rem This is Java 19, so set -Djava.security.manager=allow
+        set JAVA_SECMGR_OPT=-Djava.security.manager=allow
+    )
+)
+endlocal & set "ANT_OPTS=%ANT_OPTS% %JAVA_SECMGR_OPT%"
+
 :checkJikes
 if not "%JIKESPATH%"=="" goto runAntWithJikes
 
diff --git a/src/script/ant.cmd b/src/script/ant.cmd
index 902a1a7..a018e30 100644
--- a/src/script/ant.cmd
+++ b/src/script/ant.cmd
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/script/antRun b/src/script/antRun
index 8110f86..713762e 100644
--- a/src/script/antRun
+++ b/src/script/antRun
@@ -7,7 +7,7 @@
 # (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
+#     https://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,
diff --git a/src/script/antRun.bat b/src/script/antRun.bat
index 24eade9..b3c5a10 100755
--- a/src/script/antRun.bat
+++ b/src/script/antRun.bat
@@ -7,7 +7,7 @@
 REM  (the "License"); you may not use this file except in compliance with
 REM  the License.  You may obtain a copy of the License at
 REM
-REM      http://www.apache.org/licenses/LICENSE-2.0
+REM      https://www.apache.org/licenses/LICENSE-2.0
 REM
 REM  Unless required by applicable law or agreed to in writing, software
 REM  distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/src/script/antRun.pl b/src/script/antRun.pl
index bc493dd..e57f3d7 100644
--- a/src/script/antRun.pl
+++ b/src/script/antRun.pl
@@ -7,7 +7,7 @@
 #  (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
+#      https://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,
diff --git a/src/script/antenv.cmd b/src/script/antenv.cmd
index 7913801..6cbcced 100644
--- a/src/script/antenv.cmd
+++ b/src/script/antenv.cmd
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/script/complete-ant-cmd.pl b/src/script/complete-ant-cmd.pl
index 47e3c0e..e7472b3 100644
--- a/src/script/complete-ant-cmd.pl
+++ b/src/script/complete-ant-cmd.pl
@@ -7,7 +7,7 @@
 #  (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
+#      https://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,
diff --git a/src/script/envset.cmd b/src/script/envset.cmd
index 3b07419..846f85d 100644
--- a/src/script/envset.cmd
+++ b/src/script/envset.cmd
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/script/lcp.bat b/src/script/lcp.bat
index 6a1acbe..9ad1b78 100755
--- a/src/script/lcp.bat
+++ b/src/script/lcp.bat
@@ -6,7 +6,7 @@
 REM  (the "License"); you may not use this file except in compliance with
 REM  the License.  You may obtain a copy of the License at
 REM
-REM      http://www.apache.org/licenses/LICENSE-2.0
+REM      https://www.apache.org/licenses/LICENSE-2.0
 REM
 REM  Unless required by applicable law or agreed to in writing, software
 REM  distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/src/script/runant.pl b/src/script/runant.pl
index b6c72e9..81eee8e 100644
--- a/src/script/runant.pl
+++ b/src/script/runant.pl
@@ -7,7 +7,7 @@
 #  (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
+#      https://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,
diff --git a/src/script/runrc.cmd b/src/script/runrc.cmd
index c17fd0f..47525d2 100644
--- a/src/script/runrc.cmd
+++ b/src/script/runrc.cmd
@@ -6,7 +6,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/antunit-base.xml b/src/tests/antunit/antunit-base.xml
index 4bd4643..48226b8 100644
--- a/src/tests/antunit/antunit-base.xml
+++ b/src/tests/antunit/antunit-base.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -31,10 +31,6 @@
     <javaversion atleast="10"/>
   </condition>
   <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>
@@ -55,6 +51,11 @@
     <antunit xmlns="antlib:org.apache.ant.antunit">
       <plainlistener />
       <file file="${ant.file}" xmlns="antlib:org.apache.tools.ant" />
+      <propertyset>
+        <propertyref name="antunit.tmpdir"/>
+        <propertyref name="ant.home"/>
+        <propertyref name="jenkins"/>
+      </propertyset>
     </antunit>
   </target>
 
diff --git a/src/tests/antunit/bugfixes/bugzilla-43324-stackoverflow-test.xml b/src/tests/antunit/bugfixes/bugzilla-43324-stackoverflow-test.xml
index d706b8f..9f7e8ab 100644
--- a/src/tests/antunit/bugfixes/bugzilla-43324-stackoverflow-test.xml
+++ b/src/tests/antunit/bugfixes/bugzilla-43324-stackoverflow-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/core/ant-attribute-test.xml b/src/tests/antunit/core/ant-attribute-test.xml
index 6f6dc51..81770fd 100644
--- a/src/tests/antunit/core/ant-attribute-test.xml
+++ b/src/tests/antunit/core/ant-attribute-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/bindtargets-test.xml b/src/tests/antunit/core/bindtargets-test.xml
index 0279a2c..dafc799 100644
--- a/src/tests/antunit/core/bindtargets-test.xml
+++ b/src/tests/antunit/core/bindtargets-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/classloader-test.xml b/src/tests/antunit/core/classloader-test.xml
index 4af0040..6e2c871 100644
--- a/src/tests/antunit/core/classloader-test.xml
+++ b/src/tests/antunit/core/classloader-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -48,7 +48,8 @@
 
   <target name="testLoadClass"
           description="https://issues.apache.org/bugzilla/show_bug.cgi?id=44103"
-          depends="setUp">
+          depends="setUp"
+          unless="gump">
     <echo file="${input}/A.java"><![CDATA[
 public class A {
     public static void main(String[] args) {
diff --git a/src/tests/antunit/core/createtask-test.xml b/src/tests/antunit/core/createtask-test.xml
index b69633b..8e2f872 100644
--- a/src/tests/antunit/core/createtask-test.xml
+++ b/src/tests/antunit/core/createtask-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/dirscanner-symlinks-test.xml b/src/tests/antunit/core/dirscanner-symlinks-test.xml
index 0645946..934d4e7 100644
--- a/src/tests/antunit/core/dirscanner-symlinks-test.xml
+++ b/src/tests/antunit/core/dirscanner-symlinks-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/extension-point-test.xml b/src/tests/antunit/core/extension-point-test.xml
index 8c0dbdb..5fc398f 100644
--- a/src/tests/antunit/core/extension-point-test.xml
+++ b/src/tests/antunit/core/extension-point-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -105,7 +105,7 @@
 <project name="master">
   <include file="compile-java.xml" as="compile"/>
 </project>]]></echo>
-    <!-- here prefix should be concatened from each include first 
+    <!-- here prefix should be concatenated from each include first
          "compile" then "abstract-compile"-->
     <ant dir="${output}" target="compile.abstract-compile.compile"/>
     <au:assertLogContains text="in compile java"/>
diff --git a/src/tests/antunit/core/extension/include-test.xml b/src/tests/antunit/core/extension/include-test.xml
index 4d3b674..3582757 100644
--- a/src/tests/antunit/core/extension/include-test.xml
+++ b/src/tests/antunit/core/extension/include-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/extension/module1.xml b/src/tests/antunit/core/extension/module1.xml
index 3b6312f..7c65430 100644
--- a/src/tests/antunit/core/extension/module1.xml
+++ b/src/tests/antunit/core/extension/module1.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/location/location.xml b/src/tests/antunit/core/location/location.xml
index bf37d9f..ea68eb0 100644
--- a/src/tests/antunit/core/location/location.xml
+++ b/src/tests/antunit/core/location/location.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/location/src/task/EchoLocation.java b/src/tests/antunit/core/location/src/task/EchoLocation.java
index a2031e6..4a45862 100644
--- a/src/tests/antunit/core/location/src/task/EchoLocation.java
+++ b/src/tests/antunit/core/location/src/task/EchoLocation.java
@@ -6,7 +6,7 @@
  * (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
+ *    https://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,
diff --git a/src/tests/antunit/core/magic-names-test.xml b/src/tests/antunit/core/magic-names-test.xml
index 54662da..19ac15e 100644
--- a/src/tests/antunit/core/magic-names-test.xml
+++ b/src/tests/antunit/core/magic-names-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/nested-elements-test.xml b/src/tests/antunit/core/nested-elements-test.xml
index e031c41..dfb967f 100644
--- a/src/tests/antunit/core/nested-elements-test.xml
+++ b/src/tests/antunit/core/nested-elements-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/nested-text-test.xml b/src/tests/antunit/core/nested-text-test.xml
index 05fb4c8..3fe0bf8 100644
--- a/src/tests/antunit/core/nested-text-test.xml
+++ b/src/tests/antunit/core/nested-text-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers-test.xml b/src/tests/antunit/core/projecthelpers-test.xml
index 9e9000d..cb652ed 100644
--- a/src/tests/antunit/core/projecthelpers-test.xml
+++ b/src/tests/antunit/core/projecthelpers-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xml b/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xml
index 67837a0..19bb9b4 100644
--- a/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xml
+++ b/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xmlref b/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xmlref
index f81d3db..660c7a6 100644
--- a/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xmlref
+++ b/src/tests/antunit/core/projecthelpers/build-cross-extension-ref.xmlref
@@ -5,7 +5,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-cross-extension.xml b/src/tests/antunit/core/projecthelpers/build-cross-extension.xml
index f8f1220..14377d3 100644
--- a/src/tests/antunit/core/projecthelpers/build-cross-extension.xml
+++ b/src/tests/antunit/core/projecthelpers/build-cross-extension.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xml b/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xml
index c16d989..5381ab3 100644
--- a/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xml
+++ b/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xmlref b/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xmlref
index f81d3db..660c7a6 100644
--- a/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xmlref
+++ b/src/tests/antunit/core/projecthelpers/build-cross-targets-ref.xmlref
@@ -5,7 +5,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-cross-targets.xml b/src/tests/antunit/core/projecthelpers/build-cross-targets.xml
index c4c7ca7..7749e25 100644
--- a/src/tests/antunit/core/projecthelpers/build-cross-targets.xml
+++ b/src/tests/antunit/core/projecthelpers/build-cross-targets.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import-common.xml b/src/tests/antunit/core/projecthelpers/build-many-import-common.xml
index 243de8c..402077a 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import-common.xml
+++ b/src/tests/antunit/core/projecthelpers/build-many-import-common.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import-commonref.xml b/src/tests/antunit/core/projecthelpers/build-many-import-commonref.xml
index 38b50ad..51f561b 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import-commonref.xml
+++ b/src/tests/antunit/core/projecthelpers/build-many-import-commonref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import-ref.xml b/src/tests/antunit/core/projecthelpers/build-many-import-ref.xml
index c9c02fe..e875ddd 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import-ref.xml
+++ b/src/tests/antunit/core/projecthelpers/build-many-import-ref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import-ref.xmlref b/src/tests/antunit/core/projecthelpers/build-many-import-ref.xmlref
index f81d3db..660c7a6 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import-ref.xmlref
+++ b/src/tests/antunit/core/projecthelpers/build-many-import-ref.xmlref
@@ -5,7 +5,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import.xml b/src/tests/antunit/core/projecthelpers/build-many-import.xml
index 792fb56..f518d37 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import.xml
+++ b/src/tests/antunit/core/projecthelpers/build-many-import.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xml b/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xml
index d32cf17..f780b3e 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xml
+++ b/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xmlref b/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xmlref
index f81d3db..660c7a6 100644
--- a/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xmlref
+++ b/src/tests/antunit/core/projecthelpers/build-many-import2-ref.xmlref
@@ -5,7 +5,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/ref-propertyhelper-test.xml b/src/tests/antunit/core/ref-propertyhelper-test.xml
index b3bc39c..c6b2f16 100644
--- a/src/tests/antunit/core/ref-propertyhelper-test.xml
+++ b/src/tests/antunit/core/ref-propertyhelper-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -97,8 +97,8 @@
     <javac srcdir="${input}" destdir="${output}"/>
     <taskdef name="x" classname="org.example.Task"
              classpath="${output}"/>
-    <url url="http://ant.apache.org/" id="anturl"/>
+    <url url="https://ant.apache.org/" id="anturl"/>
     <x attr="${ant.refid:anturl}"/>
-    <au:assertLogContains text="URL is: http://ant.apache.org/"/>
+    <au:assertLogContains text="URL is: https://ant.apache.org/"/>
   </target>
 </project>
diff --git a/src/tests/antunit/core/ref-psyntax-hint-test.xml b/src/tests/antunit/core/ref-psyntax-hint-test.xml
index de32411..fe492f5 100644
--- a/src/tests/antunit/core/ref-psyntax-hint-test.xml
+++ b/src/tests/antunit/core/ref-psyntax-hint-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/target-test-helper.xml b/src/tests/antunit/core/target-test-helper.xml
index 6ca2452..d5dc3a4 100644
--- a/src/tests/antunit/core/target-test-helper.xml
+++ b/src/tests/antunit/core/target-test-helper.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/target-test.xml b/src/tests/antunit/core/target-test.xml
index 3e656be..375daeb 100644
--- a/src/tests/antunit/core/target-test.xml
+++ b/src/tests/antunit/core/target-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/core/uuencode/src/task/BaseTask.java b/src/tests/antunit/core/uuencode/src/task/BaseTask.java
index 70eb7a3..375eb52 100644
--- a/src/tests/antunit/core/uuencode/src/task/BaseTask.java
+++ b/src/tests/antunit/core/uuencode/src/task/BaseTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,12 +26,13 @@
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 
 /**
  * Base class for the uuencode/decode test tasks.
  */
 abstract public class BaseTask extends Task {
-    private final static FileUtils FILE_UTILS = FileUtils.getFileUtils();
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
     private File inFile;
     private File outFile;
 
@@ -54,8 +55,8 @@
         OutputStream outputStream = null;
         try {
             inputStream = new BufferedInputStream(
-                new FileInputStream(getInFile()));
-            outputStream = new FileOutputStream(getOutFile());
+                Files.newInputStream(getInFile().toPath()));
+            outputStream = Files.newOutputStream(getOutFile().toPath());
             doit(inputStream, outputStream);
         } catch (Exception ex) {
             throw new BuildException(ex);
diff --git a/src/tests/antunit/core/uuencode/src/task/UUDecodeTask.java b/src/tests/antunit/core/uuencode/src/task/UUDecodeTask.java
index d74b846..cd2f4fe 100644
--- a/src/tests/antunit/core/uuencode/src/task/UUDecodeTask.java
+++ b/src/tests/antunit/core/uuencode/src/task/UUDecodeTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/antunit/core/uuencode/src/task/UUEncodeTask.java b/src/tests/antunit/core/uuencode/src/task/UUEncodeTask.java
index 2b878f8..6bd270c 100644
--- a/src/tests/antunit/core/uuencode/src/task/UUEncodeTask.java
+++ b/src/tests/antunit/core/uuencode/src/task/UUEncodeTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/antunit/core/uuencode/uuencode-test.xml b/src/tests/antunit/core/uuencode/uuencode-test.xml
index 2d68ab0..56dcc5b 100644
--- a/src/tests/antunit/core/uuencode/uuencode-test.xml
+++ b/src/tests/antunit/core/uuencode/uuencode-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/filters/expandproperties-test.xml b/src/tests/antunit/filters/expandproperties-test.xml
index 5dff832..8d9692d 100644
--- a/src/tests/antunit/filters/expandproperties-test.xml
+++ b/src/tests/antunit/filters/expandproperties-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
diff --git a/src/tests/antunit/filters/native2ascii-test.xml b/src/tests/antunit/filters/native2ascii-test.xml
index 26fa0c7..3649335 100644
--- a/src/tests/antunit/filters/native2ascii-test.xml
+++ b/src/tests/antunit/filters/native2ascii-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
diff --git a/src/tests/antunit/filters/replacetokens-test.xml b/src/tests/antunit/filters/replacetokens-test.xml
index c1f98ab..d160052 100644
--- a/src/tests/antunit/filters/replacetokens-test.xml
+++ b/src/tests/antunit/filters/replacetokens-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/filters/sort-test.xml b/src/tests/antunit/filters/sort-test.xml
index 8c2a88b..c17c24a 100644
--- a/src/tests/antunit/filters/sort-test.xml
+++ b/src/tests/antunit/filters/sort-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
diff --git a/src/tests/antunit/filters/striplinecomments-test.xml b/src/tests/antunit/filters/striplinecomments-test.xml
index 2af0f01..b96b434 100644
--- a/src/tests/antunit/filters/striplinecomments-test.xml
+++ b/src/tests/antunit/filters/striplinecomments-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/filters/suffix-test.xml b/src/tests/antunit/filters/suffix-test.xml
index a0a9403..77352dc 100644
--- a/src/tests/antunit/filters/suffix-test.xml
+++ b/src/tests/antunit/filters/suffix-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
diff --git a/src/tests/antunit/filters/uniq-test.xml b/src/tests/antunit/filters/uniq-test.xml
index 832ec94..1b12d05 100644
--- a/src/tests/antunit/filters/uniq-test.xml
+++ b/src/tests/antunit/filters/uniq-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
diff --git a/src/tests/antunit/junit-frames.xsl b/src/tests/antunit/junit-frames.xsl
index 9fab285..bbb0c76 100644
--- a/src/tests/antunit/junit-frames.xsl
+++ b/src/tests/antunit/junit-frames.xsl
@@ -15,7 +15,7 @@
 "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
+https://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
@@ -695,7 +695,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href="http://ant.apache.org/antlibs/antunit/">AntUnit</a> and <a href="http://ant.apache.org/">Ant</a>.</td>
+        <td align="right">Designed for use with <a href="https://ant.apache.org/antlibs/antunit/">AntUnit</a> and <a href="https://ant.apache.org/">Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/tests/antunit/junit-noframes.xsl b/src/tests/antunit/junit-noframes.xsl
index 255046a..2f5e4fb 100644
--- a/src/tests/antunit/junit-noframes.xsl
+++ b/src/tests/antunit/junit-noframes.xsl
@@ -14,7 +14,7 @@
 "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
+https://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
@@ -318,7 +318,7 @@
     <table width="100%">
     <tr>
         <td align="left"></td>
-        <td align="right">Designed for use with <a href='http://ant.apache.org/antlibs/antunit/'>AntUnit</a> and <a href='http://ant.apache.org/'>Ant</a>.</td>
+        <td align="right">Designed for use with <a href='https://ant.apache.org/antlibs/antunit/'>AntUnit</a> and <a href='https://ant.apache.org/'>Ant</a>.</td>
     </tr>
     </table>
     <hr size="1"/>
diff --git a/src/tests/antunit/propertyhelpers.xml b/src/tests/antunit/propertyhelpers.xml
index 287f00c..e455b14 100644
--- a/src/tests/antunit/propertyhelpers.xml
+++ b/src/tests/antunit/propertyhelpers.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/ant-test.xml b/src/tests/antunit/taskdefs/ant-test.xml
index c3ee56b..133b8ba 100644
--- a/src/tests/antunit/taskdefs/ant-test.xml
+++ b/src/tests/antunit/taskdefs/ant-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/antcall-test.xml b/src/tests/antunit/taskdefs/antcall-test.xml
index 9767185..452b788 100644
--- a/src/tests/antunit/taskdefs/antcall-test.xml
+++ b/src/tests/antunit/taskdefs/antcall-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
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/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/augment-test.xml b/src/tests/antunit/taskdefs/augment-test.xml
index 2e6f335..828d95f 100644
--- a/src/tests/antunit/taskdefs/augment-test.xml
+++ b/src/tests/antunit/taskdefs/augment-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/bunzip2-test.xml b/src/tests/antunit/taskdefs/bunzip2-test.xml
index fcf05d9..76148d9 100644
--- a/src/tests/antunit/taskdefs/bunzip2-test.xml
+++ b/src/tests/antunit/taskdefs/bunzip2-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -30,9 +30,9 @@
 
   <target name="testWithNonFileResourceToFile" depends="setup">
     <bunzip2 dest="${output}/greeting.txt">
-      <url url="http://ant.apache.org/webtest/bunzip2/greeting.txt.bz2"/>
+      <url url="https://ant.apache.org/webtest/bunzip2/greeting.txt.bz2"/>
     </bunzip2>
-    <get src="http://ant.apache.org/webtest/gunzip/greeting.txt"
+    <get src="https://ant.apache.org/webtest/gunzip/greeting.txt"
          dest="${output}/orig.greeting.txt"/>
     <au:assertFilesMatch expected="${output}/orig.greeting.txt"
                          actual="${output}/greeting.txt"/>
@@ -40,9 +40,9 @@
 
   <target name="testWithNonFileResourceToDir" depends="setup">
     <bunzip2 dest="${output}">
-      <url url="http://ant.apache.org/webtest/bunzip2/greeting.txt.bz2"/>
+      <url url="https://ant.apache.org/webtest/bunzip2/greeting.txt.bz2"/>
     </bunzip2>
-    <get src="http://ant.apache.org/webtest/gunzip/greeting.txt"
+    <get src="https://ant.apache.org/webtest/gunzip/greeting.txt"
          dest="${output}/orig.greeting.txt"/>
     <au:assertFilesMatch expected="${output}/orig.greeting.txt"
                          actual="${output}/greeting.txt"/>
diff --git a/src/tests/antunit/taskdefs/checksum-test.xml b/src/tests/antunit/taskdefs/checksum-test.xml
index 8341f42..b6c8057 100644
--- a/src/tests/antunit/taskdefs/checksum-test.xml
+++ b/src/tests/antunit/taskdefs/checksum-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/commandlauncher/commandlauncher-test.xml b/src/tests/antunit/taskdefs/commandlauncher/commandlauncher-test.xml
index 49519bd..2c770ba 100644
--- a/src/tests/antunit/taskdefs/commandlauncher/commandlauncher-test.xml
+++ b/src/tests/antunit/taskdefs/commandlauncher/commandlauncher-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/concat-test.xml b/src/tests/antunit/taskdefs/concat-test.xml
index 4b285e3..82182ff 100644
--- a/src/tests/antunit/taskdefs/concat-test.xml
+++ b/src/tests/antunit/taskdefs/concat-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -118,6 +118,50 @@
     </au:assertTrue>
   </target>
 
+  <target name="testFilterIsAppliedToConcatenation"
+          depends="-fixlastline-setup"
+          description="https://bz.apache.org/bugzilla/show_bug.cgi?id=64855">
+    <au:assertTrue>
+      <resourcesmatch>
+        <string>1${line.separator}2${line.separator}1${line.separator}2${line.separator}</string>
+        <concat fixlastline="true">
+          <filelist dir="${input}">
+            <file name="1"/>
+            <file name="2"/>
+          </filelist>
+          <filterchain>
+	    <tokenfilter>
+          <filetokenizer/>
+          <replaceregex pattern="(.*)" flags="s" replace="\1\1"/>
+	    </tokenfilter>
+	  </filterchain>
+        </concat>
+      </resourcesmatch>
+    </au:assertTrue>
+  </target>
+
+  <target name="testFilterBeforeConcatActuallyAppliesFilterToEachInput"
+          depends="-fixlastline-setup"
+          description="https://bz.apache.org/bugzilla/show_bug.cgi?id=64855">
+    <au:assertTrue>
+      <resourcesmatch>
+        <string>1${line.separator}1${line.separator}2${line.separator}2${line.separator}</string>
+        <concat fixlastline="true" filterbeforeconcat="true">
+          <filelist dir="${input}">
+            <file name="1"/>
+            <file name="2"/>
+          </filelist>
+          <filterchain>
+	    <tokenfilter>
+          <filetokenizer/>
+          <replaceregex pattern="(.*)" flags="s" replace="\1\1"/>
+	    </tokenfilter>
+	  </filterchain>
+        </concat>
+      </resourcesmatch>
+    </au:assertTrue>
+  </target>
+
   <target name="testIgnoreEmptyFalseFileIsCreated">
     <mkdir dir="${input}" />
     <mkdir dir="${output}" />
diff --git a/src/tests/antunit/taskdefs/condition/antversion-test.xml b/src/tests/antunit/taskdefs/condition/antversion-test.xml
index 89c2d7e..236f0e7 100644
--- a/src/tests/antunit/taskdefs/condition/antversion-test.xml
+++ b/src/tests/antunit/taskdefs/condition/antversion-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/equals-test.xml b/src/tests/antunit/taskdefs/condition/equals-test.xml
index 8888d39..c423c82 100644
--- a/src/tests/antunit/taskdefs/condition/equals-test.xml
+++ b/src/tests/antunit/taskdefs/condition/equals-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/filesmatch-test.xml b/src/tests/antunit/taskdefs/condition/filesmatch-test.xml
index 67e7c00..45cdf05 100644
--- a/src/tests/antunit/taskdefs/condition/filesmatch-test.xml
+++ b/src/tests/antunit/taskdefs/condition/filesmatch-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/hasfreespace-test.xml b/src/tests/antunit/taskdefs/condition/hasfreespace-test.xml
index 01f1809..011b636 100644
--- a/src/tests/antunit/taskdefs/condition/hasfreespace-test.xml
+++ b/src/tests/antunit/taskdefs/condition/hasfreespace-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/hasmethod-text.xml b/src/tests/antunit/taskdefs/condition/hasmethod-text.xml
index 9ae9b32..dce604d 100644
--- a/src/tests/antunit/taskdefs/condition/hasmethod-text.xml
+++ b/src/tests/antunit/taskdefs/condition/hasmethod-text.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/http-test.xml b/src/tests/antunit/taskdefs/condition/http-test.xml
new file mode 100644
index 0000000..1b9f133
--- /dev/null
+++ b/src/tests/antunit/taskdefs/condition/http-test.xml
@@ -0,0 +1,105 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<project name="http-test" default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
+  <import file="../../antunit-base.xml" />
+
+  <property name="location" value="https://ant.apache.org/webtest/gettest" />
+  <property name="unsecurelocation" value="http://ant.apache.org/webtest/gettest/http-to-https.txt" />
+
+  <target name="testSeeOtherRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/other.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/other.txt was 200" />
+  </target>
+
+  <target name="testPermanentRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/permanent.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/permanent.txt was 200" />
+  </target>
+
+  <target name="testTemporaryRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/temp.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/temp.txt was 200" />
+  </target>
+
+  <target name="testStatusCode307Redirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/307.txt"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${location}/307.txt was 200" />
+  </target>
+
+  <target name="testHttpToHttpsRedirect" description="Tests that a resource that's redirected
+        from HTTP to HTTPS works without an error. See bugzilla-65105 for details">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${unsecurelocation}"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+        text="Result code for ${unsecurelocation} was 200" />
+  </target>
+
+  <target name="testDontFollowPermanentRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/permanent.txt" followRedirects="false"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+                          text="Result code for ${location}/permanent.txt was 301" />
+  </target>
+
+  <target name="testDontFollowTemporaryRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/temp.txt" followRedirects="false"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+                          text="Result code for ${location}/temp.txt was 302" />
+  </target>
+
+  <target name="testDontFollowStatusCode307Redirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${location}/307.txt" followRedirects="false"/>
+    </au:assertTrue>
+    <au:assertLogContains level="verbose"
+                          text="Result code for ${location}/307.txt was 307" />
+  </target>
+
+  <target name="testDontFollowHttpToHttpsRedirect">
+    <sleep milliseconds="250"/>
+    <au:assertTrue>
+      <http url="${unsecurelocation}" followRedirects="false"/>
+    </au:assertTrue>
+  </target>
+
+</project>
diff --git a/src/tests/antunit/taskdefs/condition/islastmodified-test.xml b/src/tests/antunit/taskdefs/condition/islastmodified-test.xml
index 429e3f8..6ad7528 100644
--- a/src/tests/antunit/taskdefs/condition/islastmodified-test.xml
+++ b/src/tests/antunit/taskdefs/condition/islastmodified-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/javaversion-test.xml b/src/tests/antunit/taskdefs/condition/javaversion-test.xml
index 5f15a1e..586cad0 100644
--- a/src/tests/antunit/taskdefs/condition/javaversion-test.xml
+++ b/src/tests/antunit/taskdefs/condition/javaversion-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -25,6 +25,20 @@
     </au:assertTrue>
   </target>
 
+  <target name="test-atmost">
+    <au:assertTrue message="Expected javaversion ${java.version} to be at most 1000.111.211">
+      <!-- a high version value so that the check passes -->
+      <javaversion atmost="1000.111.211" />
+    </au:assertTrue>
+  </target>
+
+  <target name="test-atmost-negative">
+    <au:assertFalse message="Expected javaversion ${java.version} to be at most 1.4.0">
+      <!-- Ant 1.10.x requires Java 8 at runtime - so this check is expected to return false -->
+      <javaversion atmost="1.4.0" />
+    </au:assertFalse>
+  </target>
+
   <target name="test-exactly">
     <au:assertTrue message="Expected javaversion of ${ant.java.version}">
       <javaversion exactly="${ant.java.version}" />
diff --git a/src/tests/antunit/taskdefs/condition/resourcecontains-test.xml b/src/tests/antunit/taskdefs/condition/resourcecontains-test.xml
index 11c6a9e..b36c7f0 100644
--- a/src/tests/antunit/taskdefs/condition/resourcecontains-test.xml
+++ b/src/tests/antunit/taskdefs/condition/resourcecontains-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/condition/resourceexists-test.xml b/src/tests/antunit/taskdefs/condition/resourceexists-test.xml
index bdf40c2..b50a00d 100644
--- a/src/tests/antunit/taskdefs/condition/resourceexists-test.xml
+++ b/src/tests/antunit/taskdefs/condition/resourceexists-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -39,7 +39,7 @@
   <target name="testURL">
     <au:assertTrue>
       <cond:resourceexists>
-        <url url="http://ant.apache.org/index.html"/>
+        <url url="https://ant.apache.org/index.html"/>
       </cond:resourceexists>
     </au:assertTrue>
   </target>
diff --git a/src/tests/antunit/taskdefs/copy-test.xml b/src/tests/antunit/taskdefs/copy-test.xml
index 1fd4b59..14a4bec 100644
--- a/src/tests/antunit/taskdefs/copy-test.xml
+++ b/src/tests/antunit/taskdefs/copy-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -187,7 +187,7 @@
     <au:expectfailure>
       <copy todir="${output}" failonerror="true" flatten="true">
         <resources>
-          <url url="http://i-do-not-exist/"/>
+          <url url="https://i-do-not-exist/"/>
         </resources>
       </copy>
     </au:expectfailure>
@@ -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/cvs/cvs.xml b/src/tests/antunit/taskdefs/cvs/cvs.xml
index 564e587..43c6291 100644
--- a/src/tests/antunit/taskdefs/cvs/cvs.xml
+++ b/src/tests/antunit/taskdefs/cvs/cvs.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/defaultexcludes-test.xml b/src/tests/antunit/taskdefs/defaultexcludes-test.xml
index cbea93c..d4e4eba 100644
--- a/src/tests/antunit/taskdefs/defaultexcludes-test.xml
+++ b/src/tests/antunit/taskdefs/defaultexcludes-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/delete-and-symlinks-test.xml b/src/tests/antunit/taskdefs/delete-and-symlinks-test.xml
index ac78994..ffc4a8a 100644
--- a/src/tests/antunit/taskdefs/delete-and-symlinks-test.xml
+++ b/src/tests/antunit/taskdefs/delete-and-symlinks-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/delete-test.xml b/src/tests/antunit/taskdefs/delete-test.xml
index 554f08f..86ae8cd 100644
--- a/src/tests/antunit/taskdefs/delete-test.xml
+++ b/src/tests/antunit/taskdefs/delete-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/dependset-test.xml b/src/tests/antunit/taskdefs/dependset-test.xml
index 5525259..1301444 100644
--- a/src/tests/antunit/taskdefs/dependset-test.xml
+++ b/src/tests/antunit/taskdefs/dependset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/dirname-test.xml b/src/tests/antunit/taskdefs/dirname-test.xml
index 60caaf1..afb9446 100644
--- a/src/tests/antunit/taskdefs/dirname-test.xml
+++ b/src/tests/antunit/taskdefs/dirname-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/ear-test.xml b/src/tests/antunit/taskdefs/ear-test.xml
index 239c501..aaacb71 100644
--- a/src/tests/antunit/taskdefs/ear-test.xml
+++ b/src/tests/antunit/taskdefs/ear-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/echo-test.xml b/src/tests/antunit/taskdefs/echo-test.xml
index bd1fc05..71b24ae 100644
--- a/src/tests/antunit/taskdefs/echo-test.xml
+++ b/src/tests/antunit/taskdefs/echo-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/echoxml-test.xml b/src/tests/antunit/taskdefs/echoxml-test.xml
index d461d3d..b7a3eca 100644
--- a/src/tests/antunit/taskdefs/echoxml-test.xml
+++ b/src/tests/antunit/taskdefs/echoxml-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/exec/apply-test.xml b/src/tests/antunit/taskdefs/exec/apply-test.xml
index 1b5a661..8f1c14d 100644
--- a/src/tests/antunit/taskdefs/exec/apply-test.xml
+++ b/src/tests/antunit/taskdefs/exec/apply-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/exec/exec-test.xml b/src/tests/antunit/taskdefs/exec/exec-test.xml
index 25b0088..bbe95e5 100644
--- a/src/tests/antunit/taskdefs/exec/exec-test.xml
+++ b/src/tests/antunit/taskdefs/exec/exec-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -707,4 +707,31 @@
         </au:assertTrue>
     </target>
 
+    <target name="test-discard-output" depends="setUp" if="test.can.run">
+        <exec executable="sh" discardOutput="true">
+            <arg value="parrot.sh" />
+            <arg value="${ant.file}" />
+        </exec>
+        <au:assertLogDoesntContain text="${ant.file} out" />
+        <au:assertLogDoesntContain text="${ant.file} err" />
+    </target>
+
+    <target name="test-discard-output-only" depends="setUp" if="test.can.run">
+        <exec executable="sh" discardOutput="true" logError="true">
+            <arg value="parrot.sh" />
+            <arg value="${ant.file}" />
+        </exec>
+        <au:assertLogDoesntContain text="${ant.file} out" />
+        <au:assertLogContains text="${ant.file} err" />
+    </target>
+
+    <target name="test-discard-error" depends="setUp" if="test.can.run">
+        <exec executable="sh" discardError="true">
+            <arg value="parrot.sh" />
+            <arg value="${ant.file}" />
+        </exec>
+        <au:assertLogContains text="${ant.file} out" />
+        <au:assertLogDoesntContain text="${ant.file} err" />
+    </target>
+
 </project>
diff --git a/src/tests/antunit/taskdefs/exec/parrot.sh b/src/tests/antunit/taskdefs/exec/parrot.sh
index c064c38..c2c087b 100755
--- a/src/tests/antunit/taskdefs/exec/parrot.sh
+++ b/src/tests/antunit/taskdefs/exec/parrot.sh
@@ -6,7 +6,7 @@
 # (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
+#     https://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,
diff --git a/src/tests/antunit/taskdefs/fail-test.xml b/src/tests/antunit/taskdefs/fail-test.xml
index d525b73..c0f73da 100644
--- a/src/tests/antunit/taskdefs/fail-test.xml
+++ b/src/tests/antunit/taskdefs/fail-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/get-test.xml b/src/tests/antunit/taskdefs/get-test.xml
index 44d5af9..2133321 100644
--- a/src/tests/antunit/taskdefs/get-test.xml
+++ b/src/tests/antunit/taskdefs/get-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -19,17 +19,15 @@
 <project name="get-test" default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
   <import file="../antunit-base.xml" />
 
-  <property name="location" value="http://ant.apache.org/webtest/gettest" />
-  <condition property="java.atleast.1_8">
-      <javaversion atleast="1.8"/>
-  </condition>
+  <property name="location" value="https://ant.apache.org/webtest/gettest" />
+  <property name="unsecurelocation" value="http://ant.apache.org/webtest/gettest/http-to-https.txt" />
 
-
-    <target name="setUp">
+  <target name="setUp">
     <mkdir dir="${output}" />
   </target>
 
   <target name="testSeeOtherRedirect">
+    <sleep milliseconds="250"/>
     <get  src="${location}/other.txt" dest="${output}/other.tmp"/>
       <au:assertTrue>
             <resourcecount count="1">
@@ -43,6 +41,7 @@
   </target>
     
     <target name="testPermanentRedirect">
+      <sleep milliseconds="250"/>
       <get  src="${location}/permanent.txt" dest="${output}/permanent.tmp"/>
         <au:assertTrue>
           <resourcecount count="1">
@@ -56,6 +55,7 @@
     </target>
     
     <target name="testTemporaryRedirect">
+      <sleep milliseconds="250"/>
       <get  src="${location}/temp.txt" dest="${output}/temp.txt"/>
         <au:assertTrue>
           <resourcecount count="1">
@@ -69,6 +69,7 @@
     </target>
     
     <target name="testStatusCode307Redirect">
+      <sleep milliseconds="250"/>
       <get  src="${location}/307.txt" dest="${output}/307.txt"/>
         <au:assertTrue>
           <resourcecount count="1">
@@ -82,6 +83,7 @@
     </target>
     
     <target name="test5LevelsOfRedirect">
+      <sleep milliseconds="250"/>
       <get  src="${location}/redir5.txt" dest="${output}/redir5.tmp"/>
         <au:assertTrue>
           <resourcecount count="1">
@@ -99,22 +101,25 @@
     
     
     <target name="testInfiniteRedirect" unless="jenkins">
-        <au:expectfailure expectedmessage="More than 25 times redirected, giving up">
+      <sleep milliseconds="250"/>
+      <au:expectfailure expectedmessage="More than 25 times redirected, giving up">
       <get  src="${location}/infinite.txt" dest="${output}/infinite.tmp"/>
         </au:expectfailure>
     </target>
 
 
     <target name="testNestedResources">
+      <sleep milliseconds="250"/>
       <get dest="${output}/downloads">
-        <url url="http://ant.apache.org/index.html"/> 
-        <url url="http://ant.apache.org/faq.html"/>
+        <url url="https://ant.apache.org/index.html"/> 
+        <url url="https://ant.apache.org/faq.html"/>
       </get>
       <au:assertFileExists file="${output}/downloads/index.html"/>
       <au:assertFileExists file="${output}/downloads/faq.html"/>
     </target>
 
   <target name="XtestRelativeRedirect">
+    <sleep milliseconds="250"/>
     <get  src="${location}/local.cgi" dest="${output}/other.tmp"/>
     <au:assertTrue>
       <resourcecount count="1">
@@ -128,8 +133,9 @@
   </target>
 
   <target name="testHttpToHttpsRedirect" description="Tests that a resource that's redirected
-        from HTTP to HTTPS works without an error. See bugzilla-62499 for details" if="java.atleast.1_8">
-    <get  src="${location}/http-to-https.txt" dest="${output}/http-to-https-redirect.tmp"/>
+        from HTTP to HTTPS works without an error. See bugzilla-62499 for details">
+    <sleep milliseconds="250"/>
+    <get  src="${unsecurelocation}" dest="${output}/http-to-https-redirect.tmp"/>
     <au:assertFileExists file="${output}/http-to-https-redirect.tmp"/>
     <au:assertTrue>
       <resourcecontains resource="${output}/http-to-https-redirect.tmp" substring="hello world"/>
diff --git a/src/tests/antunit/taskdefs/gunzip-test.xml b/src/tests/antunit/taskdefs/gunzip-test.xml
index e678eb0..19ca0ce 100644
--- a/src/tests/antunit/taskdefs/gunzip-test.xml
+++ b/src/tests/antunit/taskdefs/gunzip-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -39,20 +39,22 @@
   </target>
 
   <target name="testWithNonFileResourceToFile" depends="setup">
+    <sleep milliseconds="250"/>
     <gunzip dest="${output}/greeting.txt">
-      <url url="http://ant.apache.org/webtest/gunzip/greeting.txt.gz"/>
+      <url url="https://ant.apache.org/webtest/gunzip/greeting.txt.gz"/>
     </gunzip>
-    <get src="http://ant.apache.org/webtest/gunzip/greeting.txt"
+    <get src="https://ant.apache.org/webtest/gunzip/greeting.txt"
          dest="${output}/orig.greeting.txt"/>
     <au:assertFilesMatch expected="${output}/orig.greeting.txt"
                          actual="${output}/greeting.txt"/>
   </target>
 
   <target name="testWithNonFileResourceToDir" depends="setup">
+    <sleep milliseconds="250"/>
     <gunzip dest="${output}">
-      <url url="http://ant.apache.org/webtest/gunzip/greeting.txt.gz"/>
+      <url url="https://ant.apache.org/webtest/gunzip/greeting.txt.gz"/>
     </gunzip>
-    <get src="http://ant.apache.org/webtest/gunzip/greeting.txt"
+    <get src="https://ant.apache.org/webtest/gunzip/greeting.txt"
          dest="${output}/orig.greeting.txt"/>
     <au:assertFilesMatch expected="${output}/orig.greeting.txt"
                          actual="${output}/greeting.txt"/>
diff --git a/src/tests/antunit/taskdefs/gzip-test.xml b/src/tests/antunit/taskdefs/gzip-test.xml
index 38f0a7a..450762b 100644
--- a/src/tests/antunit/taskdefs/gzip-test.xml
+++ b/src/tests/antunit/taskdefs/gzip-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/taskdefs/hostinfo-test.xml b/src/tests/antunit/taskdefs/hostinfo-test.xml
index a044b9b..1a42403 100644
--- a/src/tests/antunit/taskdefs/hostinfo-test.xml
+++ b/src/tests/antunit/taskdefs/hostinfo-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/import-test.xml b/src/tests/antunit/taskdefs/import-test.xml
index f9e4b05..e9c84f7 100644
--- a/src/tests/antunit/taskdefs/import-test.xml
+++ b/src/tests/antunit/taskdefs/import-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/import-url-test.xml b/src/tests/antunit/taskdefs/import-url-test.xml
index 103ece3..7a1ff17 100644
--- a/src/tests/antunit/taskdefs/import-url-test.xml
+++ b/src/tests/antunit/taskdefs/import-url-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/a.xml b/src/tests/antunit/taskdefs/importtests/a.xml
index 6082990..080725c 100644
--- a/src/tests/antunit/taskdefs/importtests/a.xml
+++ b/src/tests/antunit/taskdefs/importtests/a.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/b.xml b/src/tests/antunit/taskdefs/importtests/b.xml
index 546badf..8f94173 100644
--- a/src/tests/antunit/taskdefs/importtests/b.xml
+++ b/src/tests/antunit/taskdefs/importtests/b.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/nested.xml b/src/tests/antunit/taskdefs/importtests/nested.xml
index 28d7ad4..309b613 100644
--- a/src/tests/antunit/taskdefs/importtests/nested.xml
+++ b/src/tests/antunit/taskdefs/importtests/nested.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/override.xml b/src/tests/antunit/taskdefs/importtests/override.xml
index 97fd320..8d773a1 100644
--- a/src/tests/antunit/taskdefs/importtests/override.xml
+++ b/src/tests/antunit/taskdefs/importtests/override.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/w.xml b/src/tests/antunit/taskdefs/importtests/w.xml
index e400c50..911e42b 100644
--- a/src/tests/antunit/taskdefs/importtests/w.xml
+++ b/src/tests/antunit/taskdefs/importtests/w.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/x.xml b/src/tests/antunit/taskdefs/importtests/x.xml
index a509e57..adff20e 100644
--- a/src/tests/antunit/taskdefs/importtests/x.xml
+++ b/src/tests/antunit/taskdefs/importtests/x.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/y.xml b/src/tests/antunit/taskdefs/importtests/y.xml
index 0e54fa8..8bd6270 100644
--- a/src/tests/antunit/taskdefs/importtests/y.xml
+++ b/src/tests/antunit/taskdefs/importtests/y.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/importtests/z.xml b/src/tests/antunit/taskdefs/importtests/z.xml
index 607dee7..50700ec 100644
--- a/src/tests/antunit/taskdefs/importtests/z.xml
+++ b/src/tests/antunit/taskdefs/importtests/z.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/include-test.xml b/src/tests/antunit/taskdefs/include-test.xml
index 7e1a452..f8d5302 100644
--- a/src/tests/antunit/taskdefs/include-test.xml
+++ b/src/tests/antunit/taskdefs/include-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/jar-spi-test.xml b/src/tests/antunit/taskdefs/jar-spi-test.xml
index c05311a..c272978 100644
--- a/src/tests/antunit/taskdefs/jar-spi-test.xml
+++ b/src/tests/antunit/taskdefs/jar-spi-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/jar-test.xml b/src/tests/antunit/taskdefs/jar-test.xml
index c2c8834..2ae557a 100644
--- a/src/tests/antunit/taskdefs/jar-test.xml
+++ b/src/tests/antunit/taskdefs/jar-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -249,4 +249,89 @@
         resource="${output}/META-INF/MANIFEST.MF"/>
   </target>
 
+  <target name="multiReleaseJarPart1" description="https://openjdk.java.net/jeps/238">
+    <!-- Preparation of the 'MultiRelease-Project' -->
+    <property name="java8.src"  value="${input}/src/java"/>
+    <property name="java9.src"  value="${input}/src/java9"/>
+    <property name="java10.src" value="${input}/src/java10"/>
+    <property name="java8.classes"  value="${input}/build/classes"/>
+    <property name="java9.classes"  value="${input}/build/classes9"/>
+    <property name="java10.classes" value="${input}/build/classes10"/>
+    <macrodef name="create">
+      <attribute name="version" />
+      <sequential>
+        <local name="src"/>
+        <local name="classes"/>
+        <property name="src" value="${java@{version}.src}"/>
+        <property name="classes" value="${java@{version}.classes}"/>
+        <mkdir dir="${src}/org/apache/ant/test"/>
+        <echo file="${src}/org/apache/ant/test/MRJarTest.java">
+          package org.apache.ant.test;
+          public class MRJarTest {
+            public static final String VERSION = "Java@{version}";
+          }
+        </echo>
+        <mkdir dir="${classes}"/>
+        <javac srcdir="${src}" destdir="${classes}" debug="on" includeantruntime="false"/>
+      </sequential>
+    </macrodef>
+    <create version="8"/>
+    <create version="9"/>
+    <create version="10"/>
+    
+    <!-- Now create the MultiReleaseJar -->
+    <jar destfile="${antunit.tmpdir}/mrjar.jar">
+      <manifest>
+        <!-- special mf-entry according to the spec -->
+        <attribute name="Multi-Release" value="true"/>
+      </manifest>
+      <!-- directory structure according to the spec ... -->
+      <!-- ... default classes loadable by old (<Java9) versions -->
+      <fileset dir="${java8.classes}"/>
+      <!-- ... per release classes, require Java9+ for loadable via standard ClassLoader -->
+      <zipfileset prefix="META-INF/versions/9/" dir="${java9.classes}"/>
+      <zipfileset prefix="META-INF/versions/10/" dir="${java10.classes}"/>
+    </jar>
+    
+    <!-- Now some tests -->
+    <au:assertNestedResourceExists>
+      <zipentry zipfile="${antunit.tmpdir}/mrjar.jar" name="META-INF/versions/9/org/apache/ant/test/MRJarTest.class"/>
+    </au:assertNestedResourceExists>
+    <au:assertNestedResourceExists>
+      <zipentry zipfile="${antunit.tmpdir}/mrjar.jar" name="META-INF/versions/10/org/apache/ant/test/MRJarTest.class"/>
+    </au:assertNestedResourceExists>
+  </target>
+
+  <target name="testMultiReleaseJar" depends="multiReleaseJarPart1"
+          unless="build.sysclasspath.only"
+          description="most of the tests happen in , this target contains the part that cannot be tested insid Gump">
+    <loadresource property="valueFrom8">
+      <javaconstant name="org.apache.ant.test.MRJarTest.VERSION">
+        <classpath>
+          <pathelement location="${antunit.tmpdir}/mrjar.jar"/>
+        </classpath>
+      </javaconstant>
+    </loadresource>
+    <au:assertTrue>
+      <or>
+        <and>
+          <not>
+            <javaversion atleast="9"/>
+          </not>
+          <equals arg1="Java8" arg2="${valueFrom8}"/>
+        </and>
+
+        <and>
+          <javaversion exactly="9"/>
+          <equals arg1="Java9" arg2="${valueFrom8}"/>
+        </and>
+
+        <and>
+          <javaversion atleast="10"/>
+          <equals arg1="Java10" arg2="${valueFrom8}"/>
+        </and>
+      </or>
+    </au:assertTrue>
+  </target>
+
 </project>
diff --git a/src/tests/antunit/taskdefs/java-test.xml b/src/tests/antunit/taskdefs/java-test.xml
index db67316..b27489f 100644
--- a/src/tests/antunit/taskdefs/java-test.xml
+++ b/src/tests/antunit/taskdefs/java-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/javac-dir/bad-src/Bad.java b/src/tests/antunit/taskdefs/javac-dir/bad-src/Bad.java
index 3b749f8..89f79c6 100644
--- a/src/tests/antunit/taskdefs/javac-dir/bad-src/Bad.java
+++ b/src/tests/antunit/taskdefs/javac-dir/bad-src/Bad.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/antunit/taskdefs/javac-dir/good-src/Simple.java b/src/tests/antunit/taskdefs/javac-dir/good-src/Simple.java
index 9c08f56..c860b91 100644
--- a/src/tests/antunit/taskdefs/javac-dir/good-src/Simple.java
+++ b/src/tests/antunit/taskdefs/javac-dir/good-src/Simple.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/antunit/taskdefs/javac-test.xml b/src/tests/antunit/taskdefs/javac-test.xml
index 48ed15d..ab5e3eb 100644
--- a/src/tests/antunit/taskdefs/javac-test.xml
+++ b/src/tests/antunit/taskdefs/javac-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -193,6 +193,26 @@
     <au:assertLogContains text="adapter called" />
   </target>
 
+  <target name="testSpaceCharInArgs" depends="setup" description="https://bz.apache.org/bugzilla/show_bug.cgi?id=64912">
+    <delete dir="${javac-dir}/src" />
+    <mkdir dir="${javac-dir}/src" />
+    <echo file="${javac-dir}/src/Foo.java">
+      public class Foo { }
+    </echo>
+    <mkdir dir="${output}/foo with space bar" />
+    <javac srcdir="${javac-dir}/src" destdir="${output}/foo with space bar" fork="yes" failOnError="true"/>
+  </target>
+
+  <target name="test#CharInArgs" depends="setup" description="https://bz.apache.org/bugzilla/show_bug.cgi?id=64912">
+    <delete dir="${javac-dir}/src" />
+    <mkdir dir="${javac-dir}/src" />
+    <echo file="${javac-dir}/src/Foo.java">
+      public class Foo { }
+    </echo>
+    <mkdir dir="${output}/foo#bar" />
+    <javac srcdir="${javac-dir}/src" destdir="${output}/foo#bar" fork="yes" failOnError="true"/>
+  </target>
+
   <target name="testCompilerAsNestedElement" depends="-create-javac-adapter">
     <componentdef classname="org.example.Adapter" name="myjavac">
       <classpath location="${resources}" />
@@ -224,28 +244,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"/>
@@ -274,34 +273,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"/>
@@ -323,7 +294,7 @@
     </sequential>
   </target>
 
-  <target name="testJavacWithNativeHeaderGeneration" if="jdk1.8+" depends="setup">
+  <target name="testJavacWithNativeHeaderGeneration" depends="setup">
     <mkdir dir="${javac-dir}/src/org/example" />
     <mkdir dir="${javac-dir}/classes"/>
     <mkdir dir="${javac-dir}/headers"/>
diff --git a/src/tests/antunit/taskdefs/javadoc-test.xml b/src/tests/antunit/taskdefs/javadoc-test.xml
index 200082b..ca2e127 100644
--- a/src/tests/antunit/taskdefs/javadoc-test.xml
+++ b/src/tests/antunit/taskdefs/javadoc-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/length-test.xml b/src/tests/antunit/taskdefs/length-test.xml
index acd5310..c6bdf35 100644
--- a/src/tests/antunit/taskdefs/length-test.xml
+++ b/src/tests/antunit/taskdefs/length-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/loadproperties-test.xml b/src/tests/antunit/taskdefs/loadproperties-test.xml
index 04b53f1..f3ac9e9 100644
--- a/src/tests/antunit/taskdefs/loadproperties-test.xml
+++ b/src/tests/antunit/taskdefs/loadproperties-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/loadresource-test.xml b/src/tests/antunit/taskdefs/loadresource-test.xml
index 814ded5..7a92ec8 100644
--- a/src/tests/antunit/taskdefs/loadresource-test.xml
+++ b/src/tests/antunit/taskdefs/loadresource-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/local-test.xml b/src/tests/antunit/taskdefs/local-test.xml
index 9c4e7b7..8c4c51b 100644
--- a/src/tests/antunit/taskdefs/local-test.xml
+++ b/src/tests/antunit/taskdefs/local-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -93,4 +93,24 @@
     <au:assertPropertyEquals name="foo" value="foo" />
   </target>
 
+  <target name="testMulti">
+    <property name="bar" value="bar" />
+    <property name="baz" value="baz" />
+    <sequential>
+      <local>
+        <name>foo</name>
+        <name>bar</name>
+        <name>baz</name>
+      </local>
+      <property name="foo" value="FOO" />
+      <property name="bar" value="BAR" />
+      <property name="baz" value="BAZ" />
+      <au:assertPropertyEquals name="foo" value="FOO" />
+      <au:assertPropertyEquals name="bar" value="BAR" />
+      <au:assertPropertyEquals name="baz" value="BAZ" />
+    </sequential>
+    <au:assertPropertyEquals name="foo" value="foo" />
+    <au:assertPropertyEquals name="bar" value="bar" />
+    <au:assertPropertyEquals name="baz" value="baz" />
+  </target>
 </project>
diff --git a/src/tests/antunit/taskdefs/macrodef-test.xml b/src/tests/antunit/taskdefs/macrodef-test.xml
index b12e6f7..e45729e 100644
--- a/src/tests/antunit/taskdefs/macrodef-test.xml
+++ b/src/tests/antunit/taskdefs/macrodef-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/manifest-test.xml b/src/tests/antunit/taskdefs/manifest-test.xml
index 4247ef2..933e77f 100644
--- a/src/tests/antunit/taskdefs/manifest-test.xml
+++ b/src/tests/antunit/taskdefs/manifest-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/manifestclasspath-test.xml b/src/tests/antunit/taskdefs/manifestclasspath-test.xml
index 612990b..6f9d7d9 100644
--- a/src/tests/antunit/taskdefs/manifestclasspath-test.xml
+++ b/src/tests/antunit/taskdefs/manifestclasspath-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/move-test.xml b/src/tests/antunit/taskdefs/move-test.xml
index 9acac74..01c9807 100644
--- a/src/tests/antunit/taskdefs/move-test.xml
+++ b/src/tests/antunit/taskdefs/move-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/cab.xml b/src/tests/antunit/taskdefs/optional/cab.xml
index 4909107..b12517e 100644
--- a/src/tests/antunit/taskdefs/optional/cab.xml
+++ b/src/tests/antunit/taskdefs/optional/cab.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/depend/depend-test.xml b/src/tests/antunit/taskdefs/optional/depend/depend-test.xml
index 48f94aa..0d29915 100644
--- a/src/tests/antunit/taskdefs/optional/depend/depend-test.xml
+++ b/src/tests/antunit/taskdefs/optional/depend/depend-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/funtest-test.xml b/src/tests/antunit/taskdefs/optional/funtest-test.xml
index 6baa4f7..b5bba49 100644
--- a/src/tests/antunit/taskdefs/optional/funtest-test.xml
+++ b/src/tests/antunit/taskdefs/optional/funtest-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/javah-test.xml b/src/tests/antunit/taskdefs/optional/javah-test.xml
index 82d91c8..72f42b9 100644
--- a/src/tests/antunit/taskdefs/optional/javah-test.xml
+++ b/src/tests/antunit/taskdefs/optional/javah-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/junit/junit-formatter-test.xml b/src/tests/antunit/taskdefs/optional/junit/junit-formatter-test.xml
index b9a63c9..9cccdbd 100644
--- a/src/tests/antunit/taskdefs/optional/junit/junit-formatter-test.xml
+++ b/src/tests/antunit/taskdefs/optional/junit/junit-formatter-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/junit/junit-outputtoformatters-test.xml b/src/tests/antunit/taskdefs/optional/junit/junit-outputtoformatters-test.xml
index c84ae49..c55b275 100644
--- a/src/tests/antunit/taskdefs/optional/junit/junit-outputtoformatters-test.xml
+++ b/src/tests/antunit/taskdefs/optional/junit/junit-outputtoformatters-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/junit/junit-test.xml b/src/tests/antunit/taskdefs/optional/junit/junit-test.xml
index e6aa794..876afb8 100644
--- a/src/tests/antunit/taskdefs/optional/junit/junit-test.xml
+++ b/src/tests/antunit/taskdefs/optional/junit/junit-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/optional/junit/src/ExampleTest.java b/src/tests/antunit/taskdefs/optional/junit/src/ExampleTest.java
index f1e5ca2..e595f09 100644
--- a/src/tests/antunit/taskdefs/optional/junit/src/ExampleTest.java
+++ b/src/tests/antunit/taskdefs/optional/junit/src/ExampleTest.java
@@ -6,7 +6,7 @@
 (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
+    https://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,
diff --git a/src/tests/antunit/taskdefs/optional/junit/xmlformatter-test.xml b/src/tests/antunit/taskdefs/optional/junit/xmlformatter-test.xml
index 4aa6e4d..4616a43 100644
--- a/src/tests/antunit/taskdefs/optional/junit/xmlformatter-test.xml
+++ b/src/tests/antunit/taskdefs/optional/junit/xmlformatter-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/native2ascii-test.xml b/src/tests/antunit/taskdefs/optional/native2ascii-test.xml
index 8eff37c..0b36eb0 100644
--- a/src/tests/antunit/taskdefs/optional/native2ascii-test.xml
+++ b/src/tests/antunit/taskdefs/optional/native2ascii-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/propertyfile-test.xml b/src/tests/antunit/taskdefs/optional/propertyfile-test.xml
index 0ea7051..f8e1a8d 100644
--- a/src/tests/antunit/taskdefs/optional/propertyfile-test.xml
+++ b/src/tests/antunit/taskdefs/optional/propertyfile-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/propertyfilelayout-test.xml b/src/tests/antunit/taskdefs/optional/propertyfilelayout-test.xml
index f1b367f..8f0efd2 100644
--- a/src/tests/antunit/taskdefs/optional/propertyfilelayout-test.xml
+++ b/src/tests/antunit/taskdefs/optional/propertyfilelayout-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/replaceregexp-test.xml b/src/tests/antunit/taskdefs/optional/replaceregexp-test.xml
index 2d64ce7..4021bc6 100644
--- a/src/tests/antunit/taskdefs/optional/replaceregexp-test.xml
+++ b/src/tests/antunit/taskdefs/optional/replaceregexp-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/script/script-test.xml b/src/tests/antunit/taskdefs/optional/script/script-test.xml
new file mode 100644
index 0000000..a003c2f
--- /dev/null
+++ b/src/tests/antunit/taskdefs/optional/script/script-test.xml
@@ -0,0 +1,70 @@
+<?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
+
+      https://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" />
+
+  <target name="setUp">
+    <condition property="expect-js">
+      <not>
+        <and>
+          <isset property="jenkins" />
+          <javaversion atleast="15" />
+        </and>
+      </not>
+    </condition>
+    <echo>$${expect-js}=${expect-js}</echo>
+  </target>
+
+  <target name="test-available-property-default" depends="setUp" if="expect-js">
+    <property name="foo" value="FOO" />
+    <script language="javascript">
+      project.setProperty('bar', foo);
+    </script>
+    <au:assertEquals expected="${foo}" actual="${bar}" />
+  </target>
+
+  <target name="test-available-property-setbeans-false" depends="setUp" if="expect-js">
+    <property name="baz" value="BAZ" />
+    <au:expectfailure>
+      <script language="javascript" setbeans="false">
+        project.log(nosuch);
+        var b = (baz == project.getProperty('baz'));
+      </script>
+    </au:expectfailure>
+  </target>
+
+  <target name="test-available-local-property" depends="setUp" if="expect-js">
+    <local name="localproperty" />
+    <property name="localproperty" value="iamlocal" />
+    <script language="javascript">
+      if (localproperty != project.getProperty('localproperty')) throw new org.apache.tools.ant.BuildException();
+    </script>
+  </target>
+
+  <target name="test-shaded-local-property" depends="setUp" if="expect-js">
+    <property name="shademe" value="FOO" />
+    <sequential>
+      <local name="shademe" />
+      <property name="shademe" value="BAR" />
+      <script language="javascript">
+        if (shademe != project.getProperty('shademe')) throw new org.apache.tools.ant.BuildException();
+      </script>
+    </sequential>
+  </target>
+
+</project>
diff --git a/src/tests/antunit/taskdefs/optional/script/scriptdef-test.xml b/src/tests/antunit/taskdefs/optional/script/scriptdef-test.xml
index da78e42..62ddda6 100644
--- a/src/tests/antunit/taskdefs/optional/script/scriptdef-test.xml
+++ b/src/tests/antunit/taskdefs/optional/script/scriptdef-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -26,13 +26,17 @@
   </description>
 
   <condition property="prereqs-ok">
-    <or>
-      <and>
-        <available classname="org.apache.bsf.BSFManager" />
-        <available classname="org.apache.bsf.engines.javascript.JavaScriptEngine" />
-      </and>
-      <available classname="javax.script.ScriptEngineManager" />
-    </or>
+    <and>
+      <!-- Starting Java 15, there's no "javascript" script engine (not even nashorn) bundled in JRE -->
+      <javaversion atmost="14"/>
+      <or>
+        <and>
+          <available classname="org.apache.bsf.BSFManager" />
+          <available classname="org.apache.bsf.engines.javascript.JavaScriptEngine" />
+        </and>
+        <available classname="javax.script.ScriptEngineManager" />
+      </or>
+    </and>
   </condition>
 
   <!-- auto doesn't verify the language is supported and selects BSF
@@ -56,6 +60,7 @@
     <scriptdef language="javascript" name="scripttest" manager="${script.manager}">
       <!-- optional property attribute-->
       <attribute name="property" />
+      <attribute name="propertywithdefault" default="prop_dv" />
     </scriptdef>
   </presetdef>
 
@@ -65,7 +70,6 @@
     <au:assertPropertyEquals name="property" value="live" />
   </presetdef>
 
-
   <!--purely to test that everything works -->
   <target name="testInline" if="prereqs-ok">
     <js>self.log("Hello");</js>
@@ -128,4 +132,37 @@
       <quickfail />
     </au:expectfailure>
   </target>
+
+  <target name="testAttribute" if="prereqs-ok">
+    <js>
+      project.setNewProperty(attributes.get('property'), 'live');
+    </js>
+    <scripttest property="property" />
+    <assertPropSet />
+  </target>
+
+  <target name="testAttributeDefaultValue" if="prereqs-ok">
+    <js>
+      project.setNewProperty(attributes.get('propertywithdefault'), 'live');
+    </js>
+    <scripttest />
+    <assertPropSet name="prop_dv" />
+  </target>
+
+  <target name="testInvalidAttribute" if="prereqs-ok">
+    <js />
+    <au:expectfailure expectedMessage="does not support">
+      <scripttest foo="bar" />
+    </au:expectfailure>
+  </target>
+
+  <target name="testSetbeans" if="prereqs-ok">
+    <js setbeans="true">
+      project.setNewProperty('property', sourceProperty)
+    </js>
+    <property name="sourceProperty" value="live" />
+    <scripttest />
+    <assertPropSet />
+  </target>
+
 </project>
diff --git a/src/tests/antunit/taskdefs/optional/unix/symlink-test.xml b/src/tests/antunit/taskdefs/optional/unix/symlink-test.xml
index 90c57f4..de2bdec 100644
--- a/src/tests/antunit/taskdefs/optional/unix/symlink-test.xml
+++ b/src/tests/antunit/taskdefs/optional/unix/symlink-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/taskdefs/optional/windows/attrib-test.xml b/src/tests/antunit/taskdefs/optional/windows/attrib-test.xml
index d5cea2b..07d4134 100644
--- a/src/tests/antunit/taskdefs/optional/windows/attrib-test.xml
+++ b/src/tests/antunit/taskdefs/optional/windows/attrib-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/optional/xz/unxz-test.xml b/src/tests/antunit/taskdefs/optional/xz/unxz-test.xml
new file mode 100644
index 0000000..89252b7
--- /dev/null
+++ b/src/tests/antunit/taskdefs/optional/xz/unxz-test.xml
@@ -0,0 +1,63 @@
+<?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
+
+      https://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" />
+
+  <target name="setup">
+    <mkdir dir="${output}"/>
+    <available property="xz.present" classname="org.tukaani.xz.XZOutputStream"/>
+  </target>
+
+  <target name="testWithFileResourceToFile" depends="setup" if="xz.present">
+    <unxz dest="${output}/asf-logo.gif">
+      <file file="../../../../../etc/testcases/taskdefs/expected/asf-logo.gif.xz"/>
+    </unxz>
+    <au:assertFilesMatch expected="../../../../../etc/testcases/asf-logo.gif"
+                         actual="${output}/asf-logo.gif"/>
+  </target>
+
+  <target name="testWithFileResourceToDirectory" depends="setup" if="xz.present">
+    <unxz dest="${output}">
+      <file file="../../../../../etc/testcases/taskdefs/expected/asf-logo.gif.xz"/>
+    </unxz>
+    <au:assertFilesMatch expected="../../../../../etc/testcases/asf-logo.gif"
+                         actual="${output}/asf-logo.gif"/>
+  </target>
+
+  <target name="testWithNonFileResourceToFile" depends="setup" if="xz.present">
+    <unxz dest="${output}/greeting.txt">
+      <url url="https://ant.apache.org/webtest/xz/greeting.txt.xz"/>
+    </unxz>
+    <get src="https://ant.apache.org/webtest/gunzip/greeting.txt"
+         dest="${output}/orig.greeting.txt"/>
+    <au:assertFilesMatch expected="${output}/orig.greeting.txt"
+                         actual="${output}/greeting.txt"/>
+  </target>
+
+  <target name="testWithNonFileResourceToDir" depends="setup" if="xz.present">
+    <unxz dest="${output}">
+      <url url="https://ant.apache.org/webtest/xz/greeting.txt.xz"/>
+    </unxz>
+    <get src="https://ant.apache.org/webtest/gunzip/greeting.txt"
+         dest="${output}/orig.greeting.txt"/>
+    <au:assertFilesMatch expected="${output}/orig.greeting.txt"
+                         actual="${output}/greeting.txt"/>
+  </target>
+
+</project>
+
diff --git a/src/tests/antunit/taskdefs/optional/xz/xz-test.xml b/src/tests/antunit/taskdefs/optional/xz/xz-test.xml
new file mode 100644
index 0000000..706f46b
--- /dev/null
+++ b/src/tests/antunit/taskdefs/optional/xz/xz-test.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+   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
+
+       https://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">
+
+    <!-- note relies on antunit 1.1 -->
+    <import file="../../../antunit-base.xml" />
+
+    <target name="setUp">
+        <mkdir dir="${output}" />
+        <mkdir dir="${output}/empty" />
+        <touch file="${output}/fileone" />
+        <touch file="${output}/filetwo" />
+        <available property="xz.present" classname="org.tukaani.xz.XZOutputStream"/>
+    </target>
+
+    <target name="testFailNone" if="xz.present">
+        <au:expectfailure expectedmessage="No resource selected, xz needs exactly one resource." message="Should have thrown an exception">
+            <xz destfile="${output}/file.gz">
+                <fileset dir="${output}/empty" />
+            </xz>
+        </au:expectfailure>
+    </target>
+
+    <target name="testFailTwo" if="xz.present">
+        <au:expectfailure expectedmessage="xz cannot handle multiple resources at once. (2 resources were selected.)" message="Should have thrown an exception">
+            <xz destfile="${output}/file.xz">
+                <fileset dir="${output}" />
+            </xz>
+        </au:expectfailure>
+    </target>
+
+</project>
diff --git a/src/tests/antunit/taskdefs/parallel-test.xml b/src/tests/antunit/taskdefs/parallel-test.xml
index 72e4828..18422ad 100644
--- a/src/tests/antunit/taskdefs/parallel-test.xml
+++ b/src/tests/antunit/taskdefs/parallel-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/pathconvert-test.xml b/src/tests/antunit/taskdefs/pathconvert-test.xml
index 3683aff..02ca110 100644
--- a/src/tests/antunit/taskdefs/pathconvert-test.xml
+++ b/src/tests/antunit/taskdefs/pathconvert-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -28,4 +28,105 @@
     </au:assertTrue>
   </target>
 
+  <path id="testpath">
+      <pathelement path="${ant.file}" />
+  </path>
+
+  <basename property="basename" file="${ant.file}" />
+
+  <target name="testmap">
+      <pathconvert property="result" dirsep="#">
+          <path refid="testpath" />
+          <map from="${basedir}" to="test" />
+      </pathconvert>
+      <au:assertPropertyEquals name="result" value="test#${basename}" />
+  </target>
+
+  <target name="testmapper">
+      <pathconvert property="result" dirsep="#">
+          <path refid="testpath" />
+          <mapper type="glob" from="${basedir}*" to="test*" />
+      </pathconvert>
+      <au:assertPropertyEquals name="result" value="test#${basename}" />
+  </target>
+
+  <target name="testnotargetos">
+      <pathconvert property="result" refid="testpath" />
+      <au:assertPropertyEquals name="result" value="${ant.file}" />
+  </target>
+
+  <target name="test-nonmatching-mapper" description="test for bug fix bz-62076">
+      <mkdir dir="${output}/mapper-source-dir"/>
+      <!-- create 2 files, one of which will be matched/included by the globmapper
+      later in this target -->
+      <touch file="${output}/mapper-source-dir/file1.txt"/>
+      <touch file="${output}/mapper-source-dir/file2.log"/>
+
+      <pathconvert property="pc">
+          <mappedresources>
+              <fileset dir="${output}/mapper-source-dir"/>
+              <!-- we intentionally exclude one of the files -->
+              <globmapper from="*.log" to="*.txt"/>
+          </mappedresources>
+      </pathconvert>
+
+      <au:assertPropertyEquals name="pc" value="file2.txt" />
+  </target>
+
+  <target name="testRef">
+      <pathconvert property="result" refid="testpath" />
+      <au:assertPropertyEquals name="result" value="${ant.file}" />
+  </target>
+
+  <target name="testConsole">
+      <pathconvert refid="testpath" />
+      <au:assertLogContains text="${ant.file}" />
+  </target>
+
+  <target name="testPreserveDuplicates">
+      <pathconvert property="result" pathsep=") " preserveduplicates="true">
+          <resources>
+              <path refid="testpath" />
+              <path refid="testpath" />
+          </resources>
+      </pathconvert>
+      <au:assertPropertyEquals name="result" value="${ant.file}) ${ant.file}" />
+  </target>
+
+  <target name="testDirsep">
+      <pathconvert property="result" dirsep="|">
+          <file file="foo/bar/baz" />
+          <globmapper from="${basedir}/*" to="*" handledirsep="true" />
+      </pathconvert>
+      <au:assertPropertyEquals name="result" value="foo|bar|baz" />
+  </target>
+
+  <target name="testNoSetonempty">
+      <pathconvert property="result" setonempty="false">
+          <resources />
+      </pathconvert>
+      <au:assertFalse>
+          <isset property="result" />
+      </au:assertFalse>
+  </target>
+
+  <target name="testDest">
+      <au:assertFileDoesntExist file="${output}/destfile" />
+      <pathconvert dest="${output}/destfile">
+          <file file="${ant.file}" />
+      </pathconvert>
+      <au:assertFileExists file="${output}/destfile" />
+      <au:assertTrue>
+        <resourcesmatch astext="true">
+          <file file="${output}/destfile" />
+          <string value="${ant.file}" />
+        </resourcesmatch>
+      </au:assertTrue>
+  </target>
+
+  <target name="testDestPropertyMutex">
+      <au:expectfailure message="@property and @dest are mutually exclusive">
+          <pathconvert property="someprop" dest="somefile" refid="testpath" />
+      </au:expectfailure>
+  </target>
 </project>
diff --git a/src/tests/antunit/taskdefs/property-test.xml b/src/tests/antunit/taskdefs/property-test.xml
index 2eb0e18..59f000f 100644
--- a/src/tests/antunit/taskdefs/property-test.xml
+++ b/src/tests/antunit/taskdefs/property-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
@@ -154,7 +154,7 @@
   <!-- 
   Problems with @-sign discussed on the mailinglist.
   Seems to work.
-  http://mail-archives.apache.org/mod_mbox/ant-user/201412.mbox/%3CCAPxjwW%2BQKFFj45O-ZbCGOnAkJXe9KJ5qKtVQCvS2x7hObRJmkQ%40mail.gmail.com%3E
+  https://mail-archives.apache.org/mod_mbox/ant-user/201412.mbox/%3CCAPxjwW%2BQKFFj45O-ZbCGOnAkJXe9KJ5qKtVQCvS2x7hObRJmkQ%40mail.gmail.com%3E
   -->
   <target name="testAtSign">
     <mkdir dir="${input}"/>
diff --git a/src/tests/antunit/taskdefs/propertyfile-test.xml b/src/tests/antunit/taskdefs/propertyfile-test.xml
index b02cfa4..bda7c2a 100644
--- a/src/tests/antunit/taskdefs/propertyfile-test.xml
+++ b/src/tests/antunit/taskdefs/propertyfile-test.xml
@@ -7,7 +7,7 @@
    (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
+   https://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,
diff --git a/src/tests/antunit/taskdefs/propertyhelper-test.xml b/src/tests/antunit/taskdefs/propertyhelper-test.xml
index f86342e..2eecb4a 100644
--- a/src/tests/antunit/taskdefs/propertyhelper-test.xml
+++ b/src/tests/antunit/taskdefs/propertyhelper-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/taskdefs/replace-test.xml b/src/tests/antunit/taskdefs/replace-test.xml
index e7aa118..61d93ad 100644
--- a/src/tests/antunit/taskdefs/replace-test.xml
+++ b/src/tests/antunit/taskdefs/replace-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/retry-test.xml b/src/tests/antunit/taskdefs/retry-test.xml
index e81853b..fc99537 100644
--- a/src/tests/antunit/taskdefs/retry-test.xml
+++ b/src/tests/antunit/taskdefs/retry-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -26,7 +26,7 @@
 
   <target name="test-fail-and-retry" depends="setUp">
     <!-- just in case this ever becomes a legit url... -->
-    <property name="src" value="http://iojasodjojaosdj"/>
+    <property name="src" value="https://iojasodjojaosdj"/>
     <au:expectfailure expectedmessage="Task [get] failed after [${i}] attempts; giving up">
       <retry retrycount="${i}">
         <get src="${src}" dest="${dest}"/>
diff --git a/src/tests/antunit/taskdefs/rmic-test.xml b/src/tests/antunit/taskdefs/rmic-test.xml
index 3fdf5a5..58c3c00 100644
--- a/src/tests/antunit/taskdefs/rmic-test.xml
+++ b/src/tests/antunit/taskdefs/rmic-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/secure-input.xml b/src/tests/antunit/taskdefs/secure-input.xml
index 8311ce9..0ef1f72 100644
--- a/src/tests/antunit/taskdefs/secure-input.xml
+++ b/src/tests/antunit/taskdefs/secure-input.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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..a7d99d6
--- /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
+
+      https://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/signjar-test.xml b/src/tests/antunit/taskdefs/signjar-test.xml
index 8fff479..b118f3c 100644
--- a/src/tests/antunit/taskdefs/signjar-test.xml
+++ b/src/tests/antunit/taskdefs/signjar-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/subant-helper/echo.xml b/src/tests/antunit/taskdefs/subant-helper/echo.xml
index 24f445c..957d0b2 100644
--- a/src/tests/antunit/taskdefs/subant-helper/echo.xml
+++ b/src/tests/antunit/taskdefs/subant-helper/echo.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/subant-test.xml b/src/tests/antunit/taskdefs/subant-test.xml
index 3bc4405..d9b9c1e 100644
--- a/src/tests/antunit/taskdefs/subant-test.xml
+++ b/src/tests/antunit/taskdefs/subant-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/sync-test.xml b/src/tests/antunit/taskdefs/sync-test.xml
index 21a1442..54c8b00 100644
--- a/src/tests/antunit/taskdefs/sync-test.xml
+++ b/src/tests/antunit/taskdefs/sync-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/tar-test.xml b/src/tests/antunit/taskdefs/tar-test.xml
index 1aac9a8..79644b3 100644
--- a/src/tests/antunit/taskdefs/tar-test.xml
+++ b/src/tests/antunit/taskdefs/tar-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -24,6 +24,7 @@
   <target name="setUp">
     <mkdir dir="${input}" />
     <mkdir dir="${output}" />
+    <available property="xz.present" classname="org.tukaani.xz.XZOutputStream"/>
   </target>
 
   <target name="testTarFilesetHandlesFilesetReferences" depends="setUp">
@@ -115,4 +116,47 @@
     <untar dest="${output}" src="${output}/x.tar"/>
     <au:assertFileExists file="${output}/${longfile.file.name}"/>
   </target>
+
+  <target name="testGzipCompression" depends="setUp">
+    <au:assertFileExists file="../../../etc/testcases/asf-logo.gif"/>
+    <tar destfile="${input}/asf-logo.gif.tar.gz" compression="gzip">
+      <file file="../../../etc/testcases/asf-logo.gif"/>
+    </tar>
+    <gunzip dest="${input}/asf-logo.gif.tar">
+      <file file="${input}/asf-logo.gif.tar.gz"/>
+    </gunzip>
+    <untar src="${input}/asf-logo.gif.tar" dest="${output}"/>
+    <au:assertFilesMatch
+        expected="../../../etc/testcases/asf-logo.gif"
+        actual="${output}/asf-logo.gif"/>
+  </target>
+
+  <target name="testBzip2Compression" depends="setUp">
+    <au:assertFileExists file="../../../etc/testcases/asf-logo.gif"/>
+    <tar destfile="${input}/asf-logo.gif.tar.bz2" compression="bzip2">
+      <file file="../../../etc/testcases/asf-logo.gif"/>
+    </tar>
+    <bunzip2 dest="${input}/asf-logo.gif.tar">
+      <file file="${input}/asf-logo.gif.tar.bz2"/>
+    </bunzip2>
+    <untar src="${input}/asf-logo.gif.tar" dest="${output}"/>
+    <au:assertFilesMatch
+        expected="../../../etc/testcases/asf-logo.gif"
+        actual="${output}/asf-logo.gif"/>
+  </target>
+
+  <target name="testXzCompression" depends="setUp" if="xz.present">
+    <au:assertFileExists file="../../../etc/testcases/asf-logo.gif"/>
+    <tar destfile="${input}/asf-logo.gif.tar.xz" compression="xz">
+      <file file="../../../etc/testcases/asf-logo.gif"/>
+    </tar>
+    <unxz dest="${input}/asf-logo.gif.tar">
+      <file file="${input}/asf-logo.gif.tar.xz"/>
+    </unxz>
+    <untar src="${input}/asf-logo.gif.tar" dest="${output}"/>
+    <au:assertFilesMatch
+        expected="../../../etc/testcases/asf-logo.gif"
+        actual="${output}/asf-logo.gif"/>
+  </target>
+
 </project>
diff --git a/src/tests/antunit/taskdefs/taskdef-antlib-test.xml b/src/tests/antunit/taskdefs/taskdef-antlib-test.xml
index b03911e..5261e51 100644
--- a/src/tests/antunit/taskdefs/taskdef-antlib-test.xml
+++ b/src/tests/antunit/taskdefs/taskdef-antlib-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/antunit/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 0244270..aeb3587 100644
--- a/src/tests/antunit/taskdefs/taskdef-test.xml
+++ b/src/tests/antunit/taskdefs/taskdef-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/tempfile-test.xml b/src/tests/antunit/taskdefs/tempfile-test.xml
index 1132007..42bcecc 100644
--- a/src/tests/antunit/taskdefs/tempfile-test.xml
+++ b/src/tests/antunit/taskdefs/tempfile-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/touch-test.xml b/src/tests/antunit/taskdefs/touch-test.xml
index a9327ed..8abdf37 100644
--- a/src/tests/antunit/taskdefs/touch-test.xml
+++ b/src/tests/antunit/taskdefs/touch-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/truncate/truncate-test.xml b/src/tests/antunit/taskdefs/truncate/truncate-test.xml
index 86f896c..209eaba 100644
--- a/src/tests/antunit/taskdefs/truncate/truncate-test.xml
+++ b/src/tests/antunit/taskdefs/truncate/truncate-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/tstamp-test.xml b/src/tests/antunit/taskdefs/tstamp-test.xml
index c9bebf8..434adf8 100644
--- a/src/tests/antunit/taskdefs/tstamp-test.xml
+++ b/src/tests/antunit/taskdefs/tstamp-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -18,10 +18,93 @@
 <project default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
   <import file="../antunit-base.xml" />
 
-  <target name="testMagicProperty">
+  <target name="-adjust-for-offset-at-epoch">
+    <property name="ant-package" location="${input}/org/apache/ant"/>
+    <mkdir dir="${ant-package}"/>
+    <mkdir dir="${output}"/>
+    <echo file="${ant-package}/IsEpochIn1969Here.java"><![CDATA[
+package org.apache.ant;
+
+import org.apache.tools.ant.taskdefs.condition.Condition;
+import java.util.Calendar;
+import java.util.Date;
+
+public class IsEpochIn1969Here implements Condition {
+    @Override
+    public boolean eval() {
+        final Calendar c = Calendar.getInstance();
+        c.setTime(new Date(0));
+        final int offset = (c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET));
+        return offset < 0;
+    }
+}
+]]></echo>
+    <javac srcdir="${input}" destdir="${output}"/>
+    <typedef name="isepochin1969here" classname="org.apache.ant.IsEpochIn1969Here">
+      <classpath>
+        <pathelement location="${output}"/>
+      </classpath>
+    </typedef>
+    <condition property="expected-dstamp" value="19700101">
+      <isepochin1969here/>
+    </condition>
+    <property name="expected-dstamp" value="19700102"/>
+    <echo>${expected-dstamp}</echo>
+  </target>
+
+  <target name="testMagicProperty" depends="-adjust-for-offset-at-epoch">
     <local name="ant.tstamp.now"/>
-    <property name="ant.tstamp.now" value="100000"/>
+    <property name="ant.tstamp.now" value="86400"/>
     <tstamp/>
-    <au:assertPropertyEquals name="DSTAMP" value="19700102"/>
+    <au:assertPropertyEquals name="DSTAMP" value="${expected-dstamp}"/>
+  </target>
+
+  <target name="testMagicPropertyIso">
+    <local name="ant.tstamp.now.iso"/>
+    <property name="ant.tstamp.now.iso" value="1972-04-17T08:07:00Z"/>
+    <tstamp/>
+    <au:assertPropertyEquals name="DSTAMP" value="19720417"/>
+  </target>
+
+  <target name="testMagicPropertyBoth">
+    <local name="ant.tstamp.now"/>
+    <local name="ant.tstamp.now.iso"/>
+    <property name="ant.tstamp.now" value="100000"/>
+    <property name="ant.tstamp.now.iso" value="1972-04-17T08:07:22Z"/>
+    <tstamp/>
+    <!-- 'iso' overrides 'simple' -->
+    <au:assertPropertyEquals name="DSTAMP" value="19720417"/>
+  </target>
+
+  <target name="testSourceDateEpoch">
+    <mkdir dir="${input}"/>
+    <mkdir dir="${output}"/>
+    <echo file="${input}/TstampAntunitTest.java"><![CDATA[
+      import org.apache.tools.ant.*;
+      import org.apache.tools.ant.taskdefs.*;
+      public class TstampAntunitTest {
+        public static void main(String[] args) {
+          Task task = new Tstamp();
+          task.setProject(new Project());
+          task.execute();
+          String today = task.getProject().getProperty("TODAY");
+          System.out.println("TODAY is " + today);
+        }
+      }
+    ]]></echo>
+    <javac srcdir="${input}" destdir="${output}"/>
+    <local name="testout"/>
+    <java classname="TstampAntunitTest"
+          failonerror="true"
+          outputproperty="testout"
+          fork="true">
+      <sysproperty key="user.timezone" value="GMT"/>
+      <classpath>
+        <pathelement location="${output}"/>
+        <pathelement path="${java.class.path}"/>
+      </classpath>
+      <env key="SOURCE_DATE_EPOCH" value="1650585600"/>
+    </java>
+    <au:assertEquals expected="TODAY is April 22 2022" actual="${testout}"/>
   </target>
 </project>
diff --git a/src/tests/antunit/taskdefs/untar-test.xml b/src/tests/antunit/taskdefs/untar-test.xml
new file mode 100644
index 0000000..403541f
--- /dev/null
+++ b/src/tests/antunit/taskdefs/untar-test.xml
@@ -0,0 +1,61 @@
+<?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
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<project name="untar-test" default="antunit"
+         xmlns:au="antlib:org.apache.ant.antunit">
+  <import file="../antunit-base.xml" />
+
+  <target name="setUp">
+    <mkdir dir="${input}"/>
+    <mkdir dir="${output}/expected" />
+    <mkdir dir="${output}/actual" />
+    <available property="xz.present" classname="org.tukaani.xz.XZOutputStream"/>
+  </target>
+
+  <target name="testGzipCompression" depends="setUp">
+    <untar src="../../../etc/testcases/taskdefs/expected/asf-logo.gif.tar"
+           dest="${output}/expected"/>
+    <untar src="../../../etc/testcases/taskdefs/expected/asf-logo.gif.tar.gz"
+           compression="gzip"
+           dest="${output}/actual"/>
+    <au:assertFilesMatch expected="${output}/expected/asf-logo.gif"
+                         actual="${output}/actual/asf-logo.gif"/>
+  </target>
+
+  <target name="testBzip2Compression" depends="setUp">
+    <untar src="../../../etc/testcases/taskdefs/expected/asf-logo.gif.tar"
+           dest="${output}/expected"/>
+    <untar src="../../../etc/testcases/taskdefs/expected/asf-logo.gif.tar.bz2"
+           compression="bzip2"
+           dest="${output}/actual"/>
+    <au:assertFilesMatch expected="${output}/expected/asf-logo.gif"
+                         actual="${output}/actual/asf-logo.gif"/>
+  </target>
+
+  <target name="testXZCompression" depends="setUp" if="xz.present">
+    <untar src="../../../etc/testcases/taskdefs/expected/asf-logo.gif.tar"
+           dest="${output}/expected"/>
+    <xz destfile="${input}/asf-logo.gif.tar.xz"
+        src="../../../etc/testcases/taskdefs/expected/asf-logo.gif.tar"/>
+    <untar src="${input}/asf-logo.gif.tar.xz"
+           compression="xz"
+           dest="${output}/actual"/>
+    <au:assertFilesMatch expected="${output}/expected/asf-logo.gif"
+                         actual="${output}/actual/asf-logo.gif"/>
+  </target>
+</project>
diff --git a/src/tests/antunit/taskdefs/unzip-test.xml b/src/tests/antunit/taskdefs/unzip-test.xml
index bdf5f61..e3ed436 100644
--- a/src/tests/antunit/taskdefs/unzip-test.xml
+++ b/src/tests/antunit/taskdefs/unzip-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/uptodate-test.xml b/src/tests/antunit/taskdefs/uptodate-test.xml
index e477803..fcc8b93 100644
--- a/src/tests/antunit/taskdefs/uptodate-test.xml
+++ b/src/tests/antunit/taskdefs/uptodate-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/war-test.xml b/src/tests/antunit/taskdefs/war-test.xml
index e264ebd..78ba57f 100644
--- a/src/tests/antunit/taskdefs/war-test.xml
+++ b/src/tests/antunit/taskdefs/war-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/web.xml b/src/tests/antunit/taskdefs/web.xml
index 414625a..5898729 100644
--- a/src/tests/antunit/taskdefs/web.xml
+++ b/src/tests/antunit/taskdefs/web.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/whichresource-test.xml b/src/tests/antunit/taskdefs/whichresource-test.xml
index 6bf5a88..be8648c 100644
--- a/src/tests/antunit/taskdefs/whichresource-test.xml
+++ b/src/tests/antunit/taskdefs/whichresource-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/xmlproperty-test.xml b/src/tests/antunit/taskdefs/xmlproperty-test.xml
index 5be0420..b664d22 100644
--- a/src/tests/antunit/taskdefs/xmlproperty-test.xml
+++ b/src/tests/antunit/taskdefs/xmlproperty-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/xmlproperty.inline-expansion.xml b/src/tests/antunit/taskdefs/xmlproperty.inline-expansion.xml
index a915179..87f9c42 100644
--- a/src/tests/antunit/taskdefs/xmlproperty.inline-expansion.xml
+++ b/src/tests/antunit/taskdefs/xmlproperty.inline-expansion.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/xmlproperty.multi.xml b/src/tests/antunit/taskdefs/xmlproperty.multi.xml
index 9899c58..4c37ece 100644
--- a/src/tests/antunit/taskdefs/xmlproperty.multi.xml
+++ b/src/tests/antunit/taskdefs/xmlproperty.multi.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/taskdefs/xslt-test.xml b/src/tests/antunit/taskdefs/xslt-test.xml
index d6f6d66..2d88350 100644
--- a/src/tests/antunit/taskdefs/xslt-test.xml
+++ b/src/tests/antunit/taskdefs/xslt-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/taskdefs/xslt/printParams-invalid.xsl b/src/tests/antunit/taskdefs/xslt/printParams-invalid.xsl
index 36d404e..e045a53 100644
--- a/src/tests/antunit/taskdefs/xslt/printParams-invalid.xsl
+++ b/src/tests/antunit/taskdefs/xslt/printParams-invalid.xsl
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/taskdefs/zip-test.xml b/src/tests/antunit/taskdefs/zip-test.xml
index 7ff45c1..d1dc72b 100644
--- a/src/tests/antunit/taskdefs/zip-test.xml
+++ b/src/tests/antunit/taskdefs/zip-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/build-embedded-ref.xml b/src/tests/antunit/types/build-embedded-ref.xml
index f2cbd2a..f90d0e6 100644
--- a/src/tests/antunit/types/build-embedded-ref.xml
+++ b/src/tests/antunit/types/build-embedded-ref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/conditions/isreference-test.xml b/src/tests/antunit/types/conditions/isreference-test.xml
index 8929e90..f476e6c 100644
--- a/src/tests/antunit/types/conditions/isreference-test.xml
+++ b/src/tests/antunit/types/conditions/isreference-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/types/conditions/matches-test.xml b/src/tests/antunit/types/conditions/matches-test.xml
index 5d17461..f0cb71c 100644
--- a/src/tests/antunit/types/conditions/matches-test.xml
+++ b/src/tests/antunit/types/conditions/matches-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/cutdirs-test.xml b/src/tests/antunit/types/cutdirs-test.xml
index 64f0652..2ff7366 100644
--- a/src/tests/antunit/types/cutdirs-test.xml
+++ b/src/tests/antunit/types/cutdirs-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/defer-reference-test.xml b/src/tests/antunit/types/defer-reference-test.xml
index a67ad3b..5f4996d 100644
--- a/src/tests/antunit/types/defer-reference-test.xml
+++ b/src/tests/antunit/types/defer-reference-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/fileset-test.xml b/src/tests/antunit/types/fileset-test.xml
index ea39dec..d67509d 100644
--- a/src/tests/antunit/types/fileset-test.xml
+++ b/src/tests/antunit/types/fileset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/filterset-test.xml b/src/tests/antunit/types/filterset-test.xml
index f1654f6..ae457c4 100644
--- a/src/tests/antunit/types/filterset-test.xml
+++ b/src/tests/antunit/types/filterset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/firstmatch-test.xml b/src/tests/antunit/types/firstmatch-test.xml
index 68c332b..20ba049 100644
--- a/src/tests/antunit/types/firstmatch-test.xml
+++ b/src/tests/antunit/types/firstmatch-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/javaresource-test.xml b/src/tests/antunit/types/javaresource-test.xml
index d0e99e0..294628f 100644
--- a/src/tests/antunit/types/javaresource-test.xml
+++ b/src/tests/antunit/types/javaresource-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/mapper-ref.xml b/src/tests/antunit/types/mapper-ref.xml
index 3ada7f3..af4d46b 100644
--- a/src/tests/antunit/types/mapper-ref.xml
+++ b/src/tests/antunit/types/mapper-ref.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/mappers/glob-test.xml b/src/tests/antunit/types/mappers/glob-test.xml
index c4d92da..f4e0863 100644
--- a/src/tests/antunit/types/mappers/glob-test.xml
+++ b/src/tests/antunit/types/mappers/glob-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/mappers/packagemapper-test.xml b/src/tests/antunit/types/mappers/packagemapper-test.xml
index cad0146..a281162 100644
--- a/src/tests/antunit/types/mappers/packagemapper-test.xml
+++ b/src/tests/antunit/types/mappers/packagemapper-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/modified-selector-test.xml b/src/tests/antunit/types/modified-selector-test.xml
index 16688ca..f52b8f9 100644
--- a/src/tests/antunit/types/modified-selector-test.xml
+++ b/src/tests/antunit/types/modified-selector-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/optional/scriptcondition-test.xml b/src/tests/antunit/types/optional/scriptcondition-test.xml
new file mode 100644
index 0000000..d136b0d
--- /dev/null
+++ b/src/tests/antunit/types/optional/scriptcondition-test.xml
@@ -0,0 +1,99 @@
+<?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
+
+      https://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" />
+
+  <target name="setUp">
+    <condition property="expect-js">
+      <not>
+        <and>
+          <isset property="jenkins" />
+          <javaversion atleast="15" />
+        </and>
+      </not>
+    </condition>
+    <echo>$${expect-js}=${expect-js}</echo>
+  </target>
+
+  <target name="test-default-behavior" depends="setUp" if="expect-js">
+    <au:assertFalse>
+      <scriptcondition language="javascript" />
+    </au:assertFalse>
+  </target>
+
+  <target name="test-set-value-true" depends="setUp" if="expect-js">
+    <au:assertTrue>
+      <scriptcondition language="javascript">
+        self.setValue(true);
+      </scriptcondition>
+    </au:assertTrue>
+  </target>
+
+  <target name="test-set-value-false" depends="setUp" if="expect-js">
+    <au:assertFalse>
+      <scriptcondition language="javascript">
+        self.setValue(false);
+      </scriptcondition>
+    </au:assertFalse>
+  </target>
+
+  <target name="test-default-value-true" depends="setUp" if="expect-js">
+    <au:assertTrue>
+      <scriptcondition language="javascript" value="true" />
+    </au:assertTrue>
+  </target>
+
+  <target name="test-default-value-false" depends="setUp" if="expect-js">
+    <au:assertFalse>
+      <scriptcondition language="javascript" value="false" />
+    </au:assertFalse>
+  </target>
+
+  <target name="test-default-value-override-true" depends="setUp" if="expect-js">
+    <au:assertTrue>
+      <scriptcondition language="javascript" value="false">
+        self.setValue(true);
+      </scriptcondition>
+    </au:assertTrue>
+  </target>
+
+  <target name="test-default-value-override-false" depends="setUp" if="expect-js">
+    <au:assertFalse>
+      <scriptcondition language="javascript" value="true">
+        self.setValue(false);
+      </scriptcondition>
+    </au:assertFalse>
+  </target>
+
+  <target name="test-return-value-true" depends="setUp" if="expect-js">
+    <au:assertTrue>
+      <scriptcondition language="javascript" manager="javax">
+        true
+      </scriptcondition>
+    </au:assertTrue>
+  </target>
+
+  <target name="test-return-value-false" depends="setUp" if="expect-js">
+    <au:assertFalse>
+      <scriptcondition language="javascript" manager="javax" value="true">
+        false
+      </scriptcondition>
+    </au:assertFalse>
+  </target>
+
+</project>
diff --git a/src/tests/antunit/types/optional/xz/xzresource-test.xml b/src/tests/antunit/types/optional/xz/xzresource-test.xml
new file mode 100644
index 0000000..96b21ba
--- /dev/null
+++ b/src/tests/antunit/types/optional/xz/xzresource-test.xml
@@ -0,0 +1,37 @@
+<?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
+
+      https://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="${output}"/>
+    <available property="xz.present" classname="org.tukaani.xz.XZOutputStream"/>
+  </target>
+
+  <target name="testDocumentationClaimsOnCopy" if="xz.present">
+    <copy todir="${output}">
+      <xzresource>
+        <file file="../../../../../etc/testcases/taskdefs/expected/asf-logo.gif.xz"/>
+      </xzresource>
+      <mapper type="glob" from="*.xz" to="*"/>
+    </copy>
+    <au:assertFilesMatch expected="../../../../../etc/testcases/asf-logo.gif"
+                         actual="${output}/asf-logo.gif"/>
+  </target>
+</project>
diff --git a/src/tests/antunit/types/path-test.xml b/src/tests/antunit/types/path-test.xml
index 4f4be9a..61ca2de 100644
--- a/src/tests/antunit/types/path-test.xml
+++ b/src/tests/antunit/types/path-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/patternset-invert-test.xml b/src/tests/antunit/types/patternset-invert-test.xml
index 7c0912e..2208ecd 100644
--- a/src/tests/antunit/types/patternset-invert-test.xml
+++ b/src/tests/antunit/types/patternset-invert-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/patternset-test.xml b/src/tests/antunit/types/patternset-test.xml
index 60690d4..4da76f2 100644
--- a/src/tests/antunit/types/patternset-test.xml
+++ b/src/tests/antunit/types/patternset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/propertyset-test.xml b/src/tests/antunit/types/propertyset-test.xml
index 0b7e236..11a1f52 100644
--- a/src/tests/antunit/types/propertyset-test.xml
+++ b/src/tests/antunit/types/propertyset-test.xml
@@ -7,7 +7,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/antunit/types/resources/archives-test.xml b/src/tests/antunit/types/resources/archives-test.xml
index 961effc..c1bb7b1 100644
--- a/src/tests/antunit/types/resources/archives-test.xml
+++ b/src/tests/antunit/types/resources/archives-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/types/resources/comparators/test.xml b/src/tests/antunit/types/resources/comparators/test.xml
index 524f67a..9c3964c 100644
--- a/src/tests/antunit/types/resources/comparators/test.xml
+++ b/src/tests/antunit/types/resources/comparators/test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/concat-resource-test.xml b/src/tests/antunit/types/resources/concat-resource-test.xml
index 554c13d..d04b223 100644
--- a/src/tests/antunit/types/resources/concat-resource-test.xml
+++ b/src/tests/antunit/types/resources/concat-resource-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/fileresource-test.xml b/src/tests/antunit/types/resources/fileresource-test.xml
index 7114119..03c99ac 100644
--- a/src/tests/antunit/types/resources/fileresource-test.xml
+++ b/src/tests/antunit/types/resources/fileresource-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/files-test.xml b/src/tests/antunit/types/resources/files-test.xml
index 447a262..9834be0 100644
--- a/src/tests/antunit/types/resources/files-test.xml
+++ b/src/tests/antunit/types/resources/files-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/types/resources/first-last-test.xml b/src/tests/antunit/types/resources/first-last-test.xml
index e7fc831..38117e3 100644
--- a/src/tests/antunit/types/resources/first-last-test.xml
+++ b/src/tests/antunit/types/resources/first-last-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/javaresource-test.xml b/src/tests/antunit/types/resources/javaresource-test.xml
index a83184d..fc2cdb2 100644
--- a/src/tests/antunit/types/resources/javaresource-test.xml
+++ b/src/tests/antunit/types/resources/javaresource-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/types/resources/latepath-test.xml b/src/tests/antunit/types/resources/latepath-test.xml
index 5cafffd..c70f516 100644
--- a/src/tests/antunit/types/resources/latepath-test.xml
+++ b/src/tests/antunit/types/resources/latepath-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/multirootfileset-test.xml b/src/tests/antunit/types/resources/multirootfileset-test.xml
index 27b6193..4c3c178 100644
--- a/src/tests/antunit/types/resources/multirootfileset-test.xml
+++ b/src/tests/antunit/types/resources/multirootfileset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/resourcelist-test.xml b/src/tests/antunit/types/resources/resourcelist-test.xml
index 3357747..602ee54 100644
--- a/src/tests/antunit/types/resources/resourcelist-test.xml
+++ b/src/tests/antunit/types/resources/resourcelist-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -101,4 +101,41 @@
     </copy>
     <au:assertFileExists file="${output}/antlib.xml"/>
   </target>
+
+  <target name="testDuplicatesRemoved" depends="setUp">
+    <echo file="${input}/a.txt">${input}/b.txt
+${input}/b.txt</echo>
+    <echo file="${input}/b.txt">Demo content</echo>
+    <echo file="${input}/c.txt">${input}/b.txt
+${input}/b.txt</echo>
+    <pathconvert property="1b" pathsep="|" preserveduplicates="true">
+      <flattenmapper/>
+      <resourcelist>
+        <resources>
+          <file file="${input}/a.txt"/>
+          <file file="${input}/c.txt"/>
+        </resources>
+      </resourcelist>
+    </pathconvert>
+    <au:assertPropertyEquals name="1b" value="b.txt"/>
+  </target>
+
+  <target name="testDuplicatesPreserved" depends="setUp">
+    <echo file="${input}/a.txt">${input}/b.txt
+${input}/b.txt</echo>
+    <echo file="${input}/b.txt">Demo content</echo>
+    <echo file="${input}/c.txt">${input}/b.txt
+${input}/b.txt</echo>
+    <pathconvert property="4bs" pathsep="|" preserveduplicates="true">
+      <flattenmapper/>
+      <resourcelist preserveduplicates="true">
+        <resources>
+          <file file="${input}/a.txt"/>
+          <file file="${input}/a.txt"/>
+          <file file="${input}/c.txt"/>
+        </resources>
+      </resourcelist>
+    </pathconvert>
+    <au:assertPropertyEquals name="4bs" value="b.txt|b.txt|b.txt|b.txt|b.txt|b.txt"/>
+  </target>
 </project>
diff --git a/src/tests/antunit/types/resources/resources-test.xml b/src/tests/antunit/types/resources/resources-test.xml
index 19985c7..85b2c83 100644
--- a/src/tests/antunit/types/resources/resources-test.xml
+++ b/src/tests/antunit/types/resources/resources-test.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
diff --git a/src/tests/antunit/types/resources/selectors/name-test.xml b/src/tests/antunit/types/resources/selectors/name-test.xml
index 84cbedb..15d0221 100644
--- a/src/tests/antunit/types/resources/selectors/name-test.xml
+++ b/src/tests/antunit/types/resources/selectors/name-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/resources/selectors/readwrite-test.xml b/src/tests/antunit/types/resources/selectors/readwrite-test.xml
index 6a0301b..073adb2 100644
--- a/src/tests/antunit/types/resources/selectors/readwrite-test.xml
+++ b/src/tests/antunit/types/resources/selectors/readwrite-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/resources/selectors/test-componentdef.xml b/src/tests/antunit/types/resources/selectors/test-componentdef.xml
index 187412e..384682e 100644
--- a/src/tests/antunit/types/resources/selectors/test-componentdef.xml
+++ b/src/tests/antunit/types/resources/selectors/test-componentdef.xml
@@ -7,7 +7,7 @@
    (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
+       https://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,
@@ -81,7 +81,7 @@
         <restrict>
           <resources>
             <file file="foo" />
-            <url url="http://ant.apache.org/index.html" />
+            <url url="https://ant.apache.org/index.html" />
             <resource name="foo" />
             <string value="foo" />
             <file file="bar" />
diff --git a/src/tests/antunit/types/resources/selectors/test.xml b/src/tests/antunit/types/resources/selectors/test.xml
index 24b804a..b758eb4 100644
--- a/src/tests/antunit/types/resources/selectors/test.xml
+++ b/src/tests/antunit/types/resources/selectors/test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -85,7 +85,7 @@
         <restrict>
           <resources>
             <file file="foo" />
-            <url url="http://ant.apache.org/index.html" />
+            <url url="https://ant.apache.org/index.html" />
             <resource name="foo" />
             <string value="foo" />
             <file file="bar" />
diff --git a/src/tests/antunit/types/resources/test.xml b/src/tests/antunit/types/resources/test.xml
index 5af37b9..7afeb5c 100644
--- a/src/tests/antunit/types/resources/test.xml
+++ b/src/tests/antunit/types/resources/test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -28,8 +28,8 @@
   <condition property="offline">
     <not>
       <or>
-        <http url="http://www.apache.org"/>
-        <http url="http://www.google.com"/>
+        <http url="https://www.apache.org"/>
+        <http url="https://www.google.com"/>
       </or>
     </not>
   </condition>
@@ -280,7 +280,7 @@
 
   <target name="testhttpurl2" unless="offline">
     <concat destfile="${file}" force="true" append="false">
-      <url id="httpurl" url="http://ant.apache.org/index.html" />
+      <url id="httpurl" url="https://ant.apache.org/index.html" />
       <url refid="httpurl" />
     </concat>
     <length property="httpurl.length">
diff --git a/src/tests/antunit/types/resources/tokens-test.xml b/src/tests/antunit/types/resources/tokens-test.xml
index 26a300d..51a7e15 100644
--- a/src/tests/antunit/types/resources/tokens-test.xml
+++ b/src/tests/antunit/types/resources/tokens-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/selectors/depend-test.xml b/src/tests/antunit/types/selectors/depend-test.xml
index e868f6a..da2e6f5 100644
--- a/src/tests/antunit/types/selectors/depend-test.xml
+++ b/src/tests/antunit/types/selectors/depend-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/selectors/different-test.xml b/src/tests/antunit/types/selectors/different-test.xml
index c2542d2..b1d04ff 100644
--- a/src/tests/antunit/types/selectors/different-test.xml
+++ b/src/tests/antunit/types/selectors/different-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
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..28bdab4
--- /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
+
+      https://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/filename-test.xml b/src/tests/antunit/types/selectors/filename-test.xml
index 3f28e11..9013ab8 100644
--- a/src/tests/antunit/types/selectors/filename-test.xml
+++ b/src/tests/antunit/types/selectors/filename-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/selectors/modified-test.xml b/src/tests/antunit/types/selectors/modified-test.xml
index a4c43e0..c7fdc34 100644
--- a/src/tests/antunit/types/selectors/modified-test.xml
+++ b/src/tests/antunit/types/selectors/modified-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
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..5d85c3b
--- /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
+
+      https://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/present-test.xml b/src/tests/antunit/types/selectors/present-test.xml
index e31c722..efaa3be 100644
--- a/src/tests/antunit/types/selectors/present-test.xml
+++ b/src/tests/antunit/types/selectors/present-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/selectors/readwrite-test.xml b/src/tests/antunit/types/selectors/readwrite-test.xml
index bd4ac8d..fcc07fa 100644
--- a/src/tests/antunit/types/selectors/readwrite-test.xml
+++ b/src/tests/antunit/types/selectors/readwrite-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
@@ -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/select-test.xml b/src/tests/antunit/types/selectors/select-test.xml
index f5f5b99..05cc466 100644
--- a/src/tests/antunit/types/selectors/select-test.xml
+++ b/src/tests/antunit/types/selectors/select-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
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..41fb69a
--- /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
+
+      https://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/antunit/types/tarfileset-test.xml b/src/tests/antunit/types/tarfileset-test.xml
index 3c4d3a9..8282313 100644
--- a/src/tests/antunit/types/tarfileset-test.xml
+++ b/src/tests/antunit/types/tarfileset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/antunit/types/zipfileset-test.xml b/src/tests/antunit/types/zipfileset-test.xml
index c8bb022..4221fa7 100644
--- a/src/tests/antunit/types/zipfileset-test.xml
+++ b/src/tests/antunit/types/zipfileset-test.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/AntAssert.java b/src/tests/junit/org/apache/tools/ant/AntAssert.java
index d23792e..353a265 100644
--- a/src/tests/junit/org/apache/tools/ant/AntAssert.java
+++ b/src/tests/junit/org/apache/tools/ant/AntAssert.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,9 +21,13 @@
 import static org.junit.Assert.assertTrue;
 
 /**
- * Provides common assert functions for use across multiple tests, similar to the <tt>Assert</tt>s
+ * Provides common assert functions for use across multiple tests, similar to the <code>Assert</code>s
  * within JUnit.
+ *
+ * @deprecated use assertThat() in JUnit 4.4+ in combination with containsString() matcher;
+ * for exception messages, use ExpectedException rule.
  */
+@Deprecated
 public class AntAssert {
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/AntClassLoaderDelegationTest.java b/src/tests/junit/org/apache/tools/ant/AntClassLoaderDelegationTest.java
index b6f5b5f..660a28c 100644
--- a/src/tests/junit/org/apache/tools/ant/AntClassLoaderDelegationTest.java
+++ b/src/tests/junit/org/apache/tools/ant/AntClassLoaderDelegationTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,7 +24,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
-import java.util.List;
+
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.FileUtils;
 import org.junit.Before;
@@ -52,15 +52,14 @@
     }
 
     /** Sample resource present in build/testcases/ */
-    private static final String TEST_RESOURCE
-        = "apache/tools/ant/IncludeTest.class";
+    private static final String TEST_RESOURCE = "apache/tools/ant/IncludeTest.class";
 
     @SuppressWarnings("resource")
     @Test
     public void testFindResources() throws Exception {
         // This path should contain the class files for these testcases:
-        String buildTestcases = System.getProperty("build.tests");
-        assertNotNull("defined ${build.tests}", buildTestcases);
+        String buildTestcases = System.getProperty("build.tests.value");
+        assertNotNull("defined ${build.tests.value}", buildTestcases);
         assertTrue("have a dir " + buildTestcases,
                    new File(buildTestcases).isDirectory());
         Path path = new Path(p, buildTestcases + "/org");
@@ -72,21 +71,21 @@
         // The intended result URLs:
         URL urlFromPath = new URL(
             FILE_UTILS.toURI(buildTestcases) + "org/" + TEST_RESOURCE);
-        URL urlFromParent = new URL("http://ant.apache.org/" + TEST_RESOURCE);
+        URL urlFromParent = new URL("https://ant.apache.org/" + TEST_RESOURCE);
         assertEquals("correct resources (regular delegation order)",
-            Arrays.asList(new URL[] {urlFromParent, urlFromPath}),
-            enum2List(acl.getResources(TEST_RESOURCE)));
+            Arrays.asList(urlFromParent, urlFromPath),
+                Collections.list(acl.getResources(TEST_RESOURCE)));
         acl = new AntClassLoader(parent, p, path, false);
         assertEquals("correct resources (reverse delegation order)",
-            Arrays.asList(new URL[] {urlFromPath, urlFromParent}),
-            enum2List(acl.getResources(TEST_RESOURCE)));
+            Arrays.asList(urlFromPath, urlFromParent),
+                Collections.list(acl.getResources(TEST_RESOURCE)));
     }
 
     @SuppressWarnings("resource")
     @Test
     public void testFindIsolateResources() throws Exception {
-        String buildTestcases = System.getProperty("build.tests");
-        assertNotNull("defined ${build.tests}", buildTestcases);
+        String buildTestcases = System.getProperty("build.tests.value");
+        assertNotNull("defined ${build.tests.value}", buildTestcases);
         assertTrue("have a dir " + buildTestcases,
                    new File(buildTestcases).isDirectory());
         Path path = new Path(p, buildTestcases + "/org");
@@ -98,12 +97,8 @@
         AntClassLoader acl = new AntClassLoader(parent, p, path, false);
         acl.setIsolated(true);
         assertEquals("correct resources (reverse delegation order)",
-            Arrays.asList(new URL[] {urlFromPath}),
-            enum2List(acl.getResources(TEST_RESOURCE)));
-    }
-
-    private static List enum2List(Enumeration e) {
-        return Collections.list(e);
+                Collections.singletonList(urlFromPath),
+                Collections.list(acl.getResources(TEST_RESOURCE)));
     }
 
     /** Special loader that just knows how to find TEST_RESOURCE. */
@@ -112,13 +107,13 @@
         public ParentLoader() {
         }
 
-        protected Enumeration findResources(String name) throws IOException {
+        protected Enumeration<URL> findResources(String name) throws IOException {
             if (name.equals(TEST_RESOURCE)) {
                 return Collections.enumeration(
                     Collections.singleton(
-                        new URL("http://ant.apache.org/" + name)));
+                        new URL("https://ant.apache.org/" + name)));
             } else {
-                return Collections.enumeration(Collections.EMPTY_SET);
+                return Collections.enumeration(Collections.emptySet());
             }
         }
 
diff --git a/src/tests/junit/org/apache/tools/ant/AntClassLoaderPerformance.java b/src/tests/junit/org/apache/tools/ant/AntClassLoaderPerformance.java
index 2145cfa..8421655 100644
--- a/src/tests/junit/org/apache/tools/ant/AntClassLoaderPerformance.java
+++ b/src/tests/junit/org/apache/tools/ant/AntClassLoaderPerformance.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/AntClassLoaderTest.java b/src/tests/junit/org/apache/tools/ant/AntClassLoaderTest.java
index a016d49..cedeed0 100644
--- a/src/tests/junit/org/apache/tools/ant/AntClassLoaderTest.java
+++ b/src/tests/junit/org/apache/tools/ant/AntClassLoaderTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,21 +23,23 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.net.URL;
+import java.util.Collections;
 import java.util.Enumeration;
 
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.CollectionUtils;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * Test case for ant class loader
@@ -48,6 +50,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private AntClassLoader loader;
 
     @Before
@@ -70,7 +75,7 @@
         String extjarstring = buildRule.getProject().getProperty("ext.jar");
         Path myPath = new Path(buildRule.getProject());
         myPath.setLocation(new File(mainjarstring));
-        buildRule.getProject().setUserProperty("build.sysclasspath", "ignore");
+        buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         loader = buildRule.getProject().createClassLoader(myPath);
         String path = loader.getClasspath();
         assertEquals(mainjarstring + File.pathSeparator + extjarstring, path);
@@ -82,45 +87,46 @@
         String extjarstring = buildRule.getProject().getProperty("ext.jar.nonascii");
         Path myPath = new Path(buildRule.getProject());
         myPath.setLocation(new File(mainjarstring));
-        buildRule.getProject().setUserProperty("build.sysclasspath", "ignore");
+        buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         loader = buildRule.getProject().createClassLoader(myPath);
         String path = loader.getClasspath();
         assertEquals(mainjarstring + File.pathSeparator + extjarstring, path);
     }
 
+    /**
+     * The test should fail if NullPointException is thrown
+     *
+     * @throws ClassNotFoundException if a class is not found, ignored
+     */
     @Test
-    public void testCleanup() throws BuildException {
+    public void testCleanup() throws ClassNotFoundException {
+        thrown.expect(ClassNotFoundException.class);
         Path path = new Path(buildRule.getProject(), ".");
         loader = buildRule.getProject().createClassLoader(path);
+        boolean canary = false;
         try {
             // we don't expect to find this
             loader.findClass("fubar");
-            fail("Did not expect to find fubar class");
-        } catch (ClassNotFoundException e) {
-            // ignore expected
-        }
-
-        loader.cleanup();
-        try {
-            // we don't expect to find this
-            loader.findClass("fubar");
-            fail("Did not expect to find fubar class");
-        } catch (ClassNotFoundException e) {
-            // ignore expected
-        } catch (NullPointerException e) {
-            fail("loader should not fail even if cleaned up");
-        }
-
-        // tell the build it is finished
-        buildRule.getProject().fireBuildFinished(null);
-        try {
-            // we don't expect to find this
-            loader.findClass("fubar");
-            fail("Did not expect to find fubar class");
-        } catch (ClassNotFoundException e) {
-            // ignore expected
-        } catch (NullPointerException e) {
-            fail("loader should not fail even if project finished");
+            canary = true;
+        } finally {
+            assertFalse("Nonexistent class found", canary);
+            loader.cleanup();
+            try {
+                // we don't expect to find this
+                loader.findClass("fubar");
+                canary = true;
+            } finally {
+                assertFalse("Nonexistent class found", canary);
+                // tell the build it is finished
+                buildRule.getProject().fireBuildFinished(null);
+                try {
+                    // we don't expect to find this
+                    loader.findClass("fubar");
+                    canary = true;
+                } finally {
+                    assertFalse("Nonexistent class found", canary);
+                }
+            }
         }
     }
 
@@ -129,7 +135,7 @@
         buildRule.executeTarget("prepareGetPackageTest");
         Path myPath = new Path(buildRule.getProject());
         myPath.setLocation(new File(buildRule.getProject().getProperty("test.jar")));
-        buildRule.getProject().setUserProperty("build.sysclasspath", "ignore");
+        buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         loader = buildRule.getProject().createClassLoader(myPath);
         assertNotNull("should find class", loader.findClass("org.example.Foo"));
         assertNotNull("should find package",
@@ -142,7 +148,7 @@
         Path myPath = new Path(buildRule.getProject());
         File testJar = new File(buildRule.getProject().getProperty("test.jar"));
         myPath.setLocation(testJar);
-        buildRule.getProject().setUserProperty("build.sysclasspath", "ignore");
+        buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         loader = buildRule.getProject().createClassLoader(myPath);
         Class<?> foo = loader.findClass("org.example.Foo");
         URL codeSourceLocation =
@@ -158,7 +164,7 @@
 
         Path myPath = new Path(buildRule.getProject());
         myPath.setLocation(jar);
-        buildRule.getProject().setUserProperty("build.sysclasspath", "ignore");
+        buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         loader = buildRule.getProject().createClassLoader(myPath);
         Class<?> foo = loader.findClass("org.example.Foo");
 
@@ -170,19 +176,19 @@
     }
 
     /**
-     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=47593">
-     *     bug 47593, request to log the name of corrupt zip files from which
-     *     classes cannot be loaded</a>
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=47593">bug 47593</a>
+     *     request to log the name of corrupt zip files from which
+     *     classes cannot be loaded
      */
     @Test
-    public void testInvalidZipException() throws Exception {
+    public void testInvalidZipException() {
         buildRule.executeTarget("createNonJar");
         File jar = new File(buildRule.getProject().getProperty("tmp.dir")
                             + "/foo.jar");
 
         Path myPath = new Path(buildRule.getProject());
         myPath.setLocation(jar);
-        buildRule.getProject().setUserProperty("build.sysclasspath", "ignore");
+        buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         loader = buildRule.getProject().createClassLoader(myPath);
         PrintStream sysErr = System.err;
         try {
@@ -204,8 +210,7 @@
      * Asserts that getResources won't return resources that cannot be
      * seen by AntClassLoader but by ClassLoader.this.parent.
      *
-     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=46752">
-     *     https://issues.apache.org/bugzilla/show_bug.cgi?id=46752</a>
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=46752">bug 46752</a>
      */
     @SuppressWarnings("resource")
     @Test
@@ -230,12 +235,33 @@
         assertFalse(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements());
     }
 
+    /**
+     * Tests that {@link AntClassLoader} supports multi-release jar files while dealing with
+     * runtime resources in Java 9+ runtime environments.
+     *
+     * @see <a href="bz-62952">https://bz.apache.org/bugzilla/show_bug.cgi?id=62952</a>
+     */
+    @Test
+    public void testMultiReleaseJar() {
+        buildRule.executeTarget("testMRJar");
+        final boolean atleastJava9 = JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9);
+        final String targetOutput = buildRule.getOutput();
+        Assert.assertNotNull("Multi-release jar test did not generate any output", targetOutput);
+        if (atleastJava9) {
+            Assert.assertTrue("Unexpected output from multi-release jar test for Java runtime >= 9",
+                    targetOutput.contains("mrjar test result = 9"));
+        } else {
+            Assert.assertTrue("Unexpected output from multi-release jar test", targetOutput.contains("mrjar test result = default"));
+        }
+    }
+
     private static class EmptyLoader extends ClassLoader {
         public URL getResource(String n) {
             return null;
         }
-        public Enumeration getResources(String n) {
-            return new CollectionUtils.EmptyEnumeration();
+
+        public Enumeration<URL> getResources(String n) {
+            return Collections.emptyEnumeration();
         }
     }
 
@@ -243,6 +269,7 @@
         GetPackageWrapper(ClassLoader parent) {
             super(parent);
         }
+
         public Package getPackage(String s) {
             return super.getPackage(s);
         }
diff --git a/src/tests/junit/org/apache/tools/ant/BuildFileRule.java b/src/tests/junit/org/apache/tools/ant/BuildFileRule.java
index a444109..4f407ea 100644
--- a/src/tests/junit/org/apache/tools/ant/BuildFileRule.java
+++ b/src/tests/junit/org/apache/tools/ant/BuildFileRule.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,6 +35,9 @@
  *     \@Rule
  *     public BuildFileRule rule = new BuildFileRule();
  *
+ *     \@Rule
+ *     public ExpectedException thrown = ExpectedException.none();
+ *
  *     \@Before
  *     public void setUp() {
  *         rule.configureProject("my/and/file.xml");
@@ -48,12 +51,9 @@
  *
  *     \@Test
  *     public void testException() {
- *         try {
- *             rule.executeTarget("failingTarget");
- *             fail("Target should have thrown a BuildException");
- *         } catch (BuildException ex) {
- *             assertContains("Exception did not contain correct text", "Could not find compiler on classpath", ex.getMessage());
- *         }
+ *         thrown.expect(BuildException.class);
+ *         thrown.expectMessage("Could not find compiler on classpath");
+ *         rule.executeTarget("failingTarget");
  *     }
  *
  * }
@@ -68,11 +68,9 @@
     private StringBuffer outputBuffer;
     private StringBuffer errorBuffer;
 
-
-
     /**
      * Tidies up following a test execution. If the currently configured
-     * project has a <tt>tearDown</tt> target then this will automatically
+     * project has a <code>tearDown</code> target then this will automatically
      * be called, otherwise this method will not perform any actions.
      */
     @Override
@@ -155,11 +153,14 @@
         logBuffer = new StringBuffer();
         fullLogBuffer = new StringBuffer();
         project = new Project();
+        if (Boolean.getBoolean(MagicTestNames.TEST_BASEDIR_IGNORE)) {
+            System.clearProperty(MagicNames.PROJECT_BASEDIR);
+        }
         project.init();
-        File antFile = new File(System.getProperty("root"), filename);
-        project.setProperty("ant.processid", ProcessUtil.getProcessId("<Process>"));
-        project.setProperty("ant.threadname", Thread.currentThread().getName());
-        project.setUserProperty("ant.file", antFile.getAbsolutePath());
+        File antFile = new File(System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY), filename);
+        project.setProperty(MagicTestNames.TEST_PROCESS_ID, ProcessUtil.getProcessId("<Process>"));
+        project.setProperty(MagicTestNames.TEST_THREAD_NAME, Thread.currentThread().getName());
+        project.setUserProperty(MagicNames.ANT_FILE, antFile.getAbsolutePath());
         project.addBuildListener(new AntTestListener(logLevel));
         ProjectHelper.configureProject(project, antFile);
     }
diff --git a/src/tests/junit/org/apache/tools/ant/BuildFileTest.java b/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
index 51e2dad..18326e4 100644
--- a/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
+++ b/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -71,6 +71,10 @@
      * to clean up after each test. Note that no "setUp" target
      * is automatically called, since it's trivial to have a
      * test target depend on it.
+     *
+     * @throws Exception this implementation doesn't throw any
+     * exception but we've added it to the signature so that
+     * subclasses can throw whatever they need.
      */
     protected void tearDown() throws Exception {
         if (project == null) {
@@ -151,7 +155,7 @@
      * Assert that the given substring is in the output messages.
      *
      * @param message Print this message if the test fails. Defaults to
-     *                a meaningful text if <tt>null</tt> is passed.
+     *                a meaningful text if <code>null</code> is passed.
      * @param substring String
      * @since Ant1.7
      */
@@ -167,7 +171,7 @@
      * Assert that the given substring is not in the output messages.
      *
      * @param message Print this message if the test fails. Defaults to
-     *                a meaningful text if <tt>null</tt> is passed.
+     *                a meaningful text if <code>null</code> is passed.
      * @param substring String
      * @since Ant1.7
      */
@@ -323,12 +327,15 @@
         logBuffer = new StringBuffer();
         fullLogBuffer = new StringBuffer();
         project = new Project();
+        if (Boolean.getBoolean(MagicTestNames.TEST_BASEDIR_IGNORE)) {
+            System.clearProperty(MagicNames.PROJECT_BASEDIR);
+        }
         project.init();
-        File antFile = new File(System.getProperty("root"), filename);
-        project.setUserProperty("ant.file", antFile.getAbsolutePath());
+        File antFile = new File(System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY), filename);
+        project.setUserProperty(MagicNames.ANT_FILE, antFile.getAbsolutePath());
         // set two new properties to allow to build unique names when running multithreaded tests
-        project.setProperty("ant.processid", ProcessUtil.getProcessId("<Process>"));
-        project.setProperty("ant.threadname", Thread.currentThread().getName());
+        project.setProperty(MagicTestNames.TEST_PROCESS_ID, ProcessUtil.getProcessId("<Process>"));
+        project.setProperty(MagicTestNames.TEST_THREAD_NAME, Thread.currentThread().getName());
         project.addBuildListener(new AntTestListener(logLevel));
         ProjectHelper.configureProject(project, antFile);
     }
@@ -402,11 +409,10 @@
             executeTarget(target);
         } catch (BuildException ex) {
             buildException = ex;
-            if ((null != msg) && (!ex.getMessage().equals(msg))) {
-                fail("Should throw BuildException because '" + cause
-                        + "' with message '" + msg
-                        + "' (actual message '" + ex.getMessage() + "' instead)");
-            }
+            assertTrue("Should throw BuildException because '" + cause
+                    + "' with message '" + msg + "' (actual message '"
+                            + ex.getMessage() + "' instead)",
+                    msg == null || ex.getMessage().equals(msg));
             return;
         }
         fail("Should throw BuildException because: " + cause);
@@ -423,12 +429,12 @@
     public void expectBuildExceptionContaining(String target, String cause, String contains) {
         try {
             executeTarget(target);
-        } catch (org.apache.tools.ant.BuildException ex) {
+        } catch (BuildException ex) {
             buildException = ex;
-            if (null != contains && !ex.getMessage().contains(contains)) {
-                fail("Should throw BuildException because '" + cause + "' with message containing '"
-                        + contains + "' (actual message '" + ex.getMessage() + "' instead)");
-            }
+            assertTrue("Should throw BuildException because '" + cause
+                    + "' with message containing '" + contains + "' (actual message '"
+                            + ex.getMessage() + "' instead)",
+                    null == contains || ex.getMessage().contains(contains));
             return;
         }
         fail("Should throw BuildException because: " + cause);
@@ -473,10 +479,8 @@
      */
     public void assertPropertyUnset(String property) {
         String result = project.getProperty(property);
-        if (result != null) {
-            fail("Expected property " + property
-                    + " to be unset, but it is set to the value: " + result);
-        }
+        assertNull("Expected property " + property
+                + " to be unset, but it is set to the value: " + result, result);
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/CaseTest.java b/src/tests/junit/org/apache/tools/ant/CaseTest.java
index a466ea4..b5c4756 100644
--- a/src/tests/junit/org/apache/tools/ant/CaseTest.java
+++ b/src/tests/junit/org/apache/tools/ant/CaseTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,9 +21,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Simple tests of build file processing
@@ -33,6 +31,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/core/case.xml");
@@ -49,15 +50,12 @@
 
     /**
      * Test whether the build file uses case when determining
-     * task names.
+     * task names. Task name should be case sensitive.
      */
     @Test
     public void testTaskCase() {
-        try {
-            buildRule.executeTarget("taskcase");
-            fail("Build exception should have been thrown due to case sensitivity of name");
-        } catch (BuildException ex) {
-            assertContains("Task names should be case sensitive", "Problem: failed to create task or type ecHO", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Problem: failed to create task or type ecHO");
+        buildRule.executeTarget("taskcase");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/DefaultLoggerTest.java b/src/tests/junit/org/apache/tools/ant/DefaultLoggerTest.java
index 303a44b..fc950c3 100644
--- a/src/tests/junit/org/apache/tools/ant/DefaultLoggerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/DefaultLoggerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 
 package org.apache.tools.ant;
 
-import org.apache.tools.ant.util.StringUtils;
 import org.junit.Test;
 
 import java.io.PrintWriter;
@@ -36,21 +35,18 @@
 
     @SuppressWarnings("serial")
     @Test
-    public void testThrowableMessage() throws Exception { // #43398
+    public void testThrowableMessage() { // #43398
         BuildException be = new BuildException("oops", new Location("build.xml", 1, 0));
-        assertEquals(
-                "build.xml:1: oops" + StringUtils.LINE_SEP,
-                msg(be, false));
+        assertEquals(String.format("build.xml:1: oops%n"), msg(be, false));
         be = ProjectHelper.addLocationToBuildException(be, new Location("build.xml", 2, 0));
-        assertEquals(
-                "build.xml:2: The following error occurred while executing this line:" + StringUtils.LINE_SEP +
-                "build.xml:1: oops" + StringUtils.LINE_SEP,
-                msg(be, false));
+        assertEquals(String.format(
+                "build.xml:2: The following error occurred while executing this line:%n"
+                        + "build.xml:1: oops%n"), msg(be, false));
         be = ProjectHelper.addLocationToBuildException(be, new Location("build.xml", 3, 0));
-        assertEquals(
-                "build.xml:3: The following error occurred while executing this line:" + StringUtils.LINE_SEP +
-                "build.xml:2: The following error occurred while executing this line:" + StringUtils.LINE_SEP +
-                "build.xml:1: oops" + StringUtils.LINE_SEP,
+        assertEquals(String.format(
+                "build.xml:3: The following error occurred while executing this line:%n"
+                        + "build.xml:2: The following error occurred while executing this line:%n"
+                        + "build.xml:1: oops%n"),
                 msg(be, false));
         Exception x = new Exception("problem") {
             public void printStackTrace(PrintWriter w) {
@@ -58,21 +54,14 @@
                 w.println("  at p.C.m");
             }
         };
-        assertEquals(
-                "problem" + StringUtils.LINE_SEP +
-                "  at p.C.m" + StringUtils.LINE_SEP,
-                msg(x, false));
+        assertEquals(String.format("problem%n  at p.C.m%n"), msg(x, false));
+
         be = new BuildException(x, new Location("build.xml", 1, 0));
-        assertEquals(
-                "build.xml:1: problem" + StringUtils.LINE_SEP +
-                "  at p.C.m" + StringUtils.LINE_SEP,
-                msg(be, false));
+        assertEquals(String.format("build.xml:1: problem%n  at p.C.m%n"), msg(be, false));
+
         be = ProjectHelper.addLocationToBuildException(be, new Location("build.xml", 2, 0));
-        assertEquals(
-                "build.xml:2: The following error occurred while executing this line:" + StringUtils.LINE_SEP +
-                "build.xml:1: problem" + StringUtils.LINE_SEP +
-                "  at p.C.m" + StringUtils.LINE_SEP,
-                msg(be, false));
+        assertEquals(String.format("build.xml:2: The following error occurred while executing this line:%n"
+                        + "build.xml:1: problem%n  at p.C.m%n"), msg(be, false));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java b/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java
index 819d4e5..6d38129 100644
--- a/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,11 @@
 
 package org.apache.tools.ant;
 
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
@@ -27,10 +30,10 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.apache.tools.ant.types.selectors.TokenizedPath;
@@ -50,15 +53,17 @@
     // keep track of what operating systems are supported here.
     private boolean supportsSymlinks = Os.isFamily("unix");
 
+    private DirectoryScanner ds;
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/core/directoryscanner.xml");
         buildRule.getProject().executeTarget("setUp");
+        ds = new DirectoryScanner();
     }
 
     @Test
     public void test1() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha"});
         ds.scan();
@@ -67,7 +72,6 @@
 
     @Test
     public void test2() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/"});
         ds.scan();
@@ -78,7 +82,6 @@
 
     @Test
     public void test3() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.scan();
         compareFiles(ds, new String[] {"alpha/beta/beta.xml",
@@ -89,7 +92,6 @@
 
     @Test
     public void testFullPathMatchesCaseSensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/beta/gamma/GAMMA.XML"});
         ds.scan();
@@ -98,7 +100,6 @@
 
     @Test
     public void testFullPathMatchesCaseInsensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setCaseSensitive(false);
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/beta/gamma/GAMMA.XML"});
@@ -109,7 +110,6 @@
 
     @Test
     public void test2ButCaseInsensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"ALPHA/"});
         ds.setCaseSensitive(false);
@@ -120,11 +120,9 @@
 
     @Test
     public void testAllowSymlinks() {
-
         assumeTrue("Current system does not support Symlinks", supportsSymlinks);
-
         buildRule.getProject().executeTarget("symlink-setup");
-        DirectoryScanner ds = new DirectoryScanner();
+
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/beta/gamma/"});
         ds.scan();
@@ -135,9 +133,8 @@
     @Test
     public void testProhibitSymlinks() {
         assumeTrue("Current system does not support Symlinks", supportsSymlinks);
-
         buildRule.getProject().executeTarget("symlink-setup");
-        DirectoryScanner ds = new DirectoryScanner();
+
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/beta/gamma/"});
         ds.setFollowSymlinks(false);
@@ -151,7 +148,7 @@
         String[] expectedFiles = {"alpha/beta/beta.xml",
                                    "alpha/beta/gamma/gamma.xml"};
         String[] expectedDirectories = {"alpha/beta", "alpha/beta/gamma" };
-        DirectoryScanner ds = new DirectoryScanner();
+
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/be?a/**", "alpha/beta/gamma/"});
         ds.scan();
@@ -166,7 +163,6 @@
 
     @Test
     public void testPatternsDifferInCaseScanningSensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/"});
         ds.scan();
@@ -176,7 +172,6 @@
 
     @Test
     public void testPatternsDifferInCaseScanningInsensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/"});
         ds.setCaseSensitive(false);
@@ -187,7 +182,6 @@
 
     @Test
     public void testFullpathDiffersInCaseScanningSensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/beta/gamma/gamma.xml", "alpha/beta/gamma/GAMMA.XML"});
         ds.scan();
@@ -196,7 +190,6 @@
 
     @Test
     public void testFullpathDiffersInCaseScanningInsensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/beta/gamma/gamma.xml", "alpha/beta/gamma/GAMMA.XML"});
         ds.setCaseSensitive(false);
@@ -206,7 +199,6 @@
 
     @Test
     public void testParentDiffersInCaseScanningSensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/beta/"});
         ds.scan();
@@ -216,7 +208,6 @@
 
     @Test
     public void testParentDiffersInCaseScanningInsensitive() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/beta/"});
         ds.setCaseSensitive(false);
@@ -226,29 +217,30 @@
     }
 
     /**
-     * Test case for setFollowLinks() and associated functionality.
+     * Test case for setFollowSymlinks() and associated functionality.
      * Only supports test on Linux at the moment because Java has
      * no real notion of symlinks built in, so an os-specfic call
      * to Runtime.exec() must be made to create a link to test against.
      * @throws InterruptedException if something goes wrong
      */
     @Test
-    public void testSetFollowLinks() throws IOException, InterruptedException {
+    public void testSetFollowSymlinks() throws IOException, InterruptedException {
         if (supportsSymlinks) {
-            File linkFile = new File(System.getProperty("root"), "src/main/org/apache/tools/ThisIsALink");
-            System.err.println("link exists pre-test? " + linkFile.exists());
+            File dir = new File(buildRule.getProject().getBaseDir(),
+                    "../../../main/org/apache/tools");
+
+            File linkFile = new File(dir, "ThisIsALink");
+            assertFalse("link exists pre-test", linkFile.exists());
+            File targetFile = new File(dir, "ant");
+            assertTrue("target does not exist pre-test", targetFile.exists());
 
             try {
                 // add conditions and more commands as soon as the need arises
-                String[] command = new String[] {"ln", "-s", "ant", linkFile.getAbsolutePath()};
+                String[] command = new String[] {"ln", "-s", targetFile.getAbsolutePath(), linkFile.getAbsolutePath()};
                 Process process = Runtime.getRuntime().exec(command);
                 assertEquals("0 return code expected for external process", 0, process.waitFor());
 
-                File dir = new File(System.getProperty("root"), "src/main/org/apache/tools");
-
-                DirectoryScanner ds = new DirectoryScanner();
-
-                // followLinks should be true by default, but if this ever
+                // followSymlinks should be true by default, but if this ever
                 // changes we will need this line.
                 ds.setFollowSymlinks(true);
 
@@ -306,7 +298,6 @@
 
     @Test
     public void testExcludeOneFile() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"**/*.xml"});
         ds.setExcludes(new String[] {"alpha/beta/b*xml"});
@@ -317,7 +308,6 @@
 
     @Test
     public void testExcludeHasPrecedence() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/**"});
         ds.setExcludes(new String[] {"alpha/**"});
@@ -328,7 +318,6 @@
 
     @Test
     public void testAlternateIncludeExclude() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setIncludes(new String[] {"alpha/**", "alpha/beta/gamma/**"});
         ds.setExcludes(new String[] {"alpha/beta/**"});
@@ -339,7 +328,6 @@
 
     @Test
     public void testAlternateExcludeInclude() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setExcludes(new String[] {"alpha/**", "alpha/beta/gamma/**"});
         ds.setIncludes(new String[] {"alpha/beta/**"});
@@ -352,17 +340,24 @@
      * Test inspired by Bug#1415.
      */
     @Test
-    public void testChildrenOfExcludedDirectory() {
+    public void testChildrenOfRecursivelyExcludedDirectory() {
         buildRule.getProject().executeTarget("children-of-excluded-dir-setup");
-        DirectoryScanner ds = new DirectoryScanner();
+
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setExcludes(new String[] {"alpha/**"});
         ds.setFollowSymlinks(false);
         ds.scan();
         compareFiles(ds, new String[] {"delta/delta.xml"},
                     new String[] {"", "delta"});
+    }
 
-        ds = new DirectoryScanner();
+    /**
+     * Test inspired by Bug#1415.
+     */
+    @Test
+    public void testChildrenOfExcludedDirectory() {
+        buildRule.getProject().executeTarget("children-of-excluded-dir-setup");
+
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setExcludes(new String[] {"alpha"});
         ds.setFollowSymlinks(false);
@@ -386,24 +381,23 @@
                 + "package private method called", shareclassloader == null
                         || shareclassloader.indexOf("${") == 0);
         buildRule.getProject().executeTarget("children-of-excluded-dir-setup");
-        DirectoryScanner ds = new DirectoryScanner();
-        ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
 
+        ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setExcludes(new String[] {"**/gamma/**"});
         ds.setFollowSymlinks(false);
         ds.scan();
         Set<String> set = ds.getScannedDirs();
         assertFalse("empty set", set.isEmpty());
         String s = "alpha/beta/gamma/".replace('/', File.separatorChar);
-        assertFalse("scanned " + s, set.contains(s));
+        assertThat("scanned " + s, set, not(hasItem(s)));
     }
 
     @Test
     public void testAbsolute1() {
         buildRule.getProject().executeTarget("extended-setup");
-        DirectoryScanner ds = new DirectoryScanner();
-        String tmpdir = buildRule.getProject().getProperty("output").replace(
-                File.separatorChar, '/');
+
+        String tmpdir = buildRule.getProject().getProperty("output")
+                .replace(File.separatorChar, '/');
         ds.setIncludes(new String[] {tmpdir + "/**/*"});
         ds.scan();
         compareFiles(ds,
@@ -418,7 +412,6 @@
 
     @Test
     public void testAbsolute2() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setIncludes(new String[] {"alpha/**", "alpha/beta/gamma/**"});
         ds.scan();
         String[] mt = new String[0];
@@ -428,7 +421,7 @@
     @Test
     public void testAbsolute3() {
         buildRule.getProject().executeTarget("extended-setup");
-        DirectoryScanner ds = new DirectoryScanner();
+
         String tmpdir = buildRule.getProject().getProperty("output").replace(
                 File.separatorChar, '/');
         ds.setIncludes(new String[] {tmpdir + "/**/*"});
@@ -445,7 +438,7 @@
     @Test
     public void testAbsolute4() {
         buildRule.getProject().executeTarget("extended-setup");
-        DirectoryScanner ds = new DirectoryScanner();
+
         String tmpdir = buildRule.getProject().getProperty("output").replace(
                 File.separatorChar, '/');
         ds.setIncludes(new String[] {tmpdir + "/alpha/beta/**/*", tmpdir + "/delta/*"});
@@ -462,7 +455,7 @@
         //testing drive letter search from root:
         assumeTrue("Can't use drive letters on non DOS or Netware systems",
                 Os.isFamily("dos") || Os.isFamily("netware"));
-        DirectoryScanner ds = new DirectoryScanner();
+
         String pattern = new File(File.separator).getAbsolutePath().toUpperCase() + "*";
         ds.setIncludes(new String[] {pattern});
         ds.scan();
@@ -480,56 +473,45 @@
         assertEquals("directories present: ", expectedDirectories.length,
                      includedDirectories.length);
 
-        TreeSet<String> files = new TreeSet<String>();
-        for (String includedFile : includedFiles) {
-            files.add(includedFile.replace(File.separatorChar, '/'));
-        }
-        TreeSet<String> directories = new TreeSet<String>();
-        for (String includedDirectory : includedDirectories) {
-            directories.add(includedDirectory.replace(File.separatorChar, '/'));
-        }
+        TreeSet<String> files = Arrays.stream(includedFiles)
+                .map(includedFile -> includedFile.replace(File.separatorChar, '/'))
+                .collect(Collectors.toCollection(TreeSet::new));
 
-        String currentfile;
-        Iterator<String> i = files.iterator();
+        TreeSet<String> directories = Arrays.stream(includedDirectories)
+                .map(includedDirectory -> includedDirectory.replace(File.separatorChar, '/'))
+                .collect(Collectors.toCollection(TreeSet::new));
+
         int counter = 0;
-        while (i.hasNext()) {
-            currentfile = i.next();
-            assertEquals(expectedFiles[counter], currentfile);
-            counter++;
+        for (String currentFile : files) {
+            assertEquals(expectedFiles[counter++], currentFile);
         }
-        String currentdirectory;
-        Iterator<String> dirit = directories.iterator();
         counter = 0;
-        while (dirit.hasNext()) {
-            currentdirectory = dirit.next();
-            assertEquals(expectedDirectories[counter], currentdirectory);
-            counter++;
+        for (String currentDirectory : directories) {
+             assertEquals(expectedDirectories[counter++], currentDirectory);
         }
     }
 
     @Test
-    public void testRecursiveExcludes() throws Exception {
-        DirectoryScanner ds = new DirectoryScanner();
+    public void testRecursiveExcludes() {
         ds.setBasedir(new File(buildRule.getProject().getProperty("output")));
         ds.setExcludes(new String[] {"**/beta/**"});
         ds.scan();
         List<String> dirs = Arrays.asList(ds.getExcludedDirectories());
         assertEquals(2, dirs.size());
-        assertTrue("beta is excluded", dirs.contains("alpha/beta"
-                .replace('/', File.separatorChar)));
-        assertTrue("gamma is excluded", dirs.contains("alpha/beta/gamma"
-                .replace('/', File.separatorChar)));
+        assertThat("beta is excluded", dirs,
+                hasItem("alpha/beta".replace('/', File.separatorChar)));
+        assertThat("gamma is excluded", dirs,
+                hasItem("alpha/beta/gamma".replace('/', File.separatorChar)));
         List<String> files = Arrays.asList(ds.getExcludedFiles());
         assertEquals(2, files.size());
-        assertTrue("beta.xml is excluded", files.contains("alpha/beta/beta.xml"
-                .replace('/', File.separatorChar)));
-        assertTrue("gamma.xml is excluded", files.contains("alpha/beta/gamma/gamma.xml"
-                .replace('/', File.separatorChar)));
+        assertThat("beta.xml is excluded", files,
+                hasItem("alpha/beta/beta.xml".replace('/', File.separatorChar)));
+        assertThat("gamma.xml is excluded", files,
+                hasItem("alpha/beta/gamma/gamma.xml".replace('/', File.separatorChar)));
     }
 
     @Test
     public void testContentsExcluded() {
-        DirectoryScanner ds = new DirectoryScanner();
         ds.setBasedir(new File("."));
         ds.setIncludes(new String[] {"**"});
         ds.addDefaultExcludes();
diff --git a/src/tests/junit/org/apache/tools/ant/DispatchTaskTest.java b/src/tests/junit/org/apache/tools/ant/DispatchTaskTest.java
index c682093..fcd6f2d 100644
--- a/src/tests/junit/org/apache/tools/ant/DispatchTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/DispatchTaskTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,17 +18,19 @@
 
 package org.apache.tools.ant;
 
-import static org.junit.Assert.fail;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 public class DispatchTaskTest {
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/core/dispatch/dispatch.xml");
@@ -36,11 +38,8 @@
 
     @Test
     public void testDisp() {
-        try {
-            buildRule.executeTarget("disp");
-            fail("BuildException should have been thrown");
-        } catch(BuildException ex) {
-            //FIXME the previous method used here ignored the build exception - what are we trying to test
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("list");
+        buildRule.executeTarget("disp");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/DummyMailServer.java b/src/tests/junit/org/apache/tools/ant/DummyMailServer.java
index 3fc66f3..dc7dff6 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyMailServer.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyMailServer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskAbstract.java b/src/tests/junit/org/apache/tools/ant/DummyTaskAbstract.java
index 18fe09d..70dd87d 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskAbstract.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskAbstract.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskInterface.java b/src/tests/junit/org/apache/tools/ant/DummyTaskInterface.java
index 8ae5f5b..025bedb 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskInterface.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskInterface.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskOk.java b/src/tests/junit/org/apache/tools/ant/DummyTaskOk.java
index ff8fdab..6dce80b 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskOk.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskOk.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskOkNonTask.java b/src/tests/junit/org/apache/tools/ant/DummyTaskOkNonTask.java
index 234abd6..2b085e2 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskOkNonTask.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskOkNonTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonPublicExecute.java b/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonPublicExecute.java
index 766283d..3ae5437 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonPublicExecute.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonPublicExecute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonVoidExecute.java b/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonVoidExecute.java
index 876b9b7..6a7f086 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonVoidExecute.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskWithNonVoidExecute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutDefaultConstructor.java b/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutDefaultConstructor.java
index 40661f5..5b77a08 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutDefaultConstructor.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutDefaultConstructor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutExecute.java b/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutExecute.java
index 6d5ea00..991ba02 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutExecute.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutExecute.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutPublicConstructor.java b/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutPublicConstructor.java
index 0ec4ff8..aadfa26 100644
--- a/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutPublicConstructor.java
+++ b/src/tests/junit/org/apache/tools/ant/DummyTaskWithoutPublicConstructor.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/ExecutorTest.java b/src/tests/junit/org/apache/tools/ant/ExecutorTest.java
index b17554c..e96f209 100644
--- a/src/tests/junit/org/apache/tools/ant/ExecutorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/ExecutorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,34 +19,37 @@
 package org.apache.tools.ant;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 import java.util.Vector;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * Executor tests
  */
 public class ExecutorTest implements BuildListener  {
 
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private static final String SINGLE_CHECK
-        = "org.apache.tools.ant.helper.SingleCheckExecutor";
+            = "org.apache.tools.ant.helper.SingleCheckExecutor";
     private static final String IGNORE_DEPS
-        = "org.apache.tools.ant.helper.IgnoreDependenciesExecutor";
+            = "org.apache.tools.ant.helper.IgnoreDependenciesExecutor";
 
     private static final Vector<String> TARGET_NAMES;
     static {
-        TARGET_NAMES = new Vector<String>();
+        TARGET_NAMES = new Vector<>();
         TARGET_NAMES.add("a");
         TARGET_NAMES.add("b");
     }
 
-    @Rule
-    public BuildFileRule buildRule = new BuildFileRule();
-
     private int targetCount;
 
     /* BuildListener stuff */
@@ -89,7 +92,7 @@
 
     private Project getProject(String e, boolean f, boolean k) {
         Project p = buildRule.getProject();
-        p.setNewProperty("ant.executor.class", e);
+        p.setNewProperty(MagicNames.ANT_EXECUTOR_CLASSNAME, e);
         p.setKeepGoingMode(k);
         if (f) {
             p.setNewProperty("failfoo", "foo");
@@ -117,22 +120,22 @@
 
     @Test
     public void testDefaultFailure() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("failfoo");
         try {
             getProject(null, true).executeTargets(TARGET_NAMES);
-            fail("should fail");
-        } catch (BuildException e) {
-            assertEquals("failfoo", e.getMessage());
+        } finally {
             assertEquals(1, targetCount);
         }
     }
 
     @Test
     public void testSingleCheckFailure() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("failfoo");
         try {
             getProject(SINGLE_CHECK, true).executeTargets(TARGET_NAMES);
-            fail("should fail");
-        } catch (BuildException e) {
-            assertEquals("failfoo", e.getMessage());
+        } finally {
             assertEquals(1, targetCount);
         }
     }
@@ -145,36 +148,36 @@
 
     @Test
     public void testKeepGoingDefault() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("failfoo");
         try {
             getProject(null, true, true).executeTargets(TARGET_NAMES);
-            fail("should fail");
-        } catch (BuildException e) {
-            assertEquals("failfoo", e.getMessage());
+        } finally {
             assertEquals(2, targetCount);
         }
     }
 
     @Test
     public void testKeepGoingSingleCheck() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("failfoo");
         try {
             getProject(SINGLE_CHECK, true, true).executeTargets(TARGET_NAMES);
-            fail("should fail");
-        } catch (BuildException e) {
-            assertEquals("failfoo", e.getMessage());
+        } finally {
             assertEquals(1, targetCount);
         }
     }
 
     @Test
     public void testKeepGoingIgnoreDependencies() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("failfoo");
+        Vector<String> targetNames = new Vector<>(TARGET_NAMES);
+        // explicitly add foo for failure
+        targetNames.add(0, "foo");
         try {
-            //explicitly add foo for failure
-            Vector<String> targetNames = new Vector<String>(TARGET_NAMES);
-            targetNames.add(0, "foo");
             getProject(IGNORE_DEPS, true, true).executeTargets(targetNames);
-            fail("should fail");
-        } catch (BuildException e) {
-            assertEquals("failfoo", e.getMessage());
+        } finally {
             assertEquals(3, targetCount);
         }
     }
diff --git a/src/tests/junit/org/apache/tools/ant/ExtendedTaskdefTest.java b/src/tests/junit/org/apache/tools/ant/ExtendedTaskdefTest.java
index d5444f9..92d0d77 100644
--- a/src/tests/junit/org/apache/tools/ant/ExtendedTaskdefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/ExtendedTaskdefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,14 +17,11 @@
  */
 package org.apache.tools.ant;
 
-import static org.junit.Assert.fail;
-
-import static org.apache.tools.ant.AntAssert.assertContains;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * created 16-Mar-2006 12:25:12
@@ -35,34 +32,37 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/core/extended-taskdef.xml");
     }
 
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
         buildRule.executeTarget("teardown");
     }
 
+    /**
+     * Exception should be thrown by a subclass
+     */
     @Test
-    public void testRun() throws Exception {
-        try {
-            buildRule.executeTarget("testRun");
-            fail("BuildException should have been thrown");
-        } catch (BuildException ex) {
-            assertContains("exception thrown by the subclass", "executing the Foo task", ex.getMessage());
-        }
+    public void testRun() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("executing the Foo task");
+        buildRule.executeTarget("testRun");
     }
 
+    /**
+     * Exception should be thrown by a subclass
+     */
     @Test
-    public void testRun2() throws Exception {
-        try {
-            buildRule.executeTarget("testRun2");
-            fail("BuildException should have been thrown");
-        } catch (BuildException ex) {
-            assertContains("exception thrown by the subclass", "executing the Foo task", ex.getMessage());
-        }
+    public void testRun2() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("executing the Foo task");
+        buildRule.executeTarget("testRun2");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/FileUtilities.java b/src/tests/junit/org/apache/tools/ant/FileUtilities.java
index 321d8d4..2a64f1f 100644
--- a/src/tests/junit/org/apache/tools/ant/FileUtilities.java
+++ b/src/tests/junit/org/apache/tools/ant/FileUtilities.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.util.Arrays;
 
 import static org.junit.Assume.assumeTrue;
 
@@ -46,20 +47,13 @@
      * @throws IOException on error reading the file (not existing, not readable etc)
      */
     public static String getFileContents(File file) throws IOException {
-            FileReader rdr = null;
-            try {
-                rdr = new FileReader(file);
-                return FileUtils.readFully(rdr);
-            }
-            finally {
-                if (rdr != null) {
-                rdr.close();
-            }
+        try (FileReader rdr = new FileReader(file)) {
+            return FileUtils.readFully(rdr);
         }
     }
 
     /**
-     * Modified the timestamp on a file so it's <tt>seconds</tt> earlier than it was before. Where <tt>file</tt>
+     * Modified the timestamp on a file so it's <code>seconds</code> earlier than it was before. Where <code>file</code>
      * is a directory, this function recurses into all child files (and directories) and reduces their modified
      * timestamps by the same range, rather than set all timestamps to the same time.
      * @param file the file to change, or the directory to change then recurse into
@@ -78,9 +72,7 @@
             if (children == null) {
                 return;
             }
-            for (File child : children) {
-                rollbackTimestamps(child, seconds);
-            }
+            Arrays.stream(children).forEach(child -> rollbackTimestamps(child, seconds));
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/ImmutableTest.java b/src/tests/junit/org/apache/tools/ant/ImmutableTest.java
index eb8c4cc..f9f1789 100644
--- a/src/tests/junit/org/apache/tools/ant/ImmutableTest.java
+++ b/src/tests/junit/org/apache/tools/ant/ImmutableTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/IncludeTest.java b/src/tests/junit/org/apache/tools/ant/IncludeTest.java
index 80e53fe..9bb7cd0 100644
--- a/src/tests/junit/org/apache/tools/ant/IncludeTest.java
+++ b/src/tests/junit/org/apache/tools/ant/IncludeTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,16 @@
 
 package org.apache.tools.ant;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * Test the build file inclusion using XML entities.
@@ -35,6 +38,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void test1() {
         buildRule.configureProject("src/etc/testcases/core/include/basic/include.xml");
@@ -72,59 +78,41 @@
 
     @Test
     public void testParseErrorInIncluding() {
-        try {
-            buildRule.configureProject("src/etc/testcases/core/include/including_file_parse_error/build.xml");
-            fail("should have caused a parser exception");
-        } catch (BuildException e) {
-            assertContains(e.getLocation().toString()
-                       + " should refer to build.xml",
-                       "build.xml:", e.getLocation().toString());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("location", hasProperty("fileName",
+                containsString("build.xml"))));
+        buildRule.configureProject("src/etc/testcases/core/include/including_file_parse_error/build.xml");
     }
 
     @Test
     public void testTaskErrorInIncluding() {
+        // TODO the test breaks in IDE
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("location",
+                both(hasProperty("fileName", containsString("build.xml")))
+                        .and(hasProperty("lineNumber", equalTo(14)))));
+        thrown.expectMessage(startsWith("Warning: Could not find file "));
         buildRule.configureProject("src/etc/testcases/core/include/including_file_task_error/build.xml");
-        try {
-            buildRule.executeTarget("test");
-            fail("should have cause a build failure");
-        } catch (BuildException e) {
-            assertTrue(e.getMessage()
-                       + " should start with \'Warning: Could not find",
-                         e.getMessage().startsWith("Warning: Could not find file "));
-            assertTrue(e.getLocation().toString()
-                       + " should end with build.xml:14: ",
-                       e.getLocation().toString().endsWith("build.xml:14: "));
-        }
     }
 
     @Test
     public void testParseErrorInIncluded() {
-        try {
-            buildRule.configureProject("src/etc/testcases/core/include/included_file_parse_error/build.xml");
-            fail("should have caused a parser exception");
-        } catch (BuildException e) {
-            assertContains(e.getLocation().toString()
-                       + " should refer to included_file.xml",
-                       "included_file.xml:",
-                       e.getLocation().toString());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("location",
+                hasProperty("fileName", containsString("included_file.xml"))));
+        buildRule.configureProject("src/etc/testcases/core/include/included_file_parse_error/build.xml");
     }
 
     @Test
     public void testTaskErrorInIncluded() {
+        // TODO the test breaks in IDE
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("location",
+                both(hasProperty("fileName", containsString("included_file.xml")))
+                        .and(hasProperty("lineNumber", equalTo(2)))));
+        thrown.expectMessage(startsWith("Warning: Could not find file "));
         buildRule.configureProject("src/etc/testcases/core/include/included_file_task_error/build.xml");
-        try {
-            buildRule.executeTarget("test");
-            fail("should have cause a build failure");
-        } catch (BuildException e) {
-            assertTrue(e.getMessage()
-                       + " should start with \'Warning: Could not find",
-                         e.getMessage().startsWith("Warning: Could not find file "));
-            assertTrue(e.getLocation().toString()
-                       + " should end with included_file.xml:2: ",
-                       e.getLocation().toString().endsWith("included_file.xml:2: "));
-        }
+        buildRule.executeTarget("test");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/IntrospectionHelperSetOptionalAttributesTest.java b/src/tests/junit/org/apache/tools/ant/IntrospectionHelperSetOptionalAttributesTest.java
new file mode 100644
index 0000000..25c028e
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/IntrospectionHelperSetOptionalAttributesTest.java
@@ -0,0 +1,171 @@
+/*
+ *  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
+ *
+ *      https://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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+
+import java.io.File;
+import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
+
+import org.apache.tools.ant.util.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class IntrospectionHelperSetOptionalAttributesTest {
+    public static class HavingOptionals {
+        private Optional<String> foo;
+        private Optional<File> bar;
+        @SuppressWarnings("rawtypes")
+        private Optional baz;
+        private OptionalInt a;
+        private OptionalLong b;
+        private OptionalDouble c;
+
+        public Optional<String> getFoo() {
+            return foo;
+        }
+
+        public void setFoo(Optional<String> foo) {
+            this.foo = foo;
+        }
+
+        public Optional<File> getBar() {
+            return bar;
+        }
+
+        public void setBar(Optional<File> bar) {
+            this.bar = bar;
+        }
+
+        public OptionalInt getA() {
+            return a;
+        }
+
+        public void setA(OptionalInt a) {
+            this.a = a;
+        }
+
+        public OptionalLong getB() {
+            return b;
+        }
+
+        public void setB(OptionalLong b) {
+            this.b = b;
+        }
+
+        public OptionalDouble getC() {
+            return c;
+        }
+
+        public void setC(OptionalDouble c) {
+            this.c = c;
+        }
+
+        @SuppressWarnings("rawtypes")
+        public Optional getBaz() {
+            return baz;
+        }
+
+        @SuppressWarnings("rawtypes")
+        public void setBaz(Optional baz) {
+            this.baz = baz;
+        }
+    }
+
+    private Project p;
+    private IntrospectionHelper ih;
+    private HavingOptionals subject;
+
+    @Before
+    public void setup() {
+        p = new Project();
+        p.setBasedir(File.separator);
+        ih = IntrospectionHelper.getHelper(HavingOptionals.class);
+        subject = new HavingOptionals();
+    }
+
+    @Test
+    public void testOptionalString() {
+        ih.setAttribute(p, subject, "foo", "fooValue");
+        assertEquals("fooValue", subject.getFoo().get());
+    }
+
+    @Test
+    public void testEmptyOptionalString() {
+        ih.setAttribute(p, subject, "foo", null);
+        assertFalse(subject.getFoo().isPresent());
+    }
+
+    @Test
+    public void testOptionalFile() {
+        ih.setAttribute(p, subject, "bar", "barFile");
+        assertEquals(p.resolveFile("barFile"), subject.getBar().get());
+    }
+
+    @Test
+    public void testEmptyOptionalFile() {
+        ih.setAttribute(p, subject, "bar", null);
+        assertFalse(subject.getBar().isPresent());
+    }
+
+    @Test
+    public void testOptionalRaw() {
+        assertThrows(BuildException.class, () -> ih.setAttribute(p, subject, "baz", "bazValue"));
+    }
+
+    @Test
+    public void testOptionalInt() {
+        ih.setAttribute(p, subject, "a", "6");
+        assertEquals(6, subject.getA().getAsInt());
+    }
+
+    @Test
+    public void testEmptyOptionalInt() {
+        ih.setAttribute(p, subject, "a", null);
+        assertFalse(subject.getA().isPresent());
+    }
+
+    @Test
+    public void testOptionalLong() throws Exception {
+        ih.setAttribute(p, subject, "b", "6K");
+        assertEquals(StringUtils.parseHumanSizes("6K"), subject.getB().getAsLong());
+    }
+
+    @Test
+    public void testEmptyOptionalLong() throws Exception {
+        ih.setAttribute(p, subject, "b", null);
+        assertFalse(subject.getB().isPresent());
+    }
+
+    @Test
+    public void testOptionalDouble() {
+        ih.setAttribute(p, subject, "c", "6.66");
+        assertEquals(6.66, subject.getC().getAsDouble(), 0.00001);
+    }
+
+    @Test
+    public void testEmptyOptionalDouble() {
+        ih.setAttribute(p, subject, "c", null);
+        assertFalse(subject.getC().isPresent());
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/IntrospectionHelperTest.java b/src/tests/junit/org/apache/tools/ant/IntrospectionHelperTest.java
index c318c68..63746a3 100644
--- a/src/tests/junit/org/apache/tools/ant/IntrospectionHelperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/IntrospectionHelperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,9 @@
 import java.io.File;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.Enumeration;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
@@ -32,13 +34,17 @@
 import org.junit.Before;
 import org.junit.ComparisonFailure;
 import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
+import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit testcases for org.apache.tools.ant.IntrospectionHelper.
@@ -47,6 +53,9 @@
 
 public class IntrospectionHelperTest {
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private Project p;
     private IntrospectionHelper ih;
     private static final String projectBasedir = File.separator;
@@ -69,141 +78,171 @@
     }
 
     @Test
-    public void testAddText() throws BuildException {
+    public void testAddText() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(ComparisonFailure.class)));
         ih.addText(p, this, "test");
-        try {
-            ih.addText(p, this, "test2");
-            fail("test2 shouldn\'t be equal to test");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof ComparisonFailure);
-        }
-
-        ih = IntrospectionHelper.getHelper(String.class);
-        try {
-            ih.addText(p, "", "test");
-            fail("String doesn\'t support addText");
-        } catch (BuildException be) {
-            //TODO the value should be asserted
-        }
+        ih.addText(p, this, "test2");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
+    public void testAddTextToString() throws BuildException {
+        ih = IntrospectionHelper.getHelper(String.class);
+        ih.addText(p, "", "test");
+    }
+
     @Ignore("This silently ignores a build exception")
+    @Test(expected = BuildException.class)
     public void testGetAddTextMethod() {
         Method m = ih.getAddTextMethod();
         assertMethod(m, "addText", String.class, "test", "bing!");
-
-        ih = IntrospectionHelper.getHelper(String.class);
-        try {
-            m = ih.getAddTextMethod();
-        } catch (BuildException e) {
-        }
+        IntrospectionHelper.getHelper(String.class).getAddTextMethod();
     }
 
     @Test
     public void testSupportsCharacters() {
-        assertTrue("IntrospectionHelperTest supports addText",
-                   ih.supportsCharacters());
-
+        assertTrue("IntrospectionHelperTest supports addText", ih.supportsCharacters());
         ih = IntrospectionHelper.getHelper(String.class);
-        assertTrue("String doesn\'t support addText", !ih.supportsCharacters());
+        assertFalse("String doesn't support addText", ih.supportsCharacters());
     }
 
     public void addText(String text) {
         assertEquals("test", text);
     }
 
+    /**
+     * Fail: don't have element type one
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorOne() {
+        ih.getElementType("one");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: createTwo takes arguments
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorTwo() {
+        ih.getElementType("two");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: createThree returns void
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorThree() {
+        ih.getElementType("three");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: createFour returns array
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorFour() {
+        ih.getElementType("four");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: createFive returns primitive type
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorFive() {
+        ih.getElementType("five");
+        // TODO we should be asserting a value in here
+    }
+
     @Test
-    public void testElementCreators() throws BuildException {
-        try {
-            ih.getElementType("one");
-            fail("don't have element type one");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("two");
-            fail("createTwo takes arguments");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("three");
-            fail("createThree returns void");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("four");
-            fail("createFour returns array");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("five");
-            fail("createFive returns primitive type");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
+    public void testElementCreatorSix() throws BuildException {
         assertEquals(String.class, ih.getElementType("six"));
         assertEquals("test", ih.createElement(p, this, "six"));
+    }
 
-        try {
-            ih.getElementType("seven");
-            fail("addSeven takes two arguments");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("eight");
-            fail("addEight takes no arguments");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("nine");
-            fail("nine return non void");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("ten");
-            fail("addTen takes array argument");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("eleven");
-            fail("addEleven takes primitive argument");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.getElementType("twelve");
-            fail("no primitive constructor for java.lang.Class");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
+    /**
+     * Fail: addSeven takes two arguments
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorSeven() {
+        ih.getElementType("seven");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: addEight takes no arguments
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorEight() {
+        ih.getElementType("eight");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: addNine returns non void
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorNine() {
+        ih.getElementType("nine");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: addTen takes array argument
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorTen() {
+        ih.getElementType("ten");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * addEleven takes primitive argument
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorEleven() {
+        ih.getElementType("eleven");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: no primitive constructor for java.lang.Class
+     */
+    @Test(expected = BuildException.class)
+    public void testElementCreatorTwelve() throws BuildException {
+        ih.getElementType("twelve");
+        // TODO we should be asserting a value in here
+    }
+
+    @Test
+    public void testElementCreatorThirteen() throws BuildException {
         assertEquals(StringBuffer.class, ih.getElementType("thirteen"));
         assertEquals("test", ih.createElement(p, this, "thirteen").toString());
+    }
 
-        try {
-            ih.createElement(p, this, "fourteen");
-            fail("fourteen throws NullPointerException");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof NullPointerException);
-        }
+    /**
+     * Fail: fourteen throws NullPointerException
+     */
+    @Test
+    public void testElementCreatorFourteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(NullPointerException.class)));
+        ih.createElement(p, this, "fourteen");
+    }
 
-        try {
-            ih.createElement(p, this, "fourteen");
-            fail("fifteen throws NullPointerException");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof NullPointerException);
-        }
+    /**
+     * Fail: fifteen throws NullPointerException
+     */
+    @Test
+    public void testElementCreatorFifteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(NullPointerException.class)));
+        ih.createElement(p, this, "fifteen");
     }
 
     private Map<String, Class<?>> getExpectedNestedElements() {
-        Map<String, Class<?>> elemMap = new Hashtable<String, Class<?>>();
+        Map<String, Class<?>> elemMap = new Hashtable<>();
         elemMap.put("six", String.class);
         elemMap.put("thirteen", StringBuffer.class);
         elemMap.put("fourteen", StringBuffer.class);
@@ -214,11 +253,9 @@
     @Test
     public void testGetNestedElements() {
         Map<String, Class<?>> elemMap = getExpectedNestedElements();
-        Enumeration e = ih.getNestedElements();
-        while (e.hasMoreElements()) {
-            String name = (String) e.nextElement();
-            Class expect = (Class) elemMap.get(name);
-            assertNotNull("Support for "+name+" in IntrospectioNHelperTest?",
+        for (String name : Collections.list(ih.getNestedElements())) {
+            Class<?> expect = elemMap.get(name);
+            assertNotNull("Support for " + name + " in IntrospectionHelperTest?",
                           expect);
             assertEquals("Return type of " + name, expect, ih.getElementType(name));
             elemMap.remove(name);
@@ -226,26 +263,21 @@
         assertTrue("Found all", elemMap.isEmpty());
     }
 
-    @Test
+    @Test(expected = UnsupportedOperationException.class)
     public void testGetNestedElementMap() {
         Map<String, Class<?>> elemMap = getExpectedNestedElements();
         Map<String, Class<?>> actualMap = ih.getNestedElementMap();
-        for (Map.Entry<String, Class<?>> entry : actualMap.entrySet()) {
-            String elemName = (String) entry.getKey();
-            Class<?> elemClass = (Class) elemMap.get(elemName);
-            assertNotNull("Support for " + elemName +
-                          " in IntrospectionHelperTest?", elemClass);
-            assertEquals("Type of " + elemName, elemClass, entry.getValue());
+        actualMap.forEach((elemName, value) -> {
+            Class<?> elemClass = elemMap.get(elemName);
+            assertNotNull("Support for " + elemName + " in IntrospectionHelperTest?", elemClass);
+            assertEquals("Type of " + elemName, elemClass, value);
             elemMap.remove(elemName);
-        }
+        });
         assertTrue("Found all", elemMap.isEmpty());
 
         // Check it's a read-only map.
-        try {
-            actualMap.clear();
-            //TODO we should be asserting a value somewhere in here
-        } catch (UnsupportedOperationException e) {
-        }
+        actualMap.clear();
+        // TODO we should be asserting a value somewhere in here
     }
 
     @Test
@@ -257,12 +289,12 @@
     }
 
     private void assertElemMethod(String elemName, String methodName,
-                                  Class returnType, Class methodArg) {
+                                  Class<?> returnType, Class<?> methodArg) {
         Method m = ih.getElementMethod(elemName);
         assertEquals("Method name", methodName, m.getName());
-        Class expectedReturnType = (returnType == null)? Void.TYPE: returnType;
+        Class<?> expectedReturnType = (returnType == null) ? Void.TYPE : returnType;
         assertEquals("Return type", expectedReturnType, m.getReturnType());
-        Class[] args = m.getParameterTypes();
+        Class<?>[] args = m.getParameterTypes();
         if (methodArg != null) {
             assertEquals("Arg Count", 1, args.length);
             assertEquals("Arg Type", methodArg, args[0]);
@@ -310,7 +342,7 @@
     public void addEleven(int i) {
     }
 
-    public void addTwelve(Class c) {
+    public void addTwelve(Class<?> c) {
     }
 
     public void addThirteen(StringBuffer sb) {
@@ -321,145 +353,215 @@
         throw new NullPointerException();
     }
 
-    @Test
-    public void testAttributeSetters() throws BuildException {
-        try {
-            ih.setAttribute(p, this, "one", "test");
-            fail("setOne doesn't exist");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.setAttribute(p, this, "two", "test");
-            fail("setTwo returns non void");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.setAttribute(p, this, "three", "test");
-            fail("setThree takes no args");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.setAttribute(p, this, "four", "test");
-            fail("setFour takes two args");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.setAttribute(p, this, "five", "test");
-            fail("setFive takes array arg");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        try {
-            ih.setAttribute(p, this, "six", "test");
-            fail("Project doesn't have a String constructor");
-        } catch (BuildException be) {
-            //TODO we should be asserting a value in here
-        }
-        ih.setAttribute(p, this, "seven", "2");
-        try {
-            ih.setAttribute(p, this, "seven", "3");
-            fail("2 shouldn't be equals to three");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof ComparisonFailure);
-        }
-        ih.setAttribute(p, this, "eight", "2");
-        try {
-            ih.setAttribute(p, this, "eight", "3");
-            fail("2 shouldn't be equals to three - as int");
-        } catch (BuildException be) {
-            assertTrue("Cause of error: " + be.toString(), be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "nine", "2");
-        try {
-            ih.setAttribute(p, this, "nine", "3");
-            fail("2 shouldn't be equals to three - as Integer");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "ten", "2");
-        try {
-            ih.setAttribute(p, this, "ten", "3");
-            fail(projectBasedir + "2 shouldn't be equals to " + projectBasedir + "3");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "eleven", "2");
-        try {
-            ih.setAttribute(p, this, "eleven", "on");
-            fail("on shouldn't be false");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "twelve", "2");
-        try {
-            ih.setAttribute(p, this, "twelve", "on");
-            fail("on shouldn't be false");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.Project");
-        try {
-            ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.ProjectHelper");
-            fail("org.apache.tools.ant.Project shouldn't be equal to org.apache.tools.ant.ProjectHelper");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        try {
-            ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.Project2");
-            fail("org.apache.tools.ant.Project2 doesn't exist");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof ClassNotFoundException);
-        }
-        ih.setAttribute(p, this, "fourteen", "2");
-        try {
-            ih.setAttribute(p, this, "fourteen", "on");
-            fail("2 shouldn't be equals to three - as StringBuffer");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof ComparisonFailure);
-        }
-        ih.setAttribute(p, this, "fifteen", "abcd");
-        try {
-            ih.setAttribute(p, this, "fifteen", "on");
-            fail("o shouldn't be equal to a");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "sixteen", "abcd");
-        try {
-            ih.setAttribute(p, this, "sixteen", "on");
-            fail("o shouldn't be equal to a");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "seventeen", "17");
-        try {
-            ih.setAttribute(p, this, "seventeen", "3");
-            fail("17 shouldn't be equals to three");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "eightteen", "18");
-        try {
-            ih.setAttribute(p, this, "eightteen", "3");
-            fail("18 shouldn't be equals to three");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
-        ih.setAttribute(p, this, "nineteen", "19");
-        try {
-            ih.setAttribute(p, this, "nineteen", "3");
-            fail("19 shouldn't be equals to three");
-        } catch (BuildException be) {
-            assertTrue(be.getCause() instanceof AssertionError);
-        }
+    /**
+     * Fail: setOne doesn't exist
+     */
+    @Test(expected = BuildException.class)
+    public void testAttributeSetterOne() {
+        ih.setAttribute(p, this, "one", "test");
+        // TODO we should be asserting a value in here
     }
 
-    private Map getExpectedAttributes() {
-        Map attrMap = new Hashtable();
+    /**
+     * Fail: setTwo returns non void
+     */
+    @Test(expected = BuildException.class)
+    public void testAttributeSetterTwo() {
+        ih.setAttribute(p, this, "two", "test");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: setThree takes no args
+     */
+    @Test(expected = BuildException.class)
+    public void testAttributeSetterThree() {
+        ih.setAttribute(p, this, "three", "test");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: setFour takes two args
+     */
+    @Test(expected = BuildException.class)
+    public void testAttributeSetterFour() {
+        ih.setAttribute(p, this, "four", "test");
+        //TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: setFive takes array arg
+     */
+    @Test(expected = BuildException.class)
+    public void testAttributeSetterFive() {
+        ih.setAttribute(p, this, "five", "test");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: Project doesn't have a String constructor
+     */
+    @Test(expected = BuildException.class)
+    public void testAttributeSetterSix() {
+        ih.setAttribute(p, this, "six", "test");
+        // TODO we should be asserting a value in here
+    }
+
+    /**
+     * Fail: 2 shouldn't be equal to three
+     */
+    @Test
+    public void testAttributeSetterSeven() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(ComparisonFailure.class)));
+        ih.setAttribute(p, this, "seven", "2");
+        ih.setAttribute(p, this, "seven", "3");
+    }
+
+    /**
+     * Fail: 2 shouldn't be equal to three as int
+     */
+    @Test
+    public void testAttributeSetterEight() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "eight", "2");
+        ih.setAttribute(p, this, "eight", "3");
+    }
+
+    /**
+     * Fail: 2 shouldn't be equal to three as Integer
+     */
+    @Test
+    public void testAttributeSetterNine() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "nine", "2");
+        ih.setAttribute(p, this, "nine", "3");
+    }
+
+    /**
+     * Fail: string + 2 shouldn't be equal to string + 3
+     */
+    @Test
+    public void testAttributeSetterTen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "ten", "2");
+        ih.setAttribute(p, this, "ten", "3");
+    }
+
+    /**
+     * Fail: on shouldn't be false
+     */
+    @Test
+    public void testAttributeSetterEleven() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "eleven", "2");
+        ih.setAttribute(p, this, "eleven", "on");
+    }
+
+    /**
+     * Fail: on shouldn't be false
+     */
+    @Test
+    public void testAttributeSetterTwelve() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "twelve", "2");
+        ih.setAttribute(p, this, "twelve", "on");
+    }
+
+    /**
+     * Fail: org.apache.tools.ant.Project shouldn't be equal to org.apache.tools.ant.ProjectHelper
+     */
+    @Test
+    public void testAttributeSetterThirteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.Project");
+        ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.ProjectHelper");
+    }
+
+    /**
+     * Fail: org.apache.tools.ant.Project2 doesn't exist
+     */
+    @Test
+    public void testAttributeSetterThirteenNonExistentClass() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(ClassNotFoundException.class)));
+        ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.Project2");
+    }
+
+    /**
+     * Fail: 2 shouldn't be equal to three as StringBuffer
+     */
+    @Test
+    public void testAttributeSetterFourteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(ComparisonFailure.class)));
+        ih.setAttribute(p, this, "fourteen", "2");
+            ih.setAttribute(p, this, "fourteen", "on");
+    }
+
+    /**
+     * Fail: o shouldn't be equal to a
+     */
+    @Test
+    public void testAttributeSetterFifteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "fifteen", "abcd");
+        ih.setAttribute(p, this, "fifteen", "on");
+    }
+
+    /**
+     * Fail: o shouldn't be equal to a
+     */
+    @Test
+    public void testAttributeSetterSixteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "sixteen", "abcd");
+        ih.setAttribute(p, this, "sixteen", "on");
+    }
+
+    /**
+     * Fail: 17 shouldn't be equals to three
+     */
+    @Test
+    public void testAttributeSetterSeventeen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "seventeen", "17");
+        ih.setAttribute(p, this, "seventeen", "3");
+    }
+
+    /**
+     * Fail: 18 shouldn't be equals to three
+     */
+    @Test
+    public void testAttributeSetterEighteen() {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "eightteen", "18");
+        ih.setAttribute(p, this, "eightteen", "3");
+    }
+
+    /**
+     * Fail: 19 shouldn't be equals to three
+     */
+    @Test
+    public void testAttributeSetterNineteen() throws BuildException {
+        thrown.expect(BuildException.class);
+        thrown.expect(hasProperty("cause", instanceOf(AssertionError.class)));
+        ih.setAttribute(p, this, "nineteen", "19");
+        ih.setAttribute(p, this, "nineteen", "3");
+    }
+
+    private Map<String, Class<?>> getExpectedAttributes() {
+        Map<String, Class<?>> attrMap = new Hashtable<>();
         attrMap.put("seven", String.class);
         attrMap.put("eight", Integer.TYPE);
         attrMap.put("nine", Integer.class);
@@ -473,11 +575,11 @@
         attrMap.put("seventeen", Byte.TYPE);
         attrMap.put("eightteen", Short.TYPE);
         attrMap.put("nineteen", Double.TYPE);
+        attrMap.put("twenty", Path.class);
 
         /*
          * JUnit 3.7 adds a getName method to TestCase - so we now
-         * have a name attribute in IntrospectionHelperTest if we run
-         * under JUnit 3.7 but not in earlier versions.
+         * have a name attribute in IntrospectionHelperTest.
          *
          * Simply add it here and remove it after the tests.
          */
@@ -488,14 +590,12 @@
 
     @Test
     public void testGetAttributes() {
-        Map attrMap = getExpectedAttributes();
-        Enumeration e = ih.getAttributes();
-        while (e.hasMoreElements()) {
-            String name = (String) e.nextElement();
-            Class expect = (Class) attrMap.get(name);
-            assertNotNull("Support for "+name+" in IntrospectionHelperTest?",
+        Map<String, Class<?>> attrMap = getExpectedAttributes();
+        for (String name : Collections.list(ih.getAttributes())) {
+            Class<?> expect = attrMap.get(name);
+            assertNotNull("Support for " + name + " in IntrospectionHelperTest?",
                           expect);
-            assertEquals("Type of "+name, expect, ih.getAttributeType(name));
+            assertEquals("Type of " + name, expect, ih.getAttributeType(name));
             attrMap.remove(name);
         }
         attrMap.remove("name");
@@ -505,67 +605,63 @@
     @Test
     public void testGetAttributeMap() {
         Map<String, Class<?>> attrMap = getExpectedAttributes();
-        Map<String, Class<?>> actualMap = ih.getAttributeMap();
-        for (Map.Entry<String, Class<?>> entry : actualMap.entrySet()) {
-            String attrName = (String) entry.getKey();
-            Class attrClass = (Class) attrMap.get(attrName);
-            assertNotNull("Support for " + attrName +
-                          " in IntrospectionHelperTest?", attrClass);
-            assertEquals("Type of " + attrName, attrClass, entry.getValue());
+        ih.getAttributeMap().forEach((attrName, value) -> {
+            Class<?> attrClass = attrMap.get(attrName);
+            assertNotNull("Support for " + attrName + " in IntrospectionHelperTest?", attrClass);
+            assertEquals("Type of " + attrName, attrClass, value);
             attrMap.remove(attrName);
-        }
+        });
         attrMap.remove("name");
         assertTrue("Found all", attrMap.isEmpty());
+    }
 
+    @Test
+    public void testClearGetAttributeMap() {
+        thrown.expect(UnsupportedOperationException.class);
+        // TODO we should be asserting a value somewhere in here
         // Check it's a read-only map.
-        try {
-            actualMap.clear();
-            //TODO we should be asserting a value somewhere in here
-        } catch (UnsupportedOperationException e) {
-        }
+        ih.getAttributeMap().clear();
     }
 
     @Test
     public void testGetAttributeMethod() {
         assertAttrMethod("seven", "setSeven", String.class,
-                         "2", "3");
+                "2", "3");
         assertAttrMethod("eight", "setEight", Integer.TYPE,
-                         Integer.valueOf(2), Integer.valueOf(3));
+                2, 3);
         assertAttrMethod("nine", "setNine", Integer.class,
-                         Integer.valueOf(2), Integer.valueOf(3));
+                2, 3);
         assertAttrMethod("ten", "setTen", File.class,
-                         new File(projectBasedir + 2), new File("toto"));
+                new File(projectBasedir + 2), new File("toto"));
         assertAttrMethod("eleven", "setEleven", Boolean.TYPE,
-                         Boolean.FALSE, Boolean.TRUE);
+                Boolean.FALSE, Boolean.TRUE);
         assertAttrMethod("twelve", "setTwelve", Boolean.class,
-                         Boolean.FALSE, Boolean.TRUE);
+                Boolean.FALSE, Boolean.TRUE);
         assertAttrMethod("thirteen", "setThirteen", Class.class,
-                         Project.class, Map.class);
+                Project.class, Map.class);
         assertAttrMethod("fourteen", "setFourteen", StringBuffer.class,
-                         new StringBuffer("2"), new StringBuffer("3"));
+                new StringBuffer("2"), new StringBuffer("3"));
         assertAttrMethod("fifteen", "setFifteen", Character.TYPE,
-                         Character.valueOf('a'), Character.valueOf('b'));
+                'a', 'b');
         assertAttrMethod("sixteen", "setSixteen", Character.class,
-                         Character.valueOf('a'), Character.valueOf('b'));
+                'a', 'b');
         assertAttrMethod("seventeen", "setSeventeen", Byte.TYPE,
-                         Byte.valueOf((byte) 17), Byte.valueOf((byte) 10));
+                (byte) 17, (byte) 10);
         assertAttrMethod("eightteen", "setEightteen", Short.TYPE,
-                         Short.valueOf((short) 18), Short.valueOf((short) 10));
+                (short) 18, (short) 10);
         assertAttrMethod("nineteen", "setNineteen", Double.TYPE,
-                         Double.valueOf(19), Double.valueOf((short) 10));
+                19d, (double) (short) 10);
+        assertAttrMethod("twenty", "setTwenty", Path.class,
+                new File(projectBasedir + 20).toPath(), Paths.get("toto"));
 
-        try {
-            assertAttrMethod("onehundred", null, null, null, null);
-            fail("Should have raised a BuildException!");
-        } catch (BuildException e) {
-            //TODO we should be asserting a value in here
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("doesn't support the \"onehundred\" attribute.");
+        assertAttrMethod("onehundred", null, null, null, null);
     }
 
     private void assertAttrMethod(String attrName, String methodName,
-                                  Class methodArg, Object arg, Object badArg) {
-        Method m = ih.getAttributeMethod(attrName);
-        assertMethod(m, methodName, methodArg, arg, badArg);
+                                  Class<?> methodArg, Object arg, Object badArg) {
+        assertMethod(ih.getAttributeMethod(attrName), methodName, methodArg, arg, badArg);
     }
 
     public int setTwo(String s) {
@@ -609,14 +705,14 @@
     }
 
     public void setEleven(boolean b) {
-        assertTrue(!b);
+        assertFalse(b);
     }
 
     public void setTwelve(Boolean b) {
-        assertTrue(!b.booleanValue());
+        assertFalse(b);
     }
 
-    public void setThirteen(Class c) {
+    public void setThirteen(Class<?> c) {
         assertEquals(Project.class, c);
     }
 
@@ -645,9 +741,21 @@
         assertTrue("Expected 19, received " + d, diff > -1e-6 && diff < 1e-6);
     }
 
+    public void setTwenty(Path p) {
+        String path = p.toAbsolutePath().toString();
+        if (Os.isFamily("unix") || Os.isFamily("openvms")) {
+            assertEquals(projectBasedir + "20", path);
+        } else if (Os.isFamily("netware")) {
+            assertEquals(projectBasedir + "20", path.toLowerCase(Locale.US));
+        } else {
+            assertEquals(":" + projectBasedir + "20",
+                         path.toLowerCase(Locale.US).substring(1));
+        }
+    }
+
     @Test
     public void testGetExtensionPoints() {
-        List extensions = ih.getExtensionPoints();
+        List<Method> extensions = ih.getExtensionPoints();
         final int adders = 2;
         assertEquals("extension count", adders, extensions.size());
 
@@ -658,51 +766,41 @@
         // combinatorics are too hard to check.  We really only want
         // to ensure that the more derived Hashtable can be found
         // before Map.
-//        assertExtMethod(extensions.get(0), "add", Number.class,
-//                        new Integer(2), new Integer(3));
+        // assertMethod(extensions.get(0), "add", Number.class, new Integer(2), new Integer(3));
 
         // addConfigured(Hashtable) should come before addConfigured(Map)
-        assertExtMethod(extensions.get(adders - 2),
+        assertMethod(extensions.get(adders - 2),
                         "addConfigured", Hashtable.class,
                         makeTable("key", "value"), makeTable("1", "2"));
 
-        assertExtMethod(extensions.get(adders - 1), "addConfigured", Map.class,
-                        new HashMap(), makeTable("1", "2"));
+        assertMethod(extensions.get(adders - 1), "addConfigured", Map.class,
+                        new HashMap<String, String>(), makeTable("1", "2"));
     }
 
-    private void assertExtMethod(Object mo, String methodName, Class methodArg,
-                                 Object arg, Object badArg) {
-        assertMethod((Method) mo, methodName, methodArg, arg, badArg);
-    }
-
-    private void assertMethod(Method m, String methodName, Class methodArg,
+    private void assertMethod(Method m, String methodName, Class<?> methodArg,
                               Object arg, Object badArg) {
         assertEquals("Method name", methodName, m.getName());
         assertEquals("Return type", Void.TYPE, m.getReturnType());
-        Class[] args = m.getParameterTypes();
+        Class<?>[] args = m.getParameterTypes();
         assertEquals("Arg Count", 1, args.length);
         assertEquals("Arg Type", methodArg, args[0]);
 
         try {
-            m.invoke(this, new Object[] { arg });
-        } catch (IllegalAccessException e) {
-            throw new BuildException(e);
-        } catch (InvocationTargetException e) {
+            m.invoke(this, arg);
+        } catch (IllegalAccessException | InvocationTargetException e) {
             throw new BuildException(e);
         }
 
         try {
-            m.invoke(this, new Object[] { badArg });
-            fail("Should have raised an assertion exception");
+            m.invoke(this, badArg);
         } catch (IllegalAccessException e) {
             throw new BuildException(e);
         } catch (InvocationTargetException e) {
-            Throwable t = e.getTargetException();
-            assertTrue(t.toString(), t instanceof AssertionError);
+            assertThat(e, hasProperty("cause", instanceOf(AssertionError.class)));
         }
     }
 
-    public List add(List l) {
+    public List<Object> add(List<Object> l) {
         // INVALID extension point
         return null;
     }
@@ -713,25 +811,24 @@
 //        assertEquals(2, n.intValue());
 //    }
 
-    public void add(List l, int i) {
+    public void add(List<Object> l, int i) {
         // INVALID extension point
     }
 
-    public void addConfigured(Map m) {
+    public void addConfigured(Map<Object, Object> m) {
         // Valid extension point
-        assertTrue(m.size() == 0);
+        assertTrue(m.isEmpty());
     }
 
-    public void addConfigured(Hashtable h) {
+    public void addConfigured(Hashtable<String, String> h) {
         // Valid extension point, more derived than Map above, but *after* it!
         assertEquals(makeTable("key", "value"), h);
     }
 
-    private Hashtable makeTable(Object key, Object value) {
-        Hashtable table = new Hashtable();
+    private Hashtable<String, String> makeTable(String key, String value) {
+        Hashtable<String, String> table = new Hashtable<>();
         table.put(key, value);
         return table;
     }
 
-} // IntrospectionHelperTest
-
+}
diff --git a/src/tests/junit/org/apache/tools/ant/LoaderRefTest.java b/src/tests/junit/org/apache/tools/ant/LoaderRefTest.java
index 668170b..497828a 100644
--- a/src/tests/junit/org/apache/tools/ant/LoaderRefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/LoaderRefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,10 @@
 
 package org.apache.tools.ant;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  */
@@ -32,6 +30,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/core/loaderref/loaderref.xml");
@@ -41,11 +42,8 @@
     // override allowed on <available>
     @Test
     public void testBadRef() {
-        try {
-            buildRule.executeTarget("testbadref");
-            fail("BuildRule should have thrown an exception due to a bad classloader being specified");
-        } catch (BuildException ex) {
-            assertContains("Should fail due to ref not being a class loader", "does not reference a class loader", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("does not reference a class loader");
+        buildRule.executeTarget("testbadref");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/LocationTest.java b/src/tests/junit/org/apache/tools/ant/LocationTest.java
index ca7f9b1..0788380 100644
--- a/src/tests/junit/org/apache/tools/ant/LocationTest.java
+++ b/src/tests/junit/org/apache/tools/ant/LocationTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,9 +25,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThat;
 
 public class LocationTest {
 
@@ -42,17 +44,17 @@
     @Test
     public void testPlainTask() {
         buildRule.executeTarget("testPlainTask");
-        Echo e = (Echo) buildRule.getProject().getReference("echo");
-        assertFalse(e.getLocation() == Location.UNKNOWN_LOCATION);
-        assertFalse(e.getLocation().getLineNumber() == 0);
+        Echo e = buildRule.getProject().getReference("echo");
+        assertNotSame(e.getLocation(), Location.UNKNOWN_LOCATION);
+        assertNotEquals(0, e.getLocation().getLineNumber());
     }
 
     @Test
     public void testStandaloneType() {
         buildRule.executeTarget("testStandaloneType");
-        Echo e = (Echo) buildRule.getProject().getReference("echo2");
-        FileSet f = (FileSet) buildRule.getProject().getReference("fs");
-        assertFalse(f.getLocation() == Location.UNKNOWN_LOCATION);
+        Echo e = buildRule.getProject().getReference("echo2");
+        FileSet f = buildRule.getProject().getReference("fs");
+        assertNotSame(f.getLocation(), Location.UNKNOWN_LOCATION);
         assertEquals(e.getLocation().getLineNumber() + 1,
                      f.getLocation().getLineNumber());
     }
@@ -60,26 +62,26 @@
     @Test
     public void testConditionTask() {
         buildRule.executeTarget("testConditionTask");
-        TaskAdapter ta = (TaskAdapter) buildRule.getProject().getReference("cond");
+        TaskAdapter ta = buildRule.getProject().getReference("cond");
         ConditionTask c = (ConditionTask) ta.getProxy();
-        assertFalse(c.getLocation() == Location.UNKNOWN_LOCATION);
-        assertFalse(c.getLocation().getLineNumber() == 0);
+        assertNotSame(c.getLocation(), Location.UNKNOWN_LOCATION);
+        assertNotEquals(0, c.getLocation().getLineNumber());
     }
 
     @Test
     public void testMacrodefWrappedTask() {
         buildRule.executeTarget("testMacrodefWrappedTask");
-        Echo e = (Echo) buildRule.getProject().getReference("echo3");
-        assertTrue(buildRule.getLog().contains("Line: "
-                + (e.getLocation().getLineNumber() + 1)));
+        Echo e = buildRule.getProject().getReference("echo3");
+        assertThat(buildRule.getLog(),
+                containsString("Line: " + (e.getLocation().getLineNumber() + 1)));
     }
 
     @Test
     public void testPresetdefWrappedTask() {
         buildRule.executeTarget("testPresetdefWrappedTask");
-        Echo e = (Echo) buildRule.getProject().getReference("echo4");
-        assertTrue(buildRule.getLog().contains("Line: "
-                + (e.getLocation().getLineNumber() + 1)));
+        Echo e = buildRule.getProject().getReference("echo4");
+        assertThat(buildRule.getLog(),
+                containsString("Line: " + (e.getLocation().getLineNumber() + 1)));
     }
 
     public static class EchoLocation extends Task {
diff --git a/src/tests/junit/org/apache/tools/ant/MagicTestNames.java b/src/tests/junit/org/apache/tools/ant/MagicTestNames.java
new file mode 100644
index 0000000..52611bc
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/MagicTestNames.java
@@ -0,0 +1,61 @@
+/*
+ *  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
+ *
+ *      https://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;
+
+/**
+ * Magic names used within Ant's tests.
+ *
+ * @since Ant 1.10.6
+ */
+public final class MagicTestNames {
+    /**
+     * Magic property that makes unit tests based on BuildFileTest
+     * or BuildFileRule ignore externally set basedir
+     * (typically by Surefire/Failsafe)
+     *
+     * Value: {@value}
+     * @since Ant 1.10.6
+     */
+    public static final String TEST_BASEDIR_IGNORE = "ant.test.basedir.ignore";
+
+    /**
+     * Magic property that makes unit tests based on BuildFileTest
+     * or BuildFileRule use build files in alternative locations
+     * (relative to "root" directory)
+     *
+     * Value: {@value}
+     * @since Ant 1.10.6
+     */
+    public static final String TEST_ROOT_DIRECTORY = "root";
+
+    /**
+     * Property for ant process ID set in unit tests by BuildFileTest
+     * or BuildFileRule.
+     *
+     * Value: {@value}
+     */
+    public static final String TEST_PROCESS_ID = "ant.processid";
+
+    /**
+     * Property for ant thread name set in unit tests by BuildFileTest
+     * or BuildFileRule.
+     *
+     * Value: {@value}
+     */
+    public static final String TEST_THREAD_NAME = "ant.threadname";
+}
diff --git a/src/tests/junit/org/apache/tools/ant/MockBuildListener.java b/src/tests/junit/org/apache/tools/ant/MockBuildListener.java
index 654872c..435e96c 100644
--- a/src/tests/junit/org/apache/tools/ant/MockBuildListener.java
+++ b/src/tests/junit/org/apache/tools/ant/MockBuildListener.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,14 +18,15 @@
 
 package org.apache.tools.ant;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
-
 import java.util.Vector;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 public class MockBuildListener implements BuildListener {
 
-    private final Vector<BuildEvent> buffer = new Vector<BuildEvent>();
+    private final Vector<BuildEvent> buffer = new Vector<>();
     private final Project project;
 
     public MockBuildListener(final Project project) {
@@ -54,10 +55,10 @@
         if (actual.getPriority() == Project.MSG_DEBUG) {
             return;
         }
-        assertTrue("unexpected messageLogged: "+ actual.getMessage(), !buffer.isEmpty());
+        assertFalse("unexpected messageLogged: " + actual.getMessage(), buffer.isEmpty());
         assertEquals("unexpected project ", project, actual.getProject());
 
-        BuildEvent expected = (BuildEvent) buffer.elementAt(0);
+        BuildEvent expected = buffer.elementAt(0);
         buffer.removeElementAt(0);
         assertEquals("unexpected messageLogged ", expected.getMessage(), actual.getMessage());
         assertEquals("unexpected priority ", expected.getPriority(), actual.getPriority());
diff --git a/src/tests/junit/org/apache/tools/ant/PickOneTask.java b/src/tests/junit/org/apache/tools/ant/PickOneTask.java
index 560194b..8472dc8 100644
--- a/src/tests/junit/org/apache/tools/ant/PickOneTask.java
+++ b/src/tests/junit/org/apache/tools/ant/PickOneTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/ProjectComponentTest.java b/src/tests/junit/org/apache/tools/ant/ProjectComponentTest.java
index 6e51209..da8447f 100644
--- a/src/tests/junit/org/apache/tools/ant/ProjectComponentTest.java
+++ b/src/tests/junit/org/apache/tools/ant/ProjectComponentTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/ProjectHelperRepositoryTest.java b/src/tests/junit/org/apache/tools/ant/ProjectHelperRepositoryTest.java
index eec42f7..32447d8 100644
--- a/src/tests/junit/org/apache/tools/ant/ProjectHelperRepositoryTest.java
+++ b/src/tests/junit/org/apache/tools/ant/ProjectHelperRepositoryTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,8 +25,8 @@
 import org.apache.tools.ant.types.resources.StringResource;
 import org.junit.Test;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertThat;
 
 /**
  * Testing around the management of the project helpers
@@ -45,61 +45,41 @@
     }
 
     @Test
-    public void testFind() throws Exception {
+    public void testFind() {
         ProjectHelperRepository repo = ProjectHelperRepository.getInstance();
         repo.registerProjectHelper(SomeHelper.class);
 
         Resource r = new FileResource(new File("test.xml"));
-        ProjectHelper helper = repo.getProjectHelperForBuildFile(r);
-        assertTrue(helper instanceof ProjectHelper2);
-        helper = repo.getProjectHelperForAntlib(r);
-        assertTrue(helper instanceof ProjectHelper2);
+        assertThat(repo.getProjectHelperForBuildFile(r), instanceOf(ProjectHelper2.class));
+        assertThat(repo.getProjectHelperForAntlib(r), instanceOf(ProjectHelper2.class));
 
         r = new FileResource(new File("test.myext"));
-        helper = repo.getProjectHelperForBuildFile(r);
-        assertTrue(helper instanceof SomeHelper);
-        helper = repo.getProjectHelperForAntlib(r);
-        assertTrue(helper instanceof SomeHelper);
+        assertThat(repo.getProjectHelperForBuildFile(r), instanceOf(SomeHelper.class));
+        assertThat(repo.getProjectHelperForAntlib(r), instanceOf(SomeHelper.class));
 
         r = new StringResource("test.myext");
-        helper = repo.getProjectHelperForBuildFile(r);
-        assertTrue(helper instanceof ProjectHelper2);
-        helper = repo.getProjectHelperForAntlib(r);
-        assertTrue(helper instanceof ProjectHelper2);
+        assertThat(repo.getProjectHelperForBuildFile(r), instanceOf(ProjectHelper2.class));
+        assertThat(repo.getProjectHelperForAntlib(r), instanceOf(ProjectHelper2.class));
 
         r = new StringResource("test.other");
-        helper = repo.getProjectHelperForBuildFile(r);
-        assertTrue(helper instanceof ProjectHelper2);
-        helper = repo.getProjectHelperForAntlib(r);
-        assertTrue(helper instanceof ProjectHelper2);
+        assertThat(repo.getProjectHelperForBuildFile(r), instanceOf(ProjectHelper2.class));
+        assertThat(repo.getProjectHelperForAntlib(r), instanceOf(ProjectHelper2.class));
     }
 
-    @Test
-    public void testNoDefaultContructor() throws Exception {
+    @Test(expected = BuildException.class)
+    public void testNoDefaultConstructor() {
 
-        class IncrrectHelper extends ProjectHelper {
+        class IncorrectHelper extends ProjectHelper {
             // the default constructor is not visible to ant here
         }
 
-        ProjectHelperRepository repo = ProjectHelperRepository.getInstance();
-        try {
-            repo.registerProjectHelper(IncrrectHelper.class);
-            fail("Registring an helper with no default constructor should fail");
-        } catch (BuildException e) {
-            // ok
-            //TODO we should be asserting a value in here
-        }
+        ProjectHelperRepository.getInstance().registerProjectHelper(IncorrectHelper.class);
+        // TODO we should be asserting a value in here
     }
 
-    @Test
-    public void testUnkwnowHelper() throws Exception {
-        ProjectHelperRepository repo = ProjectHelperRepository.getInstance();
-        try {
-            repo.registerProjectHelper("xxx.yyy.zzz.UnknownHelper");
-            fail("Registring an unknwon helper should fail");
-        } catch (BuildException e) {
-            // ok
-            //TODO we should be asserting a value in here
-        }
+    @Test(expected = BuildException.class)
+    public void testUnknownHelper() {
+        ProjectHelperRepository.getInstance().registerProjectHelper("xxx.yyy.zzz.UnknownHelper");
+        // TODO we should be asserting a value in here
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/ProjectTest.java b/src/tests/junit/org/apache/tools/ant/ProjectTest.java
index 365e92d..885e5aa 100644
--- a/src/tests/junit/org/apache/tools/ant/ProjectTest.java
+++ b/src/tests/junit/org/apache/tools/ant/ProjectTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,15 +31,21 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.hasValue;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Very limited test class for Project. Waiting to be extended.
@@ -50,6 +56,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private Project p;
     private String root;
     private MockBuildListener mbl;
@@ -68,70 +77,82 @@
                    p.createDataType("dummy"));
         Object o = p.createDataType("fileset");
         assertNotNull("fileset is a known type", o);
-        assertTrue("fileset creates FileSet", o instanceof FileSet);
-        assertTrue("PatternSet",
-               p.createDataType("patternset") instanceof PatternSet);
-        assertTrue("Path", p.createDataType("path") instanceof Path);
+        assertThat("fileset creates FileSet", o, instanceOf(FileSet.class));
+        assertThat("PatternSet", p.createDataType("patternset"),
+                instanceOf(PatternSet.class));
+        assertThat("Path", p.createDataType("path"), instanceOf(Path.class));
     }
 
     /**
-     * This test has been a starting point for moving the code to FileUtils.
+     * This test has been a starting point for moving the code to FileUtils;
+     * first, the DOS/Netware-specific part.
+     */
+    @Test
+    public void testResolveFileWithDriveLetter() {
+        assumeTrue("Not DOS or Netware", Os.isFamily("netware") || Os.isFamily("dos"));
+        assertEqualsIgnoreDriveCase(localize(File.separator),
+                p.resolveFile("/", null).getPath());
+        assertEqualsIgnoreDriveCase(localize(File.separator),
+                p.resolveFile("\\", null).getPath());
+        /*
+         * throw in drive letters
+         */
+        String driveSpec = "C:";
+        String driveSpecLower = "c:";
+
+        assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
+                p.resolveFile(driveSpec + "/", null).getPath());
+        assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
+                p.resolveFile(driveSpec + "\\", null).getPath());
+        assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
+                p.resolveFile(driveSpecLower + "/", null).getPath());
+        assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
+                p.resolveFile(driveSpecLower + "\\", null).getPath());
+        /*
+         * promised to eliminate consecutive slashes after drive letter.
+         */
+        assertEqualsIgnoreDriveCase(driveSpec + "\\",
+                p.resolveFile(driveSpec + "/////", null).getPath());
+        assertEqualsIgnoreDriveCase(driveSpec + "\\",
+                p.resolveFile(driveSpec + "\\\\\\\\\\\\", null).getPath());
+    }
+
+    /**
+     * This test has been a starting point for moving the code to FileUtils;
+     * now, the POSIX-specific part.
      */
     @Test
     public void testResolveFile() {
-        if (Os.isFamily("netware") || Os.isFamily("dos")) {
-            assertEqualsIgnoreDriveCase(localize(File.separator),
-                p.resolveFile("/", null).getPath());
-            assertEqualsIgnoreDriveCase(localize(File.separator),
-                p.resolveFile("\\", null).getPath());
-            /*
-             * throw in drive letters
-             */
-            String driveSpec = "C:";
-            String driveSpecLower = "c:";
-
-            assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
-                         p.resolveFile(driveSpec + "/", null).getPath());
-            assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
-                         p.resolveFile(driveSpec + "\\", null).getPath());
-            assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
-                         p.resolveFile(driveSpecLower + "/", null).getPath());
-            assertEqualsIgnoreDriveCase(driveSpecLower + "\\",
-                         p.resolveFile(driveSpecLower + "\\", null).getPath());
-            /*
-             * promised to eliminate consecutive slashes after drive letter.
-             */
-            assertEqualsIgnoreDriveCase(driveSpec + "\\",
-                         p.resolveFile(driveSpec + "/////", null).getPath());
-            assertEqualsIgnoreDriveCase(driveSpec + "\\",
-                         p.resolveFile(driveSpec + "\\\\\\\\\\\\", null).getPath());
-        } else {
-            /*
-             * Start with simple absolute file names.
-             */
-            assertEquals(File.separator,
-                         p.resolveFile("/", null).getPath());
-            assertEquals(File.separator,
-                         p.resolveFile("\\", null).getPath());
-            /*
-             * drive letters are not used, just to be considered as normal
-             * part of a name
-             */
-            String driveSpec = "C:";
-            String udir = System.getProperty("user.dir") + File.separatorChar;
-            assertEquals(udir + driveSpec,
-                         p.resolveFile(driveSpec + "/", null).getPath());
-            assertEquals(udir + driveSpec,
-                         p.resolveFile(driveSpec + "\\", null).getPath());
-            String driveSpecLower = "c:";
-            assertEquals(udir + driveSpecLower,
-                         p.resolveFile(driveSpecLower + "/", null).getPath());
-            assertEquals(udir + driveSpecLower,
-                         p.resolveFile(driveSpecLower + "\\", null).getPath());
-        }
+        assumeFalse("DOS or Netware", Os.isFamily("netware") || Os.isFamily("dos"));
         /*
-         * Now test some relative file name magic.
+         * Start with simple absolute file names.
          */
+        assertEquals(File.separator,
+                p.resolveFile("/", null).getPath());
+        assertEquals(File.separator,
+                p.resolveFile("\\", null).getPath());
+        /*
+         * drive letters are not used, just to be considered as normal
+         * part of a name
+         */
+        String driveSpec = "C:";
+        String udir = System.getProperty("user.dir") + File.separatorChar;
+        assertEquals(udir + driveSpec,
+                p.resolveFile(driveSpec + "/", null).getPath());
+        assertEquals(udir + driveSpec,
+                p.resolveFile(driveSpec + "\\", null).getPath());
+        String driveSpecLower = "c:";
+        assertEquals(udir + driveSpecLower,
+                p.resolveFile(driveSpecLower + "/", null).getPath());
+        assertEquals(udir + driveSpecLower,
+                p.resolveFile(driveSpecLower + "\\", null).getPath());
+    }
+
+    /**
+     * Test some relative file name magic: platform-neutral.
+     */
+    @Test
+    public void testResolveRelativeFile() {
         assertEquals(localize("/1/2/3/4"),
                      p.resolveFile("4", new File(localize("/1/2/3"))).getPath());
         assertEquals(localize("/1/2/3/4"),
@@ -166,8 +187,8 @@
      * is called via resolveFile to pass under cygwin
      */
     private void assertEqualsIgnoreDriveCase(String s1, String s2) {
-        if ((Os.isFamily("dos") || Os.isFamily("netware"))
-            && s1.length() >= 1 && s2.length() >= 1) {
+        assumeTrue("Not DOS or Netware", Os.isFamily("netware") || Os.isFamily("dos"));
+        if (s1.length() >= 1 && s2.length() >= 1) {
             StringBuilder sb1 = new StringBuilder(s1);
             StringBuilder sb2 = new StringBuilder(s2);
             sb1.setCharAt(0, Character.toUpperCase(s1.charAt(0)));
@@ -178,18 +199,16 @@
         }
     }
 
-    private void assertTaskDefFails(final Class taskClass,
-                                       final String message) {
+    private void assertTaskDefFails(final Class<?> taskClass, final String message) {
         final String dummyName = "testTaskDefinitionDummy";
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(message);
         try {
             mbl.addBuildEvent(message, Project.MSG_ERR);
             p.addTaskDefinition(dummyName, taskClass);
-            fail(String.format("expected BuildException(\"%s\", Project.MSG_ERR) when adding task %s",
-                    message, taskClass));
-        } catch (BuildException e) {
-            assertEquals(message, e.getMessage());
+        } finally {
             mbl.assertEmpty();
-            assertTrue(!p.getTaskDefinitions().containsKey(dummyName));
+            assertThat(p.getTaskDefinitions(), not(hasKey(dummyName)));
         }
     }
 
@@ -233,7 +252,7 @@
     public void testInputHandler() {
         InputHandler ih = p.getInputHandler();
         assertNotNull(ih);
-        assertTrue(ih instanceof DefaultInputHandler);
+        assertThat(ih, instanceOf(DefaultInputHandler.class));
         InputHandler pfih = new PropertyFileInputHandler();
         p.setInputHandler(pfih);
         assertSame(pfih, p.getInputHandler());
@@ -241,25 +260,22 @@
 
     @Test
     public void testTaskDefinitionContainsKey() {
-        assertTrue(p.getTaskDefinitions().containsKey("echo"));
+        assertThat(p.getTaskDefinitions(), hasKey("echo"));
     }
 
     @Test
-    public void testTaskDefinitionContains() {
-        assertTrue(p.getTaskDefinitions().contains(org.apache.tools.ant.taskdefs.Echo.class));
+    public void testTaskDefinitionContainsValue() {
+        assertThat(p.getTaskDefinitions(), hasValue(org.apache.tools.ant.taskdefs.Echo.class));
     }
 
+    /**
+     *  Fail because buildfile contains two targets with the same name
+     */
     @Test
     public void testDuplicateTargets() {
-        // fail, because buildfile contains two targets with the same name
-        try {
-            buildRule.configureProject("src/etc/testcases/core/duplicate-target.xml");
-            fail("Should throw BuildException about duplicate target");
-        } catch (BuildException ex) {
-            assertEquals("specific message",
-                         "Duplicate target 'twice'",
-                         ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Duplicate target 'twice'");
+        buildRule.configureProject("src/etc/testcases/core/duplicate-target.xml");
     }
 
     @Test
@@ -267,7 +283,7 @@
         // overriding target from imported buildfile is allowed
         buildRule.configureProject("src/etc/testcases/core/duplicate-target2.xml");
         buildRule.executeTarget("once");
-        assertContains("once from buildfile", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("once from buildfile"));
     }
 
     @Test
@@ -277,16 +293,22 @@
         p.addBuildListener(new BuildListener() {
                 public void buildStarted(BuildEvent event) {
                 }
+
                 public void buildFinished(BuildEvent event) {
                 }
+
                 public void targetStarted(BuildEvent event) {
                 }
+
                 public void targetFinished(BuildEvent event) {
                 }
+
                 public void taskStarted(BuildEvent event) {
                 }
+
                 public void taskFinished(BuildEvent event) {
                 }
+
                 public void messageLogged(final BuildEvent actual) {
                     assertEquals(FOO, actual.getMessage());
                     // each of the following lines would cause an
@@ -297,20 +319,17 @@
                 }
             });
         final boolean[] done = new boolean[] {false};
-        Thread t = new Thread() {
-                public void run() {
-                    p.log(FOO, Project.MSG_INFO);
-                    done[0] = true;
-                }
-            };
+        Thread t = new Thread(() -> {
+            p.log(FOO, Project.MSG_INFO);
+            done[0] = true;
+        });
         t.start();
         t.join(2000);
         assertTrue("Expected logging thread to finish successfully", done[0]);
     }
 
     /**
-     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=47623">
-     *     https://issues.apache.org/bugzilla/show_bug.cgi?id=47623</a>
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=47623">bug 47623</a>
      */
     @Test
     public void testNullThrowableMessageLog() {
@@ -322,6 +341,7 @@
         @SuppressWarnings("unused")
         public DummyTaskPrivate() {
         }
+
         public void execute() {
         }
     }
@@ -329,6 +349,7 @@
     protected class DummyTaskProtected extends Task {
         public DummyTaskProtected() {
         }
+
         public void execute() {
         }
     }
@@ -336,6 +357,7 @@
     class DummyTaskPackage extends Task {
         public DummyTaskPackage() {
         }
+
         public void execute() {
         }
     }
diff --git a/src/tests/junit/org/apache/tools/ant/PropertyExpansionTest.java b/src/tests/junit/org/apache/tools/ant/PropertyExpansionTest.java
index c943d3e..14eac76 100644
--- a/src/tests/junit/org/apache/tools/ant/PropertyExpansionTest.java
+++ b/src/tests/junit/org/apache/tools/ant/PropertyExpansionTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,19 +20,62 @@
 package org.apache.tools.ant;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
 
 import static org.junit.Assert.assertEquals;
 
 /**
  * class to look at how we expand properties
  */
+@RunWith(Parameterized.class)
 public class PropertyExpansionTest {
 
+    @Parameterized.Parameters(name = "expand \"{0}\" => \"{1}\"")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object [][] {
+                /* property expansion */
+                {"", ""},
+                {"$", "$"},
+                {"$$-", "$-"},
+                {"$$", "$"},
+                {"a${expanded}b", "aEXPANDEDb"},
+                {"${expanded}${expanded}", "EXPANDEDEXPANDED"},
+                {"$$$", "$$"},
+                {"$$$$-", "$$-"},
+                {"", ""},
+                {"Class$$subclass", "Class$subclass"},
+                /* dollar passthrough */
+                {"$-", "$-"},
+                {"Class$subclass", "Class$subclass"},
+                {"$$$-", "$$-"},
+                {"$$$$$", "$$$"},
+                {"${unassigned.property}", "${unassigned.property}"},
+                {"a$b", "a$b"},
+                {"$}}", "$}}"}
+                /* old things
+                {"Class$subclass", "Classsubclass"},
+                {"$$$-", "$-"},
+                {"a$b", "ab"},
+                {"$}}", "}}"},
+                */
+        });
+    }
+
+    @Parameterized.Parameter
+    public String input;
+
+    @Parameterized.Parameter(1)
+    public String expected;
+
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
+
     /**
      * we bind to an existing test file because we are too lazy to write our
      * own, and we don't really care what it is
@@ -40,59 +83,15 @@
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/core/immutable.xml");
-    }
-
-    /**
-     * run through the test cases of expansion
-     */
-    @Test
-    public void testPropertyExpansion() {
-        assertExpandsTo("", "");
-        assertExpandsTo("$", "$");
-        assertExpandsTo("$$-", "$-");
-        assertExpandsTo("$$", "$");
         buildRule.getProject().setProperty("expanded", "EXPANDED");
-        assertExpandsTo("a${expanded}b", "aEXPANDEDb");
-        assertExpandsTo("${expanded}${expanded}", "EXPANDEDEXPANDED");
-        assertExpandsTo("$$$", "$$");
-        assertExpandsTo("$$$$-", "$$-");
-        assertExpandsTo("", "");
-        assertExpandsTo("Class$$subclass", "Class$subclass");
     }
 
     /**
-     * new things we want
+     * the test itself
      */
     @Test
-    public void testDollarPassthru() {
-        assertExpandsTo("$-", "$-");
-        assertExpandsTo("Class$subclass", "Class$subclass");
-        assertExpandsTo("$$$-", "$$-");
-        assertExpandsTo("$$$$$", "$$$");
-        assertExpandsTo("${unassigned.property}", "${unassigned.property}");
-        assertExpandsTo("a$b", "a$b");
-        assertExpandsTo("$}}", "$}}");
-    }
-
-
-    /**
-     * old things we don't want; not a test anymore
-     */
-    @Test
-    @Ignore("Previously disabled through naming convention")
-    public void oldtestQuirkyLegacyBehavior() {
-        assertExpandsTo("Class$subclass", "Classsubclass");
-        assertExpandsTo("$$$-", "$-");
-        assertExpandsTo("a$b", "ab");
-        assertExpandsTo("$}}", "}}");
-    }
-
-    /**
-     * little helper method to validate stuff
-     */
-    private void assertExpandsTo(String source,String expected) {
-        String actual = buildRule.getProject().replaceProperties(source);
-        assertEquals(source,expected,actual);
+    public void test() {
+        assertEquals(input, expected, buildRule.getProject().replaceProperties(input));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/PropertyFileCLITest.java b/src/tests/junit/org/apache/tools/ant/PropertyFileCLITest.java
index 3718882..e1c8ec6 100644
--- a/src/tests/junit/org/apache/tools/ant/PropertyFileCLITest.java
+++ b/src/tests/junit/org/apache/tools/ant/PropertyFileCLITest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,42 +22,38 @@
 import java.io.FileReader;
 import java.io.FileWriter;
 import org.apache.tools.ant.util.FileUtils;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
 
 public class PropertyFileCLITest {
+    @Rule
+    public TemporaryFolder testFolder = new TemporaryFolder();
 
     @Test
     public void testPropertyResolution() throws Exception {
-        FileUtils fu = FileUtils.getFileUtils();
-        File props = fu.createTempFile("propertyfilecli", ".properties",
-                                       null, true, true);
-        File build = fu.createTempFile("propertyfilecli", ".xml", null, true,
-                                       true);
-        File log = fu.createTempFile("propertyfilecli", ".log", null, true,
-                                     true);
-        FileWriter fw = null;
-        FileReader fr = null;
-        try {
-            fw = new FileWriter(props);
+        File props = testFolder.newFile("propertyfilecli.properties");
+        try (FileWriter fw = new FileWriter(props)) {
             fw.write("w=world\nmessage=Hello, ${w}\n");
-            fw.close();
-            fw = new FileWriter(build);
+        }
+
+        File build = testFolder.newFile("propertyfilecli.xml");
+        try (FileWriter fw = new FileWriter(build)) {
             fw.write("<project><echo>${message}</echo></project>");
-            fw.close();
-            fw = null;
-            Main m = new NoExitMain();
-            m.startAnt(new String[] {
-                    "-propertyfile", props.getAbsolutePath(),
-                    "-f", build.getAbsolutePath(),
-                    "-l", log.getAbsolutePath()
-                }, null, null);
-            String l = FileUtils.safeReadFully(fr = new FileReader(log));
-            assertContains("Hello, world", l);
-        } finally {
-            FileUtils.close(fw);
-            FileUtils.close(fr);
+        }
+
+        Main m = new NoExitMain();
+        File log = testFolder.newFile("propertyfilecli.log");
+        m.startAnt(new String[] {
+                "-propertyfile", props.getAbsolutePath(),
+                "-f", build.getAbsolutePath(),
+                "-l", log.getAbsolutePath()
+        }, null, null);
+        try (FileReader fr = new FileReader(log)) {
+            assertThat(FileUtils.safeReadFully(fr), containsString("Hello, world"));
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java b/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java
new file mode 100644
index 0000000..883e5f1
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java
@@ -0,0 +1,55 @@
+/*
+ *  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
+ *
+ *      https://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;
+
+import org.apache.tools.ant.property.LocalProperties;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class PropertyHelperTest {
+
+    @Test
+    public void findsPropertyNamesSetDirectly() {
+        Project p = new Project();
+        p.setNewProperty("foo", "bar");
+        assertTrue(p.getPropertyNames().contains("foo"));
+    }
+
+    @Test
+    public void findsPropertyNamesSetForLocalProperties() {
+        Project p = new Project();
+        p.setNewProperty("foo", "bar");
+
+        LocalProperties localProperties = LocalProperties.get(p);
+        localProperties.enterScope();
+        localProperties.addLocal("baz");
+        p.setNewProperty("baz", "xyzzy");
+
+        assertTrue(p.getPropertyNames().contains("foo"));
+        assertTrue(p.getPropertyNames().contains("baz"));
+        assertTrue(p.getProperties().keySet().contains("foo"));
+        assertFalse(p.getProperties().keySet().contains("baz"));
+        localProperties.exitScope();
+
+        assertTrue(p.getPropertyNames().contains("foo"));
+        assertFalse(p.getPropertyNames().contains("baz"));
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/TaskContainerTest.java b/src/tests/junit/org/apache/tools/ant/TaskContainerTest.java
index 491d361..3a53e18 100644
--- a/src/tests/junit/org/apache/tools/ant/TaskContainerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/TaskContainerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
 
 public class TaskContainerTest {
 
@@ -37,30 +38,28 @@
     @Test
     public void testPropertyExpansion() {
         buildRule.executeTarget("testPropertyExpansion");
-        assertTrue("attribute worked",
-                buildRule.getLog().contains("As attribute: it worked"));
-        assertTrue("nested text worked",
-                buildRule.getLog().contains("As nested text: it worked"));
+        assertThat("attribute worked", buildRule.getLog(),
+                containsString(("As attribute: it worked")));
+        assertThat("nested text worked", buildRule.getLog(),
+                containsString(("As nested text: it worked")));
     }
 
     @Test
     public void testTaskdef() {
         buildRule.executeTarget("testTaskdef");
-        assertTrue("attribute worked",
-                buildRule.getLog().contains("As attribute: it worked"));
-        assertTrue("nested text worked",
-                buildRule.getLog().contains("As nested text: it worked"));
-        assertTrue("nested text worked",
-                buildRule.getLog().contains("As nested task: it worked"));
+        assertThat("attribute worked", buildRule.getLog(),
+                containsString("As attribute: it worked"));
+        assertThat("nested text worked", buildRule.getLog(),
+                containsString("As nested text: it worked"));
     }
 
     @Test
     public void testCaseInsensitive() {
         buildRule.executeTarget("testCaseInsensitive");
-        assertTrue("works outside of container",
-                buildRule.getLog().contains("hello "));
-        assertTrue("works inside of container",
-                buildRule.getLog().contains("world"));
+        assertThat("works outside of container", buildRule.getLog(),
+                containsString("hello "));
+        assertThat("works inside of container", buildRule.getLog(),
+                containsString("world"));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/TestHelper.java b/src/tests/junit/org/apache/tools/ant/TestHelper.java
index f36dd46..9f8582f 100644
--- a/src/tests/junit/org/apache/tools/ant/TestHelper.java
+++ b/src/tests/junit/org/apache/tools/ant/TestHelper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,21 +33,11 @@
      * after this method since the associated socket is released and some other process can now use it.
      */
     public static int getMaybeAvailablePort() {
-        final ServerSocket s;
-        try {
-            s = new ServerSocket(0);
+        try (ServerSocket s = new ServerSocket(0)) {
             s.setReuseAddress(true);
-            int port = s.getLocalPort();
-            try {
-                s.close();
-            } catch (IOException e) {
-                // ignore
-            }
-            return port;
+            return s.getLocalPort();
         } catch (IOException e) {
             // ignore
-        } finally {
-
         }
         throw new IllegalStateException("No TCP/IP port available");
     }
diff --git a/src/tests/junit/org/apache/tools/ant/TopLevelTaskTest.java b/src/tests/junit/org/apache/tools/ant/TopLevelTaskTest.java
index 7d73dc0..06e3575 100644
--- a/src/tests/junit/org/apache/tools/ant/TopLevelTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/TopLevelTaskTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,11 @@
 
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
 
 import static org.junit.Assert.assertEquals;
 
@@ -31,29 +36,31 @@
  *
  * @since Ant 1.6
  */
+@RunWith(Parameterized.class)
 public class TopLevelTaskTest {
 
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object[][]{
+                {"notarget", ""},
+                {"toplevelant", ""},
+                {"targetlevelant", "foo"}
+        });
+    }
+
+    @Parameterized.Parameter
+    public String fileName;
+
+    @Parameterized.Parameter(1)
+    public String targetName;
+
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Test
-    public void testNoTarget() {
-        buildRule.configureProject("src/etc/testcases/core/topleveltasks/notarget.xml");
-        buildRule.executeTarget("");
-        assertEquals("Called", buildRule.getLog());
-    }
-
-    @Test
-    public void testCalledFromTopLevelAnt() {
-        buildRule.configureProject("src/etc/testcases/core/topleveltasks/toplevelant.xml");
-        buildRule.executeTarget("");
-        assertEquals("Called", buildRule.getLog());
-    }
-
-    @Test
-    public void testCalledFromTargetLevelAnt() {
-        buildRule.configureProject("src/etc/testcases/core/topleveltasks/targetlevelant.xml");
-        buildRule.executeTarget("foo");
+    public void test() {
+        buildRule.configureProject("src/etc/testcases/core/topleveltasks/" + fileName + ".xml");
+        buildRule.executeTarget(targetName);
         assertEquals("Called", buildRule.getLog());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/UnknownElementTest.java b/src/tests/junit/org/apache/tools/ant/UnknownElementTest.java
index 76f0d8f..f73ec20 100644
--- a/src/tests/junit/org/apache/tools/ant/UnknownElementTest.java
+++ b/src/tests/junit/org/apache/tools/ant/UnknownElementTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,9 +26,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 
 public class UnknownElementTest {
 
@@ -49,53 +50,62 @@
     /**
      * Not really a UnknownElement test but rather one of "what
      * information is available in taskFinished".
-     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=26197">
-     *     https://issues.apache.org/bugzilla/show_bug.cgi?id=26197</a>
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=26197">bug 26197</a>
      */
     @Test
     @Ignore("Previously disabled through naming convention")
-    public void XtestTaskFinishedEvent() {
+    public void testTaskFinishedEvent() {
         buildRule.getProject().addBuildListener(new BuildListener() {
-                public void buildStarted(BuildEvent event) {
-                }
-                public void buildFinished(BuildEvent event) {
-                }
-                public void targetStarted(BuildEvent event) {
-                }
-                public void targetFinished(BuildEvent event) {
-                }
-                public void taskStarted(BuildEvent event) {
-                    assertTaskProperties(event.getTask());
-                }
-                public void taskFinished(BuildEvent event) {
-                    assertTaskProperties(event.getTask());
-                }
-                public void messageLogged(BuildEvent event) {
-                }
-                private void assertTaskProperties(Task ue) {
-                    assertNotNull(ue);
-                    assertTrue(ue instanceof UnknownElement);
-                    Task t = ((UnknownElement) ue).getTask();
-                    assertNotNull(t);
-                    assertEquals("org.apache.tools.ant.taskdefs.Echo",
-                                 t.getClass().getName());
-                }
-            });
+            public void buildStarted(BuildEvent event) {
+            }
+
+            public void buildFinished(BuildEvent event) {
+            }
+
+            public void targetStarted(BuildEvent event) {
+            }
+
+            public void targetFinished(BuildEvent event) {
+            }
+
+            public void taskStarted(BuildEvent event) {
+                assertTaskProperties(event.getTask());
+            }
+
+            public void taskFinished(BuildEvent event) {
+                assertTaskProperties(event.getTask());
+            }
+
+            public void messageLogged(BuildEvent event) {
+            }
+
+            private void assertTaskProperties(Task ue) {
+                assertNotNull(ue);
+                assertThat(ue, instanceOf(UnknownElement.class));
+                Task t = ((UnknownElement) ue).getTask();
+                assertNotNull(t);
+                assertEquals("org.apache.tools.ant.taskdefs.Echo",
+                        t.getClass().getName());
+            }
+        });
         buildRule.executeTarget("echo");
     }
 
     public static class Child extends Task {
         Parent parent;
+
         public void injectParent(Parent parent) {
             this.parent = parent;
         }
+
         public void execute() {
             parent.fromChild();
         }
     }
 
     public static class Parent extends Task implements TaskContainer {
-        List<Task> children = new ArrayList<Task>();
+        List<Task> children = new ArrayList<>();
+
         public void addTask(Task t) {
             children.add(t);
         }
diff --git a/src/tests/junit/org/apache/tools/ant/XmlLoggerTest.java b/src/tests/junit/org/apache/tools/ant/XmlLoggerTest.java
index cfeb16b..46eb830 100644
--- a/src/tests/junit/org/apache/tools/ant/XmlLoggerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/XmlLoggerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,10 +23,13 @@
 
 public class XmlLoggerTest {
 
+    /**
+     * "NPE in XmlLogger.buildFinished"
+     *
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=56850">bug 56850</a>
+     */
     @Test
-    // see https://issues.apache.org/bugzilla/show_bug.cgi?id=56850
-    // "NPE in XmlLogger.buildFinished"
-    public void test() throws Throwable {
+    public void test() {
         final XmlLogger logger = new XmlLogger();
         final Cvs task = new Cvs();
         final BuildEvent event = new BuildEvent(task);
diff --git a/src/tests/junit/org/apache/tools/ant/filters/ConcatFilterTest.java b/src/tests/junit/org/apache/tools/ant/filters/ConcatFilterTest.java
index 06cd2f8..ef6a8dd 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/ConcatFilterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/ConcatFilterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,48 +23,44 @@
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.FileUtilities;
-import org.apache.tools.ant.util.StringUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
 
 /**
  * JUnit Testcases for ConcatReader
  */
 public class ConcatFilterTest {
 
-    private static final String lSep = StringUtils.LINE_SEP;
+    private static final String FILE_PREPEND_WITH = String.format("this-should-be-the-first-line%n"
+        + "Line  1%n"
+        + "Line  2%n"
+        + "Line  3%n"
+        + "Line  4%n");
 
-    private static final String FILE_PREPEND_WITH =
-          "this-should-be-the-first-line" + lSep
-        + "Line  1" + lSep
-        + "Line  2" + lSep
-        + "Line  3" + lSep
-        + "Line  4" + lSep;
+    private static final String FILE_PREPEND = String.format("Line  1%n"
+        + "Line  2%n"
+        + "Line  3%n"
+        + "Line  4%n"
+        + "Line  5%n");
 
-    private static final String FILE_PREPEND =
-          "Line  1" + lSep
-        + "Line  2" + lSep
-        + "Line  3" + lSep
-        + "Line  4" + lSep
-        + "Line  5" + lSep;
-
-    private static final String FILE_APPEND_WITH =
-          "Line 57" + lSep
-        + "Line 58" + lSep
-        + "Line 59" + lSep
-        + "Line 60" + lSep
-        + "this-should-be-the-last-line" + lSep;
+    private static final String FILE_APPEND_WITH = String.format("Line 57%n"
+        + "Line 58%n"
+        + "Line 59%n"
+        + "Line 60%n"
+        + "this-should-be-the-last-line%n");
 
     private static final String FILE_APPEND =
-          "Line 56" + lSep
-        + "Line 57" + lSep
-        + "Line 58" + lSep
-        + "Line 59" + lSep
-        + "Line 60" + lSep;
+          String.format("Line 56%n"
+        + "Line 57%n"
+        + "Line 58%n"
+        + "Line 59%n"
+        + "Line 60%n");
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
@@ -79,8 +75,8 @@
         buildRule.executeTarget("testFilterReaderNoArgs");
         File expected = new File(buildRule.getProject().getProperty("output"), "concatfilter.test");
         File result = new File(buildRule.getProject().getProperty("output"),  "concat.FilterReaderNoArgs.test");
-        assertEquals("testFilterReaderNoArgs: Result not like expected", FileUtilities.getFileContents(expected),
-                FileUtilities.getFileContents(result));
+        assertEquals("testFilterReaderNoArgs: Result not like expected",
+                FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
     }
 
     @Test
@@ -131,9 +127,8 @@
         buildRule.executeTarget(target);
         String resultContent = FileUtilities.getFileContents(
                 new File(buildRule.getProject().getProperty("output") + "/concat." + target.substring(4) + ".test"));
-        assertTrue("First 5 lines differs.", resultContent.startsWith(expectedStart));
-        assertTrue("Last 5 lines differs.", resultContent.endsWith(expectedEnd));
+        assertThat("First 5 lines differs.", resultContent, startsWith(expectedStart));
+        assertThat("Last 5 lines differs.", resultContent, endsWith(expectedEnd));
     }
 
-
 }
diff --git a/src/tests/junit/org/apache/tools/ant/filters/DynamicFilterTest.java b/src/tests/junit/org/apache/tools/ant/filters/DynamicFilterTest.java
index 85df0ce..8f3331a 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/DynamicFilterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/DynamicFilterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,8 +19,8 @@
 package org.apache.tools.ant.filters;
 
 import java.io.File;
-import java.io.Reader;
 import java.io.IOException;
+import java.io.Reader;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.FileUtilities;
@@ -28,7 +28,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
 
 public class DynamicFilterTest {
 
@@ -46,7 +47,7 @@
         buildRule.executeTarget("dynamicfilter");
         String content = FileUtilities.getFileContents(
                 new File(buildRule.getProject().getProperty("output") + "/dynamicfilter"));
-        assertContains("hellO wOrld", content);
+        assertThat(content, containsString("hellO wOrld"));
     }
 
     public static class CustomFilter implements ChainableReader {
diff --git a/src/tests/junit/org/apache/tools/ant/filters/EscapeUnicodeTest.java b/src/tests/junit/org/apache/tools/ant/filters/EscapeUnicodeTest.java
index 7c5e304..93fb4ff 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/EscapeUnicodeTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/EscapeUnicodeTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/filters/HeadTailTest.java b/src/tests/junit/org/apache/tools/ant/filters/HeadTailTest.java
index 21d25a1..5f26cf9 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/HeadTailTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/HeadTailTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,12 +20,16 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.FileUtilities;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import static org.junit.Assert.assertEquals;
 
@@ -34,8 +38,31 @@
 /* I wrote the testcases in one java file because I want also to test the
  * combined behaviour (see end of the class).
 */
+@RunWith(Parameterized.class)
 public class HeadTailTest {
 
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object [][] {
+                {"head", "head"},
+                {"headLines", "headLines"},
+                {"headSkip", "headSkip"},
+                {"headLinesSkip", "headLinesSkip"},
+                {"filterReaderHeadLinesSkip", "headLinesSkip"},
+                {"tail", "tail"},
+                {"tailSkip", "tailSkip"},
+                {"tailLines", "tailLines"},
+                {"tailLinesSkip", "tailLinesSkip"},
+                {"filterReaderTailLinesSkip", "tailLinesSkip"},
+                {"headTail", "headtail"}});
+    }
+
+    @Parameterized.Parameter
+    public String result;
+
+    @Parameterized.Parameter(1)
+    public String input;
+
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
@@ -45,93 +72,14 @@
     }
 
     @Test
-    public void testHead() throws IOException {
-        buildRule.executeTarget("testHead");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.head.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.head.test");
-        assertEquals("testHead: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
+    public void test() throws  IOException {
+        buildRule.executeTarget("test" + result.substring(0, 1).toUpperCase()
+                + result.substring(1));
+        File expected = buildRule.getProject().resolveFile("expected/head-tail."
+                + input + ".test");
+        File actual = new File(buildRule.getProject().getProperty("output")
+                + "/head-tail." +  result + ".test");
+        assertEquals(result + ": Result not like expected",
+                FileUtilities.getFileContents(expected), FileUtilities.getFileContents(actual));
     }
-
-    @Test
-    public void testHeadLines() throws IOException {
-        buildRule.executeTarget("testHeadLines");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.headLines.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.headLines.test");
-        assertEquals("testHeadLines: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testHeadSkip() throws IOException {
-        buildRule.executeTarget("testHeadSkip");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.headSkip.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.headSkip.test");
-        assertEquals("testHeadSkip: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testHeadLinesSkip() throws IOException {
-        buildRule.executeTarget("testHeadLinesSkip");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.headLinesSkip.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.headLinesSkip.test");
-        assertEquals("testHeadLinesSkip: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testFilterReaderHeadLinesSkip() throws IOException {
-        buildRule.executeTarget("testFilterReaderHeadLinesSkip");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.headLinesSkip.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.filterReaderHeadLinesSkip.test");
-        assertEquals("testFilterReaderHeadLinesSkip: Result not like expected",
-                FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testTail() throws IOException {
-        buildRule.executeTarget("testTail");
-        File expected =buildRule.getProject().resolveFile("expected/head-tail.tail.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.tail.test");
-        assertEquals("testTail: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testTailLines() throws IOException {
-        buildRule.executeTarget("testTailLines");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.tailLines.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.tailLines.test");
-        assertEquals("testTailLines: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testTailSkip() throws IOException {
-        buildRule.executeTarget("testTailSkip");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.tailSkip.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.tailSkip.test");
-        assertEquals("testTailSkip: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testTailLinesSkip() throws IOException {
-        buildRule.executeTarget("testTailLinesSkip");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.tailLinesSkip.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.tailLinesSkip.test");
-        assertEquals("testTailLinesSkip: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testFilterReaderTailLinesSkip() throws IOException {
-        buildRule.executeTarget("testFilterReaderTailLinesSkip");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.tailLinesSkip.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.filterReaderTailLinesSkip.test");
-        assertEquals("testFilterReaderTailLinesSkip: Result not like expected",
-                FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testHeadTail() throws IOException {
-        buildRule.executeTarget("testHeadTail");
-        File expected = buildRule.getProject().resolveFile("expected/head-tail.headtail.test");
-        File result = new File(buildRule.getProject().getProperty("output") + "/head-tail.headtail.test");
-        assertEquals("testHeadTail: Result not like expected", FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
 }
diff --git a/src/tests/junit/org/apache/tools/ant/filters/LineContainsTest.java b/src/tests/junit/org/apache/tools/ant/filters/LineContainsTest.java
index d10d951..0b5554d 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/LineContainsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/LineContainsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -49,8 +49,34 @@
     }
 
     @Test
-    public void testNegateLineContains() throws IOException {
+    public void testNegateLineContains() {
         buildRule.executeTarget("testNegateLineContains");
     }
 
+    /**
+     * Tests that the {@code matchAny} attribute of {@link LineContains} works as expected
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testLineContainsMatchAny() throws IOException {
+        buildRule.executeTarget("testMatchAny");
+        File expected = buildRule.getProject().resolveFile("expected/linecontains-matchany.test");
+        File result = new File(buildRule.getProject().getProperty("output"), "linecontains.test");
+        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
+    }
+
+    /**
+     * Tests that the {@code matchAny} attribute when used with the {@code negate} attribute
+     * of {@link LineContains} works as expected
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testLineContainsMatchAnyNegate() throws IOException {
+        buildRule.executeTarget("testMatchAnyNegate");
+        File expected = buildRule.getProject().resolveFile("expected/linecontains-matchany-negate.test");
+        File result = new File(buildRule.getProject().getProperty("output"), "linecontains.test");
+        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/filters/NoNewLineTest.java b/src/tests/junit/org/apache/tools/ant/filters/NoNewLineTest.java
index c12a1d3..59b8959 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/NoNewLineTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/NoNewLineTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,6 @@
 
 package org.apache.tools.ant.filters;
 
-import java.io.IOException;
-
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
@@ -41,7 +39,7 @@
 
 
     @Test
-    public void testNoAddNewLine() throws IOException {
+    public void testNoAddNewLine() {
         buildRule.executeTarget("testNoAddNewLine");
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/filters/ReplaceTokensTest.java b/src/tests/junit/org/apache/tools/ant/filters/ReplaceTokensTest.java
index 4db8d7a..7de37da 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/ReplaceTokensTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/ReplaceTokensTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,17 +20,38 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.FileUtilities;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import static org.junit.Assert.assertEquals;
 
+@RunWith(Parameterized.class)
 public class ReplaceTokensTest {
 
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object [][] {
+                {"replaceTokens", "replacetokens"},
+                {"replaceTokensPropertyFile", "replacetokens"},
+                {"replaceTokensDoubleEncoded", "replacetokens.double"},
+                {"replaceTokensDoubleEncodedToSimple", "replacetokens"},
+                {"replaceTokensMustacheStyle", "replacetokens"}});
+    }
+
+    @Parameterized.Parameter
+    public String result;
+
+    @Parameterized.Parameter(1)
+    public String input;
+
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
@@ -40,42 +61,14 @@
     }
 
     @Test
-    public void testReplaceTokens() throws IOException {
-        buildRule.executeTarget("testReplaceTokens");
-        File expected = buildRule.getProject().resolveFile("expected/replacetokens.test");
-        File result = new File(buildRule.getProject().getProperty("output"), "replacetokens.test");
-        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testReplaceTokensPropertyFile() throws IOException {
-        buildRule.executeTarget("testReplaceTokensPropertyFile");
-        File expected = buildRule.getProject().resolveFile("expected/replacetokens.test");
-        File result = new File(buildRule.getProject().getProperty("output"), "replacetokensPropertyFile.test");
-        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testReplaceTokensDoubleEncoded() throws IOException {
-        buildRule.executeTarget("testReplaceTokensDoubleEncoded");
-        File expected = buildRule.getProject().resolveFile("expected/replacetokens.double.test");
-        File result = new File(buildRule.getProject().getProperty("output"), "replacetokens.double.test");
-        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testReplaceTokensDoubleEncodedToSimple() throws IOException {
-        buildRule.executeTarget("testReplaceTokensDoubleEncodedToSimple");
-        File expected = buildRule.getProject().resolveFile("expected/replacetokens.test");
-        File result = new File(buildRule.getProject().getProperty("output"), "replacetokens.double.test");
-        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
-    }
-
-    @Test
-    public void testReplaceTokensMustacheStyle() throws IOException {
-        buildRule.executeTarget("testReplaceTokensMustacheStyle");
-        File expected = buildRule.getProject().resolveFile("expected/replacetokens.test");
-        File result = new File(buildRule.getProject().getProperty("output"), "replacetokens.mustache.test");
-        assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result));
+    public void test() throws  IOException {
+        buildRule.executeTarget("test" + result.substring(0, 1).toUpperCase()
+                + result.substring(1));
+        File expected = buildRule.getProject().resolveFile("expected/"
+                + input + ".test");
+        File actual = new File(buildRule.getProject().getProperty("output")
+                + "/" +  result + ".test");
+        assertEquals(result + ": Result not like expected",
+                FileUtilities.getFileContents(expected), FileUtilities.getFileContents(actual));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/filters/StripJavaCommentsTest.java b/src/tests/junit/org/apache/tools/ant/filters/StripJavaCommentsTest.java
index 7114d49..ba8cb73 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/StripJavaCommentsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/StripJavaCommentsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java b/src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java
index b07abe0..5ed47e8 100644
--- a/src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,18 +18,21 @@
 
 package org.apache.tools.ant.filters;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.apache.tools.ant.AntAssert.assertNotContains;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.tools.ant.util.FileUtils.readFully;
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeThat;
 
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.Reader;
 
 import org.apache.tools.ant.BuildFileRule;
-import org.apache.tools.ant.util.FileUtils;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -41,8 +44,6 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/filters/tokenfilter.xml");
@@ -51,99 +52,101 @@
 
     /** make sure tokenfilter exists */
     @Test
-    public void testTokenfilter() throws IOException {
+    public void testTokenfilter() {
         buildRule.executeTarget("tokenfilter");
     }
 
     @Test
-    public void testTrimignore() throws IOException {
+    public void testTrimignore() {
         buildRule.executeTarget("trimignore");
-        assertContains("Hello-World", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Hello-World"));
     }
 
     @Test
-    public void testStringTokenizer() throws IOException {
+    public void testStringTokenizer() {
         buildRule.executeTarget("stringtokenizer");
-        assertContains("#This#is#a#number#of#words#", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("#This#is#a#number#of#words#"));
     }
 
     @Test
     public void testUnixLineOutput() throws IOException {
         buildRule.executeTarget("unixlineoutput");
-        assertContains("\nThis\nis\na\nnumber\nof\nwords\n",
-                getFileString(buildRule.getProject().getProperty("output") + "/unixlineoutput"));
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/unixlineoutput"),
+                containsString("\nThis\nis\na\nnumber\nof\nwords\n"));
     }
 
     @Test
     public void testDosLineOutput() throws IOException {
-
         buildRule.executeTarget("doslineoutput");
-        assertContains("\r\nThis\r\nis\r\na\r\nnumber\r\nof\r\nwords\r\n",
-                getFileString(buildRule.getProject().getProperty("output") + "/doslineoutput"));
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/doslineoutput"),
+                containsString("\r\nThis\r\nis\r\na\r\nnumber\r\nof\r\nwords\r\n"));
     }
 
     @Test
     public void testFileTokenizer() throws IOException {
         buildRule.executeTarget("filetokenizer");
-        String contents = getFileString(buildRule.getProject().getProperty("output") + "/filetokenizer");
-        assertContains("   of words", contents);
-        assertNotContains(" This is", contents);
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/filetokenizer"),
+                both(containsString("   of words")).and(not(containsString(" This is"))));
     }
 
     @Test
     public void testReplaceString() throws IOException {
         buildRule.executeTarget("replacestring");
-        assertContains("this is the moon",
-                getFileString(buildRule.getProject().getProperty("output") + "/replacestring"));
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/replacestring"),
+                containsString("this is the moon"));
     }
 
     @Test
-    public void testReplaceStrings() throws IOException {
+    public void testReplaceStrings() {
         buildRule.executeTarget("replacestrings");
-        assertContains("bar bar bar", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("bar bar bar"));
     }
 
     @Test
     public void testContainsString() throws IOException {
         buildRule.executeTarget("containsstring");
-        String contents = getFileString(buildRule.getProject().getProperty("output") + "/containsstring");
-        assertContains("this is a line contains foo", contents);
-        assertNotContains("this line does not", contents);
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/containsstring"),
+                both(containsString("this is a line contains foo"))
+                        .and(not(containsString("this line does not"))));
     }
 
     @Test
     public void testReplaceRegex() throws IOException {
 
         buildRule.executeTarget("hasregex");
-        Assume.assumeTrue("Regex not present",
-                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp").contains("bye world"));
+        assumeThat("Regex not present",
+                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp"),
+                containsString("bye world"));
 
         buildRule.executeTarget("replaceregex");
         String contents = getFileString(buildRule.getProject().getProperty("output") + "/replaceregex");
-        assertContains("world world world world", contents);
-        assertContains("dog Cat dog", contents);
-        assertContains("moon Sun Sun", contents);
-        assertContains("found WhiteSpace", contents);
-        assertContains("Found digits [1234]", contents);
-        assertNotContains("This is a line with digits", contents);
+        assertThat(contents, containsString("world world world world"));
+        assertThat(contents, containsString("dog Cat dog"));
+        assertThat(contents, containsString("moon Sun Sun"));
+        assertThat(contents, containsString("found WhiteSpace"));
+        assertThat(contents, containsString("Found digits [1234]"));
+        assertThat(contents, not(containsString("This is a line with digits")));
     }
 
     @Test
     public void testFilterReplaceRegex() throws IOException {
         buildRule.executeTarget("hasregex");
-        Assume.assumeTrue("Regex not present",
-                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp").contains("bye world"));
+        assumeThat("Regex not present",
+                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp"),
+                containsString("bye world"));
 
         buildRule.executeTarget("filterreplaceregex");
-        String contents = getFileString(buildRule.getProject().getProperty("output") + "/filterreplaceregex");
-        assertContains("world world world world", contents);
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/filterreplaceregex"),
+                containsString("world world world world"));
 
     }
 
     @Test
     public void testHandleDollerMatch() throws IOException {
         buildRule.executeTarget("hasregex");
-        Assume.assumeTrue("Regex not present", getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp").contains("bye world"));
+        assumeThat("Regex not present",
+                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp"),
+                containsString("bye world"));
 
         buildRule.executeTarget("dollermatch");
     }
@@ -152,99 +155,110 @@
     public void testTrimFile() throws IOException {
         buildRule.executeTarget("trimfile");
         String contents = getFileString(buildRule.getProject().getProperty("output") + "/trimfile");
-        assertTrue("no ws at start", contents.startsWith("This is th"));
-        assertTrue("no ws at end", contents.endsWith("second line."));
-        assertContains("  This is the second", contents);
+        assertThat("no ws at start", contents, startsWith("This is th"));
+        assertThat("no ws at end", contents, endsWith("second line."));
+        assertThat(contents, containsString("  This is the second"));
     }
 
     @Test
     public void testTrimFileByLine() throws IOException {
         buildRule.executeTarget("trimfilebyline");
         String contents = getFileString(buildRule.getProject().getProperty("output") + "/trimfilebyline");
-        assertFalse("no ws at start", contents.startsWith("This is th"));
-        assertFalse("no ws at end", contents.endsWith("second line."));
-        assertNotContains("  This is the second", contents);
-        assertContains("file.\nThis is the second", contents);
+        assertThat("no ws at start", contents, not(startsWith("This is th")));
+        assertThat("no ws at end", contents, not(endsWith("second line.")));
+        assertThat(contents, not(containsString("  This is the second")));
+        assertThat(contents, containsString("file.\nThis is the second"));
     }
 
     @Test
     public void testFilterReplaceString() throws IOException {
         buildRule.executeTarget("filterreplacestring");
-        String contents = getFileString(buildRule.getProject().getProperty("output") + "/filterreplacestring");
-        assertContains("This is the moon", contents);
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/filterreplacestring"),
+                containsString("This is the moon"));
     }
 
     @Test
-    public void testFilterReplaceStrings() throws IOException {
+    public void testFilterReplaceStrings() {
         buildRule.executeTarget("filterreplacestrings");
-        assertContains("bar bar bar", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("bar bar bar"));
     }
 
     @Test
     public void testContainsRegex() throws IOException {
         buildRule.executeTarget("hasregex");
-        Assume.assumeTrue("Regex not present", getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp").contains("bye world"));
+        assumeThat("Regex not present",
+                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp"),
+                containsString("bye world"));
 
-        //expectFileContains(buildRule.getProject().getProperty("output") + "/replaceregexp", "bye world");
+        // assertThat(buildRule.getProject().getProperty("output") + "/replaceregexp",
+        // containsString("bye world"));
 
         buildRule.executeTarget("containsregex");
         String contents = getFileString(buildRule.getProject().getProperty("output") + "/containsregex");
-        assertContains("hello world", contents);
-        assertNotContains("this is the moon", contents);
-        assertContains("World here", contents);
+        assertThat(contents, containsString("hello world"));
+        assertThat(contents, not(containsString("this is the moon")));
+        assertThat(contents, containsString("World here"));
     }
 
     @Test
     public void testFilterContainsRegex() throws IOException {
         buildRule.executeTarget("hasregex");
-        Assume.assumeTrue("Regex not present", getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp").contains("bye world"));
+        assumeThat("Regex not present",
+                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp"),
+                containsString("bye world"));
 
         buildRule.executeTarget("filtercontainsregex");
         String contents = getFileString(buildRule.getProject().getProperty("output") + "/filtercontainsregex");
-        assertContains("hello world", contents);
-        assertNotContains("this is the moon", contents);
-        assertContains("World here", contents);
+        assertThat(contents, containsString("hello world"));
+        assertThat(contents, not(containsString("this is the moon")));
+        assertThat(contents, containsString("World here"));
     }
 
     @Test
     public void testContainsRegex2() throws IOException {
         buildRule.executeTarget("hasregex");
-        Assume.assumeTrue("Regex not present", getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp").contains("bye world"));
+        assumeThat("Regex not present",
+                getFileString(buildRule.getProject().getProperty("output") + "/replaceregexp"),
+                containsString("bye world"));
 
         buildRule.executeTarget("containsregex2");
-        String contents = getFileString(buildRule.getProject().getProperty("output") + "/containsregex2");
-        assertContains("void register_bits();", contents);
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/containsregex2"),
+                containsString("void register_bits();"));
     }
 
     @Test
     public void testDeleteCharacters() throws IOException {
         buildRule.executeTarget("deletecharacters");
         String contents = getFileString(buildRule.getProject().getProperty("output") + "/deletechars");
-        assertNotContains("#", contents);
-        assertNotContains("*", contents);
-        assertContains("This is some ", contents);
+        assertThat(contents, not(containsString("#")));
+        assertThat(contents, not(containsString("*")));
+        assertThat(contents, containsString("This is some "));
     }
 
     @Test
     public void testScriptFilter() throws IOException {
-        Assume.assumeTrue("Project does not have 'testScriptFilter' target",
-                buildRule.getProject().getTargets().contains("testScriptFilter"));
+        assumeThat("Project does not have 'testScriptFilter' target",
+                buildRule.getProject().getTargets(), hasKey("testScriptFilter"));
         buildRule.executeTarget("scriptfilter");
-        assertContains("HELLO WORLD", getFileString(buildRule.getProject().getProperty("output") + "/scriptfilter"));
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/scriptfilter"),
+                containsString("HELLO WORLD"));
 
     }
 
     @Test
     public void testScriptFilter2() throws IOException {
-        Assume.assumeTrue("Project does not have 'testScriptFilter' target", buildRule.getProject().getTargets().contains("testScriptFilter"));
+        assumeThat("Project does not have 'testScriptFilter' target",
+                buildRule.getProject().getTargets(), hasKey("testScriptFilter"));
         buildRule.executeTarget("scriptfilter2");
-        assertContains("HELLO MOON", getFileString(buildRule.getProject().getProperty("output") + "/scriptfilter2"));
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/scriptfilter2"),
+                containsString("HELLO MOON"));
     }
 
     @Test
     public void testCustomTokenFilter() throws IOException {
         buildRule.executeTarget("customtokenfilter");
-        assertContains("Hello World", getFileString(buildRule.getProject().getProperty("output") + "/custom"));
+        assertThat(getFileString(buildRule.getProject().getProperty("output") + "/custom"),
+                containsString("Hello World"));
     }
 
     // ------------------------------------------------------
@@ -252,23 +266,15 @@
     // -----------------------------------------------------
 
     private String getFileString(String filename) throws IOException {
-        Reader r = null;
-        try {
-            r = new FileReader(FILE_UTILS.resolveFile(buildRule.getProject().getBaseDir(),filename));
-            return  FileUtils.readFully(r);
-        }
-        finally {
-            FileUtils.close(r);
+        try (Reader r = new FileReader(buildRule.getProject().resolveFile(filename))) {
+            return readFully(r);
         }
     }
 
 
     public static class Capitalize implements TokenFilter.Filter {
         public String filter(String token) {
-            if (token.length() == 0) {
-                return token;
-            }
-            return token.substring(0, 1).toUpperCase() + token.substring(1);
+            return token.isEmpty() ? token : token.substring(0, 1).toUpperCase() + token.substring(1);
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java b/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java
index b8dffae..488a3a1 100644
--- a/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/launch/LocatorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,11 +22,12 @@
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.junit.Before;
 import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static junit.framework.Assert.assertEquals;
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
 
 /** Test the locator in the ant-launch JAR */
 public class LocatorTest {
@@ -36,9 +37,11 @@
     private static final String SHARED_JAR_URI = "jar:file:" + LAUNCHER_JAR
             + "!/org/apache/tools/ant/launch/Launcher.class";
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         windows = Os.isFamily(Os.FAMILY_DOS);
         unix = Os.isFamily(Os.FAMILY_UNIX);
     }
@@ -65,7 +68,7 @@
      * @param enabled is the test enabled?
      */
     private void assertResolved(String uri, String expectedResult, String result, boolean enabled) {
-        if (enabled && expectedResult != null && expectedResult.length() > 0) {
+        if (enabled && expectedResult != null && !expectedResult.isEmpty()) {
             assertEquals("Expected " + uri + " to resolve to \n" + expectedResult + "\n but got\n"
                     + result + "\n", expectedResult, result);
         }
@@ -86,9 +89,9 @@
 
     /**
      * this isn't really a valid URI, except maybe in IE
-     * @throws Exception if something goes wrong
      */
-    public void testNetworkURI() throws Exception {
+    @Test
+    public void testNetworkURI() {
         resolveTo("file:\\\\PC03\\jclasses\\lib\\ant-1.7.0.jar", ""
                 + "\\\\PC03\\jclasses\\lib\\ant-1.7.0.jar",
                 "\\\\PC03\\jclasses\\lib\\ant-1.7.0.jar");
@@ -96,26 +99,26 @@
 
     @Ignore("We don't appear to generate paths like this in the launcher")
     @Test
-    public void testTripleForwardSlashNetworkURI() throws Exception {
+    public void testTripleForwardSlashNetworkURI() {
         resolveTo("file:///PC03/jclasses/lib/ant-1.7.0.jar",
                 "///PC03/jclasses/lib/ant-1.7.0.jar",
                 "\\\\PC03\\jclasses\\lib\\ant-1.7.0.jar");
     }
 
     @Test
-    public void testUnixNetworkPath() throws Exception {
+    public void testUnixNetworkPath() {
         resolveTo("file://cluster/home/ant/lib",
                 "//cluster/home/ant/lib",
                 "\\\\cluster\\home\\ant\\lib");
     }
 
     @Test
-    public void testUnixPath() throws Exception {
+    public void testUnixPath() {
         resolveTo("file:/home/ant/lib", "/home/ant/lib", null);
     }
 
     @Test
-    public void testSpacedURI() throws Exception {
+    public void testSpacedURI() {
         resolveTo("file:C:\\Program Files\\Ant\\lib",
                 "C:\\Program Files\\Ant\\lib",
                 "C:\\Program Files\\Ant\\lib");
@@ -123,10 +126,9 @@
 
     /**
      * Bug 42275; Ant failing to run off a remote share
-     * @throws Throwable if desired
      */
     @Test
-    public void testAntOnRemoteShare() throws Throwable {
+    public void testAntOnRemoteShare() {
         String resolved = Locator.fromJarURI(SHARED_JAR_URI);
         assertResolved(SHARED_JAR_URI, LAUNCHER_JAR, resolved, unix);
         assertResolved(SHARED_JAR_URI, LAUNCHER_JAR.replace('/', '\\'),
@@ -135,30 +137,22 @@
 
     /**
      * Bug 42275; Ant failing to run off a remote share
-     *
-     * @throws Throwable if desired
      */
     @Test
-    public void testFileFromRemoteShare() throws Throwable {
+    public void testFileFromRemoteShare() {
+        assumeTrue("not Windows", windows);
         String resolved = Locator.fromJarURI(SHARED_JAR_URI);
         File f = new File(resolved);
         String path = f.getAbsolutePath();
-        if (windows) {
-            assertEquals(0, path.indexOf("\\\\"));
-        }
+        assertEquals(0, path.indexOf("\\\\"));
     }
 
     @Test
-    public void testHttpURI() throws Exception {
-        String url = "http://ant.apache.org";
-        try {
-            Locator.fromURI(url);
-            fail("Exception should have been thrown");
-        } catch (IllegalArgumentException e) {
-            String message = e.getMessage();
-            assertContains(Locator.ERROR_NOT_FILE_URI, message);
-            assertContains(url, message);
-        }
+    public void testHttpsURI() {
+        String url = "https://ant.apache.org";
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage(Locator.ERROR_NOT_FILE_URI + url);
+        Locator.fromURI(url);
     }
 
     @Test
@@ -174,7 +168,7 @@
     }
 
     @Test
-    public void testOddLowAsciiURI() throws Exception {
+    public void testOddLowAsciiURI() {
         assertResolves("hash# and percent%");
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/AbstractCvsTaskTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/AbstractCvsTaskTest.java
index 227987f..bd7c689 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/AbstractCvsTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/AbstractCvsTaskTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,7 +17,6 @@
  */
 package org.apache.tools.ant.taskdefs;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.After;
 import org.junit.Before;
@@ -26,6 +25,9 @@
 
 import java.io.File;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -54,18 +56,18 @@
     @Test
     public void testPackageAttribute() {
         File f = new File(buildRule.getProject().getProperty("output") + "/src/Makefile");
-        assertTrue("starting empty", !f.exists());
+        assertFalse("starting empty", f.exists());
         buildRule.executeTarget("package-attribute");
-        AntAssert.assertContains("U src/Makefile", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("U src/Makefile"));
         assertTrue("now it is there", f.exists());
     }
 
     @Test
     public void testTagAttribute() {
         File f = new File(buildRule.getProject().getProperty("output") + "/src/Makefile");
-        assertTrue("starting empty", !f.exists());
+        assertFalse("starting empty", f.exists());
         buildRule.executeTarget("tag-attribute");
-        AntAssert.assertContains("OPENBSD_5_3", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("OPENBSD_5_3"));
         assertTrue("now it is there", f.exists());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/AntLikeTasksAtTopLevelTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/AntLikeTasksAtTopLevelTest.java
index cb03609..e1ddbab 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/AntLikeTasksAtTopLevelTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/AntLikeTasksAtTopLevelTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,9 +22,7 @@
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * @since Ant 1.6
@@ -34,37 +32,28 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void testAnt() {
-        try {
-            buildRule.configureProject("src/etc/testcases/taskdefs/toplevelant.xml");
-            fail("no exception thrown");
-        } catch (BuildException e) {
-            assertEquals("ant task at the top level must not invoke its own"
-                         + " build file.", e.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("ant task at the top level must not invoke its own build file.");
+        buildRule.configureProject("src/etc/testcases/taskdefs/toplevelant.xml");
     }
 
     @Test
     public void testSubant() {
-        try {
-            buildRule.configureProject("src/etc/testcases/taskdefs/toplevelsubant.xml");
-            fail("no exception thrown");
-        } catch (BuildException e) {
-            assertEquals("subant task at the top level must not invoke its own"
-                         + " build file.", e.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("subant task at the top level must not invoke its own build file.");
+        buildRule.configureProject("src/etc/testcases/taskdefs/toplevelsubant.xml");
     }
 
     @Test
     public void testAntcall() {
-        try {
-            buildRule.configureProject("src/etc/testcases/taskdefs/toplevelantcall.xml");
-            fail("no exception thrown");
-        } catch (BuildException e) {
-            assertEquals("antcall must not be used at the top level.",
-                         e.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("antcall must not be used at the top level.");
+        buildRule.configureProject("src/etc/testcases/taskdefs/toplevelantcall.xml");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/AntStructureTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/AntStructureTest.java
index da51b5d..486b49e 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/AntStructureTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/AntStructureTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,10 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -31,7 +29,11 @@
 import java.io.PrintWriter;
 import java.util.Hashtable;
 
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 /**
  */
@@ -50,14 +52,12 @@
         buildRule.executeTarget("tearDown");
     }
 
-    @Test
+    /**
+     * Expected failure due lacking a required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test1");
     }
 
     @Test
@@ -68,7 +68,7 @@
         // the test has likely been loaded via a different classloader
         // than this class.  Therefore we make the printer assert its
         // state and only check for the tail invocation.
-        AntAssert.assertContains(MyPrinter.TAIL_CALLED, buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString(MyPrinter.TAIL_CALLED));
     }
 
     public static class MyPrinter implements AntStructure.StructurePrinter {
@@ -79,34 +79,38 @@
         private int elementCalled = 0;
         private Project p;
 
-        public void printHead(PrintWriter out, Project p, Hashtable tasks,
-                              Hashtable types) {
-            Assert.assertTrue(!headCalled);
-            Assert.assertTrue(!targetCalled);
-            Assert.assertTrue(!tailCalled);
-            Assert.assertEquals(0, elementCalled);
+        public void printHead(PrintWriter out, Project p,
+                              Hashtable<String, Class<?>> tasks,
+                              Hashtable<String, Class<?>> types) {
+            assertFalse(headCalled);
+            assertFalse(targetCalled);
+            assertFalse(tailCalled);
+            assertEquals(0, elementCalled);
             headCalled = true;
         }
+
         public void printTargetDecl(PrintWriter out) {
-            Assert.assertTrue(headCalled);
-            Assert.assertTrue(!targetCalled);
-            Assert.assertTrue(!tailCalled);
-            Assert.assertEquals(0, elementCalled);
+            assertTrue(headCalled);
+            assertFalse(targetCalled);
+            assertFalse(tailCalled);
+            assertEquals(0, elementCalled);
             targetCalled = true;
         }
+
         public void printElementDecl(PrintWriter out, Project p, String name,
-                                     Class element) {
-            Assert.assertTrue(headCalled);
-            Assert.assertTrue(targetCalled);
-            Assert.assertTrue(!tailCalled);
+                                     Class<?> element) {
+            assertTrue(headCalled);
+            assertTrue(targetCalled);
+            assertFalse(tailCalled);
             elementCalled++;
             this.p = p;
         }
+
         public void printTail(PrintWriter out) {
-            Assert.assertTrue(headCalled);
-            Assert.assertTrue(targetCalled);
-            Assert.assertTrue(!tailCalled);
-            Assert.assertTrue(elementCalled > 0);
+            assertTrue(headCalled);
+            assertTrue(targetCalled);
+            assertFalse(tailCalled);
+            assertTrue(elementCalled > 0);
             tailCalled = true;
             p.log(TAIL_CALLED);
         }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/AntTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/AntTest.java
index aee91fe..577571f 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/AntTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/AntTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,9 @@
 package org.apache.tools.ant.taskdefs;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.List;
 
-import junit.framework.AssertionFailedError;
-
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
@@ -35,12 +34,14 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  */
@@ -59,56 +60,49 @@
         buildRule.executeTarget("cleanup");
     }
 
-    @Test
+    /**
+     * Fail due to recursive call
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("recursive call");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert exception message
     }
 
-    // target must be specified
-    @Test
+    /**
+     * Fail due to unspecified target
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("required argument not specified");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert exception message
     }
 
-    // Should fail since a recursion will occur...
-    @Test
+    /**
+     * Fail due to recursive call
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("recursive call");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert exception message
     }
 
-    @Test
+    /**
+     * Fail due to empty target name
+     */
+    @Test(expected = BuildException.class)
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("target attribute must not be empty");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test4");
+        // TODO assert exception message
     }
 
-    @Test
+    /**
+     * Fail due to nonexistent target
+     */
+    @Test(expected = BuildException.class)
     public void test4b() {
-        try {
-            buildRule.executeTarget("test4b");
-            fail("target doesn't exist");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test4b");
+        // TODO assert exception message
     }
 
     @Test
@@ -163,7 +157,7 @@
         BasedirChecker bc = new BasedirChecker(dirs);
         buildRule.getProject().addBuildListener(bc);
         buildRule.executeTarget(target);
-        AssertionFailedError ae = bc.getError();
+        AssertionError ae = bc.getError();
         if (ae != null) {
             throw ae;
         }
@@ -227,7 +221,7 @@
         ReferenceChecker rc = new ReferenceChecker(keys, expect, value);
         buildRule.getProject().addBuildListener(rc);
         buildRule.executeTarget(target);
-        AssertionFailedError ae = rc.getError();
+        AssertionError ae = rc.getError();
         if (ae != null) {
             throw ae;
         }
@@ -236,23 +230,17 @@
 
     @Test
     public void testLogfilePlacement() {
-        File[] logFiles = new File[] {
-            buildRule.getProject().resolveFile("test1.log"),
-            buildRule.getProject().resolveFile("test2.log"),
-            buildRule.getProject().resolveFile("ant/test3.log"),
-            buildRule.getProject().resolveFile("ant/test4.log")
-        };
-        for (File logFile : logFiles) {
-            assertTrue(logFile.getName() + " doesn\'t exist",
-                    !logFile.exists());
-        }
+        List<File> logFiles = Arrays.asList(buildRule.getProject().resolveFile("test1.log"),
+                buildRule.getProject().resolveFile("test2.log"),
+                buildRule.getProject().resolveFile("ant/test3.log"),
+                buildRule.getProject().resolveFile("ant/test4.log"));
+
+        logFiles.forEach(logFile -> assertFalse(logFile.getName() + " doesn't exist",
+                logFile.exists()));
 
         buildRule.executeTarget("testLogfilePlacement");
 
-        for (File logFile : logFiles) {
-            assertTrue(logFile.getName() + " exists",
-                    logFile.exists());
-        }
+        logFiles.forEach(logFile -> assertTrue(logFile.getName() + " exists", logFile.exists()));
     }
 
     @Test
@@ -262,7 +250,7 @@
         InputHandlerChecker ic = new InputHandlerChecker(ih);
         buildRule.getProject().addBuildListener(ic);
         buildRule.executeTarget("tripleCall");
-        AssertionFailedError ae = ic.getError();
+        AssertionError ae = ic.getError();
         if (ae != null) {
             throw ae;
         }
@@ -273,13 +261,11 @@
     public void testRefId() {
         Path testPath = new Path(buildRule.getProject());
         testPath.createPath().setPath(System.getProperty("java.class.path"));
-        PropertyChecker pc =
-            new PropertyChecker("testprop",
-                                new String[] {null,
-                                              testPath.toString()});
+        PropertyChecker pc = new PropertyChecker("testprop",
+                new String[] {null, testPath.toString()});
         buildRule.getProject().addBuildListener(pc);
         buildRule.executeTarget("testRefid");
-        AssertionFailedError ae = pc.getError();
+        AssertionError ae = pc.getError();
         if (ae != null) {
             throw ae;
         }
@@ -290,47 +276,43 @@
     public void testUserPropertyWinsInheritAll() {
         buildRule.getProject().setUserProperty("test", "7");
         buildRule.executeTarget("test-property-override-inheritall-start");
-
-        AntAssert.assertContains("The value of test is 7", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("The value of test is 7"));
     }
 
     @Test
     public void testUserPropertyWinsNoInheritAll() {
         buildRule.getProject().setUserProperty("test", "7");
         buildRule.executeTarget("test-property-override-no-inheritall-start");
-
-        AntAssert.assertContains("The value of test is 7", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("The value of test is 7"));
     }
 
     @Test
     public void testOverrideWinsInheritAll() {
         buildRule.executeTarget("test-property-override-inheritall-start");
-
-        AntAssert.assertContains("The value of test is 4", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("The value of test is 4"));
     }
 
     @Test
     public void testOverrideWinsNoInheritAll() {
         buildRule.executeTarget("test-property-override-no-inheritall-start");
-        AntAssert.assertContains("The value of test is 4", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("The value of test is 4"));
     }
 
     @Test
     public void testPropertySet() {
         buildRule.executeTarget("test-propertyset");
-        assertTrue(buildRule.getLog().contains("test1 is ${test1}"));
-        assertTrue(buildRule.getLog().contains("test2 is ${test2}"));
-        assertTrue(buildRule.getLog().contains("test1.x is 1"));
+        assertThat(buildRule.getLog(), containsString("test1 is ${test1}"));
+        assertThat(buildRule.getLog(), containsString("test2 is ${test2}"));
+        assertThat(buildRule.getLog(), containsString("test1.x is 1"));
     }
 
-    @Test
+    /**
+     * Fail due to infinite recursion loop
+     */
+    @Test(expected = BuildException.class)
     public void testInfiniteLoopViaDepends() {
-        try {
-            buildRule.executeTarget("infinite-loop-via-depends");
-            fail("recursive call");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("infinite-loop-via-depends");
+        // TODO assert exception message
     }
 
     @Test
@@ -342,7 +324,6 @@
     @Test
     public void testTopLevelTarget() {
         buildRule.executeTarget("topleveltarget");
-
         assertEquals("Hello world", buildRule.getLog());
     }
 
@@ -355,11 +336,11 @@
         buildRule.getProject().addBuildListener(pcBar);
         buildRule.getProject().addBuildListener(pcFoo);
         buildRule.executeTarget("multiple-property-file-children");
-        AssertionFailedError aeBar = pcBar.getError();
+        AssertionError aeBar = pcBar.getError();
         if (aeBar != null) {
             throw aeBar;
         }
-        AssertionFailedError aeFoo = pcFoo.getError();
+        AssertionError aeFoo = pcFoo.getError();
         if (aeFoo != null) {
             throw aeFoo;
         }
@@ -367,14 +348,13 @@
         buildRule.getProject().removeBuildListener(pcFoo);
     }
 
-    @Test
+    /**
+     * Fail due to empty target name
+     */
+    @Test(expected = BuildException.class)
     public void testBlankTarget() {
-        try {
-            buildRule.executeTarget("blank-target");
-            fail("target name must not be empty");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("blank-target");
+        // TODO assert exception message
     }
 
     @Test
@@ -394,13 +374,14 @@
         // Cf. #42263
         buildRule.executeTarget("sub-show-ant.core.lib");
         String realLog = buildRule.getLog();
-        assertTrue("found ant.core.lib in: " + realLog, realLog.matches(".*(ant[.]jar|build.classes).*"));
+        assertTrue("found ant.core.lib in: " + realLog,
+                realLog.matches(".*(ant[.]jar|ant.classes|build.classes).*"));
     }
 
     private class BasedirChecker implements BuildListener {
         private String[] expectedBasedirs;
         private int calls = 0;
-        private AssertionFailedError error;
+        private AssertionError error;
 
         BasedirChecker(String[] dirs) {
             expectedBasedirs = dirs;
@@ -425,23 +406,22 @@
         }
 
         public void targetStarted(BuildEvent event) {
-            if (event.getTarget().getName().equals("")) {
+            if (event.getTarget().getName().isEmpty()) {
                 return;
             }
             if (error == null) {
                 try {
                     assertEquals(expectedBasedirs[calls++],
                                  event.getProject().getBaseDir().getAbsolutePath());
-                } catch (AssertionFailedError e) {
+                } catch (AssertionError e) {
                     error = e;
                 }
             }
         }
 
-        AssertionFailedError getError() {
+        AssertionError getError() {
             return error;
         }
-
     }
 
     private class ReferenceChecker implements BuildListener {
@@ -449,7 +429,7 @@
         private boolean[] expectSame;
         private Object value;
         private int calls = 0;
-        private AssertionFailedError error;
+        private AssertionError error;
 
         ReferenceChecker(String[] keys, boolean[] expectSame, Object value) {
             this.keys = keys;
@@ -476,13 +456,12 @@
         }
 
         public void targetStarted(BuildEvent event) {
-            if (event.getTarget().getName().equals("")) {
+            if (event.getTarget().getName().isEmpty()) {
                 return;
             }
             if (error == null) {
                 try {
-                    String msg =
-                        "Call " + calls + " refid=\'" + keys[calls] + "\'";
+                    String msg = "Call " + calls + " refid='" + keys[calls] + "'";
                     if (value == null) {
                         Object o = event.getProject().getReference(keys[calls]);
                         if (expectSame[calls++]) {
@@ -493,40 +472,39 @@
                     } else {
                         // a rather convoluted equals() test
                         Path expect = (Path) value;
-                        Path received = (Path) event.getProject().getReference(keys[calls]);
+                        Path received = event.getProject().getReference(keys[calls]);
                         boolean shouldBeEqual = expectSame[calls++];
                         if (received == null) {
-                            assertTrue(msg, !shouldBeEqual);
+                            assertFalse(msg, shouldBeEqual);
                         } else {
                             String[] l1 = expect.list();
                             String[] l2 = received.list();
                             if (l1.length == l2.length) {
                                 for (int i = 0; i < l1.length; i++) {
                                     if (!l1[i].equals(l2[i])) {
-                                        assertTrue(msg, !shouldBeEqual);
+                                        assertFalse(msg, shouldBeEqual);
                                     }
                                 }
                                 assertTrue(msg, shouldBeEqual);
                             } else {
-                                assertTrue(msg, !shouldBeEqual);
+                                assertFalse(msg, shouldBeEqual);
                             }
                         }
                     }
-                } catch (AssertionFailedError e) {
+                } catch (AssertionError e) {
                     error = e;
                 }
             }
         }
 
-        AssertionFailedError getError() {
+        AssertionError getError() {
             return error;
         }
-
     }
 
     private class InputHandlerChecker implements BuildListener {
         private InputHandler ih;
-        private AssertionFailedError error;
+        private AssertionError error;
 
         InputHandlerChecker(InputHandler value) {
             ih = value;
@@ -535,18 +513,23 @@
         public void buildStarted(BuildEvent event) {
             check(event);
         }
+
         public void buildFinished(BuildEvent event) {
             check(event);
         }
+
         public void targetFinished(BuildEvent event) {
             check(event);
         }
+
         public void taskStarted(BuildEvent event) {
             check(event);
         }
+
         public void taskFinished(BuildEvent event) {
             check(event);
         }
+
         public void messageLogged(BuildEvent event) {
             check(event);
         }
@@ -560,23 +543,22 @@
                 try {
                     assertNotNull(event.getProject().getInputHandler());
                     assertSame(ih, event.getProject().getInputHandler());
-                } catch (AssertionFailedError e) {
+                } catch (AssertionError e) {
                     error = e;
                 }
             }
         }
 
-        AssertionFailedError getError() {
+        AssertionError getError() {
             return error;
         }
-
     }
 
     private class PropertyChecker implements BuildListener {
         private String[] expectedValues;
         private String key;
         private int calls = 0;
-        private AssertionFailedError error;
+        private AssertionError error;
 
         PropertyChecker(String key, String[] values) {
             this.key = key;
@@ -602,29 +584,27 @@
         }
 
         public void targetStarted(BuildEvent event) {
-            if (event.getTarget().getName().equals("")) {
+            if (event.getTarget().getName().isEmpty()) {
                 return;
             }
             if (calls >= expectedValues.length) {
-                error = new AssertionFailedError("Unexpected invocation of"
-                                                 + " target "
-                                                 + event.getTarget().getName());
+                error = new AssertionError("Unexpected invocation of target "
+                        + event.getTarget().getName());
             }
 
             if (error == null) {
                 try {
                     assertEquals(expectedValues[calls++],
                                  event.getProject().getProperty(key));
-                } catch (AssertionFailedError e) {
+                } catch (AssertionError e) {
                     error = e;
                 }
             }
         }
 
-        AssertionFailedError getError() {
+        AssertionError getError() {
             return error;
         }
-
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/AntlibTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/AntlibTest.java
index 70abe0c..c4a76eb 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/AntlibTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/AntlibTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,12 +21,13 @@
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
 
 /**
  */
@@ -58,10 +59,11 @@
     /**
      * Confirms that all matching resources will be used, so that you
      * can collect several antlibs in one Definer call.
-     * @see "http://issues.apache.org/bugzilla/show_bug.cgi?id=24024"
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=24024">bug 24024</a>
      */
     @Test
     public void testAntlibResource() {
+        assertNotNull("build.tests.value not set", System.getProperty("build.tests.value"));
         buildRule.executeTarget("antlib.resource");
         assertEquals("MyTask called-and-then-MyTask2 called", buildRule.getLog());
     }
@@ -74,19 +76,19 @@
 
     @Test
     public void testAntlib_uri() {
-        Assume.assumeTrue("Test requires shared JVM", isSharedJVM());
+        assumeTrue("Test requires shared JVM", isSharedJVM());
         buildRule.executeTarget("antlib_uri");
     }
 
     @Test
     public void testAntlib_uri_auto() {
-        Assume.assumeTrue("Test requires shared JVM", isSharedJVM());
+        assumeTrue("Test requires shared JVM", isSharedJVM());
         buildRule.executeTarget("antlib_uri_auto");
     }
 
     @Test
     public void testAntlib_uri_auto2() {
-        Assume.assumeTrue("Test requires shared JVM", isSharedJVM());
+        assumeTrue("Test requires shared JVM", isSharedJVM());
         buildRule.executeTarget("antlib_uri_auto2");
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/AvailableTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/AvailableTest.java
index ae87a5a..82ac08f 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/AvailableTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/AvailableTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,13 +21,12 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit test for the Available task/condition.
@@ -44,95 +43,105 @@
         buildRule.executeTarget("setUp");
     }
 
-    // Nothing specified -> Fail
-    @Test
+    /**
+     *  Nothing specified -&gt; Fail
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test1");
     }
 
-    // Only property specified -> Fail
-    @Test
+    /**
+     * Only property specified -&gt; Fail
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test2");
     }
 
-    // Only file specified -> Fail
-    @Test
+    /**
+     * Only file specified -&gt; Fail
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test3");
     }
 
-    // file doesn't exist -> property 'test' == null
+    /**
+     * File doesn't exist -&gt; property 'test' == null
+     */
     @Test
     public void test4() {
         buildRule.executeTarget("test4");
-        assertTrue(buildRule.getProject().getProperty("test") == null);
+        assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // file does exist -> property 'test' == 'true'
+    /**
+     * File does exist -&gt; property 'test' == 'true'
+     */
+    @Test
     public void test5() {
         buildRule.executeTarget("test5");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // resource doesn't exist -> property 'test' == null
+    /**
+     * Resource doesn't exist -&gt; property 'test' == null
+     */
     @Test
     public void test6() {
         buildRule.executeTarget("test6");
-        assertTrue(buildRule.getProject().getProperty("test") == null);
+        assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // resource does exist -> property 'test' == 'true'
+    /**
+     * Resource does exist -&gt; property 'test' == 'true'
+     */
     @Test
     public void test7() {
         buildRule.executeTarget("test7");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // class doesn't exist -> property 'test' == null
+    /**
+     * Class doesn't exist -&gt; property 'test' == null
+     */
     @Test
     public void test8() {
         buildRule.executeTarget("test8");
-        assertTrue(buildRule.getProject().getProperty("test") == null);
+        assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // class does exist -> property 'test' == 'true'
+    /**
+     * class does exist -&gt; property 'test' == 'true'
+     */
     @Test
     public void test9() {
         buildRule.executeTarget("test9");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // All three specified and all three exist -> true
+    /**
+     * All three specified and all three exist -&gt; true
+     */
     @Test
     public void test10() {
         buildRule.executeTarget("test10");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // All three specified but class missing -> null
+    /**
+     * All three specified but class missing -&gt; null
+     */
     @Test
     public void test11() {
         buildRule.executeTarget("test11");
         assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // Specified property-name is "" -> true
+    /**
+     * Specified property-name is "" -&gt; true
+     */
     @Test
     public void test12() {
         buildRule.executeTarget("test12");
@@ -140,131 +149,162 @@
         assertEquals("true", buildRule.getProject().getProperty(""));
     }
 
-    // Specified file is "" -> invalid files do not exist
+    /**
+     * Specified file is "" -&gt; invalid files do not exist
+     */
     @Test
     public void test13() {
         buildRule.executeTarget("test13");
         assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // Specified file is "" actually a directory, so it should pass
+    /**
+     * Specified file is "" actually a directory, so it should pass
+     */
     @Test
     public void test13b() {
         buildRule.executeTarget("test13b");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // Specified resource is "" -> can such a thing exist?
-    /*
-     * returns non null IBM JDK 1.3 Linux
+    /**
+     * Specified resource is "" -gt; can such a thing exist?
      */
-//    public void test14() {
-//        buildRule.executeTarget("test14");
-//        assertEquals(buildRule.getProject().getProperty("test"), null);
-//    }
+    @Ignore("returns non null IBM JDK 1.3 Linux")
+    @Test
+    public void test14() {
+        buildRule.executeTarget("test14");
+        assertNull(buildRule.getProject().getProperty("test"));
+    }
 
-    // Specified class is "" -> can not exist
+    /**
+     * Specified class is "" -&gt; can not exist
+     */
     @Test
     public void test15() {
         buildRule.executeTarget("test15");
         assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // Specified dir is "" -> this is the current directory and should
-    // always exist
+    /**
+     * Specified dir is "" -&gt; this is the current directory and should always exist
+     */
     @Test
     public void test16() {
         buildRule.executeTarget("test16");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // Specified dir is "../taskdefs" -> should exist since it's the
-    // location of the buildfile used...
+    /**
+     * Specified dir is "../taskdefs" -&gt; should exist since it's the location
+     * of the buildfile used...
+     */
     @Test
     public void test17() {
         buildRule.executeTarget("test17");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // Specified dir is "../this_dir_should_never_exist" -> null
+    /**
+     * Specified dir is "../this_dir_should_never_exist" -&gt; null
+     */
     @Test
     public void test18() {
         buildRule.executeTarget("test18");
         assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // Invalid type specified
-    @Test
+    /**
+     * Invalid type specified
+     */
+    @Test(expected = BuildException.class)
     public void test19() {
-        try {
-            buildRule.executeTarget("test19");
-            fail("Invalid value for type attribute");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test19");
     }
 
-    // Core class that exists in system classpath is ignored
+    /**
+     * Core class that exists in system classpath is ignored
+     */
     @Test
     public void test20() {
         buildRule.executeTarget("test20");
         assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // Core class that exists in system classpath is ignored, but found in specified classpath
+    /**
+     * Core class that exists in system classpath is ignored, but found in specified classpath
+     */
     @Test
     public void test21() {
         buildRule.executeTarget("test21");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // Core class that exists in system classpath is not ignored with ignoresystemclass="false"
+    /**
+     * Core class that exists in system classpath is not ignored with ignoresystemclass="false"
+     */
     @Test
     public void test22() {
         buildRule.executeTarget("test22");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // Core class that exists in system classpath is not ignored with default ignoresystemclasses value
+    /**
+     * Core class that exists in system classpath is not ignored with default
+     * ignoresystemclasses value
+     */
     @Test
     public void test23() {
         buildRule.executeTarget("test23");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // Class is found in specified classpath
+    /**
+     * Class is found in specified classpath
+     */
     @Test
     public void test24() {
         buildRule.executeTarget("test24");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // File is not found in specified filepath
+    /**
+     * File is not found in specified filepath
+     */
     @Test
     public void testSearchInPathNotThere() {
         buildRule.executeTarget("searchInPathNotThere");
         assertNull(buildRule.getProject().getProperty("test"));
     }
 
-    // File is not found in specified filepath
+    /**
+     * File is not found in specified filepath
+     */
     @Test
     public void testSearchInPathIsThere() {
         buildRule.executeTarget("searchInPathIsThere");
         assertEquals("true", buildRule.getProject().getProperty("test"));
     }
 
-    // test when file begins with basedir twice
+    /**
+     * File begins with basedir twice
+     */
     @Test
     public void testDoubleBasedir() {
         buildRule.executeTarget("testDoubleBasedir");
     }
 
-    // test for searching parents
+    /**
+     * Search parents
+     */
     @Test
     public void testSearchParents() {
         buildRule.executeTarget("search-parents");
     }
-    // test for not searching parents
+
+    /**
+     * Do not search parents
+     */
     @Test
     public void testSearchParentsNot() {
         buildRule.executeTarget("search-parents-not");
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/BUnzip2Test.java b/src/tests/junit/org/apache/tools/ant/taskdefs/BUnzip2Test.java
index 0faacd1..9f85a45 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/BUnzip2Test.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/BUnzip2Test.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/BZip2Test.java b/src/tests/junit/org/apache/tools/ant/taskdefs/BZip2Test.java
index d080fae..cbebdf4 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/BZip2Test.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/BZip2Test.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,13 +26,13 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
 
+import static org.hamcrest.Matchers.endsWith;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -68,12 +68,12 @@
         File actualFile   = new File(outputDir, "asf-logo-huge.tar.bz2");
 
         InputStream originalIn =
-            new BufferedInputStream(new FileInputStream(originalFile));
+            new BufferedInputStream(Files.newInputStream(originalFile.toPath()));
         assertEquals((byte) 'B', originalIn.read());
         assertEquals((byte) 'Z', originalIn.read());
 
         InputStream actualIn =
-            new BufferedInputStream(new FileInputStream(actualFile));
+            new BufferedInputStream(Files.newInputStream(actualFile.toPath()));
         assertEquals((byte) 'B', actualIn.read());
         assertEquals((byte) 'Z', actualIn.read());
 
@@ -83,14 +83,8 @@
         while (true) {
             int expected = originalIn.read();
             int actual   = actualIn.read();
-            if (expected >= 0) {
-                if (expected != actual) {
-                    fail("File content mismatch");
-                }
-            } else {
-                if (actual >= 0) {
-                    fail("File content mismatch");
-                }
+            assertEquals("File content mismatch", expected, actual);
+            if (expected < 0) {
                 break;
             }
         }
@@ -108,9 +102,8 @@
     public void testDateCheck() {
         buildRule.executeTarget("testDateCheck");
         String log = buildRule.getLog();
-        assertTrue(
-            "Expecting message ending with 'asf-logo.gif.bz2 is up to date.' but got '" + log + "'",
-            log.endsWith("asf-logo.gif.bz2 is up to date."));
+        assertThat("Expecting message ending with 'asf-logo.gif.bz2 is up to date.' but got '"
+                        + log + "'", log, endsWith("asf-logo.gif.bz2 is up to date."));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/BasenameTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/BasenameTest.java
index 3915d6b..407e6d7 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/BasenameTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/BasenameTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,6 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  */
@@ -39,34 +38,22 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/basename.xml");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("Required attribute missing");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert exception message
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("Required attribute missing");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert exception message
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("Required attribute missing");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert exception message
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/CVSPassTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/CVSPassTest.java
index 63ee645..fe50906 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/CVSPassTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/CVSPassTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,17 +27,17 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Tests CVSLogin task.
  *
  */
 public class CVSPassTest {
-    private final String EOL = System.getProperty("line.separator");
+    private final String EOL = System.lineSeparator();
     private static final String JAKARTA_URL =
         ":pserver:anoncvs@jakarta.apache.org:/home/cvspublic Ay=0=h<Z";
     private static final String XML_URL =
@@ -46,37 +46,33 @@
         ":pserver:guest@cvs.tigris.org:/cvs AIbdZ,";
 
     @Rule
-    public final BuildFileRule buildRule = new BuildFileRule();
+    public ExpectedException thrown = ExpectedException.none();
 
+    @Rule
+    public final BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/cvspass.xml");
     }
 
+    @After
+    public void tearDown() {
+        buildRule.executeTarget("cleanup");
+    }
+
     @Test
     public void testNoCVSRoot() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException not thrown");
-        } catch (BuildException e) {
-            assertEquals("cvsroot is required", e.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("cvsroot is required");
+        buildRule.executeTarget("test1");
     }
 
     @Test
     public void testNoPassword() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException not thrown");
-        } catch (BuildException e) {
-            assertEquals("password is required", e.getMessage());
-        }
-    }
-
-    @After
-    public void tearDown() {
-        buildRule.executeTarget("cleanup");
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("password is required");
+        buildRule.executeTarget("test2");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/CallTargetTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/CallTargetTest.java
index 337c6a4..968ce1a 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/CallTargetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/CallTargetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
@@ -27,8 +26,9 @@
 
 import java.util.Vector;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -47,7 +47,7 @@
     @Test
     public void testInheritRefFileSet() {
         buildRule.executeTarget("testinheritreffileset");
-        AntAssert.assertContains("calltarget.xml", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("calltarget.xml"));
     }
 
     // see bugrep 21724 (references not passing through with antcall)
@@ -60,21 +60,19 @@
     // params will not be passed in)
     @Test
     public void testMultiCall() {
-        Vector<String> v = new Vector<String>();
+        Vector<String> v = new Vector<>();
         v.add("call-multi");
         v.add("call-multi");
         buildRule.getProject().executeTargets(v);
-        AntAssert.assertContains("multi is SETmulti is SET", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("multi is SETmulti is SET"));
     }
 
-    @Test
+    /**
+     * Expected failure due to empty target name
+     */
+    @Test(expected = BuildException.class)
     public void testBlankTarget() {
-        try {
-            buildRule.executeTarget("blank-target");
-            fail("target name must not be empty");
-        } catch (BuildException ex) {
-            //TODO assert exception contents
-        }
+        buildRule.executeTarget("blank-target");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ChecksumTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ChecksumTest.java
index 8d26153..2838559 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ChecksumTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ChecksumTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,6 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import java.io.IOException;
-
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.After;
 import org.junit.Before;
@@ -42,22 +40,22 @@
     }
 
     @Test
-    public void testCreateMd5() throws IOException {
+    public void testCreateMd5() {
         buildRule.executeTarget("createMd5");
     }
 
     @Test
-    public void testCreateMD5SUMformat() throws IOException {
+    public void testCreateMD5SUMformat() {
         buildRule.executeTarget("createMD5SUMformat");
     }
 
     @Test
-    public void testCreateSVFformat() throws IOException {
+    public void testCreateSVFformat() {
         buildRule.executeTarget("createSVFformat");
     }
 
     @Test
-    public void testCreatePattern() throws IOException {
+    public void testCreatePattern() {
         buildRule.executeTarget("createPattern");
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ConcatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ConcatTest.java
index daec44b..5c2b177 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ConcatTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ConcatTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,10 +29,11 @@
 import java.io.File;
 import java.io.IOException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * A test class for the 'concat' task, used to concatenate a series of
@@ -77,28 +78,19 @@
     /**
      * Expect an exception when insufficient information is provided.
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException should have been thrown - Insufficient information");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
-
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
     /**
      * Expect an exception when the destination file is invalid.
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException should have been thrown - Invalid destination file");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
     /**
@@ -106,14 +98,12 @@
      */
     @Test
     public void test3() {
-
         File file = new File(buildRule.getProject().getBaseDir(), tempFile);
         if (file.exists()) {
             file.delete();
         }
 
         buildRule.executeTarget("test3");
-
         assertTrue(file.exists());
     }
 
@@ -149,7 +139,7 @@
         String filename = "src/etc/testcases/taskdefs/thisfiledoesnotexist"
             .replace('/', File.separatorChar);
         buildRule.executeTarget("test6");
-        assertContains(filename + " does not exist", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString(filename + " does not exist"));
     }
 
     @Test
@@ -177,7 +167,6 @@
         final long newSize = file2.length();
 
         assertEquals(origSize, newSize);
-
     }
 
     @Test
@@ -193,13 +182,12 @@
         final long newSize = file2.length();
 
         assertEquals(origSize * 2, newSize);
-
     }
 
     @Test
     public void testFilter() {
         buildRule.executeTarget("testfilter");
-        assertTrue(buildRule.getLog().contains("REPLACED"));
+        assertThat(buildRule.getLog(), containsString("REPLACED"));
     }
 
     @Test
@@ -235,14 +223,9 @@
     /**
      * Expect an exception when attempting to cat an file to itself
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void testsame() {
-        try {
-            buildRule.executeTarget("samefile");
-            fail("Build exception should have been thrown - output file same as input");
-        } catch(BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("samefile");
     }
 
     /**
@@ -251,7 +234,7 @@
     @Test
     public void testfilterinline() {
         buildRule.executeTarget("testfilterinline");
-        assertTrue(buildRule.getLog().contains("REPLACED"));
+        assertThat(buildRule.getLog(), containsString("REPLACED"));
     }
 
     /**
@@ -260,8 +243,8 @@
     @Test
     public void testmultireader() {
         buildRule.executeTarget("testmultireader");
-        assertTrue(buildRule.getLog().contains("Bye"));
-        assertTrue(!buildRule.getLog().contains("Hello"));
+        assertThat(buildRule.getLog(), containsString("Bye"));
+        assertThat(buildRule.getLog(), not(containsString("Hello")));
     }
     /**
      * Check if fixlastline works
@@ -269,8 +252,8 @@
     @Test
     public void testfixlastline() throws IOException {
         buildRule.executeTarget("testfixlastline");
-        assertContains("end of line" + System.getProperty("line.separator") + "This has",
-                FileUtilities.getFileContents(buildRule.getProject(), "concat.line4"));
+        assertThat(FileUtilities.getFileContents(buildRule.getProject(), "concat.line4"),
+                containsString("end of line" + System.lineSeparator() + "This has"));
     }
 
     /**
@@ -279,7 +262,8 @@
     @Test
     public void testfixlastlineeol() throws IOException {
         buildRule.executeTarget("testfixlastlineeol");
-        assertContains("end of line\rThis has", FileUtilities.getFileContents(buildRule.getProject(), "concat.linecr"));
+        assertThat(FileUtilities.getFileContents(buildRule.getProject(), "concat.linecr"),
+                containsString("end of line\rThis has"));
     }
 
     @Test
@@ -291,18 +275,4 @@
                 FileUtilities.getFileContents(f1), FileUtilities.getFileContents(f2));
     }
 
-    // ------------------------------------------------------
-    //   Helper methods - should be in a utility class
-    // -----------------------------------------------------
-    @SuppressWarnings("unused")
-    private void expectFileContainsx(String target, String filename, String contains)
-        throws IOException {
-        buildRule.executeTarget(target);
-        String content = FileUtilities.getFileContents(buildRule.getProject(), filename);
-        assertTrue(
-            "expecting file " + filename + " to contain " +
-            contains +
-            " but got " + content, content.contains(contains));
-    }
-
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ConditionTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ConditionTest.java
index 9329512..0a5b401 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ConditionTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ConditionTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,16 +23,18 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
 
 public class ConditionTest {
 
     @Rule
-    public BuildFileRule buildRule = new BuildFileRule();
+    public ExpectedException thrown = ExpectedException.none();
 
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
 
     /**
      * The JUnit setup method
@@ -59,22 +61,16 @@
 
     @Test
     public void testConditionIncomplete() {
-        try {
-            buildRule.executeTarget("condition-incomplete");
-            fail("BuildException should have been thrown - property attribute has been omitted");
-        } catch (BuildException ex) {
-            assertEquals("The property attribute is required.", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The property attribute is required.");
+        buildRule.executeTarget("condition-incomplete");
     }
 
     @Test
     public void testConditionEmpty() {
-        try {
-            buildRule.executeTarget("condition-empty");
-            fail("BuildException should have been thrown - no conditions");
-        } catch (BuildException ex) {
-            assertEquals("You must nest a condition into <condition>", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must nest a condition into <condition>");
+        buildRule.executeTarget("condition-empty");
     }
 
     @Test
@@ -109,12 +105,9 @@
 
     @Test
     public void testNegationIncomplete() {
-        try {
-            buildRule.executeTarget("negationincomplete");
-            fail("BuildException should have been thrown - no conditions in <not>");
-        } catch (BuildException ex) {
-            assertEquals("You must nest a condition into <not>", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must nest a condition into <not>");
+        buildRule.executeTarget("negationincomplete");
     }
 
     @Test
@@ -173,12 +166,9 @@
 
     @Test
     public void testFilesmatchIncomplete() {
-        try {
-            buildRule.executeTarget("filesmatch-incomplete");
-            fail("Build exception should have been thrown - Missing file2 attirbute");
-        } catch (BuildException ex) {
-            assertEquals("both file1 and file2 are required in filesmatch", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("both file1 and file2 are required in filesmatch");
+        buildRule.executeTarget("filesmatch-incomplete");
     }
 
     @Test
@@ -252,22 +242,16 @@
 
     @Test
     public void testContainsIncomplete1() {
-        try {
-            buildRule.executeTarget("contains-incomplete1");
-            fail("BuildException should have been thrown - Missing contains attribute");
-        } catch (BuildException ex) {
-            assertEquals("both string and substring are required in contains", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("both string and substring are required in contains");
+        buildRule.executeTarget("contains-incomplete1");
     }
 
     @Test
     public void testContainsIncomplete2() {
-        try {
-            buildRule.executeTarget("contains-incomplete2");
-            fail("BuildException should have been thrown - Missing contains attribute");
-        } catch (BuildException ex) {
-            assertEquals("both string and substring are required in contains", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("both string and substring are required in contains");
+        buildRule.executeTarget("contains-incomplete2");
     }
 
     @Test
@@ -290,12 +274,9 @@
 
     @Test
     public void testIstrueIncomplete1() {
-        try {
-            buildRule.executeTarget("istrue-incomplete");
-            fail("BuildException should have been thrown - Missing attribute");
-        } catch (BuildException ex) {
-            assertEquals("Nothing to test for truth", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Nothing to test for truth");
+        buildRule.executeTarget("istrue-incomplete");
     }
 
     @Test
@@ -319,12 +300,9 @@
 
     @Test
     public void testIsfalseIncomplete1() {
-        try {
-            buildRule.executeTarget("isfalse-incomplete");
-            fail("BuildException should have been thrown - Missing attribute");
-        } catch (BuildException ex) {
-            assertEquals("Nothing to test for falsehood", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Nothing to test for falsehood");
+        buildRule.executeTarget("isfalse-incomplete");
     }
 
     @Test
@@ -332,14 +310,10 @@
         buildRule.executeTarget("testElse");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testResourcesmatchError() {
-        try {
-            buildRule.executeTarget("resourcematch-error");
-            fail("BuildException should have been thrown - no resources specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("resourcematch-error");
+        // TODO assert value
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/CopyTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/CopyTest.java
index db2daf8..64173f4 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/CopyTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/CopyTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,22 +23,26 @@
 import org.apache.tools.ant.FileUtilities;
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.apache.tools.ant.util.FileUtils;
-import org.junit.Assert;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Tests FileSet using the Copy task.
@@ -49,6 +53,8 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
     public void setUp() {
@@ -60,70 +66,62 @@
     public void test1() {
         buildRule.executeTarget("test1");
         File f = new File(buildRule.getProject().getProperty("output"), "copytest1.tmp");
-        if (!f.exists()) {
-            fail("Copy failed");
-        }
+        assertTrue("Copy failed", f.exists());
     }
 
     @Test
     public void test2() {
         buildRule.executeTarget("test2");
         File f = new File(buildRule.getProject().getProperty("output"), "copytest1dir/copy.xml");
-        if (!f.exists()) {
-            fail("Copy failed");
-        }
+        assertTrue("Copy failed", f.exists());
     }
 
     @Test
     public void test3() {
         buildRule.executeTarget("test3");
-        File file3  = new File(buildRule.getProject().getProperty("output"), "copytest3.tmp");
-        //rollback file timestamp instead of delaying test
+        final String output = buildRule.getProject().getProperty("output");
+        final File file3 = new File(output, "copytest3.tmp");
+        // rollback file timestamp instead of delaying test
         FileUtilities.rollbackTimestamps(file3, 3);
         buildRule.executeTarget("test3Part2");
         assertTrue(file3.exists());
 
-        File file3a = new File(buildRule.getProject().getProperty("output"), "copytest3a.tmp");
+        File file3a = new File(output, "copytest3a.tmp");
         assertTrue(file3a.exists());
-        File file3b = new File(buildRule.getProject().getProperty("output"), "copytest3b.tmp");
+        File file3b = new File(output, "copytest3b.tmp");
         assertTrue(file3b.exists());
-        File file3c = new File(buildRule.getProject().getProperty("output"), "copytest3c.tmp");
+        File file3c = new File(output, "copytest3c.tmp");
         assertTrue(file3c.exists());
 
-        //file length checks rely on touch generating a zero byte file
-        if (file3.length()==0) {
-            fail("could not overwrite an existing, older file");
-        }
-        if (file3c.length()!=0) {
-            fail("could not force overwrite an existing, newer file");
-        }
-        if (file3b.length()==0) {
-            fail("unexpectedly overwrote an existing, newer file");
-        }
+        // file length checks rely on touch generating a zero byte file
 
-        //file time checks for java1.2+
-        assertTrue(file3a.lastModified() == file3.lastModified());
+        assertNotEquals("could not overwrite an existing, older file", 0, file3.length());
+        assertEquals("could not force overwrite an existing, newer file", 0, file3c.length());
+        assertNotEquals("unexpectedly overwrote an existing, newer file", 0, file3b.length());
+
+        // file time checks for java1.2+
+        assertEquals(file3a.lastModified(), file3.lastModified());
         assertTrue(file3c.lastModified() < file3a.lastModified());
-
     }
 
     @Test
     public void testFilterTest() {
         buildRule.executeTarget("filtertest");
-        assertTrue(!buildRule.getLog().contains("loop in tokens"));
+        assertThat(buildRule.getLog(), not(containsString("loop in tokens")));
     }
 
     @Test
     public void testInfiniteFilter() {
         buildRule.executeTarget("infinitetest");
-        assertContains("loop in tokens", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("loop in tokens"));
     }
 
     @Test
     public void testFilterSet() throws IOException {
         buildRule.executeTarget("testFilterSet");
-        File tmp  = new File(buildRule.getProject().getProperty("output"), "copy.filterset.tmp");
-        File check  = new File(buildRule.getProject().getBaseDir(), "expected/copy.filterset.filtered");
+        File tmp = new File(buildRule.getProject().getProperty("output"), "copy.filterset.tmp");
+        File check = new File(buildRule.getProject().getBaseDir(),
+                "expected/copy.filterset.filtered");
         assertTrue(tmp.exists());
         assertEquals(FileUtilities.getFileContents(tmp), FileUtilities.getFileContents(check));
     }
@@ -131,8 +129,9 @@
     @Test
     public void testFilterChain() throws IOException {
         buildRule.executeTarget("testFilterChain");
-        File tmp  = new File(buildRule.getProject().getProperty("output"), "copy.filterchain.tmp");
-        File check  = new File(buildRule.getProject().getBaseDir(), "expected/copy.filterset.filtered");
+        File tmp = new File(buildRule.getProject().getProperty("output"), "copy.filterchain.tmp");
+        File check = new File(buildRule.getProject().getBaseDir(),
+                "expected/copy.filterset.filtered");
         assertTrue(tmp.exists());
         assertEquals(FileUtilities.getFileContents(tmp), FileUtilities.getFileContents(check));
     }
@@ -140,16 +139,16 @@
     @Test
     public void testSingleFileFileset() {
         buildRule.executeTarget("test_single_file_fileset");
-        File file  = new File(buildRule.getProject().getProperty("output"),
-                                        "copytest_single_file_fileset.tmp");
+        File file = new File(buildRule.getProject().getProperty("output"),
+                "copytest_single_file_fileset.tmp");
         assertTrue(file.exists());
     }
 
     @Test
     public void testSingleFilePath() {
         buildRule.executeTarget("test_single_file_path");
-        File file  = new File(buildRule.getProject().getProperty("output"),
-                                        "copytest_single_file_path.tmp");
+        File file = new File(buildRule.getProject().getProperty("output"),
+                "copytest_single_file_path.tmp");
         assertTrue(file.exists());
     }
 
@@ -164,57 +163,46 @@
     @Test
     public void testMissingFileIgnore() {
         buildRule.executeTarget("testMissingFileIgnore");
-        assertContains("Warning: Could not find file", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Warning: Could not find file"));
     }
 
     @Test
     public void testMissingFileBail() {
-        try {
-            buildRule.executeTarget("testMissingFileBail");
-            fail("not-there doesn't exist");
-        } catch (BuildException ex) {
-            assertTrue(ex.getMessage()
-                    .startsWith("Warning: Could not find file "));
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(startsWith("Warning: Could not find file "));
+        buildRule.executeTarget("testMissingFileBail");
     }
 
     @Test
     public void testMissingDirIgnore() {
         buildRule.executeTarget("testMissingDirIgnore");
-        assertContains("Warning: ", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Warning: "));
     }
 
     @Test
     public void testMissingDirBail() {
-        try {
-            buildRule.executeTarget("testMissingDirBail");
-            fail("not-there doesn't exist");
-        } catch (BuildException ex) {
-            assertTrue(ex.getMessage().endsWith(" does not exist."));
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(endsWith(" does not exist."));
+        buildRule.executeTarget("testMissingDirBail");
     }
 
     @Test
     public void testFileResourcePlain() {
         buildRule.executeTarget("testFileResourcePlain");
-        File file1 = new File(buildRule.getProject().getProperty("to.dir") + "/file1.txt");
-        File file2 = new File(buildRule.getProject().getProperty("to.dir") + "/file2.txt");
-        File file3 = new File(buildRule.getProject().getProperty("to.dir") + "/file3.txt");
-        assertTrue(file1.exists());
-        assertTrue(file2.exists());
-        assertTrue(file3.exists());
+        final String toDir = buildRule.getProject().getProperty("to.dir");
+        assertTrue(new File(toDir + "/file1.txt").exists());
+        assertTrue(new File(toDir + "/file2.txt").exists());
+        assertTrue(new File(toDir + "/file3.txt").exists());
     }
 
     @Ignore("Previously ignored by naming convention")
     @Test
     public void testFileResourceWithMapper() {
         buildRule.executeTarget("testFileResourceWithMapper");
-        File file1 = new File(buildRule.getProject().getProperty("to.dir") + "/file1.txt.bak");
-        File file2 = new File(buildRule.getProject().getProperty("to.dir") + "/file2.txt.bak");
-        File file3 = new File(buildRule.getProject().getProperty("to.dir") + "/file3.txt.bak");
-        assertTrue(file1.exists());
-        assertTrue(file2.exists());
-        assertTrue(file3.exists());
+        final String toDir = buildRule.getProject().getProperty("to.dir");
+        assertTrue(new File(toDir + "/file1.txt.bak").exists());
+        assertTrue(new File(toDir + "/file2.txt.bak").exists());
+        assertTrue(new File(toDir + "/file3.txt.bak").exists());
     }
 
     @Test
@@ -222,38 +210,30 @@
         buildRule.executeTarget("testFileResourceWithFilter");
         File file1 = new File(buildRule.getProject().getProperty("to.dir") + "/fileNR.txt");
         assertTrue(file1.exists());
-        FileReader f = null;
-        try {
-            f = new FileReader(file1);
+        try (FileReader f = new FileReader(file1)) {
             String file1Content = FileUtils.readFully(f);
             assertEquals("This is file 42", file1Content);
         } catch (IOException e) {
             // no-op: not a real business error
-        } finally {
-            FileUtils.close(f);
         }
     }
 
     @Test
     public void testPathAsResource() {
         buildRule.executeTarget("testPathAsResource");
-        File file1 = new File(buildRule.getProject().getProperty("to.dir") + "/file1.txt");
-        File file2 = new File(buildRule.getProject().getProperty("to.dir") + "/file2.txt");
-        File file3 = new File(buildRule.getProject().getProperty("to.dir") + "/file3.txt");
-        assertTrue(file1.exists());
-        assertTrue(file2.exists());
-        assertTrue(file3.exists());
+        final String toDir = buildRule.getProject().getProperty("to.dir");
+        assertTrue(new File(toDir + "/file1.txt").exists());
+        assertTrue(new File(toDir + "/file2.txt").exists());
+        assertTrue(new File(toDir + "/file3.txt").exists());
     }
 
     @Test
     public void testZipfileset() {
         buildRule.executeTarget("testZipfileset");
-        File file1 = new File(buildRule.getProject().getProperty("to.dir") + "/file1.txt");
-        File file2 = new File(buildRule.getProject().getProperty("to.dir") + "/file2.txt");
-        File file3 = new File(buildRule.getProject().getProperty("to.dir") + "/file3.txt");
-        assertTrue(file1.exists());
-        assertTrue(file2.exists());
-        assertTrue(file3.exists());
+        final String toDir = buildRule.getProject().getProperty("to.dir");
+        assertTrue(new File(toDir + "/file1.txt").exists());
+        assertTrue(new File(toDir + "/file2.txt").exists());
+        assertTrue(new File(toDir + "/file3.txt").exists());
     }
 
     @Test
@@ -295,49 +275,43 @@
     @Test
     public void testCopyToSymlinkedSelf() throws Exception {
         // we are only going to test against systems that support symlinks
-        Assume.assumeTrue("Symlinks not supported on this operating system", Os.isFamily(Os.FAMILY_UNIX));
+        assumeTrue("Symlinks not supported on this operating system", Os.isFamily(Os.FAMILY_UNIX));
 
         // setup the source files to run copying against
         buildRule.executeTarget("setupSelfCopyTesting");
         final File testDir = new File(buildRule.getProject().getProperty("self.copy.test.root.dir"));
-        Assert.assertTrue(testDir + " was expected to be a directory", testDir.isDirectory());
+        assertTrue(testDir + " was expected to be a directory", testDir.isDirectory());
         final File srcFile = new File(testDir, "file.txt");
-        Assert.assertTrue("Source file " + srcFile + " was expected to be a file", srcFile.isFile());
+        assertTrue("Source file " + srcFile + " was expected to be a file", srcFile.isFile());
         final long originalFileSize = srcFile.length();
         final String originalContent;
-        final BufferedReader reader = new BufferedReader(new FileReader(srcFile));
-        try {
+        try (BufferedReader reader = new BufferedReader(new FileReader(srcFile))) {
             originalContent = FileUtils.readFully(reader);
-        } finally {
-            reader.close();
         }
-        Assert.assertTrue("Content missing in file " + srcFile, originalContent != null && originalContent.length() > 0);
+        assertTrue("Content missing in file " + srcFile, originalContent != null && !originalContent.isEmpty());
 
         // run the copy tests
         buildRule.executeTarget("testSelfCopy");
         // make sure the source file hasn't been impacted by the copy
         assertSizeAndContent(srcFile, originalFileSize, originalContent);
         final File symlinkedFile = new File(testDir, "sylmink-file.txt");
-        Assert.assertTrue(symlinkedFile + " was expected to be a file", symlinkedFile.isFile());
+        assertTrue(symlinkedFile + " was expected to be a file", symlinkedFile.isFile());
         assertSizeAndContent(symlinkedFile, originalFileSize, originalContent);
 
         final File symlinkedTestDir = new File(buildRule.getProject().getProperty("self.copy.test.symlinked.dir"));
-        Assert.assertTrue(symlinkedTestDir + " was expected to be a directory", symlinkedTestDir.isDirectory());
+        assertTrue(symlinkedTestDir + " was expected to be a directory", symlinkedTestDir.isDirectory());
         assertSizeAndContent(new File(symlinkedTestDir, "file.txt"), originalFileSize, originalContent);
         assertSizeAndContent(new File(symlinkedTestDir, "sylmink-file.txt"), originalFileSize, originalContent);
 
     }
 
     private void assertSizeAndContent(final File file, final long expectedSize, final String expectedContent) throws IOException {
-        Assert.assertTrue(file + " was expected to be a file", file.isFile());
-        Assert.assertEquals("Unexpected size of file " + file, expectedSize, file.length());
-        final BufferedReader reader = new BufferedReader(new FileReader(file));
+        assertTrue(file + " was expected to be a file", file.isFile());
+        assertEquals("Unexpected size of file " + file, expectedSize, file.length());
         final String content;
-        try {
+        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
             content = FileUtils.readFully(reader);
-        } finally {
-            reader.close();
         }
-        Assert.assertEquals("Unexpected content in file " + file, expectedContent, content);
+        assertEquals("Unexpected content in file " + file, expectedContent, content);
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/CopydirTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/CopydirTest.java
index adad994..6681204 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/CopydirTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/CopydirTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,7 +26,7 @@
 import java.io.File;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 
 public class CopydirTest {
@@ -39,34 +39,31 @@
         buildRule.executeTarget("setUp");
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO Assert exception message
     }
 
     @Test
@@ -81,20 +78,17 @@
         buildRule.executeTarget("test5");
         File f = new File(new File(buildRule.getProject().getProperty("output")), "taskdefs.tmp");
 
-        if (!f.exists() || !f.isDirectory()) {
-            fail("Copy failed");
-        }
+        assertTrue("Copy failed", f.exists() && f.isDirectory());
         // We keep this, so we have something to delete in later tests :-)
     }
 
-    @Test
+    /**
+     * expected failure because target is file
+     */
+    @Test(expected = BuildException.class)
     public void test6() {
-        try {
-            buildRule.executeTarget("test6");
-            fail("target is file");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test6");
+        // TODO Assert exception message
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/CopyfileTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/CopyfileTest.java
index a3d84ee..9fd60ea 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/CopyfileTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/CopyfileTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,7 +26,7 @@
 import java.io.File;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 /**
  */
@@ -40,34 +40,22 @@
         buildRule.executeTarget("setUp");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert value
     }
 
     @Test
@@ -81,20 +69,13 @@
     public void test5() {
         buildRule.executeTarget("test5");
         File f = new File(new File(buildRule.getProject().getProperty("output")), "copyfile.tmp");
-        if (f.exists()) {
-            f.delete();
-        } else {
-            fail("Copy failed");
-        }
+        assertTrue("Copy failed", f.exists());
+        f.delete();
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test6() {
-        try {
-            buildRule.executeTarget("test6");
-            fail("Required argument not specified");
-        } catch (BuildException ex) {
-            // TODO assert value
-        }
+        buildRule.executeTarget("test6");
+        // TODO assert value
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DefaultExcludesTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DefaultExcludesTest.java
index 06ca3a2..f17a4b3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DefaultExcludesTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DefaultExcludesTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,13 +24,121 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 /**
  */
+@RunWith(Parameterized.class)
 public class DefaultExcludesTest {
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object[][]{
+                /* default */
+                {"test1", new String[]{
+                        "**/*~",
+                        "**/#*#",
+                        "**/.#*",
+                        "**/%*%",
+                        "**/._*",
+                        "**/CVS",
+                        "**/CVS/**",
+                        "**/.cvsignore",
+                        "**/SCCS",
+                        "**/SCCS/**",
+                        "**/vssver.scc",
+                        "**/.svn",
+                        "**/.svn/**",
+                        "**/.git",
+                        "**/.git/**",
+                        "**/.gitattributes",
+                        "**/.gitignore",
+                        "**/.gitmodules",
+                        "**/.hg",
+                        "**/.hg/**",
+                        "**/.hgignore",
+                        "**/.hgsub",
+                        "**/.hgsubstate",
+                        "**/.hgtags",
+                        "**/.bzr",
+                        "**/.bzr/**",
+                        "**/.bzrignore",
+                        "**/.DS_Store"}},
+                /* add */
+                {"test2", new String[]{
+                        "**/*~",
+                        "**/#*#",
+                        "**/.#*",
+                        "**/%*%",
+                        "**/._*",
+                        "**/CVS",
+                        "**/CVS/**",
+                        "**/.cvsignore",
+                        "**/SCCS",
+                        "**/SCCS/**",
+                        "**/vssver.scc",
+                        "**/.svn",
+                        "**/.svn/**",
+                        "**/.git",
+                        "**/.git/**",
+                        "**/.gitattributes",
+                        "**/.gitignore",
+                        "**/.gitmodules",
+                        "**/.hg",
+                        "**/.hg/**",
+                        "**/.hgignore",
+                        "**/.hgsub",
+                        "**/.hgsubstate",
+                        "**/.hgtags",
+                        "**/.bzr",
+                        "**/.bzr/**",
+                        "**/.bzrignore",
+                        "**/.DS_Store",
+                        "foo"}},
+                /* subtract */
+                {"test3", new String[]{
+                        "**/*~",
+                        "**/#*#",
+                        "**/.#*",
+                        "**/%*%",
+                        "**/._*",
+                        //CVS missing
+                        "**/CVS/**",
+                        "**/.cvsignore",
+                        "**/SCCS",
+                        "**/SCCS/**",
+                        "**/vssver.scc",
+                        "**/.svn",
+                        "**/.svn/**",
+                        "**/.git",
+                        "**/.git/**",
+                        "**/.gitattributes",
+                        "**/.gitignore",
+                        "**/.gitmodules",
+                        "**/.hg",
+                        "**/.hg/**",
+                        "**/.hgignore",
+                        "**/.hgsub",
+                        "**/.hgsubstate",
+                        "**/.hgtags",
+                        "**/.bzr",
+                        "**/.bzr/**",
+                        "**/.bzrignore",
+                        "**/.DS_Store"}}
+        });
+    }
+
+    @Parameterized.Parameter
+    public String targetName;
+
+    @Parameterized.Parameter(1)
+    public String[] expected;
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
@@ -45,126 +153,15 @@
         buildRule.executeTarget("cleanup");
     }
 
-    // Output the default excludes
     @Test
-    public void test1() {
-        String[] expected = {
-                          "**/*~",
-                          "**/#*#",
-                          "**/.#*",
-                          "**/%*%",
-                          "**/._*",
-                          "**/CVS",
-                          "**/CVS/**",
-                          "**/.cvsignore",
-                          "**/SCCS",
-                          "**/SCCS/**",
-                          "**/vssver.scc",
-                          "**/.svn",
-                          "**/.svn/**",
-                          "**/.git",
-                          "**/.git/**",
-                          "**/.gitattributes",
-                          "**/.gitignore",
-                          "**/.gitmodules",
-                          "**/.hg",
-                          "**/.hg/**",
-                          "**/.hgignore",
-                          "**/.hgsub",
-                          "**/.hgsubstate",
-                          "**/.hgtags",
-                          "**/.bzr",
-                          "**/.bzr/**",
-                          "**/.bzrignore",
-                          "**/.DS_Store"};
-        buildRule.getProject().executeTarget("test1");
-        assertArrayContentsEquals("current default excludes", expected, DirectoryScanner.getDefaultExcludes());
-    }
-
-    // adding something to the excludes'
-    @Test
-    public void test2() {
-        String[] expected = {
-                          "**/*~",
-                          "**/#*#",
-                          "**/.#*",
-                          "**/%*%",
-                          "**/._*",
-                          "**/CVS",
-                          "**/CVS/**",
-                          "**/.cvsignore",
-                          "**/SCCS",
-                          "**/SCCS/**",
-                          "**/vssver.scc",
-                          "**/.svn",
-                          "**/.svn/**",
-                          "**/.git",
-                          "**/.git/**",
-                          "**/.gitattributes",
-                          "**/.gitignore",
-                          "**/.gitmodules",
-                          "**/.hg",
-                          "**/.hg/**",
-                          "**/.hgignore",
-                          "**/.hgsub",
-                          "**/.hgsubstate",
-                          "**/.hgtags",
-                          "**/.bzr",
-                          "**/.bzr/**",
-                          "**/.bzrignore",
-                          "**/.DS_Store",
-                          "foo"};
-        buildRule.executeTarget("test2");
-        assertArrayContentsEquals("current default excludes", expected, DirectoryScanner.getDefaultExcludes());
-    }
-
-    // removing something from the defaults
-    @Test
-    public void test3() {
-        String[] expected = {
-                          "**/*~",
-                          "**/#*#",
-                          "**/.#*",
-                          "**/%*%",
-                          "**/._*",
-                          //CVS missing
-                          "**/CVS/**",
-                          "**/.cvsignore",
-                          "**/SCCS",
-                          "**/SCCS/**",
-                          "**/vssver.scc",
-                          "**/.svn",
-                          "**/.svn/**",
-                          "**/.git",
-                          "**/.git/**",
-                          "**/.gitattributes",
-                          "**/.gitignore",
-                          "**/.gitmodules",
-                          "**/.hg",
-                          "**/.hg/**",
-                          "**/.hgignore",
-                          "**/.hgsub",
-                          "**/.hgsubstate",
-                          "**/.hgtags",
-                          "**/.bzr",
-                          "**/.bzr/**",
-                          "**/.bzrignore",
-                          "**/.DS_Store"};
-        buildRule.executeTarget("test3");
-        assertArrayContentsEquals("current default excludes", expected, DirectoryScanner.getDefaultExcludes());
-    }
-
-    private void assertArrayContentsEquals(String message, String[] expected, String[] actual) {
+    public void test() {
+        buildRule.getProject().executeTarget(targetName);
+        String[] actual = DirectoryScanner.getDefaultExcludes();
         // check that both arrays have the same size
-        assertEquals(message + " : string array length match", expected.length, actual.length);
+        assertEquals("current default excludes: string array length match", expected.length, actual.length);
         for (String element : expected) {
-            boolean found = false;
-            for (int i = 0; !found && i < actual.length; i++) {
-                found |= element.equals(actual[i]);
-            }
-            assertTrue(message + " : didn't find element "
-                    + element + " in array match", found);
+            assertTrue("current default excludes: didn't find element " + element + " in array match",
+                    Arrays.asList(actual).contains(element));
         }
-
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DeleteTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DeleteTest.java
index 4d34341..99ccc71 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DeleteTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DeleteTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 /**
  */
 public class DeleteTest {
@@ -38,73 +36,86 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/delete.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO Assert exception message
     }
 
     @Test
     public void test2() {
         buildRule.executeTarget("test2");
     }
+
     //where oh where has my test case 3 gone?
     @Test
     public void test4() {
         buildRule.executeTarget("test4");
     }
+
     @Test
     public void test5() {
         buildRule.executeTarget("test5");
     }
+
     @Test
     public void test6() {
         buildRule.executeTarget("test6");
     }
+
     @Test
     public void test7() {
         buildRule.executeTarget("test7");
     }
+
     @Test
     public void test8() {
         buildRule.executeTarget("test8");
     }
+
     @Test
     public void test9() {
         buildRule.executeTarget("test9");
     }
+
     @Test
     public void test10() {
         buildRule.executeTarget("test10");
     }
+
     @Test
     public void test11() {
         buildRule.executeTarget("test11");
     }
+
     @Test
     public void test12() {
         buildRule.executeTarget("test12");
     }
+
     @Test
     public void test13() {
         buildRule.executeTarget("test13");
     }
+
     @Test
     public void test14() {
         buildRule.executeTarget("test14");
     }
+
     @Test
     public void test15() {
         buildRule.executeTarget("test15");
     }
+
     @Test
     public void test16() {
         buildRule.executeTarget("test16");
     }
+
     @Test
     public void test17() {
         buildRule.executeTarget("test17");
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DeltreeTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DeltreeTest.java
index b2dcc69..c85f6ab 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DeltreeTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DeltreeTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 public class DeltreeTest {
 
     @Rule
@@ -36,14 +34,13 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/deltree.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO Assert exception message
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DemuxOutputTask.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DemuxOutputTask.java
index e5e3b2f..581557d 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DemuxOutputTask.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DemuxOutputTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -54,7 +54,7 @@
 
     protected void handleOutput(String line) {
         line = line.trim();
-        if (line.length() != 0 && !line.equals(randomOutValue)) {
+        if (!line.isEmpty() && !line.equals(randomOutValue)) {
             String message = "Received = [" + line + "], expected = ["
                 + randomOutValue + "]";
             throw new BuildException(message);
@@ -64,7 +64,7 @@
 
     protected void handleErrorOutput(String line) {
         line = line.trim();
-        if (line.length() != 0 && !line.equals(randomErrValue)) {
+        if (!line.isEmpty() && !line.equals(randomErrValue)) {
             String message = "Received = [" + line + "], expected = ["
                 + randomErrValue + "]";
             throw new BuildException(message);
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DirnameTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DirnameTest.java
index d870348..3a0a4f3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DirnameTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DirnameTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,21 +19,27 @@
 package org.apache.tools.ant.taskdefs;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.taskdefs.condition.Os;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.File;
 
 /**
  */
 public class DirnameTest {
 
     @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
@@ -43,50 +49,39 @@
 
     @Test
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("Build exception should have been thrown as property attribute is required");
-        } catch (BuildException ex) {
-            assertEquals("property attribute required", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("property attribute required");
+        buildRule.executeTarget("test1");
     }
 
     @Test
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("Build exception should have been thrown as file attribute is required");
-        } catch (BuildException ex) {
-            assertEquals("file attribute required", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("file attribute required");
+        buildRule.executeTarget("test2");
     }
 
     @Test
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("Build exception should have been thrown as property attribute is required");
-        } catch (BuildException ex) {
-            assertEquals("property attribute required", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("property attribute required");
+        buildRule.executeTarget("test3");
     }
 
     @Test
     public void test4() {
-        Assume.assumeFalse("Test not possible on DOS or Netware family OS", Os.isFamily("netware") || Os.isFamily("dos"));
+        assumeFalse("Skip on DOS or Netware", Os.isFamily("netware") || Os.isFamily("dos"));
         buildRule.executeTarget("test4");
-        String filesep = System.getProperty("file.separator");
-        String expected = filesep + "usr" + filesep + "local";
-        String checkprop = buildRule.getProject().getProperty("local.dir");
-        assertEquals("dirname failed", expected, checkprop);
+        assertEquals("dirname failed", File.separator + "usr" + File.separator + "local",
+                buildRule.getProject().getProperty("local.dir"));
     }
 
     @Test
     public void test5() {
         buildRule.executeTarget("test5");
-        String expected = buildRule.getProject().getProperty("basedir");
-        String checkprop = buildRule.getProject().getProperty("base.dir");
-        assertEquals("dirname failed", expected, checkprop);
+        assertEquals("dirname failed",
+                buildRule.getProject().getProperty(MagicNames.PROJECT_BASEDIR),
+                buildRule.getProject().getProperty("base.dir"));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTask.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTask.java
index 0d4b6cd..fd257a4 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTask.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTest.java
index 615dd90..117efaf 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/DynamicTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/EchoTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/EchoTest.java
index 6f0c7a9..9c71eb9 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/EchoTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/EchoTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,13 +24,17 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.tools.ant.DefaultLogger;
 import org.apache.tools.ant.Project;
-import org.apache.tools.ant.util.FileUtils;
-import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
+import static org.apache.tools.ant.util.FileUtils.readFully;
 import static org.junit.Assert.assertEquals;
 
 /**
@@ -38,16 +42,25 @@
  */
 public class EchoTest {
 
-    private File removeThis;
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private EchoTestLogger logger;
+
+    private Echo echo;
+
+    @Before
+    public void setUp() {
+        Project p = new Project();
+        p.init();
+        logger = new EchoTestLogger();
+        p.addBuildListener(logger);
+        echo = new Echo();
+        echo.setProject(p);
+    }
 
     @Test
     public void testLogBlankEcho() {
-        Project p = new Project();
-        p.init();
-        EchoTestLogger logger = new EchoTestLogger();
-        p.addBuildListener(logger);
-        Echo echo = new Echo();
-        echo.setProject(p);
         echo.setTaskName("testLogBlankEcho");
         echo.execute();
         assertEquals("[testLogBlankEcho] ", logger.lastLoggedMessage);
@@ -55,29 +68,17 @@
 
     @Test
     public void testLogUTF8Echo() throws IOException {
-        Project p = new Project();
-        p.init();
-        EchoTestLogger logger = new EchoTestLogger();
-        p.addBuildListener(logger);
-        Echo echo = new Echo();
-        echo.setProject(p);
-        echo.setTaskName("testLogUTF8Echo");
-        echo.setMessage("\u00e4\u00a9");
-        removeThis = new File("abc.txt");
-        echo.setFile(removeThis);
-        echo.setEncoding("UTF-8");
-        echo.execute();
-        String x = FileUtils.readFully(new InputStreamReader(new FileInputStream(removeThis), "UTF-8"));
-        assertEquals(x,"\u00e4\u00a9");
-    }
+        File removeThis = folder.newFile("abc.txt");
+        Charset cs = StandardCharsets.UTF_8;
+        String msg = "\u00e4\u00a9";
 
-    @After
-    public void tearDown() {
-        if (removeThis != null && removeThis.exists()) {
-            if (!removeThis.delete()) {
-                removeThis.deleteOnExit();
-            }
-        }
+        echo.setTaskName("testLogUTF8Echo");
+        echo.setMessage(msg);
+        echo.setFile(removeThis);
+        echo.setEncoding(cs.name());
+        echo.execute();
+
+        assertEquals(msg, readFully(new InputStreamReader(new FileInputStream(removeThis), cs)));
     }
 
     private class EchoTestLogger extends DefaultLogger {
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/EchoXMLTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/EchoXMLTest.java
index cc9ec24..673dd57 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/EchoXMLTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/EchoXMLTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,15 +24,16 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 public class EchoXMLTest {
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/echoxml.xml");
@@ -50,22 +51,16 @@
 
     @Test
     public void testFail() {
-        try {
-            buildRule.executeTarget("testFail");
-            fail("BuildException expected: must fail");
-        } catch (BuildException ex) {
-            assertContains("${foo}=bar", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("${foo}=bar");
+        buildRule.executeTarget("testFail");
     }
 
     @Test
     public void testEmpty() {
-        try {
-            buildRule.executeTarget("testEmpty");
-            fail("BuildException expected: must fail");
-        } catch (BuildException ex) {
-            assertContains("No nested XML specified", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No nested XML specified");
+        buildRule.executeTarget("testEmpty");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecStreamRedirectorTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecStreamRedirectorTest.java
index 8a31d0b..b503db2 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecStreamRedirectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecStreamRedirectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,18 +17,19 @@
  */
 package org.apache.tools.ant.taskdefs;
 
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Arrays;
 
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -37,71 +38,65 @@
  */
 public class ExecStreamRedirectorTest {
 
-    private Project project;
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private File outputDir;
 
     @Before
-    public void setUp() throws Exception {
-        project = new Project();
-        project.init();
-        final File antFile = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/exec/exec-with-redirector.xml");
-        project.setUserProperty("ant.file", antFile.getAbsolutePath());
-        final File outputDir = this.createTmpDir();
-        project.setUserProperty("output", outputDir.toString());
-        ProjectHelper.configureProject(project, antFile);
-        project.executeTarget("setUp");
+    public void setUp() throws IOException {
+        buildRule.configureProject("src/etc/testcases/taskdefs/exec/exec-with-redirector.xml");
+        outputDir = folder.newFolder("temp-" + System.nanoTime());
+        buildRule.getProject().setUserProperty("output", outputDir.toString());
+        buildRule.executeTarget("setUp");
     }
 
     /**
      * Tests that the redirected streams of the exec'ed process aren't truncated.
      *
-     * @throws Exception
+     * @throws Exception if something goes wrong
      * @see <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=58451">bz-58451</a> and
      * <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=58833">bz-58833</a> for more details
      */
     @Test
     public void testRedirection() throws Exception {
-        final String dirToList = project.getProperty("dir.to.ls");
+        final String dirToList = buildRule.getProject().getProperty("dir.to.ls");
         assertNotNull("Directory to list isn't available", dirToList);
         assertTrue(dirToList + " is not a directory", new File(dirToList).isDirectory());
 
-        project.executeTarget("list-dir");
+        buildRule.executeTarget("list-dir");
 
         // verify the redirected output
-        final String outputDirPath = project.getProperty("output");
         byte[] dirListingOutput = null;
         for (int i = 1; i <= 16; i++) {
-            final File redirectedOutputFile = new File(outputDirPath, "ls" + i + ".txt");
-            assertTrue(redirectedOutputFile + " is missing or not a regular file", redirectedOutputFile.isFile());
+            final File redirectedOutputFile = new File(outputDir, "ls" + i + ".txt");
+            assertTrue(redirectedOutputFile + " is missing or not a regular file",
+                    redirectedOutputFile.isFile());
             final byte[] redirectedOutput = readAllBytes(redirectedOutputFile);
             assertNotNull("No content was redirected to " + redirectedOutputFile, redirectedOutput);
-            assertFalse("Content in redirected file " + redirectedOutputFile + " was empty", redirectedOutput.length == 0);
+            assertNotEquals("Content in redirected file " + redirectedOutputFile + " was empty",
+                    0, redirectedOutput.length);
             if (dirListingOutput != null) {
-                // compare the directory listing that was redirected to these files. all files should have the same content
-                assertTrue("Redirected output in file " + redirectedOutputFile +
-                        " doesn't match content in other redirected output file(s)", Arrays.equals(dirListingOutput, redirectedOutput));
+                // Compare the directory listing that was redirected to these files.
+                // All files should have the same content.
+                assertArrayEquals("Redirected output in file " + redirectedOutputFile +
+                        " doesn't match content in other redirected output file(s)", dirListingOutput, redirectedOutput);
             }
             dirListingOutput = redirectedOutput;
         }
     }
 
-    private File createTmpDir() {
-        final File tmpDir = new File(System.getProperty("java.io.tmpdir"), String.valueOf("temp-" + System.nanoTime()));
-        tmpDir.mkdir();
-        tmpDir.deleteOnExit();
-        return tmpDir;
-    }
-
     private static byte[] readAllBytes(final File file) throws IOException {
-        final FileInputStream fis = new FileInputStream(file);
         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        try {
+        try (FileInputStream fis = new FileInputStream(file)) {
             final byte[] dataChunk = new byte[1024];
             int numRead = -1;
             while ((numRead = fis.read(dataChunk)) > 0) {
                 bos.write(dataChunk, 0, numRead);
             }
-        } finally {
-            fis.close();
         }
         return bos.toByteArray();
     }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecTaskTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecTaskTest.java
index 95b2ca9..d77bd40 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecTaskTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,9 @@
 
 package org.apache.tools.ant.taskdefs;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNotNull;
 
 import java.io.File;
 import java.util.GregorianCalendar;
@@ -26,10 +28,10 @@
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.util.FileUtils;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -43,8 +45,6 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
-    private static final String BUILD_PATH = "src/etc/testcases/taskdefs/exec/";
-    private static final String BUILD_FILE = BUILD_PATH + "exec.xml";
     private static final int TIME_TO_WAIT = 1;
     /** maximum time allowed for the build in milliseconds */
     private static final int MAX_BUILD_TIME = 6000;
@@ -55,25 +55,23 @@
     /** Utilities used for file operations */
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-    private File logFile;
-    private MonitoredBuild myBuild = null;
     private volatile boolean buildFinished = false;
 
-
     @Before
     public void setUp() {
-        buildRule.configureProject(BUILD_FILE);
+        buildRule.configureProject("src/etc/testcases/taskdefs/exec/exec.xml");
     }
 
     @Test
     public void testspawn() throws InterruptedException {
         buildRule.getProject().executeTarget("setUp");
-        Assume.assumeNotNull(buildRule.getProject().getProperty("test.can.run"));
-        myBuild = new MonitoredBuild(new File(System.getProperty("root"), BUILD_FILE), "spawn");
-        logFile = FILE_UTILS.createTempFile("spawn", "log", new File(buildRule.getProject().getProperty("output")),
-                false, false);
+        assumeNotNull(buildRule.getProject().getProperty("test.can.run"));
+        MonitoredBuild myBuild = new MonitoredBuild(new File(
+                buildRule.getProject().getProperty(MagicNames.ANT_FILE)), "spawn");
+        File logFile = FILE_UTILS.createTempFile("spawn", "log",
+                new File(buildRule.getProject().getProperty("output")), false, false);
         // this is guaranteed by FileUtils#createTempFile
-        assertTrue("log file not existing", !logFile.exists());
+        assertFalse("log file not existing", logFile.exists());
         // make the spawned process run 1 seconds
         myBuild.setTimeToWait(TIME_TO_WAIT);
         myBuild.setLogFile(logFile.getAbsolutePath());
@@ -134,7 +132,7 @@
             this.target = target;
             project = new Project();
             project.init();
-            project.setUserProperty("ant.file", myBuildFile.getAbsolutePath());
+            project.setUserProperty(MagicNames.ANT_FILE, myBuildFile.getAbsolutePath());
             ProjectHelper.configureProject(project, myBuildFile);
         }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteJavaTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteJavaTest.java
index 06beab4..9e93f64 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteJavaTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteJavaTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,6 +26,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -54,7 +55,7 @@
         ej.setClasspath(cp);
     }
 
-    private Commandline getCommandline(int timetorun) throws Exception {
+    private Commandline getCommandline(int timetorun) {
         Commandline cmd = new Commandline();
         cmd.setExecutable(TimeProcess.class.getName());
         cmd.createArgument().setValue(String.valueOf(timetorun));
@@ -62,16 +63,16 @@
     }
 
     @Test
-    public void testNoTimeOut() throws Exception {
+    public void testNoTimeOut() {
         Commandline cmd = getCommandline(TIME_OUT / 2);
         ej.setJavaCommand(cmd);
         ej.execute(project);
-        assertTrue("process should not have been killed", !ej.killedProcess());
+        assertFalse("process should not have been killed", ej.killedProcess());
     }
 
     // test that the watchdog ends the process
     @Test
-    public void testTimeOut() throws Exception {
+    public void testTimeOut() {
         Commandline cmd = getCommandline(TIME_OUT * 2);
         ej.setJavaCommand(cmd);
         long now = System.currentTimeMillis();
@@ -88,16 +89,16 @@
     }
 
     @Test
-    public void testNoTimeOutForked() throws Exception {
+    public void testNoTimeOutForked() {
         Commandline cmd = getCommandline(TIME_OUT / 2);
         ej.setJavaCommand(cmd);
         ej.fork(cp);
-        assertTrue("process should not have been killed", !ej.killedProcess());
+        assertFalse("process should not have been killed", ej.killedProcess());
     }
 
     // test that the watchdog ends the process
     @Test
-    public void testTimeOutForked() throws Exception {
+    public void testTimeOutForked() {
         Commandline cmd = getCommandline(TIME_OUT * 2);
         ej.setJavaCommand(cmd);
         long now = System.currentTimeMillis();
@@ -114,13 +115,13 @@
     }
 
     /**
-     * Dangerous method to obtain the classpath for the test. This is
-     * severely tighted to the build.xml properties.
+     * Dangerous method to obtain the classpath for the test.
+     * This is severely dependent on the build.xml properties.
      */
     private static String getTestClassPath() {
-        String classpath = System.getProperty("build.tests");
+        String classpath = System.getProperty("build.tests.value");
         if (classpath == null) {
-            System.err.println("WARNING: 'build.tests' property is not available!");
+            System.err.println("WARNING: 'build.tests.value' property is not available!");
             classpath = System.getProperty("java.class.path");
         }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteWatchdogTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteWatchdogTest.java
index b557e76..190b650 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteWatchdogTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ExecuteWatchdogTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,14 +20,16 @@
 
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.util.JavaEnvUtils;
+import org.junit.AssumptionViolatedException;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.internal.AssumptionViolatedException;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -54,9 +56,9 @@
      * severely tied to the build.xml properties.
      */
     private static String getTestClassPath() {
-        String classpath = System.getProperty("build.tests");
+        String classpath = System.getProperty("build.tests.value");
         if (classpath == null) {
-            System.err.println("WARNING: 'build.tests' property is not available!");
+            System.err.println("WARNING: 'build.tests.value' property is not available!");
             classpath = System.getProperty("java.class.path");
         }
 
@@ -72,21 +74,16 @@
         return Runtime.getRuntime().exec(cmdArray);
     }
 
-    private String getErrorOutput(Process p) throws Exception {
+    private String getErrorOutput(Process p) {
         BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
-        StringBuilder buf = new StringBuilder();
-        String line;
-        while ((line = err.readLine()) != null) {
-            buf.append(line);
-        }
-        return buf.toString();
+        return err.lines().collect(Collectors.joining());
     }
 
     private int waitForEnd(Process p) throws Exception {
         int retcode = p.waitFor();
         if (retcode != 0) {
             String err = getErrorOutput(p);
-            if (err.length() > 0) {
+            if (!err.isEmpty()) {
                 System.err.println("ERROR:");
                 System.err.println(err);
             }
@@ -126,8 +123,8 @@
         Process process = getProcess(-1); // process should abort
         watchdog.start(process);
         int retCode = process.waitFor();
-        assertTrue("process should not have been killed", !watchdog.killedProcess());
-        assertTrue("return code is invalid: " + retCode, retCode!=0);
+        assertFalse("process should not have been killed", watchdog.killedProcess());
+        assertNotEquals("return code is invalid: " + retCode, 0, retCode);
     }
 
     @Test
@@ -136,16 +133,14 @@
         watchdog.start(process);
 
         // I assume that starting this takes less than TIME_OUT/2 ms...
-        Thread thread = new Thread(){
-                public void run(){
-                    try {
-                        process.waitFor();
-                    } catch(InterruptedException e){
-                        // not very nice but will do the job
-                        throw new AssumptionViolatedException("process interrupted in thread", e);
-                    }
-                }
-        };
+        Thread thread = new Thread(() -> {
+            try {
+                process.waitFor();
+            } catch (InterruptedException e) {
+                // not very nice but will do the job
+                throw new AssumptionViolatedException("process interrupted in thread", e);
+            }
+        });
         thread.start();
 
         // wait for TIME_OUT / 2, there should be about TIME_OUT / 2 ms remaining before timeout
@@ -159,6 +154,6 @@
 
         // process should be dead and well finished
         assertEquals(0, process.exitValue());
-        assertTrue("process should not have been killed", !watchdog.killedProcess());
+        assertFalse("process should not have been killed", watchdog.killedProcess());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/FailTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/FailTest.java
index 34299d5..726d792 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/FailTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/FailTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,17 +23,18 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.util.Arrays;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
 /**
  */
 public class FailTest {
 
     @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
     @Before
@@ -43,57 +44,42 @@
 
     @Test
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("No message", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No message");
+        buildRule.executeTarget("test1");
     }
 
     @Test
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("test2", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("test2");
+        buildRule.executeTarget("test2");
     }
 
     @Test
     public void testText() {
-        try {
-            buildRule.executeTarget("testText");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("testText", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("testText");
+        buildRule.executeTarget("testText");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testIf() {
         buildRule.executeTarget("testIf");
         buildRule.getProject().setProperty("foo", "");
-        try {
-            buildRule.executeTarget("testIf");
-            fail("testIf must fail if foo has been set");
-        } catch (BuildException ex) {
-            //TODO assert result
-        }
+        buildRule.executeTarget("testIf");
+        // TODO assert result
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testUnless() {
         try {
             buildRule.executeTarget("testUnless");
-            fail("testUnless must fail unless foo has been set");
-        } catch (BuildException ex) {
-            //TODO assert rules
+            // TODO assert rules
+        } finally {
+            buildRule.getProject().setProperty("foo", "");
+            buildRule.executeTarget("testUnless");
         }
-        buildRule.getProject().setProperty("foo", "");
-        buildRule.executeTarget("testUnless");
-
     }
 
     /**
@@ -103,18 +89,18 @@
      */
     @Test
     public void testIfAndUnless() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("if=if and unless=unless");
         //neither
         buildRule.executeTarget("testIfAndUnless");
         buildRule.getProject().setProperty("if", "");
         try {
             buildRule.executeTarget("testIfAndUnless");
-            fail("expect fail on defined(if)");
-        } catch (BuildException ex) {
-            assertEquals("if=if and unless=unless", ex.getMessage());
+        } finally {
+            buildRule.getProject().setProperty("unless", "");
+            //this call should succeed as unless overrides if
+            buildRule.executeTarget("testIfAndUnless");
         }
-        buildRule.getProject().setProperty("unless", "");
-        //this call should succeed as unless overrides if
-        buildRule.executeTarget("testIfAndUnless");
     }
     /**
      * see that the different combinations work, and
@@ -129,12 +115,9 @@
 
     @Test
     public void testNested1() {
-        try {
-            buildRule.executeTarget("testNested1");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("condition satisfied", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("condition satisfied");
+        buildRule.executeTarget("testNested1");
     }
 
     @Test
@@ -144,64 +127,46 @@
 
     @Test
     public void testNested3() {
-        try {
-            buildRule.executeTarget("testNested3");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("testNested3", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("testNested3");
+        buildRule.executeTarget("testNested3");
     }
 
     @Test
     public void testNested4() {
-        String specificMessage = "Nested conditions "
-          + "not permitted in conjunction with if/unless attributes";
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Nested conditions not permitted in conjunction with if/unless attributes");
 
         StringBuilder target = new StringBuilder("testNested4x");
         for (char ch : Arrays.asList('a', 'b', 'c')) {
             target.setCharAt(target.length() - 1, ch);
-            try {
-                buildRule.executeTarget(target.toString());
-                fail("it is required to fail :-)");
-            } catch (BuildException ex) {
-                assertEquals(specificMessage, ex.getMessage());
-            }
+            buildRule.executeTarget(target.toString());
         }
     }
 
     @Test
     public void testNested5() {
-        try {
-            buildRule.executeTarget("testNested5");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("Only one nested condition is allowed.", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Only one nested condition is allowed.");
+        buildRule.executeTarget("testNested5");
     }
 
     @Test
     public void testNested6() {
-        try {
-            buildRule.executeTarget("testNested6");
-            fail("it is required to fail :-)");
-        } catch (BuildException ex) {
-            assertEquals("testNested6\ntestNested6\ntestNested6", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("testNested6\ntestNested6\ntestNested6");
+        buildRule.executeTarget("testNested6");
     }
 
     @Test
     public void testNested7() {
-        String specificMessage = "A single nested condition is required.";
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("A single nested condition is required.");
 
         StringBuilder target = new StringBuilder("testNested7x");
         for (char ch : Arrays.asList('a', 'b')) {
             target.setCharAt(target.length() - 1, ch);
-            try {
-                buildRule.executeTarget(target.toString());
-                fail("it is required to fail :-)");
-            } catch (BuildException ex) {
-                assertEquals(specificMessage, ex.getMessage());
-            }
+            buildRule.executeTarget(target.toString());
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/FilterTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/FilterTest.java
index 0e40ad8..6a01d02 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/FilterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/FilterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,6 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 
@@ -32,9 +31,9 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-
 public class FilterTest {
 
     @Rule
@@ -50,34 +49,22 @@
         buildRule.executeTarget("cleanup");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert value
     }
 
     @Test
@@ -122,24 +109,15 @@
     }
 
     private String getFilteredFile(String testNumber, String filteredFile) {
-
         String line = null;
         File f = new File(buildRule.getProject().getBaseDir(), filteredFile);
-        if (!f.exists()) {
-            fail("filter test" + testNumber + " failed");
-        } else {
-            BufferedReader in = null;
-            try {
-                in = new BufferedReader(new FileReader(f));
-            } catch (FileNotFoundException fnfe) {
-                fail("filter test" + testNumber + " failed, filtered file: " + f.toString() + " not found");
-            }
-            try {
-                line = in.readLine();
-                in.close();
-            } catch (IOException ioe) {
-                fail("filter test" + testNumber + " failed.  IOException while reading filtered file: " + ioe);
-            }
+        assertTrue("filter test" + testNumber + " failed", f.exists());
+
+        try (BufferedReader in = new BufferedReader(new FileReader(f))) {
+            line = in.readLine();
+        } catch (IOException ioe) {
+            fail("filter test" + testNumber
+                 + " failed.  IOException while reading filtered file: " + ioe);
         }
         f.delete();
         return line;
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/FixCrLfTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/FixCrLfTest.java
index 258688d..8ca75a4 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/FixCrLfTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/FixCrLfTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,21 +20,21 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
 
 import junit.framework.AssertionFailedError;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 /**
  */
@@ -43,119 +43,119 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/fixcrlf/build.xml");
     }
 
     @Test
-    public void test1() throws IOException {
+    public void test1() {
         buildRule.executeTarget("test1");
     }
 
     @Test
-    public void test2() throws IOException {
+    public void test2() {
         buildRule.executeTarget("test2");
     }
 
     @Test
-    public void test3() throws IOException {
+    public void test3() {
         buildRule.executeTarget("test3");
     }
 
     @Test
-    public void test4() throws IOException {
+    public void test4() {
         buildRule.executeTarget("test4");
     }
 
     @Test
-    public void test5() throws IOException {
+    public void test5() {
         buildRule.executeTarget("test5");
     }
 
     @Test
-    public void test6() throws IOException {
+    public void test6() {
         buildRule.executeTarget("test6");
     }
 
     @Test
-    public void test7() throws IOException {
+    public void test7() {
         buildRule.executeTarget("test7");
     }
 
     @Test
-    public void test8() throws IOException {
+    public void test8() {
         buildRule.executeTarget("test8");
     }
 
     @Test
-    public void test9() throws IOException {
+    public void test9() {
         buildRule.executeTarget("test9");
     }
 
     @Test
-    public void testMacLines() throws IOException {
+    public void testMacLines() {
         buildRule.executeTarget("testMacLines");
     }
 
     @Test
-    public void testNoOverwrite() throws IOException {
+    public void testNoOverwrite() {
         buildRule.executeTarget("testNoOverwrite");
     }
 
     @Test
-    public void testEncoding() throws IOException {
+    public void testEncoding() {
         buildRule.executeTarget("testEncoding");
     }
 
     @Test
-    public void testOutputEncoding() throws IOException {
+    public void testOutputEncoding() {
         buildRule.executeTarget("testOutputEncoding");
     }
 
     @Test
-    public void testLongLines() throws IOException {
+    public void testLongLines() {
         buildRule.executeTarget("testLongLines");
     }
 
     @Test
-    public void testCrCrLfSequenceUnix() throws IOException {
+    public void testCrCrLfSequenceUnix() {
         buildRule.executeTarget("testCrCrLfSequence-unix");
     }
 
     @Test
-    public void testCrCrLfSequenceDos() throws IOException {
+    public void testCrCrLfSequenceDos() {
         buildRule.executeTarget("testCrCrLfSequence-dos");
     }
 
     @Test
-    public void testCrCrLfSequenceMac() throws IOException {
+    public void testCrCrLfSequenceMac() {
         buildRule.executeTarget("testCrCrLfSequence-mac");
     }
 
     @Test
-    public void testFixlastDos() throws IOException {
+    public void testFixlastDos() {
         buildRule.executeTarget("testFixlastDos");
     }
 
     @Test
-    public void testFixlastFalseMac() throws IOException {
+    public void testFixlastFalseMac() {
         buildRule.executeTarget("testFixlastFalseMac");
     }
 
     @Test
-    public void testFixFile() throws Exception {
+    public void testFixFile() {
         buildRule.executeTarget("testFixFile");
     }
 
     @Test
-    public void testFixFileExclusive() throws Exception {
-        try {
-            buildRule.executeTarget("testFixFileExclusive");
-            fail(FixCRLF.ERROR_FILE_AND_SRCDIR);
-        } catch (BuildException ex) {
-            AntAssert.assertContains(FixCRLF.ERROR_FILE_AND_SRCDIR, ex.getMessage());
-        }
+    public void testFixFileExclusive() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(FixCRLF.ERROR_FILE_AND_SRCDIR);
+        buildRule.executeTarget("testFixFileExclusive");
     }
 
     /**
@@ -231,17 +231,11 @@
 
     // not used, but public so theoretically must remain for BC?
     @Deprecated
-    public void assertEqualContent(File expect, File result)
-        throws AssertionFailedError, IOException {
-        if (!result.exists()) {
-            fail("Expected file " + result + " doesn\'t exist");
-        }
+    public void assertEqualContent(File expect, File result) throws AssertionFailedError, IOException {
+        assertTrue("Expected file " + result + " doesn't exist", result.exists());
 
-        InputStream inExpect = null;
-        InputStream inResult = null;
-        try {
-            inExpect = new BufferedInputStream(new FileInputStream(expect));
-            inResult = new BufferedInputStream(new FileInputStream(result));
+        try (InputStream inExpect = new BufferedInputStream(Files.newInputStream(expect.toPath()));
+             InputStream inResult = new BufferedInputStream(Files.newInputStream(result.toPath()))) {
 
             int expectedByte = inExpect.read();
             while (expectedByte != -1) {
@@ -249,13 +243,6 @@
                 expectedByte = inExpect.read();
             }
             assertEquals("End of file", -1, inResult.read());
-        } finally {
-            if (inResult != null) {
-                inResult.close();
-            }
-            if (inExpect != null) {
-                inExpect.close();
-            }
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/GUnzipTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/GUnzipTest.java
index a7aac5d..2a73800 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/GUnzipTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/GUnzipTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,7 +28,6 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 public class GUnzipTest {
 
@@ -45,24 +44,22 @@
         buildRule.executeTarget("cleanup");
     }
 
-    @Test
+    /**
+     * Expected failure due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to invalid attribute
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("attribute src invalid");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO Assert exception message
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/GetTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/GetTest.java
index 3e1157d..407cc57 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/GetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/GetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,13 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -34,6 +39,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/get.xml");
@@ -44,54 +52,49 @@
         buildRule.executeTarget("cleanup");
     }
 
-    @Test
+    /**
+     * Fail due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to invalid src argument
+     */
+    @Test(expected = BuildException.class)
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("src invalid");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to invalid dest argument or no HTTP server on localhost
+     */
+    @Test(expected = BuildException.class)
     public void test5() {
-        try {
-            buildRule.executeTarget("test5");
-            fail("dest invalid (or no http-server on local machine");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test5");
+        // TODO assert value
     }
 
     @Test
@@ -99,13 +102,17 @@
         buildRule.executeTarget("test6");
     }
 
+    /**
+     * Fail due to null or empty userAgent argument
+     */
     @Test
     public void test7() {
+        thrown.expect(BuildException.class);
         try {
             buildRule.executeTarget("test7");
-            fail("userAgent may not be null or empty");
-        } catch (BuildException ex) {
-            //TODO assert value
+        } finally {
+            // post-mortem
+            assertThat(buildRule.getLog(), not(containsString("Adding header")));
         }
     }
 
@@ -119,4 +126,34 @@
         buildRule.executeTarget("testUseTomorrow");
     }
 
+    @Test
+    public void testTwoHeadersAreAddedOK() {
+        buildRule.executeTarget("testTwoHeadersAreAddedOK");
+        assertThat(buildRule.getLog(), both(containsString("Adding header 'header1'"))
+                        .and(containsString("Adding header 'header2'")));
+    }
+
+    @Test
+    public void testEmptyHeadersAreNeverAdded() {
+        buildRule.executeTarget("testEmptyHeadersAreNeverAdded");
+        assertThat(buildRule.getLog(), not(containsString("Adding header")));
+    }
+
+    @Test
+    public void testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded() {
+        buildRule.executeTarget("testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded");
+        String log = buildRule.getLog();
+        assertThat(log, containsString("Adding header 'header1'"));
+
+        int actualHeaderCount = log.split("Adding header ").length - 1;
+
+        assertEquals("Only one header has been added", 1, actualHeaderCount);
+    }
+
+    @Test
+    public void testHeaderSpaceTrimmed() {
+        buildRule.executeTarget("testHeaderSpaceTrimmed");
+        assertThat(buildRule.getLog(), containsString("Adding header 'header1'"));
+    }
+
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/GzipTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/GzipTest.java
index 76342b8..da182ec 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/GzipTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/GzipTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,9 +24,11 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -35,60 +37,58 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/gzip.xml");
     }
 
-    @Test
+    /**
+     * Fail due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to zipfile pointing to a directory
+     */
+    @Test(expected = BuildException.class)
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException expected: zipfile must not point to a directory");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
+        // TODO assert value
     }
 
     @Test
     public void testGZip() {
         buildRule.executeTarget("realTest");
         String log = buildRule.getLog();
-        assertTrue("Expecting message starting with 'Building:' but got '"
-            + log + "'", log.startsWith("Building:"));
-        assertTrue("Expecting message ending with 'asf-logo.gif.gz' but got '"
-            + log + "'", log.endsWith("asf-logo.gif.gz"));
+        assertThat("Expecting message starting with 'Building:' but got '"
+                + log + "'", log, startsWith("Building:"));
+        assertThat("Expecting message ending with 'asf-logo.gif.gz' but got '"
+                + log + "'", log, endsWith("asf-logo.gif.gz"));
     }
 
     @Test
@@ -100,9 +100,8 @@
     public void testDateCheck() {
         buildRule.executeTarget("testDateCheck");
         String log = buildRule.getLog();
-        assertTrue(
-            "Expecting message ending with 'asf-logo.gif.gz is up to date.' but got '" + log + "'",
-            log.endsWith("asf-logo.gif.gz is up to date."));
+        assertThat("Expecting message ending with 'asf-logo.gif.gz is up to date.' but got '"
+                + log + "'", log, endsWith("asf-logo.gif.gz is up to date."));
     }
 
     @After
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ImportTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ImportTest.java
index 40a52cd..b874033 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ImportTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ImportTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,34 +18,36 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasProperty;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
-import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
-import org.apache.tools.ant.Location;
 import org.apache.tools.ant.Project;
-import org.junit.Assume;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 public class ImportTest {
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void testSimpleImport() {
         buildRule.configureProject("src/etc/testcases/taskdefs/import/import.xml");
-        assertContains("Before importIn imported topAfter import", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Before importIn imported topAfter import"));
     }
 
     @Test
@@ -53,16 +55,15 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/import/unnamedImport.xml",
                          Project.MSG_WARN);
         String log = buildRule.getLog();
-        assertTrue("Warnings logged when not expected: " + log,
-                    log.length() == 0);
+        assertEquals("Warnings logged when not expected: " + log, 0, log.length());
     }
 
     @Test
     public void testSerial() {
         buildRule.configureProject("src/etc/testcases/taskdefs/import/subdir/serial.xml");
-        assertContains("Unnamed2.xmlUnnamed1.xml", buildRule.getLog());
-        assertContains("Expected string was not found in log",
-                "Skipped already imported file", buildRule.getFullLog());
+        assertThat(buildRule.getLog(), containsString("Unnamed2.xmlUnnamed1.xml"));
+        assertThat("Expected string was not found in log",
+                buildRule.getFullLog(), containsString("Skipped already imported file"));
     }
 
     // allow this as imported in targets are only tested when a target is run
@@ -85,15 +86,10 @@
 
     @Test
     public void testImportInTargetNotAllowed() {
-        buildRule.configureProject(
-            "src/etc/testcases/taskdefs/import/subdir/importintarget.xml");
-        try {
-            buildRule.executeTarget("do-import");
-            fail("Build exception should have been thrown as import only allowed in top level task");
-        } catch (BuildException ex) {
-            assertContains("not a top level task", "import only allowed as a top-level task",
-                    ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("import only allowed as a top-level task");
+        buildRule.configureProject("src/etc/testcases/taskdefs/import/subdir/importintarget.xml");
+        buildRule.executeTarget("do-import");
     }
 
     @Test
@@ -107,31 +103,18 @@
 
     @Test
     public void testImportSameTargets() {
-        try {
-            buildRule.configureProject(
-                "src/etc/testcases/taskdefs/import/same_target.xml");
-            fail("Expected build exception");
-        } catch (BuildException ex) {
-            assertContains("Message did not contain expected contents", "Duplicate target",
-                    ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Duplicate target");
+        buildRule.configureProject("src/etc/testcases/taskdefs/import/same_target.xml");
     }
 
     @Test
     public void testImportError() {
-        try {
-            buildRule.configureProject(
-                "src/etc/testcases/taskdefs/import/import_bad_import.xml");
-            fail("Build exception should have been thrown");
-        } catch (BuildException ex) {
-            Location lo = ex.getLocation();
-            assertNotNull(
-                "expected location of build exception to be set", lo);
-            assertContains(
-                "expected location to contain calling file", "import_bad_import.xml", lo.getFileName());
-            assertContains(
-                "expected message of ex to contain called file", "bad.xml", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("bad.xml");
+        thrown.expect(hasProperty("location",
+                hasProperty("fileName", containsString("import_bad_import.xml"))));
+        buildRule.configureProject("src/etc/testcases/taskdefs/import/import_bad_import.xml");
     }
 
     @Test
@@ -140,23 +123,17 @@
         if (!new File(ln).exists()) {
             ln = "/bin/ln";
         }
-        Assume.assumeTrue("Current system does not support Symlinks", new File(ln).exists());
-        String symlink = "src/etc/testcases/taskdefs/import/symlinks/d3b";
-        File symlinkFile = new File(System.getProperty("root"), symlink);
-        if (Runtime.getRuntime().exec(new String[] {ln, "-s", "d3a", symlinkFile.getAbsolutePath()}).waitFor() != 0) {
-            throw new IOException("'" + ln + " -s d3a " + symlink + "' failed");
-        }
+        assumeTrue("Current system does not support Symlinks", new File(ln).exists());
+        buildRule.configureProject("src/etc/testcases/taskdefs/import/import.xml");
+        File symlinkFile = buildRule.getProject().resolveFile("symlinks/d3b");
+        assertEquals("'" + ln + " -s d3a " + symlinkFile.getAbsolutePath() + "' failed",
+                Runtime.getRuntime().exec(new String[] {ln, "-s", "d3a", symlinkFile.getAbsolutePath()}).waitFor(), 0);
         try {
-            buildRule.configureProject(
-                "src/etc/testcases/taskdefs/import/symlinks/d1/p1.xml");
-            assertEquals(
-                buildRule.getProject().getProperty("ant.file.p2"),
-                new File(System.getProperty("root"), "src/etc/testcases/taskdefs/import/symlinks/d2/p2.xml")
-                .getAbsolutePath());
-            assertEquals(
-                buildRule.getProject().getProperty("ant.file.p3"),
-                new File(System.getProperty("root"), "src/etc/testcases/taskdefs/import/symlinks/d3b/p3.xml")
-                .getAbsolutePath());
+            buildRule.configureProject("src/etc/testcases/taskdefs/import/symlinks/d1/p1.xml");
+            assertEquals(buildRule.getProject().getProperty("ant.file.p2"),
+                buildRule.getProject().resolveFile("../d2/p2.xml").getAbsolutePath());
+            assertEquals(buildRule.getProject().getProperty("ant.file.p3"),
+                    buildRule.getProject().resolveFile("../d3b/p3.xml").getAbsolutePath());
         } finally {
             symlinkFile.delete();
         }
@@ -165,7 +142,8 @@
     @Test
     public void testTargetFirst() {
         buildRule.configureProject("src/etc/testcases/taskdefs/import/importtargetfirst.xml");
-        assertContains("Importing targetfirstAfter target firstAfter importing", buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("Importing targetfirstAfter target firstAfter importing"));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/InitializeClassTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/InitializeClassTest.java
index a44303f..75e8e81 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/InitializeClassTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/InitializeClassTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,6 +31,7 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 /**
  * Test to see if static initializers are invoked the same way
@@ -42,13 +43,15 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
-    private File f1 = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/forkedout");
-    private File f2 = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/unforkedout");
-
+    private File f1;
+    private File f2;
 
     @Before
     public void setUp() {
+        assertNotNull("build.tests.value not set", System.getProperty("build.tests.value"));
         buildRule.configureProject("src/etc/testcases/taskdefs/initializeclass.xml");
+        f1 = buildRule.getProject().resolveFile("forkedout");
+        f2 = buildRule.getProject().resolveFile("unforkedout");
     }
 
     @Test
@@ -56,15 +59,12 @@
         buildRule.executeTarget("forked");
         synchronized (System.out) {
             PrintStream ps = System.out;
-            PrintStream newps = new PrintStream(new FileOutputStream(f2));
-             try {
-                 System.setOut(newps);
-                 buildRule.getProject().executeTarget("unforked");
-             } finally {
-                 System.setOut(ps);
-
-                 newps.close();
-             }
+            try (PrintStream newps = new PrintStream(new FileOutputStream(f2))) {
+                System.setOut(newps);
+                buildRule.getProject().executeTarget("unforked");
+            } finally {
+                System.setOut(ps);
+            }
         }
         assertEquals(FileUtilities.getFileContents(f1), FileUtilities.getFileContents(f2));
     }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/InputTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/InputTest.java
index 4b6efaa..383eaf3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/InputTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/InputTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,26 +29,25 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
 
 public class InputTest {
 
     @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
     private InputStream originalStdIn;
 
-
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/input.xml");
-        System.getProperties()
-            .put(PropertyFileInputHandler.FILE_NAME_KEY,
-                 buildRule.getProject().resolveFile("input.properties")
-                 .getAbsolutePath());
+        System.getProperties().put(PropertyFileInputHandler.FILE_NAME_KEY,
+                buildRule.getProject().resolveFile("input.properties").getAbsolutePath());
         buildRule.getProject().setInputHandler(new PropertyFileInputHandler());
         originalStdIn = System.in;
     }
@@ -70,13 +69,9 @@
 
     @Test
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: invalid input");
-        } catch (BuildException ex) {
-             assertEquals("Found invalid input test for 'All data is going to be deleted from DB continue?'",
-                     ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Found invalid input test for 'All data is going to be deleted from DB continue?'");
+        buildRule.executeTarget("test3");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java
index 402979c..21cdd68 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.IOException;
-import java.io.Reader;
-import java.util.Enumeration;
+import java.nio.charset.StandardCharsets;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -33,17 +32,19 @@
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.FileUtilities;
 import org.apache.tools.ant.util.FileUtils;
-import org.junit.After;
-import org.junit.Assume;
+import org.apache.tools.ant.util.StreamUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 /**
  */
@@ -52,11 +53,11 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private static String tempJar = "tmp.jar";
     private static String tempDir = "jartmp/";
-    private Reader r1;
-    private Reader r2;
-
 
     @Before
     public void setUp() {
@@ -64,50 +65,31 @@
         buildRule.executeTarget("setUp");
     }
 
-    @After
-    public void tearDown() {
-        if (r1 != null) {
-            try {
-                r1.close();
-            } catch (IOException e) {
-            }
-        }
-        if (r2 != null) {
-            try {
-                r2.close();
-            } catch (IOException e) {
-            }
-        }
-    }
-
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to nonexistent manifest file
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: manifest file does not exist");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to unrecognized whenempty attribute: format C: /y
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: Unrecognized whenempty attribute: format C: /y");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert exception message
     }
 
     private File getOutputDir() {
@@ -118,7 +100,6 @@
     public void test4() {
         buildRule.executeTarget("test4");
         File jarFile = new File(getOutputDir(), tempJar);
-
         assertTrue(jarFile.exists());
     }
 
@@ -137,7 +118,7 @@
         File jarFile = new File(getOutputDir(), tempJar);
 
         // move the modified date back a couple of seconds rather than delay the test on each run
-        Assume.assumeTrue(jarFile.setLastModified(jarFile.lastModified()
+        assumeTrue(jarFile.setLastModified(jarFile.lastModified()
                 - FileUtils.getFileUtils().getFileTimestampGranularity() * 3));
         long jarModifiedDate = jarFile.lastModified();
 
@@ -158,14 +139,12 @@
 
     @Test
     public void testRecreateWithoutUpdateNewerFile() {
-        testRecreate("testRecreateNewerFileSetup",
-                     "testRecreateWithoutUpdateNewerFile");
+        testRecreate("testRecreateNewerFileSetup", "testRecreateWithoutUpdateNewerFile");
     }
 
     @Test
     public void testRecreateWithUpdateNewerFile() {
-        testRecreate("testRecreateNewerFileSetup",
-                     "testRecreateWithUpdateNewerFile");
+        testRecreate("testRecreateNewerFileSetup", "testRecreateWithUpdateNewerFile");
     }
 
     private void testRecreate(String firstTarget, String secondTarget) {
@@ -181,22 +160,24 @@
         long jarModifiedDate = jarFile.lastModified();
         buildRule.executeTarget(secondTarget);
         jarFile = new File(getOutputDir(), tempJar);
-        assertTrue("jar has been recreated in " + secondTarget,
-                   jarModifiedDate < jarFile.lastModified());
+        assertTrue("jar has been recreated in " + secondTarget, jarModifiedDate < jarFile.lastModified());
     }
 
     @Test
-    public void testManifestStaysIntact()
-        throws IOException, ManifestException {
+    public void testManifestStaysIntact() throws IOException, ManifestException {
         buildRule.executeTarget("testManifestStaysIntact");
 
-        r1 = new FileReader(new File(getOutputDir(),
-                            tempDir + "manifest"));
-        r2 = new FileReader(new File(getOutputDir(),
-                tempDir + "META-INF/MANIFEST.MF"));
+        Manifest mf1;
+        try (FileReader r1 = new FileReader(new File(getOutputDir(), tempDir + "manifest"))) {
+            mf1 = new Manifest(r1);
+        }
 
-        Manifest mf1 = new Manifest(r1);
-        Manifest mf2 = new Manifest(r2);
+        Manifest mf2;
+        try (FileReader r2 = new FileReader(new File(getOutputDir(), tempDir
+                + "META-INF/MANIFEST.MF"))) {
+            mf2 = new Manifest(r2);
+        }
+
         assertEquals(mf1, mf2);
     }
 
@@ -222,26 +203,22 @@
 
     @Test
     public void testRecreateZipfilesetWithoutUpdateAdditionalFiles() {
-        testRecreate("test4",
-                     "testRecreateZipfilesetWithoutUpdateAdditionalFiles");
+        testRecreate("test4", "testRecreateZipfilesetWithoutUpdateAdditionalFiles");
     }
 
     @Test
     public void testRecreateZipfilesetWithUpdateAdditionalFiles() {
-        testRecreate("test4",
-                     "testRecreateZipfilesetWithUpdateAdditionalFiles");
+        testRecreate("test4", "testRecreateZipfilesetWithUpdateAdditionalFiles");
     }
 
     @Test
     public void testRecreateZipfilesetWithoutUpdateNewerFile() {
-        testRecreate("testRecreateNewerFileSetup",
-                     "testRecreateZipfilesetWithoutUpdateNewerFile");
+        testRecreate("testRecreateNewerFileSetup", "testRecreateZipfilesetWithoutUpdateNewerFile");
     }
 
     @Test
     public void testRecreateZipfilesetWithUpdateNewerFile() {
-        testRecreate("testRecreateNewerFileSetup",
-                     "testRecreateZipfilesetWithUpdateNewerFile");
+        testRecreate("testRecreateNewerFileSetup", "testRecreateZipfilesetWithUpdateNewerFile");
     }
 
     @Test
@@ -261,116 +238,219 @@
     // bugzilla report 10262
     @Test
     public void testNoDuplicateIndex() throws IOException {
-        ZipFile archive = null;
-        try {
-            buildRule.executeTarget("testIndexTests");
-            archive = new ZipFile(new File(getOutputDir(), tempJar));
-            Enumeration e = archive.entries();
-            int numberOfIndexLists = 0;
-            while (e.hasMoreElements()) {
-                ZipEntry ze = (ZipEntry) e.nextElement();
-                if (ze.getName().equals("META-INF/INDEX.LIST")) {
-                    numberOfIndexLists++;
-                }
-            }
-            assertEquals(1, numberOfIndexLists);
-        } finally {
-            if (archive != null) {
-                archive.close();
-            }
+        buildRule.executeTarget("testIndexTests");
+        try (ZipFile archive = new ZipFile(new File(getOutputDir(), tempJar))) {
+            assertEquals(1, StreamUtils.enumerationAsStream(archive.entries())
+                    .filter(ze -> ze.getName().equals("META-INF/INDEX.LIST")).count());
         }
     }
 
     // bugzilla report 16972
     @Test
     public void testRootFilesInIndex() throws IOException {
-        ZipFile archive = null;
-        try {
-            buildRule.executeTarget("testIndexTests");
-            archive = new ZipFile(new File(getOutputDir(), tempJar));
+        buildRule.executeTarget("testIndexTests");
+        try (ZipFile archive = new ZipFile(new File(getOutputDir(), tempJar))) {
             ZipEntry ze = archive.getEntry("META-INF/INDEX.LIST");
             InputStream is = archive.getInputStream(ze);
-            BufferedReader r = new BufferedReader(new InputStreamReader(is,
-                                                                        "UTF8"));
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+            boolean foundArchive = false;
             boolean foundSub = false;
             boolean foundSubFoo = false;
             boolean foundFoo = false;
 
             String line = r.readLine();
             while (line != null) {
-                if (line.equals("foo")) {
-                    foundFoo = true;
-                } else if (line.equals("sub")) {
-                    foundSub = true;
-                } else if (line.equals("sub/foo")) {
-                    foundSubFoo = true;
+                switch (line) {
+                    case "tmp.jar":
+                        foundArchive = true;
+                        break;
+                    case "foo":
+                        foundFoo = true;
+                        break;
+                    case "sub":
+                        foundSub = true;
+                        break;
+                    case "sub/foo":
+                        foundSubFoo = true;
+                        break;
                 }
                 line = r.readLine();
             }
 
+            assertTrue(foundArchive);
             assertTrue(foundSub);
-            assertTrue(!foundSubFoo);
+            assertFalse(foundSubFoo);
             assertTrue(foundFoo);
-        } finally {
-            if (archive != null) {
-                archive.close();
-            }
         }
     }
     @Test
     public void testManifestOnlyJar() {
-
         buildRule.executeTarget("testManifestOnlyJar");
-        assertContains("Building MANIFEST-only jar: ", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Building MANIFEST-only jar: "));
         File manifestFile = new File(getOutputDir(), tempDir + "META-INF" + File.separator + "MANIFEST.MF");
         assertTrue(manifestFile.exists());
     }
 
     @Test
-    public void testIndexJarsPlusJarMarker() {
+    public void testIndexJarsPlusJarMarker() throws IOException {
         buildRule.executeTarget("testIndexJarsPlusJarMarker");
+        try (ZipFile archive = new ZipFile(new File(getOutputDir(), tempJar + "2"))) {
+            ZipEntry ze = archive.getEntry("META-INF/INDEX.LIST");
+            InputStream is = archive.getInputStream(ze);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+            // tmp.jar
+            boolean foundTmp = false;
+            boolean foundA = false;
+            boolean foundAB = false;
+            boolean foundABC = false;
+
+            // tmp2.jar
+            boolean foundTmp2 = false;
+            boolean foundD = false;
+            boolean foundDE = false;
+            boolean foundDEF = false;
+
+            String line = r.readLine();
+            while (line != null) {
+                switch (line) {
+                    case "tmp.jar":
+                        foundTmp = true;
+                        break;
+                    case "a":
+                        foundA = true;
+                        break;
+                    case "a/b":
+                        foundAB = true;
+                        break;
+                    case "a/b/c":
+                        foundABC = true;
+                        break;
+                    case "tmp.jar2":
+                        foundTmp2 = true;
+                        break;
+                    case "d":
+                        foundD = true;
+                        break;
+                    case "d/e":
+                        foundDE = true;
+                        break;
+                    case "d/e/f":
+                        foundDEF = true;
+                        break;
+                }
+                line = r.readLine();
+            }
+
+            assertTrue(foundTmp);
+            assertTrue(foundA);
+            assertTrue(foundAB);
+            assertTrue(foundABC);
+            assertTrue(foundTmp2);
+            assertTrue(foundD);
+            assertTrue(foundDE);
+            assertTrue(foundDEF);
+        }
+    }
+
+    @Test
+    public void testIndexJarsPlusJarMarkerWithMapping() throws IOException {
+        buildRule.executeTarget("testIndexJarsPlusJarMarkerWithMapping");
+        try (ZipFile archive = new ZipFile(new File(getOutputDir(), tempJar + "2"))) {
+            ZipEntry ze = archive.getEntry("META-INF/INDEX.LIST");
+            InputStream is = archive.getInputStream(ze);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+            // tmp.jar
+            boolean foundTmp = false;
+            boolean foundA = false;
+            boolean foundAB = false;
+            boolean foundABC = false;
+
+            // tmp2.jar
+            boolean foundTmp2 = false;
+            boolean foundD = false;
+            boolean foundDE = false;
+            boolean foundDEF = false;
+
+            String line = r.readLine();
+            while (line != null) {
+                System.out.println("line = " + line);
+                switch (line) {
+                    case "foo/tmp.jar":
+                        foundTmp = true;
+                        break;
+                    case "a":
+                        foundA = true;
+                        break;
+                    case "a/b":
+                        foundAB = true;
+                        break;
+                    case "a/b/c":
+                        foundABC = true;
+                        break;
+                    case "tmp.jar2":
+                        foundTmp2 = true;
+                        break;
+                    case "d":
+                        foundD = true;
+                        break;
+                    case "d/e":
+                        foundDE = true;
+                        break;
+                    case "d/e/f":
+                        foundDEF = true;
+                        break;
+                }
+                line = r.readLine();
+            }
+
+            assertTrue(foundTmp);
+            assertTrue(foundA);
+            assertTrue(foundAB);
+            assertTrue(foundABC);
+            assertTrue(foundTmp2);
+            assertTrue(foundD);
+            assertTrue(foundDE);
+            assertTrue(foundDEF);
+        }
     }
 
     @Test
     public void testNoVersionInfoFail() {
-        try {
-            buildRule.executeTarget("testNoVersionInfoFail");
-            fail("BuildException expected: Manifest Implementation information missing.");
-        } catch (BuildException ex) {
-            assertContains("No Implementation-Title set.", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No Implementation-Title set.");
+        buildRule.executeTarget("testNoVersionInfoFail");
     }
 
     @Test
     public void testNoVersionInfoIgnore() {
         buildRule.executeTarget("testNoVersionInfoIgnore");
-        assertTrue(buildRule.getFullLog().contains("No Implementation-Title set."));
-        assertTrue(buildRule.getFullLog().contains("No Implementation-Version set."));
-        assertTrue(buildRule.getFullLog().contains("No Implementation-Vendor set."));
+        assertThat(buildRule.getFullLog(), containsString("No Implementation-Title set."));
+        assertThat(buildRule.getFullLog(), containsString("No Implementation-Version set."));
+        assertThat(buildRule.getFullLog(), containsString("No Implementation-Vendor set."));
     }
 
     @Test
     public void testNoVersionInfoWarn() {
         buildRule.executeTarget("testNoVersionInfoWarn");
-        assertTrue(buildRule.getLog().contains("No Implementation-Title set."));
-        assertTrue(buildRule.getLog().contains("No Implementation-Version set."));
-        assertTrue(buildRule.getLog().contains("No Implementation-Vendor set."));
+        assertThat(buildRule.getLog(), containsString("No Implementation-Title set."));
+        assertThat(buildRule.getLog(), containsString("No Implementation-Version set."));
+        assertThat(buildRule.getLog(), containsString("No Implementation-Vendor set."));
     }
 
     @Test
     public void testNoVersionInfoNoStrict() {
         buildRule.executeTarget("testNoVersionInfoNoStrict");
-        assertFalse(buildRule.getLog().contains("No Implementation-Title set."));
-        assertFalse(buildRule.getLog().contains("No Implementation-Version set."));
-        assertFalse(buildRule.getLog().contains("No Implementation-Vendor set."));
+        assertThat(buildRule.getLog(), not(containsString("No Implementation-Title set.")));
+        assertThat(buildRule.getLog(), not(containsString("No Implementation-Version set.")));
+        assertThat(buildRule.getLog(), not(containsString("No Implementation-Vendor set.")));
     }
 
     @Test
     public void testHasVersionInfo() {
         buildRule.executeTarget("testHasVersionInfo");
-        assertFalse(buildRule.getLog().contains("No Implementation-Title set."));
-        assertFalse(buildRule.getLog().contains("No Implementation-Version set."));
-        assertFalse(buildRule.getLog().contains("No Implementation-Vendor set."));
+        assertThat(buildRule.getLog(), not(containsString("No Implementation-Title set.")));
+        assertThat(buildRule.getLog(), not(containsString("No Implementation-Version set.")));
+        assertThat(buildRule.getLog(), not(containsString("No Implementation-Vendor set.")));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java
index 5579f85..1265461 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,20 +31,25 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.input.DefaultInputHandler;
+import org.apache.tools.ant.taskdefs.condition.JavaVersion;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.TeeOutputStream;
 import org.junit.Assume;
+import org.junit.AssumptionViolatedException;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.internal.AssumptionViolatedException;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import org.junit.Assert;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * stress out java task
@@ -54,6 +59,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private static final int TIME_TO_WAIT = 1;
     // wait 1 second extra to allow for java to start ...
     // this time was OK on a Win NT machine and on nagoya
@@ -62,7 +70,7 @@
     /** Utilities used for file operations */
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-    private boolean runFatalTests=false;
+    private boolean runFatalTests = false;
 
 
     /**
@@ -86,62 +94,44 @@
 
     @Test
     public void testNoJarNoClassname() {
-        try {
-            buildRule.executeTarget("testNoJarNoClassname");
-            fail("Build exception should have been thrown - parameter validation");
-        } catch (BuildException ex) {
-            assertContains("Classname must not be null.", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Classname must not be null.");
+        buildRule.executeTarget("testNoJarNoClassname");
     }
 
     @Test
     public void testJarNoFork() {
-        try {
-            buildRule.executeTarget("testJarNoFork");
-            fail("Build exception should have been thrown - parameter validation");
-        } catch (BuildException ex) {
-            assertContains("Cannot execute a jar in non-forked mode. Please set fork='true'. ", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot execute a jar in non-forked mode. Please set fork='true'. ");
+        buildRule.executeTarget("testJarNoFork");
     }
 
     @Test
     public void testJarAndClassName() {
-        try {
-            buildRule.executeTarget("testJarAndClassName");
-            fail("Build exception should have been thrown - both classname and JAR are not allowed");
-        } catch (BuildException ex) {
-            assertEquals("Cannot use 'jar' and 'classname' attributes in same command", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use combination of ");
+        buildRule.executeTarget("testJarAndClassName");
     }
 
     @Test
     public void testClassnameAndJar() {
-        try {
-            buildRule.executeTarget("testClassnameAndJar");
-            fail("Build exception should have been thrown - both classname and JAR are not allowed");
-        } catch (BuildException ex) {
-            assertEquals("Cannot use 'jar' with 'classname' or 'module' attributes in same command.", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use combination of ");
+        buildRule.executeTarget("testClassnameAndJar");
     }
 
     @Test
     public void testJarAndModule() {
-        try {
-            buildRule.executeTarget("testJarAndModule");
-            fail("Build exception should have been thrown - both module and JAR are not allowed");
-        } catch (BuildException ex) {
-            assertEquals("Cannot use 'jar' and 'module' attributes in same command", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use combination of ");
+        buildRule.executeTarget("testJarAndModule");
     }
 
     @Test
     public void testModuleAndJar() {
-        try {
-            buildRule.executeTarget("testModuleAndJar");
-            fail("Build exception should have been thrown - both module and JAR are not allowed");
-        } catch (BuildException ex) {
-            assertEquals("Cannot use 'jar' with 'classname' or 'module' attributes in same command.", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use combination of ");
+        buildRule.executeTarget("testModuleAndJar");
     }
 
     @Test
@@ -169,7 +159,7 @@
         java.setJvmargs("-Xmx128M");
         java.setArgs(arg);
         final String[] cmdLine = java.getCommandLine().getCommandline();
-        Assert.assertNotNull("Has command line.", cmdLine);
+        assertNotNull("Has command line.", cmdLine);
         assertEquals("Command line should have 5 elements", 5, cmdLine.length);
         assertEquals("Last command line element should be java argument: " + arg,
                 arg,
@@ -195,7 +185,7 @@
         java.setJvmargs("-Xmx128M");    //NOI18N
         java.setArgs(arg);
         final String[] cmdLine = java.getCommandLine().getCommandline();
-        Assert.assertNotNull("Has command line.", cmdLine);
+        assertNotNull("Has command line.", cmdLine);
         assertEquals("Command line should have 5 elements", 5, cmdLine.length);
         assertEquals("Last command line element should be java argument: " + arg,
                 arg,
@@ -213,68 +203,54 @@
         buildRule.executeTarget("testRun");
     }
 
-
-
     /** this test fails but we ignore the return value;
      *  we verify that failure only matters when failonerror is set
      */
     @Test
     public void testRunFail() {
-        Assume.assumeTrue("Fatal tests have not been set to run", runFatalTests);
+        assumeTrue("Fatal tests have not been set to run", runFatalTests);
         buildRule.executeTarget("testRunFail");
     }
 
     @Test
     public void testRunFailFoe() {
-        Assume.assumeTrue("Fatal tests have not been set to run", runFatalTests);
-        try {
-            buildRule.executeTarget("testRunFailFoe");
-            fail("Build exception should have been thrown - " + "java failures being propagated");
-        } catch (BuildException ex) {
-            assertContains("Java returned:", ex.getMessage());
-        }
+        assumeTrue("Fatal tests have not been set to run", runFatalTests);
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Java returned:");
+        buildRule.executeTarget("testRunFailFoe");
     }
 
     @Test
     public void testRunFailFoeFork() {
-        try {
-            buildRule.executeTarget("testRunFailFoeFork");
-            fail("Build exception should have been thrown - " + "java failures being propagated");
-        } catch (BuildException ex) {
-            assertContains("Java returned:", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Java returned:");
+        buildRule.executeTarget("testRunFailFoeFork");
     }
 
     @Test
     public void testExcepting() {
         buildRule.executeTarget("testExcepting");
-        assertContains("Exception raised inside called program", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Exception raised inside called program"));
     }
 
     @Test
     public void testExceptingFork() {
         buildRule.executeTarget("testExceptingFork");
-        assertContains("Java Result:", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Java Result:"));
     }
 
     @Test
     public void testExceptingFoe() {
-        try {
-            buildRule.executeTarget("testExceptingFoe");
-            fail("Build exception should have been thrown - " + "passes exception through");
-        } catch (BuildException ex) {
-            assertContains("Exception raised inside called program", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Exception raised inside called program");
+        buildRule.executeTarget("testExceptingFoe");
     }
 
     @Test
     public void testExceptingFoeFork() {
-        try {
-            buildRule.executeTarget("testExceptingFoeFork");
-            fail("Build exception should have been thrown - " + "exceptions turned into error codes");
-        } catch (BuildException ex) {
-            assertContains("Java returned:", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Java returned:");
+        buildRule.executeTarget("testExceptingFoeFork");
     }
 
     @Test
@@ -303,12 +279,9 @@
 
     @Test
     public void testRunFailWithFailOnError() {
-        try {
-            buildRule.executeTarget("testRunFailWithFailOnError");
-            fail("Build exception should have been thrown - " + "non zero return code");
-        } catch (BuildException ex) {
-            assertContains("Java returned:", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Java returned:");
+        buildRule.executeTarget("testRunFailWithFailOnError");
     }
 
     @Test
@@ -321,14 +294,13 @@
         File logFile = FILE_UTILS.createTempFile("spawn", "log",
                 new File(buildRule.getProject().getProperty("output")), false, false);
         // this is guaranteed by FileUtils#createTempFile
-        assertTrue("log file not existing", !logFile.exists());
+        assertFalse("log file not existing", logFile.exists());
         buildRule.getProject().setProperty("logFile", logFile.getAbsolutePath());
         buildRule.getProject().setProperty("timeToWait", Long.toString(TIME_TO_WAIT));
         buildRule.getProject().executeTarget("testSpawn");
 
         Thread.sleep(TIME_TO_WAIT * 1000 + SECURITY_MARGIN);
 
-
         // let's be nice with the next generation of developers
         if (!logFile.exists()) {
             System.out.println("suggestion: increase the constant"
@@ -375,20 +347,18 @@
 
         Java java = new Java();
         java.setProject(buildRule.getProject());
-        java.setClassname("org.apache.tools.ant.Main");
+        java.setClassname(MagicNames.ANT_CORE_PACKAGE + ".Main");
         java.setArgs("-version");
         java.setFork(true);
         // note: due to the missing classpath it will fail, but the input stream
         // reader will be read
         java.execute();
 
-        Thread inputThread = new Thread(new Runnable() {
-            public void run() {
-                Input input = new Input();
-                input.setProject(buildRule.getProject());
-                input.setAddproperty("input.value");
-                input.execute();
-            }
+        Thread inputThread = new Thread(() -> {
+            Input input = new Input();
+            input.setProject(buildRule.getProject());
+            input.setAddproperty("input.value");
+            input.execute();
         });
         inputThread.start();
 
@@ -424,19 +394,17 @@
         final boolean[] timeout = new boolean[1];
         timeout[0] = false;
 
-        Thread writingThread = new Thread(new Runnable() {
-            public void run() {
-                try {
-                    // wait a little bit to have the target executed
-                    Thread.sleep(500);
-                } catch (InterruptedException e) {
-                    throw new AssumptionViolatedException("Thread interrupted", e);
-                }
-                try {
-                    out.write("foo-FlushedInput\n".getBytes());
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
+        Thread writingThread = new Thread(() -> {
+            try {
+                // wait a little bit to have the target executed
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                throw new AssumptionViolatedException("Thread interrupted", e);
+            }
+            try {
+                out.write("foo-FlushedInput\n".getBytes());
+            } catch (IOException e) {
+                throw new RuntimeException(e);
             }
         });
         writingThread.setDaemon(true);
@@ -446,6 +414,78 @@
     }
 
     /**
+     * Test that the Java single file source program feature introduced in Java 11 works fine
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testSimpleSourceFile() {
+        requireJava11();
+        buildRule.executeTarget("simpleSourceFile");
+    }
+
+    /**
+     * Test that the sourcefile option of the Java task can only be run when fork attribute is set
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testSourceFileRequiresFork() {
+        requireJava11();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot execute sourcefile in non-forked mode. Please set fork='true'");
+        buildRule.executeTarget("sourceFileRequiresFork");
+    }
+
+    /**
+     * Tests that the sourcefile attribute and the classname attribute of the Java task cannot be used
+     * together
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testSourceFileCantUseClassname() {
+        requireJava11();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use 'sourcefile' in combination with");
+        buildRule.executeTarget("sourceFileCantUseClassname");
+    }
+
+    /**
+     * Tests that the sourcefile attribute and the jar attribute of the Java task cannot be used
+     * together
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testSourceFileCantUseJar() {
+        requireJava11();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use 'sourcefile' in combination with");
+        buildRule.executeTarget("sourceFileCantUseJar");
+    }
+
+    /**
+     * Tests that the sourcefile attribute and the module attribute of the Java task cannot be used
+     * together
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testSourceFileCantUseModule() {
+        requireJava11();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot use 'sourcefile' in combination with");
+        buildRule.executeTarget("sourceFileCantUseModule");
+    }
+
+    private static void requireJava11() {
+        final JavaVersion javaVersion = new JavaVersion();
+        javaVersion.setAtLeast("11");
+        Assume.assumeTrue("Skipping test which requires a minimum of Java 11 runtime", javaVersion.eval());
+    }
+
+    /**
      * entry point class with no dependencies other
      * than normal JRE runtime
      */
@@ -506,22 +546,13 @@
             if (argv.length >= 2) {
                 logFile = argv[1];
             }
-            OutputStreamWriter out = null;
             Thread.sleep(sleepTime * 1000);
 
-            try {
-                File dest = new File(logFile);
-                FileOutputStream fos = new FileOutputStream(dest);
-                out = new OutputStreamWriter(fos);
+            File dest = new File(logFile);
+            try (OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(dest))) {
                 out.write("bye bye\n");
             } catch (Exception ex) {
-            } finally {
-                try {
-                    out.close();
-                } catch (IOException ioe) {
-                }
             }
-
         }
     }
 
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 1005c1d..a7a0875 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,25 +20,26 @@
 
 import java.io.File;
 
-import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
 import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory;
 import org.apache.tools.ant.taskdefs.compilers.Javac13;
 import org.apache.tools.ant.taskdefs.compilers.JavacExternal;
-import org.apache.tools.ant.types.Path;
 
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Path;
+
 import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Testcase for <javac>.
@@ -69,13 +70,12 @@
 
         javac.setFork(true);
         assertNotNull("normal fork", javac.getJavacExecutable());
-        assertContains("name should contain \"javac\"", "javac",
-                   javac.getJavacExecutable());
+        assertThat("name should contain \"javac\"", javac.getJavacExecutable(), containsString("javac"));
 
         project.setProperty("build.compiler", "extJavac");
         javac.setFork(false);
         assertNotNull("fork via property", javac.getJavacExecutable());
-        assertContains("name should contain \"javac\"", "javac", javac.getJavacExecutable());
+        assertThat("name should contain \"javac\"", javac.getJavacExecutable(), containsString("javac"));
 
         project.setProperty("build.compiler", "org.apache.tools.ant.taskdefs.compilers.JavacExternal");
         javac.setFork(false);
@@ -83,8 +83,7 @@
         assertThat("name should contain \"javac\"", javac.getJavacExecutable(), containsString("javac"));
 
         project.setProperty("build.compiler", "whatever");
-        assertNull("no fork and not extJavac means no executable",
-                   javac.getJavacExecutable());
+        assertNull("no fork and not extJavac means no executable", javac.getJavacExecutable());
 
         String myJavac = "Slartibartfast";
         javac.setFork(true);
@@ -161,8 +160,7 @@
         String compiler = javac.getCompiler();
         assertNotNull(compiler);
         if (System.getProperty("build.compiler") != null) {
-            assertEquals(System.getProperty("build.compiler"),
-                         compiler);
+            assertEquals(System.getProperty("build.compiler"), compiler);
         } else {
             assertTrue("default value",
                        "javac1.1".equals(compiler)
@@ -208,17 +206,13 @@
     @Test
     public void testCompilerAdapter() {
         javac.setCompiler("javac1.4");
-
         javac.setDepend(true);
-        CompilerAdapter adapter =
-            CompilerAdapterFactory.getCompiler(javac.getCompiler(), javac);
-
-        assertTrue(adapter instanceof Javac13);
+        CompilerAdapter adapter = CompilerAdapterFactory.getCompiler(javac.getCompiler(), javac);
+        assertThat(adapter, instanceOf(Javac13.class));
 
         javac.setFork(true);
-        adapter =
-            CompilerAdapterFactory.getCompiler(javac.getCompiler(), javac);
-        assertTrue(adapter instanceof JavacExternal);
+        adapter = CompilerAdapterFactory.getCompiler(javac.getCompiler(), javac);
+        assertThat(adapter, instanceOf(JavacExternal.class));
     }
 
     @Test
@@ -228,13 +222,13 @@
 
     @Test
     public void testSourceWithDefault() {
-        project.setNewProperty("ant.build.javac.source", "1.4");
+        project.setNewProperty(MagicNames.BUILD_JAVAC_SOURCE, "1.4");
         assertEquals("1.4", javac.getSource());
     }
 
     @Test
     public void testSourceOverridesDefault() {
-        project.setNewProperty("ant.build.javac.source", "1.4");
+        project.setNewProperty(MagicNames.BUILD_JAVAC_SOURCE, "1.4");
         javac.setSource("1.5");
         assertEquals("1.5", javac.getSource());
     }
@@ -246,57 +240,42 @@
 
     @Test
     public void testTargetWithDefault() {
-        project.setNewProperty("ant.build.javac.target", "1.4");
+        project.setNewProperty(MagicNames.BUILD_JAVAC_TARGET, "1.4");
         assertEquals("1.4", javac.getTarget());
     }
 
     @Test
     public void testTargetOverridesDefault() {
-        project.setNewProperty("ant.build.javac.target", "1.4");
+        project.setNewProperty(MagicNames.BUILD_JAVAC_TARGET, "1.4");
         javac.setTarget("1.5");
         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
@@ -325,16 +304,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/JavadocTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/JavadocTest.java
index f7a287d..1730cb0 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JavadocTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JavadocTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,13 +28,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
-    private static final String BUILD_PATH = "src/etc/testcases/taskdefs/javadoc/";
-    private static final String BUILD_FILENAME = "javadoc.xml";
-    private static final String BUILD_FILE = BUILD_PATH + BUILD_FILENAME;
-
     @Before
     public void setUp() {
-        buildRule.configureProject(BUILD_FILE);
+        buildRule.configureProject("src/etc/testcases/taskdefs/javadoc/javadoc.xml");
     }
 
     // PR 38370
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/LoadFileTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/LoadFileTest.java
index ab665ad..3bd6728 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/LoadFileTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/LoadFileTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,12 +23,13 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  * Test the load file task
@@ -38,6 +39,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/loadfile.xml");
@@ -49,29 +53,21 @@
     }
 
     /**
-     * A unit test for JUnit
+     * Fail due to source file not defined
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void testNoSourcefileDefined() {
-        try {
-            buildRule.executeTarget("testNoSourcefileDefined");
-            fail("BuildException expected: source file not defined");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testNoSourcefileDefined");
+        // TODO assert value
     }
 
     /**
-     * A unit test for JUnit
+     * Fail due to output property not defined
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void testNoPropertyDefined() {
-        try {
-            buildRule.executeTarget("testNoPropertyDefined");
-            fail("BuildException expected: output property not defined");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testNoPropertyDefined");
+        // TODO assert value
     }
 
     /**
@@ -79,12 +75,9 @@
      */
     @Test
     public void testNoSourcefilefound() {
-        try {
-            buildRule.executeTarget("testNoSourcefilefound");
-            fail("BuildException expected: File not found");
-        } catch (BuildException ex) {
-            assertContains(" doesn't exist", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(" doesn't exist");
+        buildRule.executeTarget("testNoSourcefilefound");
     }
 
     /**
@@ -102,9 +95,8 @@
     @Test
     public void testLoadAFile() throws BuildException {
         buildRule.executeTarget("testLoadAFile");
-        if(!buildRule.getProject().getProperty("testLoadAFile").contains("eh?")) {
-            fail("property is not all in the file");
-        }
+        assertThat("property is not all in the file",
+                buildRule.getProject().getProperty("testLoadAFile"), containsString("eh?"));
     }
 
     /**
@@ -122,9 +114,8 @@
     @Test
     public void testEvalProps() throws BuildException {
         buildRule.executeTarget("testEvalProps");
-        if(!buildRule.getProject().getProperty("testEvalProps").contains("rain")) {
-            fail("property eval broken");
-        }
+        assertThat("property eval broken",
+                buildRule.getProject().getProperty("testEvalProps"), containsString("rain"));
     }
 
     /**
@@ -133,9 +124,8 @@
     @Test
     public void testFilterChain() throws BuildException {
         buildRule.executeTarget("testFilterChain");
-        if(!buildRule.getProject().getProperty("testFilterChain").contains("World!")) {
-            fail("Filter Chain broken");
-        }
+        assertThat("Filter Chain broken",
+                buildRule.getProject().getProperty("testFilterChain"), containsString("World!"));
     }
 
     /**
@@ -144,9 +134,8 @@
     @Test
     public final void testStripJavaComments() throws BuildException {
         buildRule.executeTarget("testStripJavaComments");
-        final String expected = buildRule.getProject().getProperty("expected");
-        final String generated = buildRule.getProject().getProperty("testStripJavaComments");
-        assertEquals(expected, generated);
+        assertEquals(buildRule.getProject().getProperty("expected"),
+                buildRule.getProject().getProperty("testStripJavaComments"));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/MacroDefTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/MacroDefTest.java
index 59b6bd7..50155b2 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/MacroDefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/MacroDefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,10 +23,12 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -35,6 +37,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/macrodef.xml");
@@ -52,24 +57,16 @@
         assertEquals("Inner Text", buildRule.getLog());
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testDuplicateAttribute() {
-        try {
-            buildRule.executeTarget("duplicate.attribute");
-            fail("BuildException expected: the attribute text has already been specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("duplicate.attribute");
+        //TODO assert value
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testDuplicateElement() {
-        try {
-            buildRule.executeTarget("duplicate.element");
-            fail("BuildException expected: the element text has already been specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("duplicate.element");
+        //TODO assert value
     }
 
     @Test
@@ -105,32 +102,31 @@
     @Test
     public void testTextElement() {
         buildRule.executeTarget("textelement");
-        assertContains("Hello world", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Hello world"));
     }
 
     @Test
     public void testTextTrim() {
         buildRule.executeTarget("text.trim");
-        assertContains("[Hello world]", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("[Hello world]"));
     }
 
-    @Test
+    /**
+     * Fail due to the name "text" already used as an attribute
+     */
+    @Test(expected = BuildException.class)
     public void testDuplicateTextName() {
-        try {
-            buildRule.executeTarget("duplicatetextname");
-            fail("BuildException expected: the name \"text\" is already used as an attribute");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("duplicatetextname");
+        // TODO assert value
     }
-    @Test
+
+    /**
+     * Fail due to the attribute name "text" already used by a text element
+     */
+    @Test(expected = BuildException.class)
     public void testDuplicateTextName2() {
-        try {
-            buildRule.executeTarget("duplicatetextname2");
-            fail("BuildException expected: the attribute name \"text\" has already been used by the text element");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("duplicatetextname2");
+        // TODO assert value
     }
 
     @Test
@@ -159,12 +155,9 @@
 
     @Test
     public void testImplicitNotOptional() {
-        try {
-            buildRule.executeTarget("implicit.notoptional");
-            fail("BuildException expected: Missing nested elements for implicit element implicit");
-        } catch (BuildException ex) {
-            assertEquals("Missing nested elements for implicit element implicit", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Missing nested elements for implicit element implicit");
+        buildRule.executeTarget("implicit.notoptional");
     }
 
     @Test
@@ -175,38 +168,28 @@
 
     @Test
     public void testImplicitExplicit() {
-        try {
-            buildRule.executeTarget("implicit.explicit");
-            fail("BuildException expected: Only one element allowed when using implicit elements");
-        } catch (BuildException ex) {
-            assertEquals("Only one element allowed when using implicit elements", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Only one element allowed when using implicit elements");
+        buildRule.executeTarget("implicit.explicit");
     }
 
     @Test
     public void testBackTraceOff() {
-        try {
-            buildRule.executeTarget("backtraceoff");
-        } catch (BuildException ex) {
-            if (ex.getMessage().contains("following error occurred")) {
-                fail("error message contained backtrace - " + ex.getMessage());
-            }
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(not(containsString("following error occurred")));
+        buildRule.executeTarget("backtraceoff");
     }
 
     @Test
     public void testBackTrace() {
-        try {
-            buildRule.executeTarget("backtraceon");
-            fail("BuildException expected: Checking if a back trace is created");
-        } catch (BuildException ex) {
-            assertContains("following error occurred", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("following error occurred");
+        buildRule.executeTarget("backtraceon");
     }
 
     @Test
     public void testTopLevelText() {
         buildRule.executeTarget("top-level-text");
-        assertContains("Hello World", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Hello World"));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/MakeUrlTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/MakeUrlTest.java
index b60604b..66036e2 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/MakeUrlTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/MakeUrlTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,158 +19,112 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
+import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import java.io.InputStream;
 import java.io.IOException;
 import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 
-
+@RunWith(Enclosed.class)
 public class MakeUrlTest {
 
-    @Rule
-    public final BuildFileRule buildRule = new BuildFileRule();
+    @RunWith(Parameterized.class)
+    public static class InvalidArgumentTest {
 
-    @Before
-    public void setUp() {
-        buildRule.configureProject("src/etc/testcases/taskdefs/makeurl.xml");
-    }
+        @Rule
+        public final BuildFileRule buildRule = new BuildFileRule();
 
-    @Test
-    public void testEmpty() {
-        try {
-            buildRule.executeTarget("testEmpty");
-            fail("BuildException expected: missing property");
-        } catch (BuildException ex) {
-            assertContains("property", ex.getMessage());
+        @Rule
+        public ExpectedException thrown = ExpectedException.none();
+
+        @Before
+        public void setUp() {
+            buildRule.configureProject("src/etc/testcases/taskdefs/makeurl.xml");
+        }
+
+        @Parameterized.Parameters(name = "{0}")
+        public static Collection<Object[]> targets() {
+            return Arrays.asList(new Object[][]{
+                    {"testEmpty", "No property defined"},
+                    {"testNoProperty", "No property defined"},
+                    {"testNoFile", "No files defined"},
+                    {"testValidation", "A source file is missing"}
+            });
+        }
+
+        @Parameterized.Parameter
+        public String targetName;
+
+        @Parameterized.Parameter(1)
+        public String message;
+
+        @Test
+        public void test() {
+            thrown.expect(BuildException.class);
+            thrown.expectMessage(message);
+            buildRule.executeTarget(targetName);
         }
     }
 
-    @Test
-    public void testNoProperty() {
-        try {
-            buildRule.executeTarget("testNoProperty");
-            fail("BuildException expected: missing property");
-        } catch (BuildException ex) {
-            assertContains("property", ex.getMessage());
+    @RunWith(Parameterized.class)
+    public static class ValidArgumentTest {
+
+        @Rule
+        public final BuildFileRule buildRule = new BuildFileRule();
+
+        @Before
+        public void setUp() {
+            buildRule.configureProject("src/etc/testcases/taskdefs/makeurl.xml");
+        }
+
+        @Parameterized.Parameters(name = "{0}")
+        public static Collection<Object[]> targets() {
+            return Arrays.asList(new Object[][]{
+                    {"testWorks", both(containsString("file:")).and(containsString("/foo"))},
+                    {"testIllegalChars", both(containsString("file:")).and(containsString("fo%20o%25"))},
+                    {"testRoundTrip", containsString("file:")},
+                    {"testIllegalCombinations", both(containsString("/foo")).and(containsString(".xml"))},
+                    {"testFileset", both(containsString(".xml ")).and(endsWith(".xml"))},
+                    {"testFilesetSeparator", both(containsString(".xml\",\"")).and(endsWith(".xml"))},
+                    {"testPath", containsString("makeurl.xml")}
+            });
+        }
+
+        @Parameterized.Parameter
+        public String targetName;
+
+        @Parameterized.Parameter(1)
+        public Matcher<String> matcher;
+
+        @Test
+        public void test() throws IOException {
+            buildRule.executeTarget(targetName);
+            String property = buildRule.getProject().getProperty(targetName);
+            assertNotNull("property not set", property);
+            assertThat(property, matcher);
+
+            if (targetName.equals("testRoundTrip")) {
+                // test that we can round trip by opening a url that exists
+                URL url = new URL(property);
+                InputStream instream = url.openStream();
+                instream.close();
+            }
         }
     }
 
-    @Test
-    public void testNoFile() {
-        try {
-            buildRule.executeTarget("testNoFile");
-            fail("BuildException expected: missing file");
-        } catch (BuildException ex) {
-            assertContains("file", ex.getMessage());
-        }
-    }
-
-    @Test
-    public void testValidation() {
-        try {
-            buildRule.executeTarget("testValidation");
-            fail("BuildException expected: " + MakeUrl.ERROR_MISSING_FILE);
-        } catch (BuildException ex) {
-            assertContains("file", ex.getMessage());
-        }
-    }
-
-    @Test
-    public void testWorks() {
-        buildRule.executeTarget("testWorks");
-        assertPropertyContains("testWorks", "file:");
-        assertPropertyContains("testWorks", "/foo");
-    }
-
-    @Test
-    public void testIllegalChars() {
-        buildRule.executeTarget("testIllegalChars");
-        assertPropertyContains("testIllegalChars", "file:");
-        assertPropertyContains("testIllegalChars", "fo%20o%25");
-    }
-
-    /**
-     * test that we can round trip by opening a url that exists
-     *
-     * @throws IOException if something goes wrong
-     */
-    @Test
-    public void testRoundTrip() throws IOException {
-        buildRule.executeTarget("testRoundTrip");
-        assertPropertyContains("testRoundTrip", "file:");
-        String property = getProperty("testRoundTrip");
-        URL url = new URL(property);
-        InputStream instream = url.openStream();
-        instream.close();
-    }
-
-    @Test
-    public void testIllegalCombinations() {
-        buildRule.executeTarget("testIllegalCombinations");
-        assertPropertyContains("testIllegalCombinations", "/foo");
-        assertPropertyContains("testIllegalCombinations", ".xml");
-    }
-
-    @Test
-    public void testFileset() {
-        buildRule.executeTarget("testFileset");
-        assertPropertyContains("testFileset", ".xml ");
-        assertPropertyEndsWith("testFileset", ".xml");
-    }
-
-    @Test
-    public void testFilesetSeparator() {
-        buildRule.executeTarget("testFilesetSeparator");
-        assertPropertyContains("testFilesetSeparator", ".xml\",\"");
-        assertPropertyEndsWith("testFilesetSeparator", ".xml");
-    }
-
-    @Test
-    public void testPath() {
-        buildRule.executeTarget("testPath");
-        assertPropertyContains("testPath", "makeurl.xml");
-    }
-
-    /**
-     * assert that a property ends with
-     *
-     * @param property String
-     * @param ending String
-     */
-    private void assertPropertyEndsWith(String property, String ending) {
-        String result = getProperty(property);
-        String substring = result.substring(result.length() - ending.length());
-        assertEquals(ending, substring);
-    }
-
-    /**
-     * assert that a property contains a string
-     *
-     * @param property name of property to look for
-     * @param contains what to search for in the string
-     */
-    protected void assertPropertyContains(String property, String contains) {
-        String result = getProperty(property);
-
-        assertTrue("expected " + contains + " in " + result,
-                result != null && result.contains(contains));
-    }
-
-    /**
-     * get a property from the project
-     *
-     * @param property String
-     * @return String
-     */
-    protected String getProperty(String property) {
-        return buildRule.getProject().getProperty(property);
-    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestClassPathTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestClassPathTest.java
index cfdbf11..7ec700d 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestClassPathTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestClassPathTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,13 @@
  */
 package org.apache.tools.ant.taskdefs;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
 import java.io.IOException;
@@ -29,10 +32,10 @@
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests &lt;bm:manifestclasspath&gt;.
@@ -42,6 +45,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/manifestclasspath.xml");
@@ -49,57 +55,62 @@
 
     @Test
     public void testBadDirectory() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Jar's directory not found:");
         try {
             buildRule.executeTarget("test-bad-directory");
-            fail("Build exception should have been thrown on bad directory");
-        } catch (BuildException ex) {
-            assertContains("Jar's directory not found:", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertNull(buildRule.getProject().getProperty("jar.classpath"));
         }
-        assertNull(buildRule.getProject().getProperty("jar.classpath"));
     }
 
     @Test
     public void testBadNoProperty() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Missing 'property' attribute!");
         try {
             buildRule.executeTarget("test-bad-no-property");
-            fail("Build exception should have been thrown on no property");
-        } catch (BuildException ex) {
-            assertContains("Missing 'property' attribute!", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertNull(buildRule.getProject().getProperty("jar.classpath"));
         }
-        assertNull(buildRule.getProject().getProperty("jar.classpath"));
     }
 
     @Test
     public void testBadPropertyExists() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Property 'jar.classpath' already set!");
         try {
             buildRule.executeTarget("test-bad-property-exists");
-            fail("Build exception should have been thrown on bad property");
-        } catch (BuildException ex) {
-            assertContains("Property 'jar.classpath' already set!", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertEquals("exists", buildRule.getProject().getProperty("jar.classpath"));
         }
-        assertEquals(buildRule.getProject().getProperty("jar.classpath"), "exists");
     }
 
     @Test
     public void testBadNoJarfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Missing 'jarfile' attribute!");
         try {
             buildRule.executeTarget("test-bad-no-jarfile");
-            fail("Build exception should have been thrown on bad jar file");
-        } catch (BuildException ex) {
-            assertContains("Missing 'jarfile' attribute!", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertNull(buildRule.getProject().getProperty("jar.classpath"));
         }
-        assertNull(buildRule.getProject().getProperty("jar.classpath"));
     }
 
     @Test
     public void testBadNoClassPath() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Missing nested <classpath>!");
         try {
             buildRule.executeTarget("test-bad-no-classpath");
-            fail("Build exception should have been thrown on no classpath");
-        } catch (BuildException ex) {
-            assertContains("Missing nested <classpath>!", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertNull(buildRule.getProject().getProperty("jar.classpath"));
         }
-        assertNull(buildRule.getProject().getProperty("jar.classpath"));
     }
 
     @Test
@@ -134,18 +145,20 @@
 
     @Test
     public void testParentLevel2TooDeep() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No suitable relative path from ");
         try {
             buildRule.executeTarget("test-parent-level2-too-deep");
-            fail("Build exception should have been thrown on no suitable path");
-        } catch (BuildException ex) {
-            assertContains("No suitable relative path from ", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertNull(buildRule.getProject().getProperty("jar.classpath"));
         }
-        assertNull(buildRule.getProject().getProperty("jar.classpath"));
     }
 
     @Test
     public void testPseudoTahoeRefid() {
-        Assume.assumeTrue("No regexp matcher is present", RegexpMatcherFactory.regexpMatcherPresent(buildRule.getProject()));
+        assumeTrue("No regexp matcher is present",
+                RegexpMatcherFactory.regexpMatcherPresent(buildRule.getProject()));
 
         buildRule.executeTarget("test-pseudo-tahoe-refid");
         assertEquals(buildRule.getProject().getProperty("jar.classpath"), "classes/dsp-core/ "
@@ -158,7 +171,8 @@
 
     @Test
     public void testPseudoTahoeNested() {
-        Assume.assumeTrue("No regexp matcher is present", RegexpMatcherFactory.regexpMatcherPresent(buildRule.getProject()));
+        assumeTrue("No regexp matcher is present",
+                RegexpMatcherFactory.regexpMatcherPresent(buildRule.getProject()));
 
         buildRule.executeTarget("test-pseudo-tahoe-nested");
         assertEquals(buildRule.getProject().getProperty("jar.classpath"), "classes/dsp-core/ "
@@ -190,27 +204,27 @@
     public void testInternationalGerman() {
         buildRule.executeTarget("international-german");
         buildRule.executeTarget("run-two-jars");
-        assertContains("beta alpha", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("beta alpha"));
     }
 
     @Test
     public void testInternationalHebrew() {
-        Assume.assumeFalse("Test with hebrew path not attempted under Windows", Os.isFamily("windows"));
+        assumeFalse("Test with hebrew path not attempted under Windows", Os.isFamily("windows"));
         buildRule.executeTarget("international-hebrew");
         buildRule.executeTarget("run-two-jars");
-        assertContains("beta alpha", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("beta alpha"));
     }
 
     @Test
     public void testSameWindowsDrive() {
-        Assume.assumeTrue("Test with drive letters only run on windows", Os.isFamily("windows"));
+        assumeTrue("Test with drive letters only run on windows", Os.isFamily("windows"));
         buildRule.executeTarget("testSameDrive");
         assertEquals(buildRule.getProject().getProperty("cp"), "../a/b/x.jar");
     }
 
     @Test
     public void testDifferentWindowsDrive() {
-        Assume.assumeTrue("Test with drive letters only run on windows", Os.isFamily("windows"));
+        assumeTrue("Test with drive letters only run on windows", Os.isFamily("windows"));
         // the lines below try to find a drive name different than the one containing the temp dir
         // if the temp dir is C will try to use D
         // if the temp dir is on D or other will try to use C
@@ -220,7 +234,8 @@
             String tmpCanonicalPath = tmpdir.getCanonicalPath();
             driveLetter = tmpCanonicalPath.substring(0, 1).toUpperCase();
         } catch (IOException ioe) {
-            System.out.println("exception happened getting canonical path of java.io.tmpdir : " + ioe.getMessage());
+            System.out.println("exception happened getting canonical path of java.io.tmpdir : "
+                    + ioe.getMessage());
         }
         String altDriveLetter = null;
         try {
@@ -231,17 +246,17 @@
             }
             new File(altDriveLetter + ":/foo.txt").getCanonicalPath();
         } catch (IOException e) {
-            Assume.assumeNoException("Drive " + altDriveLetter + ": doesn't exist or is not ready", e);
+            assumeNoException("Drive " + altDriveLetter + ": doesn't exist or is not ready", e);
         }
         buildRule.getProject().setProperty("altDriveLetter", altDriveLetter);
 
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No suitable relative path from ");
         try {
             buildRule.executeTarget("testDifferentDrive");
-            fail("Build exception should have been thrown on no alternative drive");
-        } catch (BuildException ex) {
-            assertContains("No suitable relative path from ", ex.getMessage());
+        } finally {
+            // post-mortem
+            assertNull(buildRule.getProject().getProperty("cp"));
         }
-
-        assertNull(buildRule.getProject().getProperty("cp"));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestTest.java
index e518782..1609a39 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ManifestTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -33,12 +33,16 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Testcase for the Manifest class used in the jar task.
@@ -49,14 +53,17 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private File expandedManifest;
     private File outDir;
 
     public static final String LONG_LINE
-        = "AReallyLongLineToTestLineBreakingInManifests-ACapabilityWhich" +
-          "IsSureToLeadToHundredsOfQuestionsAboutWhyAntMungesManifests" +
-          "OfCourseTheAnswerIsThatIsWhatTheSpecRequiresAndIfAnythingHas" +
-          "AProblemWithThatItIsNotABugInAnt";
+            = "AReallyLongLineToTestLineBreakingInManifests-ACapabilityWhich"
+            + "IsSureToLeadToHundredsOfQuestionsAboutWhyAntMungesManifests"
+            + "OfCourseTheAnswerIsThatIsWhatTheSpecRequiresAndIfAnythingHas"
+            + "AProblemWithThatItIsNotABugInAnt";
 
     public static final String LONG_70_NAME
         = "ThisNameIsJustSeventyCharactersWhichIsAllowedAccordingToTheSpecsFiller";
@@ -107,12 +114,9 @@
      */
     @Test
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: Manifest is invalid - no colon on header line");
-        } catch (BuildException ex) {
-            assertContains("Invalid Manifest", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid Manifest");
+        buildRule.executeTarget("test3");
     }
 
     /**
@@ -120,12 +124,9 @@
      */
     @Test
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException expected: Manifest is invalid - section starts with continuation line");
-        } catch (BuildException ex) {
-            assertContains("Invalid Manifest", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid Manifest");
+        buildRule.executeTarget("test4");
    }
 
     /**
@@ -134,8 +135,8 @@
     @Test
     public void test5() {
         buildRule.executeTarget("test5");
-        assertTrue("Expected warning about Name in main section", buildRule.getLog()
-                .contains("Manifest warning: \"Name\" attributes should not occur in the main section"));
+        assertThat("Expected warning about Name in main section", buildRule.getLog(),
+                containsString("Manifest warning: \"Name\" attributes should not occur in the main section"));
     }
 
     /**
@@ -143,16 +144,16 @@
      */
     @Test
     public void test6() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid Manifest");
         try {
             buildRule.executeTarget("test6");
-            fail("BuildException expected: Manifest is invalid - section starts with incorrect attribute");
-        } catch (BuildException ex) {
-            assertContains("Invalid Manifest", ex.getMessage());
-        }
-        assertTrue("Expected warning about section not starting with Name: attribute", buildRule.getLog()
-                .contains("Manifest sections should start with a \"Name\" attribute"));
-    }
+        } finally {
+            assertThat("Expected warning about section not starting with Name: attribute", buildRule.getLog(),
+                    containsString("Manifest sections should start with a \"Name\" attribute"));
 
+        }
+    }
 
     /**
      * From attribute is illegal
@@ -160,8 +161,8 @@
     @Test
     public void test7() {
         buildRule.executeTarget("test7");
-        assertTrue("Expected warning about From: attribute", buildRule.getLog()
-                .contains(Manifest.ERROR_FROM_FORBIDDEN));
+        assertThat("Expected warning about From: attribute", buildRule.getLog(),
+                containsString(Manifest.ERROR_FROM_FORBIDDEN));
     }
 
     /**
@@ -185,13 +186,9 @@
      */
     @Test
     public void test9() {
-        try {
-            buildRule.executeTarget("test9");
-            fail("BuildException expected: Construction is invalid - Name attribute should not be used");
-        } catch (BuildException ex) {
-            assertContains("Specify the section name using the \"name\" attribute of the <section> element",
-                           ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Specify the section name using the \"name\" attribute of the <section> element");
+        buildRule.executeTarget("test9");
     }
 
     /**
@@ -199,12 +196,9 @@
      */
     @Test
     public void test10() {
-        try {
-            buildRule.executeTarget("test10");
-            fail("BuildException expected: Attribute has no name");
-        } catch (BuildException ex) {
-            assertContains("Attributes must have name and value", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Attributes must have name and value");
+        buildRule.executeTarget("test10");
     }
 
     /**
@@ -212,12 +206,9 @@
      */
     @Test
     public void test11() {
-        try {
-            buildRule.executeTarget("test11");
-            fail("BuildException expected: Attribute has no value");
-        } catch (BuildException ex) {
-            assertContains("Attributes must have name and value", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Attributes must have name and value");
+        buildRule.executeTarget("test11");
     }
 
     /**
@@ -225,12 +216,9 @@
      */
     @Test
     public void test12() {
-        try {
-            buildRule.executeTarget("test12");
-            fail("BuildException expected: Section with no name");
-        } catch (BuildException ex) {
-            assertContains("Sections must have a name", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Sections must have a name");
+        buildRule.executeTarget("test12");
     }
 
     /**
@@ -238,13 +226,9 @@
      */
     @Test
     public void test13() {
-        try {
-            buildRule.executeTarget("test13");
-            fail("BuildException expected: Duplicate Attribute");
-        } catch (BuildException ex) {
-            assertContains("The attribute \"Test\" may not occur more than once in the same section",
-                    ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The attribute \"Test\" may not occur more than once in the same section");
+        buildRule.executeTarget("test13");
     }
 
     /**
@@ -279,16 +263,15 @@
         assertEquals("Class-Path attribute was not set correctly - ",
             LONG_LINE, classpath);
 
-        String value = mainSection.getAttributeValue(LONG_68_NAME);
-        assertEquals("LONG_68_NAME_VALUE_MISMATCH", VALUE, value);
-        value = mainSection.getAttributeValue(LONG_70_NAME);
-        assertEquals("LONG_70_NAME_VALUE_MISMATCH", VALUE, value);
-        value = mainSection.getAttributeValue(NOT_LONG_NAME);
-        assertEquals("NOT_LONG_NAME_VALUE_MISMATCH", VALUE, value);
+        assertEquals("LONG_68_NAME_VALUE_MISMATCH", VALUE,
+                mainSection.getAttributeValue(LONG_68_NAME));
+        assertEquals("LONG_70_NAME_VALUE_MISMATCH", VALUE,
+                mainSection.getAttributeValue(LONG_70_NAME));
+        assertEquals("NOT_LONG_NAME_VALUE_MISMATCH", VALUE,
+                mainSection.getAttributeValue(NOT_LONG_NAME));
 
-        Set set = new HashSet();
-        FileReader fin = new FileReader(expandedManifest);
-        try {
+        Set<String> set = new HashSet<>();
+        try (FileReader fin = new FileReader(expandedManifest)) {
             BufferedReader in = new BufferedReader(fin);
 
             String read = in.readLine();
@@ -297,8 +280,6 @@
                 read = in.readLine();
             }
             in.close();
-        } finally {
-            fin.close();
         }
 
         assertTrue("Manifest file should have contained string ",
@@ -319,16 +300,16 @@
         buildRule.executeTarget("testOrder1");
 
         Manifest manifest = getManifest(expandedManifest);
-        Enumeration e = manifest.getSectionNames();
-        String section1 = (String) e.nextElement();
-        String section2 = (String) e.nextElement();
+        Enumeration<String> e = manifest.getSectionNames();
+        String section1 = e.nextElement();
+        String section2 = e.nextElement();
         assertEquals("First section name unexpected", "Test1", section1);
         assertEquals("Second section name unexpected", "Test2", section2);
 
         Manifest.Section section = manifest.getSection("Test1");
         e = section.getAttributeKeys();
-        String attr1Key = (String) e.nextElement();
-        String attr2Key = (String) e.nextElement();
+        String attr1Key = e.nextElement();
+        String attr2Key = e.nextElement();
         String attr1 = section.getAttribute(attr1Key).getName();
         String attr2 = section.getAttribute(attr2Key).getName();
         assertEquals("First attribute name unexpected", "TestAttr1", attr1);
@@ -343,16 +324,16 @@
         buildRule.executeTarget("testOrder2");
 
         Manifest manifest = getManifest(expandedManifest);
-        Enumeration e = manifest.getSectionNames();
-        String section1 = (String) e.nextElement();
-        String section2 = (String) e.nextElement();
+        Enumeration<String> e = manifest.getSectionNames();
+        String section1 = e.nextElement();
+        String section2 = e.nextElement();
         assertEquals("First section name unexpected", "Test2", section1);
         assertEquals("Second section name unexpected", "Test1", section2);
 
         Manifest.Section section = manifest.getSection("Test1");
         e = section.getAttributeKeys();
-        String attr1Key = (String) e.nextElement();
-        String attr2Key = (String) e.nextElement();
+        String attr1Key = e.nextElement();
+        String attr2Key = e.nextElement();
         String attr1 = section.getAttribute(attr1Key).getName();
         String attr2 = section.getAttribute(attr2Key).getName();
         assertEquals("First attribute name unexpected", "TestAttr2", attr1);
@@ -362,14 +343,10 @@
     /**
      * file attribute for manifest task is required.
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void testNoFile() {
-        try {
-            buildRule.executeTarget("testNoFile");
-            fail("BuildException expected: file is required");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testNoFile");
+        //TODO assert value
     }
 
     /**
@@ -391,85 +368,77 @@
         buildRule.executeTarget("testUpdate");
         Manifest mf = getManifest(new File(outDir, "mftest.mf"));
         assertNotNull(mf);
-        assertTrue(!Manifest.getDefaultManifest().equals(mf));
+        assertNotEquals(Manifest.getDefaultManifest(), mf);
         String mfAsString = mf.toString();
         assertNotNull(mfAsString);
-        assertTrue(mfAsString.startsWith("Manifest-Version: 2.0"));
-        assertTrue(mfAsString.contains("Foo: Bar"));
+        assertThat(mfAsString, startsWith("Manifest-Version: 2.0"));
+        assertThat(mfAsString, containsString("Foo: Bar"));
 
         mf = getManifest(new File(outDir, "mftest2.mf"));
         assertNotNull(mf);
         mfAsString = mf.toString();
         assertNotNull(mfAsString);
-        assertEquals(-1, mfAsString.indexOf("Foo: Bar"));
-        assertTrue(mfAsString.contains("Foo: Baz"));
+        assertThat(mfAsString, containsString("Foo: Baz"));
+        assertThat(mfAsString, not(containsString("Foo: Bar")));
     }
 
     @Test
     public void testFrom() {
         buildRule.executeTarget("testFrom");
-        assertContains(Manifest.ERROR_FROM_FORBIDDEN, buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString(Manifest.ERROR_FROM_FORBIDDEN));
     }
 
-    @Test
+    /**
+     * Expected failure: manifest attribute names must not contain ' '
+     */
+    @Test(expected = BuildException.class)
     public void testIllegalName() {
-        try {
-            buildRule.executeTarget("testIllegalName");
-            fail("BuildException expected: Manifest attribute names must not contain ' '");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testIllegalName");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: manifest section names must not contain ' '
+     */
+    @Test(expected = BuildException.class)
     public void testIllegalNameInSection() {
-        try {
-            buildRule.executeTarget("testIllegalNameInSection");
-            fail("BuildException expected: Manifest attribute names must not contain ' '");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testIllegalNameInSection");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: manifest attribute names must not begin with '-'
+     */
+    @Test(expected = BuildException.class)
     public void testIllegalNameBegin() {
-        try {
-            buildRule.executeTarget("testIllegalNameInSection");
-            fail("BuildException expected: Manifest attribute names must not start with '-' at the begin.");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testIllegalNameInSection");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: manifest attribute names must not contain '.'
+     */
+    @Test(expected = BuildException.class)
     public void testIllegalName2() {
-        try {
-            buildRule.executeTarget("testIllegalName");
-            fail("BuildException expected: Manifest attribute names must not contain '.'");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testIllegalName");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: manifest attribute names must not contain '*'
+     */
+    @Test(expected = BuildException.class)
     public void testIllegalName3() {
-        try {
-            buildRule.executeTarget("testIllegalName");
-            fail("BuildException expected: Manifest attribute names must not contain '*'");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
-    }
+        buildRule.executeTarget("testIllegalName");
+        // TODO assert value
+     }
 
     /**
      * Reads mftest.mf.
      */
     private Manifest getManifest(File file) throws IOException, ManifestException {
-        FileReader r = new FileReader(file);
-        try {
+        try (FileReader r = new FileReader(file)) {
             return new Manifest(r);
-        } finally {
-            r.close();
         }
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/MkdirTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/MkdirTest.java
index 9864a4a..e14ccb0 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/MkdirTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/MkdirTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,14 +19,14 @@
 
 import java.io.File;
 
+import static org.junit.Assert.assertTrue;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 /**
  */
 public class MkdirTest {
@@ -39,34 +39,27 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/mkdir.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument missing
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
     }
 
-    @Test
+    /**
+     * Expected failure due to directory already existing as a file
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: directory already exists as a file");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
     }
 
     @Test
     public void test3() {
         buildRule.executeTarget("test3");
         File f = new File(buildRule.getProject().getProperty("output"), "testdir.tmp");
-        if (!f.exists() || !f.isDirectory()) {
-            fail("mkdir failed");
-        } else {
-            f.delete();
-        }
+        assertTrue("mkdir failed", f.exists() && f.isDirectory());
+        f.delete();
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/MoveTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/MoveTest.java
index 9f5a799..4a0ba79 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/MoveTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/MoveTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,6 +28,7 @@
 import java.io.IOException;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -65,59 +66,59 @@
 
     /** Bugzilla Report 11732 */
     @Test
-    public void testDirectoryRemoval() throws IOException {
+    public void testDirectoryRemoval() {
 
         buildRule.executeTarget("testDirectoryRemoval");
         String output = buildRule.getProject().getProperty("output");
-        assertTrue(!new File(output,"E/B/1").exists());
+        assertFalse(new File(output, "E/B/1").exists());
         assertTrue(new File(output, "E/C/2").exists());
-        assertTrue(new File(output,"E/D/3").exists());
-        assertTrue(new File(output,"A/B/1").exists());
-        assertTrue(!new File(output,"A/C/2").exists());
-        assertTrue(!new File(output,"A/D/3").exists());
-        assertTrue(!new File(output,"A/C").exists());
-        assertTrue(!new File(output,"A/D").exists());
+        assertTrue(new File(output, "E/D/3").exists());
+        assertTrue(new File(output, "A/B/1").exists());
+        assertFalse(new File(output, "A/C/2").exists());
+        assertFalse(new File(output, "A/D/3").exists());
+        assertFalse(new File(output, "A/C").exists());
+        assertFalse(new File(output, "A/D").exists());
     }
 
     /** Bugzilla Report 18886 */
     @Test
-    public void testDirectoryRetaining() throws IOException {
+    public void testDirectoryRetaining() {
         buildRule.executeTarget("testDirectoryRetaining");
         String output = buildRule.getProject().getProperty("output");
-        assertTrue(new File(output,"E").exists());
-        assertTrue(new File(output,"E/1").exists());
-        assertTrue(!new File(output,"A/1").exists());
-        assertTrue(new File(output,"A").exists());
+        assertTrue(new File(output, "E").exists());
+        assertTrue(new File(output, "E/1").exists());
+        assertFalse(new File(output, "A/1").exists());
+        assertTrue(new File(output, "A").exists());
     }
 
     @Test
-    public void testCompleteDirectoryMove() throws IOException {
+    public void testCompleteDirectoryMove() {
         testCompleteDirectoryMove("testCompleteDirectoryMove");
     }
 
     @Test
-    public void testCompleteDirectoryMove2() throws IOException {
+    public void testCompleteDirectoryMove2() {
         testCompleteDirectoryMove("testCompleteDirectoryMove2");
     }
 
-    private void testCompleteDirectoryMove(String target) throws IOException {
+    private void testCompleteDirectoryMove(String target) {
         buildRule.executeTarget(target);
         String output = buildRule.getProject().getProperty("output");
-        assertTrue(new File(output,"E").exists());
-        assertTrue(new File(output,"E/1").exists());
-        assertTrue(!new File(output,"A/1").exists());
+        assertTrue(new File(output, "E").exists());
+        assertTrue(new File(output, "E/1").exists());
+        assertFalse(new File(output, "A/1").exists());
         // <path> swallows the basedir, it seems
-        //assertTrue(!new File(getOutputDir(),"A").exists());
+        //assertFalse(new File(getOutputDir(), "A").exists());
     }
 
     @Test
-    public void testPathElementMove() throws IOException {
+    public void testPathElementMove() {
         buildRule.executeTarget("testPathElementMove");
         String output = buildRule.getProject().getProperty("output");
-        assertTrue(new File(output,"E").exists());
-        assertTrue(new File(output,"E/1").exists());
-        assertTrue(!new File(output,"A/1").exists());
-        assertTrue(new File(output,"A").exists());
+        assertTrue(new File(output, "E").exists());
+        assertTrue(new File(output, "E/1").exists());
+        assertFalse(new File(output, "A/1").exists());
+        assertTrue(new File(output, "A").exists());
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/MultiMapTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/MultiMapTest.java
index 2273ef2..151acd2 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/MultiMapTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/MultiMapTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/NiceTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/NiceTest.java
index 635c2d5..18add5a 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/NiceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/NiceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,9 +23,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * test nice
@@ -35,6 +33,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/nice.xml");
@@ -62,22 +63,16 @@
 
     @Test
     public void testTooSlow() {
-        try {
-            buildRule.executeTarget("too_slow");
-            fail("BuildException expected: out of range");
-        } catch (BuildException ex) {
-            assertContains("out of the range 1-10", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("out of the range 1-10");
+        buildRule.executeTarget("too_slow");
     }
 
     @Test
     public void testTooFast() {
-        try {
-            buildRule.executeTarget("too_fast");
-            fail("BuildException expected: out of range");
-        } catch (BuildException ex) {
-            assertContains("out of the range 1-10", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("out of the range 1-10");
+        buildRule.executeTarget("too_fast");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ParallelTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ParallelTest.java
index 0da5978..c3f298a 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ParallelTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ParallelTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,9 +27,12 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasProperty;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Test of the parallel TaskContainer
@@ -39,6 +42,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     /** Standard property value for the basic test */
     public static final String DIRECT_MESSAGE = "direct";
     /** Standard property value for the basic and fail test */
@@ -46,20 +52,18 @@
     /** Standard property value for the fail test */
     public static final String FAILURE_MESSAGE = "failure";
 
-    /** the build file associated with this test */
-    public static final String TEST_BUILD_FILE = "src/etc/testcases/taskdefs/parallel.xml";
-
+    private Project p;
     /** The JUnit setup method */
     @Before
     public void setUp() {
-        buildRule.configureProject(TEST_BUILD_FILE);
+        buildRule.configureProject("src/etc/testcases/taskdefs/parallel.xml");
+        p = buildRule.getProject();
     }
 
     /** tests basic operation of the parallel task */
     @Test
     public void testBasic() {
         // should get no output at all
-        Project p = buildRule.getProject();
         p.setUserProperty("test.direct", DIRECT_MESSAGE);
         p.setUserProperty("test.delayed", DELAYED_MESSAGE);
         buildRule.executeTarget("testBasic");
@@ -75,7 +79,6 @@
     @Test
     public void testThreadCount() {
         // should get no output at all
-        Project p = buildRule.getProject();
         p.setUserProperty("test.direct", DIRECT_MESSAGE);
         p.setUserProperty("test.delayed", DELAYED_MESSAGE);
         buildRule.executeTarget("testThreadCount");
@@ -100,7 +103,7 @@
         int firstPipe = s.indexOf('|', start);
         int beginSlash = s.indexOf('/', firstPipe);
         int lastPipe = s.indexOf('|', beginSlash);
-        if ((firstPipe == -1) || (beginSlash == -1) || (lastPipe == -1)) {
+        if (firstPipe == -1 || beginSlash == -1 || lastPipe == -1) {
             return -1;
         }
 
@@ -108,6 +111,9 @@
         int current = 0;
         int pos = beginSlash + 1;
         while (pos < lastPipe) {
+            assertTrue("Only expect '+-' in result count, found " + s.charAt(pos)
+                            + " at position " + (pos + 1),
+                    s.charAt(pos) == '+' || s.charAt(pos) == '-');
             switch (s.charAt(pos++)) {
                 case '+':
                     current++;
@@ -116,13 +122,10 @@
                     current--;
                     break;
                 default:
-                    fail("Only expect '+-' in result count, found "
-                            + s.charAt(--pos) + " at position " + pos);
+                    break;
             }
-            if (current > max) {
-                fail("Number of executing threads exceeded number allowed: "
-                        + current + " > " + max);
-            }
+            assertTrue("Number of executing threads exceeded number allowed: "
+                    + current + " > " + max, current <= max);
         }
         return lastPipe;
     }
@@ -132,21 +135,16 @@
     @Test
     public void testFail() {
         // should get no output at all
-        Project p = buildRule.getProject();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(FAILURE_MESSAGE);
         p.setUserProperty("test.failure", FAILURE_MESSAGE);
         p.setUserProperty("test.delayed", DELAYED_MESSAGE);
-        try {
-            buildRule.executeTarget("testFail");
-            fail("fail task in one parallel branch");
-        } catch (BuildException ex) {
-            assertEquals(FAILURE_MESSAGE, ex.getMessage());
-        }
+        buildRule.executeTarget("testFail");
     }
 
     /** tests the demuxing of output streams in a multithreaded situation */
     @Test
     public void testDemux() {
-        Project p = buildRule.getProject();
         p.addTaskDefinition("demuxtest", DemuxOutputTask.class);
         synchronized (System.out) {
             PrintStream out = System.out;
@@ -164,29 +162,23 @@
     }
 
     /**
-     * @see "https://issues.apache.org/bugzilla/show_bug.cgi?id=55539"
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=55539">bug 55539</a>
      */
     @Test
     public void testSingleExit() {
-        try {
-            buildRule.executeTarget("testSingleExit");
-            fail("ExitStatusException should have been thrown");
-        } catch (ExitStatusException ex) {
-            assertEquals(42, ex.getStatus());
-        }
+        thrown.expect(ExitStatusException.class);
+        thrown.expect(hasProperty("status", equalTo(42)));
+        buildRule.executeTarget("testSingleExit");
     }
 
     /**
-     * @see "https://issues.apache.org/bugzilla/show_bug.cgi?id=55539"
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=55539">bug 55539</a>
      */
     @Test
     public void testExitAndOtherException() {
-        try {
-            buildRule.executeTarget("testExitAndOtherException");
-            fail("ExitStatusException should have been thrown");
-        } catch (ExitStatusException ex) {
-            assertEquals(42, ex.getStatus());
-        }
+        thrown.expect(ExitStatusException.class);
+        thrown.expect(hasProperty("status", equalTo(42)));
+        buildRule.executeTarget("testExitAndOtherException");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/PathConvertTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/PathConvertTest.java
deleted file mode 100644
index f29dc12..0000000
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/PathConvertTest.java
+++ /dev/null
@@ -1,76 +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 org.apache.tools.ant.BuildFileRule;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Unit test for the &lt;pathconvert&gt; task.
- */
-public class PathConvertTest {
-
-    @Rule
-    public final BuildFileRule buildRule = new BuildFileRule();
-
-    private static final String BUILD_PATH = "src/etc/testcases/taskdefs/";
-    private static final String BUILD_FILENAME = "pathconvert.xml";
-    private static final String BUILD_FILE = BUILD_PATH + BUILD_FILENAME;
-
-    @Before
-    public void setUp() {
-        buildRule.configureProject(BUILD_FILE);
-    }
-
-    @Test
-    public void testMap() {
-        test("testmap");
-    }
-
-    @Test
-    public void testMapper() {
-        test("testmapper");
-    }
-
-    @Test
-    public void testNoTargetOs() {
-        buildRule.executeTarget("testnotargetos");
-    }
-
-    /**
-     * Tests that if a {@code mappedresource}, that excludes certain resources, is used in a {@code pathconvert},
-     * then it doesn't lead to a {@link NullPointerException}.
-     *
-     * @see <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=62076">bz-62076</a> for more details
-     */
-    @Test
-    public void testNonMatchingMapper() {
-        buildRule.executeTarget("test-nonmatching-mapper");
-    }
-
-    private void test(String target) {
-        buildRule.executeTarget(target);
-        assertEquals("test#" + BUILD_FILENAME, buildRule.getProject().getProperty("result"));
-    }
-
-}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/PreSetDefTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/PreSetDefTest.java
index 65b66a4..61c8fa5 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/PreSetDefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/PreSetDefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,10 +25,9 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  */
@@ -37,6 +36,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/presetdef.xml");
@@ -98,22 +100,16 @@
 
     @Test
     public void testCorrectTaskNameBadAttr() {
-        try {
-            buildRule.executeTarget("correct_taskname_badattr");
-            fail("BuildException expected: attribute message");
-        } catch (BuildException ex) {
-            assertContains("javac doesn't support the", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("javac doesn't support the");
+        buildRule.executeTarget("correct_taskname_badattr");
     }
 
     @Test
     public void testCorrectTaskNameBadEl() {
-        try {
-            buildRule.executeTarget("correct_taskname_badel");
-            fail("BuildException expected: element message");
-        } catch (BuildException ex) {
-            assertContains("javac doesn't support the", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("javac doesn't support the");
+        buildRule.executeTarget("correct_taskname_badel");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ProcessDestroyerTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ProcessDestroyerTest.java
index eadac40..71d105f 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ProcessDestroyerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ProcessDestroyerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java
index 16c4d8a..29bf516 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,19 +18,20 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeNoException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.util.FileUtils;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  */
@@ -39,8 +40,8 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
-    /** Utilities used for file operations */
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
     public void setUp() {
@@ -59,35 +60,33 @@
     @Test
     public void test2() {
         buildRule.executeTarget("test2");
-        assertContains("testprop1=aa, testprop3=xxyy, testprop4=aazz", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("testprop1=aa, testprop3=xxyy, testprop4=aazz"));
     }
 
+    /**
+     * Fail due to circular definition
+     */
     @Test
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("Did not throw exception on circular exception");
-        } catch (BuildException e) {
-            assertTrue("Circular definition not detected - ",
-                    e.getMessage().contains("was circularly defined"));
-        }
-
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("was circularly defined");
+        buildRule.executeTarget("test3");
     }
 
     @Test
     public void test4() {
         buildRule.executeTarget("test4");
-        assertContains("http.url is http://localhost:999", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("http.url is http://localhost:999"));
     }
 
     @Test
     public void test5() {
-        String baseDir = buildRule.getProject().getProperty("basedir");
-        String uri = FILE_UTILS.toURI(baseDir + "/property3.properties");
+        String baseDir = buildRule.getProject().getProperty(MagicNames.PROJECT_BASEDIR);
+        String uri = FileUtils.getFileUtils().toURI(baseDir + "/property3.properties");
         buildRule.getProject().setNewProperty("test5.url", uri);
 
         buildRule.executeTarget("test5");
-        assertContains("http.url is http://localhost:999", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("http.url is http://localhost:999"));
     }
 
     @Test
@@ -96,32 +95,30 @@
         assertEquals("80", buildRule.getProject().getProperty("server1.http.port"));
     }
 
+    /**
+     * Fail due to prefix allowed only non-resource/file load
+     */
     @Test
     public void testPrefixFailure() {
-       try {
-            buildRule.executeTarget("prefix.fail");
-            fail("Did not throw exception on invalid use of prefix");
-        } catch (BuildException e) {
-            assertContains("Prefix allowed on non-resource/file load - ",
-                     "Prefix is only valid", e.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Prefix is only valid");
+        buildRule.executeTarget("prefix.fail");
     }
 
+    /**
+     * Fail due to circular definition
+     */
     @Test
     public void testCircularReference() {
-        try {
-            buildRule.executeTarget("testCircularReference");
-            fail("Did not throw exception on circular exception");
-        } catch (BuildException e) {
-            assertContains("Circular definition not detected - ",
-                         "was circularly defined", e.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("was circularly defined");
+        buildRule.executeTarget("testCircularReference");
     }
 
     @Test
     public void testThisIsNotACircularReference() {
         buildRule.executeTarget("thisIsNotACircularReference");
-        assertContains("b is A/A/A", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("b is A/A/A"));
     }
 
     @Test
@@ -129,12 +126,11 @@
         try {
             Class.forName("java.lang.Iterable");
         } catch (ClassNotFoundException e) {
-            Assume.assumeNoException("XML Loading only on Java 5+", e);
+            assumeNoException("XML Loading only on Java 5+", e);
         }
         buildRule.executeTarget("testXmlProperty");
         assertEquals("ONE", buildRule.getProject().getProperty("xml.one"));
         assertEquals("TWO", buildRule.getProject().getProperty("xml.two"));
-
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ProtectedJarMethodsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ProtectedJarMethodsTest.java
index c83a772..c3ca6a2 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ProtectedJarMethodsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ProtectedJarMethodsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,15 +21,18 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.hasItem;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -37,8 +40,6 @@
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
-    private static String tempJar = "tmp.jar";
-
 
     @Before
     public void setUp() {
@@ -49,9 +50,10 @@
     @Test
     public void testGrabFilesAndDirs() throws IOException {
         buildRule.executeTarget("testIndexTests");
+        String tempJar = "tmp.jar";
         String archive = buildRule.getProject().getProperty(tempJar);
-        ArrayList dirs = new ArrayList();
-        ArrayList files = new ArrayList();
+        List<String> dirs = new ArrayList<>();
+        List<String> files = new ArrayList<>();
         String[] expectedDirs = new String[] {
             "META-INF/",
             "sub/",
@@ -60,16 +62,14 @@
             "foo",
         };
         Jar.grabFilesAndDirs(archive, dirs, files);
+
         assertEquals(expectedDirs.length, dirs.size());
-        for (int i = 0; i < expectedDirs.length; i++) {
-            assertTrue("Found " + expectedDirs[i],
-                       dirs.contains(expectedDirs[i]));
-        }
+        Arrays.stream(expectedDirs).forEach(expectedDir -> assertThat("Found " + expectedDir,
+                dirs, hasItem(expectedDir)));
+
         assertEquals(expectedFiles.length, files.size());
-        for (int i = 0; i < expectedFiles.length; i++) {
-            assertTrue("Found " + expectedFiles[i],
-                       files.contains(expectedFiles[i]));
-        }
+        Arrays.stream(expectedFiles).forEach(expectedFile -> assertThat("Found " + expectedFile,
+                files, hasItem(expectedFile)));
     }
 
     @Test
@@ -81,26 +81,23 @@
 
     @Test
     public void testFindJarNameNoMatch() {
-        assertNull(Jar.findJarName("foo", new String[] {"bar"}));
+        assertNull(Jar.findJarName("foo", new String[] { "bar" }));
     }
 
     @Test
     public void testFindJarNameSimpleMatches() {
-        assertEquals("foo", Jar.findJarName("foo", new String[] {"foo"}));
-        assertEquals("lib/foo", Jar.findJarName("foo",
-                                                new String[] {"lib/foo"}));
-        assertEquals("foo", Jar.findJarName("bar" + File.separatorChar + "foo",
-                                            new String[] {"foo"}));
+        assertEquals("foo", Jar.findJarName("foo", new String[] { "foo" }));
         assertEquals("lib/foo",
-                     Jar.findJarName("bar" + File.separatorChar + "foo",
-                                     new String[] {"lib/foo"}));
+            Jar.findJarName("foo", new String[] { "lib/foo" }));
+        assertEquals("foo", Jar.findJarName("bar" + File.separatorChar + "foo",
+            new String[] { "foo" }));
+        assertEquals("lib/foo", Jar.findJarName(
+            "bar" + File.separatorChar + "foo", new String[] { "lib/foo" }));
     }
 
     @Test
     public void testFindJarNameLongestMatchWins() {
-        assertEquals("lib/foo",
-                     Jar.findJarName("lib/foo",
-                                     new String[] {"foo", "lib/foo",
-                                                   "lib/bar/foo"}));
+        assertEquals("lib/foo", Jar.findJarName("lib/foo",
+            new String[] { "foo", "lib/foo", "lib/bar/foo" }));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/RecorderTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/RecorderTest.java
index fb6f118..88874d6 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/RecorderTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/RecorderTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/RenameTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/RenameTest.java
index ca37799..9fec45d 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/RenameTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/RenameTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 public class RenameTest {
 
     @Rule
@@ -36,43 +34,37 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/rename.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to missing required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException should have been thrown:  required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
-    }
-    @Test
-    public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException should have been thrown: required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
-    }
-    @Test
-    public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException should have been thrown: required argument missing");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
     }
 
-    @Test
+    /**
+     * Expected failure due to missing required argument
+     */
+    @Test(expected = BuildException.class)
+    public void test2() {
+        buildRule.executeTarget("test2");
+    }
+
+    /**
+     * Expected failure due to missing required argument
+     */
+    @Test(expected = BuildException.class)
+    public void test3() {
+        buildRule.executeTarget("test3");
+    }
+
+    /**
+     * Expected failure due to source same as destination
+     */
     @Ignore("Previously commented out")
+    @Test
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException should have been thrown: source and destination the same");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ReplaceTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ReplaceTest.java
index 4a9691e..66ba359 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ReplaceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ReplaceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,11 +20,9 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-
-import junit.framework.AssertionFailedError;
+import java.nio.file.Files;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
@@ -35,7 +33,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 /**
@@ -51,44 +48,40 @@
         buildRule.executeTarget("setUp");
     }
 
-    @Test
+    /**
+     * Fail: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail: empty token not allowed
+     */
+    @Test(expected = BuildException.class)
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException expected: empty token not allowed");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
+        // TODO assert value
     }
 
     @Test
@@ -96,24 +89,22 @@
         buildRule.executeTarget("test5");
     }
 
-    @Test
+    /**
+     * Fail: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test6() {
-        try {
-            buildRule.executeTarget("test6");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test6");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Fail: empty token not allowed
+     */
+    @Test(expected = BuildException.class)
     public void test7() {
-        try {
-            buildRule.executeTarget("test7");
-            fail("BuildException expected: empty token not allowed");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test7");
+        // TODO assert value
     }
 
     @Test
@@ -123,14 +114,13 @@
 
     @Test
     public void test9() throws IOException {
-
         buildRule.executeTarget("test9");
         assertEqualContent(new File(buildRule.getOutputDir(), "result.txt"),
                     new File(buildRule.getOutputDir(), "output.txt"));
     }
 
     @Test
-    public void testNoPreserveLastModified() throws Exception {
+    public void testNoPreserveLastModified() {
         buildRule.executeTarget("lastModifiedSetup");
         File testFile = new File(buildRule.getOutputDir(), "test.txt");
         assumeTrue("Could not change file modification time",
@@ -141,41 +131,27 @@
     }
 
     @Test
-    public void testPreserveLastModified() throws Exception {
+    public void testPreserveLastModified() {
         buildRule.executeTarget("lastModifiedSetup");
         File testFile = new File(buildRule.getOutputDir(), "test.txt");
         assumeTrue("Could not change file modification time",
                 testFile.setLastModified(testFile.lastModified() - FileUtils.getFileUtils().getFileTimestampGranularity() * 5));
         long ts1 = testFile.lastModified();
         buildRule.executeTarget("testPreserve");
-        assertTrue(ts1 == new File(buildRule.getOutputDir(), "test.txt").lastModified());
+        assertEquals(ts1, new File(buildRule.getOutputDir(), "test.txt").lastModified());
     }
 
-    public void assertEqualContent(File expect, File result)
-        throws AssertionFailedError, IOException {
-        if (!result.exists()) {
-            fail("Expected file " + result + " doesn\'t exist");
-        }
+    public void assertEqualContent(File expect, File result) throws IOException {
+        assertTrue("Expected file " + result + " doesn't exist", result.exists());
 
-        InputStream inExpect = null;
-        InputStream inResult = null;
-        try {
-            inExpect = new BufferedInputStream(new FileInputStream(expect));
-            inResult = new BufferedInputStream(new FileInputStream(result));
-
+        try (InputStream inExpect = new BufferedInputStream(Files.newInputStream(expect.toPath()));
+             InputStream inResult = new BufferedInputStream(Files.newInputStream(result.toPath()))) {
             int expectedByte = inExpect.read();
             while (expectedByte != -1) {
                 assertEquals(expectedByte, inResult.read());
                 expectedByte = inExpect.read();
             }
             assertEquals("End of file", -1, inResult.read());
-        } finally {
-            if (inResult != null) {
-                inResult.close();
-            }
-            if (inExpect != null) {
-                inExpect.close();
-            }
         }
     }
 }
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 4ca4fe2..3b78b81 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,20 +19,21 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory;
 import org.apache.tools.ant.taskdefs.rmic.DefaultRmicAdapter;
+import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory;
 import org.apache.tools.ant.util.JavaEnvUtils;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Date: 04-Aug-2004
@@ -40,24 +41,25 @@
  */
 public class RmicAdvancedTest {
 
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/rmic/";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     /**
      * The JUnit setup method
      */
     @Before
-    public void setUp() throws Exception {
-        buildRule.configureProject(TASKDEFS_DIR + "rmic.xml");
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/rmic/rmic.xml");
     }
 
     /**
      * verify that "default" binds us to the default compiler
      */
     @Test
-    public void testDefault() throws Exception {
+    public void testDefault() {
         buildRule.executeTarget("testDefault");
     }
 
@@ -65,7 +67,7 @@
      * verify that "default" binds us to the default compiler
      */
     @Test
-    public void testDefaultDest() throws Exception {
+    public void testDefaultDest() {
         buildRule.executeTarget("testDefaultDest");
     }
 
@@ -73,7 +75,7 @@
      * verify that "" binds us to the default compiler
      */
     @Test
-    public void testEmpty() throws Exception {
+    public void testEmpty() {
         buildRule.executeTarget("testEmpty");
     }
 
@@ -81,7 +83,7 @@
      * verify that "" binds us to the default compiler
      */
     @Test
-    public void testEmptyDest() throws Exception {
+    public void testEmptyDest() {
         buildRule.executeTarget("testEmptyDest");
     }
 
@@ -89,7 +91,7 @@
      * test sun's rmic compiler
      */
     @Test
-    public void testRmic() throws Exception {
+    public void testRmic() {
         buildRule.executeTarget("testRmic");
     }
 
@@ -97,7 +99,7 @@
      * test sun's rmic compiler
      */
     @Test
-    public void testRmicDest() throws Exception {
+    public void testRmicDest() {
         buildRule.executeTarget("testRmicDest");
     }
 
@@ -106,7 +108,7 @@
      * out -J arguments when not forking
      */
     @Test
-    public void testRmicJArg() throws Exception {
+    public void testRmicJArg() {
         buildRule.executeTarget("testRmicJArg");
     }
 
@@ -115,7 +117,7 @@
      * out -J arguments when not forking
      */
     @Test
-    public void testRmicJArgDest() throws Exception {
+    public void testRmicJArgDest() {
         buildRule.executeTarget("testRmicJArgDest");
     }
 
@@ -123,7 +125,7 @@
      * A unit test for JUnit
      */
     @Test
-    public void testKaffe() throws Exception {
+    public void testKaffe() {
         buildRule.executeTarget("testKaffe");
     }
 
@@ -131,7 +133,7 @@
      * A unit test for JUnit
      */
     @Test
-    public void testKaffeDest() throws Exception {
+    public void testKaffeDest() {
         buildRule.executeTarget("testKaffeDest");
     }
 
@@ -141,7 +143,7 @@
      */
     @Test
     @Ignore("WLRmic tests don't work")
-    public void XtestWlrmic() throws Exception {
+    public void XtestWlrmic() {
         buildRule.executeTarget("testWlrmic");
     }
 
@@ -150,7 +152,7 @@
      */
     @Test
     @Ignore("WLRmic tests don't work")
-    public void XtestWlrmicJArg() throws Exception {
+    public void XtestWlrmicJArg() {
         buildRule.executeTarget("testWlrmicJArg");
     }
 
@@ -158,7 +160,7 @@
      * test the forking compiler
      */
     @Test
-    public void testForking() throws Exception {
+    public void testForking() {
         buildRule.executeTarget("testForking");
     }
 
@@ -166,7 +168,7 @@
      * test the forking compiler
      */
     @Test
-    public void testForkingAntClasspath() throws Exception {
+    public void testForkingAntClasspath() {
         buildRule.executeTarget("testForkingAntClasspath");
     }
 
@@ -174,7 +176,7 @@
      * test the forking compiler
      */
     @Test
-    public void testForkingAntClasspathDest() throws Exception {
+    public void testForkingAntClasspathDest() {
         buildRule.executeTarget("testForkingAntClasspathDest");
     }
 
@@ -182,7 +184,7 @@
      * test the forking compiler
      */
     @Test
-    public void testAntClasspath() throws Exception {
+    public void testAntClasspath() {
         buildRule.executeTarget("testAntClasspath");
     }
 
@@ -190,7 +192,7 @@
      * test the forking compiler
      */
     @Test
-    public void testAntClasspathDest() throws Exception {
+    public void testAntClasspathDest() {
         buildRule.executeTarget("testAntClasspathDest");
     }
 
@@ -198,20 +200,17 @@
      * A unit test for JUnit
      */
     @Test
-    public void testBadName() throws Exception {
-        try {
-            buildRule.executeTarget("testBadName");
-            fail("Compile not known");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(RmicAdapterFactory.ERROR_UNKNOWN_COMPILER, ex.getMessage());
-        }
+    public void testBadName() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(RmicAdapterFactory.ERROR_UNKNOWN_COMPILER);
+        buildRule.executeTarget("testBadName");
     }
 
     /**
      * load an adapter by name
      */
     @Test
-    public void testExplicitClass() throws Exception {
+    public void testExplicitClass() {
         buildRule.executeTarget("testExplicitClass");
     }
 
@@ -219,41 +218,26 @@
      * A unit test for JUnit
      */
     @Test
-    public void testWrongClass() throws Exception {
-        try {
-            buildRule.executeTarget("testWrongClass");
-            fail("Class not an RMIC adapter");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(RmicAdapterFactory.ERROR_NOT_RMIC_ADAPTER, ex.getMessage());
-        }
+    public void testWrongClass() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(RmicAdapterFactory.ERROR_NOT_RMIC_ADAPTER);
+        buildRule.executeTarget("testWrongClass");
     }
 
     /**
      * A unit test for JUnit
      */
     @Test
-    public void testDefaultBadClass() throws Exception {
-        Assume.assumeFalse(JavaEnvUtils.isAtLeastJavaVersion("15"));
+    public void testDefaultBadClass() {
+        assumeFalse("Current system is Java 15 or newer",
+                    JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(Rmic.ERROR_RMIC_FAILED);
         try {
             buildRule.executeTarget("testDefaultBadClass");
-            fail("expected the class to fail");
-        } catch(BuildException ex) {
-            AntAssert.assertContains(Rmic.ERROR_RMIC_FAILED, ex.getMessage());
-        }
-        //dont look for much text here as it is vendor and version dependent
-        AntAssert.assertContains("unimplemented.class", buildRule.getLog());
-    }
-
-    /**
-     * A unit test for JUnit
-     */
-    @Test
-    public void testMagicProperty() throws Exception {
-        try {
-            buildRule.executeTarget("testMagicProperty");
-            fail("Magic property not working");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(RmicAdapterFactory.ERROR_UNKNOWN_COMPILER, ex.getMessage());
+        } finally {
+            // don't look for much text here as it is vendor and version dependent
+            assertThat(buildRule.getLog(), containsString("unimplemented.class"));
         }
     }
 
@@ -261,223 +245,265 @@
      * A unit test for JUnit
      */
     @Test
-    public void testMagicPropertyOverridesEmptyString() throws Exception {
-        try {
-            buildRule.executeTarget("testMagicPropertyOverridesEmptyString");
-            fail("Magic property not working");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(RmicAdapterFactory.ERROR_UNKNOWN_COMPILER, ex.getMessage());
-        }
+    public void testMagicProperty() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(RmicAdapterFactory.ERROR_UNKNOWN_COMPILER);
+        buildRule.executeTarget("testMagicProperty");
+    }
+
+    /**
+     * A unit test for JUnit
+     */
+    @Test
+    public void testMagicPropertyOverridesEmptyString() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(RmicAdapterFactory.ERROR_UNKNOWN_COMPILER);
+        buildRule.executeTarget("testMagicPropertyOverridesEmptyString");
     }
 
     @Test
-    public void testMagicPropertyIsEmptyString() throws Exception {
+    public void testMagicPropertyIsEmptyString() {
         buildRule.executeTarget("testMagicPropertyIsEmptyString");
     }
 
     @Test
     @Ignore("Previously named to prevent execution")
-    public void NotestFailingAdapter() throws Exception {
-        try {
-            buildRule.executeTarget("testFailingAdapter");
-            fail("Expected failures to propagate");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(Rmic.ERROR_RMIC_FAILED, ex.getMessage());
-        }
+    public void NotestFailingAdapter() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(Rmic.ERROR_RMIC_FAILED);
+        buildRule.executeTarget("testFailingAdapter");
     }
 
     /**
      * test that version 1.1 stubs are good
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testVersion11() throws Exception {
+    public void testVersion11() {
         buildRule.executeTarget("testVersion11");
     }
 
     /**
      * test that version 1.1 stubs are good
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testVersion11Dest() throws Exception {
+    public void testVersion11Dest() {
         buildRule.executeTarget("testVersion11Dest");
     }
 
     /**
      * test that version 1.2 stubs are good
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testVersion12() throws Exception {
+    public void testVersion12() {
         buildRule.executeTarget("testVersion12");
     }
 
     /**
      * test that version 1.2 stubs are good
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testVersion12Dest() throws Exception {
+    public void testVersion12Dest() {
         buildRule.executeTarget("testVersion12Dest");
     }
 
     /**
      * test that version compat stubs are good
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testVersionCompat() throws Exception {
+    public void testVersionCompat() {
         buildRule.executeTarget("testVersionCompat");
     }
 
     /**
      * test that version compat stubs are good
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testVersionCompatDest() throws Exception {
+    public void testVersionCompatDest() {
         buildRule.executeTarget("testVersionCompatDest");
     }
 
     /**
-     * test that passes -Xnew to sun's rmic.
-     *
-     * @throws Exception
+     * test that passes -Xnew to sun's rmic running in a different VM.
      */
     @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");
+    public void testXnewForked() {
+        assumeFalse("Current system is Java 9 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        buildRule.executeTarget("testXnewForked");
     }
 
     /**
      * test that passes -Xnew to sun's rmic running in a different VM.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testXnewForked() throws Exception {
-        xnewTest("testXnewForked");
+    public void testXnewForkedJava9plus() {
+        assumeTrue("Current system is Java 8 or older",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        assumeFalse("Current system is Java 15 or newer",
+                    JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("JDK9 has removed support for -Xnew");
+        buildRule.executeTarget("testXnewForked");
     }
 
     /**
      * test that passes -Xnew to sun's rmic running in a different VM.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testXnewForkedDest() throws Exception {
-        xnewTest("testXnewForkedDest");
+    public void testXnewForkedDest() {
+        assumeFalse("Current system is Java 9 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        buildRule.executeTarget("testXnewForkedDest");
+    }
+
+    /**
+     * test that passes -Xnew to sun's rmic running in a different VM.
+     */
+    @Test
+    public void testXnewForkedDestJava9plus() {
+        assumeTrue("Current system is Java 8 or older",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        assumeFalse("Current system is Java 15 or newer",
+                    JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("JDK9 has removed support for -Xnew");
+        buildRule.executeTarget("testXnewForkedDest");
     }
 
     /**
      * test that runs the new xnew compiler adapter.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testXnewCompiler() throws Exception {
-        xnewTest("testXnewCompiler");
+    public void testXnewCompiler() {
+        assumeFalse("Current system is Java 9 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        buildRule.executeTarget("testXnewCompiler");
     }
 
     /**
      * test that runs the new xnew compiler adapter.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testXnewCompilerDest() throws Exception {
-        xnewTest("testXnewCompilerDest");
+    public void testXnewCompilerJava9plus() {
+        assumeTrue("Current system is Java 8 or older",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        assumeFalse("Current system is Java 15 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("JDK9 has removed support for -Xnew");
+        buildRule.executeTarget("testXnewCompiler");
+    }
+
+    /**
+     * test that runs the new xnew compiler adapter.
+     */
+    @Test
+    public void testXnewCompilerDest() {
+        assumeFalse("Current system is Java 9 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        buildRule.executeTarget("testXnewCompilerDest");
+    }
+
+    /**
+     * test that runs the new xnew compiler adapter.
+     */
+    @Test
+    public void testXnewCompilerDestJava9plus() {
+        assumeTrue("Current system is Java 8 or older",
+                JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        assumeFalse("Current system is Java 15 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("JDK9 has removed support for -Xnew");
+        buildRule.executeTarget("testXnewCompilerDest");
     }
 
     /**
      * test that verifies that IDL compiles.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testIDL() throws Exception {
-        corbaTest("testIDL");
+    public void testIDL() {
+        assumeFalse("Current system is Java 11 or newer", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        buildRule.executeTarget("testIDL");
     }
 
     /**
      * test that verifies that IDL compiles.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testIDLDest() throws Exception {
-        corbaTest("testIDLDest");
+    public void testIDLJava11plus() {
+        assumeTrue("Current system is Java 10 or older", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        assumeFalse("Current system is Java 15 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("this rmic implementation doesn't support the -idl switch");
+        buildRule.executeTarget("testIDL");
+    }
+
+    /**
+     * test that verifies that IDL compiles.
+     */
+    @Test
+    public void testIDLDest() {
+        assumeFalse("Current system is Java 11 or newer", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        buildRule.executeTarget("testIDLDest");
+    }
+
+    /**
+     * test that verifies that IDL compiles.
+     */
+    @Test
+    public void testIDLDestJava11plus() {
+        assumeTrue("Current system is Java 10 or older", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        assumeFalse("Current system is Java 15 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("this rmic implementation doesn't support the -idl switch");
+        buildRule.executeTarget("testIDL");
+   }
+
+    /**
+     * test that verifies that IIOP compiles.
+     */
+    @Test
+    public void testIIOP() {
+        assumeFalse("Current system is Java 11 or newer", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        buildRule.executeTarget("testIIOP");
     }
 
     /**
      * test that verifies that IIOP compiles.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testIIOP() throws Exception {
-        corbaTest("testIIOP");
+    public void testIIOPJava11plus() {
+        assumeTrue("Current system is Java 10 or older", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        assumeFalse("Current system is Java 15 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("this rmic implementation doesn't support the -iiop switch");
+        buildRule.executeTarget("testIIOP");
     }
 
     /**
      * test that verifies that IIOP compiles.
-     *
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testIIOPDest() throws Exception {
-        corbaTest("testIIOPDest");
+    public void testIIOPDest() {
+        assumeFalse("Current system is Java 11 or newer", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        buildRule.executeTarget("testIIOPDest");
     }
 
-    private void xnewTest(String target) {
-        if (!JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)
-            || JavaEnvUtils.isAtLeastJavaVersion("15")) {
-            // target is skipped with Java 15+
-            buildRule.executeTarget(target);
-        } else {
-            try {
-                buildRule.executeTarget(target);
-                fail("Target should have thrown a BuildException");
-            } catch (BuildException ex) {
-                assertEquals("JDK9 has removed support for -Xnew", ex.getMessage());
-            }
-        }
-    }
-
-    private void corbaTest(String target) {
-        if (!JavaEnvUtils.isAtLeastJavaVersion("11")
-            || JavaEnvUtils.isAtLeastJavaVersion("15")) {
-            // target is skipped with Java 15+
-            buildRule.executeTarget(target);
-        } else {
-            try {
-                buildRule.executeTarget(target);
-                fail("Target should have thrown a BuildException");
-            } catch (BuildException ex) {
-                if (target.contains("IDL")) {
-                    assertEquals("this rmic implementation doesn't support the -idl switch", ex.getMessage());
-                } else {
-                    assertEquals("this rmic implementation doesn't support the -iiop switch", ex.getMessage());
-                }
-            }
-        }
+    /**
+     * test that verifies that IIOP compiles.
+     */
+    @Test
+    public void testIIOPDestJava11plus() {
+        assumeTrue("Current system is Java 10 or older", JavaEnvUtils.isAtLeastJavaVersion("11"));
+        assumeFalse("Current system is Java 15 or newer",
+                JavaEnvUtils.isAtLeastJavaVersion("15"));
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("this rmic implementation doesn't support the -iiop switch");
+        buildRule.executeTarget("testIIOP");
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/RmicTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/RmicTest.java
index eb81857..1c800c3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/RmicTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/RmicTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/SQLExecTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/SQLExecTest.java
index faa890e..92fbca6 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/SQLExecTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/SQLExecTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,26 +17,29 @@
  */
 package org.apache.tools.ant.taskdefs;
 
-import java.sql.Driver;
 import java.sql.Connection;
-import java.sql.SQLException;
+import java.sql.Driver;
 import java.sql.DriverPropertyInfo;
-import java.util.Properties;
+import java.sql.SQLException;
 import java.io.File;
 import java.net.URL;
+import java.util.Properties;
 import java.util.logging.Logger;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.junit.Before;
 import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  * Simple testcase to test for driver caching.
@@ -62,8 +65,11 @@
     public static final String PATH = "path";
     public static final String SQL = "sql";
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         // make sure the cache is cleared.
         JDBCTask.getLoaderMap().clear();
     }
@@ -71,34 +77,38 @@
    // simple test to ensure that the caching does work...
     @Test
     public void testDriverCaching() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No suitable Driver");
+        boolean canary = false;
         SQLExec sql = createTask(getProperties(NULL));
-        assertTrue(!SQLExec.getLoaderMap().containsKey(NULL_DRIVER));
+        assertThat(SQLExec.getLoaderMap(), not(hasKey(NULL_DRIVER)));
         try {
             sql.execute();
-            fail("BuildException should have been thrown");
-        } catch (BuildException e) {
-            assertContains("No suitable Driver", e.getMessage());
-        }
-        assertTrue(SQLExec.getLoaderMap().containsKey(NULL_DRIVER));
-        assertSame(sql.getLoader(), JDBCTask.getLoaderMap().get(NULL_DRIVER));
-        ClassLoader loader1 = sql.getLoader();
+            canary = true;
+        } finally {
+            assertFalse("Found some Driver", canary);
+            assertThat(SQLExec.getLoaderMap(), hasKey(NULL_DRIVER));
+            assertSame(sql.getLoader(), JDBCTask.getLoaderMap().get(NULL_DRIVER));
+            ClassLoader loader1 = sql.getLoader();
 
-        // 2nd run..
-        sql = createTask(getProperties(NULL));
-        // the driver must still be cached.
-        assertTrue(JDBCTask.getLoaderMap().containsKey(NULL_DRIVER));
-        try {
-            sql.execute();
-        } catch (BuildException e){
-            assertTrue(e.getCause().getMessage().contains("No suitable Driver"));
+            // 2nd run..
+            sql = createTask(getProperties(NULL));
+            // the driver must still be cached.
+            assertThat(JDBCTask.getLoaderMap(), hasKey(NULL_DRIVER));
+            try {
+                sql.execute();
+                canary = true;
+            } finally {
+                assertFalse("Found some Driver", canary);
+                assertThat(JDBCTask.getLoaderMap(), hasKey(NULL_DRIVER));
+                assertSame(sql.getLoader(), JDBCTask.getLoaderMap().get(NULL_DRIVER));
+                assertSame(loader1, sql.getLoader());
+            }
         }
-        assertTrue(JDBCTask.getLoaderMap().containsKey(NULL_DRIVER));
-        assertSame(sql.getLoader(), JDBCTask.getLoaderMap().get(NULL_DRIVER));
-        assertSame(loader1, sql.getLoader());
     }
 
     @Test
-    public void testNull() throws Exception {
+    public void testNull() {
         doMultipleCalls(1000, NULL, true, true);
     }
 
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..4d5f29c 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/SignJarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/SignJarTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,16 +22,16 @@
 
 import org.apache.tools.ant.BuildException;
 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.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 
 /**
  * Testcase for the Signjar task
@@ -42,6 +42,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/signjar.xml");
@@ -62,8 +65,7 @@
         sj.setAlias("testonly");
         sj.setKeystore("testkeystore");
         sj.setStorepass("apacheant");
-        File jar = new File(buildRule.getProject().getProperty("test.jar"));
-        sj.setJar(jar);
+        sj.setJar(new File(buildRule.getProject().getProperty("test.jar")));
         assertFalse("mustn't find signature without sigfile attribute",
                     sj.isSigned());
         sj.setSigfile("TEST");
@@ -78,8 +80,7 @@
         sj.setAlias("test@nly");
         sj.setKeystore("testkeystore");
         sj.setStorepass("apacheant");
-        File jar = new File(buildRule.getProject().getProperty("test.jar"));
-        sj.setJar(jar);
+        sj.setJar(new File(buildRule.getProject().getProperty("test.jar")));
         assertTrue(sj.isSigned());
     }
 
@@ -100,19 +101,15 @@
 
     @Test
     public void testURLKeystoreHTTP() {
-        Assume.assumeFalse("Test is set offline", isOffline());
+        assumeFalse("Test is set offline", isOffline());
         buildRule.executeTarget("urlKeystoreHTTP");
     }
 
     @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");
-        } catch(BuildException ex) {
-            assertEquals("jarsigner returned: 1", ex.getMessage());
-        }
+         thrown.expect(BuildException.class);
+         thrown.expectMessage("jarsigner returned: 1");
+         buildRule.executeTarget("testTsaLocalhost");
     }
 
     /**
@@ -126,7 +123,7 @@
         File f = new File(testJarParent,
                           "../" + testJarParent.getName() + "/"
                           + testJar.getName());
-        assertFalse(testJar.equals(f));
+        assertNotEquals(testJar, f);
         assertEquals(testJar.getCanonicalPath(), f.getCanonicalPath());
         SignJar s = new SignJar();
         s.setProject(buildRule.getProject());
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/SleepTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/SleepTest.java
index 3d6ce87..764fc85 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/SleepTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/SleepTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,26 +18,24 @@
 
 package org.apache.tools.ant.taskdefs;
 
+import static org.junit.Assert.assertTrue;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 public class SleepTest {
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/";
     private static final int ERROR_RANGE = 1000;
 
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "sleep.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/sleep.xml");
     }
 
     @Test
@@ -72,14 +70,13 @@
         assertTrue(timer.time() >= (2000 - ERROR_RANGE) && timer.time() < 60000);
     }
 
-    @Test
+    /**
+     * Expected failure: negative sleep periods are not supported
+     */
+    @Test(expected = BuildException.class)
     public void test5() {
-        try {
-            buildRule.executeTarget("test5");
-            fail("Negative sleep periods are not supported");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test5");
+        // TODO assert value
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/StyleTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/StyleTest.java
index e958524..001b6cd 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/StyleTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/StyleTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,10 +27,12 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.junit.Assert.assertEquals;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 
 /**
@@ -43,21 +45,23 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/style/build.xml");
     }
 
+    /**
+     * Expected failure: no stylesheet specified
+     */
     @Test
-    public void testStyleIsSet() throws Exception {
-
-        try {
-            buildRule.executeTarget("testStyleIsSet");
-            fail("Must throws a BuildException: no stylesheet specified");
-        } catch (BuildException ex) {
-            assertEquals("specify the stylesheet either as a filename in style attribute or as a nested resource",
-                    ex.getMessage());
-        }
+    public void testStyleIsSet() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("specify the stylesheet either as a filename in style attribute or "
+                + "as a nested resource");
+        buildRule.executeTarget("testStyleIsSet");
     }
 
     @Test
@@ -106,8 +110,7 @@
     }
 
     public void testDefaultMapper(String target) throws Exception {
-        assertTrue(!(
-                new File(buildRule.getOutputDir().getAbsoluteFile(), "data.html").exists()));
+        assertFalse(new File(buildRule.getOutputDir().getAbsoluteFile(), "data.html").exists());
         expectFileContains(target,
                            buildRule.getOutputDir().getAbsoluteFile() + "/data.html",
                            "set='myvalue'");
@@ -115,7 +118,7 @@
 
     @Test
     public void testCustomMapper() throws Exception {
-        assertTrue(!new File(buildRule.getOutputDir().getAbsoluteFile(),  "out.xml").exists());
+        assertFalse(new File(buildRule.getOutputDir().getAbsoluteFile(), "out.xml").exists());
         expectFileContains("testCustomMapper",
                            buildRule.getOutputDir().getAbsoluteFile() + "/out.xml",
                            "set='myvalue'");
@@ -123,35 +126,35 @@
 
     @Test
     public void testTypedMapper() throws Exception {
-        assertTrue(!new File(buildRule.getOutputDir().getAbsoluteFile(),  "out.xml").exists());
+        assertFalse(new File(buildRule.getOutputDir().getAbsoluteFile(), "out.xml").exists());
         expectFileContains("testTypedMapper",
                            buildRule.getOutputDir().getAbsoluteFile() + "/out.xml",
                            "set='myvalue'");
     }
 
     @Test
-    public void testDirectoryHierarchyWithDirMatching() throws Exception {
+    public void testDirectoryHierarchyWithDirMatching() {
         buildRule.executeTarget("testDirectoryHierarchyWithDirMatching");
         assertTrue(new File(buildRule.getOutputDir().getAbsoluteFile(),  "dest/level1/data.html")
                    .exists());
     }
 
     @Test
-    public void testDirsWithSpaces() throws Exception {
+    public void testDirsWithSpaces() {
         buildRule.executeTarget("testDirsWithSpaces");
         assertTrue(new File(buildRule.getOutputDir().getAbsoluteFile(),  "d est/data.html")
                    .exists());
     }
 
+    /**
+     * Expected failure: stylesheet specified twice
+     */
     @Test
     public void testWithStyleAttrAndResource() {
-        try {
-            buildRule.executeTarget("testWithStyleAttrAndResource");
-            fail("Must throws a BuildException");
-        } catch (BuildException ex) {
-            assertEquals("specify the stylesheet either as a filename in style attribute or as a "
-                    + "nested resource but not as both", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("specify the stylesheet either as a filename in style attribute or "
+                + "as a nested resource but not as both");
+        buildRule.executeTarget("testWithStyleAttrAndResource");
     }
 
     @Test
@@ -228,11 +231,8 @@
 
     private void assertFileContains(String filename, String contains) throws IOException {
         String content = getFileString(filename);
-        assertTrue(
-              "expecting file " + filename
-            + " to contain " + contains
-            + " but got " + content,
-                content.contains(contains));
+        assertThat("expecting file " + filename + " to contain " + contains + " but got " + content,
+                content, containsString(contains));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/SubAntTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/SubAntTest.java
index 0a7321f..2564b61 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/SubAntTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/SubAntTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,8 +20,6 @@
 
 import java.io.File;
 
-import junit.framework.AssertionFailedError;
-
 import org.apache.tools.ant.BuildEvent;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
@@ -29,17 +27,20 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
+import static org.junit.Assert.assertThat;
 
 public class SubAntTest {
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/subant.xml");
@@ -84,33 +85,31 @@
     @Test
     public void testMultipleTargets() {
         buildRule.executeTarget("multipleTargets");
-        assertContains("test1-one", buildRule.getLog());
-        assertContains("test1-two", buildRule.getLog());
-        assertContains("test2-one", buildRule.getLog());
-        assertContains("test2-two", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("test1-one"));
+        assertThat(buildRule.getLog(), containsString("test1-two"));
+        assertThat(buildRule.getLog(), containsString("test2-one"));
+        assertThat(buildRule.getLog(), containsString("test2-two"));
     }
 
     @Test
     public void testMultipleTargetsOneDoesntExist_FOEfalse() {
         buildRule.executeTarget("multipleTargetsOneDoesntExist_FOEfalse");
-        assertContains("Target \"three\" does not exist in the project \"subant\"", buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("Target \"three\" does not exist in the project \"subant\""));
     }
 
     @Test
     public void testMultipleTargetsOneDoesntExist_FOEtrue() {
-        try {
-            buildRule.executeTarget("multipleTargetsOneDoesntExist_FOEtrue");
-            fail("BuildException expected: Calling not existent target");
-        } catch (BuildException ex) {
-            assertContains("Target \"three\" does not exist in the project \"subant\"", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Target \"three\" does not exist in the project \"subant\"");
+        buildRule.executeTarget("multipleTargetsOneDoesntExist_FOEtrue");
     }
 
     protected void testBaseDirs(String target, String[] dirs) {
         SubAntTest.BasedirChecker bc = new SubAntTest.BasedirChecker(dirs);
         buildRule.getProject().addBuildListener(bc);
         buildRule.executeTarget(target);
-        AssertionFailedError ae = bc.getError();
+        AssertionError ae = bc.getError();
         if (ae != null) {
             throw ae;
         }
@@ -120,7 +119,7 @@
     private class BasedirChecker implements BuildListener {
         private String[] expectedBasedirs;
         private int calls = 0;
-        private AssertionFailedError error;
+        private AssertionError error;
 
         BasedirChecker(String[] dirs) {
             expectedBasedirs = dirs;
@@ -145,24 +144,22 @@
         }
 
         public void targetStarted(BuildEvent event) {
-            if (event.getTarget().getName().equals("")) {
+            if (event.getTarget().getName().isEmpty()) {
                 return;
             }
             if (error == null) {
                 try {
                     assertEquals(expectedBasedirs[calls++],
                             event.getProject().getBaseDir().getAbsolutePath());
-                } catch (AssertionFailedError e) {
+                } catch (AssertionError e) {
                     error = e;
                 }
             }
         }
 
-        AssertionFailedError getError() {
+        AssertionError getError() {
             return error;
         }
-
     }
 
-
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/SyncTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/SyncTest.java
index b296b7b..85e09e7 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/SyncTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/SyncTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,11 +19,15 @@
 package org.apache.tools.ant.taskdefs;
 
 import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.util.FileUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 public class SyncTest {
@@ -41,7 +45,7 @@
         buildRule.executeTarget("simplecopy");
         String d = buildRule.getProject().getProperty("dest") + "/a/b/c/d";
         assertFileIsPresent(d);
-        assertTrue(!buildRule.getFullLog().contains("dangling"));
+        assertThat(buildRule.getFullLog(), not(containsString("dangling")));
     }
 
     @Test
@@ -51,7 +55,7 @@
         assertFileIsNotPresent(d);
         String c = buildRule.getProject().getProperty("dest") + "/a/b/c";
         assertFileIsNotPresent(c);
-        assertTrue(!buildRule.getFullLog().contains("dangling"));
+        assertThat(buildRule.getFullLog(), not(containsString("dangling")));
     }
 
     @Test
@@ -61,7 +65,7 @@
         assertFileIsNotPresent(d);
         String c = buildRule.getProject().getProperty("dest") + "/a/b/c";
         assertFileIsPresent(c);
-        assertTrue(!buildRule.getFullLog().contains("dangling"));
+        assertThat(buildRule.getFullLog(), not(containsString("dangling")));
     }
 
     @Test
@@ -85,9 +89,9 @@
         assertFileIsPresent(d);
         String f = buildRule.getProject().getProperty("dest") + "/e/f";
         assertFileIsNotPresent(f);
-        assertTrue(buildRule.getFullLog().contains("Removing orphan file:"));
-        assertContains("Removed 1 dangling file from", buildRule.getFullLog());
-        assertContains("Removed 1 dangling directory from", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), containsString(("Removing orphan file:")));
+        assertThat(buildRule.getFullLog(), containsString("Removed 1 dangling file from"));
+        assertThat(buildRule.getFullLog(), containsString("Removed 1 dangling directory from"));
     }
 
     @Test
@@ -97,9 +101,9 @@
         assertFileIsPresent(d);
         String f = buildRule.getProject().getProperty("dest") + "/e/f";
         assertFileIsNotPresent(f);
-        assertTrue(buildRule.getFullLog().contains("Removing orphan file:"));
-        assertContains("Removed 1 dangling file from", buildRule.getFullLog());
-        assertContains("Removed 1 dangling directory from", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), containsString(("Removing orphan file:")));
+        assertThat(buildRule.getFullLog(), containsString("Removed 1 dangling file from"));
+        assertThat(buildRule.getFullLog(), containsString("Removed 1 dangling directory from"));
     }
 
     @Test
@@ -111,9 +115,9 @@
         assertFileIsPresent(c);
         String f = buildRule.getProject().getProperty("dest") + "/e/f";
         assertFileIsNotPresent(f);
-        assertTrue(buildRule.getFullLog().contains("Removing orphan directory:"));
-        assertContains("NO dangling file to remove from", buildRule.getFullLog());
-        assertContains("Removed 2 dangling directories from", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), containsString(("Removing orphan directory:")));
+        assertThat(buildRule.getFullLog(), containsString("NO dangling file to remove from"));
+        assertThat(buildRule.getFullLog(), containsString("Removed 2 dangling directories from"));
     }
 
     @Test
@@ -123,7 +127,7 @@
         assertFileIsPresent(d);
         String f = buildRule.getProject().getProperty("dest") + "/e/f";
         assertFileIsPresent(f);
-        assertTrue(!buildRule.getFullLog().contains("Removing orphan file:"));
+        assertThat(buildRule.getFullLog(), not(containsString("Removing orphan file:")));
     }
 
     @Test
@@ -133,16 +137,36 @@
         assertFileIsPresent(d);
         String f = buildRule.getProject().getProperty("dest") + "/e/f";
         assertFileIsPresent(f);
-        assertTrue(!buildRule.getFullLog().contains("Removing orphan file:"));
+        assertThat(buildRule.getFullLog(), not(containsString("Removing orphan file:")));
     }
 
+    /**
+     * Test for bz-62890 bug fix
+     */
+    @Test
+    public void testCaseSensitivityOfDest() {
+        buildRule.executeTarget("casesensitivity-test");
+        final String destDir = buildRule.getProject().getProperty("dest") + "/casecheck";
+        assertFileIsPresent(destDir + "/a.txt");
+        final boolean caseSensitive = FileUtils.isCaseSensitiveFileSystem(
+                buildRule.getProject().resolveFile(destDir).toPath())
+                .orElse(true); // directory scanner defaults to case sensitive = true
+        if (caseSensitive) {
+            assertFileIsNotPresent(destDir + "/A.txt");
+        } else {
+            assertFileIsPresent(destDir + "/A.txt");
+        }
+        assertFileIsPresent(destDir + "/foo.txt");
+
+        assertFileIsNotPresent(destDir + "/bar.txt");
+    }
+
+
     public void assertFileIsPresent(String f) {
-        assertTrue("Expected file " + f,
-                buildRule.getProject().resolveFile(f).exists());
+        assertTrue("Expected file " + f, buildRule.getProject().resolveFile(f).exists());
     }
 
     public void assertFileIsNotPresent(String f) {
-        assertTrue("Didn't expect file " + f,
-                   !buildRule.getProject().resolveFile(f).exists());
+        assertFalse("Didn't expect file " + f, buildRule.getProject().resolveFile(f).exists());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TStampTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TStampTest.java
index 033d1b9..f393bf9 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TStampTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TStampTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -40,7 +40,7 @@
     protected Location location;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         location = new Location("test.xml");
         project = new Project();
         tstamp = new Tstamp();
@@ -49,7 +49,7 @@
     }
 
     @Test
-    public void testTimeZone() throws Exception {
+    public void testTimeZone() {
         Tstamp.CustomFormat format = tstamp.createFormat();
         format.setProperty("today");
         format.setPattern("HH:mm:ss z");
@@ -68,10 +68,9 @@
     /**
      * verifies that custom props have priority over the
      * originals
-     * @throws Exception if something goes wrong
      */
     @Test
-    public void testWriteOrder() throws Exception {
+    public void testWriteOrder() {
         Tstamp.CustomFormat format = tstamp.createFormat();
         format.setProperty("TODAY");
         format.setPattern("HH:mm:ss z");
@@ -89,12 +88,10 @@
     }
 
     /**
-     * verifies that custom props have priority over the
-     * originals
-     * @throws Exception if something goes wrong
+     * verifies that custom props have priority over the originals
      */
     @Test
-    public void testPrefix() throws Exception {
+    public void testPrefix() {
         tstamp.setPrefix("prefix");
         tstamp.execute();
         String prop = project.getProperty("prefix.DSTAMP");
@@ -102,7 +99,7 @@
     }
 
     @Test
-    public void testFormatPrefix() throws Exception {
+    public void testFormatPrefix() {
         Tstamp.CustomFormat format = tstamp.createFormat();
         format.setProperty("format");
         format.setPattern("HH:mm:ss z");
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TarTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TarTest.java
index f747c42..249022b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TarTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,9 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import java.io.IOException;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.IOException;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
@@ -32,8 +32,8 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 public class TarTest {
 
@@ -46,65 +46,56 @@
         buildRule.executeTarget("setUp");
     }
 
-    @Test
+    /**
+     * Expected failure: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO assert value
     }
 
-    @Test
+    /**
+     * Expected failure: tar cannot include itself
+     */
+    @Test(expected = BuildException.class)
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException expected: tar cannot include itself");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
+        // TODO assert value
     }
 
     @Test
     public void test5() {
         buildRule.executeTarget("test5");
-        File f
-            = new File(buildRule.getProject().getProperty("output"), "test5.tar");
-
-        if (!f.exists()) {
-            fail("Tarring a directory failed");
-        }
+        File f = new File(buildRule.getProject().getProperty("output"), "test5.tar");
+        assertTrue("Tarring a directory failed", f.exists());
     }
 
-    @Test
+    /**
+     * Expected failure due to invalid value specified for longfile attribute.
+     */
+    @Test(expected = BuildException.class)
     public void test6() {
-        try {
-            buildRule.executeTarget("test6");
-            fail("BuildException expected: Invalid value specified for longfile attribute.");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test6");
+        // TODO assert value
     }
 
     @Test
@@ -124,19 +115,11 @@
 
     private void test7(String target) {
         buildRule.executeTarget(target);
-        File f1
-            = new File(buildRule.getProject().getProperty("output"), "untar/test7-prefix");
-
-        if (!(f1.exists() && f1.isDirectory())) {
-            fail("The prefix attribute is not working properly.");
-        }
-
-        File f2
-            = new File(buildRule.getProject().getProperty("output"), "untar/test7dir");
-
-        if (!(f2.exists() && f2.isDirectory())) {
-            fail("The prefix attribute is not working properly.");
-        }
+        final String output = buildRule.getProject().getProperty("output");
+        File f1 = new File(output, "untar/test7-prefix");
+        assertTrue("The prefix attribute is not working properly.", f1.exists() && f1.isDirectory());
+        File f2 = new File(output, "untar/test7dir");
+        assertTrue("The prefix attribute is not working properly.", f2.exists() && f2.isDirectory());
     }
 
     @Test
@@ -166,41 +149,34 @@
 
     private void test8(String target) {
         buildRule.executeTarget(target);
-        File f1
-            = new File(buildRule.getProject().getProperty("output"), "untar/test8.xml");
-        if (! f1.exists()) {
-            fail("The fullpath attribute or the preserveLeadingSlashes attribute does not work properly");
-        }
+        File f1 = new File(buildRule.getProject().getProperty("output"), "untar/test8.xml");
+        assertTrue("The fullpath attribute or the preserveLeadingSlashes attribute does not work properly",
+                f1.exists());
     }
 
-    @Test
+    /**
+     * Expected failure due to invalid value specified for compression attribute.
+     */
+    @Test(expected = BuildException.class)
     public void test9() {
-        try {
-            buildRule.executeTarget("test9");
-            fail("BuildException expected: Invalid value specified for compression attribute.");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test9");
+        // TODO assert value
     }
 
     @Test
     public void test10() {
         buildRule.executeTarget("test10");
-        File f1
-            = new File(buildRule.getProject().getProperty("output"), "untar/test10.xml");
-        if (! f1.exists()) {
-            fail("The fullpath attribute or the preserveLeadingSlashes attribute does not work properly");
-        }
+        File f1 = new File(buildRule.getProject().getProperty("output"), "untar/test10.xml");
+        assertTrue("The fullpath attribute or the preserveLeadingSlashes attribute does not work properly",
+                f1.exists());
     }
 
     @Test
     public void test11() {
         buildRule.executeTarget("test11");
-        File f1
-            = new File(buildRule.getProject().getProperty("output"), "untar/test11.xml");
-        if (! f1.exists()) {
-            fail("The fullpath attribute or the preserveLeadingSlashes attribute does not work properly");
-        }
+        File f1 = new File(buildRule.getProject().getProperty("output"), "untar/test11.xml");
+        assertTrue("The fullpath attribute or the preserveLeadingSlashes attribute does not work properly",
+                f1.exists());
     }
 
     @Test
@@ -211,6 +187,11 @@
     }
 
     @Test
+    public void testtestTarFilesetWithReference() {
+        buildRule.executeTarget("testTarFilesetWithReference");
+    }
+
+    @Test
     public void testTarFilesetWithSymlinks() throws IOException {
         buildRule.executeTarget("testTarFilesetWithSymlinks");
         final File f = new File(buildRule.getProject().getProperty("output"), "result.tar");
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefTest.java
index 24e5090..bcefcbc 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,14 +20,13 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
-import org.apache.tools.ant.Project;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -41,54 +40,49 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/taskdef.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due lacking a required argument
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due lacking a required argument
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due lacking a required argument
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to nonexistent class specified
+     */
+    @Test(expected = BuildException.class)
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException expected: classname specified doesn't exist");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to non-public execute() method
+     */
+    @Test(expected = BuildException.class)
     public void test5() {
-        try {
-            buildRule.executeTarget("test5");
-            fail("BuildException expected: No public execute() in " + Project.class);
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test5");
+        // TODO Assert exception message
     }
 
     @Test
@@ -118,11 +112,11 @@
     public void testOverride() {
         buildRule.executeTarget("testOverride");
         String log = buildRule.getLog();
-        assertTrue("override warning sent",
-                log.contains("Trying to override old definition of task copy"));
-        assertTrue("task inside target worked",
-                log.contains("In target"));
-        assertTrue("task inside target worked",
-                log.contains("In TaskContainer"));
+        assertThat("override warning sent", log,
+                containsString("Trying to override old definition of task copy"));
+        assertThat("task inside target worked", log,
+                containsString("In target"));
+        assertThat("task inside target worked", log,
+                containsString("In TaskContainer"));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefsTest.java
index 9316059..699aeae 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TaskdefsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TestProcess.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TestProcess.java
index a61ca3c..f0860b7 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TestProcess.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TestProcess.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,7 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import org.junit.internal.AssumptionViolatedException;
+import org.junit.AssumptionViolatedException;
 
 /**
  * Interactive Testcase for Processdestroyer.
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TimeProcess.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TimeProcess.java
index eee15d1..1fab118 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TimeProcess.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TimeProcess.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TouchTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TouchTest.java
index 0f90146..64053bd 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TouchTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TouchTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,31 +18,30 @@
 
 package org.apache.tools.ant.taskdefs;
 
-import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.util.FileUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.File;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 public class TouchTest {
 
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
-    private static String TOUCH_FILE = "src/etc/testcases/taskdefs/touchtest";
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     /** Utilities used for file operations */
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
 
-
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/touch.xml");
@@ -54,8 +53,7 @@
     }
 
     public long getTargetTime() {
-
-        File file = new File(System.getProperty("root"), TOUCH_FILE);
+        File file = new File(buildRule.getProject().getBaseDir(), "touchtest");
         if (!file.exists()) {
             throw new BuildException("failed to touch file " + file);
         }
@@ -96,9 +94,9 @@
     public void testNow() {
         long now = System.currentTimeMillis();
         buildRule.executeTarget("testNow");
-        long time = getTargetTime();
-        assertTimesNearlyMatch(time, now, 5000);
+        assertTimesNearlyMatch(getTargetTime(), now, 5000);
     }
+
     /**
      * verify that the millis test sets things up
      */
@@ -168,13 +166,9 @@
      */
     @Test
     public void testBadPattern() {
-        try {
-            buildRule.executeTarget("testBadPattern");
-            fail("No parsing exception thrown");
-        } catch (BuildException ex) {
-            assertContains("Unparseable", ex.getMessage());
-        }
-
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Unparseable");
+        buildRule.executeTarget("testBadPattern");
     }
 
     /**
@@ -184,8 +178,7 @@
      */
     private void touchFile(String targetName, long timestamp) {
         buildRule.executeTarget(targetName);
-        long time = getTargetTime();
-        assertTimesNearlyMatch(timestamp, time);
+        assertTimesNearlyMatch(timestamp, getTargetTime());
     }
 
     /**
@@ -193,9 +186,8 @@
      * @param timestamp long
      * @param time long
      */
-    public void assertTimesNearlyMatch(long timestamp,long time) {
-        long granularity= FILE_UTILS.getFileTimestampGranularity();
-        assertTimesNearlyMatch(timestamp, time, granularity);
+    public void assertTimesNearlyMatch(long timestamp, long time) {
+        assertTimesNearlyMatch(timestamp, time, FILE_UTILS.getFileTimestampGranularity());
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TypeAdapterTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TypeAdapterTest.java
index aac89ae..c4fc8fc 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TypeAdapterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TypeAdapterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,11 +28,11 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -41,6 +41,8 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
     public void setUp() {
@@ -50,35 +52,32 @@
     @Test
     public void testTaskAdapter() {
         buildRule.executeTarget("taskadapter");
-        assertContains("MyExec called", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("MyExec called"));
     }
 
     @Test
     public void testRunAdapter() {
         buildRule.executeTarget("runadapter");
-        assertContains("MyRunnable called", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("MyRunnable called"));
     }
 
     @Test
     public void testRunAdapterError() {
-        try {
-            buildRule.executeTarget("runadaptererror");
-            fail("BuildException expected: no public run method");
-        } catch (BuildException ex) {
-            assertContains("No public run() method in", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No public run() method in");
+        buildRule.executeTarget("runadaptererror");
     }
 
     @Test
     public void testDelay() {
         buildRule.executeTarget("delay");
-        assertContains("MyTask called", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("MyTask called"));
     }
 
     @Test
     public void testOnErrorReport() {
         buildRule.executeTarget("onerror.report");
-        assertContains("MyTaskNotPresent cannot be found", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("MyTaskNotPresent cannot be found"));
     }
 
     @Test
@@ -120,7 +119,7 @@
         private String execMethodName = "run";
         private Object proxy;
 
-        public Method getExecuteMethod(Class proxyClass) {
+        public Method getExecuteMethod(Class<?> proxyClass) {
             try {
                 Method execMethod = proxyClass.getMethod(execMethodName);
                 if (!Void.TYPE.equals(execMethod.getReturnType())) {
@@ -136,7 +135,7 @@
                 throw new BuildException(message);
             }
         }
-        public void checkProxyClass(Class proxyClass) {
+        public void checkProxyClass(Class<?> proxyClass) {
             getExecuteMethod(proxyClass);
         }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/TypedefTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/TypedefTest.java
index 0b93826..4f80643 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/TypedefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/TypedefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,11 +23,12 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  */
@@ -36,50 +37,37 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/typedef.xml");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testEmpty() {
-        try {
-            buildRule.executeTarget("empty");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("empty");
+        // TODO assert value
     }
 
     @Test
     public void testNoName() {
-        try {
-            buildRule.executeTarget("noName");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Only antlib URIs can be located from the URI alone, not the URI ''");
+        buildRule.executeTarget("noName");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testNoClassname() {
-        try {
-            buildRule.executeTarget("noClassname");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("noClassname");
+        // TODO assert value
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testClassNotFound() {
-        try {
-            buildRule.executeTarget("classNotFound");
-            fail("BuildException expected: classname specified doesn't exist");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("classNotFound");
+        // TODO assert value
     }
 
     @Test
@@ -88,8 +76,7 @@
         assertEquals("", buildRule.getLog());
         Object ref = buildRule.getProject().getReferences().get("global");
         assertNotNull("ref is not null", ref);
-        assertEquals("org.example.types.TypedefTestType",
-                     ref.getClass().getName());
+        assertEquals("org.example.types.TypedefTestType", ref.getClass().getName());
     }
 
     @Test
@@ -98,8 +85,7 @@
         assertEquals("", buildRule.getLog());
         Object ref = buildRule.getProject().getReferences().get("local");
         assertNotNull("ref is not null", ref);
-        assertEquals("org.example.types.TypedefTestType",
-                     ref.getClass().getName());
+        assertEquals("org.example.types.TypedefTestType", ref.getClass().getName());
     }
 
     /**
@@ -109,28 +95,25 @@
     @Test
     public void testDoubleNotPresent() {
         buildRule.executeTarget("double-notpresent");
-        assertContains("hi", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("hi"));
     }
 
     @Test
     public void testNoResourceOnErrorFailAll() {
-            try {
-            buildRule.executeTarget("noresourcefailall");
-            fail("BuildException expected: the requested resource does not exist");
-        } catch (BuildException ex) {
-            assertContains("Could not load definitions from resource ", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Could not load definitions from resource ");
+        buildRule.executeTarget("noresourcefailall");
     }
 
     @Test
     public void testNoResourceOnErrorFail() {
         buildRule.executeTarget("noresourcefail");
-        assertContains("Could not load definitions from resource ", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Could not load definitions from resource "));
     }
 
     @Test
     public void testNoResourceOnErrorNotFail() {
-            buildRule.executeTarget("noresourcenotfail");
-        assertContains("Could not load definitions from resource ", buildRule.getLog());
+        buildRule.executeTarget("noresourcenotfail");
+        assertThat(buildRule.getLog(), containsString("Could not load definitions from resource "));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/UntarTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/UntarTest.java
index ea0c60c..6a1cca4 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/UntarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/UntarTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,8 +30,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 
 public class UntarTest {
 
@@ -73,14 +71,10 @@
         testLogoExtraction("testBzip2TarTask");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testSrcDirTest() {
-        try {
-            buildRule.executeTarget("srcDirTest");
-            fail("Src cannot be a directory.");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("srcDirTest");
+        // TODO assert value
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/UnzipTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/UnzipTest.java
index 55d4c8b..458eba7 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/UnzipTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/UnzipTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -29,8 +29,8 @@
 import java.io.IOException;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 public class UnzipTest {
 
@@ -42,37 +42,33 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/unzip.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        // TODO Assert exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        // TODO Assert exception message
     }
 
-
     @Test
     public void testRealTest() throws IOException {
         buildRule.executeTarget("realTest");
@@ -107,10 +103,9 @@
     @Test
     public void testPatternSetExcludeOnly() {
         buildRule.executeTarget("testPatternSetExcludeOnly");
-        assertFileMissing("1/foo is excluded",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("2/bar is not excluded",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is excluded", output + "/unziptestout/1/foo");
+        assertFileExists("2/bar is not excluded", output + "/unziptestout/2/bar");
     }
 
     /*
@@ -119,10 +114,9 @@
     @Test
     public void testPatternSetIncludeOnly() {
         buildRule.executeTarget("testPatternSetIncludeOnly");
-        assertFileMissing("1/foo is not included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("2/bar is included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not included", output + "/unziptestout/1/foo");
+        assertFileExists("2/bar is included", output + "/unziptestout/2/bar");
     }
 
     /*
@@ -131,10 +125,9 @@
     @Test
     public void testPatternSetIncludeAndExclude() {
         buildRule.executeTarget("testPatternSetIncludeAndExclude");
-        assertFileMissing("1/foo is not included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileMissing("2/bar is excluded",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not included", output + "/unziptestout/1/foo");
+        assertFileMissing("2/bar is excluded", output + "/unziptestout/2/bar");
     }
 
     /*
@@ -143,10 +136,9 @@
     @Test
     public void testTwoPatternSets() {
         buildRule.executeTarget("testTwoPatternSets");
-        assertFileMissing("1/foo is not included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("2/bar is included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not included", output + "/unziptestout/1/foo");
+        assertFileExists("2/bar is included", output + "/unziptestout/2/bar");
     }
 
     /*
@@ -155,10 +147,9 @@
     @Test
     public void testTwoPatternSetsWithExcludes() {
         buildRule.executeTarget("testTwoPatternSetsWithExcludes");
-        assertFileMissing("1/foo is not included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileMissing("2/bar is excluded",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not included", output + "/unziptestout/1/foo");
+        assertFileMissing("2/bar is excluded", output + "/unziptestout/2/bar");
     }
 
     /*
@@ -172,20 +163,17 @@
         buildRule.executeTarget("selfExtractingArchive");
     }
 
-
     /*
      * PR 20969
      */
     @Test
     public void testPatternSetSlashOnly() {
         buildRule.executeTarget("testPatternSetSlashOnly");
-        assertFileMissing("1/foo is not included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("\"2/bar is included",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not included", output + "/unziptestout/1/foo");
+        assertFileExists("\"2/bar is included", output + "/unziptestout/2/bar");
     }
 
-
     /*
      * PR 10504
      */
@@ -202,10 +190,9 @@
     @Test
     public void testFlattenMapper() {
         buildRule.executeTarget("testFlattenMapper");
-        assertFileMissing("1/foo is not flattened",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("foo is flattened",
-                buildRule.getProject().getProperty("output") + "/unziptestout/foo");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not flattened", output + "/unziptestout/1/foo");
+        assertFileExists("foo is flattened", output + "/unziptestout/foo");
     }
 
     /**
@@ -214,8 +201,7 @@
      * @param filename filename to resolve against the project
      */
     private void assertFileExists(String message, String filename) {
-        assertTrue(message,
-                buildRule.getProject().resolveFile(filename).exists());
+        assertTrue(message, buildRule.getProject().resolveFile(filename).exists());
     }
 
     /**
@@ -225,8 +211,7 @@
      * @param filename filename to resolve against the project
      */
     private void assertFileMissing(String message, String filename) {
-        assertTrue(message,
-                !buildRule.getProject().resolveFile(filename).exists());
+        assertFalse(message, buildRule.getProject().resolveFile(filename).exists());
     }
 
     /**
@@ -235,20 +220,18 @@
     @Test
     public void testGlobMapper() {
         buildRule.executeTarget("testGlobMapper");
-        assertFileMissing("1/foo is not mapped",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("1/foo is mapped",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo.txt");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is not mapped", output + "/unziptestout/1/foo");
+        assertFileExists("1/foo is mapped", output + "/unziptestout/1/foo.txt");
     }
 
-    @Test
+    /**
+     * Expected failure due to multiple mappers
+     */
+    @Test(expected = BuildException.class)
     public void testTwoMappers() {
-        try {
-            buildRule.executeTarget("testTwoMappers");
-            fail("BuildException expected: " + Expand.ERROR_MULTIPLE_MAPPERS);
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("testTwoMappers");
+        // TODO Assert exception message
     }
 
     @Test
@@ -261,9 +244,8 @@
     @Test
     public void testDocumentationClaimsOnCopy() {
         buildRule.executeTarget("testDocumentationClaimsOnCopy");
-        assertFileMissing("1/foo is excluded",
-                buildRule.getProject().getProperty("output") + "/unziptestout/1/foo");
-        assertFileExists("2/bar is not excluded",
-                buildRule.getProject().getProperty("output") + "/unziptestout/2/bar");
+        final String output = buildRule.getProject().getProperty("output");
+        assertFileMissing("1/foo is excluded", output + "/unziptestout/1/foo");
+        assertFileExists("2/bar is not excluded", output + "/unziptestout/2/bar");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/UpToDateTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/UpToDateTest.java
index 97a3c8c..9b77320 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/UpToDateTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/UpToDateTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/WarTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/WarTest.java
index 1513ac7..8041502 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/WarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/WarTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,15 +32,13 @@
  *
  */
 public class WarTest {
-    public static final String TEST_BUILD_FILE
-        = "src/etc/testcases/taskdefs/war.xml";
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(TEST_BUILD_FILE);
+        buildRule.configureProject("src/etc/testcases/taskdefs/war.xml");
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/WhichResourceTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/WhichResourceTest.java
index 8e282b3..374229d 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/WhichResourceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/WhichResourceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,16 +26,13 @@
 import static org.junit.Assert.assertNotNull;
 
 public class WhichResourceTest {
-    public static final String TEST_BUILD_FILE
-        = "src/etc/testcases/taskdefs/whichresource.xml";
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
-
     @Before
     public void setUp() {
-        buildRule.configureProject(TEST_BUILD_FILE);
+        buildRule.configureProject("src/etc/testcases/taskdefs/whichresource.xml");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/XmlPropertyTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/XmlPropertyTest.java
index d833f75..7f9f801 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/XmlPropertyTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/XmlPropertyTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,10 +22,10 @@
 import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Enumeration;
+import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Properties;
-import java.util.Vector;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
@@ -35,8 +35,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 /**
  */
@@ -145,10 +148,7 @@
      */
     private void doTest(String msg, boolean keepRoot, boolean collapse,
                         boolean semantic, boolean include, boolean localRoot) throws IOException {
-        Enumeration iter =
-            getFiles(new File(System.getProperty("root"), "src/etc/testcases/taskdefs/xmlproperty/inputs"));
-        while (iter.hasMoreElements()) {
-            File inputFile = (File) iter.nextElement();
+        for (File inputFile : getFiles(buildRule.getProject().resolveFile("xmlproperty/inputs"))) {
             // What's the working directory?  If local, then its the
             // folder of the input file.  Otherwise, its the "current" dir..
             File workingDir;
@@ -158,7 +158,6 @@
                 workingDir = FILE_UTILS.resolveFile(new File("."), ".");
             }
 
-
             File propertyFile = getGoldfile(inputFile, keepRoot, collapse,
                                             semantic, include, localRoot);
             if (!propertyFile.exists()) {
@@ -209,11 +208,9 @@
     private static void ensureProperties(String msg, File inputFile,
                                           File workingDir, Project p,
                                           Properties properties) {
-        Hashtable xmlproperties = p.getProperties();
+        Hashtable<String, Object> xmlproperties = p.getProperties();
         // Every key identified by the Properties must have been loaded.
-        Enumeration<?> propertyKeyEnum = properties.propertyNames();
-        while (propertyKeyEnum.hasMoreElements()) {
-            String currentKey = propertyKeyEnum.nextElement().toString();
+        for (String currentKey : properties.stringPropertyNames()) {
             String assertMsg = msg + "-" + inputFile.getName()
                 + " Key=" + currentKey;
 
@@ -229,18 +226,13 @@
                 // *value* of the Path object, though...
                 Object obj = p.getReferences().get(currentKey);
 
-                if (obj == null) {
-                    fail(assertMsg + " Object ID does not exist.");
-                }
+                assertNotEquals(assertMsg + " Object ID does not exist.", null, obj);
 
                 // What is the property supposed to be?
-                propertyValue =
-                    propertyValue.substring(3, propertyValue.length());
+                propertyValue = propertyValue.substring(3);
                 if (propertyValue.equals("path")) {
-                    if (!(obj instanceof Path)) {
-                        fail(assertMsg + " Path ID is a "
-                             + obj.getClass().getName());
-                    }
+                    assertThat(assertMsg + " Path ID is a " + obj.getClass().getName(),
+                            obj, instanceOf(Path.class));
                 } else {
                     assertEquals(assertMsg, propertyValue, obj.toString());
                 }
@@ -251,8 +243,7 @@
                     // The property is the name of a file.  We are testing
                     // a location attribute, so we need to resolve the given
                     // file name in the provided folder.
-                    String fileName =
-                        propertyValue.substring(5, propertyValue.length());
+                    String fileName = propertyValue.substring(5);
                     File f = new File(workingDir, fileName);
                     propertyValue = f.getAbsolutePath();
                 }
@@ -266,31 +257,19 @@
     /**
      * Debugging method to print the properties in the given hashtable
      */
-    private static void printProperties(Hashtable xmlproperties) {
-        Enumeration keyEnum = xmlproperties.keys();
-        while (keyEnum.hasMoreElements()) {
-            String currentKey = keyEnum.nextElement().toString();
-            System.out.println(currentKey + " = "
-                               + xmlproperties.get(currentKey));
-        }
+    @SuppressWarnings("unused")
+    private static void printProperties(Hashtable<Object, Object> xmlproperties) {
+        xmlproperties.forEach((key, value) -> System.out.println(key + " = " + value));
     }
 
     /**
      * Ensure all references loaded by the project are valid.
      */
-    private static void ensureReferences (String msg, File inputFile,
-                                          Hashtable references) {
-        Enumeration referenceKeyEnum = references.keys();
-        while(referenceKeyEnum.hasMoreElements()){
-            String currentKey = referenceKeyEnum.nextElement().toString();
-            Object currentValue = references.get(currentKey);
-
-            if (!(currentValue instanceof Path) && !(currentValue instanceof String)
-                    && !currentKey.startsWith("ant.")) {
-                fail(msg + "-" + inputFile.getName() + " Key="
-                        + currentKey + " is not a recognized type.");
-            }
-        }
+    private static void ensureReferences(String msg, File inputFile,
+                                         Hashtable<String, Object> references) {
+        references.forEach((key, value) -> assertTrue(msg + "-" + inputFile.getName()
+                + " Key=" + key + " is not a recognized type.",
+                value instanceof Path || value instanceof String || key.startsWith("ant.")));
     }
 
     /**
@@ -337,32 +316,30 @@
      * Retrieve a list of xml files in the specified folder
      * and below.
      */
-    private static Enumeration getFiles (final File startingDir) {
-        Vector result = new Vector();
+    private static List<File> getFiles(final File startingDir) {
+        List<File> result = new ArrayList<>();
         getFiles(startingDir, result);
-        return result.elements();
+        return result;
     }
 
     /**
      * Collect a list of xml files in the specified folder
      * and below.
      */
-    private static void getFiles (final File startingDir, Vector collect) {
-        FileFilter filter = new FileFilter() {
-            public boolean accept (File file) {
-                if (file.isDirectory()) {
-                    return true;
-                } else {
-                    return (file.getPath().indexOf("taskdefs") > 0 &&
-                            file.getPath().toLowerCase().endsWith(".xml"));
-                }
+    private static void getFiles(final File startingDir, List<File> collect) {
+        FileFilter filter = file -> {
+            if (file.isDirectory()) {
+                return true;
+            } else {
+                return file.getPath().contains("taskdefs")
+                        && file.getPath().toLowerCase().endsWith(".xml");
             }
         };
 
         File[] files = startingDir.listFiles(filter);
         for (File f : files) {
             if (!f.isDirectory()) {
-                collect.addElement(f);
+                collect.add(f);
             } else {
                 getFiles(f, collect);
             }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/XmlnsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/XmlnsTest.java
index 379fc02..60b1595 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/XmlnsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/XmlnsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,15 @@
 
 package org.apache.tools.ant.taskdefs;
 
+import static org.junit.Assert.assertEquals;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Task;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 
 public class XmlnsTest {
@@ -34,6 +34,9 @@
     @Rule
     public final BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/xmlns.xml");
@@ -59,12 +62,9 @@
 
     @Test
     public void testExcluded() {
-        try {
-            buildRule.executeTarget("excluded");
-            fail("BuildException expected: excluded uri");
-        } catch (BuildException ex) {
-            assertEquals("Attempt to use a reserved URI ant:notallowed", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Attempt to use a reserved URI ant:notallowed");
+        buildRule.executeTarget("excluded");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ZipExtraFieldTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ZipExtraFieldTest.java
index dcf4e38..6b53a68 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ZipExtraFieldTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ZipExtraFieldTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,9 +35,10 @@
 import org.apache.tools.zip.ZipFile;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
 
 public class ZipExtraFieldTest {
 
@@ -98,10 +99,10 @@
             ZipEntry ze = zf.getEntry("x");
             assertNotNull(ze);
             assertEquals(expectZip64 ? 2 : 1, ze.getExtraFields().length);
-            assertTrue(ze.getExtraFields()[0] instanceof JarMarker);
+            assertThat(ze.getExtraFields()[0], instanceOf(JarMarker.class));
             if (expectZip64) {
-                assertTrue(ze.getExtraFields()[1]
-                           instanceof Zip64ExtendedInformationExtraField);
+                assertThat(ze.getExtraFields()[1],
+                        instanceOf(Zip64ExtendedInformationExtraField.class));
             }
         } finally {
             ZipFile.closeQuietly(zf);
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java
index 4a73aec..f6b5615 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
 
 import org.apache.tools.ant.BuildException;
@@ -34,14 +33,14 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assume.assumeTrue;
 
-
 public class ZipTest {
 
     @Rule
@@ -50,52 +49,47 @@
     //instance variable to allow cleanup
     ZipFile zfPrefixAddsDir = null;
 
-
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/zip.xml");
         buildRule.executeTarget("setUp");
     }
 
-    @Test
+    /**
+     * Fail due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test1");
+        //TODO assert value
     }
 
-    @Test
+    /**
+     * Fail due to required argument not specified
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("BuildException expected: required argument not specified");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test2");
+        //TODO assert value
     }
 
-    @Test
+    /**
+     * Fail because zip cannot include itself
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("BuildException expected: zip cannot include itself");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test3");
+        //TODO assert value
     }
 
-    @Test
+    /**
+     * Fail because zip cannot include itself
+     */
+    @Test(expected = BuildException.class)
     @Ignore("Previously commented out")
     public void test4() {
-        try {
-            buildRule.executeTarget("test4");
-            fail("BuildException expected: zip cannot include itself");
-        } catch (BuildException ex) {
-            //TODO assert value
-        }
+        buildRule.executeTarget("test4");
+        //TODO assert value
     }
 
     @After
@@ -104,7 +98,6 @@
             if (zfPrefixAddsDir != null) {
                 zfPrefixAddsDir.close();
             }
-
         } catch (IOException e) {
             //ignored
         }
@@ -139,12 +132,12 @@
         ZipFile zipFile = new ZipFile(new File(buildRule.getProject().getProperty("output"),
                 "zipgroupfileset.zip"));
 
-        assertTrue(zipFile.getEntry("ant.xml") != null);
-        assertTrue(zipFile.getEntry("optional/jspc.xml") != null);
-        assertTrue(zipFile.getEntry("zip/zipgroupfileset3.zip") != null);
+        assertNotNull(zipFile.getEntry("ant.xml"));
+        assertNotNull(zipFile.getEntry("optional/jspc.xml"));
+        assertNotNull(zipFile.getEntry("zip/zipgroupfileset3.zip"));
 
-        assertTrue(zipFile.getEntry("test6.mf") == null);
-        assertTrue(zipFile.getEntry("test7.mf") == null);
+        assertNull(zipFile.getEntry("test6.mf"));
+        assertNull(zipFile.getEntry("test7.mf"));
 
         zipFile.close();
     }
@@ -152,13 +145,13 @@
     @Test
     public void testUpdateNotNecessary() {
        buildRule.executeTarget("testUpdateNotNecessary");
-        assertEquals(-1, buildRule.getLog().indexOf("Updating"));
+       assertThat(buildRule.getLog(), not(containsString("Updating")));
     }
 
     @Test
     public void testUpdateIsNecessary() {
         buildRule.executeTarget("testUpdateIsNecessary");
-        assertContains("Updating", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Updating"));
     }
 
     // Bugzilla Report 18403
@@ -206,7 +199,7 @@
     @Test
     public void testZipEmptyCreate() {
         buildRule.executeTarget("zipEmptyCreate");
-        assertContains("Note: creating empty", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Note: creating empty"));
     }
 
     // Bugzilla Report 25513
@@ -217,18 +210,10 @@
 
     // Bugzilla Report 33412
     @Test
-    public void testDefaultExcludesAndUpdate()
-        throws ZipException, IOException {
+    public void testDefaultExcludesAndUpdate() throws IOException {
        buildRule.executeTarget("testDefaultExcludesAndUpdate");
-        ZipFile f = null;
-        try {
-            f = new ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"));
-            assertNotNull("ziptest~ should be included",
-                          f.getEntry("ziptest~"));
-        } finally {
-            if (f != null) {
-                f.close();
-            }
+        try (ZipFile f = new ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"))) {
+            assertNotNull("ziptest~ should be included", f.getEntry("ziptest~"));
         }
     }
 
@@ -245,65 +230,41 @@
     @Test
     public void testTarFileSet() throws IOException {
         buildRule.executeTarget("testTarFileSet");
-        org.apache.tools.zip.ZipFile zf = null;
-        try {
-            zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"));
+        try (org.apache.tools.zip.ZipFile zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"))) {
             org.apache.tools.zip.ZipEntry ze = zf.getEntry("asf-logo.gif");
             assertEquals(UnixStat.FILE_FLAG | 0446, ze.getUnixMode());
-        } finally {
-            if (zf != null) {
-                zf.close();
-            }
         }
     }
 
     @Test
     public void testRewriteZeroPermissions() throws IOException {
        buildRule.executeTarget("rewriteZeroPermissions");
-        org.apache.tools.zip.ZipFile zf = null;
-        try {
-            zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"));
+        try (org.apache.tools.zip.ZipFile zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"))) {
             org.apache.tools.zip.ZipEntry ze = zf.getEntry("testdir/test.txt");
             assertEquals(UnixStat.FILE_FLAG | 0644, ze.getUnixMode());
-        } finally {
-            if (zf != null) {
-                zf.close();
-            }
         }
     }
 
     @Test
     public void testAcceptZeroPermissions() throws IOException {
        buildRule.executeTarget("acceptZeroPermissions");
-        org.apache.tools.zip.ZipFile zf = null;
-        try {
-            zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"));
+        try (org.apache.tools.zip.ZipFile zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"))) {
             org.apache.tools.zip.ZipEntry ze = zf.getEntry("testdir/test.txt");
             assertEquals(0000, ze.getUnixMode());
-        } finally {
-            if (zf != null) {
-                zf.close();
-            }
         }
     }
 
     @Test
     public void testForBugzilla34764() throws IOException {
        buildRule.executeTarget("testForBugzilla34764");
-        org.apache.tools.zip.ZipFile zf = null;
-        try {
-            zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"));
+        try (org.apache.tools.zip.ZipFile zf = new org.apache.tools.zip.ZipFile(new File(buildRule.getProject().getProperty("output"), "test3.zip"))) {
             org.apache.tools.zip.ZipEntry ze = zf.getEntry("file1");
             assertEquals(UnixStat.FILE_FLAG | 0644, ze.getUnixMode());
-        } finally {
-            if (zf != null) {
-                zf.close();
-            }
         }
     }
 
     @Test
-    public void testRegexpMapper() throws IOException {
+    public void testRegexpMapper() {
         buildRule.executeTarget("testRegexpMapper1");
         File testFile = new File(buildRule.getOutputDir(), "regexp.zip");
         long l = testFile.lastModified();
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 92a488c..581d10a 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,15 @@
 
 package org.apache.tools.ant.taskdefs.compilers;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
@@ -25,6 +34,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -33,13 +43,8 @@
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
-import org.junit.Assert;
 import org.junit.Test;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 
 public class DefaultCompilerAdapterTest {
 
@@ -252,6 +257,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;
@@ -266,22 +272,22 @@
             javac.setIncludeantruntime(false);
             javac.add(impl);
             javac.execute();
-            Assert.assertNotNull(cmd[0]);
+            assertNotNull(cmd[0]);
             final List<String> cmdLine = Arrays.asList(cmd[0].getCommandline());
             //No modulesourcepath
-            assertEquals(-1, cmdLine.indexOf("--module-source-path"));
+            assertThat(cmdLine, not(hasItem("--module-source-path")));
             //The -sourcepath has to be followed by src
             int index = cmdLine.indexOf("-sourcepath");
-            Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+            assertTrue(index != -1 && index < cmdLine.size() - 1);
             assertEquals(src.getAbsolutePath(), cmdLine.get(index + 1));
             //The --module-path has to be followed by modules
             index = cmdLine.indexOf("--module-path");
-            Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+            assertTrue(index != -1 && index < cmdLine.size() - 1);
             assertEquals(modules.getAbsolutePath(), cmdLine.get(index + 1));
             //J1.java & J2.java has to be in files list
-            final Set<String> expected = new TreeSet<String>();
+            final Set<String> expected = new TreeSet<>();
             Collections.addAll(expected, java1.getAbsolutePath(), java2.getAbsolutePath());
-            final Set<String> actual = new TreeSet<String>(cmdLine.subList(cmdLine.size() - 2, cmdLine.size()));
+            final Set<String> actual = new TreeSet<>(cmdLine.subList(cmdLine.size() - 2, cmdLine.size()));
             assertEquals(expected, actual);
         } finally {
             delete(workDir);
@@ -307,6 +313,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;
@@ -323,13 +330,13 @@
             javac.setIncludeantruntime(false);
             javac.add(impl);
             javac.execute();
-            Assert.assertNotNull(cmd[0]);
+            assertNotNull(cmd[0]);
             final List<String> cmdLine = Arrays.asList(cmd[0].getCommandline());
             //No sourcepath
-            assertEquals(-1, cmdLine.indexOf("-sourcepath"));
+            assertThat(cmdLine, not(hasItem("-sourcepath")));
             //The --module-source-path has to be followed by the pattern
             int index = cmdLine.indexOf("--module-source-path");
-            Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+            assertTrue(index != -1 && index < cmdLine.size() - 1);
             String expectedModSrcPath = String.format("%s/%s",
                     workDir.getAbsolutePath(),
                     moduleSrcPathStr)
@@ -338,15 +345,15 @@
             assertEquals(expectedModSrcPath, cmdLine.get(index + 1));
             //The --module-path has to be followed by modules
             index = cmdLine.indexOf("--module-path");
-            Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+            assertTrue(index != -1 && index < cmdLine.size() - 1);
             assertEquals(modules.getAbsolutePath(), cmdLine.get(index + 1));
             //J1.java, J2.java & J3.java has to be in files list
-            final Set<String> expectedFiles = new TreeSet<String>();
+            final Set<String> expectedFiles = new TreeSet<>();
             Collections.addAll(expectedFiles,
                     java1.getAbsolutePath(),
                     java2.getAbsolutePath(),
                     java3.getAbsolutePath());
-            final Set<String> actualFiles = new TreeSet<String>(cmdLine.subList(cmdLine.size() - 3, cmdLine.size()));
+            final Set<String> actualFiles = new TreeSet<>(cmdLine.subList(cmdLine.size() - 3, cmdLine.size()));
             assertEquals(expectedFiles, actualFiles);
         } finally {
             delete(workDir);
@@ -370,6 +377,7 @@
             final LogCapturingJavac javac = new LogCapturingJavac();
             javac.setProject(prj);
             final DefaultCompilerAdapter impl = new DefaultCompilerAdapter() {
+                @Override
                 public boolean execute() throws BuildException {
                     setupModernJavacCommand();
                     return true;
@@ -387,17 +395,14 @@
             javac.add(impl);
             javac.execute();
             final File[] compileList = impl.compileList;
-            Assert.assertNotNull(compileList);
+            assertNotNull(compileList);
             //J1.java, J2.java has to be in files list but not J3.java
-            final Set<String> expectedFiles = new TreeSet<String>();
+            final Set<String> expectedFiles = new TreeSet<>();
             Collections.addAll(expectedFiles,
                     java1.getAbsolutePath(),
                     java2.getAbsolutePath());
-            final Set<String> actualFiles = new TreeSet<String>();
-            for (File compileFile : compileList) {
-                actualFiles.add(compileFile.getAbsolutePath());
-            }
-            assertEquals(expectedFiles, actualFiles);
+            assertEquals(expectedFiles, Arrays.stream(compileList)
+                    .map(File::getAbsolutePath).collect(Collectors.toCollection(TreeSet::new)));
         } finally {
             delete(workDir);
         }
@@ -408,7 +413,7 @@
         LogCapturingJavac javac = new LogCapturingJavac();
         Project p = new Project();
         javac.setProject(p);
-        javac.setCompiler("javac8");
+        javac.setCompiler("javac1.8");
         javac.setSource("6");
         javac.setTarget("6");
         javac.setRelease("6");
@@ -417,8 +422,8 @@
         sth.setJavac(javac);
         Commandline cmd = new Commandline();
         sth.setupModernJavacCommandlineSwitches(cmd);
-        assertContains("Support for javac --release has been added in "
-                       + "Java9 ignoring it", javac.getLog());
+        assertThat(javac.getLog(),
+                containsString("Support for javac --release has been added in Java9 ignoring it"));
         String[] args = cmd.getCommandline();
         assertEquals(7, args.length);
         assertEquals("-classpath", args[0]);
@@ -443,8 +448,8 @@
         sth.setJavac(javac);
         Commandline cmd = new Commandline();
         sth.setupModernJavacCommandlineSwitches(cmd);
-        assertContains("Ignoring source, target and bootclasspath as "
-                       + "release has been set", javac.getLog());
+        assertThat(javac.getLog(),
+                containsString("Ignoring source, target and bootclasspath as release has been set"));
         String[] args = cmd.getCommandline();
         assertEquals(5, args.length);
         assertEquals("-classpath", args[0]);
@@ -453,6 +458,88 @@
         assertEquals("6", args[4]);
     }
 
+    @Test
+    public void testAssumeJavaXPlus() {
+    	LogCapturingJavac javac = new LogCapturingJavac();
+        Project p = new Project();
+        javac.setProject(p);
+        DefaultCompilerAdapter ca = new DefaultCompilerAdapter() {	
+			@Override
+			public boolean execute() throws BuildException {
+				// TODO Auto-generated method stub
+				return false;
+			}
+		};
+		ca.setJavac(javac);
+		System.out.println(javac.getCompiler());
+		
+		if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_10)) {
+			assertTrue(ca.assumeJava10Plus());
+			assertTrue(ca.assumeJava9Plus());
+		} else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_9)) {
+			assertFalse(ca.assumeJava10Plus());
+			assertTrue(ca.assumeJava9Plus());
+			assertTrue(ca.assumeJava1_8Plus());
+		} else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8)) {
+			assertFalse(ca.assumeJava9Plus());
+			assertTrue(ca.assumeJava1_8Plus());
+			assertTrue(ca.assumeJava1_7Plus());
+		}
+		javac.setCompiler("javac10+");
+		assertTrue(ca.assumeJava10Plus());
+		assertTrue(ca.assumeJava9Plus());
+		
+		javac.setCompiler("javac9");
+		assertFalse(ca.assumeJava10Plus());
+		assertTrue(ca.assumeJava9Plus());
+		assertTrue(ca.assumeJava1_8Plus());
+		
+		javac.setCompiler("javac1.9");
+		assertFalse(ca.assumeJava10Plus());
+		assertTrue(ca.assumeJava9Plus());
+		assertTrue(ca.assumeJava1_8Plus());
+		
+		javac.setCompiler("javac1.8");
+		assertFalse(ca.assumeJava9Plus());
+		assertTrue(ca.assumeJava1_8Plus());
+		assertTrue(ca.assumeJava1_7Plus());
+		
+		javac.setCompiler("javac1.7");
+		assertFalse(ca.assumeJava1_8Plus());
+		assertTrue(ca.assumeJava1_7Plus());
+		assertTrue(ca.assumeJava1_6Plus());
+		
+		javac.setCompiler("javac1.6");
+		assertFalse(ca.assumeJava1_7Plus());
+		assertTrue(ca.assumeJava1_6Plus());
+		assertTrue(ca.assumeJava1_5Plus());
+		
+		javac.setCompiler("javac1.5");
+		assertFalse(ca.assumeJava1_6Plus());
+		assertTrue(ca.assumeJava1_5Plus());
+		assertTrue(ca.assumeJava1_4Plus());
+		
+		javac.setCompiler("javac1.4");
+		assertFalse(ca.assumeJava1_5Plus());
+		assertTrue(ca.assumeJava1_4Plus());
+		assertTrue(ca.assumeJava1_3Plus());
+		
+		javac.setCompiler("javac1.3");
+		assertFalse(ca.assumeJava1_4Plus());
+		assertTrue(ca.assumeJava1_3Plus());
+		assertTrue(ca.assumeJava1_2Plus());
+		
+		javac.setCompiler("javac1.2");
+		assertFalse(ca.assumeJava1_3Plus());
+		assertTrue(ca.assumeJava1_2Plus());
+		assertTrue(ca.assumeJava1_1Plus());
+		
+		javac.setCompiler("javac1.1");
+		assertFalse(ca.assumeJava1_2Plus());
+		assertTrue(ca.assumeJava1_1Plus());
+    }
+    
+
     /**
      * @see "https://bz.apache.org/bugzilla/show_bug.cgi?id=65539"
      */
@@ -466,32 +553,19 @@
         javac.setSourcepath(new Path(p));
         SourceTargetHelperNoOverride ca = new SourceTargetHelperNoOverride();
         ca.setJavac(javac);
-        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
+        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_10)) {
+            assertTrue(ca.assumeJava10Plus());
             assertTrue(ca.assumeJava9Plus());
-            assertTrue(ca.assumeJava9());
-            assertTrue(ca.assumeJava19());
-            assertFalse(ca.assumeJava18());
+        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_9)) {
+            assertFalse(ca.assumeJava10Plus());
+            assertTrue(ca.assumeJava9Plus());
         } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8)) {
+            assertFalse(ca.assumeJava10Plus());
             assertFalse(ca.assumeJava9Plus());
-            assertFalse(ca.assumeJava9());
-            assertTrue(ca.assumeJava18());
-            assertFalse(ca.assumeJava17());
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_7)) {
-            assertFalse(ca.assumeJava9Plus());
-            assertFalse(ca.assumeJava18());
-            assertTrue(ca.assumeJava17());
-            assertFalse(ca.assumeJava16());
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6)) {
-            assertFalse(ca.assumeJava9Plus());
-            assertFalse(ca.assumeJava17());
-            assertTrue(ca.assumeJava16());
-            assertFalse(ca.assumeJava15());
-        } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5)) {
-            assertFalse(ca.assumeJava9Plus());
-            assertFalse(ca.assumeJava16());
-            assertTrue(ca.assumeJava15());
-            assertFalse(ca.assumeJava14());
         }
+        assertTrue(ca.assumeJava1_8Plus());
+        assertTrue(ca.assumeJava1_7Plus());
+        assertTrue(ca.assumeJava1_2Plus());
     }
 
     private void commonSourceDowngrades(String javaVersion) {
@@ -527,11 +601,10 @@
         sth.setJavac(javac);
         Commandline cmd = new Commandline();
         sth.setupModernJavacCommandlineSwitches(cmd);
-        if ("".equals(expectedLog)) {
+        if (expectedLog.isEmpty()) {
             assertEquals("", javac.getLog());
         } else {
-            String l = javac.getLog();
-            assertContains(expectedLog, l);
+            assertThat(javac.getLog(), containsString(expectedLog));
         }
         String[] args = cmd.getCommandline();
         assertEquals(expectedSource == null ? 0 : 2, args.length);
@@ -563,9 +636,7 @@
         if (f.isDirectory()) {
             final File[] clds = f.listFiles();
             if (clds != null) {
-                for (File cld : clds) {
-                    delete(cld);
-                }
+                Arrays.stream(clds).forEach(this::delete);
             }
         }
         f.delete();
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/JavacExternalTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/JavacExternalTest.java
new file mode 100644
index 0000000..a893fb4
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/JavacExternalTest.java
@@ -0,0 +1,203 @@
+/*
+ *  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
+ *
+ *      https://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.Project;
+import org.apache.tools.ant.taskdefs.Javac;
+import org.apache.tools.ant.types.Commandline;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class JavacExternalTest {
+    private static class TestJavacExternal extends JavacExternal {
+        private String[] args;
+        private int firstFileName;
+
+        @Override
+        protected int executeExternalCompile(String[] args, int firstFileName, final boolean quoteFiles) {
+            this.args = args;
+            this.firstFileName = firstFileName;
+            return 0;
+        }
+
+        public String[] getArgs() {
+            return args;
+        }
+
+        public int getFirstFileName() {
+            return firstFileName;
+        }
+    }
+
+    @Test
+    public void allJavacOptionsButJAreWrittenToFile() throws Exception {
+        final File workDir = createWorkDir("testSMC");
+        try {
+            final File src = new File(workDir, "src");
+            src.mkdir();
+            createFile(src, "org/apache/ant/tests/J1.java");
+            createFile(src, "org/apache/ant/tests/J2.java");
+            final File modules = new File(workDir, "modules");
+            modules.mkdir();
+            final Project prj = new Project();
+            prj.setBaseDir(workDir);
+            final Javac javac = new Javac();
+            javac.setProject(prj);
+            final Commandline[] cmd = new Commandline[1];
+            final TestJavacExternal impl = new TestJavacExternal();
+            final Path srcPath = new Path(prj);
+            srcPath.setLocation(src);
+            javac.setSrcdir(srcPath);
+            javac.createModulepath().setLocation(modules);
+            javac.setSource("9");
+            javac.setTarget("9");
+            javac.setFork(true);
+            javac.setMemoryInitialSize("80m");
+            javac.setExecutable("javacExecutable");
+            javac.add(impl);
+            javac.execute();
+            assertEquals("javacExecutable", impl.getArgs()[0]);
+            assertEquals("-J-Xms80m", impl.getArgs()[1]);
+            assertTrue(impl.getArgs()[impl.getArgs().length - 1].endsWith("J2.java"));
+            assertEquals(2, impl.getFirstFileName());
+        } finally {
+            delete(workDir);
+        }
+    }
+
+    @Test
+    public void allJOptionsAreMovedToBeginning() throws Exception {
+        final File workDir = createWorkDir("testSMC");
+        try {
+            final File src = new File(workDir, "src");
+            src.mkdir();
+            createFile(src, "org/apache/ant/tests/J1.java");
+            createFile(src, "org/apache/ant/tests/J2.java");
+            final File modules = new File(workDir, "modules");
+            modules.mkdir();
+            final Project prj = new Project();
+            prj.setBaseDir(workDir);
+            final Javac javac = new Javac();
+            javac.setProject(prj);
+            final Commandline[] cmd = new Commandline[1];
+            final TestJavacExternal impl = new TestJavacExternal();
+            final Path srcPath = new Path(prj);
+            srcPath.setLocation(src);
+            javac.setSrcdir(srcPath);
+            javac.createModulepath().setLocation(modules);
+            javac.setSource("9");
+            javac.setTarget("9");
+            javac.setFork(true);
+            javac.setMemoryInitialSize("80m");
+            javac.setExecutable("javacExecutable");
+            javac.add(impl);
+            javac.createCompilerArg().setValue("-JDfoo=bar");
+            javac.createCompilerArg().setValue("-JDred=color");
+            javac.createCompilerArg().setLine("-JDspace line");
+            javac.execute();
+            assertEquals("javacExecutable", impl.getArgs()[0]);
+            assertEquals("-J-Xms80m", impl.getArgs()[1]);
+            assertEquals("-JDfoo=bar", impl.getArgs()[2]);
+            assertEquals("-JDred=color", impl.getArgs()[3]);
+            assertEquals("-JDspace", impl.getArgs()[4]);
+            assertTrue(impl.getArgs()[impl.getArgs().length - 1].endsWith("J2.java"));
+            assertEquals(5, impl.getFirstFileName());
+        } finally {
+            delete(workDir);
+        }
+    }
+
+    @Test
+    public void argFileOptionIsMovedToBeginning() throws Exception {
+        final File workDir = createWorkDir("testSMC");
+        try {
+            final File src = new File(workDir, "src");
+            src.mkdir();
+            createFile(src, "org/apache/ant/tests/J1.java");
+            createFile(src, "org/apache/ant/tests/J2.java");
+            final File modules = new File(workDir, "modules");
+            modules.mkdir();
+            final Project prj = new Project();
+            prj.setBaseDir(workDir);
+            final Javac javac = new Javac();
+            javac.setProject(prj);
+            final Commandline[] cmd = new Commandline[1];
+            final TestJavacExternal impl = new TestJavacExternal();
+            final Path srcPath = new Path(prj);
+            srcPath.setLocation(src);
+            javac.setSrcdir(srcPath);
+            javac.createModulepath().setLocation(modules);
+            javac.setSource("9");
+            javac.setTarget("9");
+            javac.setFork(true);
+            javac.setMemoryInitialSize("80m");
+            javac.setExecutable("javacExecutable");
+            javac.add(impl);
+            javac.createCompilerArg().setValue("-g");
+            javac.createCompilerArg().setValue("@/home/my-compiler.args");
+            javac.execute();
+            assertEquals("javacExecutable", impl.getArgs()[0]);
+            assertEquals("-J-Xms80m", impl.getArgs()[1]);
+            assertEquals("@/home/my-compiler.args", impl.getArgs()[2]);
+            assertTrue(Stream.of(impl.getArgs()).anyMatch(x -> x.equals("-g")));
+            assertTrue(impl.getArgs()[impl.getArgs().length - 2].endsWith("J1.java"));
+            assertTrue(impl.getArgs()[impl.getArgs().length - 1].endsWith("J2.java"));
+            assertEquals(3, impl.getFirstFileName());
+        } finally {
+            delete(workDir);
+        }
+    }
+
+    private File createWorkDir(String testName) {
+        final File tmp = new File(System.getProperty("java.io.tmpdir"));   //NOI18N
+        final File destDir = new File(tmp, String.format("%s%s%d",
+                getClass().getName(),
+                testName,
+                System.currentTimeMillis() / 1000));
+        destDir.mkdirs();
+        return destDir;
+    }
+
+    private File createFile(File folder, String relativePath) throws IOException {
+        final File file = new File(
+                folder,
+                relativePath.replace('/', File.separatorChar).replace('\\', File.separatorChar));
+        FileUtils.getFileUtils().createNewFile(file, true);
+        return file;
+    }
+
+    private void delete(File f) {
+        if (f.isDirectory()) {
+            final File[] clds = f.listFiles();
+            if (clds != null) {
+                Arrays.stream(clds).forEach(this::delete);
+            }
+        }
+        f.delete();
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/AntVersionTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/AntVersionTest.java
index b70a138..2464f83 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/AntVersionTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/AntVersionTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,7 +32,7 @@
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/conditions/antversion.xml");
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ContainsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ContainsTest.java
index a45b511..b179a52 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ContainsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ContainsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,6 +20,7 @@
 
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -33,7 +34,7 @@
         Contains con = new Contains();
         con.setString("abc");
         con.setSubstring("A");
-        assertTrue(!con.eval());
+        assertFalse(con.eval());
 
         con.setCasesensitive(false);
         assertTrue(con.eval());
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/EqualsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/EqualsTest.java
index 5f9b996..78e6628 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/EqualsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/EqualsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,10 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
+import org.junit.Before;
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -28,12 +30,18 @@
  */
 public class EqualsTest {
 
+    private Equals eq;
+
+    @Before
+    public void setUp() {
+        eq = new Equals();
+    }
+
     @Test
     public void testTrim() {
-        Equals eq = new Equals();
         eq.setArg1("a");
         eq.setArg2(" a");
-        assertTrue(!eq.eval());
+        assertFalse(eq.eval());
 
         eq.setTrim(true);
         assertTrue(eq.eval());
@@ -44,10 +52,9 @@
 
     @Test
     public void testCaseSensitive() {
-        Equals eq = new Equals();
         eq.setArg1("a");
         eq.setArg2("A");
-        assertTrue(!eq.eval());
+        assertFalse(eq.eval());
 
         eq.setCasesensitive(false);
         assertTrue(eq.eval());
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/HttpTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/HttpTest.java
index 15a9d2d..01cfc48 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/HttpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/HttpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,7 +25,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
 
 /**
  * Testcases for the &lt;http&gt; condition. All these tests require
@@ -63,14 +62,12 @@
         assertNull(buildRule.getProject().getProperty("test-get-request-bad-url"));
     }
 
-    @Test
+    /**
+     * Expected failure due to invalid HTTP request method specified
+     */
+    @Test(expected = BuildException.class)
     public void testBadRequestMethod() {
-        try {
-            buildRule.executeTarget("bad-request-method");
-            fail("Exception should have been thrown as invalid HTTP request method specified");
-        } catch (BuildException ex) {
-            //TODO we should assert the correct build exception was thrown
-        }
+        buildRule.executeTarget("bad-request-method");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFailureTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFailureTest.java
index 8659476..193f78f 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFailureTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFailureTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFileSelectedTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFileSelectedTest.java
index 84d88a5..5d560d5 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFileSelectedTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsFileSelectedTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,14 +18,12 @@
 
 package org.apache.tools.ant.taskdefs.condition;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Testcase for the &lt;isfileselected&gt; condition.
@@ -36,6 +34,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/conditions/isfileselected.xml");
@@ -63,12 +64,8 @@
 
     @Test
     public void testNotSelector() {
-        try {
-            buildRule.executeTarget("not.selector");
-            fail("Exception should have been thrown: checking for use as a selector (not allowed)");
-        } catch(BuildException ex) {
-            AntAssert.assertContains("fileset doesn't support the nested \"isfile",
-                    ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("fileset doesn't support the nested \"isfileselected\"");
+        buildRule.executeTarget("not.selector");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java
index a58fb97..46205903 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,16 +17,13 @@
  */
 package org.apache.tools.ant.taskdefs.condition;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * test for reachable things
@@ -36,81 +33,67 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
-        buildRule.configureProject(
-                "src/etc/testcases/taskdefs/conditions/isreachable.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/conditions/isreachable.xml");
     }
 
-
     @Test
-    public void testLocalhost() throws Exception {
+    public void testLocalhost() {
         buildRule.executeTarget("testLocalhost");
     }
 
     @Test
-    public void testLocalhostURL() throws Exception {
+    public void testLocalhostURL() {
         buildRule.executeTarget("testLocalhostURL");
     }
 
     @Test
-    public void testIpv4localhost() throws Exception {
+    public void testIpv4localhost() {
         buildRule.executeTarget("testIpv4localhost");
     }
 
     @Test
-    public void testFTPURL() throws Exception {
+    public void testFTPURL() {
         buildRule.executeTarget("testFTPURL");
     }
 
     @Test
-    public void testBoth() throws Exception {
-        try {
-           buildRule.executeTarget("testBoth");
-            fail("Build exception expected: error on two targets");
-        } catch (BuildException ex) {
-            assertEquals(IsReachable.ERROR_BOTH_TARGETS, ex.getMessage());
-        }
+    public void testBoth() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(IsReachable.ERROR_BOTH_TARGETS);
+        buildRule.executeTarget("testBoth");
     }
 
     @Test
-    public void testNoTargets() throws Exception {
-        try {
-            buildRule.executeTarget("testNoTargets");
-            fail("Build exception expected: no params");
-        } catch (BuildException ex) {
-            assertEquals(IsReachable.ERROR_NO_HOSTNAME, ex.getMessage());
-        }
+    public void testNoTargets() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(IsReachable.ERROR_NO_HOSTNAME);
+        buildRule.executeTarget("testNoTargets");
     }
 
     @Test
-    public void testBadTimeout() throws Exception {
-        try {
-            buildRule.executeTarget("testBadTimeout");
-            fail("Build exception expected: error on -ve timeout");
-        } catch (BuildException ex) {
-            assertEquals(IsReachable.ERROR_BAD_TIMEOUT, ex.getMessage());
-        }
+    public void testBadTimeout() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(IsReachable.ERROR_BAD_TIMEOUT);
+        buildRule.executeTarget("testBadTimeout");
     }
 
     @Test
     @Ignore("Previously named in a way to prevent execution")
-    public void NotestFile() throws Exception {
-        try {
-            buildRule.executeTarget("testFile");
-            fail("Build exception expected: error on file URL");
-        } catch (BuildException ex) {
-            assertEquals(IsReachable.ERROR_NO_HOST_IN_URL, ex.getMessage());
-        }
+    public void NotestFile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(IsReachable.ERROR_NO_HOST_IN_URL);
+        buildRule.executeTarget("testFile");
     }
 
     @Test
-    public void testBadURL() throws Exception {
-        try {
-            buildRule.executeTarget("testBadURL");
-            fail("Build exception expected: error in URL");
-        } catch(BuildException ex) {
-            AntAssert.assertContains(IsReachable.ERROR_BAD_URL, ex.getMessage());
-        }
+    public void testBadURL() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(IsReachable.ERROR_BAD_URL);
+        buildRule.executeTarget("testBadURL");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReferenceTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReferenceTest.java
index 01b6b47..1c708b5 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReferenceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsReferenceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,9 +22,9 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNull;
 
 /**
@@ -36,6 +36,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/conditions/isreference.xml");
@@ -49,14 +52,14 @@
         assertNull(buildRule.getProject().getProperty("undefined"));
     }
 
+    /**
+     * Expected failure due to omitted refid attribute
+     */
     @Test
     public void testNotEnoughArgs() {
-        try {
-            buildRule.executeTarget("isreference-incomplete");
-            fail("Build exception expected: refid attirbute has been omitted");
-        } catch(BuildException ex) {
-            assertEquals("No reference specified for isreference condition", ex.getMessage());
-        }
+        thrown.expect(BuildException .class) ;
+            thrown.expectMessage("No reference specified for isreference condition");
+        buildRule.executeTarget("isreference-incomplete");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsSignedTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsSignedTest.java
index 0f4001c..a66aaa9 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsSignedTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/IsSignedTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ParserSupportsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ParserSupportsTest.java
index 271c19b..4d0a8de 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ParserSupportsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/ParserSupportsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,9 +24,7 @@
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
 
@@ -36,6 +34,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/conditions/parsersupports.xml");
@@ -43,22 +44,16 @@
 
     @Test
     public void testEmpty() {
-        try {
-            buildRule.executeTarget("testEmpty");
-            fail("Build exception expected: " + ParserSupports.ERROR_NO_ATTRIBUTES);
-        } catch(BuildException ex) {
-            assertEquals(ParserSupports.ERROR_NO_ATTRIBUTES, ex.getMessage());
-        }
+        thrown.expect(BuildException .class);
+        thrown.expectMessage(ParserSupports.ERROR_NO_ATTRIBUTES);
+        buildRule.executeTarget("testEmpty");
     }
 
     @Test
     public void testBoth() {
-        try {
-            buildRule.executeTarget("testBoth");
-            fail("Build exception expected: " + ParserSupports.ERROR_BOTH_ATTRIBUTES);
-        } catch(BuildException ex) {
-            assertEquals(ParserSupports.ERROR_BOTH_ATTRIBUTES, ex.getMessage());
-        }
+        thrown.expect(BuildException .class);
+        thrown.expectMessage(ParserSupports.ERROR_BOTH_ATTRIBUTES);
+        buildRule.executeTarget("testBoth");
     }
 
     @Test
@@ -68,12 +63,9 @@
 
     @Test
     public void testPropertyNoValue() {
-        try {
-            buildRule.executeTarget("testPropertyNoValue");
-            fail("Build exception expected: " + ParserSupports.ERROR_NO_VALUE);
-        } catch(BuildException ex) {
-            assertEquals(ParserSupports.ERROR_NO_VALUE, ex.getMessage());
-        }
+        thrown.expect(BuildException .class);
+        thrown.expectMessage(ParserSupports.ERROR_NO_VALUE);
+        buildRule.executeTarget("testPropertyNoValue");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/TypeFoundTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/TypeFoundTest.java
index 6c73188..e31e760 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/TypeFoundTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/TypeFoundTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,15 +17,14 @@
  */
 package org.apache.tools.ant.taskdefs.condition;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNull;
 
 /**
@@ -36,6 +35,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/conditions/typefound.xml");
@@ -47,14 +49,14 @@
         assertEquals("true", buildRule.getProject().getProperty("testTask"));
     }
 
+    /**
+     * Expected failure due to missing name attribute
+     */
     @Test
     public void testUndefined() {
-        try {
-            buildRule.executeTarget("testUndefined");
-            fail("Build exception expected: left out the name attribute");
-        } catch(BuildException ex) {
-            AntAssert.assertContains("No type specified", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("No type specified");
+        buildRule.executeTarget("testUndefined");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/XorTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/XorTest.java
index 4f04c35..635a90e 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/condition/XorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/condition/XorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParserTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParserTest.java
index fd065d1..2a3dd23 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParserTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParserTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,7 +34,7 @@
     protected ChangeLogParser parser = new ChangeLogParser();
 
     @Test
-    public void testOldCvsFormat() throws Exception {
+    public void testOldCvsFormat() {
         parser.stdout("Working file: build.xml");
         parser.stdout("revision 1.475");
         parser.stdout("date: 2004/06/05 16:10:32;  author: somebody;  state: Exp;  lines: +2 -2");
@@ -50,7 +50,7 @@
     }
 
     @Test
-    public void testCvs112Format() throws Exception {
+    public void testCvs112Format() {
         parser.stdout("Working file: build.xml");
         parser.stdout("revision 1.475");
         parser.stdout("date: 2004-06-05 16:10:32 +0000; author: somebody; state: Exp;  lines: +2 -2");
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriterTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriterTest.java
index 19b37a4..1e47906 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,6 +22,7 @@
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 
 import org.apache.tools.ant.util.JAXPUtils;
@@ -48,7 +49,7 @@
         CVSEntry[] entries = {entry};
 
         ByteArrayOutputStream output = new ByteArrayOutputStream();
-        PrintWriter pwriter = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));
+        PrintWriter pwriter = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
         writer.printChangeLog(pwriter, entries);
 
         // make sure that the parsing does not break
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/dir1/B.java b/src/tests/junit/org/apache/tools/ant/taskdefs/dir1/B.java
index 9057fa0..1fc5db3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/dir1/B.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/dir1/B.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/dir2/A.java b/src/tests/junit/org/apache/tools/ant/taskdefs/dir2/A.java
index 82b2048..4162b84 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/dir2/A.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/dir2/A.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java
index 00befcd..9eb17ff 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailAddressTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailTaskTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailTaskTest.java
index 200ebac..57660dc 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/email/EmailTaskTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,6 +25,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * TODO : develop these testcases - the email task needs to have attributes allowing
@@ -35,6 +36,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/email/mail.xml");
@@ -45,15 +49,9 @@
      */
     @Test
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            Assert.fail("Execution of mail task was expected to fail");
-        } catch (BuildException e) {
-            // assert it's the expected one
-            if (!e.getMessage().equals("SMTP auth only possible with MIME mail")) {
-                throw e;
-            }
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("SMTP auth only possible with MIME mail");
+        buildRule.executeTarget("test1");
     }
 
     /**
@@ -61,15 +59,9 @@
      */
     @Test
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            Assert.fail("Execution of mail task was expected to fail");
-        } catch (BuildException e) {
-            // assert it's the expected one
-            if (!e.getMessage().equals("SSL and STARTTLS only possible with MIME mail")) {
-                throw e;
-            }
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("SSL and STARTTLS only possible with MIME mail");
+        buildRule.executeTarget("test2");
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/email/MessageTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/email/MessageTest.java
index df75067..375ff30 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/email/MessageTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/email/MessageTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,19 +18,19 @@
 
 package org.apache.tools.ant.taskdefs.email;
 
-import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
 
 import org.apache.tools.ant.Project;
-import org.apache.tools.ant.util.FileUtils;
-import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 public class MessageTest {
-    private static final File f = new File(System.getProperty("java.io.tmpdir"),
-                              "message.txt");
+    @Rule
+    public TemporaryFolder testFolder = new TemporaryFolder();
+
     /**
      * test for bugzilla 48932
      */
@@ -40,23 +40,9 @@
         Project p = new Project();
         ms.setProject(p);
         ms.addText("hi, this is an email");
-        FileOutputStream fis = null;
-        try {
-            fis = new FileOutputStream(f);
-            ms.print(new PrintStream(fis));
-            fis.write(120);
-        } finally {
-            FileUtils.close(fis);
-        }
-
-    }
-
-    @After
-    public void tearDown() {
-        if (f.exists()) {
-            FileUtils fu = FileUtils.getFileUtils();
-            fu.tryHardToDelete(f);
+        try (FileOutputStream fos = new FileOutputStream(testFolder.newFile("message.txt"))) {
+            ms.print(new PrintStream(fos));
+            fos.write(120);
         }
     }
-
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/modules/JmodTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/modules/JmodTest.java
new file mode 100644
index 0000000..dda3272
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/modules/JmodTest.java
@@ -0,0 +1,690 @@
+/*
+ *  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
+ *
+ *      https://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.modules;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.nio.file.Files;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+import java.util.spi.ToolProvider;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+
+/**
+ * Tests the {@link Jmod} task.
+ */
+public class JmodTest {
+    @Rule
+    public final BuildFileRule buildRule = new BuildFileRule();
+
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/jmod.xml");
+        buildRule.executeTarget("setUp");
+    }
+
+    @Test
+    public void testDestAndClasspathNoJmod() {
+        buildRule.executeTarget("destAndClasspathNoJmod");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testDestAndNestedClasspath() {
+        buildRule.executeTarget("classpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testDestAndClasspathOlderThanJmod()
+    throws IOException {
+        buildRule.executeTarget("destAndClasspathOlderThanJmod");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        File jar = new File(buildRule.getProject().getProperty("hello.jar"));
+        Assert.assertTrue("Checking that newer jmod was not written "
+            + "when source files are older.",
+            Files.getLastModifiedTime(jmod.toPath()).toInstant().isAfter(
+                Instant.now().plus(30, ChronoUnit.MINUTES)));
+    }
+
+    @Test
+    public void testNoDestFile() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("noDestFile");
+    }
+
+    @Test
+    public void testNoClasspath() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("noClasspath");
+    }
+
+    @Test
+    public void testEmptyClasspath() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("emptyClasspath");
+    }
+
+    @Test
+    public void testClasspathEntirelyNonexistent() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("nonexistentClasspath");
+    }
+
+    @Test
+    public void testClasspathref() {
+        buildRule.executeTarget("classpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testClasspathAttributeAndChildElement() {
+        buildRule.executeTarget("classpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testModulepath() {
+        buildRule.executeTarget("modulepath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testModulepathref() {
+        buildRule.executeTarget("modulepathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testModulepathNested() {
+        buildRule.executeTarget("modulepath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testModulepathNonDir() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("modulepathnondir");
+    }
+
+    @Test
+    public void testModulepathAttributeAndChildElement() {
+        buildRule.executeTarget("modulepath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+    }
+
+    @Test
+    public void testCommandPath() {
+        buildRule.executeTarget("commandpath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains command.",
+            containsLine(output, l -> l.equals("bin/command1")));
+    }
+
+    @Test
+    public void testCommandPathref() {
+        buildRule.executeTarget("commandpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains command.",
+            containsLine(output, l -> l.equals("bin/command2")));
+    }
+
+    @Test
+    public void testCommandPathNested() {
+        buildRule.executeTarget("commandpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains command.",
+            containsLine(output, l -> l.equals("bin/command3")));
+    }
+
+    @Test
+    public void testCommandPathAttributeAndChildElement() {
+        buildRule.executeTarget("commandpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains commands "
+            + "from both attribute and child element.",
+            containsAll(output,
+                l -> l.equals("bin/command4"),
+                l -> l.equals("bin/command5")));
+    }
+
+    @Test
+    public void testHeaderPath() {
+        buildRule.executeTarget("headerpath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains header file.",
+            containsLine(output, l -> l.equals("include/header1.h")));
+    }
+
+    @Test
+    public void testHeaderPathref() {
+        buildRule.executeTarget("headerpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains header file.",
+            containsLine(output, l -> l.equals("include/header2.h")));
+    }
+
+    @Test
+    public void testHeaderPathNested() {
+        buildRule.executeTarget("headerpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains header file.",
+            containsLine(output, l -> l.equals("include/header3.h")));
+    }
+
+    @Test
+    public void testHeaderPathAttributeAndChildElement() {
+        buildRule.executeTarget("headerpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains header files "
+            + "from both attribute and child element.",
+            containsAll(output,
+                l -> l.equals("include/header4.h"),
+                l -> l.equals("include/header5.h")));
+    }
+
+    @Test
+    public void testConfigPath() {
+        buildRule.executeTarget("configpath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains config file.",
+            containsLine(output, l -> l.equals("conf/config1.properties")));
+    }
+
+    @Test
+    public void testConfigPathref() {
+        buildRule.executeTarget("configpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains config file.",
+            containsLine(output, l -> l.equals("conf/config2.properties")));
+    }
+
+    @Test
+    public void testConfigPathNested() {
+        buildRule.executeTarget("configpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains config file.",
+            containsLine(output, l -> l.equals("conf/config3.properties")));
+    }
+
+    @Test
+    public void testConfigPathAttributeAndChildElement() {
+        buildRule.executeTarget("configpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains config files "
+            + "from both attribute and child element.",
+            containsAll(output,
+                l -> l.equals("conf/config4.properties"),
+                l -> l.equals("conf/config5.properties")));
+    }
+
+    @Test
+    public void testLegalPath() {
+        buildRule.executeTarget("legalpath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains license file.",
+            containsLine(output, l -> l.equals("legal/legal1.txt")));
+    }
+
+    @Test
+    public void testLegalPathref() {
+        buildRule.executeTarget("legalpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains license file.",
+            containsLine(output, l -> l.equals("legal/legal2.txt")));
+    }
+
+    @Test
+    public void testLegalPathNested() {
+        buildRule.executeTarget("legalpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains license file.",
+            containsLine(output, l -> l.equals("legal/legal3.txt")));
+    }
+
+    @Test
+    public void testLegalPathAttributeAndChildElement() {
+        buildRule.executeTarget("legalpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains legal files "
+            + "from both attribute and child element.",
+            containsAll(output,
+                l -> l.equals("legal/legal4.txt"),
+                l -> l.equals("legal/legal5.txt")));
+    }
+
+    @Test
+    public void testManPath() {
+        buildRule.executeTarget("manpath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains man page.",
+            containsLine(output, l -> l.equals("man/man1.1")));
+    }
+
+    @Test
+    public void testManPathref() {
+        buildRule.executeTarget("manpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains man page.",
+            containsLine(output, l -> l.equals("man/man2.1")));
+    }
+
+    @Test
+    public void testManPathNested() {
+        buildRule.executeTarget("manpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains man page.",
+            containsLine(output, l -> l.equals("man/man3.1")));
+    }
+
+    @Test
+    public void testManPathAttributeAndChildElement() {
+        buildRule.executeTarget("manpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains man pages "
+            + "from both attribute and child element.",
+            containsAll(output,
+                l -> l.equals("man/man4.1"),
+                l -> l.equals("man/man5.1")));
+    }
+
+    @Test
+    public void testNativeLibPath() {
+        buildRule.executeTarget("nativelibpath");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains native library.",
+            containsLine(output, l -> l.matches("lib/[^/]+\\.(dll|dylib|so)")));
+    }
+
+    @Test
+    public void testNativeLibPathref() {
+        buildRule.executeTarget("nativelibpathref");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains native library.",
+            containsLine(output, l -> l.matches("lib/[^/]+\\.(dll|dylib|so)")));
+    }
+
+    @Test
+    public void testNativeLibPathNested() {
+        buildRule.executeTarget("nativelibpath-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains native library.",
+            containsLine(output, l -> l.matches("lib/[^/]+\\.(dll|dylib|so)")));
+    }
+
+    @Test
+    public void testNativeLibPathAttributeAndChildElement() {
+        buildRule.executeTarget("nativelibpath-both");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("list", jmod.toString());
+        Assert.assertTrue("Checking that jmod contains native libraries "
+            + "from both attribute and child element.",
+            containsAll(output,
+                l -> l.matches("lib/(lib)?zip\\.(dll|dylib|so)"),
+                l -> l.matches("lib/(lib)?jvm\\.(dll|dylib|so)")));
+    }
+
+    @Test
+    public void testVersion() {
+        buildRule.executeTarget("version");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String version = buildRule.getProject().getProperty("version");
+        Assert.assertNotNull("Checking that 'version' property is set",
+            version);
+        Assert.assertFalse("Checking that 'version' property is not empty",
+            version.isEmpty());
+
+        String output = runJmod("describe", jmod.toString());
+        Assert.assertTrue("Checking that jmod has correct version.",
+            containsLine(output, l -> l.endsWith("@" + version)));
+    }
+
+    @Test
+    public void testNestedVersion() {
+        buildRule.executeTarget("version-nested");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("describe", jmod.toString());
+        Assert.assertTrue("Checking that jmod has correct version.",
+            containsLine(output, l -> l.matches(".*@1\\.0\\.1[-+]+99")));
+    }
+
+    @Test
+    public void testNestedVersionNumberOnly() {
+        buildRule.executeTarget("version-nested-number");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("describe", jmod.toString());
+        Assert.assertTrue("Checking that jmod has correct version.",
+            containsLine(output, l -> l.endsWith("@1.0.1")));
+    }
+
+    @Test
+    public void testNestedVersionNoNumber() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("version-nested-no-number");
+    }
+
+    @Test
+    public void testNestedVersionInvalidNumber() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("version-nested-invalid-number");
+    }
+
+    @Test
+    public void testNestedVersionInvalidPreRelease() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("version-nested-invalid-prerelease");
+    }
+
+    @Test
+    public void testVersionAttributeAndChildElement() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("version-both");
+    }
+
+    @Test
+    public void testMainClass() {
+        buildRule.executeTarget("mainclass");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String mainClass =
+            buildRule.getProject().getProperty("hello.main-class");
+        Assert.assertNotNull("Checking that 'main-class' property is set",
+            mainClass);
+        Assert.assertFalse("Checking that 'main-class' property is not empty",
+            mainClass.isEmpty());
+
+        String output = runJmod("describe", jmod.toString());
+
+        String mainClassPattern = "main-class\\s+" + Pattern.quote(mainClass);
+        Assert.assertTrue("Checking that jmod has correct main class.",
+            containsLine(output, l -> l.matches(mainClassPattern)));
+    }
+
+    @Test
+    public void testPlatform() {
+        buildRule.executeTarget("platform");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String platform = buildRule.getProject().getProperty("target-platform");
+        Assert.assertNotNull("Checking that 'target-platform' property is set",
+            platform);
+        Assert.assertFalse("Checking that 'target-platform' property "
+            + "is not empty", platform.isEmpty());
+
+        String output = runJmod("describe", jmod.toString());
+
+        String platformPattern = "platform\\s+" + Pattern.quote(platform);
+        Assert.assertTrue("Checking that jmod has correct main class.",
+            containsLine(output, l -> l.matches(platformPattern)));
+    }
+
+    @Test
+    public void testHashing() {
+        buildRule.executeTarget("hashing");
+
+        File jmod = new File(buildRule.getProject().getProperty("jmod"));
+        Assert.assertTrue("Checking that jmod was successfully created.",
+            jmod.exists());
+
+        String output = runJmod("describe", jmod.toString());
+
+        Assert.assertTrue("Checking that jmod has module hashes.",
+            containsLine(output, l -> l.startsWith("hashes")));
+    }
+
+    private String runJmod(final String... args) {
+        ToolProvider jmod = ToolProvider.findFirst("jmod").orElseThrow(
+            () -> new RuntimeException("jmod tool not found in JDK."));
+
+        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+
+        int exitCode;
+        try (PrintStream out = new PrintStream(stdout);
+             PrintStream err = new PrintStream(stderr)) {
+
+            exitCode = jmod.run(out, err, args);
+        }
+
+        if (exitCode != 0) {
+            throw new RuntimeException(
+                "jmod failed, output is: " + stdout + ", error is: " + stderr);
+        }
+
+        return stdout.toString();
+    }
+
+    private boolean containsLine(final String lines,
+                                 final Predicate<? super String> test) {
+        try (BufferedReader reader =
+            new BufferedReader(new StringReader(lines))) {
+
+            return reader.lines().anyMatch(test);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private boolean containsAll(final String lines,
+                                final Predicate<? super String> test1,
+                                final Predicate<? super String> test2) {
+
+        try (BufferedReader reader =
+            new BufferedReader(new StringReader(lines))) {
+
+            boolean test1Matched = false;
+            boolean test2Matched = false;
+
+            String line;
+            while ((line = reader.readLine()) != null) {
+                test1Matched |= test1.test(line);
+                test2Matched |= test2.test(line);
+            }
+
+            return test1Matched && test2Matched;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/modules/LinkTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/modules/LinkTest.java
new file mode 100644
index 0000000..bd0dfef
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/modules/LinkTest.java
@@ -0,0 +1,983 @@
+/*
+ *  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
+ *
+ *      https://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.modules;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.FileReader;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.spi.ToolProvider;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+
+/**
+ * Tests the {@link Link} task.
+ */
+public class LinkTest {
+    /*
+     * TODO:
+     * Test --order-resources (how?)
+     * Test --exclude-files (what does this actually do?)
+     * Test --endian (how?)
+     * Test --vm (how?)
+     */
+
+    @Rule
+    public final BuildFileRule buildRule = new BuildFileRule();
+
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/link.xml");
+        buildRule.executeTarget("setUp");
+    }
+
+    private static boolean isWindows() {
+        return System.getProperty("os.name").contains("Windows");
+    }
+
+    private static boolean isEarlierThan(final Instant time,
+                                         final Path path) {
+        try {
+            return Files.getLastModifiedTime(path).toInstant().isBefore(time);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private static class ImageStructure {
+        final File root;
+        final File bin;
+        final File java;
+
+        ImageStructure(final File root) {
+            this.root = root;
+
+            bin = new File(root, "bin");
+            java = new File(bin, isWindows() ? "java.exe" : "java");
+        }
+    }
+
+    private ImageStructure verifyImageBuiltNormally() {
+        ImageStructure image = new ImageStructure(
+            new File(buildRule.getProject().getProperty("image")));
+
+        Assert.assertTrue("Checking that image was successfully created.",
+            image.root.exists());
+
+        Assert.assertTrue("Checking that image has java executable.",
+            image.java.exists());
+
+        return image;
+    }
+
+    @Test
+    public void testModulepath() {
+        buildRule.executeTarget("modulepath");
+        verifyImageBuiltNormally();
+    }
+
+    @Test
+    public void testImageNotRecreatedFromStaleJmods()
+    throws IOException {
+        buildRule.executeTarget("imageNewerThanJmods");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        Instant future = Instant.now().plus(30, ChronoUnit.MINUTES);
+        try (Stream<Path> imageFiles = Files.walk(image.root.toPath())) {
+
+            Assert.assertTrue("Checking that newer image was not written "
+                + "when source files are older.",
+                imageFiles.noneMatch(i -> isEarlierThan(future, i)));
+        }
+    }
+
+    @Test
+    public void testNoModulePath() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("nomodulepath");
+    }
+
+    @Test
+    public void testNoModules() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("nomodules");
+    }
+
+    @Test
+    public void testModulePathRef() {
+        buildRule.executeTarget("modulepathref");
+        verifyImageBuiltNormally();
+    }
+
+    @Test
+    public void testNestedModulePath() {
+        buildRule.executeTarget("modulepath-nested");
+        verifyImageBuiltNormally();
+    }
+
+    @Test
+    public void testModulePathInAttributeAndNested() {
+        buildRule.executeTarget("modulepath-both");
+        verifyImageBuiltNormally();
+    }
+
+    @Test
+    public void testNestedModules()
+    throws IOException,
+           InterruptedException {
+
+        buildRule.executeTarget("modules-nested");
+
+        ImageStructure image = verifyImageBuiltNormally();
+
+        ProcessBuilder builder = new ProcessBuilder(
+            image.java.toString(),
+            buildRule.getProject().getProperty("hello.main-class"));
+        builder.inheritIO();
+        int exitCode = builder.start().waitFor();
+        Assert.assertEquals(
+            "Checking that execution of first module succeeded.", 0, exitCode);
+
+        builder.command(
+            image.java.toString(),
+            buildRule.getProject().getProperty("smile.main-class"));
+        exitCode = builder.start().waitFor();
+        Assert.assertEquals(
+            "Checking that execution of second module succeeded.", 0, exitCode);
+    }
+
+    @Test
+    public void testNestedModuleMissingName() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("modules-nested-missing-name");
+    }
+
+    @Test
+    public void testModulesInAttributeAndNested() {
+        buildRule.executeTarget("modules-both");
+        verifyImageBuiltNormally();
+    }
+
+    @Test
+    public void testObservableModules() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("observable");
+    }
+
+    @Test
+    public void testNestedObservableModules() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("observable-nested");
+    }
+
+    @Test
+    public void testNestedObservableModuleMissingName() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("observable-nested-missing-name");
+    }
+
+    @Test
+    public void testObservableModulesInAttributeAndNested() {
+        buildRule.executeTarget("observable-both");
+        verifyImageBuiltNormally();
+    }
+
+    private void verifyLaunchersExist() {
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File launcher1 =
+            new File(image.bin, isWindows() ? "Hello.bat" : "Hello");
+        Assert.assertTrue("Checking that image has 'Hello' launcher.",
+            launcher1.exists());
+
+        File launcher2 =
+            new File(image.bin, isWindows() ? "Smile.bat" : "Smile");
+        Assert.assertTrue("Checking that image has 'Smile' launcher.",
+            launcher2.exists());
+    }
+
+    @Test
+    public void testLaunchers() {
+        buildRule.executeTarget("launchers");
+        verifyLaunchersExist();
+    }
+
+    @Test
+    public void testNestedLaunchers() {
+        buildRule.executeTarget("launchers-nested");
+        verifyLaunchersExist();
+    }
+
+    @Test
+    public void testNestedLauncherMissingName() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("launchers-nested-missing-name");
+    }
+
+    @Test
+    public void testNestedLauncherMissingModule() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("launchers-nested-missing-module");
+    }
+
+    @Test
+    public void testLaunchersInAttributeAndNested() {
+        buildRule.executeTarget("launchers-both");
+        verifyLaunchersExist();
+    }
+
+    private void verifyLocales()
+    throws IOException,
+           InterruptedException {
+
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String mainClass =
+            buildRule.getProject().getProperty("localefinder.main-class");
+        Assert.assertNotNull("Checking that main-class property exists",
+            mainClass);
+
+        ProcessBuilder builder =
+            new ProcessBuilder(image.java.toString(), mainClass, "zh", "in");
+        builder.inheritIO();
+        int exitCode = builder.start().waitFor();
+
+        Assert.assertEquals("Verifying that image has access to locales "
+            + "specified during linking.", 0, exitCode);
+
+        builder.command(image.java.toString(), mainClass, "ja");
+        exitCode = builder.start().waitFor();
+
+        Assert.assertNotEquals(
+            "Verifying that image does not have access to locales "
+            + "not specified during linking.", 0, exitCode);
+    }
+
+    @Test
+    public void testLocales()
+    throws IOException,
+           InterruptedException {
+
+        buildRule.executeTarget("locales");
+        verifyLocales();
+    }
+
+    @Test
+    public void testNestedLocales()
+    throws IOException,
+           InterruptedException {
+
+        buildRule.executeTarget("locales-nested");
+        verifyLocales();
+    }
+
+    @Test
+    public void testNestedLocaleMissingName() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("locales-nested-missing-name");
+    }
+
+    @Test
+    public void testLocalesInAttributeAndNested()
+    throws IOException,
+           InterruptedException {
+
+        buildRule.executeTarget("locales-both");
+        verifyLocales();
+    }
+
+    @Test
+    public void testExcludeResources()
+    throws IOException {
+        buildRule.executeTarget("excluderesources");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String mainClass =
+            buildRule.getProject().getProperty("hello.main-class");
+        Assert.assertNotNull("Checking that main-class property exists",
+            mainClass);
+
+        ProcessBuilder builder =
+            new ProcessBuilder(image.java.toString(), mainClass,
+                "resource1.txt", "resource2.txt");
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectErrorStream(true);
+
+        Collection<String> outputLines;
+        Process process = builder.start();
+        try (BufferedReader reader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            outputLines = reader.lines().collect(Collectors.toList());
+        }
+
+        Assert.assertTrue(
+            "Checking that excluded resource is actually excluded.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource1.txt absent")));
+
+        Assert.assertTrue(
+            "Checking that resource not excluded is present.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource2.txt present")));
+    }
+
+    @Test
+    public void testNestedExcludeResources()
+    throws IOException {
+        buildRule.executeTarget("excluderesources-nested");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String mainClass =
+            buildRule.getProject().getProperty("hello.main-class");
+        Assert.assertNotNull("Checking that main-class property exists",
+            mainClass);
+
+        ProcessBuilder builder =
+            new ProcessBuilder(image.java.toString(), mainClass,
+                "resource1.txt", "resource2.txt");
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectErrorStream(true);
+
+        Collection<String> outputLines;
+        Process process = builder.start();
+        try (BufferedReader reader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            outputLines = reader.lines().collect(Collectors.toList());
+        }
+
+        Assert.assertTrue(
+            "Checking that excluded resource is actually excluded.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource1.txt absent")));
+
+        Assert.assertTrue(
+            "Checking that resource not excluded is present.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource2.txt present")));
+    }
+
+    @Test
+    public void testNestedExcludeResourcesFile()
+    throws IOException {
+        buildRule.executeTarget("excluderesources-nested-file");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String mainClass =
+            buildRule.getProject().getProperty("hello.main-class");
+        Assert.assertNotNull("Checking that main-class property exists",
+            mainClass);
+
+        ProcessBuilder builder =
+            new ProcessBuilder(image.java.toString(), mainClass,
+                "resource1.txt", "resource2.txt");
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectErrorStream(true);
+
+        Collection<String> outputLines;
+        Process process = builder.start();
+        try (BufferedReader reader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            outputLines = reader.lines().collect(Collectors.toList());
+        }
+
+        Assert.assertTrue(
+            "Checking that excluded resource is actually excluded.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource1.txt absent")));
+
+        Assert.assertTrue(
+            "Checking that resource not excluded is present.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource2.txt present")));
+    }
+
+    @Test
+    public void testNestedExcludeResourcesNoAttributes() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("excluderesources-nested-no-attr");
+    }
+
+    @Test
+    public void testNestedExcludeResourcesFileAndPattern() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("excluderesources-nested-both");
+    }
+
+    @Test
+    public void testExcludeResourcesAttributeAndNested()
+    throws IOException {
+        buildRule.executeTarget("excluderesources-both");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String mainClass =
+            buildRule.getProject().getProperty("hello.main-class");
+        Assert.assertNotNull("Checking that main-class property exists",
+            mainClass);
+
+        ProcessBuilder builder =
+            new ProcessBuilder(image.java.toString(), mainClass,
+                "resource1.txt", "resource2.txt");
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectErrorStream(true);
+
+        Collection<String> outputLines;
+        Process process = builder.start();
+        try (BufferedReader reader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            outputLines = reader.lines().collect(Collectors.toList());
+        }
+
+        Assert.assertTrue(
+            "Checking that first excluded resource is actually excluded.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource1.txt absent")));
+
+        Assert.assertTrue(
+            "Checking that second excluded resource is actually excluded.",
+            outputLines.stream().anyMatch(
+                l -> l.endsWith("resource2.txt absent")));
+    }
+
+    @Test
+    public void testExcludeFiles()
+    throws IOException {
+        buildRule.executeTarget("excludefiles");
+        verifyImageBuiltNormally();
+        // TODO: Test created image (what does --exclude-files actually do?)
+    }
+
+    @Test
+    public void testNestedExcludeFiles()
+    throws IOException {
+        buildRule.executeTarget("excludefiles-nested");
+        verifyImageBuiltNormally();
+        // TODO: Test created image (what does --exclude-files actually do?)
+    }
+
+    @Test
+    public void testNestedExcludeFilesFile()
+    throws IOException {
+        buildRule.executeTarget("excludefiles-nested-file");
+        ImageStructure image = verifyImageBuiltNormally();
+        // TODO: Test created image (what does --exclude-files actually do?)
+    }
+
+    @Test
+    public void testNestedExcludeFilesNoAttributes() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("excludefiles-nested-no-attr");
+    }
+
+    @Test
+    public void testNestedExcludeFilesFileAndPattern() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("excludefiles-nested-both");
+    }
+
+    @Test
+    public void testExcludeFilesAttributeAndNested()
+    throws IOException {
+        buildRule.executeTarget("excludefiles-both");
+        verifyImageBuiltNormally();
+        // TODO: Test created image (what does --exclude-files actually do?)
+    }
+
+    @Test
+    public void testOrdering()
+    throws IOException {
+        buildRule.executeTarget("ordering");
+        verifyImageBuiltNormally();
+        // TODO: Test resource order in created image (how?)
+    }
+
+    @Test
+    public void testNestedOrdering()
+    throws IOException {
+        buildRule.executeTarget("ordering-nested");
+        verifyImageBuiltNormally();
+        // TODO: Test resource order in created image (how?)
+    }
+
+    @Test
+    public void testNestedOrderingListFile()
+    throws IOException {
+        buildRule.executeTarget("ordering-nested-file");
+        ImageStructure image = verifyImageBuiltNormally();
+        // TODO: Test resource order in created image (how?)
+    }
+
+    @Test
+    public void testNestedOrderingNoAttributes() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("ordering-nested-no-attr");
+    }
+
+    @Test
+    public void testNestedOrderingFileAndPattern() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("ordering-nested-both");
+    }
+
+    @Test
+    public void testOrderingAttributeAndNested()
+    throws IOException {
+        buildRule.executeTarget("ordering-both");
+        verifyImageBuiltNormally();
+        // TODO: Test resource order in created image (how?)
+    }
+
+    @Test
+    public void testIncludeHeaders() {
+        buildRule.executeTarget("includeheaders");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File[] headers = new File(image.root, "include").listFiles();
+        Assert.assertTrue("Checking that include files were omitted.",
+            headers == null || headers.length == 0);
+    }
+
+    @Test
+    public void testIncludeManPages() {
+        buildRule.executeTarget("includemanpages");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File[] manPages = new File(image.root, "man").listFiles();
+        Assert.assertTrue("Checking that man pages were omitted.",
+            manPages == null || manPages.length == 0);
+    }
+
+    @Test
+    public void testIncludeNativeCommands() {
+        buildRule.executeTarget("includenativecommands");
+        ImageStructure image = new ImageStructure(
+            new File(buildRule.getProject().getProperty("image")));
+
+        Assert.assertTrue("Checking that image was successfully created.",
+            image.root.exists());
+
+        Assert.assertFalse(
+            "Checking that image was stripped of java executable.",
+            image.java.exists());
+    }
+
+    private long totalSizeOf(final Path path)
+    throws IOException {
+        if (Files.isDirectory(path)) {
+            long size = 0;
+            try (DirectoryStream<Path> children = Files.newDirectoryStream(path)) {
+                for (Path child : children) {
+                    size += totalSizeOf(child);
+                }
+            }
+            return size;
+        }
+
+        if (Files.isRegularFile(path)) {
+            return Files.size(path);
+        }
+
+        return 0;
+    }
+
+    @Test
+    public void testCompression()
+    throws IOException {
+        buildRule.executeTarget("compression");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File compressedImageRoot =
+            new File(buildRule.getProject().getProperty("compressed-image"));
+
+        long size = totalSizeOf(image.root.toPath());
+        long compressedSize = totalSizeOf(compressedImageRoot.toPath());
+
+        Assert.assertTrue("Checking that compression resulted in smaller image.",
+            compressedSize < size);
+    }
+
+    @Test
+    public void testNestedCompression()
+    throws IOException {
+        buildRule.executeTarget("compression-nested");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File compressedImageRoot =
+            new File(buildRule.getProject().getProperty("compressed-image"));
+
+        long size = totalSizeOf(image.root.toPath());
+        long compressedSize = totalSizeOf(compressedImageRoot.toPath());
+
+        Assert.assertTrue("Checking that compression resulted in smaller image.",
+            compressedSize < size);
+    }
+
+    @Test
+    public void testNestedCompressionNoAttributes() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("compression-nested-no-attr");
+    }
+
+    @Test
+    public void testNestedCompressionAttributeAndNested() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("compression-both");
+    }
+
+    @Test
+    public void testEndian() {
+        buildRule.executeTarget("endian");
+        verifyImageBuiltNormally();
+        // TODO: How can we test the created image?  Which files does --endian
+        // affect?
+    }
+
+    @Test
+    public void testVMType() {
+        buildRule.executeTarget("vm");
+        verifyImageBuiltNormally();
+        // TODO: How can we test the created image?  Which files does --vm
+        // affect?
+    }
+
+    @Test
+    public void testReleaseInfoFile()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-file");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        try (BufferedReader reader =
+            Files.newBufferedReader(release.toPath())) {
+
+            Assert.assertTrue("Checking for 'test=true' in image release info.",
+                reader.lines().anyMatch(l -> l.equals("test=true")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoDelete()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-delete");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        try (BufferedReader reader =
+            Files.newBufferedReader(release.toPath())) {
+
+            Assert.assertFalse("Checking that 'test' was deleted "
+                + "from image release info.",
+                reader.lines().anyMatch(l -> l.startsWith("test=")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoNestedDelete()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-nested-delete");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        try (BufferedReader reader =
+            Files.newBufferedReader(release.toPath())) {
+
+            Assert.assertFalse("Checking that 'test' was deleted "
+                + "from image release info.",
+                reader.lines().anyMatch(l -> l.startsWith("test=")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoNestedDeleteNoKey() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("releaseinfo-nested-delete-no-key");
+    }
+
+    @Test
+    public void testReleaseInfoDeleteAttributeAndNested()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-nested-delete-both");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        try (BufferedReader reader =
+            Files.newBufferedReader(release.toPath())) {
+
+            Assert.assertTrue(
+                "Checking that 'test' and 'foo' were deleted "
+                + "from image release info.",
+                reader.lines().noneMatch(l ->
+                    l.startsWith("test=") || l.startsWith("foo=")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoAddFile()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-add-file");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        try (BufferedReader reader = new BufferedReader(
+            new FileReader(release))) {
+
+            Assert.assertTrue("Checking that 'test=s\u00ed' was added "
+                + "to image release info.",
+                reader.lines().anyMatch(l -> l.equals("test=s\u00ed")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoAddFileWithCharset()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-add-file-charset");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        // Using FileReader here since 'release' file is in platform's charset.
+        try (BufferedReader reader = new BufferedReader(
+            new FileReader(release))) {
+
+            Assert.assertTrue("Checking that 'test=s\u00ed' was added "
+                + "to image release info.",
+                reader.lines().anyMatch(l -> l.equals("test=s\u00ed")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoAddKeyAndValue()
+    throws IOException {
+        buildRule.executeTarget("releaseinfo-add-key");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        File release = new File(image.root, "release");
+        try (BufferedReader reader =
+            Files.newBufferedReader(release.toPath())) {
+
+            Assert.assertTrue("Checking that 'test=true' was added "
+                + "to image release info.",
+                reader.lines().anyMatch(l -> l.equals("test=true")));
+        }
+    }
+
+    @Test
+    public void testReleaseInfoAddNoValue() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("releaseinfo-add-no-value");
+    }
+
+    @Test
+    public void testReleaseInfoAddNoKey() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("releaseinfo-add-no-key");
+    }
+
+    @Test
+    public void testReleaseInfoAddFileAndKey() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("releaseinfo-add-file-and-key");
+    }
+
+    @Test
+    public void testReleaseInfoAddFileAndValue() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("releaseinfo-add-file-and-value");
+    }
+
+    @Test
+    public void testDebugStripping()
+    throws IOException,
+           InterruptedException {
+
+        buildRule.executeTarget("debug");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        ProcessBuilder builder = new ProcessBuilder(
+            image.java.toString(),
+            buildRule.getProject().getProperty("thrower.main-class"));
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectErrorStream(true);
+
+        Process process = builder.start();
+        try (BufferedReader linesReader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            Assert.assertTrue(
+                "Checking that stack trace contains no debug information.",
+                linesReader.lines().noneMatch(
+                    l -> l.matches(".*\\([^)]*:[0-9]+\\)")));
+        }
+        process.waitFor();
+    }
+
+    @Test
+    public void testDeduplicationOfLicenses() {
+        buildRule.executeTarget("dedup");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String helloModuleName =
+            buildRule.getProject().getProperty("hello.mod");
+        String smileModuleName =
+            buildRule.getProject().getProperty("smile.mod");
+
+        Assert.assertNotNull("Checking that 'hello.mod' property was set.",
+            helloModuleName);
+        Assert.assertNotNull("Checking that 'smile.mod' property was set.",
+            smileModuleName);
+
+        Assume.assumeFalse("Checking that this operating system"
+            + " supports symbolic links as a means of license de-duplication.",
+            System.getProperty("os.name").contains("Windows"));
+
+        Path legal = image.root.toPath().resolve("legal");
+
+        Path[] licenses = {
+            legal.resolve(helloModuleName).resolve("USELESSLICENSE"),
+            legal.resolve(smileModuleName).resolve("USELESSLICENSE"),
+        };
+
+        int nonLinkCount = 0;
+        for (Path license : licenses) {
+            if (!Files.isSymbolicLink(license)) {
+                nonLinkCount++;
+            }
+        }
+
+        Assert.assertEquals(
+            "Checking that USELESSLICENSE only exists once in image "
+            + "and all other instances are links to it.",
+            1, nonLinkCount);
+    }
+
+    @Test
+    public void testIgnoreSigning() {
+        buildRule.executeTarget("ignoresigning");
+        verifyImageBuiltNormally();
+    }
+
+    /**
+     * Should fail due to jlink rejecting identically named files whose
+     * contents are different.
+     */
+    @Test
+    public void testDeduplicationOfInconsistentLicenses() {
+        expected.expect(BuildException.class);
+        buildRule.executeTarget("dedup-identical");
+    }
+
+    @Test
+    public void testBindingOfServices()
+    throws IOException,
+           InterruptedException {
+        buildRule.executeTarget("bindservices");
+        ImageStructure image = verifyImageBuiltNormally();
+
+        String mainClass = buildRule.getProject().getProperty("inc.main-class");
+
+        ProcessBuilder builder = new ProcessBuilder(
+            image.java.toString(), mainClass);
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+        Process process = builder.start();
+        try (BufferedReader linesReader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            Assert.assertEquals(
+                "Checking that bindServices=false results in no providers in image.",
+                0, linesReader.lines().count());
+        }
+        process.waitFor();
+
+        image = new ImageStructure(
+            new File(buildRule.getProject().getProperty("image2")));
+
+        Assert.assertTrue("Checking that image2 was successfully created.",
+            image.root.exists());
+        Assert.assertTrue("Checking that image2 has java executable.",
+            image.java.exists());
+
+        builder = new ProcessBuilder(image.java.toString(), mainClass);
+        builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
+        builder.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+        process = builder.start();
+        try (BufferedReader linesReader = new BufferedReader(
+            new InputStreamReader(process.getInputStream()))) {
+
+            Assert.assertEquals(
+                "Checking that bindServices=true results in image with provider.",
+                5, linesReader.lines().count());
+        }
+        process.waitFor();
+    }
+
+    private String runJlink(final String... args) {
+        ToolProvider jlink = ToolProvider.findFirst("jlink").orElseThrow(
+            () -> new RuntimeException("jlink tool not found in JDK."));
+
+        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+
+        int exitCode;
+        try (PrintStream out = new PrintStream(stdout);
+             PrintStream err = new PrintStream(stderr)) {
+
+            exitCode = jlink.run(out, err, args);
+        }
+
+        if (exitCode != 0) {
+            throw new RuntimeException(
+                "jlink failed, output is: " + stdout + ", error is: " + stderr);
+        }
+
+        return stdout.toString();
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ANTLRTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ANTLRTest.java
index f57e418..fea51f6 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ANTLRTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ANTLRTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,10 +28,10 @@
 import java.io.File;
 import java.io.FilenameFilter;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.apache.tools.ant.AntAssert.assertNotContains;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
 
 /**
  * If you want to run tests, it is highly recommended
@@ -46,35 +46,31 @@
  */
 public class ANTLRTest {
 
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/antlr/";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "antlr.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/antlr/antlr.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to missing required argument, target
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
-            buildRule.executeTarget("test1");
-            fail("required argument, target, missing");
-        } catch (BuildException ex) {
-            //TODO should check exception message
-        }
+        buildRule.executeTarget("test1");
+        // TODO Check exception message
     }
 
-    @Test
+    /**
+     * Expected failure due to invalid output directory
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("Invalid output directory");
-        } catch (BuildException ex) {
-            //TODO should check exception message
-        }
-    }
+        buildRule.executeTarget("test2");
+        // TODO Check exception message
+     }
 
     @Test
     public void test3() {
@@ -86,16 +82,14 @@
         buildRule.executeTarget("test4");
     }
 
-    @Test
+    /**
+     * should print "panic: Cannot find importVocab file 'JavaTokenTypes.txt'"
+     * since it needs to run java.g first before java.tree.g
+     */
+    @Test(expected = BuildException.class)
     public void test5() {
-        // should print "panic: Cannot find importVocab file 'JavaTokenTypes.txt'"
-        // since it needs to run java.g first before java.tree.g
-        try {
-            buildRule.executeTarget("test5");
-            fail("ANTLR returned: 1");
-        } catch (BuildException ex) {
-            //TODO should check exception message
-        }
+        buildRule.executeTarget("test5");
+        // TODO Check exception message
     }
 
     @Test
@@ -103,27 +97,22 @@
         buildRule.executeTarget("test6");
     }
 
-    @Test
+    /**
+     * Expected failure due to inability to determine generated class
+     */
+    @Test(expected = BuildException.class)
     public void test7() {
-        try {
-            buildRule.executeTarget("test7");
-            fail("Unable to determine generated class");
-        } catch (BuildException ex) {
-            //TODO should check exception message
-        }
+        buildRule.executeTarget("test7");
+        // TODO Check exception message
     }
 
     /**
-     * This is a negative test for the super grammar (glib) option.
+     * Expected failure due to invalid super grammar (glib) option.
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void test8() {
-        try {
-            buildRule.executeTarget("test8");
-            fail("Invalid super grammar file");
-        } catch (BuildException ex) {
-            //TODO should check exception message
-        }
+        buildRule.executeTarget("test8");
+        // TODO Check exception message
     }
 
     /**
@@ -143,8 +132,7 @@
     public void test10() {
         buildRule.executeTarget("test10");
         File outputDirectory = new File(buildRule.getProject().getProperty("output"));
-        String[] calcFiles = outputDirectory.list(new HTMLFilter());
-        assertTrue(calcFiles.length > 0);
+        assertNotEquals(outputDirectory.list(new HTMLFilter()).length, 0);
     }
 
     /**
@@ -178,32 +166,32 @@
     @Test
     public void testNoRecompile() {
         buildRule.executeTarget("test9");
-        assertNotContains("Skipped grammar file.", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), not(containsString("Skipped grammar file.")));
         buildRule.executeTarget("noRecompile");
-        assertContains("Skipped grammar file.", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), containsString("Skipped grammar file."));
     }
 
     @Test
     public void testNormalRecompile() {
         buildRule.executeTarget("test9");
-        assertNotContains("Skipped grammar file.", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), not(containsString("Skipped grammar file.")));
 
         FileUtilities.rollbackTimestamps(buildRule.getOutputDir(), 5);
 
         buildRule.executeTarget("normalRecompile");
-        assertNotContains("Skipped grammar file.", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), not(containsString("Skipped grammar file.")));
     }
 
     @Test
     // Bugzilla Report 12961
     public void testSupergrammarChangeRecompile() {
         buildRule.executeTarget("test9");
-        assertNotContains("Skipped grammar file.", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), not(containsString("Skipped grammar file.")));
 
         FileUtilities.rollbackTimestamps(buildRule.getOutputDir(), 5);
 
         buildRule.executeTarget("supergrammarChangeRecompile");
-        assertNotContains("Skipped grammar file.", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), not(containsString("Skipped grammar file.")));
 
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/AbstractXSLTLiaisonTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/AbstractXSLTLiaisonTest.java
index f55c3f9..920a104 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/AbstractXSLTLiaisonTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/AbstractXSLTLiaisonTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/BeanShellScriptTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/BeanShellScriptTest.java
index 8802022..3383a91 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/BeanShellScriptTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/BeanShellScriptTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java
index 9d34760..b2c3054 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/EchoPropertiesTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,11 +18,12 @@
 
 package org.apache.tools.ant.taskdefs.optional;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 import java.io.BufferedInputStream;
@@ -36,11 +37,13 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests the EchoProperties task.
@@ -50,7 +53,6 @@
  */
 public class EchoPropertiesTest {
 
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
     private static final String GOOD_OUTFILE = "test.properties";
     private static final String GOOD_OUTFILE_XML = "test.xml";
     private static final String PREFIX_OUTFILE = "test-prefix.properties";
@@ -59,9 +61,12 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "echoproperties.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/echoproperties.xml");
         buildRule.getProject().setProperty("test.property", TEST_VALUE);
     }
 
@@ -73,45 +78,39 @@
     @Test
     public void testEchoToLog() {
         buildRule.executeTarget("testEchoToLog");
-        assertContains("test.property=" + TEST_VALUE, buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("test.property=" + TEST_VALUE));
     }
 
     @Test
     public void testEchoWithEmptyPrefixToLog() {
         buildRule.executeTarget("testEchoWithEmptyPrefixToLog");
-        assertContains("test.property=" + TEST_VALUE, buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("test.property=" + TEST_VALUE));
     }
 
     @Test
     public void testReadBadFile() {
-        try {
-            buildRule.executeTarget("testReadBadFile");
-            fail("BuildException should have been thrown on bad file");
-        } catch (BuildException ex) {
-            assertContains("srcfile is a directory", "srcfile is a directory!", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("srcfile is a directory!");
+        buildRule.executeTarget("testReadBadFile");
     }
 
     @Test
     public void testReadBadFileNoFail() {
         buildRule.executeTarget("testReadBadFileNoFail");
-        assertContains("srcfile is a directory!", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("srcfile is a directory!"));
     }
 
     @Test
     public void testEchoToBadFile() {
-        try {
-            buildRule.executeTarget("testEchoToBadFile");
-            fail("BuildException should have been thrown on destination file being a directory");
-        } catch (BuildException ex) {
-            assertContains("destfile is a directory", "destfile is a directory!", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("destfile is a directory!");
+        buildRule.executeTarget("testEchoToBadFile");
     }
 
     @Test
     public void testEchoToBadFileNoFail() {
         buildRule.executeTarget("testEchoToBadFileNoFail");
-        assertContains("destfile is a directory!", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("destfile is a directory!"));
     }
 
     @Test
@@ -125,27 +124,10 @@
         buildRule.executeTarget("testEchoToGoodFileXml");
 
         // read in the file
-        File f = createRelativeFile(GOOD_OUTFILE_XML);
-        FileReader fr = new FileReader(f);
-        BufferedReader br = new BufferedReader(fr);
-        try {
-            String read = null;
-            while ((read = br.readLine()) != null) {
-                if (read.contains("<property name=\"test.property\" value=\"" + TEST_VALUE + "\" />")) {
-                    // found the property we set - it's good.
-                    return;
-                }
-            }
-            fail("did not encounter set property in generated file.");
-        } finally {
-            try {
-                fr.close();
-            } catch (IOException e) {
-            }
-            try {
-                br.close();
-            } catch (IOException e) {
-            }
+        File f = new File(buildRule.getProject().getBaseDir(), GOOD_OUTFILE_XML);
+        try (BufferedReader br = new BufferedReader(new FileReader(f))) {
+            assertTrue("did not encounter set property in generated file.", br.lines().anyMatch(line
+                    -> line.contains("<property name=\"test.property\" value=\"" + TEST_VALUE + "\" />")));
         }
     }
 
@@ -182,30 +164,32 @@
     }
 
     @Test
-    public void testWithPrefixAndRegex() throws Exception {
-        try {
-            buildRule.executeTarget("testWithPrefixAndRegex");
-            fail("BuildException should have been thrown on Prefix and RegEx being set");
-        } catch (BuildException ex) {
-            assertEquals("The target must fail with prefix and regex attributes set",
-                    "Please specify either prefix or regex, but not both", ex.getMessage());
-        }
+    public void testWithPrefixAndRegex() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Please specify either prefix or regex, but not both");
+        buildRule.executeTarget("testWithPrefixAndRegex");
     }
 
     @Test
-    public void testWithEmptyPrefixAndRegex() throws Exception {
+    public void testWithEmptyPrefixAndRegex() {
         buildRule.executeTarget("testEchoWithEmptyPrefixToLog");
-        assertContains("test.property=" + TEST_VALUE, buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("test.property=" + TEST_VALUE));
     }
 
     @Test
-    public void testWithRegex() throws Exception {
+    public void testWithRegex() {
         assumeTrue("Test skipped because no regexp matcher is present.",
                 RegexpMatcherFactory.regexpMatcherPresent(buildRule.getProject()));
         buildRule.executeTarget("testWithRegex");
         // the following line has been changed from checking ant.home to ant.version
         // so the test will still work when run outside of an Ant script
-        assertContains("ant.version=", buildRule.getFullLog());
+        assertThat(buildRule.getFullLog(), containsString(MagicNames.ANT_VERSION + "="));
+    }
+
+    @Test
+    public void testLocalPropertyset() {
+        buildRule.executeTarget("testEchoLocalPropertyset");
+        assertThat(buildRule.getLog(), containsString("loc=foo"));
     }
 
     private void testEchoPrefixVarious(String target) throws Exception {
@@ -219,42 +203,21 @@
 
     protected Properties loadPropFile(String relativeFilename)
             throws IOException {
-        File f = createRelativeFile(relativeFilename);
+        assertNotNull("Null property file name", relativeFilename);
+        File f = new File(buildRule.getProject().getBaseDir(), relativeFilename);
+        assertTrue("Did not create " + f.getAbsolutePath(), f.exists());
         Properties props = new Properties();
-        InputStream in = null;
-        try  {
-            in = new BufferedInputStream(new FileInputStream(f));
+        try (InputStream in = new BufferedInputStream(new FileInputStream(f))) {
             props.load(in);
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                }
-            }
         }
         return props;
     }
 
     protected void assertGoodFile() throws Exception {
-        File f = createRelativeFile(GOOD_OUTFILE);
-        assertTrue("Did not create " + f.getAbsolutePath(),
-            f.exists());
         Properties props = loadPropFile(GOOD_OUTFILE);
         props.list(System.out);
         assertEquals("test property not found ",
                      TEST_VALUE, props.getProperty("test.property"));
     }
 
-    protected String toAbsolute(String filename) {
-        return createRelativeFile(filename).getAbsolutePath();
-    }
-
-    protected File createRelativeFile(String filename) {
-        if (filename.equals(".")) {
-            return buildRule.getProject().getBaseDir();
-        }
-        // else
-        return new File(buildRule.getProject().getBaseDir(), filename);
-    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JavahTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JavahTest.java
index 32ec8bb..3eba0da 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JavahTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JavahTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,7 +19,6 @@
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.util.JavaEnvUtils;
-import org.junit.Assume;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -28,17 +27,16 @@
 import java.io.File;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
 
 public class JavahTest {
 
-    private static final String BUILD_XML = "src/etc/testcases/taskdefs/optional/javah/build.xml";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(BUILD_XML);
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/javah/build.xml");
     }
 
     @After
@@ -48,7 +46,7 @@
 
     @Test
     public void testSimpleCompile() {
-        Assume.assumeFalse(JavaEnvUtils.isAtLeastJavaVersion("10"));
+        assumeFalse(JavaEnvUtils.isAtLeastJavaVersion("10"));
         buildRule.executeTarget("simple-compile");
         assertTrue(new File(buildRule.getProject().getProperty("output"), "org_example_Foo.h")
                 .exists());
@@ -56,8 +54,9 @@
 
     @Test
     public void testCompileFileset() {
-        Assume.assumeFalse(JavaEnvUtils.isAtLeastJavaVersion("10"));
+        assumeFalse(JavaEnvUtils.isAtLeastJavaVersion("10"));
         buildRule.executeTarget("test-fileset");
-        assertTrue(new File(buildRule.getProject().getProperty("output"), "org_example_Foo.h").exists());
+        assertTrue(new File(buildRule.getProject().getProperty("output"), "org_example_Foo.h")
+                .exists());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JspcTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JspcTest.java
index 3955f57..089403c 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JspcTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/JspcTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,10 +30,13 @@
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Tests the Jspc task.
@@ -44,14 +47,15 @@
  */
 public class JspcTest {
 
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "jspc.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/jspc.xml");
      }
 
     @Test
@@ -60,12 +64,12 @@
     }
 
     @Test
-    public void testUriroot() throws Exception {
+    public void testUriroot() {
         executeJspCompile("testUriroot", "uriroot_jsp.java");
     }
 
     @Test
-    public void testXml() throws Exception {
+    public void testXml() {
         executeJspCompile("testXml", "xml_jsp.java");
     }
 
@@ -73,7 +77,7 @@
      * try a keyword in a file
      */
     @Test
-    public void testKeyword() throws Exception {
+    public void testKeyword() {
         executeJspCompile("testKeyword", "default_jsp.java");
     }
 
@@ -81,23 +85,20 @@
      * what happens to 1nvalid-classname
      */
     @Test
-    public void testInvalidClassname() throws Exception {
+    public void testInvalidClassname() {
         executeJspCompile("testInvalidClassname",
                 "_1nvalid_0002dclassname_jsp.java");
     }
 
     @Test
-    public void testNoTld() throws Exception {
-        try {
-            buildRule.executeTarget("testNoTld");
-            fail("Not found");
-        } catch (BuildException ex) {
-            assertEquals("Java returned: 9", ex.getMessage());
-        }
+    public void testNoTld() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Java returned: 9");
+        buildRule.executeTarget("testNoTld");
     }
 
     @Test
-    public void testNotAJspFile()  throws Exception {
+    public void testNotAJspFile() {
         buildRule.executeTarget("testNotAJspFile");
     }
 
@@ -107,7 +108,7 @@
      */
     @Ignore("picks up on the missing_tld file, and incorrectly bails")
     @Test
-    public void testWebapp()  throws Exception {
+    public void testWebapp() {
         buildRule.executeTarget("testWebapp");
     }
 
@@ -130,7 +131,7 @@
     protected void assertJavaFileCreated(String filename) {
         File file = getOutputFile(filename);
         assertTrue("file " + filename + " not found", file.exists());
-        assertTrue("file " + filename + " is empty", file.length() > 0);
+        assertNotEquals("file " + filename + " is empty", 0, file.length());
     }
 
     /**
@@ -151,10 +152,10 @@
         JspCompilerAdapter adapter =
                 JspCompilerAdapterFactory.getCompiler("jasper", null, null);
         JspMangler mangler = adapter.createMangler();
-        assertTrue(mangler instanceof JspNameMangler);
+        assertThat(mangler, instanceOf(JspNameMangler.class));
         adapter = JspCompilerAdapterFactory.getCompiler("jasper41", null, null);
         mangler = adapter.createMangler();
-        assertTrue(mangler instanceof Jasper41Mangler);
+        assertThat(mangler, instanceOf(Jasper41Mangler.class));
     }
 
     @Test
@@ -181,9 +182,8 @@
      */
     protected void assertMapped(JspMangler mangler, String filename, String classname) {
         String mappedname = mangler.mapJspToJavaName(new File(filename));
-        assertTrue(filename + " should have mapped to " + classname
-                    + " but instead mapped to " + mappedname,
-                    classname.equals(mappedname));
+        assertEquals(filename + " should have mapped to " + classname
+                + " but instead mapped to " + mappedname, classname, mappedname);
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/Native2AsciiTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/Native2AsciiTest.java
index 0ea5d9b..0a839c3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/Native2AsciiTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/Native2AsciiTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,15 +32,12 @@
 
 public class Native2AsciiTest {
 
-    private static final String BUILD_XML =
-        "src/etc/testcases/taskdefs/optional/native2ascii/build.xml";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(BUILD_XML);
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/native2ascii/build.xml");
     }
 
     @After
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java
index fa6cd86..c116990 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,11 +21,11 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.time.LocalDate;
 import java.util.Properties;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -58,15 +58,14 @@
                 valueDoesNotGetOverwrittenPropertyFile);
     }
 
-
     @Test
     public void testNonExistingFile() {
-        PropertyFile props = new PropertyFile();
-        props.setProject(buildRule.getProject());
+        PropertyFile pf = new PropertyFile();
+        pf.setProject(buildRule.getProject());
         File file = new File("this-file-does-not-exist.properties");
-        props.setFile(file);
+        pf.setFile(file);
         assertFalse("Properties file exists before test.", file.exists());
-        props.execute();
+        pf.execute();
         assertTrue("Properties file does not exist after test.", file.exists());
         file.delete();
     }
@@ -81,9 +80,9 @@
         assertEquals(FNAME, beforeUpdate.getProperty(FNAME_KEY));
         assertEquals(LNAME, beforeUpdate.getProperty(LNAME_KEY));
         assertEquals(EMAIL, beforeUpdate.getProperty(EMAIL_KEY));
-        assertEquals(null, beforeUpdate.getProperty(PHONE_KEY));
-        assertEquals(null, beforeUpdate.getProperty(AGE_KEY));
-        assertEquals(null, beforeUpdate.getProperty(DATE_KEY));
+        assertNull(beforeUpdate.getProperty(PHONE_KEY));
+        assertNull(beforeUpdate.getProperty(AGE_KEY));
+        assertNull(beforeUpdate.getProperty(DATE_KEY));
 
         // ask ant to update the properties...
         buildRule.executeTarget("update-existing-properties");
@@ -115,7 +114,7 @@
     }
 
     @Test
-    public void testExerciseDefaultAndIncrement() throws Exception {
+    public void testExerciseDefaultAndIncrement() {
         buildRule.executeTarget("exercise");
         assertEquals("3", buildRule.getProject().getProperty("int.with.default"));
         assertEquals("1", buildRule.getProject().getProperty("int.without.default"));
@@ -136,29 +135,31 @@
         assertEquals("5", buildRule.getProject().getProperty("foo"));
     }
 
-
     @Test
-    @Ignore("Previously commented out")
     public void testDirect() throws Exception {
         PropertyFile pf = new PropertyFile();
         pf.setProject(buildRule.getProject());
-        pf.setFile(new File(System.getProperty("root"), testPropsFilePath));
-        PropertyFile.Entry entry = pf.createEntry();
+        pf.setFile(new File(buildRule.getOutputDir(), testPropsFilePath));
 
+        long delta = 123L;
+        PropertyFile.Entry entry = pf.createEntry();
         entry.setKey("date");
-        entry.setValue("123");
+        entry.setValue(String.valueOf(delta));
+
         PropertyFile.Entry.Type type = new PropertyFile.Entry.Type();
         type.setValue("date");
         entry.setType(type);
-
         entry.setPattern("yyyy/MM/dd");
 
         PropertyFile.Entry.Operation operation = new PropertyFile.Entry.Operation();
         operation.setValue("+");
+        entry.setOperation(operation);
         pf.execute();
 
         Properties props = getTestProperties();
-        assertEquals("yeehaw", props.getProperty("date"));
+        LocalDate currentDate = LocalDate.now().plusDays(delta);
+        assertEquals(String.format("%d/%02d/%02d", currentDate.getYear(), currentDate.getMonthValue(),
+                currentDate.getDayOfMonth()), props.getProperty("date"));
     }
 
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PvcsTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PvcsTest.java
index 29b2685..62942ee 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PvcsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/PvcsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,8 +24,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 public class PvcsTest {
 
     @Rule
@@ -36,14 +34,12 @@
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/pvcs.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to missing argument "repository"
+     */
+    @Test(expected = BuildException.class)
     public void test1() {
-        try {
             buildRule.executeTarget("test1");
-            fail("Required argument repository not specified");
-        } catch (BuildException ex) {
-            //TODO check exception message
-        }
     }
 
     @Test
@@ -66,14 +62,12 @@
         buildRule.executeTarget("test5");
     }
 
-    @Test
+    /**
+     * Expected failure due to nonexistent directory structure
+     */
+    @Test(expected = BuildException.class)
     public void test6() {
-        try {
-            buildRule.executeTarget("test6");
-            fail("Failed executing: /never/heard/of/a/directory/structure/like/this/pcli lvf -z " +
-                    "-aw -pr//ct4serv2/pvcs/monitor /. Exception: /never/heard/of/a/directory/structure/like/this/pcli: not found");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test6");
+        //TODO assert exception message
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ReplaceRegExpTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ReplaceRegExpTest.java
index b7ab748..4cd1f74 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ReplaceRegExpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ReplaceRegExpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,28 +39,21 @@
  *
  */
 public class ReplaceRegExpTest {
-    private static final String PROJECT_PATH = "src/etc/testcases/taskdefs/optional";
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(PROJECT_PATH + "/replaceregexp.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/replaceregexp.xml");
     }
 
     @Test
     public void testReplace() throws IOException {
         Properties original = new Properties();
-        FileInputStream propsFile = null;
-        try {
-            propsFile = new FileInputStream(new File(buildRule.getProject().getBaseDir() + "/replaceregexp.properties"));
+        try (FileInputStream propsFile = new FileInputStream(new File(
+                buildRule.getProject().getBaseDir() + "/replaceregexp.properties"))) {
             original.load(propsFile);
-        } finally {
-            if (propsFile != null) {
-                propsFile.close();
-                propsFile = null;
-            }
         }
 
         assertEquals("Def", original.get("OldAbc"));
@@ -68,13 +61,9 @@
         buildRule.executeTarget("testReplace");
 
         Properties after = new Properties();
-        try {
-            propsFile = new FileInputStream(new File(buildRule.getOutputDir(), "test.properties"));
+        try (FileInputStream propsFile = new FileInputStream(new File(buildRule.getOutputDir(),
+                "test.properties"))) {
             after.load(propsFile);
-        } finally {
-            if (propsFile != null) {
-                propsFile.close();
-            }
         }
 
         assertNull(after.get("OldAbc"));
@@ -108,25 +97,25 @@
     }
 
     @Test
-    public void testNoPreserveLastModified() throws Exception {
+    public void testNoPreserveLastModified() {
         buildRule.executeTarget("lastModifiedSetup");
         File testFile = new File(buildRule.getOutputDir(), "test.txt");
         assumeTrue(testFile.setLastModified(testFile.lastModified()
-                - (FileUtils.getFileUtils().getFileTimestampGranularity() * 3)));
+                - FileUtils.getFileUtils().getFileTimestampGranularity() * 3));
         long ts1 = testFile.lastModified();
         buildRule.executeTarget("testNoPreserve");
         assertTrue(ts1 < testFile.lastModified());
     }
 
     @Test
-    public void testPreserveLastModified() throws Exception {
+    public void testPreserveLastModified() {
         buildRule.executeTarget("lastModifiedSetup");
         File testFile = new File(buildRule.getOutputDir(), "test.txt");
         assumeTrue(testFile.setLastModified(testFile.lastModified()
-                - (FileUtils.getFileUtils().getFileTimestampGranularity() * 3)));
+                - FileUtils.getFileUtils().getFileTimestampGranularity() * 3));
         long ts1 = testFile.lastModified();
         buildRule.executeTarget("testPreserve");
         assertEquals(ts1, testFile.lastModified());
     }
 
-}// ReplaceRegExpTest
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoReferenceTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoReferenceTest.java
index 41803de..0a1c654 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoReferenceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoReferenceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -34,8 +34,7 @@
 
     @Before
     public void setUp() {
-        buildRule.configureProject(
-                "src/etc/testcases/taskdefs/optional/script_reference.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/script_reference.xml");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoScriptTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoScriptTest.java
index 3ca428e..693b4bc 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoScriptTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RhinoScriptTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,12 @@
  */
 package org.apache.tools.ant.taskdefs.optional;
 
+import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertTrue;
 
@@ -34,6 +36,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/script.xml");
@@ -64,4 +69,17 @@
         assertTrue(index > -1);
     }
 
+    @Test
+    public void testUseSrcAndEncoding() {
+        buildRule.getProject().setProperty("useSrcAndEncoding.reader.encoding", "UTF-8");
+        buildRule.executeTarget("useSrcAndEncoding");
+    }
+
+    @Test
+    public void testUseSrcAndEncodingFailure() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("expected <eacute [\u00e9]> but was <eacute [\u00c3\u00a9]>");
+        buildRule.getProject().setProperty("useSrcAndEncoding.reader.encoding", "ISO-8859-1");
+        buildRule.executeTarget("useSrcAndEncoding");
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RpmTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RpmTest.java
index b557f44..7291a9e 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RpmTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/RpmTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,29 +23,27 @@
 import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
 import org.apache.tools.ant.types.Commandline;
 
+import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.fail;
-import static org.apache.tools.ant.AntAssert.assertContains;
+import org.junit.rules.ExpectedException;
 
 public class RpmTest {
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Test
-    public void testShouldThrowExceptionWhenRpmFails() throws Exception {
+    public void testShouldThrowExceptionWhenRpmFails() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("' failed with exit code 2");
         Rpm rpm = new MyRpm();
         rpm.setProject(new Project());
         rpm.setFailOnError(true);
-        // execute
-        try {
-            rpm.execute();
-            fail("should have thrown a build exception");
-        } catch (BuildException ex) {
-            assertContains("' failed with exit code 2", ex.getMessage());
-        }
+        rpm.execute();
     }
 
     @Test
-    public void testShouldNotThrowExceptionWhenRpmFails() throws Exception {
+    public void testShouldNotThrowExceptionWhenRpmFails() {
         Rpm rpm = new MyRpm();
         rpm.execute();
     }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/SchemaValidateTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/SchemaValidateTest.java
index 643aa6e..79dfefb 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/SchemaValidateTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/SchemaValidateTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,14 +17,12 @@
  */
 package org.apache.tools.ant.taskdefs.optional;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Test schema validation
@@ -32,24 +30,22 @@
 
 public class SchemaValidateTest {
 
-    /**
-     * where tasks run
-     */
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "schemavalidate.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/schemavalidate.xml");
     }
 
     /**
      * test with no namespace
      */
     @Test
-    public void testNoNamespace() throws Exception {
+    public void testNoNamespace() {
         buildRule.executeTarget("testNoNamespace");
     }
 
@@ -57,71 +53,52 @@
      * add namespace awareness.
      */
     @Test
-    public void testNSMapping() throws Exception {
+    public void testNSMapping() {
         buildRule.executeTarget("testNSMapping");
     }
 
     @Test
-    public void testNoEmptySchemaNamespace() throws Exception {
-        try {
-            buildRule.executeTarget("testNoEmptySchemaNamespace");
-            fail("Empty namespace URI");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(SchemaValidate.SchemaLocation.ERROR_NO_URI, ex.getMessage());
-        }
+    public void testNoEmptySchemaNamespace() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(SchemaValidate.SchemaLocation.ERROR_NO_URI);
+        buildRule.executeTarget("testNoEmptySchemaNamespace");
     }
 
     @Test
-    public void testNoEmptySchemaLocation() throws Exception {
-        try {
-            buildRule.executeTarget("testNoEmptySchemaLocation");
-            fail("Empty schema location");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(SchemaValidate.SchemaLocation.ERROR_NO_LOCATION,
-                    ex.getMessage());
-        }
+    public void testNoEmptySchemaLocation() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(SchemaValidate.SchemaLocation.ERROR_NO_LOCATION);
+        buildRule.executeTarget("testNoEmptySchemaLocation");
     }
 
     @Test
-    public void testNoFile() throws Exception {
-        try {
-            buildRule.executeTarget("testNoFile");
-            fail("No file at file attribute");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(SchemaValidate.SchemaLocation.ERROR_NO_FILE,
-                    ex.getMessage());
-        }
+    public void testNoFile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(SchemaValidate.SchemaLocation.ERROR_NO_FILE);
+        buildRule.executeTarget("testNoFile");
     }
 
     @Test
-    public void testNoDoubleSchemaLocation() throws Exception {
-        try {
-            buildRule.executeTarget("testNoDoubleSchemaLocation");
-            fail("Two locations for schemas");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(SchemaValidate.SchemaLocation.ERROR_TWO_LOCATIONS,
-                    ex.getMessage());
-        }
+    public void testNoDoubleSchemaLocation() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(SchemaValidate.SchemaLocation.ERROR_TWO_LOCATIONS);
+        buildRule.executeTarget("testNoDoubleSchemaLocation");
     }
 
     @Test
-    public void testNoDuplicateSchema() throws Exception {
-        try {
-            buildRule.executeTarget("testNoDuplicateSchema");
-            fail("duplicate schemas with different values");
-        } catch (BuildException ex) {
-            AntAssert.assertContains(SchemaValidate.ERROR_DUPLICATE_SCHEMA,
-                    ex.getMessage());
-        }
+    public void testNoDuplicateSchema() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(SchemaValidate.ERROR_DUPLICATE_SCHEMA);
+        buildRule.executeTarget("testNoDuplicateSchema");
     }
 
     @Test
-    public void testEqualsSchemasOK() throws Exception {
+    public void testEqualsSchemasOK() {
         buildRule.executeTarget("testEqualsSchemasOK");
     }
 
     @Test
-    public void testFileset() throws Exception {
+    public void testFileset() {
         buildRule.executeTarget("testFileset");
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java
index 527e264..9ea6089 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,12 @@
 
 package org.apache.tools.ant.taskdefs.optional;
 
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -32,7 +37,6 @@
 import org.apache.tools.ant.taskdefs.XSLTLogger;
 import org.apache.tools.ant.util.JAXPUtils;
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Test;
 
 /**
@@ -59,13 +63,12 @@
         try {
             getClass().getClassLoader().loadClass("org.apache.xalan.lib.Redirect");
         } catch (Exception exc) {
-            Assume.assumeNoException("xalan redirect is not on the classpath", exc);
+            assumeNoException("xalan redirect is not on the classpath", exc);
         }
         try {
             String factoryName = TransformerFactory.newInstance().getClass().getName();
-            Assume.assumeFalse("TraxFactory is Xalan",
-                              "org.apache.xalan.processor.TransformerFactoryImpl"
-                              .equals(factoryName));
+            assumeFalse("TraxFactory is Xalan",
+                    "org.apache.xalan.processor.TransformerFactoryImpl".equals(factoryName));
         } catch (TransformerFactoryConfigurationError exc) {
             throw new RuntimeException(exc);
         }
@@ -106,13 +109,12 @@
         try {
             getClass().getClassLoader().loadClass("org.apache.xalan.lib.Redirect");
         } catch (Exception exc) {
-            Assume.assumeNoException("xalan redirect is not on the classpath", exc);
+            assumeNoException("xalan redirect is not on the classpath", exc);
         }
         try {
             String factoryName = TransformerFactory.newInstance().getClass().getName();
-            Assume.assumeTrue("TraxFactory is " + factoryName + " and not Xalan",
-                              "org.apache.xalan.processor.TransformerFactoryImpl"
-                              .equals(factoryName));
+            assumeTrue("TraxFactory is " + factoryName + " and not Xalan",
+                    "org.apache.xalan.processor.TransformerFactoryImpl".equals(factoryName));
         } catch (TransformerFactoryConfigurationError exc) {
             throw new RuntimeException(exc);
         }
@@ -161,8 +163,8 @@
             file = new File("/user/local/bin");
         }
         String systemid = JAXPUtils.getSystemId(file);
-        assertTrue("SystemIDs should start by file:/", systemid.startsWith("file:/"));
-        assertTrue("SystemIDs should not start with file:////", !systemid.startsWith("file:////"));
+        assertThat("SystemIDs should start by file:/", systemid, startsWith("file:/"));
+        assertThat("SystemIDs should not start with file:////", systemid, not(startsWith("file:////")));
     }
 
     public void log(String message) {
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateCatalogTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateCatalogTest.java
index 33fa189..187108b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateCatalogTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateCatalogTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,17 +30,12 @@
  */
 public class XmlValidateCatalogTest {
 
-    /**
-     * where tasks run
-     */
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "xmlvalidate.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/xmlvalidate.xml");
     }
 
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java
index 108e7d0..656576c 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XmlValidateTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,10 +22,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.internal.AssumptionViolatedException;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests the XMLValidate optional task, by running targets in the test script
@@ -37,24 +34,22 @@
  */
 public class XmlValidateTest {
 
-    /**
-     * where tasks run
-     */
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "xmlvalidate.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/xmlvalidate.xml");
     }
 
     /**
      * Basic inline 'dtd' element test.
      */
     @Test
-    public void testValidate() throws Exception {
+    public void testValidate() {
         buildRule.executeTarget("testValidate");
     }
 
@@ -62,7 +57,7 @@
      * Test indirect validation.
      */
     @Test
-    public void testDeepValidate() throws Exception {
+    public void testDeepValidate() {
         buildRule.executeTarget("testDeepValidate");
     }
 
@@ -104,41 +99,23 @@
     }
 
     /**
-     * Test xml schema validation
+     * Test xml schema validation,
+     * implicitly assume schema-supporting parser (Java 5+)
      */
     @Test
     public void testXmlSchemaGood() throws BuildException {
-        try {
-            buildRule.executeTarget("testSchemaGood");
-        } catch (BuildException e) {
-            if (e.getMessage().endsWith(
-                    " doesn't recognize feature http://apache.org/xml/features/validation/schema")
-                    || e.getMessage().endsWith(
-                            " doesn't support feature http://apache.org/xml/features/validation/schema")) {
-                throw new AssumptionViolatedException("parser doesn't support schema");
-            } else {
-                throw e;
-            }
-        }
+        buildRule.executeTarget("testSchemaGood");
     }
+
     /**
-     * Test xml schema validation
+     * Test xml schema validation,
+     * implicitly assume schema-supporting parser (Java 5+)
      */
     @Test
     public void testXmlSchemaBad() {
-        try {
-            buildRule.executeTarget("testSchemaBad");
-            fail("Should throw BuildException because 'Bad Schema Validation'");
-        } catch (BuildException e) {
-            if (e.getMessage().endsWith(
-                    " doesn't recognize feature http://apache.org/xml/features/validation/schema")
-                    || e.getMessage().endsWith(
-                            " doesn't support feature http://apache.org/xml/features/validation/schema")) {
-                throw new AssumptionViolatedException("parser doesn't support schema");
-            } else {
-                assertTrue(e.getMessage().contains("not a valid XML document"));
-            }
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("not a valid XML document");
+        buildRule.executeTarget("testSchemaBad");
     }
 
     /**
@@ -159,30 +136,27 @@
      *
      * Bug 11279
      */
-    @Test
+    @Test(expected = BuildException.class)
     public void testUtf8() {
-        try {
-            buildRule.executeTarget("testUtf8");
-            fail("Invalid characters in file");
-        } catch(BuildException ex) {
-          //TODO assert exception message
-        }
+        buildRule.executeTarget("testUtf8");
+        //TODO assert exception message
     }
 
-    // Tests property element, using XML schema properties as an example.
+    /**
+     * Tests property element, using XML schema properties as an example.
+     */
     @Test
     public void testPropertySchemaForValidXML() {
         buildRule.executeTarget("testProperty.validXML");
     }
 
-    @Test
+    /**
+     * Test should fail due to unsatisfied schema
+     */
+    @Test(expected = BuildException.class)
     public void testPropertySchemaForInvalidXML() {
-        try {
-            buildRule.executeTarget("testProperty.invalidXML");
-            fail("XML file does not satisfy schema");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("testProperty.invalidXML");
+        //TODO assert exception message
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XsltTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XsltTest.java
index e757fae..7a48ff3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XsltTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/XsltTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,7 +23,9 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
 
 /**
  * Tests the {@link org.apache.tools.ant.taskdefs.XSLTProcess} task.
@@ -32,53 +34,45 @@
  */
 public class XsltTest {
 
-    /**
-     * where tasks run
-     */
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "xslt.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/xslt.xml");
     }
 
-    @Test
+    /**
+     * Expected failure due to lacking DTD
+     */
+    @Test(expected = BuildException.class)
     public void testCatchNoDtd() {
-        try {
-            buildRule.executeTarget("testCatchNoDtd");
-            fail("Expected failure");
-        } catch(BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("testCatchNoDtd");
+        // TODO assert exception message
     }
 
     @Test
-    public void testCatalog() throws Exception {
+    public void testCatalog() {
          buildRule.executeTarget("testCatalog");
     }
 
     @Test
-    public void testOutputProperty() throws Exception {
+    public void testOutputProperty() {
       buildRule.executeTarget("testOutputProperty");
     }
 
     @Test
-    public void testXMLWithEntitiesInNonAsciiPath() throws Exception {
+    public void testXMLWithEntitiesInNonAsciiPath() {
         buildRule.executeTarget("testXMLWithEntitiesInNonAsciiPath");
     }
 
     /**
      * check that the system id gets set properly on stylesheets.
-     * @throws Exception if something goes wrong.
      */
     @Test
-    public void testStyleSheetWithInclude() throws Exception {
+    public void testStyleSheetWithInclude() {
         buildRule.executeTarget("testStyleSheetWithInclude");
-        if (buildRule.getLog().contains("java.io.FileNotFoundException")) {
-            fail("xsl:include was not found");
-        }
+        assertThat("xsl:include was not found", buildRule.getLog(),
+                not(containsString("java.io.FileNotFoundException")));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/depend/DependTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/depend/DependTest.java
index 1177c8a..8b24b0e 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/depend/DependTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/depend/DependTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,21 +19,28 @@
 package org.apache.tools.ant.taskdefs.optional.depend;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.Hashtable;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.DirectoryScanner;
 import org.apache.tools.ant.FileUtilities;
+import org.apache.tools.ant.taskdefs.condition.JavaVersion;
 import org.apache.tools.ant.types.FileSet;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasKey;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Testcase for the Depend optional task.
@@ -42,15 +49,15 @@
 public class DependTest {
     public static final String RESULT_FILESET = "result";
 
-    public static final String TEST_BUILD_FILE
-        = "src/etc/testcases/taskdefs/optional/depend/depend.xml";
-
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
-        buildRule.configureProject(TEST_BUILD_FILE);
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/depend/depend.xml");
     }
 
     /**
@@ -65,13 +72,10 @@
         FileUtilities.rollbackTimestamps(new File(buildRule.getProject().getProperty("classes.dir")), 5);
 
         buildRule.executeTarget("testdirect");
-        Hashtable files = getResultFiles();
-        assertEquals("Depend did not leave correct number of files", 3,
-            files.size());
-        assertTrue("Result did not contain A.class",
-            files.containsKey("A.class"));
-        assertTrue("Result did not contain D.class",
-            files.containsKey("D.class"));
+        Hashtable<String, String> files = getResultFiles();
+        assertEquals("Depend did not leave correct number of files", 3, files.size());
+        assertThat("Result did not contain A.class", files, hasKey("A.class"));
+        assertThat("Result did not contain D.class", files, hasKey("D.class"));
     }
 
     /**
@@ -86,11 +90,9 @@
         FileUtilities.rollbackTimestamps(new File(buildRule.getProject().getProperty("classes.dir")), 5);
 
         buildRule.executeTarget("testclosure");
-        Hashtable files = getResultFiles();
-        assertTrue("Depend did not leave correct number of files",
-            files.size() <= 2);
-        assertTrue("Result did not contain D.class",
-            files.containsKey("D.class"));
+        Hashtable<String, String> files = getResultFiles();
+        assertTrue("Depend did not leave correct number of files", files.size() <= 2);
+        assertThat("Result did not contain D.class", files, hasKey("D.class"));
     }
 
     /**
@@ -104,14 +106,12 @@
         FileUtilities.rollbackTimestamps(new File(buildRule.getProject().getProperty("tempsrc.dir")), 5);
         FileUtilities.rollbackTimestamps(new File(buildRule.getProject().getProperty("classes.dir")), 5);
 
-
         buildRule.executeTarget("testinner");
-        assertEquals("Depend did not leave correct number of files", 0,
-            getResultFiles().size());
+        assertEquals("Depend did not leave correct number of files", 0, getResultFiles().size());
     }
 
     /**
-     * Test that multi-leve inner class dependencies trigger deletion of
+     * Test that multi-level inner class dependencies trigger deletion of
      * the outer class
      */
     @Test
@@ -123,8 +123,7 @@
         FileUtilities.rollbackTimestamps(new File(buildRule.getProject().getProperty("classes.dir")), 5);
 
         buildRule.executeTarget("testinnerinner");
-        assertEquals("Depend did not leave correct number of files", 0,
-            getResultFiles().size());
+        assertEquals("Depend did not leave correct number of files", 0, getResultFiles().size());
     }
 
     /**
@@ -132,12 +131,9 @@
      */
     @Test
     public void testNoSource() {
-        try {
-            buildRule.executeTarget("testnosource");
-            fail("Build exception expected: No source specified");
-        } catch (BuildException ex) {
-            assertContains("srcdir attribute must be set", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("srcdir attribute must be set");
+        buildRule.executeTarget("testnosource");
     }
 
     /**
@@ -145,12 +141,9 @@
      */
     @Test
     public void testEmptySource() {
-        try {
-            buildRule.executeTarget("testemptysource");
-            fail("Build exception expected: No source specified");
-        } catch (BuildException ex) {
-            assertContains("srcdir attribute must be non-empty", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("srcdir attribute must be non-empty");
+        buildRule.executeTarget("testemptysource");
     }
 
     /**
@@ -159,14 +152,11 @@
      * @return a Hashtable containing the names of the files in the result
      * fileset
      */
-    private Hashtable getResultFiles() {
+    private Hashtable<String, String> getResultFiles() {
         FileSet resultFileSet = buildRule.getProject().getReference(RESULT_FILESET);
         DirectoryScanner scanner = resultFileSet.getDirectoryScanner(buildRule.getProject());
-        Hashtable<String, String> files = new Hashtable<String, String>();
-        for (String scannedFile : scanner.getIncludedFiles()) {
-            files.put(scannedFile, scannedFile);
-        }
-        return files;
+        return Arrays.stream(scanner.getIncludedFiles())
+                .collect(Collectors.toMap(file -> file, file -> file, (a, b) -> b, Hashtable::new));
     }
 
 
@@ -201,12 +191,21 @@
         FileUtilities.rollbackTimestamps(new File(buildRule.getProject().getProperty("classes.dir")), 5);
 
         buildRule.executeTarget("testnonpublic");
-        String log = buildRule.getLog();
-        assertContains("Expected warning about APrivate",
-            "The class APrivate in file", log);
-        assertContains("but has not been deleted because its source file "
-            + "could not be determined",
-            "The class APrivate in file", log);
+        assertThat("Expected warning about APrivate",
+                buildRule.getLog(), both(containsString("The class APrivate in file"))
+                        .and(containsString("but has not been deleted because its source file could not be determined")));
+    }
+
+    /**
+     * Tests that the depend task when run against a path containing a module-info.class (Java 9+ construct)
+     * doesn't run into error
+     */
+    @Test
+    public void testModuleInfo() {
+        final JavaVersion atLeastJava9 = new JavaVersion();
+        atLeastJava9.setAtLeast("9");
+        Assume.assumeTrue("Skipping test execution since Java version is lesser than 9", atLeastJava9.eval());
+        buildRule.executeTarget("testmoduleinfo");
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/i18n/TranslateTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/i18n/TranslateTest.java
index 75c91d4..53247e8 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/i18n/TranslateTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/i18n/TranslateTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -69,26 +69,17 @@
         byte[] buffer1 = new byte[BUF_SIZE];
         byte[] buffer2 = new byte[BUF_SIZE];
 
-        @SuppressWarnings("resource")
-        FileInputStream fis1 = new FileInputStream(file1);
-        try {
-            @SuppressWarnings("resource")
-            FileInputStream fis2 = new FileInputStream(file2);
-            try {
-                int read = 0;
-                while ((read = fis1.read(buffer1)) != -1) {
-                    fis2.read(buffer2);
-                    for (int i = 0; i < read; ++i) {
-                        if (buffer1[i] != buffer2[i]) {
-                            return false;
-                        }
+        try (FileInputStream fis1 = new FileInputStream(file1);
+             FileInputStream fis2 = new FileInputStream(file2)) {
+            int read = 0;
+            while ((read = fis1.read(buffer1)) != -1) {
+                fis2.read(buffer2);
+                for (int i = 0; i < read; ++i) {
+                    if (buffer1[i] != buffer2[i]) {
+                        return false;
                     }
                 }
-            } finally {
-                fis2.close();
             }
-        } finally {
-            fis1.close();
         }
         return true;
     }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageIOTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageIOTest.java
new file mode 100644
index 0000000..de50905
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageIOTest.java
@@ -0,0 +1,148 @@
+/*
+ *  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
+ *
+ *      https://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.image;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.File;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+/**
+ * Tests ImageIOTask.
+ *
+ * @since     Ant 1.10.6
+ */
+public class ImageIOTest {
+
+    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+    private static final String LARGEIMAGE = "largeimage.jpg";
+
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/image/imageio.xml");
+    }
+
+
+    @Test
+    public void testEchoToLog() {
+        buildRule.executeTarget("testEchoToLog");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+    }
+
+    @Test
+    public void testSimpleScale() {
+        buildRule.executeTarget("testSimpleScale");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+
+        File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        assertTrue("Did not create " + f.getAbsolutePath(), f.exists());
+    }
+
+    @Test
+    public void testOverwriteTrue() {
+        buildRule.executeTarget("testSimpleScale");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        assumeTrue("Could not change file modification date",
+                f.setLastModified(f.lastModified() - FILE_UTILS.getFileTimestampGranularity() * 2));
+        long lastModified = f.lastModified();
+        buildRule.executeTarget("testOverwriteTrue");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        long overwrittenLastModified = f.lastModified();
+        assertTrue("File was not overwritten.", lastModified < overwrittenLastModified);
+    }
+
+    @Test
+    public void testDrawOverwriteTrue() {
+        buildRule.executeTarget("testSimpleScale");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        assumeTrue("Could not change file modification date",
+                f.setLastModified(f.lastModified() - FILE_UTILS.getFileTimestampGranularity() * 2));
+        long lastModified = f.lastModified();
+        buildRule.executeTarget("testDrawOverwriteTrue");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        long overwrittenLastModified = f.lastModified();
+        assertTrue("File was not overwritten.", lastModified < overwrittenLastModified);
+    }
+
+    @Test
+    public void testOverwriteFalse() {
+        buildRule.executeTarget("testSimpleScale");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        long lastModified = f.lastModified();
+        buildRule.executeTarget("testOverwriteFalse");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        long overwrittenLastModified = f.lastModified();
+        assertEquals("File was overwritten.", lastModified, overwrittenLastModified);
+    }
+
+    @Test
+    public void testSimpleScaleWithMapper() {
+        buildRule.executeTarget("testSimpleScaleWithMapper");
+        assertThat(buildRule.getLog(), containsString("Processing File"));
+        File f = new File(buildRule.getOutputDir(), "scaled-" + LARGEIMAGE);
+        assertTrue("Did not create " + f.getAbsolutePath(), f.exists());
+    }
+
+    @Test
+    public void testFlip() {
+        buildRule.executeTarget("testFlip");
+        assertThat(buildRule.getFullLog(), containsString("Flipping an image"));
+        File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
+        assertTrue("Did not create " + f.getAbsolutePath(), f.exists());
+    }
+
+    @Test
+    @Ignore("badimage.jpg used in this test doesn't" +
+            " trigger failures https://bugs.openjdk.java.net/browse/JDK-8287120")
+    public void testFailOnError() {
+        final String message = "Unsupported Image Type";
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(message);
+        try {
+            buildRule.executeTarget("testFailOnError");
+        } finally {
+            assertThat(buildRule.getLog(), containsString(message));
+        }
+    }
+
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageTest.java
index 5320541..cefd4c0 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/image/ImageTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,20 +18,25 @@
 
 package org.apache.tools.ant.taskdefs.optional.image;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.File;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
 import static org.junit.Assume.assumeTrue;
 
-
 /**
  * Tests the Image task.
  *
@@ -40,43 +45,52 @@
 public class ImageTest {
 
     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    private static final String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/image/";
     private static final String LARGEIMAGE = "largeimage.jpg";
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
-        buildRule.configureProject(TASKDEFS_DIR + "image.xml");
+        /* JAI depends on internal API removed in Java 9 */
+        assumeFalse(JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/image/image.xml");
     }
 
 
     @Test
     public void testEchoToLog() {
         buildRule.executeTarget("testEchoToLog");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
+        assumeNotNull("JPEG codec is unavailable in classpath",
+                buildRule.getProject().getProperty("jpeg.codec.available"));
+        assertThat(buildRule.getLog(), containsString("Processing File"));
     }
 
     @Test
-    public void testSimpleScale(){
+    public void testSimpleScale() {
         buildRule.executeTarget("testSimpleScale");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
-
+        assumeNotNull("JPEG codec is unavailable in classpath",
+                buildRule.getProject().getProperty("jpeg.codec.available"));
+        assertThat(buildRule.getLog(), containsString("Processing File"));
         File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
         assertTrue("Did not create " + f.getAbsolutePath(), f.exists());
     }
 
     @Test
-    public void testOverwriteTrue() throws InterruptedException {
+    public void testOverwriteTrue() {
         buildRule.executeTarget("testSimpleScale");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
+        assumeNotNull("JPEG codec is unavailable in classpath",
+                buildRule.getProject().getProperty("jpeg.codec.available"));
+        assertThat(buildRule.getLog(), containsString("Processing File"));
         File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
-        assumeTrue("Could not change file modificaiton date",
+        assumeTrue("Could not change file modification date",
                 f.setLastModified(f.lastModified() - FILE_UTILS.getFileTimestampGranularity() * 2));
         long lastModified = f.lastModified();
         buildRule.executeTarget("testOverwriteTrue");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Processing File"));
         f = new File(buildRule.getOutputDir(), LARGEIMAGE);
         long overwrittenLastModified = f.lastModified();
         assertTrue("File was not overwritten.", lastModified < overwrittenLastModified);
@@ -85,20 +99,24 @@
     @Test
     public void testOverwriteFalse() {
         buildRule.executeTarget("testSimpleScale");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
+        assumeNotNull("JPEG codec is unavailable in classpath",
+                buildRule.getProject().getProperty("jpeg.codec.available"));
+        assertThat(buildRule.getLog(), containsString("Processing File"));
         File f = new File(buildRule.getOutputDir(), LARGEIMAGE);
         long lastModified = f.lastModified();
         buildRule.executeTarget("testOverwriteFalse");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("Processing File"));
         f = new File(buildRule.getOutputDir(), LARGEIMAGE);
         long overwrittenLastModified = f.lastModified();
-        assertTrue("File was overwritten.", lastModified == overwrittenLastModified);
+        assertEquals("File was overwritten.", lastModified, overwrittenLastModified);
     }
 
     @Test
     public void testSimpleScaleWithMapper() {
         buildRule.executeTarget("testSimpleScaleWithMapper");
-        AntAssert.assertContains("Processing File", buildRule.getLog());
+        assumeNotNull("JPEG codec is unavailable in classpath",
+                buildRule.getProject().getProperty("jpeg.codec.available"));
+        assertThat(buildRule.getLog(), containsString("Processing File"));
         File f = new File(buildRule.getOutputDir(), "scaled-" + LARGEIMAGE);
         assertTrue("Did not create " + f.getAbsolutePath(), f.exists());
     }
@@ -106,13 +124,13 @@
     @Test
     @Ignore("Previously named in a manner to prevent execution")
     public void testFailOnError() {
+        final String message = "Unable to render RenderedOp for this operation.";
+        thrown.expect(RuntimeException.class);
+        thrown.expectMessage(message);
         try {
             buildRule.executeTarget("testFailOnError");
-            AntAssert.assertContains("Unable to process image stream", buildRule.getLog());
-        } catch (RuntimeException re){
-            assertTrue("Run time exception should say 'Unable to process image stream'. :"
-                       + re.toString(),
-                    re.toString().contains("Unable to process image stream"));
+        } finally {
+            assertThat(buildRule.getLog(), containsString(message));
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTest.java
index 13691fc..e12327e 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,15 @@
 
 package org.apache.tools.ant.taskdefs.optional.jdepend;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
 /**
  * Testcase for the JDepend optional task.
  *
@@ -35,8 +38,8 @@
 
     @Before
     public void setUp() {
-        buildRule.configureProject(
-                "src/etc/testcases/taskdefs/optional/jdepend/jdepend.xml");
+        assertNotNull("build.tests.value not set", System.getProperty("build.tests.value"));
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/jdepend/jdepend.xml");
     }
 
     /**
@@ -45,8 +48,8 @@
     @Test
     public void testSimple() {
         buildRule.executeTarget("simple");
-        AntAssert.assertContains("Package: org.apache.tools.ant.util.facade",
-                buildRule.getOutput());
+        assertThat(buildRule.getOutput(),
+                containsString("Package: org.apache.tools.ant.util.facade"));
     }
 
     /**
@@ -55,7 +58,7 @@
     @Test
     public void testXml() {
         buildRule.executeTarget("xml");
-        AntAssert.assertContains("<DependsUpon>", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("<DependsUpon>"));
     }
 
     /**
@@ -65,7 +68,8 @@
     @Test
     public void testFork() {
         buildRule.executeTarget("fork");
-        AntAssert.assertContains("Package: org.apache.tools.ant.util.facade", buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("Package: org.apache.tools.ant.util.facade"));
     }
 
     /**
@@ -74,7 +78,7 @@
     @Test
     public void testForkXml() {
         buildRule.executeTarget("fork-xml");
-        AntAssert.assertContains("<DependsUpon>", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("<DependsUpon>"));
     }
 
     /**
@@ -83,7 +87,7 @@
     @Test
     public void testTimeout() {
         buildRule.executeTarget("fork-timeout");
-        AntAssert.assertContains("JDepend FAILED - Timed out", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("JDepend FAILED - Timed out"));
     }
 
 
@@ -93,7 +97,8 @@
     @Test
     public void testTimeoutNot() {
         buildRule.executeTarget("fork-timeout-not");
-        AntAssert.assertContains("Package: org.apache.tools.ant.util.facade", buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("Package: org.apache.tools.ant.util.facade"));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/BatchTestTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/BatchTestTest.java
index a5ad2fe..6e329ca 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/BatchTestTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/BatchTestTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,102 +19,97 @@
 package org.apache.tools.ant.taskdefs.optional.junit;
 
 import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.fail;
 
 import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
 
 /**
  *
  * @author  Marian Petras
  */
+@RunWith(Enclosed.class)
 public class BatchTestTest {
 
-    @Test
-    public void testParseTestMethodNamesList() {
-        try {
-            JUnitTest.parseTestMethodNamesList(null);
-            fail("IllegalArgumentException expected when the param is <null>");
-        } catch (IllegalArgumentException ex) {
-            //this is an expected exception
+    @RunWith(Parameterized.class)
+    public static class IllegalArgumentTest {
+
+        // requires JUnit 4.12
+        @Parameters(name = "illegal argument: |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList(null, ",", " ,", ", ", " , ",
+                    ",a", " ,a", "  ,a", "  , a", "  ,a  ", "  ,a  ,",
+                    "ab,,cd", "ab, ,cd", "ab,  ,cd", "ab,  ,cd,", ",ab,  ,cd,",
+                    /* illegal Java identifiers: */
+                    "1", "1a", "1ab", "1abc", "1abc d", "1abc de", "1abc def", "1abc def,",
+                    ",1abc def");
         }
 
-        assertArrayEquals(new String[0], JUnitTest.parseTestMethodNamesList(""));
-        assertArrayEquals(new String[0], JUnitTest.parseTestMethodNamesList(" "));
-        assertArrayEquals(new String[0], JUnitTest.parseTestMethodNamesList("  "));
+        @Parameter
+        public String argument;
 
-        checkParseCausesIAE(",");
-        checkParseCausesIAE(" ,");
-        checkParseCausesIAE(", ");
-        checkParseCausesIAE(" , ");
-        checkParseCausesIAE(",a");
-        checkParseCausesIAE(" ,a");
-        checkParseCausesIAE("  ,a");
-        checkParseCausesIAE("  , a");
-        checkParseCausesIAE("  ,a  ");
-        checkParseCausesIAE("  ,a  ,");
-        checkParseCausesIAE("ab,,cd");
-        checkParseCausesIAE("ab, ,cd");
-        checkParseCausesIAE("ab,  ,cd");
-        checkParseCausesIAE("ab,  ,cd,");
-        checkParseCausesIAE(",ab,  ,cd,");
-
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc"));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc "));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList(" abc"));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList(" abc "));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc  "));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc,"));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc, "));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc ,"));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList("abc , "));
-        assertArrayEquals(new String[] {"abc"}, JUnitTest.parseTestMethodNamesList(" abc  ,"));
-
-        /* legal Java identifiers: */
-        assertArrayEquals(new String[] {"a"}, JUnitTest.parseTestMethodNamesList("a"));
-        assertArrayEquals(new String[] {"a1"}, JUnitTest.parseTestMethodNamesList("a1"));
-        assertArrayEquals(new String[] {"a$"}, JUnitTest.parseTestMethodNamesList("a$"));
-        assertArrayEquals(new String[] {"a$1"}, JUnitTest.parseTestMethodNamesList("a$1"));
-        assertArrayEquals(new String[] {"_bc"}, JUnitTest.parseTestMethodNamesList("_bc"));
-        assertArrayEquals(new String[] {"___"}, JUnitTest.parseTestMethodNamesList("___"));
-
-        /* illegal Java identifiers: */
-        checkParseCausesIAE("1");
-        checkParseCausesIAE("1a");
-        checkParseCausesIAE("1ab");
-        checkParseCausesIAE("1abc");
-        checkParseCausesIAE("1abc d");
-        checkParseCausesIAE("1abc de");
-        checkParseCausesIAE("1abc def");
-        checkParseCausesIAE("1abc def,");
-        checkParseCausesIAE(",1abc def");
-
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc,def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc,def,"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc,def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc, def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc, def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc ,def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc ,def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc , def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList("abc , def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc,def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc,def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc, def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc, def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc ,def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc ,def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc , def"));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc , def "));
-        assertArrayEquals(new String[] {"abc", "def"}, JUnitTest.parseTestMethodNamesList(" abc , def ,"));
+        /**
+         * Expected failure when the parameter is illegal
+         */
+        @Test(expected = IllegalArgumentException.class)
+        public void testParseTestMethodNamesList() {
+            JUnitTest.parseTestMethodNamesList(argument);
+        }
     }
 
-    private static void checkParseCausesIAE(String param) {
-        try {
-            JUnitTest.parseTestMethodNamesList(param);
-            fail("IllegalArgumentException expected when the param is \"" + param + '"');
-        } catch (IllegalArgumentException ex) {
-            //this is an expected exception
+    @RunWith(Parameterized.class)
+    public static class LegalArgumentTest {
+
+        @Parameters(name = "legal argument: |{0}|")
+        public static Collection<Object[]> data() {
+            return Arrays.asList(new Object[][] {
+                    {"", new String[0]}, {" ", new String[0]}, {"  ", new String[0]},
+                    {"abc", new String[]{"abc"}}, {"abc ", new String[]{"abc"}},
+                    {" abc", new String[]{"abc"}}, {" abc ", new String[]{"abc"}},
+                    {"abc  ", new String[]{"abc"}}, {"abc,", new String[]{"abc"}},
+                    {"abc, ", new String[]{"abc"}}, {"abc ,", new String[]{"abc"}},
+                    {"abc , ", new String[]{"abc"}}, {" abc  ,", new String[]{"abc"}},
+                    /* legal Java identifiers: */
+                    {"a", new String[]{"a"}}, {"a1", new String[]{"a1"}},
+                    {"a$", new String[]{"a$"}}, {"a$1", new String[]{"a$1"}},
+                    {"_bc", new String[]{"_bc"}}, {"___", new String[]{"___"}},
+                    {"abc,def", new String[]{"abc", "def"}},
+                    {"abc,def,", new String[]{"abc", "def"}},
+                    {"abc,def ", new String[]{"abc", "def"}},
+                    {"abc, def", new String[]{"abc", "def"}},
+                    {"abc, def ", new String[]{"abc", "def"}},
+                    {"abc ,def", new String[]{"abc", "def"}},
+                    {"abc ,def ", new String[]{"abc", "def"}},
+                    {"abc , def", new String[]{"abc", "def"}},
+                    {"abc , def ", new String[]{"abc", "def"}},
+                    {" abc,def", new String[]{"abc", "def"}},
+                    {" abc,def ", new String[]{"abc", "def"}},
+                    {" abc, def", new String[]{"abc", "def"}},
+                    {" abc, def ", new String[]{"abc", "def"}},
+                    {" abc ,def", new String[]{"abc", "def"}},
+                    {" abc ,def ", new String[]{"abc", "def"}},
+                    {" abc , def", new String[]{"abc", "def"}},
+                    {" abc , def ", new String[]{"abc", "def"}},
+                    {" abc , def ,", new String[]{"abc", "def"}},
+            });
         }
+
+        @Parameter
+        public String argument;
+
+        @Parameter(1)
+        public String[] result;
+
+        @Test
+        public void testParseTestMethodNamesList() {
+            assertArrayEquals(result, JUnitTest.parseTestMethodNamesList(argument));
+       }
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/DOMUtilTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/DOMUtilTest.java
index 7f996df..80bc8c1 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/DOMUtilTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/DOMUtilTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitClassLoaderTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitClassLoaderTest.java
index 175df5f..1c5b6ba 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitClassLoaderTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitClassLoaderTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java
index c467e9a..078e800 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,12 @@
 
 package org.apache.tools.ant.taskdefs.optional.junit;
 
+import static org.apache.tools.ant.util.FileUtils.getFileUtils;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -35,7 +38,6 @@
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.util.FileUtils;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -63,8 +65,8 @@
     @Test
     public void testNoFileJUnitNoFrames() {
         buildRule.executeTarget("reports1");
-        assertFalse("No file junit-noframes.html expected", new File(System.getProperty("root"),
-                "src/etc/testcases/taskdefs/optional/junitreport/test/html/junit-noframes.html").exists());
+        assertFalse("No file junit-noframes.html expected", buildRule.getProject().resolveFile(
+                "junitreport/test/html/junit-noframes.html").exists());
     }
 
     public void assertIndexCreated() {
@@ -87,34 +89,34 @@
         assertTrue("Can't read the report file.", reportFile.canRead());
         assertTrue("File shouldn't be empty.", reportFile.length() > 0);
         // conversion to URL via FileUtils like in XMLResultAggregator, not as suggested in the bug report
-        URL reportUrl = new URL(FileUtils.getFileUtils().toURI(reportFile.getAbsolutePath()));
-        InputStream reportStream = reportUrl.openStream();
-        try {
+        URL reportUrl = new URL(getFileUtils().toURI(reportFile.getAbsolutePath()));
+        try (InputStream reportStream = reportUrl.openStream()) {
             assertTrue("This shouldn't be an empty stream.", reportStream.available() > 0);
-        } finally {
-            FileUtils.getFileUtils().close(reportStream);
         }
     }
 
     @Test
-    public void testEmptyFile() throws Exception {
+    public void testEmptyFile() {
         buildRule.executeTarget("testEmptyFile");
         assertIndexCreated();
-        assertContains("Required text not found in log", XMLResultAggregator.WARNING_EMPTY_FILE, buildRule.getLog());
+        assertThat("Required text not found in log", buildRule.getLog(),
+                containsString(XMLResultAggregator.WARNING_EMPTY_FILE));
     }
 
     @Test
-    public void testIncompleteFile() throws Exception {
+    public void testIncompleteFile() {
         buildRule.executeTarget("testIncompleteFile");
         assertIndexCreated();
-        assertContains("Required text not found in log", XMLResultAggregator.WARNING_IS_POSSIBLY_CORRUPTED, buildRule.getLog());
+        assertThat("Required text not found in log", buildRule.getLog(),
+                containsString(XMLResultAggregator.WARNING_IS_POSSIBLY_CORRUPTED));
     }
 
     @Test
-    public void testWrongElement() throws Exception {
+    public void testWrongElement() {
         buildRule.executeTarget("testWrongElement");
         assertIndexCreated();
-        assertContains("Required text not found in log", XMLResultAggregator.WARNING_INVALID_ROOT_ELEMENT, buildRule.getLog());
+        assertThat("Required text not found in log", buildRule.getLog(),
+                containsString(XMLResultAggregator.WARNING_INVALID_ROOT_ELEMENT));
     }
 
     // Bugzilla Report 34963
@@ -122,14 +124,13 @@
     public void testStackTraceLineBreaks() throws Exception {
         buildRule.executeTarget("testStackTraceLineBreaks");
         assertIndexCreated();
-        FileReader r = null;
-        try {
-            r = new FileReader(new File(buildRule.getOutputDir(), "html/sampleproject/coins/0_CoinTest.html"));
+        try (FileReader r = new FileReader(new File(buildRule.getOutputDir(),
+                "html/sampleproject/coins/0_CoinTest.html"))) {
             String report = FileUtils.readFully(r);
-            assertContains("output must contain <br>:\n" + report, "junit.framework.AssertionFailedError: DOEG<br>", report);
-            assertContains("#51049: output must translate line breaks:\n" + report, "cur['line.separator'] = '\\r\\n';", report);
-        } finally {
-            FileUtils.close(r);
+            assertThat("output must contain <br>:\n" + report, report,
+                    containsString("junit.framework.AssertionFailedError: DOEG<br>"));
+            assertThat("#51049: output must translate line breaks:\n" + report, report,
+                    containsString("cur['line.separator'] = '\\r\\n';"));
         }
     }
 
@@ -179,7 +180,7 @@
     @Test
     public void testWithParams() throws Exception {
         buildRule.executeTarget("testWithParams");
-        assertContains("key1=value1,key2=value2", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("key1=value1,key2=value2"));
         commonIndexFileAssertions();
     }
 
@@ -187,9 +188,8 @@
     public void testWithSecurityManagerAndXalanFactory() throws Exception {
         try {
             String factoryName = TransformerFactory.newInstance().getClass().getName();
-            Assume.assumeTrue("TraxFactory is " + factoryName + " and not Xalan",
-                              "org.apache.xalan.processor.TransformerFactoryImpl"
-                              .equals(factoryName));
+            assumeTrue("TraxFactory is " + factoryName + " and not Xalan",
+                    "org.apache.xalan.processor.TransformerFactoryImpl".equals(factoryName));
         } catch (TransformerFactoryConfigurationError exc) {
             throw new RuntimeException(exc);
         }
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 5f5d44f..0e69d9f 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
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,14 +17,16 @@
  */
 package org.apache.tools.ant.taskdefs.optional.junit;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
 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.assertThat;
 import static org.junit.Assert.assertTrue;
-
-import static org.apache.tools.ant.AntAssert.assertNotContains;
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -34,6 +36,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -51,7 +54,6 @@
 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;
@@ -96,7 +98,7 @@
     }
 
     @Test
-    public void testNonForkedCapture() throws IOException {
+    public void testNonForkedCapture() {
         buildRule.executeTarget("capture");
         assertNoPrint(buildRule.getLog(), "log");
         assertNoPrint(buildRule.getFullLog(), "debug log");
@@ -139,7 +141,7 @@
         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);
+                assumeTrue("Skipping test since it fails with JUnit 4", clazz == null);
             } catch (ClassNotFoundException e) {
                 // OK, this is JUnit3, can run test
             }
@@ -178,26 +180,26 @@
                    collectorFile.exists());
         // the passing test cases
         buildRule.executeTarget("A.test01");
-        assertContains("1st run: should run A.test01", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run A.test01"));
         buildRule.executeTarget("B.test05");
-        assertContains("1st run: should run B.test05", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run B.test05"));
         buildRule.executeTarget("B.test06");
-        assertContains("1st run: should run B.test06", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run B.test06"));
         buildRule.executeTarget("C.test07");
-        assertContains("1st run: should run C.test07", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run C.test07"));
         buildRule.executeTarget("C.test08");
-        assertContains("1st run: should run C.test08", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run C.test08"));
         buildRule.executeTarget("C.test09");
-        assertContains("1st run: should run C.test09", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run C.test09"));
         // the failing test cases
         buildRule.executeTarget("A.test02");
-        assertContains("1st run: should run A.test02", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run A.test02"));
         buildRule.executeTarget("A.test03");
-        assertContains("1st run: should run A.test03", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run A.test03"));
         buildRule.executeTarget("B.test04");
-        assertContains("1st run: should run B.test04", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run B.test04"));
         buildRule.executeTarget("D.test10");
-        assertContains("1st run: should run D.test10", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("1st run: should run D.test10"));
 
 
         // 2nd junit run: should do only failing tests
@@ -207,26 +209,26 @@
                    collectorFile.exists());
         // the passing test cases
         buildRule.executeTarget("A.test01");
-        assertNotContains("2nd run: should not run A.test01", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("2nd run: should not run A.test01")));
         buildRule.executeTarget("B.test05");
-        assertNotContains("2nd run: should not run A.test05", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("2nd run: should not run A.test05")));
         buildRule.executeTarget("B.test06");
-        assertNotContains("2nd run: should not run B.test06", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("2nd run: should not run B.test06")));
         buildRule.executeTarget("C.test07");
-        assertNotContains("2nd run: should not run C.test07", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("2nd run: should not run C.test07")));
         buildRule.executeTarget("C.test08");
-        assertNotContains("2nd run: should not run C.test08", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("2nd run: should not run C.test08")));
         buildRule.executeTarget("C.test09");
-        assertNotContains("2nd run: should not run C.test09", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("2nd run: should not run C.test09")));
         // the failing test cases
         buildRule.executeTarget("A.test02");
-        assertContains("2nd run: should run A.test02", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("2nd run: should run A.test02"));
         buildRule.executeTarget("A.test03");
-        assertContains("2nd run: should run A.test03", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("2nd run: should run A.test03"));
         buildRule.executeTarget("B.test04");
-        assertContains("2nd run: should run B.test04", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("2nd run: should run B.test04"));
         buildRule.executeTarget("D.test10");
-        assertContains("2nd run: should run D.test10", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("2nd run: should run D.test10"));
 
 
         // "fix" errors in class A
@@ -238,13 +240,13 @@
                    + "' should exist after the 3rd run.",
                    collectorFile.exists());
         buildRule.executeTarget("A.test02");
-        assertContains("3rd run: should run A.test02", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("3rd run: should run A.test02"));
         buildRule.executeTarget("A.test03");
-        assertContains("3rd run: should run A.test03", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("3rd run: should run A.test03"));
         buildRule.executeTarget("B.test04");
-        assertContains("3rd run: should run B.test04", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("3rd run: should run B.test04"));
         buildRule.executeTarget("D.test10");
-        assertContains("3rd run: should run D.test10", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("3rd run: should run D.test10"));
 
 
         // 4rd run: two running tests with errors
@@ -252,13 +254,15 @@
         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());
+        //TODO: these statements fail
+        //buildRule.executeTarget("A.test02");
+        //assertThat(buildRule.getOutput(), not(containsString("4th run: should not run A.test02")));
+        //buildRule.executeTarget("A.test03");
+        //assertThat(buildRule.getOutput(), not(containsString("4th run: should not run A.test03")));
         buildRule.executeTarget("B.test04");
-        assertContains("4th run: should run B.test04", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("4th run: should run B.test04"));
         buildRule.executeTarget("D.test10");
-        assertContains("4th run: should run D.test10", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("4th run: should run D.test10"));
 
     }
 
@@ -271,16 +275,16 @@
     @Test
     public void testMultilineAssertsNoFork() {
         buildRule.executeTarget("testMultilineAssertsNoFork");
-        assertNotContains("messaged up", buildRule.getLog());
-        assertNotContains("crashed)", buildRule.getLog());
+        assertThat(buildRule.getLog(), not(containsString("messaged up")));
+        assertThat(buildRule.getLog(), not(containsString("crashed)")));
     }
 
     // Bugzilla Issue 45411
     @Test
     public void testMultilineAssertsFork() {
         buildRule.executeTarget("testMultilineAssertsFork");
-        assertNotContains("messaged up", buildRule.getLog());
-        assertNotContains("crashed)", buildRule.getLog());
+        assertThat(buildRule.getLog(), not(containsString("messaged up")));
+        assertThat(buildRule.getLog(), not(containsString("crashed)")));
     }
 
     private void assertResultFilesExist(String target, String extension) {
@@ -300,46 +304,37 @@
     }
 
     private void assertNoPrint(String result, String where) {
-        assertNotContains(where + " '" + result + "' must not contain print statement",
-                   "print to System.", result);
+        assertThat(where + " '" + result + "' must not contain print statement",
+                result, not(containsString("print to System.")));
     }
 
     private void assertOutput() throws IOException {
-        FileReader inner = new FileReader(new File(buildRule.getOutputDir(),
-                                          "testlog.txt"));
-        BufferedReader reader = new BufferedReader(inner);
-        try {
+        FileReader inner = new FileReader(new File(buildRule.getOutputDir(), "testlog.txt"));
+        try (BufferedReader reader = new BufferedReader(inner)) {
             String line = reader.readLine();
-            assertEquals("Testsuite: org.apache.tools.ant.taskdefs.optional.junit.Printer",
-                         line);
+            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:"));
+            assertThat(line, startsWith("Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:"));
             line = reader.readLine();
-            assertEquals("------------- Standard Output ---------------",
-                         line);
+            assertEquals("------------- Standard Output ---------------", line);
             assertPrint(reader.readLine(), "static", "out");
             assertPrint(reader.readLine(), "constructor", "out");
             assertPrint(reader.readLine(), "method", "out");
             line = reader.readLine();
-            assertEquals("------------- ---------------- ---------------",
-                         line);
+            assertEquals("------------- ---------------- ---------------", line);
             line = reader.readLine();
-            assertEquals("------------- Standard Error -----------------",
-                         line);
+            assertEquals("------------- Standard Error -----------------", line);
             assertPrint(reader.readLine(), "static", "err");
             assertPrint(reader.readLine(), "constructor", "err");
             assertPrint(reader.readLine(), "method", "err");
             line = reader.readLine();
-            assertEquals("------------- ---------------- ---------------",
-                         line);
+            assertEquals("------------- ---------------- ---------------", line);
             line = reader.readLine();
             assertEquals("", line);
             line = reader.readLine();
             assertNotNull(line);
-            assertTrue(line.startsWith("Testcase: testNoCrash took "));
-        } finally {
-            inner.close();
+            assertThat(line, startsWith("Testcase: testNoCrash took "));
         }
     }
 
@@ -384,12 +379,12 @@
     }
 
     @Test
-    public void testTestMethods() throws Exception {
+    public void testTestMethods() {
         buildRule.executeTarget("testTestMethods");
     }
 
     @Test
-    public void testNonTestsSkipped() throws Exception {
+    public void testNonTestsSkipped() {
 
         buildRule.executeTarget("testNonTests");
         assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.NonTestMissed.xml",
@@ -496,7 +491,7 @@
             assertNotNull(mockProcLauncher.cmd);
             String resCp = null;
             String resMp = null;
-            Set<String> resExports = new TreeSet<String>();
+            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];
@@ -510,7 +505,8 @@
             }
             assertTrue("No exports", resExports.isEmpty());
             if (project.getProperty(MagicNames.BUILD_SYSCLASSPATH) == null
-                && System.getProperty(MagicNames.BUILD_SYSCLASSPATH) == null) {
+                && System.getProperty(MagicNames.BUILD_SYSCLASSPATH) == null
+                && project.getProperty("tests.and.ant.share.classloader") == null) {
                 assertEquals("Expected classpath", cp.toString(), resCp);
             }
             assertEquals("Expected modulepath", mp.toString(), resMp);
@@ -553,7 +549,7 @@
             assertNotNull(mockProcLauncher.cmd);
             String resCp = null;
             String resMp = null;
-            Set<String> resExports = new TreeSet<String>();
+            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];
@@ -567,7 +563,8 @@
             }
             assertTrue("No exports", resExports.isEmpty());
             if (project.getProperty(MagicNames.BUILD_SYSCLASSPATH) == null
-                && System.getProperty(MagicNames.BUILD_SYSCLASSPATH) == null) {
+                && System.getProperty(MagicNames.BUILD_SYSCLASSPATH) == null
+                && project.getProperty("tests.and.ant.share.classloader") == null) {
                 assertNull("No classpath", resCp);
             }
             assertEquals("Expected modulepath", mp.toString(), resMp);
@@ -581,6 +578,8 @@
                 LoaderUtils.classNameToResource(Project.class.getName());
         final File antclasses = LoaderUtils.getResourceSource(
                 Project.class.getClassLoader(), projectResourceName);
+        assumeTrue("skipping test as ant is found inside of a jar rather than a directory",
+                   antclasses.isDirectory());
         final String testResourceName =
                 LoaderUtils.classNameToResource(junit.framework.Test.class.getName());
         final File junitJar = LoaderUtils.getResourceSource(
@@ -590,29 +589,27 @@
     }
 
     @Test
-    public void testCheckDuplicateAntJar() throws Exception {
+    public void testCheckDuplicateAntJar() {
         setupCheckDuplicateTest();
         buildRule.executeTarget("testCheckForkedPath");
-        assertTrue("Expecting the warning about the duplicate ant jar",
-                buildRule.getLog().contains("WARNING: multiple versions of ant detected in path for junit"));
+        assertThat("Expecting the warning about the duplicate ant jar", buildRule.getLog(),
+                containsString("WARNING: multiple versions of ant detected in path for junit"));
     }
 
     @Test
-    public void testCheckNonDuplicateAntJar() throws Exception {
+    public void testCheckNonDuplicateAntJar() {
         setupCheckDuplicateTest();
         buildRule.getProject().setProperty("includeantruntime", "no");
         buildRule.executeTarget("testCheckForkedPath");
-        assertFalse("Unexpected warning about the duplicate ant jar",
-                buildRule.getLog().contains("WARNING: multiple versions of ant detected in path for junit"));
+        assertThat("Unexpected warning about the duplicate ant jar", buildRule.getLog(),
+                not(containsString("WARNING: multiple versions of ant detected in path for junit")));
     }
 
     private void delete(File f) {
         if (f.isDirectory()) {
             final File[] clds = f.listFiles();
             if (clds != null) {
-                for (File cld : clds) {
-                    delete(cld);
-                }
+                Arrays.stream(clds).forEach(this::delete);
             }
         }
         f.delete();
@@ -623,8 +620,7 @@
 
         @Override
         public Process exec(Project project, String[] cmd, String[] env, File workingDir) throws IOException {
-            this.cmd = new String[cmd.length];
-            System.arraycopy(cmd, 0, this.cmd, 0, cmd.length);
+            this.cmd = Arrays.copyOf(cmd, cmd.length);
             return new MockProcess();
         }
 
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestListenerTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestListenerTest.java
index a4798ef..386aae8 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestListenerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestListenerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,8 +18,9 @@
 
 package org.apache.tools.ant.taskdefs.optional.junit;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.apache.tools.ant.AntAssert.assertNotContains;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
@@ -48,55 +49,55 @@
     public void testFullLogOutput() {
         buildRule.getProject().setProperty("enableEvents", "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertContains("expecting full log to have BuildListener events",
-                JUnitTask.TESTLISTENER_PREFIX, buildRule.getFullLog());
+        assertThat("expecting full log to have BuildListener events", buildRule.getFullLog(),
+                containsString(JUnitTask.TESTLISTENER_PREFIX));
     }
 
     @Test
     public void testNoLogOutput() {
         buildRule.getProject().setProperty("enableEvents", "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertNotContains("expecting log to not have BuildListener events",
-                JUnitTask.TESTLISTENER_PREFIX, buildRule.getLog());
+        assertThat("expecting log to not have BuildListener events", buildRule.getLog(),
+                not(containsString(JUnitTask.TESTLISTENER_PREFIX)));
     }
 
     @Test
     public void testTestCountFired() {
         buildRule.getProject().setProperty("enableEvents", "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertContains("expecting test count message", JUnitTask.TESTLISTENER_PREFIX
-                + "tests to run: ", buildRule.getFullLog());
+        assertThat("expecting test count message", buildRule.getFullLog(),
+                containsString(JUnitTask.TESTLISTENER_PREFIX + "tests to run: "));
     }
 
     @Test
     public void testStartTestFired() {
         buildRule.getProject().setProperty("enableEvents", "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertContains("expecting test started message", JUnitTask.TESTLISTENER_PREFIX
-                + "startTest(" + PASS_TEST + ")", buildRule.getFullLog());
+        assertThat("expecting test started message", buildRule.getFullLog(),
+                containsString(JUnitTask.TESTLISTENER_PREFIX + "startTest(" + PASS_TEST + ")"));
     }
 
     @Test
     public void testEndTestFired() {
         buildRule.getProject().setProperty("enableEvents", "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertContains("expecting test ended message", JUnitTask.TESTLISTENER_PREFIX
-                + "endTest(" + PASS_TEST + ")", buildRule.getFullLog());
+        assertThat("expecting test ended message", buildRule.getFullLog(),
+                containsString(JUnitTask.TESTLISTENER_PREFIX + "endTest(" + PASS_TEST + ")"));
     }
 
     @Test
     public void testNoFullLogOutputByDefault() {
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertNotContains("expecting full log to not have BuildListener events",
-                JUnitTask.TESTLISTENER_PREFIX, buildRule.getFullLog());
+        assertThat("expecting full log to not have BuildListener events", buildRule.getFullLog(),
+                not(containsString(JUnitTask.TESTLISTENER_PREFIX)));
     }
 
     @Test
     public void testFullLogOutputMagicProperty() {
         buildRule.getProject().setProperty(JUnitTask.ENABLE_TESTLISTENER_EVENTS, "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertContains("expecting full log to have BuildListener events",
-                JUnitTask.TESTLISTENER_PREFIX, buildRule.getFullLog());
+        assertThat("expecting full log to have BuildListener events", buildRule.getFullLog(),
+                containsString(JUnitTask.TESTLISTENER_PREFIX));
     }
 
     @Test
@@ -104,8 +105,8 @@
         buildRule.getProject().setProperty(JUnitTask.ENABLE_TESTLISTENER_EVENTS, "false");
         buildRule.getProject().setProperty("enableEvents", "true");
         buildRule.executeTarget(PASS_TEST_TARGET);
-        assertNotContains("expecting full log to not have BuildListener events",
-                JUnitTask.TESTLISTENER_PREFIX, buildRule.getFullLog());
+        assertThat("expecting full log to not have BuildListener events", buildRule.getFullLog(),
+                not(containsString(JUnitTask.TESTLISTENER_PREFIX)));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunnerTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunnerTest.java
index dede70d..ad25425 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunnerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunnerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,20 +17,22 @@
  */
 package org.apache.tools.ant.taskdefs.optional.junit;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
+import org.apache.tools.ant.BuildException;
+import org.junit.Test;
+
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
-import org.apache.tools.ant.BuildException;
-import org.junit.Test;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Small testcase for the runner, tests are very very very basics.
@@ -54,7 +56,7 @@
         runner.run();
         String error = runner.getFormatter().getError();
         // might be FAILURES or ERRORS depending on JUnit version?
-        assertTrue(error, runner.getRetCode() != JUnitTestRunner.SUCCESS);
+        assertNotEquals(error, JUnitTestRunner.SUCCESS, runner.getRetCode());
     }
 
     // check that having no suite generates no errors
@@ -80,7 +82,7 @@
         runner.run();
         String error = runner.getFormatter().getError();
         assertEquals(error, JUnitTestRunner.ERRORS, runner.getRetCode());
-        assertTrue(error, error.contains("thrown on purpose"));
+        assertThat(error, error, containsString("thrown on purpose"));
     }
 
     // check that something which is not a testcase generates no errors
@@ -91,10 +93,8 @@
         runner.run();
         // On junit3 this is a FAILURE, on junit4 this is an ERROR
         int ret = runner.getRetCode();
-
-        if (ret != JUnitTestRunner.FAILURES && ret != JUnitTestRunner.ERRORS) {
-            fail("Unexpected result " + ret + " from junit runner");
-        }
+        assertTrue("Unexpected result " + ret + " from junit runner",
+                ret == JUnitTestRunner.FAILURES || ret == JUnitTestRunner.ERRORS);
         // JUnit3 test
         //assertEquals(runner.getFormatter().getError(), JUnitTestRunner.FAILURES, runner.getRetCode());
     }
@@ -121,11 +121,10 @@
     public void testStaticInitializerErrorTestCase() {
         TestRunner runner = createRunner(StaticInitializerErrorTestCase.class);
         runner.run();
-        // On junit3 this is a FAILURE, on junit4 this is an ERROR
+        // For JUnit 3 this is a FAILURE, for JUnit 4 this is an ERROR
         int ret = runner.getRetCode();
-        if (ret != JUnitTestRunner.FAILURES && ret != JUnitTestRunner.ERRORS) {
-            fail("Unexpected result " + ret + " from junit runner");
-        }
+        assertTrue("Unexpected result " + ret + " from junit runner",
+                ret == JUnitTestRunner.FAILURES || ret == JUnitTestRunner.ERRORS);
     }
 
     // check that an exception in the constructor is noticed
@@ -133,15 +132,14 @@
     public void testInvalidTestCase() {
         TestRunner runner = createRunner(InvalidTestCase.class);
         runner.run();
-        // On junit3 this is a FAILURE, on junit4 this is an ERROR
+        // For JUnit 3 this is a FAILURE, for JUnit 4 this is an ERROR
         int ret = runner.getRetCode();
-        if (ret != JUnitTestRunner.FAILURES && ret != JUnitTestRunner.ERRORS) {
-            fail("Unexpected result " + ret + " from junit runner");
-        }
+        assertTrue("Unexpected result " + ret + " from junit runner",
+                ret == JUnitTestRunner.FAILURES || ret == JUnitTestRunner.ERRORS);
         // JUNIT3 test
         //assertEquals(error, JUnitTestRunner.FAILURES, runner.getRetCode());
         //@fixme as of now does not report the original stacktrace.
-        //assertTrue(error, error.indexOf("thrown on purpose") != -1);
+        //assertThat(error, error, containsString("thrown on purpose"));
     }
 
     // check that JUnit 4 synthetic AssertionFailedError gets message and cause from AssertionError
@@ -309,9 +307,7 @@
     public static class AssertionErrorTest {
         @Test
         public void throwsAssertionError() {
-            AssertionError assertionError = new AssertionError("failure message");
-            assertionError.initCause(new RuntimeException("cause message"));
-            throw assertionError;
+            throw new AssertionError("failure message", new RuntimeException("cause message"));
         }
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelperTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelperTest.java
index a4b8ce9..4171959 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/NoVmCrash.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/NoVmCrash.java
index 392a92e..fea13a3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/NoVmCrash.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/NoVmCrash.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Printer.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Printer.java
index 0200648..a81b14b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Printer.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Printer.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Sleeper.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Sleeper.java
index ab8ccda..2443488 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Sleeper.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/Sleeper.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/SuiteMethodTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/SuiteMethodTest.java
index 14a0966..3b179d5 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/SuiteMethodTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/SuiteMethodTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrashTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrashTest.java
index eb20284..4779753 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrashTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TearDownOnVmCrashTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,9 +18,10 @@
 
 package org.apache.tools.ant.taskdefs.optional.junit;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.apache.tools.ant.AntAssert.assertNotContains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Before;
@@ -41,13 +42,13 @@
     public void testNoTeardown() {
         buildRule.executeTarget("testNoTeardown");
         assertEquals("true", buildRule.getProject().getProperty("error"));
-        assertNotContains("tearDown called on Timeout", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), not(containsString("tearDown called on Timeout")));
     }
 
     @Test
     public void testTeardown() {
         buildRule.executeTarget("testTeardown");
         assertEquals("true", buildRule.getProject().getProperty("error"));
-        assertContains("tearDown called on Timeout", buildRule.getOutput());
+        assertThat(buildRule.getOutput(), containsString("tearDown called on Timeout"));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TestFormatter.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TestFormatter.java
index 27420d6..5d9303b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TestFormatter.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/TestFormatter.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/VmCrash.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/VmCrash.java
index 92d21b6..56c40fa 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/VmCrash.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/VmCrash.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLFormatterWithCDATAOnSystemOut.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLFormatterWithCDATAOnSystemOut.java
index 1221ba4..628bb24 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLFormatterWithCDATAOnSystemOut.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLFormatterWithCDATAOnSystemOut.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,11 +26,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
 
 public class XMLFormatterWithCDATAOnSystemOut {
 
-    private static final String DIR = "src/etc/testcases/taskdefs/optional/junit";
     private static final String REPORT =
         "TEST-" + XMLFormatterWithCDATAOnSystemOut.class.getName() + ".xml";
 
@@ -60,21 +60,15 @@
 
     @Test
     public void testBuildfile() throws IOException {
-        buildRule.configureProject(DIR + "/cdataoutput.xml");
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/junit/cdataoutput.xml");
         if (buildRule.getProject().getProperty("cdata.inner") == null) {
             // avoid endless loop
             buildRule.executeTarget("run-junit");
             File f = buildRule.getProject().resolveFile(REPORT);
-            FileReader reader = null;
-            try {
-                reader = new FileReader(f);
-                String content = FileUtils.readFully(reader);
-                assertTrue(content.indexOf("</RESPONSE>&#x5d;&#x5d;&gt;"
-                                           + "</ERROR>") > 0);
+            try (FileReader reader = new FileReader(f)) {
+                assertThat(FileUtils.readFully(reader),
+                        containsString("</RESPONSE>&#x5d;&#x5d;&gt;</ERROR>"));
             } finally {
-                if (reader != null) {
-                    reader.close();
-                }
                 f.delete();
             }
         }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
index c3530ae..802f572 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 package org.apache.tools.ant.taskdefs.optional.junit;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -29,7 +30,6 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Delete;
 import org.apache.tools.ant.types.FileSet;
-import org.junit.Assume;
 import org.junit.Test;
 
 public class XMLResultAggregatorTest {
@@ -40,7 +40,7 @@
         try {
             Class.forName("java.nio.file.Files");
         } catch (ClassNotFoundException x) {
-            Assume.assumeNoException("Skip test on JDK 6 and below", x);
+            assumeNoException("Skip test on JDK 6 and below", x);
         }
         final File d = new File(System.getProperty("java.io.tmpdir"), "XMLResultAggregatorTest");
         if (d.exists()) {
@@ -50,14 +50,11 @@
         }
         assertTrue(d.getAbsolutePath(), d.mkdir());
         File xml = new File(d, "x.xml");
-        PrintWriter pw = new PrintWriter(new FileOutputStream(xml));
-        try {
+        try (PrintWriter pw = new PrintWriter(new FileOutputStream(xml))) {
             pw.println("<testsuite errors='0' failures='0' name='my.UnitTest' tests='1'>");
             pw.println(" <testcase classname='my.UnitTest' name='testSomething'/>");
             pw.println("</testsuite>");
             pw.flush();
-        } finally {
-            pw.close();
         }
         XMLResultAggregator task = new XMLResultAggregator();
         task.setTodir(d);
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
new file mode 100644
index 0000000..1c36672
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
@@ -0,0 +1,498 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import static org.example.junitlauncher.Tracker.verifyFailed;
+import static org.example.junitlauncher.Tracker.verifySetupFailed;
+import static org.example.junitlauncher.Tracker.verifySkipped;
+import static org.example.junitlauncher.Tracker.verifySuccess;
+import static org.example.junitlauncher.Tracker.wasTestRun;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask;
+import org.apache.tools.ant.util.LoaderUtils;
+import org.example.junitlauncher.jupiter.JupiterSampleTest;
+import org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll;
+import org.example.junitlauncher.jupiter.JupiterTagSampleTest;
+import org.example.junitlauncher.vintage.AlwaysFailingJUnit4Test;
+import org.example.junitlauncher.vintage.ForkedTest;
+import org.example.junitlauncher.vintage.JUnit4SampleTest;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Tests the {@link JUnitLauncherTask}
+ */
+public class JUnitLauncherTaskTest {
+
+    @Rule
+    public final BuildFileRule buildRule = new BuildFileRule();
+
+    /**
+     * The JUnit setup method.
+     */
+    @Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/junitlauncher.xml");
+    }
+
+    /**
+     * Tests that when a test, that's configured with {@code haltOnFailure=true}, stops the build, when the
+     * test fails
+     */
+    @Test
+    public void testFailureStopsBuild() throws Exception {
+        final String targetName = "test-failure-stops-build";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        try {
+            buildRule.executeTarget(targetName);
+            Assert.fail(targetName + " was expected to fail");
+        } catch (BuildException e) {
+            // expected, but do further tests to make sure the build failed for expected reason
+            if (!verifyFailed(trackerFile, AlwaysFailingJUnit4Test.class.getName(),
+                    "testWillFail")) {
+                // throw back the original cause
+                throw e;
+            }
+        }
+    }
+    
+    /**
+     * Tests that when a test, that's isn't configured with {@code haltOnFailure=true}, continues the
+     * build even when there are test failures
+     */
+    @Test
+    public void testFailureContinuesBuild() throws Exception {
+        final String targetName = "test-failure-continues-build";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+        // make sure the test that was expected to be run (and fail), did indeed fail
+        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to run", wasTestRun(trackerFile,
+                AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
+        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to fail", verifyFailed(trackerFile,
+                AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
+    }
+
+    /**
+     * Tests the execution of test that's expected to succeed
+     */
+    @Test
+    public void testSuccessfulTests() throws Exception {
+        final String targetName = "test-success";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+        // make sure the right test(s) were run
+        Assert.assertTrue("JUnit4SampleTest test was expected to be run", wasTestRun(trackerFile, JUnit4SampleTest.class.getName()));
+        Assert.assertTrue("JUnit4SampleTest#testFoo was expected to succeed", verifySuccess(trackerFile,
+                JUnit4SampleTest.class.getName(), "testFoo"));
+    }
+
+    /**
+     * Tests execution of a test which is configured to execute only a particular set of test methods
+     */
+    @Test
+    public void testSpecificMethodTest() throws Exception {
+        final String targetSpecificMethod = "test-one-specific-method";
+        final Path tracker1 = setupTrackerProperty(targetSpecificMethod);
+        buildRule.executeTarget(targetSpecificMethod);
+        // verify only that specific method was run
+        Assert.assertTrue("testBar was expected to be run", wasTestRun(tracker1, JUnit4SampleTest.class.getName(),
+                "testBar"));
+        Assert.assertFalse("testFoo wasn't expected to be run", wasTestRun(tracker1, JUnit4SampleTest.class.getName(),
+                "testFoo"));
+
+
+        final String targetMultipleMethods = "test-multiple-specific-methods";
+        final Path tracker2 = setupTrackerProperty(targetMultipleMethods);
+        buildRule.executeTarget(targetMultipleMethods);
+        Assert.assertTrue("testFooBar was expected to be run", wasTestRun(tracker2, JUnit4SampleTest.class.getName(),
+                "testFooBar"));
+        Assert.assertTrue("testFoo was expected to be run", wasTestRun(tracker2, JUnit4SampleTest.class.getName(),
+                "testFoo"));
+        Assert.assertFalse("testBar wasn't expected to be run", wasTestRun(tracker2, JUnit4SampleTest.class.getName(),
+                "testBar"));
+    }
+
+    /**
+     * Tests the execution of more than one {@code &lt;test&gt;} elements in the {@code &lt;junitlauncher&gt;} task
+     */
+    @Test
+    public void testMultipleIndividualTests() throws Exception {
+        final String targetName = "test-multiple-individual";
+        final Path trackerFile1 = setupTrackerProperty(targetName + "-1");
+        final Path trackerFile2 = setupTrackerProperty(targetName + "-2");
+        buildRule.executeTarget(targetName);
+
+        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to be run", wasTestRun(trackerFile1,
+                AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
+        Assert.assertTrue("JUnit4SampleTest#testFoo was expected to be run", wasTestRun(trackerFile2,
+                JUnit4SampleTest.class.getName(), "testFoo"));
+    }
+
+    /**
+     * Tests execution of tests, that have been configured using the {@code &lt;testclasses&gt;} nested element
+     * of the {@code &lt;junitlauncher&gt;} task
+     */
+    @Test
+    public void testTestClasses() throws Exception {
+        final String targetName = "test-batch";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+
+        Assert.assertTrue("JUnit4SampleTest#testFoo was expected to succeed", verifySuccess(trackerFile,
+                JUnit4SampleTest.class.getName(), "testFoo"));
+        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to fail", verifyFailed(trackerFile,
+                AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
+        Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", verifySuccess(trackerFile,
+                JupiterSampleTest.class.getName(), "testSucceeds"));
+        Assert.assertTrue("JupiterSampleTest#testFails was expected to succeed", verifyFailed(trackerFile,
+                JupiterSampleTest.class.getName(), "testFails"));
+        Assert.assertTrue("JupiterSampleTest#testSkipped was expected to be skipped", verifySkipped(trackerFile,
+                JupiterSampleTest.class.getName(), "testSkipped"));
+        Assert.assertFalse("ForkedTest wasn't expected to be run", wasTestRun(trackerFile, ForkedTest.class.getName()));
+
+        verifyLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.xml", "<failure message=\"Intentional failure\" type=\"java.lang.RuntimeException\">");
+        verifyLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingStatic.xml", "Caused by: java.lang.RuntimeException: Intentional exception from static init block");
+    }
+
+    private void verifyLegacyXMLFile(final String fileName, final String expectedContentExtract) throws IOException {
+        final String outputDir = buildRule.getProject().getProperty("output.dir");
+        final Path xmlFile = Paths.get(outputDir, fileName);
+
+        Assert.assertTrue("XML file doesn't exist: " + xmlFile, Files.exists(xmlFile));
+        final String content = new String(Files.readAllBytes(xmlFile), StandardCharsets.UTF_8);
+        Assert.assertTrue(fileName + " doesn't contain " + expectedContentExtract, content.contains(expectedContentExtract));
+    }
+
+    /**
+     * Tests the execution of a forked test
+     */
+    @Test
+    public void testBasicFork() throws Exception {
+        final String targetName = "test-basic-fork";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        // setup a dummy and incorrect value of a sysproperty that's used in the test
+        // being forked
+        System.setProperty(ForkedTest.SYS_PROP_ONE, "dummy");
+        buildRule.executeTarget(targetName);
+        // verify that our JVM's sysprop value didn't get changed
+        Assert.assertEquals("System property " + ForkedTest.SYS_PROP_ONE + " was unexpected updated",
+                "dummy", System.getProperty(ForkedTest.SYS_PROP_ONE));
+
+        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", verifySuccess(trackerFile,
+                ForkedTest.class.getName(), "testSysProp"));
+    }
+
+    /**
+     * Tests that in a forked mode execution of tests, when the {@code includeJUnitPlatformLibraries} attribute
+     * is set to false, then the execution of such tests fails with a classloading error for the JUnit platform
+     * classes
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testExcludeJUnitPlatformLibs() throws Exception {
+        final String targetName = "test-junit-platform-lib-excluded";
+        try {
+            buildRule.executeTarget(targetName);
+            Assert.fail(targetName + " was expected to fail since JUnit platform libraries " +
+                    "weren't included in the classpath of the forked JVM");
+        } catch (BuildException be) {
+            // expect a ClassNotFoundException for a JUnit platform class
+            final String cnfeMessage = ClassNotFoundException.class.getName() + ": org.junit.platform";
+            if (!buildRule.getFullLog().contains(cnfeMessage)) {
+                throw be;
+            }
+        }
+        final String exclusionLogMsg = "Excluding JUnit platform libraries";
+        Assert.assertTrue("JUnit platform libraries weren't excluded from classpath", buildRule.getFullLog().contains(exclusionLogMsg));
+    }
+
+    /**
+     * Tests that in a forked mode execution of tests, when the {@code includeAntRuntimeLibraries} attribute
+     * is set to false, then the execution of such tests fails with a classloading error for the Ant runtime
+     * classes
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testExcludeAntRuntimeLibs() throws Exception {
+        final String targetName = "test-junit-ant-runtime-lib-excluded";
+        try {
+            buildRule.executeTarget(targetName);
+            Assert.fail(targetName + " was expected to fail since Ant runtime libraries " +
+                    "weren't included in the classpath of the forked JVM");
+        } catch (BuildException be) {
+            // expect a Error due to missing main class (which is part of Ant runtime libraries
+            // that we excluded)
+            final String missingMainClass = "Could not find or load main class " + StandaloneLauncher.class.getName();
+            if (!buildRule.getFullLog().contains(missingMainClass)) {
+                throw be;
+            }
+        }
+        final String exclusionLogMsg = "Excluding Ant runtime libraries";
+        Assert.assertTrue("Ant runtime libraries weren't excluded from classpath", buildRule.getFullLog().contains(exclusionLogMsg));
+    }
+
+
+    /**
+     * Tests that in a forked mode execution, with {@code includeJUnitPlatformLibraries} attribute set to false
+     * and with the test classpath explicitly including JUnit platform library jars, the tests are executed successfully
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testJUnitPlatformLibsCustomLocation() throws Exception {
+        final String targetName = "test-junit-platform-lib-custom-location";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+        final String exclusionLogMsg = "Excluding JUnit platform libraries";
+        Assert.assertTrue("JUnit platform libraries weren't excluded from classpath", buildRule.getFullLog().contains(exclusionLogMsg));
+        Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", verifySuccess(trackerFile,
+                JupiterSampleTest.class.getName(), "testSucceeds"));
+        Assert.assertTrue("JupiterSampleTest#testFails was expected to fail", verifyFailed(trackerFile,
+                JupiterSampleTest.class.getName(), "testFails"));
+    }
+
+    /**
+     * Tests that in a forked mode execution, with {@code includeAntRuntimeLibraries} attribute set to false
+     * and with the test classpath explicitly including Ant runtime library jars, the tests are executed successfully
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testAntRuntimeLibsCustomLocation() throws Exception {
+        final String targetName = "test-ant-runtime-lib-custom-location";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        setupRuntimeClassesProperty();
+        // run the target
+        buildRule.executeTarget(targetName);
+        final String exclusionLogMsg = "Excluding Ant runtime libraries";
+        Assert.assertTrue("Ant runtime libraries weren't excluded from classpath", buildRule.getFullLog().contains(exclusionLogMsg));
+        Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", verifySuccess(trackerFile,
+                JupiterSampleTest.class.getName(), "testSucceeds"));
+        Assert.assertTrue("JupiterSampleTest#testFails was expected to fail", verifyFailed(trackerFile,
+                JupiterSampleTest.class.getName(), "testFails"));
+        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to fail", verifyFailed(trackerFile,
+                AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
+        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", verifySuccess(trackerFile,
+                ForkedTest.class.getName(), "testSysProp"));
+
+
+    }
+
+    /**
+     * Tests that in a forked mode execution, with {@code includeAntRuntimeLibraries} and {@code includeJUnitPlatformLibraries}
+     * attributes set to false and with the test classpath explicitly including Ant runtime and JUnit platform library jars,
+     * the tests are executed successfully
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testAntAndJUnitPlatformLibsCustomLocation() throws Exception {
+        final String targetName = "test-ant-and-junit-platform-lib-custom-location";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        setupRuntimeClassesProperty();
+        // run the target
+        buildRule.executeTarget(targetName);
+
+        Assert.assertTrue("Ant runtime libraries weren't excluded from classpath",
+                buildRule.getFullLog().contains("Excluding Ant runtime libraries"));
+        Assert.assertTrue("JUnit platform libraries weren't excluded from classpath",
+                buildRule.getFullLog().contains("Excluding JUnit platform libraries"));
+
+        Assert.assertTrue("JUnit4SampleTest#testBar was expected to pass", verifySuccess(trackerFile,
+                JUnit4SampleTest.class.getName(), "testBar"));
+    }
+
+    /**
+     * Tests execution of a test which is configured to execute only methods with a special tag
+     */
+    @Test
+    public void testMethodWithIncludeTag() throws Exception {
+        final String target = "test-method-with-include-tag";
+        final Path tracker2 = setupTrackerProperty(target);
+        buildRule.executeTarget(target);
+        // verify only that specific method was run
+        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisExecuted"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecuted"));
+    }
+
+    /**
+     * Tests execution of a test which is configured to execute only methods without special tags
+     */
+    @Test
+    public void testMethodWithExcludeTag() throws Exception {
+        final String target = "test-method-with-exclude-tag";
+        final Path tracker2 = setupTrackerProperty(target);
+        buildRule.executeTarget(target);
+        // verify only that specific method was run
+        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisExecuted"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecuted"));
+    }
+
+    /**
+     * Tests execution of a test which is configured to execute only methods with special tags, two classes specified
+     */
+    @Test
+    public void testMethodWithTag2Classes() throws Exception {
+        final String target = "test-method-with-tag-2-classes";
+        final Path tracker1 = setupTrackerProperty(target + "1");
+
+        final Path tracker2 = setupTrackerProperty(target + "2");
+
+        buildRule.executeTarget(target);
+        // verify only that specific method was run
+        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be run", wasTestRun(tracker1, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisExecuted"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be run", wasTestRun(tracker1, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecuted"));
+        Assert.assertTrue("testMethodIncludeTagisExecutedTagSampleTest was expected to be run", wasTestRun(tracker2, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisExecutedTagSampleTest"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was expected NOT to be run", wasTestRun(tracker2, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecutedTagSampleTest"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 was expected NOT to be run", wasTestRun(tracker2, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecutedTagSampleTest2"));
+    }
+    
+
+    /**
+     * Tests that failure at with beforeall stops the build 
+     */
+    @Test
+    public void testBeforeAllFailureStopsBuild() throws Exception {
+        final String targetName = "test-beforeall-failure-stops-build";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        try {
+            buildRule.executeTarget(targetName);
+            Assert.fail(targetName + " was expected to fail");
+        } catch (BuildException e) {
+            // expected, but do further tests to make sure the build failed for expected reason
+            if (!verifySetupFailed(trackerFile, JupiterSampleTestFailingBeforeAll.class.getName())) {
+                // throw back the original cause
+                throw e;
+            }
+        }
+    }
+    
+    /**
+     * Tests that when a test, that's isn't configured with {@code haltOnFailure=true}, continues the
+     * build even when there are test failures
+     */
+    @Test
+    public void testBeforeAllFailureContinuesBuild() throws Exception {
+        final String targetName = "test-beforeall-failure-continues-build";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+        Assert.assertTrue("Expected @BeforeAll failure to lead to failing testcase", verifySetupFailed(trackerFile, JupiterSampleTestFailingBeforeAll.class.getName()));
+    }
+
+
+    /**
+     * Tests execution of a test which is configured to execute only methods with special tags, two classes specified
+     */
+    @Test
+    public void testMethodWithTagFileSet() throws Exception {
+        final String target = "test-method-with-tag-fileset";
+        final Path tracker = setupTrackerProperty(target);
+
+        buildRule.executeTarget(target);
+        // verify only that specific method was run
+        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisExecuted"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecuted"));
+        Assert.assertTrue("testMethodIncludeTagisExecutedTagSampleTest was expected to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisExecutedTagSampleTest"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was expected NOT to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecutedTagSampleTest"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 was expected NOT to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecutedTagSampleTest2"));
+    }
+
+    /**
+     * Tests execution of a test which is configured to execute only methods with special tags, two classes specified
+     */
+    @Test
+    public void testMethodWithTagFileSetFork() throws Exception {
+        final String target = "test-method-with-tag-fileset-fork";
+        final Path tracker = setupTrackerProperty(target);
+
+        buildRule.executeTarget(target);
+
+        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisExecuted"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecuted"));
+        Assert.assertTrue("testMethodIncludeTagisExecutedTagSampleTest was expected to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisExecutedTagSampleTest"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was expected NOT to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecutedTagSampleTest"));
+        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 was expected NOT to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+                "testMethodIncludeTagisNotExecutedTagSampleTest2"));
+
+        // Do it in the test, cause otherwise the file will be too big
+        Files.deleteIfExists(tracker);
+    }
+
+
+    /**
+     * Tests that the forked test works fine when the {@code testclasses} element is used
+     * as a sibling of a {@code listener} element
+     */
+    @Test
+    public void testBz63958() throws Exception {
+        final String targetName = "bz-63958";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+
+        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", verifySuccess(trackerFile,
+                ForkedTest.class.getName(), "testSysProp"));
+    }
+
+    private Path setupTrackerProperty(final String targetName) {
+        final String filename = targetName + "-tracker.txt";
+        buildRule.getProject().setProperty(targetName + ".tracker", filename);
+        final String outputDir = buildRule.getProject().getProperty("output.dir");
+        return Paths.get(outputDir, filename);
+    }
+
+    private void setupRuntimeClassesProperty() {
+        // setup a property that points to the locations of Ant runtime classes.
+        // this path will then be used in target to create a duplicate copied
+        // classes and then will be used as a custom location for Ant runtime libraries
+        final String projectResourceName = LoaderUtils.classNameToResource(Project.class.getName());
+        final File antClassesPath = LoaderUtils.getResourceSource(Project.class.getClassLoader(), projectResourceName);
+        buildRule.getProject().setProperty("ant.runtime.classes.original.path", antClassesPath.getAbsolutePath());
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatterTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatterTest.java
new file mode 100644
index 0000000..b2123d1
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatterTest.java
@@ -0,0 +1,102 @@
+/*
+ *  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
+ *
+ *      https://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.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.junit.Test;
+import org.junit.platform.engine.ConfigurationParameters;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Properties;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+
+public class LegacyXmlResultFormatterTest {
+
+    private static final String KEY = "key";
+    private static final String ORIG = "<\u0000&>foo";
+    private static final String ENCODED = "&lt;&amp;#0;&amp;&gt;foo";
+
+    private final LegacyXmlResultFormatter f = new LegacyXmlResultFormatter();
+
+    @Test
+    public void encodesAttributesProperly() throws Exception {
+        final TestPlan plan = startTest(true);
+        final String result = finishTest(plan);
+        assertThat(result, containsString("=\"" + ENCODED + "\""));
+    }
+
+    @Test
+    public void encodesSysOutProperly() throws Exception {
+        final TestPlan plan = startTest(false);
+        f.sysOutAvailable(ORIG.getBytes(StandardCharsets.UTF_8));
+        final String result = finishTest(plan);
+        assertThat(result, containsString(ENCODED));
+    }
+
+    private TestPlan startTest(final boolean withProperties) {
+        f.setContext(new TestExecutionContext() {
+            @Override
+            public Properties getProperties() {
+                final Properties p = new Properties();
+                if (withProperties) {
+                    p.setProperty(KEY, ORIG);
+                }
+                return p;
+            }
+
+            @Override
+            public Optional<Project> getProject() {
+                return Optional.empty();
+            }
+        });
+        final ConfigurationParameters dummyParams = new ConfigurationParameters() {
+            @Override
+            public Optional<String> get(String key) {
+                return Optional.empty();
+            }
+
+            @Override
+            public Optional<Boolean> getBoolean(String key) {
+                return Optional.empty();
+            }
+
+            @Override
+            public int size() {
+                return 0;
+            }
+        };
+        final TestPlan testPlan = TestPlan.from(Collections.emptySet(), dummyParams);
+        f.testPlanExecutionStarted(testPlan);
+        return testPlan;
+    }
+
+    private String finishTest(final TestPlan testPlan) throws IOException {
+        try (final ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+            f.setDestination(bos);
+            f.testPlanExecutionFinished(testPlan);
+            return new String(bos.toByteArray(), StandardCharsets.UTF_8);
+        }
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java
index edca693..d33d48b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,10 +17,10 @@
  */
 package org.apache.tools.ant.taskdefs.optional.net;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
 import java.io.IOException;
@@ -44,7 +44,6 @@
 import org.apache.tools.ant.util.regexp.RegexpMatcher;
 import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -64,20 +63,18 @@
 
     private String loginFailureMessage;
 
-    private String tmpDir = null;
     private String remoteTmpDir = null;
-    private String ftpFileSep = null;
-    private myFTP myFTPTask = new myFTP();
 
+    private myFTP myFTPTask = new myFTP();
 
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/net/ftp.xml");
         Project project = buildRule.getProject();
         project.executeTarget("setup");
-        tmpDir = project.getProperty("tmp.dir");
+        String tmpDir = project.getProperty("tmp.dir");
         ftp = new FTPClient();
-        ftpFileSep = project.getProperty("ftp.filesep");
+        String ftpFileSep = project.getProperty("ftp.filesep");
         myFTPTask.setSeparator(ftpFileSep);
         myFTPTask.setProject(project);
         remoteTmpDir = myFTPTask.resolveFile(tmpDir);
@@ -127,8 +124,8 @@
 
     @Test
     public void test1() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
 
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
@@ -139,8 +136,8 @@
 
     @Test
     public void test2() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/"});
@@ -151,8 +148,8 @@
 
     @Test
     public void test3() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.scan();
@@ -162,8 +159,8 @@
 
     @Test
     public void testFullPathMatchesCaseSensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/beta/gamma/GAMMA.XML"});
@@ -173,8 +170,8 @@
 
     @Test
     public void testFullPathMatchesCaseInsensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setCaseSensitive(false);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
@@ -185,8 +182,8 @@
 
     @Test
     public void test2ButCaseInsensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"ALPHA/"});
@@ -198,8 +195,8 @@
 
     @Test
     public void test2bisButCaseInsensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/BETA/gamma/"});
@@ -212,8 +209,8 @@
     @Test
     public void testGetWithSelector() {
         buildRule.executeTarget("ftp-get-with-selector");
-        assertContains("selectors are not supported in remote filesets", buildRule.getLog());
-        FileSet fsDestination = (FileSet) buildRule.getProject().getReference("fileset-destination-without-selector");
+        assertThat(buildRule.getLog(), containsString("selectors are not supported in remote filesets"));
+        FileSet fsDestination = buildRule.getProject().getReference("fileset-destination-without-selector");
         DirectoryScanner dsDestination = fsDestination.getDirectoryScanner(buildRule.getProject());
         dsDestination.scan();
         String[] sortedDestinationDirectories = dsDestination.getIncludedDirectories();
@@ -226,7 +223,7 @@
             sortedDestinationFiles[counter] =
                 sortedDestinationFiles[counter].replace(File.separatorChar, '/');
         }
-        FileSet fsSource =  (FileSet) buildRule.getProject().getReference("fileset-source-without-selector");
+        FileSet fsSource = buildRule.getProject().getReference("fileset-source-without-selector");
         DirectoryScanner dsSource = fsSource.getDirectoryScanner(buildRule.getProject());
         dsSource.scan();
         compareFiles(dsSource, sortedDestinationFiles, sortedDestinationDirectories);
@@ -234,9 +231,9 @@
 
     @Test
     public void testGetFollowSymlinksTrue() {
-        Assume.assumeTrue("System does not support Symlinks", supportsSymlinks);
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue("System does not support Symlinks", supportsSymlinks);
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         buildRule.getProject().executeTarget("ftp-get-directory-symbolic-link");
         FileSet fsDestination = buildRule.getProject().getReference("fileset-destination-without-selector");
         DirectoryScanner dsDestination = fsDestination.getDirectoryScanner(buildRule.getProject());
@@ -247,11 +244,11 @@
 
     @Test
     public void testGetFollowSymlinksFalse() {
-        Assume.assumeTrue("System does not support Symlinks", supportsSymlinks);
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue("System does not support Symlinks", supportsSymlinks);
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         buildRule.getProject().executeTarget("ftp-get-directory-no-symbolic-link");
-        FileSet fsDestination = (FileSet) buildRule.getProject().getReference("fileset-destination-without-selector");
+        FileSet fsDestination = buildRule.getProject().getReference("fileset-destination-without-selector");
         DirectoryScanner dsDestination = fsDestination.getDirectoryScanner(buildRule.getProject());
         dsDestination.scan();
         compareFiles(dsDestination, new String[] {}, new String[] {});
@@ -259,9 +256,9 @@
 
     @Test
     public void testAllowSymlinks() {
-        Assume.assumeTrue("System does not support Symlinks", supportsSymlinks);
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue("System does not support Symlinks", supportsSymlinks);
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         buildRule.getProject().executeTarget("symlink-setup");
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
@@ -274,9 +271,9 @@
 
     @Test
     public void testProhibitSymlinks() {
-        Assume.assumeTrue("System does not support Symlinks", supportsSymlinks);
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue("System does not support Symlinks", supportsSymlinks);
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         buildRule.getProject().executeTarget("symlink-setup");
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
@@ -288,9 +285,9 @@
 
     @Test
     public void testFileSymlink() {
-        Assume.assumeTrue("System does not support Symlinks", supportsSymlinks);
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue("System does not support Symlinks", supportsSymlinks);
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         buildRule.getProject().executeTarget("symlink-file-setup");
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
@@ -304,8 +301,8 @@
     // father and child pattern test
     @Test
     public void testOrderOfIncludePatternsIrrelevant() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         String[] expectedFiles = {"alpha/beta/beta.xml", "alpha/beta/gamma/gamma.xml"};
         String[] expectedDirectories = {"alpha/beta", "alpha/beta/gamma" };
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
@@ -323,8 +320,8 @@
 
     @Test
     public void testPatternsDifferInCaseScanningSensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/"});
@@ -335,8 +332,8 @@
 
     @Test
     public void testPatternsDifferInCaseScanningInsensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/"});
@@ -348,8 +345,8 @@
 
     @Test
     public void testFullpathDiffersInCaseScanningSensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/beta/gamma/gamma.xml", "alpha/beta/gamma/GAMMA.XML"});
@@ -359,8 +356,8 @@
 
     @Test
     public void testFullpathDiffersInCaseScanningInsensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {
@@ -375,8 +372,8 @@
 
     @Test
     public void testParentDiffersInCaseScanningSensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/beta/"});
@@ -388,8 +385,8 @@
 
     @Test
     public void testParentDiffersInCaseScanningInsensitive() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/", "ALPHA/beta/"});
@@ -401,8 +398,8 @@
 
     @Test
     public void testExcludeOneFile() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"**/*.xml"});
@@ -413,8 +410,8 @@
 
     @Test
     public void testExcludeHasPrecedence() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/**"});
@@ -425,8 +422,8 @@
 
     @Test
     public void testAlternateIncludeExclude() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setIncludes(new String[] {"alpha/**", "alpha/beta/gamma/**"});
@@ -437,8 +434,8 @@
 
     @Test
     public void testAlternateExcludeInclude() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setExcludes(new String[] {"alpha/**", "alpha/beta/gamma/**"});
@@ -452,8 +449,8 @@
      */
     @Test
     public void testChildrenOfExcludedDirectory() {
-        Assume.assumeTrue(loginFailureMessage, loginSucceeded);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue(loginFailureMessage, loginSucceeded);
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         buildRule.getProject().executeTarget("children-of-excluded-dir-setup");
         FTP.FTPDirectoryScanner ds = myFTPTask.newScanner(ftp);
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
@@ -462,7 +459,7 @@
         compareFiles(ds, new String[] {"delta/delta.xml"}, new String[] {"delta"});
 
         ds = myFTPTask.newScanner(ftp);
-        Assume.assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
+        assumeTrue("Could not change remote directory", changeRemoteDir(remoteTmpDir));
         ds.setBasedir(new File(buildRule.getProject().getBaseDir(), "tmp"));
         ds.setExcludes(new String[] {"alpha"});
         ds.scan();
@@ -478,7 +475,7 @@
      * to parse the log output.
      */
     private class CountLogListener extends DefaultLogger {
-        private Vector lastMatchGroups = null;
+        private Vector<String> lastMatchGroups = null;
         private RegexpMatcher matcher = new RegexpMatcherFactory().newRegexpMatcher();
 
         /**
@@ -514,7 +511,7 @@
             if (this.lastMatchGroups == null) {
                 return -1;
             }
-            return Integer.parseInt((String) this.lastMatchGroups.get(1));
+            return Integer.parseInt(this.lastMatchGroups.get(1));
         }
     }
 
@@ -523,11 +520,10 @@
      * of times a message has been emitted.
      */
     private class LogCounter extends DefaultLogger {
-        private Map searchMap = new HashMap();
-        private int matchCount;
+        private Map<String, Integer> searchMap = new HashMap<>();
 
         public void addLogMessageToSearch(String message) {
-            searchMap.put(message, Integer.valueOf(0));
+            searchMap.put(message, 0);
         }
 
         /*
@@ -535,9 +531,9 @@
          */
         public void messageLogged(BuildEvent event) {
             String message = event.getMessage();
-            Integer mcnt = (Integer) searchMap.get(message);
+            Integer mcnt = searchMap.get(message);
             if (null != mcnt) {
-                searchMap.put(message, Integer.valueOf(mcnt.intValue() + 1));
+                searchMap.put(message, mcnt + 1);
             }
             super.messageLogged(event);
         }
@@ -547,9 +543,9 @@
          * to the log
          */
         public int getMatchCount(String message) {
-            Integer mcnt = (Integer) searchMap.get(message);
+            Integer mcnt = searchMap.get(message);
             if (null != mcnt) {
-                return mcnt.intValue();
+                return mcnt;
             }
             return 0;
         }
@@ -614,16 +610,15 @@
     }
 
     @Test
-    public void testConfigurationLang() {
+    public void testConfigurationGoodLang() {
         int[] expectedCounts = {1, 1, 0, 0, 0, 0, 1};
         performConfigTest("configuration.lang.good", expectedCounts);
+    }
 
-        try {
-            performConfigTest("configuration.lang.bad", expectedCounts);
-            fail("BuildException Expected");
-        } catch (Exception bx) {
-            assertTrue(bx instanceof BuildException);
-        }
+    @Test(expected = BuildException.class)
+    public void testConfigurationBadLang() {
+        int[] expectedCounts = {1, 1, 0, 0, 0, 0, 1};
+        performConfigTest("configuration.lang.bad", expectedCounts);
     }
     /**
      * Tests the systemTypeKey attribute.
@@ -646,9 +641,7 @@
                 "custom config: server language code = de"
         };
         LogCounter counter = new LogCounter();
-        for (String message : messages) {
-            counter.addLogMessageToSearch(message);
-        }
+        Arrays.stream(messages).forEach(counter::addLogMessageToSearch);
 
         buildRule.getProject().addBuildListener(counter);
         buildRule.getProject().executeTarget(target);
@@ -755,44 +748,32 @@
         }
     }
 
+    @Test
     public void testGetWithSelectorRetryable1() {
         buildRule.getProject().addTaskDefinition("ftp", oneFailureFTP.class);
-        try {
-            buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
-        } catch (BuildException bx) {
-            fail("Two retries expected, failed after one.");
-        }
+        buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
     }
 
     @Test
     public void testGetWithSelectorRetryable2() {
         buildRule.getProject().addTaskDefinition("ftp", twoFailureFTP.class);
-        try {
-            buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
-        } catch (BuildException bx) {
-            fail("Two retries expected, failed after two.");
-        }
+        buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
     }
 
-    @Test
+    /**
+     * Two retries expected, continued after two.
+     */
+    @Test(expected = BuildException.class)
     public void testGetWithSelectorRetryable3() {
         buildRule.getProject().addTaskDefinition("ftp", threeFailureFTP.class);
-        try {
-            buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
-            fail("Two retries expected, continued after two.");
-        } catch (BuildException bx) {
-        }
+        buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
     }
 
     @Test
     public void testGetWithSelectorRetryableRandom() {
         buildRule.getProject().addTaskDefinition("ftp", randomFailureFTP.class);
-        try {
-            buildRule.getProject().setProperty("ftp.retries", "forever");
-            buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
-        } catch (BuildException bx) {
-            fail("Retry forever specified, but failed.");
-        }
+        buildRule.getProject().setProperty("ftp.retries", "forever");
+        buildRule.getProject().executeTarget("ftp-get-with-selector-retryable");
     }
 
     @Test
@@ -809,12 +790,9 @@
         String[] messages = new String[]{
                 "Doing Site Command: umask 222",
                 "Failed to issue Site Command: umask 222",
-
         };
         LogCounter counter = new LogCounter();
-        for (String message : messages) {
-            counter.addLogMessageToSearch(message);
-        }
+        Arrays.stream(messages).forEach(counter::addLogMessageToSearch);
 
         buildRule.getProject().addBuildListener(counter);
         buildRule.getProject().executeTarget(target);
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/ScriptDefTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/ScriptDefTest.java
index bfba298..2a39535 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/ScriptDefTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/ScriptDefTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,20 +17,23 @@
  */
 package org.apache.tools.ant.taskdefs.optional.script;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.condition.JavaVersion;
 import org.apache.tools.ant.types.FileSet;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.File;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Tests the examples of the &lt;scriptdef&gt; task.
@@ -42,6 +45,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/script/scriptdef.xml");
@@ -52,34 +58,33 @@
         buildRule.executeTarget("simple");
         // get the fileset and its basedir
         Project p = buildRule.getProject();
-        FileSet fileset = (FileSet) p.getReference("testfileset");
+        FileSet fileset = p.getReference("testfileset");
         File baseDir = fileset.getDir(p);
         String log = buildRule.getLog();
-        assertTrue("Expecting attribute value printed",
-                log.contains("Attribute attr1 = test"));
-
-        assertTrue("Expecting nested element value printed",
-                log.contains("Fileset basedir = " + baseDir.getAbsolutePath()));
+        assertThat("Expecting attribute value printed", log,
+                containsString("Attribute attr1 = test"));
+        assertThat("Expecting nested element value printed", log,
+                containsString("Fileset basedir = " + baseDir.getAbsolutePath()));
     }
 
+    /**
+     * Expected failure due to lacking language attribute
+     */
     @Test
     public void testNoLang() {
-        try {
-            buildRule.executeTarget("nolang");
-            fail("Absence of language attribute not detected");
-        } catch(BuildException ex) {
-            AntAssert.assertContains("requires a language attribute", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("requires a language attribute");
+        buildRule.executeTarget("nolang");
     }
 
+    /**
+     * Expected failure due to lacking name attribute
+     */
     @Test
     public void testNoName() {
-        try {
-            buildRule.executeTarget("noname");
-            fail("Absence of name attribute not detected");
-        } catch(BuildException ex) {
-            AntAssert.assertContains("scriptdef requires a name attribute", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("scriptdef requires a name attribute");
+        buildRule.executeTarget("noname");
     }
 
     @Test
@@ -87,14 +92,13 @@
         buildRule.executeTarget("nestedbyclassname");
         // get the fileset and its basedir
         Project p = buildRule.getProject();
-        FileSet fileset = (FileSet) p.getReference("testfileset");
+        FileSet fileset = p.getReference("testfileset");
         File baseDir = fileset.getDir(p);
         String log = buildRule.getLog();
-        assertTrue("Expecting attribute value to be printed",
-                log.contains("Attribute attr1 = test"));
-
-        assertTrue("Expecting nested element value to be printed",
-                log.contains("Fileset basedir = " + baseDir.getAbsolutePath()));
+        assertThat("Expecting attribute value to be printed", log,
+                containsString("Attribute attr1 = test"));
+        assertThat("Expecting nested element value to be printed", log,
+                containsString("Fileset basedir = " + baseDir.getAbsolutePath()));
     }
 
     @Test
@@ -105,40 +109,83 @@
 
     @Test
     public void testException() {
-        try {
-            buildRule.executeTarget("exception");
-            fail("Should have thrown an exception in the script");
-        } catch(BuildException ex) {
-            AntAssert.assertContains("TypeError", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("TypeError");
+        buildRule.executeTarget("exception");
     }
 
     @Test
     public void testDoubleDef() {
         buildRule.executeTarget("doubledef");
         String log = buildRule.getLog();
-        assertTrue("Task1 did not execute", log.contains("Task1"));
-        assertTrue("Task2 did not execute", log.contains("Task2"));
+        assertThat("Task1 did not execute", log, containsString("Task1"));
+        assertThat("Task2 did not execute", log, containsString("Task2"));
     }
 
+    /**
+     * Expected failure due to duplicate attribute definition
+     */
     @Test
     public void testDoubleAttribute() {
-        try {
-            buildRule.executeTarget("doubleAttributeDef");
-            fail("Should have detected duplicate attirbute definition");
-        } catch(BuildException ex) {
-            AntAssert.assertContains("attr1 attribute more than once", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("attr1 attribute more than once");
+        buildRule.executeTarget("doubleAttributeDef");
     }
 
     @Test
     public void testProperty() {
         buildRule.executeTarget("property");
-        // get the fileset and its basedir
-        String log = buildRule.getLog();
-        assertTrue("Expecting property in attribute value replaced",
-                log.contains("Attribute value = test"));
+        assertThat("Expecting property in attribute value replaced",
+                buildRule.getLog(), containsString("Attribute value = test"));
     }
 
+    @Test
+    public void testUseSrcAndEncoding() {
+        final String readerEncoding = "UTF-8";
+        buildRule.getProject().setProperty("useSrcAndEncoding.reader.encoding", readerEncoding);
+        buildRule.executeTarget("useSrcAndEncoding");
+    }
 
+    @Test
+    public void testUseSrcAndEncodingFailure() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("expected <eacute [\u00e9]> but was <eacute [\u00c3\u00a9]>");
+        final String readerEncoding = "ISO-8859-1";
+        buildRule.getProject().setProperty("useSrcAndEncoding.reader.encoding", readerEncoding);
+        buildRule.executeTarget("useSrcAndEncoding");
+    }
+
+    @Test
+    public void testUseCompiled() {
+        final JavaVersion atMostJava14 = new JavaVersion();
+        atMostJava14.setAtMost("14");
+        // skip execution since this compilation timing based test consistently fails starting Java 15 (where we use
+        // Graal libraries for Javascript engine)
+        Assume.assumeTrue("Skipping test execution since Java version is greater than Java 14", atMostJava14.eval());
+
+        // warm everything up:
+        buildRule.executeTarget("useNotCompiled");
+
+        final long duration;
+        {
+            long start = System.nanoTime();
+            buildRule.executeTarget("useCompiled");
+            duration = System.nanoTime() - start;
+        }
+
+        final long notCompiledDuration;
+        {
+            long start = System.nanoTime();
+            buildRule.executeTarget("useNotCompiled");
+            notCompiledDuration = System.nanoTime() - start;
+        }
+
+        assertTrue(
+            String.format(
+                "Compiled scripts should run faster (%d ns) than not compiled (%d ns) scripts.",
+                duration, notCompiledDuration
+	        ), 
+            duration < notCompiledDuration
+        );
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/AbstractNashornCompatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/AbstractNashornCompatTest.java
new file mode 100644
index 0000000..25123d2
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/AbstractNashornCompatTest.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
+ *
+ *      https://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.script.graal;
+
+import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+
+public class AbstractNashornCompatTest {
+
+    private final String magicPropertyValue;
+
+    public AbstractNashornCompatTest(String magicPropertyValue) {
+        this.magicPropertyValue = magicPropertyValue;
+    }
+
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
+
+    @Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/script/graal.xml");
+        buildRule.getProject().setProperty(MagicNames.DISABLE_NASHORN_COMPAT, magicPropertyValue);
+    }
+
+    @Test
+    public void runSquaresTest() {
+        buildRule.executeTarget("run-squares-test");
+        assertThat("Expecting the square of 7 to be logged", buildRule.getLog(),
+            containsString("49"));
+    }
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DefaultNashornCompatTest.java
similarity index 74%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DefaultNashornCompatTest.java
index 9d6fcba..a5c1771 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DefaultNashornCompatTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,11 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package org.apache.tools.ant.taskdefs.optional.script.graal;
+
+public class DefaultNashornCompatTest extends AbstractNashornCompatTest {
+
+    public DefaultNashornCompatTest() {
+        super(null);
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DisableNashornCompatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DisableNashornCompatTest.java
new file mode 100644
index 0000000..808bdee
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DisableNashornCompatTest.java
@@ -0,0 +1,41 @@
+/*
+ *  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
+ *
+ *      https://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.script.graal;
+
+import org.apache.tools.ant.BuildException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class DisableNashornCompatTest extends AbstractNashornCompatTest {
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    public DisableNashornCompatTest() {
+        super("true");
+    }
+
+    @Test
+    @Override
+    public void runSquaresTest() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("TypeError");
+        super.runSquaresTest();
+    }
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/EnableNashornCompatTest.java
similarity index 74%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/EnableNashornCompatTest.java
index 9d6fcba..2161b6f 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/EnableNashornCompatTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,11 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package org.apache.tools.ant.taskdefs.optional.script.graal;
+
+public class EnableNashornCompatTest extends AbstractNashornCompatTest {
+
+    public EnableNashornCompatTest() {
+        super("false");
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/sos/SOSTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/sos/SOSTest.java
index 3e8caf5..a8eb350 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/sos/SOSTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/sos/SOSTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,9 +28,9 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  *  Testcase to ensure that command line generation and required attributes are
@@ -55,7 +55,11 @@
     private static final String VERSION = "007";
 
     @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
     public BuildFileRule buildRule = new BuildFileRule();
+
     private Project project;
 
     @Before
@@ -136,10 +140,10 @@
     @Test
     public void testGetExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/sos/sos.xml");
-        expectSpecificBuildException("sosget.1", "some cause", "sosserverpath attribute must be set!");
-        expectSpecificBuildException("sosget.2", "some cause", "username attribute must be set!");
-        expectSpecificBuildException("sosget.3", "some cause", "vssserverpath attribute must be set!");
-        expectSpecificBuildException("sosget.4", "some cause", "projectpath attribute must be set!");
+        expectSpecificBuildException("sosget.1", "sosserverpath attribute must be set!");
+        expectSpecificBuildException("sosget.2", "username attribute must be set!");
+        expectSpecificBuildException("sosget.3", "vssserverpath attribute must be set!");
+        expectSpecificBuildException("sosget.4", "projectpath attribute must be set!");
     }
 
     /**  Test CheckInFile option flags  */
@@ -205,10 +209,10 @@
     @Test
     public void testCheckinExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/sos/sos.xml");
-        expectSpecificBuildException("soscheckin.1", "some cause", "sosserverpath attribute must be set!");
-        expectSpecificBuildException("soscheckin.2", "some cause", "username attribute must be set!");
-        expectSpecificBuildException("soscheckin.3", "some cause", "vssserverpath attribute must be set!");
-        expectSpecificBuildException("soscheckin.4", "some cause", "projectpath attribute must be set!");
+        expectSpecificBuildException("soscheckin.1", "sosserverpath attribute must be set!");
+        expectSpecificBuildException("soscheckin.2", "username attribute must be set!");
+        expectSpecificBuildException("soscheckin.3", "vssserverpath attribute must be set!");
+        expectSpecificBuildException("soscheckin.4", "projectpath attribute must be set!");
     }
 
     /**  Test CheckOutFile option flags  */
@@ -272,10 +276,10 @@
     @Test
     public void testCheckoutExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/sos/sos.xml");
-        expectSpecificBuildException("soscheckout.1", "some cause", "sosserverpath attribute must be set!");
-        expectSpecificBuildException("soscheckout.2", "some cause", "username attribute must be set!");
-        expectSpecificBuildException("soscheckout.3", "some cause", "vssserverpath attribute must be set!");
-        expectSpecificBuildException("soscheckout.4", "some cause", "projectpath attribute must be set!");
+        expectSpecificBuildException("soscheckout.1", "sosserverpath attribute must be set!");
+        expectSpecificBuildException("soscheckout.2", "username attribute must be set!");
+        expectSpecificBuildException("soscheckout.3", "vssserverpath attribute must be set!");
+        expectSpecificBuildException("soscheckout.4", "projectpath attribute must be set!");
     }
 
     /**  Test Label option flags  */
@@ -308,21 +312,18 @@
     @Test
     public void testLabelExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/sos/sos.xml");
-        expectSpecificBuildException("soslabel.1", "some cause", "sosserverpath attribute must be set!");
-        expectSpecificBuildException("soslabel.2", "some cause", "username attribute must be set!");
-        expectSpecificBuildException("soslabel.3", "some cause", "vssserverpath attribute must be set!");
-        expectSpecificBuildException("soslabel.4", "some cause", "projectpath attribute must be set!");
-        expectSpecificBuildException("soslabel.5", "some cause", "label attribute must be set!");
+        expectSpecificBuildException("soslabel.1", "sosserverpath attribute must be set!");
+        expectSpecificBuildException("soslabel.2", "username attribute must be set!");
+        expectSpecificBuildException("soslabel.3", "vssserverpath attribute must be set!");
+        expectSpecificBuildException("soslabel.4", "projectpath attribute must be set!");
+        expectSpecificBuildException("soslabel.5", "label attribute must be set!");
     }
 
-    private void expectSpecificBuildException(String target, String errorMessage,
+    private void expectSpecificBuildException(String target,
                                               String exceptionMessage) {
-        try {
-            buildRule.executeTarget(target);
-            fail(errorMessage);
-        } catch (BuildException ex) {
-            assertEquals(exceptionMessage, ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(exceptionMessage);
+        buildRule.executeTarget(target);
     }
 
     /**
@@ -334,18 +335,9 @@
      */
     private void checkCommandLines(String[] sTestCmdLine, String[] sGeneratedCmdLine) {
         int length = sTestCmdLine.length;
+        assertEquals("number of arguments doesn't match", length, sGeneratedCmdLine.length);
         for (int i = 0; i < length; i++) {
-            try {
-                assertEquals("arg # " + String.valueOf(i),
-                        sTestCmdLine[i],
-                        sGeneratedCmdLine[i]);
-            } catch (ArrayIndexOutOfBoundsException aioob) {
-                fail("missing arg " + sTestCmdLine[i]);
-            }
-        }
-        if (sGeneratedCmdLine.length > sTestCmdLine.length) {
-            // We have extra elements
-            fail("extra args");
+            assertEquals("arg # " + i, sTestCmdLine[i], sGeneratedCmdLine[i]);
         }
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/splash/SplashScreenTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/splash/SplashScreenTest.java
index dfec9f5..f460fc3 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/splash/SplashScreenTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/splash/SplashScreenTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ssh/ScpTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ssh/ScpTest.java
index 1c2a17d..832520f 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ssh/ScpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/ssh/ScpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -39,7 +39,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNotNull;
 
 /**
  * This is a unit test for the Scp task in Ant.  It must be
@@ -65,7 +65,7 @@
     private int port = Integer.parseInt(System.getProperty("scp.port", "22"));
     private String knownHosts = System.getProperty("scp.known.hosts");
 
-    private List<File> cleanUpList = new ArrayList<File>();
+    private List<File> cleanUpList = new ArrayList<>();
 
     @Before
     public void setUp() {
@@ -78,13 +78,12 @@
 
     @After
     public void tearDown() {
-        for (File file : cleanUpList) {
-            file.delete();
-        }
+        cleanUpList.forEach(File::delete);
     }
 
     @Test
     public void testSingleFileUploadAndDownload() throws IOException {
+        assumeNotNull("system property scp.host must be set", sshHostUri);
         assertNotNull("system property scp.tmp must be set", tempDir);
         File uploadFile = createTemporaryFile();
 
@@ -110,8 +109,9 @@
 
     @Test
     public void testMultiUploadAndDownload() throws IOException {
+        assumeNotNull("system property scp.host must be set", sshHostUri);
         assertNotNull("system property scp.tmp must be set", tempDir);
-        List<File> uploadList = new ArrayList<File>();
+        List<File> uploadList = new ArrayList<>();
         for (int i = 0; i < 5; i++) {
             uploadList.add(createTemporaryFile());
         }
@@ -146,8 +146,9 @@
 
     @Test
     public void testMultiResourceCollectionUpload() throws IOException {
+        assumeNotNull("system property scp.host must be set", sshHostUri);
         assertNotNull("system property scp.tmp must be set", tempDir);
-        List uploadList = new ArrayList();
+        List<File> uploadList = new ArrayList<>();
         for (int i = 0; i < 5; i++) {
             uploadList.add(createTemporaryFile());
         }
@@ -172,22 +173,17 @@
         scpTask.execute();
     }
 
+    /**
+     * Expected failure due to invalid remoteToDir
+     */
+    @Test(expected = BuildException.class)
+    public void testInvalidRemoteToDir() {
+        scpTask.setRemoteTodir("host:/a/path/without/an/at");
+    }
+
     @Test
-    public void testRemoteToDir() throws IOException {
-
-        // first try an invalid URI
-        try {
-            scpTask.setRemoteTodir("host:/a/path/without/an/at");
-            fail("Expected a BuildException to be thrown due to invalid"
-                    + " remoteToDir");
-        } catch (BuildException e) {
-            // expected
-            //TODO we should be asserting a value in here
-        }
-
-        // And this one should work
+    public void testRemoteToDir() {
         scpTask.setRemoteTodir("user:password@host:/a/path/with/an/at");
-        // no exception
     }
 
     private void addCleanup(File file) {
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java
index b5f4bbf..8d3b574 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -35,17 +35,21 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.util.SymbolicLinkUtils;
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+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.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
 /**
  * Test cases for the Symlink task. Link creation, link deletion, recording
@@ -61,11 +65,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
-    private boolean supportsSymlinks = Os.isFamily("unix");
-
     @Before
     public void setUp() {
-        Assume.assumeTrue("Symlinks not supported on current operating system", supportsSymlinks);
+        assumeTrue("Symlinks not supported on current operating system", Os.isFamily("unix"));
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/unix/symlink.xml");
         buildRule.executeTarget("setUp");
     }
@@ -84,12 +86,10 @@
     public void testDelete() {
         buildRule.executeTarget("test-delete");
         Project p = buildRule.getProject();
-        String linkDeleted = p.getProperty("test.delete.link.still.there");
         assertNotNull("Actual file deleted by symlink",
                       p.getProperty("test.delete.file.still.there"));
-        if (linkDeleted != null) {
-            fail(linkDeleted);
-        }
+        String linkDeleted = p.getProperty("test.delete.link.still.there");
+        assertNull(linkDeleted, linkDeleted);
     }
 
     @Test
@@ -140,11 +140,7 @@
                       p.getProperty("test.record.dir2.recorded"));
 
         String dir3rec = p.getProperty("test.record.dir3.recorded");
-
-        if (dir3rec != null) {
-            fail(dir3rec);
-        }
-
+        assertNull(dir3rec, dir3rec);
     }
 
     @Test
@@ -155,18 +151,12 @@
         String link2Rem = p.getProperty("test.recreate.link2.not.removed");
         String link3Rem = p.getProperty("test.recreate.link3.not.removed");
         String dirlinkRem = p.getProperty("test.recreate.dirlink.not.removed");
-        if (link1Rem != null) {
-            fail(link1Rem);
-        }
-        if (link2Rem != null) {
-            fail(link2Rem);
-        }
-        if (link3Rem != null) {
-            fail(link3Rem);
-        }
-        if (dirlinkRem != null) {
-            fail(dirlinkRem);
-        }
+
+        assertNull(link1Rem, link1Rem);
+        assertNull(link2Rem ,link2Rem);
+        assertNull(link3Rem ,link3Rem);
+        assertNull(dirlinkRem ,dirlinkRem);
+
         assertNotNull("Failed to recreate link1",
                       p.getProperty("test.recreate.link1.recreated"));
         assertNotNull("Failed to recreate link2",
@@ -177,10 +167,7 @@
                       p.getProperty("test.recreate.dirlink.recreated"));
 
         String doubleRecreate = p.getProperty("test.recreate.dirlink2.recreated.twice");
-
-        if (doubleRecreate != null) {
-            fail(doubleRecreate);
-        }
+        assertNull(doubleRecreate, doubleRecreate);
 
         assertNotNull("Failed to alter dirlink3",
                       p.getProperty("test.recreate.dirlink3.was.altered"));
@@ -269,8 +256,8 @@
         assertFalse(f.exists());
         assertFalse(f.isDirectory());
         assertFalse(f.isFile());
-        assertTrue(su.isSymbolicLink(f.getAbsolutePath()) == false);
-        assertTrue(su.isSymbolicLink(f.getParentFile(), f.getName()) == false);
+        assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
+        assertFalse(su.isSymbolicLink(f.getParentFile(), f.getName()));
         assertTrue(su.isDanglingSymbolicLink(f.getAbsolutePath()));
         assertTrue(su.isDanglingSymbolicLink(f.getParentFile(),
                                              f.getName()));
@@ -279,14 +266,33 @@
         assertFalse(f.exists());
         assertFalse(f.isDirectory());
         assertFalse(f.isFile());
-        assertTrue(su.isSymbolicLink(f.getAbsolutePath()) == false);
-        assertTrue(su.isSymbolicLink(f.getParentFile(), f.getName()) == false);
+        assertFalse(su.isSymbolicLink(f.getAbsolutePath()));
+        assertFalse(su.isSymbolicLink(f.getParentFile(), f.getName()));
         assertTrue(su.isDanglingSymbolicLink(f.getAbsolutePath()));
         assertTrue(su.isDanglingSymbolicLink(f.getParentFile(),
                                              f.getName()));
 
     }
 
+    /**
+     * Tests that when {@code symlink} task is used to create a symbolic link and {@code overwrite} option
+     * is {@code false}, then any existing symbolic link at the {@code link} location (whose target is a directory)
+     * doesn't end up create a new symbolic link within the target directory.
+     *
+     * @throws Exception if something goes wrong
+     * @see <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=58683">BZ-58683</a> for more details
+     */
+    @Test
+    public void testOverwriteExistingLink() throws Exception {
+        buildRule.executeTarget("test-overwrite-link");
+        final Project p = buildRule.getProject();
+        final String linkTargetResource = p.getProperty("test.overwrite.link.target.dir");
+        assertNotNull("Property test.overwrite.link.target.dir is not set", linkTargetResource);
+        final Path targetResourcePath = Paths.get(linkTargetResource);
+        assertTrue(targetResourcePath + " is not a directory", Files.isDirectory(targetResourcePath));
+        assertEquals(targetResourcePath + " directory was expected to be empty", 0, Files.list(targetResourcePath).count());
+    }
+
     @After
     public void tearDown() {
         if (buildRule.getProject() != null) {
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java
index 5d27f57..5ca4f3b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 
 import java.io.File;
 import java.text.SimpleDateFormat;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
@@ -34,9 +35,11 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  *  Testcase to ensure that command line generation and required attributes are correct.
@@ -64,6 +67,9 @@
     public BuildFileRule buildRule = new BuildFileRule();
     private Project project;
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         project = new Project();
@@ -114,7 +120,7 @@
     @Test
     public void testGetExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vssget.1", "some cause", "vsspath attribute must be set!");
+        expectSpecificBuildException("vssget.1", "vsspath attribute must be set!");
     }
 
     /**  Tests Label commandline generation.  */
@@ -167,8 +173,8 @@
     @Test
     public void testLabelExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vsslabel.1", "some cause", "vsspath attribute must be set!");
-        expectSpecificBuildException("vsslabel.2", "some cause", "label attribute must be set!");
+        expectSpecificBuildException("vsslabel.1", "vsspath attribute must be set!");
+        expectSpecificBuildException("vsslabel.2", "label attribute must be set!");
     }
 
     /**  Tests VSSHistory commandline generation with from label.  */
@@ -261,17 +267,13 @@
     @Test
     public void testHistoryExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vsshistory.1", "some cause", "vsspath attribute must be set!");
+        expectSpecificBuildException("vsshistory.1", "vsspath attribute must be set!");
     }
 
-    private void expectSpecificBuildException(String target, String failMessage,
-                                              String exceptionMessage) {
-        try {
-            buildRule.executeTarget(target);
-            fail(failMessage);
-        } catch (BuildException ex) {
-            assertEquals(exceptionMessage, ex.getMessage());
-        }
+    private void expectSpecificBuildException(String target, String exceptionMessage) {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(exceptionMessage);
+        buildRule.executeTarget(target);
     }
 
     /**  Tests CheckIn commandline generation.  */
@@ -301,7 +303,7 @@
     @Test
     public void testCheckinExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vsscheckin.1", "some cause", "vsspath attribute must be set!");
+        expectSpecificBuildException("vsscheckin.1", "vsspath attribute must be set!");
     }
 
     /**  Tests CheckOut commandline generation.  */
@@ -337,8 +339,8 @@
     @Test
     public void testCheckoutExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vsscheckout.1", "some cause", "vsspath attribute must be set!");
-        expectSpecificBuildException("vsscheckout.2", "some cause", "blah is not a legal value for this attribute");
+        expectSpecificBuildException("vsscheckout.1", "vsspath attribute must be set!");
+        expectSpecificBuildException("vsscheckout.2", "blah is not a legal value for this attribute");
     }
 
     /**  Tests Add commandline generation.  */
@@ -370,7 +372,7 @@
     @Test
     public void testAddExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vssadd.1", "some cause", "localPath attribute must be set!");
+        expectSpecificBuildException("vssadd.1", "localPath attribute must be set!");
     }
 
     /**  Tests CP commandline generation.  */
@@ -397,7 +399,7 @@
     @Test
     public void testCpExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vsscp.1", "some cause", "vsspath attribute must be set!");
+        expectSpecificBuildException("vsscp.1", "vsspath attribute must be set!");
     }
 
     /**  Tests Create commandline generation.  */
@@ -428,7 +430,7 @@
     @Test
     public void testCreateExceptions() {
         buildRule.configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml");
-        expectSpecificBuildException("vsscreate.1", "some cause", "vsspath attribute must be set!");
+        expectSpecificBuildException("vsscreate.1", "vsspath attribute must be set!");
     }
 
     /**
@@ -444,31 +446,20 @@
         int testIndex = 0;
 
         while (testIndex < testLength) {
-            try {
-                if (sGeneratedCmdLine[genIndex].equals("")) {
-                    genIndex++;
-                    continue;
-                }
-                assertEquals("arg # " + testIndex,
-                        sTestCmdLine[testIndex],
-                        sGeneratedCmdLine[genIndex]);
-                testIndex++;
+            if (sGeneratedCmdLine[genIndex].isEmpty()) {
                 genIndex++;
-            } catch (ArrayIndexOutOfBoundsException aioob) {
-                fail("missing arg " + sTestCmdLine[testIndex]);
+                continue;
             }
+            assertTrue("missing arg " + sTestCmdLine[testIndex], genIndex < genLength);
+            assertEquals("arg # " + testIndex,
+                    sTestCmdLine[testIndex], sGeneratedCmdLine[genIndex]);
+            testIndex++;
+            genIndex++;
         }
 
         // Count the number of empty strings
-        int cnt = 0;
-        for (String argument : sGeneratedCmdLine) {
-            if (argument.equals("")) {
-                cnt++;
-            }
-        }
-        if (genLength - cnt > sTestCmdLine.length) {
-            // We have extra elements
-            fail("extra args");
-        }
+        int cnt = (int) Arrays.stream(sGeneratedCmdLine).filter(String::isEmpty).count();
+        // We have extra elements
+        assertFalse("extra args", genLength - cnt > sTestCmdLine.length);
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/AbstractFileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/AbstractFileSetTest.java
index a025b2b..24f6449 100644
--- a/src/tests/junit/org/apache/tools/ant/types/AbstractFileSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/AbstractFileSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,10 +23,11 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  * Base class for FileSetTest and DirSetTest.
@@ -39,10 +40,16 @@
 
     private Project project;
 
+    private AbstractFileSet f;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         project = new Project();
         project.setBasedir(".");
+        f = getInstance();
     }
 
     protected abstract AbstractFileSet getInstance();
@@ -52,216 +59,187 @@
     }
 
     @Test
-    public final void testEmptyElementIfIsReference() {
-        AbstractFileSet f = getInstance();
+    public final void testCannotSetIncludesThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         f.setIncludes("**/*.java");
-        try {
-            f.setRefid(new Reference(getProject(), "dummyref"));
-            fail("Can add reference to "
-                 + f.getDataTypeName()
-                 + " with elements from setIncludes");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-
-        f = getInstance();
-        f.createPatternSet();
-        try {
-            f.setRefid(new Reference(getProject(), "dummyref"));
-            fail("Can add reference to "
-                 + f.getDataTypeName()
-                 + " with nested patternset element.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when "
-                         + "using refid", be.getMessage());
-        }
-
-        f = getInstance();
-        f.createInclude();
-        try {
-            f.setRefid(new Reference(getProject(), "dummyref"));
-            fail("Can add reference to "
-                 + f.getDataTypeName()
-                 + " with nested include element.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-
-        f = getInstance();
         f.setRefid(new Reference(getProject(), "dummyref"));
-        try {
-            f.setIncludes("**/*.java");
-            fail("Can set includes in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.setIncludesfile(new File("/a"));
-            fail("Can set includesfile in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.setExcludes("**/*.java");
-            fail("Can set excludes in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.setExcludesfile(new File("/a"));
-            fail("Can set excludesfile in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.setDir(project.resolveFile("."));
-            fail("Can set dir in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.createInclude();
-            fail("Can add nested include in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using "
-                         + "refid", be.getMessage());
-        }
-        try {
-            f.createExclude();
-            fail("Can add nested exclude in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using "
-                         + "refid", be.getMessage());
-        }
-        try {
-            f.createIncludesFile();
-            fail("Can add nested includesfile in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using "
-                         + "refid", be.getMessage());
-        }
-        try {
-            f.createExcludesFile();
-            fail("Can add nested excludesfile in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using "
-                         + "refid", be.getMessage());
-        }
-        try {
-            f.createPatternSet();
-            fail("Can add nested patternset in "
-                 + f.getDataTypeName()
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using "
-                         + "refid", be.getMessage());
-        }
     }
 
     @Test
-    public void testCircularReferenceCheck() {
-        AbstractFileSet f = getInstance();
+    public final void testCannotAddPatternSetThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        f.createPatternSet();
+        f.setRefid(new Reference(getProject(), "dummyref"));
+    }
+
+    @Test
+    public final void testCannotAddIncludeThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.createInclude();
+        f.setRefid(new Reference(getProject(), "dummyref"));
+    }
+
+    @Test
+    public final void testCannotSetRefidThenIncludes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.setIncludes("**/*.java");
+    }
+
+    @Test
+    public final void testCannotSetRefidThenIncludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.setIncludesfile(new File("/a"));
+    }
+
+    @Test
+    public final void testCannotSetRefidThenExcludes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.setExcludes("**/*.java");
+    }
+
+    @Test
+    public final void testCannotSetRefidThenExcludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.setExcludesfile(new File("/a"));
+    }
+
+    @Test
+    public final void testCannotSetRefidThenDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.setDir(project.resolveFile("."));
+    }
+
+    @Test
+    public final void testCannotSetRefidThenAddInclude() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.createInclude();
+    }
+
+    @Test
+    public final void testCannotSetRefidThenAddExclude() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.createExclude();
+    }
+
+    @Test
+    public final void testCannotSetRefidThenAddIncludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.createIncludesFile();
+    }
+
+    @Test
+    public final void testCannotSetRefidThenAddExcludesFile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.createExcludesFile();
+    }
+
+    @Test
+    public final void testCannotSetRefidThenAddPatternset() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        f.setRefid(new Reference(getProject(), "dummyref"));
+        f.createPatternSet();
+    }
+
+    @Test
+    public void testCircularReferenceCheckGetDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         project.addReference("dummy", f);
         f.setRefid(new Reference(getProject(), "dummy"));
-        try {
-            f.getDir(project);
-            fail("Can make " + f.getDataTypeName()
-                 + " a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
-        try {
-            f.getDirectoryScanner(project);
-            fail("Can make " + f.getDataTypeName()
-                 + " a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        f.getDir(project);
+    }
 
+    @Test
+    public void testCircularReferenceCheckGetDirScanner() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        project.addReference("dummy", f);
+        f.setRefid(new Reference(getProject(), "dummy"));
+        f.getDirectoryScanner(project);
+    }
+
+    @Test
+    public void testLoopReferenceCheckGetDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         // dummy1 --> dummy2 --> dummy3 --> dummy1
-        AbstractFileSet f1 = getInstance();
-        project.addReference("dummy1", f1);
-        f1.setRefid(new Reference(getProject(), "dummy2"));
-        AbstractFileSet f2 = getInstance();
-        project.addReference("dummy2", f2);
-        f2.setRefid(new Reference(getProject(), "dummy3"));
-        AbstractFileSet f3 = getInstance();
-        project.addReference("dummy3", f3);
-        f3.setRefid(new Reference(getProject(), "dummy1"));
-        try {
-            f1.getDir(project);
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
-        try {
-            f1.getDirectoryScanner(project);
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        project.addReference("dummy1", f);
+        f.setRefid(new Reference(getProject(), "dummy2"));
+        AbstractFileSet fa = getInstance();
+        project.addReference("dummy2", fa);
+        fa.setRefid(new Reference(getProject(), "dummy3"));
+        AbstractFileSet fb = getInstance();
+        project.addReference("dummy3", fb);
+        fb.setRefid(new Reference(getProject(), "dummy1"));
+        f.getDir(project);
+    }
 
+    @Test
+    public void testLoopReferenceCheckGetDirScanner() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        // dummy1 --> dummy2 --> dummy3 --> dummy1
+        project.addReference("dummy1", f);
+        f.setRefid(new Reference(getProject(), "dummy2"));
+        AbstractFileSet fa = getInstance();
+        project.addReference("dummy2", fa);
+        fa.setRefid(new Reference(getProject(), "dummy3"));
+        AbstractFileSet fb = getInstance();
+        project.addReference("dummy3", fb);
+        fb.setRefid(new Reference(getProject(), "dummy1"));
+        f.getDirectoryScanner(project);
+    }
+
+    @Test
+    public void testLoopReferenceCheck() {
         // dummy1 --> dummy2 --> dummy3
         // (which has the Project's basedir as root).
-        f1 = getInstance();
-        project.addReference("dummy1", f1);
-        f1.setRefid(new Reference(getProject(), "dummy2"));
-        f2 = getInstance();
-        project.addReference("dummy2", f2);
-        f2.setRefid(new Reference(getProject(), "dummy3"));
-        f3 = getInstance();
-        project.addReference("dummy3", f3);
-        f3.setDir(project.resolveFile("."));
-        File dir = f1.getDir(project);
+        project.addReference("dummy1", f);
+        f.setRefid(new Reference(getProject(), "dummy2"));
+        AbstractFileSet fa = getInstance();
+        project.addReference("dummy2", fa);
+        fa.setRefid(new Reference(getProject(), "dummy3"));
+        AbstractFileSet fb = getInstance();
+        project.addReference("dummy3", fb);
+        fb.setDir(project.resolveFile("."));
+        File dir = f.getDir(project);
         assertEquals("Dir is basedir", dir, project.getBaseDir());
     }
 
     @Test
     public void canCallSetFileTwiceWithSameArgument() {
-        AbstractFileSet f = getInstance();
         f.setFile(new File("/a"));
         f.setFile(new File("/a"));
         // really only asserts no exception is thrown
     }
 
     @Test
-    public void cantCallSetFileTwiceWithDifferentArguments() {
-        AbstractFileSet f = getInstance();
+    public void cannotCallSetFileTwiceWithDifferentArguments() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("setFile cannot be called twice with different arguments");
         f.setFile(new File("/a"));
-        try {
-            f.setFile(new File("/b"));
-            fail("expected an exception");
-        } catch (BuildException ex) {
-            assertEquals("setFile cannot be called twice with different arguments", ex.getMessage());
-        }
+        f.setFile(new File("/b"));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/AddTypeTest.java b/src/tests/junit/org/apache/tools/ant/types/AddTypeTest.java
index 6dfbcf6..9728619 100644
--- a/src/tests/junit/org/apache/tools/ant/types/AddTypeTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/AddTypeTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 
 package org.apache.tools.ant.types;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -27,14 +26,19 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
 
 public class AddTypeTest {
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/types/addtype.xml");
@@ -63,71 +67,65 @@
     @Test
     public void testNestedA() {
         buildRule.executeTarget("nested.a");
-        AntAssert.assertContains("add A called", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("add A called"));
     }
 
     @Test
     public void testNestedB() {
         buildRule.executeTarget("nested.b");
-         AntAssert.assertContains("add B called", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("add B called"));
     }
 
     @Test
     public void testNestedC() {
         buildRule.executeTarget("nested.c");
-        AntAssert.assertContains("add C called", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("add C called"));
     }
 
     @Test
     public void testNestedAB() {
-        try {
-            buildRule.executeTarget("nested.ab");
-            fail("Build exception expected: Should have got ambiguous");
-        } catch (BuildException ex) {
-            AntAssert.assertContains("ambiguous", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("ambiguous");
+        buildRule.executeTarget("nested.ab");
     }
 
     @Test
     public void testConditionType() {
         buildRule.executeTarget("condition.type");
-        AntAssert.assertContains("beforeafter", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("beforeafter"));
     }
 
     @Test
     public void testConditionTask() {
         buildRule.executeTarget("condition.task");
-        AntAssert.assertContains("My Condition execution", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("My Condition execution"));
     }
 
     @Test
     public void testConditionConditionType() {
         buildRule.executeTarget("condition.condition.type");
-        AntAssert.assertContains("My Condition eval", buildRule.getLog());
+        assertThat(buildRule.getLog(), containsString("My Condition eval"));
     }
 
     @Test
     public void testConditionConditionTask() {
-        try {
-            buildRule.executeTarget("condition.condition.task");
-            fail("Build exception expected: Task masking condition");
-        } catch (BuildException ex) {
-             AntAssert.assertContains("doesn't support the nested", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("doesn't support the nested");
+        buildRule.executeTarget("condition.condition.task");
     }
 
     @Test
     public void testAddConfigured() {
         buildRule.executeTarget("myaddconfigured");
-        AntAssert.assertContains("value is Value Setexecute: value is Value Set",
-                buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("value is Value Setexecute: value is Value Set"));
     }
 
     @Test
     public void testAddConfiguredValue() {
         buildRule.executeTarget("myaddconfiguredvalue");
-        AntAssert.assertContains("value is Value Setexecute: value is Value Set",
-                buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("value is Value Setexecute: value is Value Set"));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/types/AssertionsTest.java b/src/tests/junit/org/apache/tools/ant/types/AssertionsTest.java
index 5e54f45..9b963aa 100644
--- a/src/tests/junit/org/apache/tools/ant/types/AssertionsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/AssertionsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,13 +19,14 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeFalse;
 
 /**
  * test assertion handling
@@ -35,23 +36,22 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/types/assertions.xml");
     }
 
-
     /**
      * runs a test and expects an assertion thrown in forked code
      * @param target String
      */
     private void expectAssertion(String target) {
-        try {
-            buildRule.executeTarget(target);
-            fail("BuildException should have been thrown by assertion fail in task");
-        } catch (BuildException ex) {
-            assertContains("assertion not thrown in " + target, "Java returned: 1", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Java returned: 1");
+        buildRule.executeTarget(target);
     }
 
     @Test
@@ -91,29 +91,25 @@
 
     @Test
     public void testMultipleAssertions() {
-        try {
-            buildRule.executeTarget("test-multiple-assertions");
-            fail("BuildException should have been thrown by assertion fail in task");
-        } catch (BuildException ex) {
-            assertContains("multiple assertions rejected", "Only one assertion declaration is allowed", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Only one assertion declaration is allowed");
+        buildRule.executeTarget("test-multiple-assertions");
     }
 
     @Test
     public void testReferenceAbuse() {
-        try {
-            buildRule.executeTarget("test-reference-abuse");
-            fail("BuildException should have been thrown by reference abuse");
-        } catch (BuildException ex) {
-            assertContains("reference abuse rejected", "You must not specify", ex.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify");
+        buildRule.executeTarget("test-reference-abuse");
     }
 
     @Test
     public void testNofork() {
-        Assume.assumeFalse("ran Ant tests with -ea and this would fail spuriously", AssertionsTest.class.desiredAssertionStatus());
+        assumeFalse("ran Ant tests with -ea and this would fail spuriously",
+                AssertionsTest.class.desiredAssertionStatus());
         buildRule.executeTarget("test-nofork");
-        assertContains("Assertion statements are currently ignored in non-forked mode", buildRule.getLog());
+        assertThat(buildRule.getLog(),
+                containsString("Assertion statements are currently ignored in non-forked mode"));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/types/CharSetTest.java b/src/tests/junit/org/apache/tools/ant/types/CharSetTest.java
new file mode 100644
index 0000000..14f6627
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/types/CharSetTest.java
@@ -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
+ *
+ *      https://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;
+
+import org.apache.tools.ant.BuildException;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.hamcrest.Matchers.equalToIgnoringCase;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Enclosed.class)
+public class CharSetTest {
+
+    @RunWith(Parameterized.class)
+    public static class LegalArgumentTest {
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "legal argument: |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("UTF-8", "ISO-8859-1", "037", "us", "IBM500",
+                    // some java.io encodings are not provided as aliases in java.nio.charset
+                    // so, for backwards compatibility, the case should not matter
+                    "ascii", "utf-8", "Cp1252");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Test
+        public void testCorrectNames() {
+            CharSet cs = new CharSet(argument);
+            assertThat(argument, equalToIgnoringCase(cs.getValue()));
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class IllegalArgumentTest {
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "illegal argument: |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("mojibake", "dummy");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Test(expected = BuildException.class)
+        public void testNonExistentNames() {
+            new CharSet(argument);
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class LegalEquivalenceTest {
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "equivalent argument: |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("UTF8", "unicode-1-1-utf-8");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Test
+        public void testCorrectNames() {
+            assertTrue(new CharSet(argument).equivalent(CharSet.getUtf8()));
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class IncorrectEquivalenceTest {
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "non-equivalent argument: |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("us", "ISO-8859-1", "US-ASCII");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Test
+        public void testIncorrectNames() {
+            assertFalse(new CharSet(argument).equivalent(CharSet.getUtf8()));
+        }
+    }
+
+}
diff --git a/src/tests/junit/org/apache/tools/ant/types/CommandlineJavaTest.java b/src/tests/junit/org/apache/tools/ant/types/CommandlineJavaTest.java
index 5f6bb50..07afc7b 100644
--- a/src/tests/junit/org/apache/tools/ant/types/CommandlineJavaTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/CommandlineJavaTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,18 +18,22 @@
 
 package org.apache.tools.ant.types;
 
-
 import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.MagicTestNames;
 import org.apache.tools.ant.Project;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.io.File;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.hasKey;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 
 /**
  * JUnit testcases for org.apache.tools.ant.CommandlineJava
@@ -41,15 +45,20 @@
 
     private Project project;
 
+    private CommandlineJava c;
+
     @Before
     public void setUp() {
         project = new Project();
-        project.setBasedir(System.getProperty("root"));
-        project.setProperty("build.sysclasspath", "ignore");
+        if (System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY) != null) {
+            project.setBasedir(System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY));
+        }
+        project.setProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
         cloneVm = System.getProperty("ant.build.clonevm");
         if (cloneVm != null) {
             System.setProperty("ant.build.clonevm", "false");
         }
+        c = new CommandlineJava();
     }
 
     @After
@@ -59,9 +68,14 @@
         }
     }
 
+    /**
+     * NullPointerException may break the build
+     *
+     * @throws CloneNotSupportedException if clone() fails
+     */
     @Test
-    public void testGetCommandline() throws Exception {
-        CommandlineJava c = new CommandlineJava();
+    public void testGetCommandline() throws CloneNotSupportedException {
+        assertNotNull("Ant home not set", System.getProperty(MagicNames.ANT_HOME));
         c.createArgument().setValue("org.apache.tools.ant.CommandlineJavaTest");
         c.setClassname("junit.textui.TestRunner");
         c.createVmArgument().setValue("-Djava.compiler=NONE");
@@ -79,31 +93,24 @@
         assertEquals("no classpath", "junit.textui.TestRunner", s[2]);
         assertEquals("no classpath",
                      "org.apache.tools.ant.CommandlineJavaTest", s[3]);
-        try {
-            c.clone();
-        } catch (NullPointerException ex) {
-            fail("cloning should work without classpath specified");
-        }
-
+        c.clone();
         c.createClasspath(project).setLocation(project.resolveFile("build.xml"));
         c.createClasspath(project).setLocation(project.resolveFile(
             System.getProperty(MagicNames.ANT_HOME) + "/lib/ant.jar"));
         s = c.getCommandline();
         assertEquals("with classpath", 6, s.length);
-        //        assertEquals("with classpath", "java", s[0]);
+        // assertEquals("with classpath", "java", s[0]);
         assertEquals("with classpath", "-Djava.compiler=NONE", s[1]);
         assertEquals("with classpath", "-classpath", s[2]);
-        assertTrue("build.xml contained",
-                s[3].contains("build.xml" + java.io.File.pathSeparator));
-        assertTrue("ant.jar contained", s[3].endsWith("ant.jar"));
+        assertThat("build.xml contained", s[3], containsString("build.xml" + File.pathSeparator));
+        assertThat("ant.jar contained", s[3], endsWith("ant.jar"));
         assertEquals("with classpath", "junit.textui.TestRunner", s[4]);
         assertEquals("with classpath",
                      "org.apache.tools.ant.CommandlineJavaTest", s[5]);
     }
 
     @Test
-    public void testJarOption() throws Exception {
-        CommandlineJava c = new CommandlineJava();
+    public void testJarOption() {
         c.createArgument().setValue("arg1");
         c.setJar("myfile.jar");
         c.createVmArgument().setValue("-classic");
@@ -121,7 +128,6 @@
         String currentClasspath = System.getProperty("java.class.path");
         assertNotNull(currentClasspath);
         assertNull(System.getProperty("key"));
-        CommandlineJava c = new CommandlineJava();
         Environment.Variable v = new Environment.Variable();
         v.setKey("key");
         v.setValue("value");
@@ -140,7 +146,7 @@
             assertEquals(currentClasspath, newClasspath);
             assertNotNull(System.getProperty("key"));
             assertEquals("value", System.getProperty("key"));
-            assertTrue(System.getProperties().containsKey("java.class.path"));
+            assertThat(System.getProperties(), hasKey("java.class.path"));
             assertNotNull(System.getProperty("key2"));
             assertEquals("value2", System.getProperty("key2"));
         } finally {
@@ -152,7 +158,6 @@
 
     @Test
     public void testAssertions() throws Exception {
-        CommandlineJava c = new CommandlineJava();
         c.createArgument().setValue("org.apache.tools.ant.CommandlineJavaTest");
         c.setClassname("junit.textui.TestRunner");
         c.createVmArgument().setValue("-Djava.compiler=NONE");
diff --git a/src/tests/junit/org/apache/tools/ant/types/CommandlineTest.java b/src/tests/junit/org/apache/tools/ant/types/CommandlineTest.java
index 4ba00bb..e5821ea 100644
--- a/src/tests/junit/org/apache/tools/ant/types/CommandlineTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/CommandlineTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,10 +19,11 @@
 package org.apache.tools.ant.types;
 
 import org.apache.tools.ant.BuildException;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNotNull;
 
 /**
@@ -30,6 +31,9 @@
  */
 public class CommandlineTest {
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Test
     public void testTokenizer() {
         String[] s = Commandline.translateCommandline("1 2 3");
@@ -44,7 +48,7 @@
         s = Commandline.translateCommandline(null);
         assertEquals("null", 0, s.length);
 
-        s = Commandline.translateCommandline("1 \'2\' 3");
+        s = Commandline.translateCommandline("1 '2' 3");
         assertEquals("Simple case with single quotes", 3, s.length);
         assertEquals("Single quotes have been stripped", "2", s[1]);
 
@@ -56,15 +60,15 @@
         assertEquals("Case with double quotes and whitespace", 3, s.length);
         assertEquals("Double quotes stripped, space included", "2 3", s[1]);
 
-        s = Commandline.translateCommandline("1 \"2\'3\" 4");
+        s = Commandline.translateCommandline("1 \"2'3\" 4");
         assertEquals("Case with double quotes around single quote", 3, s.length);
-        assertEquals("Double quotes stripped, single quote included", "2\'3", s[1]);
+        assertEquals("Double quotes stripped, single quote included", "2'3", s[1]);
 
-        s = Commandline.translateCommandline("1 \'2 3\' 4");
+        s = Commandline.translateCommandline("1 '2 3' 4");
         assertEquals("Case with single quotes and whitespace", 3, s.length);
         assertEquals("Single quotes stripped, space included", "2 3", s[1]);
 
-        s = Commandline.translateCommandline("1 \'2\"3\' 4");
+        s = Commandline.translateCommandline("1 '2\"3' 4");
         assertEquals("Case with single quotes around double quote", 3, s.length);
         assertEquals("Single quotes stripped, double quote included", "2\"3", s[1]);
 
@@ -89,33 +93,37 @@
         assertEquals("Doublequoted null arg", 1, s.length);
         assertEquals("Doublequoted null arg", "", s[0]);
 
-        s = Commandline.translateCommandline("\'\' a");
+        s = Commandline.translateCommandline("'' a");
         assertEquals("Singlequoted null arg prepend", 2, s.length);
         assertEquals("Singlequoted null arg prepend", "", s[0]);
         assertEquals("Singlequoted null arg prepend", "a", s[1]);
-        s = Commandline.translateCommandline("a \'\'");
+        s = Commandline.translateCommandline("a ''");
         assertEquals("Singlequoted null arg append", 2, s.length);
         assertEquals("Singlequoted null arg append", "a", s[0]);
         assertEquals("Singlequoted null arg append", "", s[1]);
-        s = Commandline.translateCommandline("\'\'");
+        s = Commandline.translateCommandline("''");
         assertEquals("Singlequoted null arg", 1, s.length);
         assertEquals("Singlequoted null arg", "", s[0]);
+    }
 
-        // now to the expected failures
+    /**
+     * Expected failure due to unbalanced single quote
+     */
+    @Test
+    public void testTokenizerUnbalancedSingleQuote() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("unbalanced quotes in a 'b c");
+        Commandline.translateCommandline("a 'b c");
+    }
 
-        try {
-            Commandline.translateCommandline("a \'b c");
-            fail("unbalanced single quotes undetected");
-        } catch (BuildException be) {
-            assertEquals("unbalanced quotes in a \'b c", be.getMessage());
-        }
-
-        try {
-            Commandline.translateCommandline("a \"b c");
-            fail("unbalanced double quotes undetected");
-        } catch (BuildException be) {
-            assertEquals("unbalanced quotes in a \"b c", be.getMessage());
-        }
+    /**
+     * Expected failure due to unbalanced double quote
+     */
+    @Test
+    public void testTokenizerUnbalancedDoubleQuote() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("unbalanced quotes in a \"b c");
+        Commandline.translateCommandline("a \"b c");
     }
 
     @Test
@@ -124,8 +132,8 @@
         assertEquals("", Commandline.toString(null));
         assertEquals("1 2 3", Commandline.toString(new String[] {"1", "2", "3"}));
         assertEquals("1 \"2 3\"", Commandline.toString(new String[] {"1", "2 3"}));
-        assertEquals("1 \"2\'3\"", Commandline.toString(new String[] {"1", "2\'3"}));
-        assertEquals("1 \'2\"3\'", Commandline.toString(new String[] {"1", "2\"3"}));
+        assertEquals("1 \"2'3\"", Commandline.toString(new String[] {"1", "2'3"}));
+        assertEquals("1 '2\"3'", Commandline.toString(new String[] {"1", "2\"3"}));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/types/DescriptionTest.java b/src/tests/junit/org/apache/tools/ant/types/DescriptionTest.java
index aeb7911..507b788 100644
--- a/src/tests/junit/org/apache/tools/ant/types/DescriptionTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/DescriptionTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,43 +21,45 @@
 import org.apache.tools.ant.BuildFileRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
 
 import static org.junit.Assert.assertEquals;
 
 /**
- * FilterSet testing
- *
+ * Description tests
  */
+@RunWith(Parameterized.class)
 public class DescriptionTest {
+    @Parameterized.Parameters(name = "{1}")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object[][]{
+                {"description1", "Single", "Test Project Description"},
+                {"description2", "Multi line", "Multi Line\nProject Description"},
+                {"description3", "Multi instance", "Multi Instance Project Description"},
+                {"description4", "Multi instance nested", "Multi Instance Nested Project Description"}
+        });
+    }
+
+    @Parameterized.Parameter
+    public String fileName;
+
+    @Parameterized.Parameter(1)
+    public String description;
+
+    @Parameterized.Parameter(2)
+    public String outcome;
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Test
-    public void test1() {
-        buildRule.configureProject("src/etc/testcases/types/description1.xml");
-        assertEquals("Single description failed", "Test Project Description",
-                buildRule.getProject().getDescription());
-    }
-
-    @Test
-    public void test2() {
-        buildRule.configureProject("src/etc/testcases/types/description2.xml");
-        assertEquals("Multi line description failed", "Multi Line\nProject Description",
-                buildRule.getProject().getDescription());
-    }
-
-    @Test
-    public void test3() {
-        buildRule.configureProject("src/etc/testcases/types/description3.xml");
-        assertEquals("Multi instance description failed", "Multi Instance Project Description",
-                buildRule.getProject().getDescription());
-    }
-
-    @Test
-    public void test4() {
-        buildRule.configureProject("src/etc/testcases/types/description4.xml");
-        assertEquals("Multi instance nested description failed", "Multi Instance Nested Project Description",
+    public void test() {
+        buildRule.configureProject("src/etc/testcases/types/" + fileName + ".xml");
+        assertEquals(description + " description failed", outcome,
                 buildRule.getProject().getDescription());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/DirSetTest.java b/src/tests/junit/org/apache/tools/ant/types/DirSetTest.java
index e9162f1..a2cd368 100644
--- a/src/tests/junit/org/apache/tools/ant/types/DirSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/DirSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,47 +22,52 @@
 import java.io.FileOutputStream;
 
 import org.apache.tools.ant.BuildException;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit 4 testcases for org.apache.tools.ant.types.DirSet.
  */
 public class DirSetTest extends AbstractFileSetTest {
 
+    private DirSet ds;
+
+    private FileSet fs;
+
+    @Before
+    public void setUp() {
+        super.setUp();
+        ds = (DirSet) getInstance();
+        ds.setProject(getProject());
+        fs = new FileSet();
+    }
+
     protected AbstractFileSet getInstance() {
         return new DirSet();
     }
 
     @Test
-    public void testFileSetIsNoDirSet() {
-        DirSet ds = (DirSet) getInstance();
-        ds.setProject(getProject());
-        FileSet fs = new FileSet();
+    public void testDirSetFromFileSet() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("dummy doesn't denote a DirSet");
         fs.setProject(getProject());
         getProject().addReference("dummy", fs);
         ds.setRefid(new Reference(getProject(), "dummy"));
-        try {
-            ds.getDir(getProject());
-            fail("DirSet created from FileSet reference");
-        } catch (BuildException e) {
-            assertEquals("dummy doesn\'t denote a DirSet", e.getMessage());
-        }
-
-        ds = (DirSet) getInstance();
-        ds.setProject(getProject());
-        getProject().addReference("dummy2", ds);
-        fs.setRefid(new Reference(getProject(), "dummy2"));
-        try {
-            fs.getDir(getProject());
-            fail("FileSet created from DirSet reference");
-        } catch (BuildException e) {
-            assertEquals("dummy2 doesn\'t denote a FileSet", e.getMessage());
-        }
+        ds.getDir(getProject());
     }
 
+    @Test
+    public void testFileSetFromDirSet() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("dummy doesn't denote a FileSet");
+        getProject().addReference("dummy", ds);
+        fs.setRefid(new Reference(getProject(), "dummy"));
+        fs.getDir(getProject());
+    }
+
+    @Test
     public void testToString() throws Exception {
         File tmp = File.createTempFile("DirSetTest", "");
         try {
@@ -75,8 +80,6 @@
             new FileOutputStream(new File(a, "x")).close();
             new FileOutputStream(new File(b, "x")).close();
             new FileOutputStream(new File(bc, "x")).close();
-            DirSet ds = new DirSet();
-            ds.setProject(getProject());
             ds.setDir(tmp);
             ds.setIncludes("b/");
             assertEquals("b;b" + File.separator + "c", ds.toString());
diff --git a/src/tests/junit/org/apache/tools/ant/types/EnumeratedAttributeTest.java b/src/tests/junit/org/apache/tools/ant/types/EnumeratedAttributeTest.java
index 14436de..2fb965e 100644
--- a/src/tests/junit/org/apache/tools/ant/types/EnumeratedAttributeTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/EnumeratedAttributeTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,9 +21,11 @@
 import org.apache.tools.ant.BuildException;
 import org.junit.Test;
 
+import java.util.Arrays;
+
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit testcases for org.apache.tools.ant.EnumeratedAttribute.
@@ -36,52 +38,44 @@
     public void testContains() {
         EnumeratedAttribute t1 = new TestNormal();
         for (String value : expected) {
-            assertTrue(value + " is in TestNormal",
-                    t1.containsValue(value));
-            assertTrue(value.toUpperCase() + " is in TestNormal",
-                    !t1.containsValue(value.toUpperCase()));
+            assertTrue(value + " is in TestNormal", t1.containsValue(value));
+            assertFalse(value.toUpperCase() + " is in TestNormal",
+                    t1.containsValue(value.toUpperCase()));
         }
-        assertTrue("TestNormal doesn\'t have \"d\" attribute",
-               !t1.containsValue("d"));
-        assertTrue("TestNull doesn\'t have \"d\" attribute and doesn\'t die",
-               !(new TestNull()).containsValue("d"));
+        assertFalse("TestNormal doesn't have \"d\" attribute", t1.containsValue("d"));
+        assertFalse("TestNull doesn't have \"d\" attribute and doesn't die",
+                (new TestNull()).containsValue("d"));
     }
 
-    @Test
+    /**
+     * Expected failure due to attempt to set an illegal value
+     */
+    @Test(expected = BuildException.class)
     public void testFactory() {
         Factory ea = (Factory) EnumeratedAttribute.getInstance(Factory.class, "one");
         assertEquals("Factory did not set the right value.", ea.getValue(), "one");
-        try {
-            EnumeratedAttribute.getInstance(Factory.class, "illegal");
-            fail("Factory should fail when trying to set an illegal value.");
-        } catch (BuildException be) {
-            // was expected
-            //TODO assert exception message
-        }
+        EnumeratedAttribute.getInstance(Factory.class, "illegal");
     }
 
     @Test
-    public void testExceptions() {
-        EnumeratedAttribute t1 = new TestNormal();
-        for (String value : expected) {
-            try {
-                t1.setValue(value);
-            } catch (BuildException be) {
-                fail("unexpected exception for value " + value);
-            }
-        }
-        try {
-            t1.setValue("d");
-            fail("expected exception for value \"d\"");
-        } catch (BuildException be) {
-         //TODO assert build exception
-        }
-        try {
-            (new TestNull()).setValue("d");
-            fail("expected exception for value \"d\" in TestNull");
-        } catch (BuildException be) {
-            //TODO assert exception message
-        }
+    public void testExceptionsNormal() {
+        Arrays.stream(expected).forEach(new TestNormal()::setValue);
+    }
+
+    /**
+     * Expected exception for value "d" in TestNormal
+     */
+    @Test(expected = BuildException.class)
+    public void testExceptionNormal() {
+        new TestNormal().setValue("d");
+    }
+
+    /**
+     * Expected exception for value "d" in TestNull
+     */
+    @Test(expected = BuildException.class)
+    public void testExceptionNull() {
+        new TestNull().setValue("d");
     }
 
     public static class TestNormal extends EnumeratedAttribute {
diff --git a/src/tests/junit/org/apache/tools/ant/types/FileListTest.java b/src/tests/junit/org/apache/tools/ant/types/FileListTest.java
index 0fe59f7..9d0d206 100644
--- a/src/tests/junit/org/apache/tools/ant/types/FileListTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/FileListTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,11 +23,11 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.io.File;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  * Some tests for filelist.
@@ -36,110 +36,117 @@
 public class FileListTest {
 
     @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    private FileList f;
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/types/filelist.xml");
+        f = new FileList();
     }
 
+    /**
+     * Can add reference to FileList with directory attribute set.
+     */
     @Test
-    public void testEmptyElementIfIsReference() {
-        FileList f = new FileList();
+    public void testEmptyElementSetDirThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         f.setDir(buildRule.getProject().resolveFile("."));
-        try {
-            f.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-            fail("Can add reference to FileList with directory attribute set.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-
-        f = new FileList();
-        f.setFiles("foo.xml,c/d/bar.xml");
-        try {
-            f.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-            fail("Can add reference to FileList with file attribute set.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-
-        f = new FileList();
         f.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-        try {
-            f.setFiles("a/b/foo.java");
-            fail("Can set files in FileList that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-        try {
-            f.setDir(buildRule.getProject().resolveFile("."));
-            fail("Can set dir in FileList that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
     }
 
     @Test
-    public void testCircularReferenceCheck() {
-        FileList f = new FileList();
+    public void testEmptyElementSetFilesThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setFiles("foo.xml,c/d/bar.xml");
+        f.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenFiles() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+        f.setFiles("a/b/foo.java");
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        f.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+        f.setDir(buildRule.getProject().resolveFile("."));
+    }
+
+    @Test
+    public void testCircularReferenceCheckDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         buildRule.getProject().addReference("dummy", f);
         f.setRefid(new Reference(buildRule.getProject(), "dummy"));
-        try {
-            f.getDir(buildRule.getProject());
-            fail("Can make FileList a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
-        try {
-            f.getFiles(buildRule.getProject());
-            fail("Can make FileList a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        f.getDir(buildRule.getProject());
+    }
 
-        // dummy1 --> dummy2 --> dummy3 --> dummy1
-        FileList f1 = new FileList();
-        buildRule.getProject().addReference("dummy1", f1);
-        f1.setRefid(new Reference(buildRule.getProject(), "dummy2"));
-        FileList f2 = new FileList();
-        buildRule.getProject().addReference("dummy2", f2);
-        f2.setRefid(new Reference(buildRule.getProject(), "dummy3"));
-        FileList f3 = new FileList();
-        buildRule.getProject().addReference("dummy3", f3);
-        f3.setRefid(new Reference(buildRule.getProject(), "dummy1"));
-        try {
-            f1.getDir(buildRule.getProject());
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
-        try {
-            f1.getFiles(buildRule.getProject());
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+    @Test
+    public void testCircularReferenceCheckFiles() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        buildRule.getProject().addReference("dummy", f);
+        f.setRefid(new Reference(buildRule.getProject(), "dummy"));
+        f.getFiles(buildRule.getProject());
+    }
 
-        // dummy1 --> dummy2 --> dummy3
+    @Test
+    public void testLoopReferenceCheckDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        // dummy --> dummyA --> dummyB --> dummy
+        buildRule.getProject().addReference("dummy", f);
+        f.setRefid(new Reference(buildRule.getProject(), "dummyA"));
+        FileList fa = new FileList();
+        buildRule.getProject().addReference("dummyA", fa);
+        fa.setRefid(new Reference(buildRule.getProject(), "dummyB"));
+        FileList fb = new FileList();
+        buildRule.getProject().addReference("dummyB", fb);
+        fb.setRefid(new Reference(buildRule.getProject(), "dummy"));
+        f.getDir(buildRule.getProject());
+    }
+
+    @Test
+    public void testLoopReferenceCheckFiles() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        // dummy --> dummyA --> dummyB --> dummy
+        buildRule.getProject().addReference("dummy", f);
+        f.setRefid(new Reference(buildRule.getProject(), "dummyA"));
+        FileList fa = new FileList();
+        buildRule.getProject().addReference("dummyA", fa);
+        fa.setRefid(new Reference(buildRule.getProject(), "dummyB"));
+        FileList fb = new FileList();
+        buildRule.getProject().addReference("dummyB", fb);
+        fb.setRefid(new Reference(buildRule.getProject(), "dummy"));
+        f.getFiles(buildRule.getProject());
+    }
+
+    @Test
+    public void testLoopReferenceCheck() {
+        // dummy --> dummyA --> dummyB
         // (which has the Project's basedir as root).
-        f1 = new FileList();
-        buildRule.getProject().addReference("dummy1", f1);
-        f1.setRefid(new Reference(buildRule.getProject(), "dummy2"));
-        f2 = new FileList();
-        buildRule.getProject().addReference("dummy2", f2);
-        f2.setRefid(new Reference(buildRule.getProject(), "dummy3"));
-        f3 = new FileList();
-        buildRule.getProject().addReference("dummy3", f3);
-        f3.setDir(buildRule.getProject().resolveFile("."));
-        File dir = f1.getDir(buildRule.getProject());
+        buildRule.getProject().addReference("dummy", f);
+        f.setRefid(new Reference(buildRule.getProject(), "dummyA"));
+        FileList fa = new FileList();
+        buildRule.getProject().addReference("dummyA", fa);
+        fa.setRefid(new Reference(buildRule.getProject(), "dummyB"));
+        FileList fb = new FileList();
+        buildRule.getProject().addReference("dummyB", fb);
+        fb.setDir(buildRule.getProject().resolveFile("."));
+        File dir = f.getDir(buildRule.getProject());
         assertEquals("Dir is basedir", dir, buildRule.getProject().getBaseDir());
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java
index 3ca5faa..c8c3d40 100644
--- a/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/FileSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/FilterSetTest.java b/src/tests/junit/org/apache/tools/ant/types/FilterSetTest.java
index 68c1754..ee8b3dd 100644
--- a/src/tests/junit/org/apache/tools/ant/types/FilterSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/FilterSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,7 +32,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * FilterSet testing
@@ -58,22 +57,19 @@
     @Test
     public void test1() throws IOException {
         buildRule.executeTarget("test1");
-        assertTrue("Filterset 1 failed", compareFiles("src/etc/testcases/types/gold/filterset1.txt",
-                                                      "src/etc/testcases/types/dest1.txt"));
+        assertTrue("Filterset 1 failed", compareFiles("gold/filterset1.txt", "dest1.txt"));
     }
 
     @Test
     public void test2() throws IOException {
         buildRule.executeTarget("test2");
-        assertTrue("Filterset 2 failed", compareFiles("src/etc/testcases/types/gold/filterset2.txt",
-                                                      "src/etc/testcases/types/dest2.txt"));
+        assertTrue("Filterset 2 failed", compareFiles("gold/filterset2.txt", "dest2.txt"));
     }
 
     @Test
     public void test3() throws IOException {
         buildRule.executeTarget("test3");
-        assertTrue("Filterset 3 failed", compareFiles("src/etc/testcases/types/gold/filterset3.txt",
-                                                      "src/etc/testcases/types/dest3.txt"));
+        assertTrue("Filterset 3 failed", compareFiles("gold/filterset3.txt", "dest3.txt"));
     }
 
     /**
@@ -152,23 +148,23 @@
     public void testNestedFilterSets() {
         buildRule.executeTarget("test-nested-filtersets");
 
-        FilterSet fs = (FilterSet) buildRule.getProject().getReference("1");
-        Hashtable filters = fs.getFilterHash();
+        FilterSet fs = buildRule.getProject().getReference("1");
+        Hashtable<String, String> filters = fs.getFilterHash();
         assertEquals(1, filters.size());
         assertEquals("value1", filters.get("token1"));
 
-        fs = (FilterSet) buildRule.getProject().getReference("2");
+        fs = buildRule.getProject().getReference("2");
         filters = fs.getFilterHash();
         assertEquals(2, filters.size());
         assertEquals("1111", filters.get("aaaa"));
         assertEquals("2222", filters.get("bbbb"));
 
-        fs = (FilterSet) buildRule.getProject().getReference("3");
+        fs = buildRule.getProject().getReference("3");
         filters = fs.getFilterHash();
         assertEquals(1, filters.size());
         assertEquals("value4", filters.get("token4"));
 
-        fs = (FilterSet) buildRule.getProject().getReference("5");
+        fs = buildRule.getProject().getReference("5");
         filters = fs.getFilterHash();
         assertEquals(1, filters.size());
         assertEquals("value1", filters.get("token1"));
@@ -189,14 +185,10 @@
         buildRule.executeTarget("testMultipleFiltersFiles");
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testMissingFiltersFile() {
-        try {
-            buildRule.executeTarget("testMissingFiltersFile");
-            fail("should fail due to missing  filtersfile");
-        } catch (BuildException ex) {
-            //TODO assert exception text
-        }
+        buildRule.executeTarget("testMissingFiltersFile");
+        // TODO assert exception text
     }
 
     @Test
@@ -205,15 +197,10 @@
     }
 
     private boolean compareFiles(String name1, String name2) throws IOException {
-        File file1 = new File(System.getProperty("root"), name1);
-        File file2 = new File(System.getProperty("root"), name2);
+        File file1 = buildRule.getProject().resolveFile(name1);
+        File file2 = buildRule.getProject().resolveFile(name2);
 
-
-        if (!file1.exists() || !file2.exists()) {
-            return false;
-        }
-
-        if (file1.length() != file2.length()) {
+        if (!file1.exists() || !file2.exists() || file1.length() != file2.length()) {
             return false;
         }
 
@@ -221,16 +208,15 @@
         byte[] buffer1 = new byte[BUF_SIZE];
         byte[] buffer2 = new byte[BUF_SIZE];
 
-        @SuppressWarnings("resource")
-        FileInputStream fis1 = new FileInputStream(file1);
-        @SuppressWarnings("resource")
-        FileInputStream fis2 = new FileInputStream(file2);
-        int read = 0;
-        while ((read = fis1.read(buffer1)) != -1) {
-            fis2.read(buffer2);
-            for (int i = 0; i < read; ++i) {
-                if (buffer1[i] != buffer2[i]) {
-                    return false;
+        try (FileInputStream fis1 = new FileInputStream(file1);
+             FileInputStream fis2 = new FileInputStream(file2)) {
+            int read = 0;
+            while ((read = fis1.read(buffer1)) != -1) {
+                fis2.read(buffer2);
+                for (int i = 0; i < read; ++i) {
+                    if (buffer1[i] != buffer2[i]) {
+                        return false;
+                    }
                 }
             }
         }
diff --git a/src/tests/junit/org/apache/tools/ant/types/FlexIntegerTest.java b/src/tests/junit/org/apache/tools/ant/types/FlexIntegerTest.java
index dd01ff7..dc1c156 100644
--- a/src/tests/junit/org/apache/tools/ant/types/FlexIntegerTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/FlexIntegerTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -47,11 +47,11 @@
     // This class acts as a custom Ant task also
     // and uses these variables/methods in that mode
     private Project taskProject;
+
     String propName;
+
     private FlexInteger value;
 
-
-
     public void setPropName(String propName) {
         this.propName = propName;
     }
diff --git a/src/tests/junit/org/apache/tools/ant/types/MapperTest.java b/src/tests/junit/org/apache/tools/ant/types/MapperTest.java
index 77c1811..b0e9d6b 100644
--- a/src/tests/junit/org/apache/tools/ant/types/MapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/MapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,12 +32,14 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 /**
  * JUnit testcases for org.apache.tools.ant.types.Mapper.
@@ -49,104 +51,97 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private Project project;
 
+    private Mapper m;
+
     @Before
     public void setUp() {
         project = new Project();
         project.setBasedir(".");
+        m = new Mapper(project);
     }
 
     @Test
-    public void testEmptyElementIfIsReference() {
-        Mapper m = new Mapper(project);
+    public void testEmptyElementIfIsReference1() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         m.setFrom("*.java");
-        try {
-            m.setRefid(new Reference(project, "dummyref"));
-            fail("Can add reference to Mapper with from attribute set");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                    be.getMessage());
-        }
-
-        m = new Mapper(project);
-        m.setRefid(new Reference(project, "dummyref"));
-        try {
-            m.setFrom("*.java");
-            fail("Can set from in Mapper that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                    be.getMessage());
-        }
-
-        m = new Mapper(project);
-        m.setRefid(new Reference(project, "dummyref"));
-        try {
-            m.setTo("*.java");
-            fail("Can set to in Mapper that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                    be.getMessage());
-        }
-        try {
-            Mapper.MapperType mt = new Mapper.MapperType();
-            mt.setValue("glob");
-            m.setType(mt);
-            fail("Can set type in Mapper that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                    be.getMessage());
-        }
+        m.setRefid(new Reference(project, "dummy"));
     }
 
     @Test
-    public void testCircularReferenceCheck() {
-        Mapper m = new Mapper(project);
+    public void testEmptyElementIfIsReference2() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        m.setRefid(new Reference(project, "dummy"));
+        m.setFrom("*.java");
+    }
+
+    @Test
+    public void testEmptyElementIfIsReference3() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        m.setRefid(new Reference(project, "dummy"));
+        m.setTo("*.java");
+    }
+
+    @Test
+    public void testEmptyElementIfIsReference4() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        m.setRefid(new Reference(project, "dummy"));
+        Mapper.MapperType mt = new Mapper.MapperType();
+        mt.setValue("glob");
+        m.setType(mt);
+    }
+
+    @Test
+    public void testCircularReferenceCheck1() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         project.addReference("dummy", m);
         m.setRefid(new Reference(project, "dummy"));
-        try {
-            m.getImplementation();
-            fail("Can make Mapper a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                    be.getMessage());
-        }
+        m.getImplementation();
+    }
 
-        // dummy1 --> dummy2 --> dummy3 --> dummy1
-        Mapper m1 = new Mapper(project);
-        project.addReference("dummy1", m1);
-        m1.setRefid(new Reference(project, "dummy2"));
+    @Test
+    public void testCircularReferenceCheck2() {
+        // dummy --> dummy2 --> dummy3 --> dummy
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        project.addReference("dummy", m);
+        m.setRefid(new Reference(project, "dummy2"));
         Mapper m2 = new Mapper(project);
         project.addReference("dummy2", m2);
         m2.setRefid(new Reference(project, "dummy3"));
         Mapper m3 = new Mapper(project);
         project.addReference("dummy3", m3);
-        m3.setRefid(new Reference(project, "dummy1"));
-        try {
-            m1.getImplementation();
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                    be.getMessage());
-        }
+        m3.setRefid(new Reference(project, "dummy"));
+        m.getImplementation();
+    }
 
-        // dummy1 --> dummy2 --> dummy3
+    @Test
+    public void testCircularReferenceCheck3() {
+        // dummy --> dummy2 --> dummy3
         // (which holds a glob mapper from "*.java" to "*.class"
-        m1 = new Mapper(project);
-        project.addReference("dummy1", m1);
-        m1.setRefid(new Reference(project, "dummy2"));
-        m2 = new Mapper(project);
+        project.addReference("dummy", m);
+        m.setRefid(new Reference(project, "dummy2"));
+        Mapper m2 = new Mapper(project);
         project.addReference("dummy2", m2);
         m2.setRefid(new Reference(project, "dummy3"));
-        m3 = new Mapper(project);
+        Mapper m3 = new Mapper(project);
         project.addReference("dummy3", m3);
         Mapper.MapperType mt = new Mapper.MapperType();
         mt.setValue("glob");
         m3.setType(mt);
         m3.setFrom("*.java");
         m3.setTo("*.class");
-        FileNameMapper fmm = m1.getImplementation();
-        assertTrue("should be glob", fmm instanceof GlobPatternMapper);
+        FileNameMapper fmm = m.getImplementation();
+        assertThat("should be glob", fmm, instanceOf(GlobPatternMapper.class));
         String[] result = fmm.mapFileName("a.java");
         assertEquals("a.java should match", 1, result.length);
         assertEquals("a.class", result[0]);
@@ -166,30 +161,29 @@
         FileNameMapper mapper3 = new MergingMapper();
         mapper3.setTo("mergefile");
 
-        Mapper container = new Mapper(project);
-        container.addConfiguredMapper(mapper1);
-        container.add(mapper2);
-        container.add(mapper3);
+        // m is implicit composite
+        m.addConfiguredMapper(mapper1);
+        m.add(mapper2);
+        m.add(mapper3);
 
-        FileNameMapper fileNameMapper = container.getImplementation();
+        FileNameMapper fileNameMapper = m.getImplementation();
         String[] targets = fileNameMapper.mapFileName("fromfilename");
         assertNotNull("no filenames mapped", targets);
         assertEquals("wrong number of filenames mapped", 3, targets.length);
-        List list = Arrays.asList(targets);
-        assertTrue("cannot find expected target \"tofilename\"",
-                list.contains("tofilename"));
-        assertTrue("cannot find expected target \"fromfilename\"",
-                list.contains("fromfilename"));
-        assertTrue("cannot find expected target \"mergefile\"",
-                list.contains("mergefile"));
+        List<String> list = Arrays.asList(targets);
+        assertThat("cannot find expected target \"tofilename\"", list, hasItem("tofilename"));
+        assertThat("cannot find expected target \"fromfilename\"", list, hasItem("fromfilename"));
+        assertThat("cannot find expected target \"mergefile\"", list, hasItem("mergefile"));
     }
 
+    /**
+     * <pre>
+     * a --> b --> c --- def
+     *              \-- ghi
+     * </pre>
+     */
     @Test
     public void testChained() {
-
-        // a --> b --> c --- def
-        //               \-- ghi
-
         FileNameMapper mapperAB = new GlobPatternMapper();
         mapperAB.setFrom("a");
         mapperAB.setTo("b");
@@ -198,9 +192,6 @@
         mapperBC.setFrom("b");
         mapperBC.setTo("c");
 
-        //implicit composite
-        Mapper mapperCX = new Mapper(project);
-
         FileNameMapper mapperDEF = new GlobPatternMapper();
         mapperDEF.setFrom("c");
         mapperDEF.setTo("def");
@@ -209,22 +200,23 @@
         mapperGHI.setFrom("c");
         mapperGHI.setTo("ghi");
 
-        mapperCX.add(mapperDEF);
-        mapperCX.add(mapperGHI);
+        // m is implicit composite
+        m.add(mapperDEF);
+        m.add(mapperGHI);
 
         Mapper chained = new Mapper(project);
         chained.setClassname(ChainedMapper.class.getName());
         chained.add(mapperAB);
         chained.add(mapperBC);
-        chained.addConfiguredMapper(mapperCX);
+        chained.addConfiguredMapper(m);
 
         FileNameMapper fileNameMapper = chained.getImplementation();
         String[] targets = fileNameMapper.mapFileName("a");
         assertNotNull("no filenames mapped", targets);
         assertEquals("wrong number of filenames mapped", 2, targets.length);
-        List list = Arrays.asList(targets);
-        assertTrue("cannot find expected target \"def\"", list.contains("def"));
-        assertTrue("cannot find expected target \"ghi\"", list.contains("ghi"));
+        List<String> list = Arrays.asList(targets);
+        assertThat("cannot find expected target \"def\"", list, hasItem("def"));
+        assertThat("cannot find expected target \"ghi\"", list, hasItem("ghi"));
 
         targets = fileNameMapper.mapFileName("z");
         assertNull(targets);
diff --git a/src/tests/junit/org/apache/tools/ant/types/ModuleVersionTest.java b/src/tests/junit/org/apache/tools/ant/types/ModuleVersionTest.java
new file mode 100644
index 0000000..ed60724
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/types/ModuleVersionTest.java
@@ -0,0 +1,132 @@
+/*
+ *  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
+ *
+ *      https://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;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests {@link ModuleVersion} class.
+ */
+public class ModuleVersionTest {
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
+
+    @Test
+    public void testModuleVersionStringNumberPreBuild() {
+        ModuleVersion moduleVersion = new ModuleVersion();
+
+        moduleVersion.setNumber("1.1.3");
+        moduleVersion.setPreRelease("ea");
+        moduleVersion.setBuild("25");
+
+        String versionStr = moduleVersion.toModuleVersionString();
+
+        Assert.assertNotNull("Checking for non-null module version string.",
+            versionStr);
+        Assert.assertTrue("Checking for correct module version string.",
+            versionStr.matches("1\\.1\\.3[-+]ea\\+25"));
+    }
+
+    @Test
+    public void testModuleVersionStringNumberPre() {
+        ModuleVersion moduleVersion = new ModuleVersion();
+
+        moduleVersion.setNumber("1.1.3");
+        moduleVersion.setPreRelease("ea");
+
+        String versionStr = moduleVersion.toModuleVersionString();
+
+        Assert.assertNotNull("Checking for non-null module version string.",
+            versionStr);
+        Assert.assertTrue("Checking for correct module version string.",
+            versionStr.matches("1\\.1\\.3[-+]ea"));
+    }
+
+    @Test
+    public void testModuleVersionStringNumberBuild() {
+        ModuleVersion moduleVersion = new ModuleVersion();
+
+        moduleVersion.setNumber("1.1.3");
+        moduleVersion.setBuild("25");
+
+        String versionStr = moduleVersion.toModuleVersionString();
+
+        Assert.assertNotNull("Checking for non-null module version string.",
+            versionStr);
+        Assert.assertTrue("Checking for correct module version string.",
+            versionStr.matches("1\\.1\\.3[-+]\\+25"));
+    }
+
+    @Test
+    public void testModuleVersionStringNumberOnly() {
+        ModuleVersion moduleVersion = new ModuleVersion();
+
+        moduleVersion.setNumber("1.1.3");
+
+        String versionStr = moduleVersion.toModuleVersionString();
+
+        Assert.assertNotNull("Checking for non-null module version string.",
+            versionStr);
+        Assert.assertEquals("Checking for correct module version string.",
+            "1.1.3", versionStr);
+    }
+
+    @Test
+    public void testModuleVersionStringNullNumber() {
+        expected.expect(IllegalStateException.class);
+
+        ModuleVersion moduleVersion = new ModuleVersion();
+        moduleVersion.toModuleVersionString();
+    }
+
+    @Test
+    public void testNullNumber() {
+        expected.expect(NullPointerException.class);
+
+        ModuleVersion moduleVersion = new ModuleVersion();
+        moduleVersion.setNumber(null);
+    }
+
+    @Test
+    public void testInvalidNumber() {
+        expected.expect(IllegalArgumentException.class);
+
+        ModuleVersion moduleVersion = new ModuleVersion();
+        moduleVersion.setNumber("1-1-3");
+    }
+
+    @Test
+    public void testInvalidNumber2() {
+        expected.expect(IllegalArgumentException.class);
+
+        ModuleVersion moduleVersion = new ModuleVersion();
+        moduleVersion.setNumber("1.1+3");
+    }
+
+    @Test
+    public void testInvalidPreRelease() {
+        expected.expect(IllegalArgumentException.class);
+
+        ModuleVersion moduleVersion = new ModuleVersion();
+        moduleVersion.setNumber("1.1.3");
+        moduleVersion.setPreRelease("ea+interim");
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/types/PathTest.java b/src/tests/junit/org/apache/tools/ant/types/PathTest.java
index b75e9f5..47ad498 100644
--- a/src/tests/junit/org/apache/tools/ant/types/PathTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/PathTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,17 +19,22 @@
 package org.apache.tools.ant.types;
 
 import java.io.File;
+import java.nio.file.Paths;
 import java.util.Locale;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicTestNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.condition.Os;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
+import static org.hamcrest.Matchers.endsWith;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 
 /**
  * JUnit testcases for org.apache.tools.ant.types.Path
@@ -42,17 +47,24 @@
     public static boolean isNetWare = Os.isFamily("netware");
 
     private Project project;
+    private Path p;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Before
     public void setUp() {
         project = new Project();
-        project.setBasedir(System.getProperty("root"));
+        if (System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY) != null) {
+            project.setBasedir(System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY));
+        }
+        p = new Path(project);
     }
 
     // actually tests constructor as well as setPath
     @Test
     public void testConstructorUnixStyle() {
-        Path p = new Path(project, "/a:/b");
+        p = new Path(project, "/a:/b");
         String[] l = p.list();
         assertEquals("two items, Unix style", 2, l.length);
         if (isUnixStyle) {
@@ -70,31 +82,31 @@
 
     @Test
     public void testRelativePathUnixStyle() {
-        project.setBasedir(new File(System.getProperty("root"), "src/etc").getAbsolutePath());
-        Path p = new Path(project, "..:testcases");
+        project.setBasedir(new File(project.getBaseDir(), "src/etc").getAbsolutePath());
+        p = new Path(project, "..:testcases");
         String[] l = p.list();
         assertEquals("two items, Unix style", 2, l.length);
         if (isUnixStyle) {
-           assertTrue("test resolved relative to src/etc",
-                 l[0].endsWith("/src"));
-           assertTrue("test resolved relative to src/etc",
-                 l[1].endsWith("/src/etc/testcases"));
+           assertThat("test resolved relative to src/etc",
+                 l[0], endsWith("/src"));
+           assertThat("test resolved relative to src/etc",
+                 l[1], endsWith("/src/etc/testcases"));
         } else if (isNetWare) {
-           assertTrue("test resolved relative to src/etc",
-                 l[0].endsWith("\\src"));
-           assertTrue("test resolved relative to src/etc",
-                 l[1].endsWith("\\src\\etc\\testcases"));
+           assertThat("test resolved relative to src/etc",
+                 l[0], endsWith("\\src"));
+           assertThat("test resolved relative to src/etc",
+                 l[1], endsWith("\\src\\etc\\testcases"));
         } else {
-           assertTrue("test resolved relative to src/etc",
-                 l[0].endsWith("\\src"));
-           assertTrue("test resolved relative to src/etc",
-                 l[1].endsWith("\\src\\etc\\testcases"));
+           assertThat("test resolved relative to src/etc",
+                 l[0], endsWith("\\src"));
+           assertThat("test resolved relative to src/etc",
+                 l[1], endsWith("\\src\\etc\\testcases"));
         }
     }
 
     @Test
-    public void testConstructorWindowsStyle() {
-        Path p = new Path(project, "\\a;\\b");
+    public void testConstructorWindowsStyleTwoItemsNoDrive() {
+        p = new Path(project, "\\a;\\b");
         String[] l = p.list();
         assertEquals("two items, DOS style", 2, l.length);
         if (isUnixStyle) {
@@ -108,13 +120,16 @@
             assertEquals(base + "a", l[0]);
             assertEquals(base + "b", l[1]);
         }
+    }
 
+    @Test
+    public void testConstructorWindowsStyle() {
         p = new Path(project, "c:\\test");
-        l = p.list();
+        String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 2, l.length);
-            assertTrue("c resolved relative to project\'s basedir",
-                   l[0].endsWith("/c"));
+            assertThat("c resolved relative to project's basedir",
+                   l[0], endsWith("/c"));
             assertEquals("/test", l[1]);
         } else if (isNetWare) {
             assertEquals("volumes on NetWare", 1, l.length);
@@ -123,51 +138,19 @@
             assertEquals("drives on DOS", 1, l.length);
             assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
         }
+    }
 
+    @Test
+    public void testConstructorWindowsStyleTwoItems() {
         p = new Path(project, "c:\\test;d:\\programs");
-        l = p.list();
+        String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 4, l.length);
-            assertTrue("c resolved relative to project\'s basedir",
-                   l[0].endsWith("/c"));
+            assertThat("c resolved relative to project's basedir",
+                   l[0], endsWith("/c"));
             assertEquals("/test", l[1]);
-            assertTrue("d resolved relative to project\'s basedir",
-                   l[2].endsWith("/d"));
-            assertEquals("/programs", l[3]);
-        } else if (isNetWare) {
-            assertEquals("volumes on NetWare", 2, l.length);
-            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
-            assertEquals("d:\\programs", l[1].toLowerCase(Locale.US));
-        } else {
-            assertEquals("drives on DOS", 2, l.length);
-            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
-            assertEquals("d:\\programs", l[1].toLowerCase(Locale.US));
-        }
-
-        p = new Path(project, "c:/test");
-        l = p.list();
-        if (isUnixStyle) {
-            assertEquals("no drives on Unix", 2, l.length);
-            assertTrue("c resolved relative to project\'s basedir",
-                   l[0].endsWith("/c"));
-            assertEquals("/test", l[1]);
-        } else if (isNetWare) {
-            assertEquals("volumes on NetWare", 1, l.length);
-            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
-        } else {
-            assertEquals("drives on DOS", 1, l.length);
-            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
-        }
-
-        p = new Path(project, "c:/test;d:/programs");
-        l = p.list();
-        if (isUnixStyle) {
-            assertEquals("no drives on Unix", 4, l.length);
-            assertTrue("c resolved relative to project\'s basedir",
-                   l[0].endsWith("/c"));
-            assertEquals("/test", l[1]);
-            assertTrue("d resolved relative to project\'s basedir",
-                   l[2].endsWith("/d"));
+            assertThat("d resolved relative to project's basedir",
+                   l[2], endsWith("/d"));
             assertEquals("/programs", l[3]);
         } else if (isNetWare) {
             assertEquals("volumes on NetWare", 2, l.length);
@@ -181,82 +164,80 @@
     }
 
     @Test
-    public void testConstructorNetWareStyle() {
-        // try a netware-volume length path, see how it is handled
-        Path p = new Path(project, "sys:\\test");
+    public void testConstructorWindowsStyleUnixFS() {
+        p = new Path(project, "c:/test");
         String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 2, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("/sys"));
+            assertThat("c resolved relative to project's basedir",
+                   l[0], endsWith("/c"));
             assertEquals("/test", l[1]);
         } else if (isNetWare) {
-            assertEquals("sys:\\test", l[0].toLowerCase(Locale.US));
             assertEquals("volumes on NetWare", 1, l.length);
+            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
         } else {
-            assertEquals("no multiple character-length volumes on Windows", 2, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("\\sys"));
-            assertTrue("test resolved relative to project\'s basedir",
-                   l[1].endsWith("\\test"));
+            assertEquals("drives on DOS", 1, l.length);
+            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
         }
+    }
 
-        // try a multi-part netware-volume length path, see how it is handled
-        p = new Path(project, "sys:\\test;dev:\\temp");
-        l = p.list();
+    @Test
+    public void testConstructorWindowsStyleUnixFSTwoItems() {
+        p = new Path(project, "c:/test;d:/programs");
+        String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 4, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("/sys"));
+            assertThat("c resolved relative to project's basedir",
+                   l[0], endsWith("/c"));
             assertEquals("/test", l[1]);
-            assertTrue("dev resolved relative to project\'s basedir",
-                   l[2].endsWith("/dev"));
-            assertEquals("/temp", l[3]);
+            assertThat("d resolved relative to project's basedir",
+                   l[2], endsWith("/d"));
+            assertEquals("/programs", l[3]);
         } else if (isNetWare) {
             assertEquals("volumes on NetWare", 2, l.length);
-            assertEquals("sys:\\test", l[0].toLowerCase(Locale.US));
-            assertEquals("dev:\\temp", l[1].toLowerCase(Locale.US));
+            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
+            assertEquals("d:\\programs", l[1].toLowerCase(Locale.US));
         } else {
-            assertEquals("no multiple character-length volumes on Windows", 4, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("\\sys"));
-            assertTrue("test resolved relative to project\'s basedir",
-                   l[1].endsWith("\\test"));
-            assertTrue("dev resolved relative to project\'s basedir",
-                   l[2].endsWith("\\dev"));
-            assertTrue("temp resolved relative to project\'s basedir",
-                   l[3].endsWith("\\temp"));
+            assertEquals("drives on DOS", 2, l.length);
+            assertEquals("c:\\test", l[0].toLowerCase(Locale.US));
+            assertEquals("d:\\programs", l[1].toLowerCase(Locale.US));
         }
+    }
 
-        // try a netware-volume length path w/forward slash, see how it is handled
-        p = new Path(project, "sys:/test");
-        l = p.list();
+    // try a netware-volume length path, see how it is handled
+    @Test
+    public void testConstructorNetWareStyle() {
+        p = new Path(project, "sys:\\test");
+        String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 2, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("/sys"));
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("/sys"));
             assertEquals("/test", l[1]);
         } else if (isNetWare) {
-            assertEquals("volumes on NetWare", 1, l.length);
             assertEquals("sys:\\test", l[0].toLowerCase(Locale.US));
+            assertEquals("volumes on NetWare", 1, l.length);
         } else {
             assertEquals("no multiple character-length volumes on Windows", 2, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("\\sys"));
-            assertTrue("test resolved relative to project\'s basedir",
-                   l[1].endsWith("\\test"));
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("\\sys"));
+            assertThat("test resolved relative to project's basedir",
+                   l[1], endsWith("\\test"));
         }
+    }
 
-        // try a multi-part netware-volume length path w/forward slash, see how it is handled
-        p = new Path(project, "sys:/test;dev:/temp");
-        l = p.list();
+    // try a multi-part netware-volume length path, see how it is handled
+    @Test
+    public void testConstructorNetWareStyleTwoItems() {
+        p = new Path(project, "sys:\\test;dev:\\temp");
+        String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 4, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("/sys"));
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("/sys"));
             assertEquals("/test", l[1]);
-            assertTrue("dev resolved relative to project\'s basedir",
-                   l[2].endsWith("/dev"));
+            assertThat("dev resolved relative to project's basedir",
+                   l[2], endsWith("/dev"));
             assertEquals("/temp", l[3]);
         } else if (isNetWare) {
             assertEquals("volumes on NetWare", 2, l.length);
@@ -264,26 +245,80 @@
             assertEquals("dev:\\temp", l[1].toLowerCase(Locale.US));
         } else {
             assertEquals("no multiple character-length volumes on Windows", 4, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("\\sys"));
-            assertTrue("test resolved relative to project\'s basedir",
-                   l[1].endsWith("\\test"));
-            assertTrue("dev resolved relative to project\'s basedir",
-                   l[2].endsWith("\\dev"));
-            assertTrue("temp resolved relative to project\'s basedir",
-                   l[3].endsWith("\\temp"));
-         }
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("\\sys"));
+            assertThat("test resolved relative to project's basedir",
+                   l[1], endsWith("\\test"));
+            assertThat("dev resolved relative to project's basedir",
+                   l[2], endsWith("\\dev"));
+            assertThat("temp resolved relative to project's basedir",
+                   l[3], endsWith("\\temp"));
+        }
+    }
 
-        // try a multi-part netware-volume length path with UNIX
-        // separator (this testcase if from an actual bug that was
-        // found, in AvailableTest, which uses PathTokenizer)
-        p = new Path(project,
-                     "SYS:\\JAVA/lib/rt.jar:SYS:\\JAVA/lib/classes.zip");
-        l = p.list();
+    // try a netware-volume length path w/forward slash, see how it is handled
+    @Test
+    public void testConstructorNetWareStyleUnixFS() {
+        p = new Path(project, "sys:/test");
+        String[] l = p.list();
+        if (isUnixStyle) {
+            assertEquals("no drives on Unix", 2, l.length);
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("/sys"));
+            assertEquals("/test", l[1]);
+        } else if (isNetWare) {
+            assertEquals("volumes on NetWare", 1, l.length);
+            assertEquals("sys:\\test", l[0].toLowerCase(Locale.US));
+        } else {
+            assertEquals("no multiple character-length volumes on Windows", 2, l.length);
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("\\sys"));
+            assertThat("test resolved relative to project's basedir",
+                   l[1], endsWith("\\test"));
+        }
+    }
+
+    // try a multi-part netware-volume length path w/forward slash, see how it is handled
+    @Test
+    public void testConstructorNetWareStyleUnixFSTwoItems() {
+        p = new Path(project, "sys:/test;dev:/temp");
+        String[] l = p.list();
+        if (isUnixStyle) {
+            assertEquals("no drives on Unix", 4, l.length);
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("/sys"));
+            assertEquals("/test", l[1]);
+            assertThat("dev resolved relative to project's basedir",
+                   l[2], endsWith("/dev"));
+            assertEquals("/temp", l[3]);
+        } else if (isNetWare) {
+            assertEquals("volumes on NetWare", 2, l.length);
+            assertEquals("sys:\\test", l[0].toLowerCase(Locale.US));
+            assertEquals("dev:\\temp", l[1].toLowerCase(Locale.US));
+        } else {
+            assertEquals("no multiple character-length volumes on Windows", 4, l.length);
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("\\sys"));
+            assertThat("test resolved relative to project's basedir",
+                   l[1], endsWith("\\test"));
+            assertThat("dev resolved relative to project's basedir",
+                   l[2], endsWith("\\dev"));
+            assertThat("temp resolved relative to project's basedir",
+                   l[3], endsWith("\\temp"));
+         }
+    }
+
+    // try a multi-part netware-volume length path with UNIX
+    // separator (this testcase if from an actual bug that was
+    // found, in AvailableTest, which uses PathTokenizer)
+    @Test
+    public void testConstructorNetWareStyleUnixPS() {
+        p = new Path(project, "SYS:\\JAVA/lib/rt.jar:SYS:\\JAVA/lib/classes.zip");
+        String[] l = p.list();
         if (isUnixStyle) {
             assertEquals("no drives on Unix", 3, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("/SYS"));
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("/SYS"));
             assertEquals("/JAVA/lib/rt.jar", l[1]);
             assertEquals("/JAVA/lib/classes.zip", l[2]);
         } else if (isNetWare) {
@@ -292,18 +327,18 @@
             assertEquals("sys:\\java\\lib\\classes.zip", l[1].toLowerCase(Locale.US));
         } else {
             assertEquals("no multiple character-length volumes on Windows", 3, l.length);
-            assertTrue("sys resolved relative to project\'s basedir",
-                   l[0].endsWith("\\SYS"));
-            assertTrue("java/lib/rt.jar resolved relative to project\'s basedir",
-                   l[1].endsWith("\\JAVA\\lib\\rt.jar"));
-            assertTrue("java/lib/classes.zip resolved relative to project\'s basedir",
-                   l[2].endsWith("\\JAVA\\lib\\classes.zip"));
+            assertThat("sys resolved relative to project's basedir",
+                   l[0], endsWith("\\SYS"));
+            assertThat("java/lib/rt.jar resolved relative to project's basedir",
+                   l[1], endsWith("\\JAVA\\lib\\rt.jar"));
+            assertThat("java/lib/classes.zip resolved relative to project's basedir",
+                   l[2], endsWith("\\JAVA\\lib\\classes.zip"));
         }
     }
 
     @Test
     public void testConstructorMixedStyle() {
-        Path p = new Path(project, "\\a;\\b:/c");
+        p = new Path(project, "\\a;\\b:/c");
         String[] l = p.list();
         assertEquals("three items, mixed style", 3, l.length);
         if (isUnixStyle) {
@@ -324,7 +359,6 @@
 
     @Test
     public void testSetLocation() {
-        Path p = new Path(project);
         p.setLocation(new File(File.separatorChar + "a"));
         String[] l = p.list();
         if (isUnixStyle) {
@@ -341,7 +375,7 @@
 
     @Test
     public void testAppending() {
-        Path p = new Path(project, "/a:/b");
+        p = new Path(project, "/a:/b");
         String[] l = p.list();
         assertEquals("2 after construction", 2, l.length);
         p.setLocation(new File("/c"));
@@ -360,7 +394,7 @@
 
     @Test
     public void testEmptyPath() {
-        Path p = new Path(project, "");
+        p = new Path(project, "");
         String[] l = p.list();
         assertEquals("0 after construction", 0, l.length);
         p.setPath("");
@@ -376,7 +410,7 @@
 
     @Test
     public void testUnique() {
-        Path p = new Path(project, "/a:/a");
+        p = new Path(project, "/a:/a");
         String[] l = p.list();
         assertEquals("1 after construction", 1, l.length);
         String base = new File(File.separator).getAbsolutePath();
@@ -395,125 +429,112 @@
     }
 
     @Test
-    public void testEmptyElementIfIsReference() {
-        Path p = new Path(project, "/a:/a");
-        try {
-            p.setRefid(new Reference(project, "dummyref"));
-            fail("Can add reference to Path with elements from constructor");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
+    public void testEmptyElementSetRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        p = new Path(project, "/a:/a");
+        p.setRefid(new Reference(project, "dummyref"));
+    }
 
-        p = new Path(project);
+    @Test
+    public void testEmptyElementSetLocationThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         p.setLocation(new File("/a"));
-        try {
-            p.setRefid(new Reference(project, "dummyref"));
-            fail("Can add reference to Path with elements from setLocation");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
+        p.setRefid(new Reference(project, "dummyref"));
+    }
 
+    @Test
+    public void testUseExistingRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         Path another = new Path(project, "/a:/a");
         project.addReference("dummyref", another);
-        p = new Path(project);
         p.setRefid(new Reference(project, "dummyref"));
-        try {
-            p.setLocation(new File("/a"));
-            fail("Can set location in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
+        p.setLocation(new File("/a"));
+    }
 
-        try {
-            p.setPath("/a;\\a");
-            fail("Can set path in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementIfIsReferenceAttr() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.setPath("/a;\\a");
+    }
 
-        try {
-            p.createPath();
-            fail("Can create nested Path in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementCreatePath() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.createPath();
+    }
 
-        try {
-            p.createPathElement();
-            fail("Can create nested PathElement in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementCreatePathElement() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.createPathElement();
+    }
 
-        try {
-            p.addFileset(new FileSet());
-            fail("Can add nested FileSet in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementAddFileset() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.addFileset(new FileSet());
+    }
 
-        try {
-            p.addFilelist(new FileList());
-            fail("Can add nested FileList in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementAddFilelist() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.addFilelist(new FileList());
+    }
 
-        try {
-            p.addDirset(new DirSet());
-            fail("Can add nested Dirset in Path that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementAddDirset() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.addDirset(new DirSet());
     }
 
     @Test
     public void testCircularReferenceCheck() {
-        Path p = new Path(project);
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         project.addReference("dummy", p);
         p.setRefid(new Reference(project, "dummy"));
-        try {
-            p.list();
-            fail("Can make Path a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        p.list();
+    }
 
+    @Test
+    public void testLoopReferenceCheck() {
         // dummy1 --> dummy2 --> dummy3 --> dummy1
-        Path p1 = new Path(project);
-        project.addReference("dummy1", p1);
-        Path p2 = p1.createPath();
-        project.addReference("dummy2", p2);
-        Path p3 = p2.createPath();
-        project.addReference("dummy3", p3);
-        p3.setRefid(new Reference(project, "dummy1"));
-        try {
-            p1.list();
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        project.addReference("dummy1", p);
+        Path pa = p.createPath();
+        project.addReference("dummy2", pa);
+        Path pb = pa.createPath();
+        project.addReference("dummy3", pb);
+        pb.setRefid(new Reference(project, "dummy1"));
+        p.list();
+    }
 
+    @Test
+    public void testLoopReferenceCheckWithLocation() {
         // dummy1 --> dummy2 --> dummy3 (with Path "/a")
-        p1 = new Path(project);
-        project.addReference("dummy1", p1);
-        p2 = p1.createPath();
-        project.addReference("dummy2", p2);
-        p3 = p2.createPath();
-        project.addReference("dummy3", p3);
-        p3.setLocation(new File("/a"));
-        String[] l = p1.list();
+        project.addReference("dummy1", p);
+        Path pa = p.createPath();
+        project.addReference("dummy2", pa);
+        Path pb = pa.createPath();
+        project.addReference("dummy3", pb);
+        pb.setLocation(new File("/a"));
+        String[] l = p.list();
         assertEquals("One element buried deep inside a nested path structure",
                      1, l.length);
         if (isUnixStyle) {
@@ -527,7 +548,6 @@
 
     @Test
     public void testFileList() {
-        Path p = new Path(project);
         FileList f = new FileList();
         f.setProject(project);
         f.setDir(project.resolveFile("."));
@@ -540,7 +560,6 @@
 
     @Test
     public void testFileSet() {
-        Path p = new Path(project);
         FileSet f = new FileSet();
         f.setProject(project);
         f.setDir(project.resolveFile("."));
@@ -553,26 +572,28 @@
 
     @Test
     public void testDirSet() {
-        Path p = new Path(project);
         DirSet d = new DirSet();
         d.setProject(project);
         d.setDir(project.resolveFile("."));
-        d.setIncludes("build");
+        String s = System.getProperty("build.tests.value");
+        assertNotNull("build.tests.value not set", s);
+        String n = Paths.get(s).getParent().getFileName().toString().equals("ant")
+                ? "target" : "build";
+        d.setIncludes(n);
         p.addDirset(d);
         String[] l = p.list();
         assertEquals(1, l.length);
-        assertEquals(project.resolveFile("build").getAbsolutePath(), l[0]);
+        assertEquals(project.resolveFile(n).getAbsolutePath(), l[0]);
     }
 
     @Test
     public void testRecursion() {
-        Path p = new Path(project);
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("circular");
         try {
             p.append(p);
+        } finally {
             assertEquals(0, p.list().length);
-        } catch (BuildException x) {
-            String m = x.toString();
-            assertTrue(m, m.contains("circular"));
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java b/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java
index 6baecbb..d931ae0 100644
--- a/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/PatternSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,20 +20,22 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
-import org.apache.tools.ant.util.FileUtils;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit 4 testcases for org.apache.tools.ant.types.PatternSet.
@@ -43,151 +45,163 @@
 
 public class PatternSetTest {
 
+    @Rule
+    public TemporaryFolder testFolder = new TemporaryFolder();
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     private Project project;
 
+    private PatternSet p;
+
     @Before
     public void setUp() {
         project = new Project();
         project.setBasedir(".");
+        p = new PatternSet();
     }
 
     @Test
-    public void testEmptyElementIfIsReference() {
-        PatternSet p = new PatternSet();
+    public void testEmptyElementSetIncludesThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         p.setIncludes("**/*.java");
-        try {
-            p.setRefid(new Reference(project, "dummyref"));
-            fail("Can add reference to PatternSet with elements from setIncludes");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-
-        p = new PatternSet();
         p.setRefid(new Reference(project, "dummyref"));
-        try {
-            p.setIncludes("**/*.java");
-            fail("Can set includes in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-
-        p = new PatternSet();
-        p.setRefid(new Reference(project, "dummyref"));
-        try {
-            p.setIncludesfile(new File("/a"));
-            fail("Can set includesfile in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-        try {
-            p.setExcludes("**/*.java");
-            fail("Can set excludes in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-        try {
-            p.setExcludesfile(new File("/a"));
-            fail("Can set excludesfile in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-        try {
-            p.createInclude();
-            fail("Can add nested include in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
-        try {
-            p.createExclude();
-            fail("Can add nested exclude in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
-        try {
-            p.createIncludesFile();
-            fail("Can add nested includesfile in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
-        try {
-            p.createExcludesFile();
-            fail("Can add nested excludesfile in PatternSet that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
     }
 
     @Test
-    public void testCircularReferenceCheck() {
-        PatternSet p = new PatternSet();
+    public void testEmptyElementSetRefidThenIncludes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.setIncludes("**/*.java");
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenIncludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+            p.setIncludesfile(new File("/a"));
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenExclude() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.setExcludes("**/*.java");
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenExcludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.setExcludesfile(new File("/a"));
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenAddInclude() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.createInclude();
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenAddExclude() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.createExclude();
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenAddIncludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.createIncludesFile();
+    }
+
+    @Test
+    public void testEmptyElementSetRefidThenAddExcludesfile() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        p.setRefid(new Reference(project, "dummyref"));
+        p.createExcludesFile();
+    }
+
+    @Test
+    public void testCircularReferenceCheckIncludePaterns() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         project.addReference("dummy", p);
         p.setRefid(new Reference(project, "dummy"));
-        try {
-            p.getIncludePatterns(project);
-            fail("Can make PatternSet a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
-        try {
-            p.getExcludePatterns(project);
-            fail("Can make PatternSet a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        p.getIncludePatterns(project);
+    }
 
-        // dummy1 --> dummy2 --> dummy3 --> dummy1
-        PatternSet p1 = new PatternSet();
-        project.addReference("dummy1", p1);
-        p1.setRefid(new Reference(project, "dummy2"));
-        PatternSet p2 = new PatternSet();
-        project.addReference("dummy2", p2);
-        p2.setRefid(new Reference(project, "dummy3"));
-        PatternSet p3 = new PatternSet();
-        project.addReference("dummy3", p3);
-        p3.setRefid(new Reference(project, "dummy1"));
-        try {
-            p1.getIncludePatterns(project);
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
-        try {
-            p1.getExcludePatterns(project);
-            fail("Can make circular reference.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+    @Test
+    public void testCircularReferenceCheckExcludePatterns() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        project.addReference("dummy", p);
+        p.setRefid(new Reference(project, "dummy"));
+        p.getExcludePatterns(project);
+    }
 
-        // dummy1 --> dummy2 --> dummy3
+    @Test
+    public void testLoopReferenceCheckIncludePaterns() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        // dummy --> dummyA --> dummyB --> dummy
+        project.addReference("dummy", p);
+        p.setRefid(new Reference(project, "dummyA"));
+        PatternSet pa = new PatternSet();
+        project.addReference("dummyA", pa);
+        pa.setRefid(new Reference(project, "dummyB"));
+        PatternSet pb = new PatternSet();
+        project.addReference("dummyB", pb);
+        pb.setRefid(new Reference(project, "dummy"));
+        p.getIncludePatterns(project);
+    }
+
+    @Test
+    public void testLoopReferenceCheckExcludePaterns() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        // dummy --> dummyA --> dummyB --> dummy
+        project.addReference("dummy", p);
+        p.setRefid(new Reference(project, "dummyA"));
+        PatternSet pa = new PatternSet();
+        project.addReference("dummyA", pa);
+        pa.setRefid(new Reference(project, "dummyB"));
+        PatternSet pb = new PatternSet();
+        project.addReference("dummyB", pb);
+        pb.setRefid(new Reference(project, "dummy"));
+        p.getExcludePatterns(project);
+    }
+
+    @Test
+    public void testLoopReferenceCheck() {
+        // dummy --> dummyA --> dummyB
         // (which holds patterns "include" and "exclude")
-        p1 = new PatternSet();
-        project.addReference("dummy1", p1);
-        p1.setRefid(new Reference(project, "dummy2"));
-        p2 = new PatternSet();
-        project.addReference("dummy2", p2);
-        p2.setRefid(new Reference(project, "dummy3"));
-        p3 = new PatternSet();
-        project.addReference("dummy3", p3);
-        p3.setIncludes("include");
-        p3.createExclude().setName("exclude");
-        String[] i = p1.getIncludePatterns(project);
+        project.addReference("dummy", p);
+        p.setRefid(new Reference(project, "dummyA"));
+        PatternSet pa = new PatternSet();
+        project.addReference("dummyA", pa);
+        pa.setRefid(new Reference(project, "dummyB"));
+        PatternSet pb = new PatternSet();
+        project.addReference("dummyB", pb);
+        pb.setIncludes("include");
+        pb.createExclude().setName("exclude");
+        String[] i = p.getIncludePatterns(project);
         assertEquals("One include pattern buried deep inside a nested patternset structure",
                      1, i.length);
         assertEquals("include", i[0]);
-        i = p3.getExcludePatterns(project);
+        i = pb.getExcludePatterns(project);
         assertEquals("One exclude pattern buried deep inside a nested patternset structure",
                      1, i.length);
         assertEquals("exclude", i[0]);
@@ -195,7 +209,6 @@
 
     @Test
     public void testNestedPatternset() {
-        PatternSet p = new PatternSet();
         p.setIncludes("**/*.java");
 
         PatternSet nested = new PatternSet();
@@ -212,23 +225,15 @@
 
     @Test
     public void testEncodingOfIncludesFile() throws IOException {
-        File testFile = File.createTempFile("ant-", ".pattern");
-        testFile.deleteOnExit();
-        OutputStream o = null;
-        Writer w = null;
-        try {
-            o = new FileOutputStream(testFile);
-            w = new OutputStreamWriter(o, "UTF-16LE");
+        File testFile = testFolder.newFile("ant.pattern");
+        Charset cs = StandardCharsets.UTF_16LE;
+        try (Writer w = new OutputStreamWriter(new FileOutputStream(testFile), cs)) {
             w.write("\u00e4\n");
-        } finally {
-            FileUtils.close(w);
-            FileUtils.close(o);
         }
-        PatternSet p = new PatternSet();
         PatternSet.PatternFileNameEntry ne =
-            (PatternSet.PatternFileNameEntry) p.createIncludesFile();
+                (PatternSet.PatternFileNameEntry) p.createIncludesFile();
         ne.setName(testFile.getAbsolutePath());
-        ne.setEncoding("UTF-16LE");
-        assertArrayEquals(new String[] { "\u00e4" }, p.getIncludePatterns(project));
+        ne.setEncoding(cs.name());
+        assertArrayEquals(new String[] {"\u00e4"}, p.getIncludePatterns(project));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java b/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java
index 0912588..bbc7f1f 100644
--- a/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,16 +19,23 @@
 package org.apache.tools.ant.types;
 
 import org.apache.tools.ant.ExitException;
+import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasProperty;
 
 /**
  * JUnit 4 testcases for org.apache.tools.ant.types.Permissions.
  */
 public class PermissionsTest {
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     Permissions perms;
 
     @Before
@@ -67,90 +74,62 @@
         perm.setName("os.*");
         perm.setClass("java.util.PropertyPermission");
         perms.addConfiguredRevoke(perm);
+
+        // Allow loading Hamcrest Matcher classes on demand
+        perm = new Permissions.Permission();
+        perm.setActions("read");
+        perm.setName("<<ALL FILES>>");
+        perm.setClass("java.io.FilePermission");
+        perms.addConfiguredGrant(perm);
+
+        perms.setSecurityManager();
+    }
+
+    @After
+    public void tearDown() {
+        perms.restoreSecurityManager();
     }
 
     /** Tests a permission that is granted per default. */
     @Test
     public void testDefaultGranted() {
-        perms.setSecurityManager();
-        try {
-            System.getProperty("line.separator");
-        } finally {
-            perms.restoreSecurityManager();
-        }
+        System.getProperty("line.separator");
     }
 
     /** Tests a permission that has been granted later via wildcard. */
     @Test
     public void testGranted() {
-        perms.setSecurityManager();
-        try {
-            String s = System.getProperty("user.name");
-            System.setProperty("user.name", s);
-        } finally {
-            perms.restoreSecurityManager();
-        }
+        System.setProperty("user.name", System.getProperty("user.name"));
     }
 
     /** Tests a permission that has been granted and revoked later. */
-    @Test
+    @Test(expected = SecurityException.class)
     public void testGrantedAndRevoked() {
-        perms.setSecurityManager();
-        try {
-            String s = System.getProperty("user.home");
-            System.setProperty("user.home", s);
-            fail("Could perform an action that should have been forbidden.");
-        } catch (SecurityException e) {
-            // Was expected, test passes
-        } finally {
-            perms.restoreSecurityManager();
-        }
+        System.setProperty("user.home", System.getProperty("user.home"));
     }
 
     /** Tests a permission that is granted as per default but revoked later via wildcard. */
-    @Test
+    @Test(expected = SecurityException.class)
     public void testDefaultRevoked() {
-        perms.setSecurityManager();
-        try {
-            System.getProperty("os.name");
-            fail("Could perform an action that should have been forbidden.");
-        } catch (SecurityException e) {
-            // Was expected, test passes
-        } finally {
-            perms.restoreSecurityManager();
-        }
+        System.getProperty("os.name");
     }
+
     /** Tests a permission that has not been granted or revoked. */
-    @Test
+    @Test(expected = SecurityException.class)
     public void testOther() {
-        String ls = System.getProperty("line.separator");
-        perms.setSecurityManager();
-        try {
-            System.setProperty("line.separator",ls);
-            fail("Could perform an action that should have been forbidden.");
-        } catch (SecurityException e) {
-            //TODO assert exception message
-            // Was expected, test passes
-        } finally {
-            perms.restoreSecurityManager();
-        }
+        System.setProperty("line.separator", System.lineSeparator());
     }
 
     /** Tests an exit condition. */
     @Test
     public void testExit() {
-        perms.setSecurityManager();
+        thrown.expect(ExitException.class);
+        thrown.expect(hasProperty("status", equalTo(3)));
         try {
             System.out.println("If this is the last line on standard out the testExit f.a.i.l.e.d");
             System.exit(3);
-            fail("Totally impossible that this fail is ever executed. Please let me know if it is!");
-        } catch (ExitException e) {
-            if (e.getStatus() != 3) {
-                fail("Received wrong exit status in Exit Exception.");
-            }
-            System.out.println("testExit successful.");
         } finally {
-            perms.restoreSecurityManager();
+            System.out.println("testExit successful.");
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/types/PolyTest.java b/src/tests/junit/org/apache/tools/ant/types/PolyTest.java
index 73ffff4..44ae0d1 100644
--- a/src/tests/junit/org/apache/tools/ant/types/PolyTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/PolyTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,38 @@
 
 package org.apache.tools.ant.types;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+
+@RunWith(Parameterized.class)
 public class PolyTest {
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> targets() {
+        return Arrays.asList(new Object[][]{
+                {"fileset", "types.FileSet"},
+                {"fileset-ant-type", "types.PolyTest$MyFileSet"},
+                {"path", "types.Path"},
+                {"path-ant-type", "types.PolyTest$MyPath"}
+        });
+    }
+
+    @Parameterized.Parameter
+    public String targetName;
+
+    @Parameterized.Parameter(1)
+    public String outcome;
 
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
@@ -37,27 +60,9 @@
     }
 
     @Test
-    public void testFileSet() {
-        buildRule.executeTarget("fileset");
-        AntAssert.assertContains("types.FileSet", buildRule.getLog());
-    }
-
-    @Test
-    public void testFileSetAntType() {
-        buildRule.executeTarget("fileset-ant-type");
-        AntAssert.assertContains("types.PolyTest$MyFileSet", buildRule.getLog());
-    }
-
-    @Test
-    public void testPath() {
-        buildRule.executeTarget("path");
-        AntAssert.assertContains("types.Path", buildRule.getLog());
-    }
-
-    @Test
-    public void testPathAntType() {
-        buildRule.executeTarget("path-ant-type");
-        AntAssert.assertContains("types.PolyTest$MyPath", buildRule.getLog());
+    public void test() {
+        buildRule.executeTarget(targetName);
+        assertThat(buildRule.getLog(), containsString(outcome));
     }
 
     public static class MyFileSet extends FileSet {
diff --git a/src/tests/junit/org/apache/tools/ant/types/RedirectorElementTest.java b/src/tests/junit/org/apache/tools/ant/types/RedirectorElementTest.java
index 9ed6ef6..c9acb49 100644
--- a/src/tests/junit/org/apache/tools/ant/types/RedirectorElementTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/RedirectorElementTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,7 +17,6 @@
  */
 package org.apache.tools.ant.types;
 
-import org.apache.tools.ant.AntAssert;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
@@ -25,8 +24,9 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 public class RedirectorElementTest {
 
@@ -41,28 +41,24 @@
     @Test
     public void test1() {
         buildRule.executeTarget("test1");
-        assertTrue((buildRule.getProject().<Object> getReference("test1")
+        assertTrue((buildRule.getProject().getReference("test1")
             instanceof RedirectorElement));
     }
 
-    @Test
+    /**
+     * Expected failure due to multiple attributes when using refid
+     */
+    @Test(expected = BuildException.class)
     public void test2() {
-        try {
-            buildRule.executeTarget("test2");
-            fail("You must not specify more than one attribute when using refid");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test2");
     }
 
-    @Test
+    /**
+     * Expected failure due to nested elements when using refid
+     */
+    @Test(expected = BuildException.class)
     public void test3() {
-        try {
-            buildRule.executeTarget("test3");
-            fail("You must not specify nested elements when using refid");
-        } catch (BuildException ex) {
-            //TODO assert exception message
-        }
+        buildRule.executeTarget("test3");
     }
 
     @Test
@@ -74,7 +70,7 @@
     public void testLogInputString() {
         buildRule.executeTarget("testLogInputString");
         if (buildRule.getLog().contains("testLogInputString can-cat")) {
-            AntAssert.assertContains("Using input string", buildRule.getFullLog());
+            assertThat(buildRule.getFullLog(), containsString("Using input string"));
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/types/ResourceOutputTest.java b/src/tests/junit/org/apache/tools/ant/types/ResourceOutputTest.java
index 25a653d..fbef907 100644
--- a/src/tests/junit/org/apache/tools/ant/types/ResourceOutputTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/ResourceOutputTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import java.net.UnknownServiceException;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Zip;
 import org.apache.tools.ant.types.resources.ImmutableResourceException;
@@ -33,34 +34,34 @@
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.ResourceUtils;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 public class ResourceOutputTest {
 
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    private static final File basedir = new File(System.getProperty("root"),
-        "src/etc/testcases/types/resources");
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
 
     private Project project;
 
     @Before
     public void setUp() {
-        project = new Project();
-        project.init();
-        project.setUserProperty("basedir", basedir.getAbsolutePath());
+        buildRule.configureProject("src/etc/testcases/types/resources/resourcelist.xml");
+        project = buildRule.getProject();
     }
 
-    @Test
+    /**
+     * Expected failure
+     */
+    @Test(expected = UnsupportedOperationException.class)
     public void testresourceoutput() {
-        try {
-            testoutputbe(new Resource("foo"));
-            fail("should have caught UnsupportedOperationException");
-        } catch (UnsupportedOperationException e) {
-            //TODO assert exception message
-        }
+        testoutputbe(new Resource("foo"));
     }
 
     @Test
@@ -70,15 +71,20 @@
         assertEquals("foo", r.getValue());
     }
 
-    @Test
+    /**
+     * Expected failure
+     *
+     * @throws IOException if something goes wrong
+     */
+    @Test(expected = ImmutableResourceException.class)
     public void teststringoutput2() throws IOException {
         StringResource r = new StringResource("bar");
-        try {
-            testoutput(r);
-            fail("should have caught ImmutableResourceException");
-        } catch (ImmutableResourceException e) {
-            //TODO assert exception message
-        }
+        testoutput(r);
+    }
+
+    @Test
+    public void teststringoutput3() {
+        StringResource r = new StringResource("bar");
         assertEquals("bar", r.getValue());
     }
 
@@ -89,28 +95,32 @@
         assertEquals("foo", project.getProperty("bar"));
     }
 
-    @Test
+    /**
+     * Expected failure
+     *
+     * @throws IOException if something goes wrong
+     */
+    @Test(expected = ImmutableResourceException.class)
     public void testpropertyoutput2() throws IOException {
         project.setNewProperty("bar", "bar");
         PropertyResource r = new PropertyResource(project, "bar");
-        try {
-            testoutput(r);
-            fail("should have caught ImmutableResourceException");
-        } catch (ImmutableResourceException e) {
-            //TODO assert exception message
-        }
+        testoutput(r);
+    }
+
+    @Test
+    public void testpropertyoutput3() {
+        project.setNewProperty("bar", "bar");
         assertEquals("bar", project.getProperty("bar"));
     }
 
     @Test
     public void testurloutput() throws IOException {
+        thrown.expect(UnknownServiceException.class);
+        // TODO assert exception message
         File f = project.resolveFile("testurloutput");
         try {
-            FILE_UTILS.createNewFile(f);
+            FileUtils.getFileUtils().createNewFile(f);
             testoutput(new URLResource(f));
-            fail("should have caught UnknownServiceException");
-        } catch (UnknownServiceException e) {
-            //TODO assert exception message
         } finally {
             if (!f.delete()) {
                 f.deleteOnExit();
@@ -120,12 +130,14 @@
 
     @Test
     public void testzipentryoutput() {
+        thrown.expect(UnsupportedOperationException.class);
+        // TODO assert exception message
         Zip z = new Zip();
         z.setProject(project);
         Zip.WhenEmpty create = new Zip.WhenEmpty();
         create.setValue("create");
         z.setWhenempty(create);
-        z.setBasedir(basedir);
+        z.setBasedir(project.getBaseDir());
         z.setExcludes("**/*");
         File f = project.resolveFile("foo");
         z.setDestFile(f);
@@ -135,9 +147,6 @@
         r.setName("foo");
         try {
             testoutputbe(r);
-            fail("should have caught UnsupportedOperationException");
-        } catch (UnsupportedOperationException e) {
-            //TODO assert exception message
         } finally {
             if (!f.delete()) {
                 f.deleteOnExit();
diff --git a/src/tests/junit/org/apache/tools/ant/types/TarFileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/TarFileSetTest.java
index 391e248..f84839f 100644
--- a/src/tests/junit/org/apache/tools/ant/types/TarFileSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/TarFileSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -14,6 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
+ * <p>This doesn't actually test much, mainly reference handling.</p>
  */
 
 package org.apache.tools.ant.types;
@@ -21,11 +22,10 @@
 import java.io.File;
 
 import org.apache.tools.ant.BuildException;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit 4 testcases for org.apache.tools.ant.types.TarFileSet.
@@ -34,87 +34,92 @@
  */
 public class TarFileSetTest extends AbstractFileSetTest {
 
+    private TarFileSet tfs;
 
     protected AbstractFileSet getInstance() {
         return new TarFileSet();
     }
 
+    @Before
+    public void setUp() {
+        super.setUp();
+        tfs = (TarFileSet) getInstance();
+    }
+
+    /**
+     * check that dir and src are incompatible
+     */
+    @Test
+    public final void testSrcDirAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both dir and src attributes");
+        tfs.setSrc(new File("example.tar"));
+        tfs.setDir(new File("examples"));
+    }
+
+    /**
+     * check that dir and src are incompatible
+     */
+    @Test
+    public final void testDirSrcAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both dir and src attributes");
+        tfs.setDir(new File("examples"));
+        tfs.setSrc(new File("example.tar"));
+    }
+
+    /**
+     * check that fullpath and prefix are incompatible
+     */
+    @Test
+    public final void testPrefixFullpathAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both fullpath and prefix attributes");
+        tfs.setSrc(new File("example.tar"));
+        tfs.setPrefix("/examples");
+        tfs.setFullpath("/doc/manual/index.html");
+    }
+
+    @Test
+    public final void testFullpathPrefixAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both fullpath and prefix attributes");
+        tfs.setSrc(new File("example.tar"));
+        tfs.setFullpath("/doc/manual/index.html");
+        tfs.setPrefix("/examples");
+    }
+
+    /**
+     * check that reference tarfilesets cannot have specific attributes
+     */
+    @Test
+    public final void testRefidSrcAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        tfs.setRefid(new Reference(getProject(), "test"));
+        tfs.setSrc(new File("example.tar"));
+    }
+
+    /**
+     * check that a reference tarfileset gets the same attributes as the original
+     */
     @Test
     public final void testAttributes() {
-        TarFileSet f = (TarFileSet) getInstance();
-        //check that dir and src are incompatible
-        f.setSrc(new File("example.tar"));
-        try {
-            f.setDir(new File("examples"));
-            fail("can add dir to "
-                    + f.getDataTypeName()
-                    + " when a src is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both dir and src attributes",be.getMessage());
-        }
-        f = (TarFileSet) getInstance();
-        //check that dir and src are incompatible
-        f.setDir(new File("examples"));
-        try {
-            f.setSrc(new File("example.tar"));
-            fail("can add src to "
-                    + f.getDataTypeName()
-                    + " when a dir is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both dir and src attributes",be.getMessage());
-        }
-        //check that fullpath and prefix are incompatible
-        f = (TarFileSet) getInstance();
-        f.setSrc(new File("example.tar"));
-        f.setPrefix("/examples");
-        try {
-            f.setFullpath("/doc/manual/index.html");
-            fail("Can add fullpath to "
-                    + f.getDataTypeName()
-                    + " when a prefix is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both fullpath and prefix attributes", be.getMessage());
-        }
-        f = (TarFileSet) getInstance();
-        f.setSrc(new File("example.tar"));
-        f.setFullpath("/doc/manual/index.html");
-        try {
-            f.setPrefix("/examples");
-            fail("Can add prefix to "
-                    + f.getDataTypeName()
-                    + " when a fullpath is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both fullpath and prefix attributes", be.getMessage());
-        }
-        // check that reference tarfilesets cannot have specific attributes
-        f = (TarFileSet) getInstance();
-        f.setRefid(new Reference(getProject(), "test"));
-        try {
-            f.setSrc(new File("example.tar"));
-            fail("Can add src to "
-                    + f.getDataTypeName()
-                    + " when a refid is already present");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one "
-            + "attribute when using refid", be.getMessage());
-        }
-        // check that a reference tarfileset gets the same attributes as the original
-        f = (TarFileSet) getInstance();
-        f.setSrc(new File("example.tar"));
-        f.setPrefix("/examples");
-        f.setFileMode("600");
-        f.setDirMode("530");
-        getProject().addReference("test", f);
+        tfs.setSrc(new File("example.tar"));
+        tfs.setPrefix("/examples");
+        tfs.setFileMode("600");
+        tfs.setDirMode("530");
+        getProject().addReference("test", tfs);
         TarFileSet zid = (TarFileSet) getInstance();
         zid.setRefid(new Reference(getProject(), "test"));
-        assertTrue("src attribute copied by copy constructor",
-                zid.getSrc(getProject()).equals(f.getSrc(getProject())));
-        assertTrue("prefix attribute copied by copy constructor",
-                f.getPrefix(getProject()).equals(zid.getPrefix(getProject())));
-        assertTrue("file mode attribute copied by copy constructor",
-                f.getFileMode(getProject()) == zid.getFileMode(getProject()));
-        assertTrue("dir mode attribute copied by copy constructor",
-                f.getDirMode(getProject()) == zid.getDirMode(getProject()));
+        assertEquals("src attribute copied by copy constructor",
+                tfs.getSrc(getProject()), zid.getSrc(getProject()));
+        assertEquals("prefix attribute copied by copy constructor",
+                tfs.getPrefix(getProject()), zid.getPrefix(getProject()));
+        assertEquals("file mode attribute copied by copy constructor",
+                tfs.getFileMode(getProject()), zid.getFileMode(getProject()));
+        assertEquals("dir mode attribute copied by copy constructor",
+                tfs.getDirMode(getProject()), zid.getDirMode(getProject()));
       }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/XMLCatalogBuildFileTest.java b/src/tests/junit/org/apache/tools/ant/types/XMLCatalogBuildFileTest.java
index 96c0c5d..3698ca9 100644
--- a/src/tests/junit/org/apache/tools/ant/types/XMLCatalogBuildFileTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/XMLCatalogBuildFileTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,6 +19,7 @@
 package org.apache.tools.ant.types;
 
 import org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -35,7 +36,10 @@
      @Rule
      public BuildFileRule buildRule = new BuildFileRule();
 
-
+     @Before
+     public void setUp() {
+         buildRule.configureProject("src/etc/testcases/types/xmlcatalog.xml");
+     }
 
     //
     // Ensure that an external entity resolves as expected with NO
@@ -46,7 +50,6 @@
     //
     @Test
     public void testEntityNoCatalog() {
-        buildRule.configureProject("src/etc/testcases/types/xmlcatalog.xml");
         buildRule.executeTarget("testentitynocatalog");
         assertEquals("A stitch in time saves nine", buildRule.getProject().getProperty("val1"));
     }
@@ -61,7 +64,6 @@
     //
     @Test
     public void testEntityWithCatalog() {
-        buildRule.configureProject("src/etc/testcases/types/xmlcatalog.xml");
         buildRule.executeTarget("testentitywithcatalog");
         assertEquals("No news is good news", buildRule.getProject().getProperty("val2"));
     }
@@ -76,7 +78,6 @@
     //
     @Test
     public void testDocumentNoCatalog() {
-        buildRule.configureProject("src/etc/testcases/types/xmlcatalog.xml");
         buildRule.executeTarget("testdocumentnocatalog");
         assertEquals("A stitch in time saves nine", buildRule.getProject().getProperty("val3"));
     }
@@ -91,7 +92,6 @@
     // Stuff result into the property: val4
     @Test
     public void testDocumentWithCatalog() {
-        buildRule.configureProject("src/etc/testcases/types/xmlcatalog.xml");
         buildRule.executeTarget("testdocumentwithcatalog");
         assertEquals("No news is good news", buildRule.getProject().getProperty("val4"));
     }
diff --git a/src/tests/junit/org/apache/tools/ant/types/XMLCatalogTest.java b/src/tests/junit/org/apache/tools/ant/types/XMLCatalogTest.java
index 961e55d..8261728 100644
--- a/src/tests/junit/org/apache/tools/ant/types/XMLCatalogTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/XMLCatalogTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -28,18 +28,21 @@
 import javax.xml.transform.sax.SAXSource;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicTestNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.util.JAXPUtils;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
+import static org.hamcrest.Matchers.endsWith;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 
 /**
  * JUnit testcases for org.apache.tools.ant.types.XMLCatalog
@@ -56,15 +59,19 @@
         return cat;
     }
 
-    private static String toURLString(File file) throws MalformedURLException {
+    private static String toURLString(File file) {
         return JAXPUtils.getSystemId(file);
     }
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         project = new Project();
-        project.setBasedir(System.getProperty("root"));
-
+        if (System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY) != null) {
+            project.setBasedir(System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY));
+        }
         // This causes XMLCatalog to print out detailed logging
         // messages for debugging
         //
@@ -78,26 +85,19 @@
     }
 
     @Test
-    public void testEmptyCatalog() {
-        try {
-            InputSource result = catalog.resolveEntity("PUBLIC ID ONE",
-                                                       "i/dont/exist.dtd");
-            assertNull("Empty catalog should return null", result);
-        } catch (Exception e) {
-            fail("resolveEntity() failed!" + e.toString());
-        }
+    public void testEmptyCatalogResolveEntity() throws IOException, SAXException {
+        InputSource result = catalog.resolveEntity("PUBLIC ID ONE", "i/dont/exist.dtd");
+        assertNull("Empty catalog should return null", result);
+     }
 
-        try {
-            Source result = catalog.resolve("i/dont/exist.dtd", null);
-            String expected = toURLString(new File(project.getBaseDir() +
-                                                   "/i/dont/exist.dtd"));
-            String resultStr = fileURLPartWithoutLeadingSlashes((SAXSource) result);
-            assertTrue("Empty catalog should return input with a system ID like "
-                       + expected + " but was " + resultStr,
-                       expected.endsWith(resultStr));
-        } catch (Exception e) {
-            fail("resolve() failed!" + e.toString());
-        }
+    @Test
+    public void testEmptyCatalogResolve() throws TransformerException, MalformedURLException {
+        String expected = toURLString(new File(project.getBaseDir() +
+                "/i/dont/exist.dtd"));
+        Source result = catalog.resolve("i/dont/exist.dtd", null);
+        String resultStr = fileURLPartWithoutLeadingSlashes((SAXSource) result);
+        assertThat("Empty catalog should return input with a system ID like "
+                        + expected + " but was " + resultStr, expected, endsWith(resultStr));
     }
 
     private static String fileURLPartWithoutLeadingSlashes(SAXSource result)
@@ -107,8 +107,7 @@
         // has a different idea of how file URLs are created on windoze
         // ie file://c:/foo instead of file:///c:/foo
         //
-        String resultStr =
-            new URL(result.getInputSource().getSystemId()).getFile();
+        String resultStr = new URL(result.getInputSource().getSystemId()).getFile();
         // on Sun's Java6 this returns an unexpected number of four
         // leading slashes, at least on Linux - strip all of them
         while (resultStr.startsWith("/")) {
@@ -123,84 +122,65 @@
         dtd.setPublicId("PUBLIC ID ONE");
         dtd.setLocation("i/dont/exist.dtd");
 
-        InputSource isResult = catalog.resolveEntity("PUBLIC ID ONE",
-                                                   "i/dont/exist.dtd");
+        InputSource isResult = catalog.resolveEntity("PUBLIC ID ONE", "i/dont/exist.dtd");
         assertNull("Nonexistent Catalog entry should not be returned", isResult);
 
         Source result = catalog.resolve("i/dont/exist.dtd", null);
-        String expected = toURLString(new File(project.getBaseDir().toURL() +
-                                               "/i/dont/exist.dtd"));
+        String expected = toURLString(new File(project.getBaseDir().toURL()
+                + "/i/dont/exist.dtd"));
         String resultStr = fileURLPartWithoutLeadingSlashes((SAXSource) result);
-        assertTrue("Nonexistent Catalog entry return input with a system ID like "
+        assertThat("Nonexistent Catalog entry return input with a system ID like "
                    + expected + " but was " + resultStr,
-                   expected.endsWith(resultStr));
+                   expected, endsWith(resultStr));
     }
 
     @Test
-    public void testEmptyElementIfIsReference() {
+    public void testEmptyElementIfIsReferenceAttr() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         ResourceLocation dtd = new ResourceLocation();
         dtd.setPublicId("PUBLIC ID ONE");
         dtd.setLocation("i/dont/exist.dtd");
         catalog.addDTD(dtd);
         project.addReference("catalog", catalog);
+        catalog.setRefid(new Reference(project, "dummyref"));
+    }
 
-        try {
-            catalog.setRefid(new Reference(project, "dummyref"));
-            fail("Can add reference to nonexistent XMLCatalog");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one "
-                         + "attribute when using refid", be.getMessage());
-        }
-
-        XMLCatalog catalog2 = newCatalog();
-        catalog2.setRefid(new Reference(project, "catalog"));
-
-        try {
-            catalog2.addConfiguredXMLCatalog(catalog);
-            fail("Can add nested XMLCatalog to XMLCatalog that is a reference");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
+    @Test
+    public void testEmptyElementIfIsReferenceElem() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        XMLCatalog catalogA = newCatalog();
+        catalogA.setRefid(new Reference(project, "catalog"));
+        catalogA.addConfiguredXMLCatalog(catalog);
     }
 
     @Test
     public void testCircularReferenceCheck() throws IOException, SAXException {
-
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
         // catalog <--> catalog
         project.addReference("catalog", catalog);
         catalog.setRefid(new Reference(project, "catalog"));
+        catalog.resolveEntity("PUBLIC ID ONE", "i/dont/exist.dtd");
+    }
 
-        try {
-            @SuppressWarnings("unused")
-            InputSource result = catalog.resolveEntity("PUBLIC ID ONE", "i/dont/exist.dtd");
-            fail("Can make XMLCatalog a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        } catch (Exception e) {
-            fail("resolveEntity() failed!" + e.toString());
-        }
+    @Test
+    public void testLoopReferenceCheck() throws IOException, SAXException {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        // catalog --> catalogA --> catalogB --> catalog
+        project.addReference("catalog", catalog);
+        XMLCatalog catalogA = newCatalog();
+        project.addReference("catalogA", catalogA);
+        XMLCatalog catalogB = newCatalog();
+        project.addReference("catalogB", catalogB);
 
-        // catalog1 --> catalog2 --> catalog3 --> catalog1
-        XMLCatalog catalog1 = newCatalog();
-        project.addReference("catalog1", catalog1);
-        XMLCatalog catalog2 = newCatalog();
-        project.addReference("catalog2", catalog2);
-        XMLCatalog catalog3 = newCatalog();
-        project.addReference("catalog3", catalog3);
+        catalogB.setRefid(new Reference(project, "catalog"));
+        catalogA.setRefid(new Reference(project, "catalogB"));
+        catalog.setRefid(new Reference(project, "catalogA"));
 
-        catalog3.setRefid(new Reference(project, "catalog1"));
-        catalog2.setRefid(new Reference(project, "catalog3"));
-        catalog1.setRefid(new Reference(project, "catalog2"));
-
-        try {
-            catalog1.resolveEntity("PUBLIC ID ONE", "i/dont/exist.dtd");
-            fail("Can make circular reference");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                    be.getMessage());
-        }
+        catalog.resolveEntity("PUBLIC ID ONE", "i/dont/exist.dtd");
     }
 
     // inspired by Bugzilla Report 23913
@@ -211,14 +191,16 @@
         ResourceLocation dtd = new ResourceLocation();
         dtd.setPublicId("-//stevo//DTD doc 1.0//EN");
 
-        String sysid = System.getProperty("root") + File.separator + "src/etc/testcases/taskdefs/optional/xml/doc.dtd";
+        String sysid = project.resolveFile("src/etc/testcases/taskdefs/optional/xml/doc.dtd")
+                .getAbsolutePath();
         dtd.setLocation(sysid);
         catalog.addDTD(dtd);
-        File dtdFile = project.resolveFile(sysid);
 
         InputSource result = catalog.resolveEntity("-//stevo//DTD doc 1.0//EN",
                                                    "nap:chemical+brothers");
         assertNotNull(result);
+
+        File dtdFile = project.resolveFile(sysid);
         assertEquals(toURLString(dtdFile), result.getSystemId());
     }
 
@@ -229,13 +211,13 @@
         String sysid = "src/etc/testcases/taskdefs/optional/xml/doc.dtd";
         dtd.setLocation(sysid);
         catalog.addDTD(dtd);
-        File dtdFile = project.resolveFile(sysid);
 
         InputSource result = catalog.resolveEntity("-//stevo//DTD doc 1.0//EN",
                                                    "nap:chemical+brothers");
         assertNotNull(result);
-        assertEquals(toURLString(dtdFile), result.getSystemId());
 
+        File dtdFile = project.resolveFile(sysid);
+        assertEquals(toURLString(dtdFile), result.getSystemId());
     }
 
     @Test
@@ -243,12 +225,11 @@
         String publicId = "-//stevo//DTD doc 1.0//EN";
         String sysid = "src/etc/testcases/taskdefs/optional/xml/doc.dtd";
 
-        // catalog2 --> catalog1 --> catalog
+        // catalogB --> catalogA --> catalog
         ResourceLocation dtd = new ResourceLocation();
         dtd.setPublicId(publicId);
         dtd.setLocation(sysid);
         catalog.addDTD(dtd);
-        File dtdFile = project.resolveFile(sysid);
 
         String uri = "http://foo.com/bar/blah.xml";
         String uriLoc = "src/etc/testcases/taskdefs/optional/xml/about.xml";
@@ -257,26 +238,28 @@
         entity.setPublicId(uri);
         entity.setLocation(uriLoc);
         catalog.addEntity(entity);
-        File xmlFile = project.resolveFile(uriLoc);
 
         project.addReference("catalog", catalog);
 
-        XMLCatalog catalog1 = newCatalog();
-        project.addReference("catalog1", catalog1);
-        XMLCatalog catalog2 = newCatalog();
-        project.addReference("catalog2", catalog1);
+        XMLCatalog catalogA = newCatalog();
+        project.addReference("catalogA", catalogA);
+        XMLCatalog catalogB = newCatalog();
+        project.addReference("catalogB", catalogB);
 
-        catalog1.setRefid(new Reference(project, "catalog"));
-        catalog2.setRefid(new Reference(project, "catalog1"));
+        catalogA.setRefid(new Reference(project, "catalog"));
+        catalogB.setRefid(new Reference(project, "catalogA"));
 
-        InputSource isResult = catalog2.resolveEntity(publicId, "nap:chemical+brothers");
-
+        InputSource isResult = catalogB.resolveEntity(publicId, "nap:chemical+brothers");
         assertNotNull(isResult);
+
+        File dtdFile = project.resolveFile(sysid);
         assertEquals(toURLString(dtdFile), isResult.getSystemId());
 
-            Source result = catalog.resolve(uri, null);
-            assertNotNull(result);
-            assertEquals(toURLString(xmlFile), result.getSystemId());
+        Source result = catalog.resolve(uri, null);
+        assertNotNull(result);
+
+        File xmlFile = project.resolveFile(uriLoc);
+        assertEquals(toURLString(xmlFile), result.getSystemId());
     }
 
     @Test
@@ -288,7 +271,6 @@
         dtd.setPublicId(publicId);
         dtd.setLocation(dtdLoc);
         catalog.addDTD(dtd);
-        File dtdFile = project.resolveFile(dtdLoc);
 
         String uri = "http://foo.com/bar/blah.xml";
         String uriLoc = "src/etc/testcases/taskdefs/optional/xml/about.xml";
@@ -297,22 +279,24 @@
         entity.setPublicId(uri);
         entity.setLocation(uriLoc);
         catalog.addEntity(entity);
-        File xmlFile = project.resolveFile(uriLoc);
 
-        XMLCatalog catalog1 = newCatalog();
-        catalog1.addConfiguredXMLCatalog(catalog);
-
-        InputSource isResult = catalog1.resolveEntity(publicId, "nap:chemical+brothers");
+        XMLCatalog catalogA = newCatalog();
+        catalogA.addConfiguredXMLCatalog(catalog);
+        InputSource isResult = catalogA.resolveEntity(publicId, "nap:chemical+brothers");
         assertNotNull(isResult);
+
+        File dtdFile = project.resolveFile(dtdLoc);
         assertEquals(toURLString(dtdFile), isResult.getSystemId());
 
         Source result = catalog.resolve(uri, null);
         assertNotNull(result);
+
+        File xmlFile = project.resolveFile(uriLoc);
         assertEquals(toURLString(xmlFile), result.getSystemId());
     }
 
     @Test
-    public void testResolverBase() throws MalformedURLException, TransformerException {
+    public void testResolverBase() throws TransformerException {
         String uri = "http://foo.com/bar/blah.xml";
         String uriLoc = "etc/testcases/taskdefs/optional/xml/about.xml";
         String base = toURLString(project.getBaseDir()) + "/src/";
@@ -321,10 +305,11 @@
         entity.setPublicId(uri);
         entity.setLocation(uriLoc);
         catalog.addEntity(entity);
-        File xmlFile = project.resolveFile("src/" + uriLoc);
 
         Source result = catalog.resolve(uri, base);
         assertNotNull(result);
+
+        File xmlFile = project.resolveFile("src/" + uriLoc);
         assertEquals(toURLString(xmlFile), result.getSystemId());
     }
 
@@ -338,7 +323,6 @@
         dtd.setPublicId(publicId);
         dtd.setLocation(dtdLoc);
         catalog.addDTD(dtd);
-        File dtdFile = project.resolveFile("src/etc/" + dtdLoc);
 
         String uri = "http://foo.com/bar/blah.xml";
         String uriLoc = "etc/testcases/taskdefs/optional/xml/about.xml";
@@ -348,7 +332,6 @@
         entity.setPublicId(uri);
         entity.setLocation(uriLoc);
         catalog.addEntity(entity);
-        File xmlFile = project.resolveFile("src/" + uriLoc);
 
         Path aPath = new Path(project, path1);
         aPath.append(new Path(project, path2));
@@ -356,12 +339,16 @@
 
         InputSource isResult = catalog.resolveEntity(publicId, "nap:chemical+brothers");
         assertNotNull(isResult);
+
         String resultStr1 = new URL(isResult.getSystemId()).getFile();
-        assertTrue(toURLString(dtdFile).endsWith(resultStr1));
+        File dtdFile = project.resolveFile("src/etc/" + dtdLoc);
+        assertThat(toURLString(dtdFile), endsWith(resultStr1));
 
         Source result = catalog.resolve(uri, null);
         assertNotNull(result);
+
+        File xmlFile = project.resolveFile("src/" + uriLoc);
         String resultStr = new URL(result.getSystemId()).getFile();
-        assertTrue(toURLString(xmlFile).endsWith(resultStr));
+        assertThat(toURLString(xmlFile), endsWith(resultStr));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/ZipFileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/ZipFileSetTest.java
index c89b420..174559e 100644
--- a/src/tests/junit/org/apache/tools/ant/types/ZipFileSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/ZipFileSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,11 +21,10 @@
 import java.io.File;
 
 import org.apache.tools.ant.BuildException;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit 4 testcases for org.apache.tools.ant.types.ZipFileSet.
@@ -34,86 +33,95 @@
  */
 public class ZipFileSetTest extends AbstractFileSetTest {
 
+    private ZipFileSet zfs;
+
     protected AbstractFileSet getInstance() {
         return new ZipFileSet();
     }
 
+    @Before
+    public void setUp() {
+        super.setUp();
+        zfs = (ZipFileSet) getInstance();
+    }
+
+    /**
+     * check that dir and src are incompatible
+     */
+    @Test
+    public final void testSrcDirAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both dir and src attributes");
+        zfs.setSrc(new File("example.zip"));
+        zfs.setDir(new File("examples"));
+    }
+
+    /**
+     * check that dir and src are incompatible
+     */
+    @Test
+    public final void testDirSrcAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both dir and src attributes");
+        zfs.setDir(new File("examples"));
+        zfs.setSrc(new File("example.zip"));
+    }
+
+    /**
+     * check that fullpath and prefix are incompatible
+     */
+    @Test
+    public final void testPrefixFullpathAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both fullpath and prefix attributes");
+        zfs.setSrc(new File("example.zip"));
+        zfs.setPrefix("/examples");
+        zfs.setFullpath("/doc/manual/index.html");
+    }
+
+    /**
+     * check that fullpath and prefix are incompatible
+     */
+    @Test
+    public final void testFullpathPrefixAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot set both fullpath and prefix attributes");
+        zfs.setSrc(new File("example.zip"));
+        zfs.setFullpath("/doc/manual/index.html");
+        zfs.setPrefix("/examples");
+    }
+
+    /**
+     * check that reference zipfilesets cannot have specific attributes
+     */
+    @Test
+    public final void testRefidSrcAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        zfs.setRefid(new Reference(getProject(), "test"));
+        zfs.setSrc(new File("example.zip"));
+    }
+
+    /**
+     * check that a reference zipfileset gets the same attributes as the original
+     */
     @Test
     public final void testAttributes() {
-        ZipFileSet f = (ZipFileSet) getInstance();
-        //check that dir and src are incompatible
-        f.setSrc(new File("example.zip"));
-        try {
-            f.setDir(new File("examples"));
-            fail("can add dir to "
-                    + f.getDataTypeName()
-                    + " when a src is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both dir and src attributes", be.getMessage());
-        }
-        f = (ZipFileSet) getInstance();
-        //check that dir and src are incompatible
-        f.setDir(new File("examples"));
-        try {
-            f.setSrc(new File("example.zip"));
-            fail("can add src to "
-                    + f.getDataTypeName()
-                    + " when a dir is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both dir and src attributes", be.getMessage());
-        }
-        //check that fullpath and prefix are incompatible
-        f = (ZipFileSet) getInstance();
-        f.setSrc(new File("example.zip"));
-        f.setPrefix("/examples");
-        try {
-            f.setFullpath("/doc/manual/index.html");
-            fail("Can add fullpath to "
-                    + f.getDataTypeName()
-                    + " when a prefix is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both fullpath and prefix attributes", be.getMessage());
-        }
-        f = (ZipFileSet) getInstance();
-        f.setSrc(new File("example.zip"));
-        f.setFullpath("/doc/manual/index.html");
-        try {
-            f.setPrefix("/examples");
-            fail("Can add prefix to "
-                    + f.getDataTypeName()
-                    + " when a fullpath is already present");
-        } catch (BuildException be) {
-            assertEquals("Cannot set both fullpath and prefix attributes", be.getMessage());
-        }
-        // check that reference zipfilesets cannot have specific attributes
-        f = (ZipFileSet) getInstance();
-        f.setRefid(new Reference(getProject(), "test"));
-        try {
-            f.setSrc(new File("example.zip"));
-            fail("Can add src to "
-                    + f.getDataTypeName()
-                    + " when a refid is already present");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one "
-            + "attribute when using refid", be.getMessage());
-        }
-        // check that a reference zipfileset gets the same attributes as the original
-        f = (ZipFileSet) getInstance();
-        f.setSrc(new File("example.zip"));
-        f.setPrefix("/examples");
-        f.setFileMode("600");
-        f.setDirMode("530");
-        getProject().addReference("test", f);
+        zfs.setSrc(new File("example.zip"));
+        zfs.setPrefix("/examples");
+        zfs.setFileMode("600");
+        zfs.setDirMode("530");
+        getProject().addReference("test", zfs);
         ZipFileSet zid = (ZipFileSet) getInstance();
         zid.setRefid(new Reference(getProject(), "test"));
-        assertTrue("src attribute copied by copy constructor",
-                zid.getSrc(getProject()).equals(f.getSrc(getProject())));
-        assertTrue("prefix attribute copied by copy constructor",
-                f.getPrefix(getProject()).equals(zid.getPrefix(getProject())));
+        assertEquals("src attribute copied by copy constructor",
+                zfs.getSrc(getProject()), zid.getSrc(getProject()));
+        assertEquals("prefix attribute copied by copy constructor",
+                zfs.getPrefix(getProject()), zid.getPrefix(getProject()));
         assertEquals("file mode attribute copied by copy constructor",
-                f.getFileMode(getProject()), zid.getFileMode(getProject()));
+                zfs.getFileMode(getProject()), zid.getFileMode(getProject()));
         assertEquals("dir mode attribute copied by copy constructor",
-                f.getDirMode(getProject()), zid.getDirMode(getProject()));
+                zfs.getDirMode(getProject()), zid.getDirMode(getProject()));
       }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/mappers/GlobMapperTest.java b/src/tests/junit/org/apache/tools/ant/types/mappers/GlobMapperTest.java
index c73c2fe..dc4d7fa 100644
--- a/src/tests/junit/org/apache/tools/ant/types/mappers/GlobMapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/mappers/GlobMapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/mappers/MapperResult.java b/src/tests/junit/org/apache/tools/ant/types/mappers/MapperResult.java
index 8382e05..1000ded 100644
--- a/src/tests/junit/org/apache/tools/ant/types/mappers/MapperResult.java
+++ b/src/tests/junit/org/apache/tools/ant/types/mappers/MapperResult.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -80,14 +80,7 @@
         if (result == null) {
             flattened = NULL_MAPPER_RESULT;
         } else {
-            StringBuilder b = new StringBuilder();
-            for (int i = 0; i < result.length; ++i) {
-                if (i != 0) {
-                    b.append("|");
-                }
-                b.append(result[i]);
-            }
-            flattened = b.toString();
+            flattened = String.join("|", result);
         }
         if (!flattened.equals(output)) {
             throw new BuildException(failMessage + " got " + flattened + " expected " + output);
diff --git a/src/tests/junit/org/apache/tools/ant/types/mappers/RegexpPatternMapperTest.java b/src/tests/junit/org/apache/tools/ant/types/mappers/RegexpPatternMapperTest.java
index 6d4d13a..8f95d63 100644
--- a/src/tests/junit/org/apache/tools/ant/types/mappers/RegexpPatternMapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/mappers/RegexpPatternMapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/optional/ScriptMapperTest.java b/src/tests/junit/org/apache/tools/ant/types/optional/ScriptMapperTest.java
index bf727db..625a3d0 100644
--- a/src/tests/junit/org/apache/tools/ant/types/optional/ScriptMapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/optional/ScriptMapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/optional/ScriptSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/optional/ScriptSelectorTest.java
index 304d6d0..c2c540b 100644
--- a/src/tests/junit/org/apache/tools/ant/types/optional/ScriptSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/optional/ScriptSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,9 +22,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.apache.tools.ant.AntAssert.assertContains;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Test that scripting selection works. Needs scripting support to work
@@ -34,6 +32,9 @@
     @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         buildRule.configureProject("src/etc/testcases/types/selectors/scriptselector.xml");
@@ -41,13 +42,9 @@
 
     @Test
     public void testNolanguage() {
-        try {
-            buildRule.executeTarget("testNolanguage");
-            fail("Absence of language attribute not detected");
-        } catch(BuildException ex) {
-            assertContains("script language must be specified", ex.getMessage());
-
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("script language must be specified");
+        buildRule.executeTarget("testNolanguage");
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/types/optional/depend/ClassFileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/optional/depend/ClassFileSetTest.java
index e225f13..dd7f54c 100644
--- a/src/tests/junit/org/apache/tools/ant/types/optional/depend/ClassFileSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/optional/depend/ClassFileSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,18 +19,20 @@
 package org.apache.tools.ant.types.optional.depend;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.Hashtable;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildFileRule;
 import org.apache.tools.ant.DirectoryScanner;
-import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.FileSet;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.hasKey;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
 
 /**
  * Testcase for the Classfileset optional type.
@@ -53,25 +55,14 @@
      */
     @Test
     public void testBasicSet() {
-        Project p = buildRule.getProject();
         buildRule.executeTarget("testbasicset");
-        FileSet resultFileSet = p.getReference(RESULT_FILESET);
-        DirectoryScanner scanner = resultFileSet.getDirectoryScanner(p);
-        String[] scannedFiles = scanner.getIncludedFiles();
-        Hashtable files = new Hashtable();
-        for (String scannedFile : scannedFiles) {
-            files.put(scannedFile, scannedFile);
-        }
-        assertEquals("Classfileset did not pick up expected number of "
-            + "class files", 4, files.size());
-        assertTrue("Result did not contain A.class",
-            files.containsKey("A.class"));
-        assertTrue("Result did not contain B.class",
-            files.containsKey("B.class"));
-        assertTrue("Result did not contain C.class",
-            files.containsKey("C.class"));
-        assertTrue("Result did not contain D.class",
-            files.containsKey("D.class"));
+        Hashtable<String, String> files = getFiles();
+        assertEquals("Classfileset did not pick up expected number of class files",
+                4, files.size());
+        assertThat("Result did not contain A.class", files, hasKey("A.class"));
+        assertThat("Result did not contain B.class", files, hasKey("B.class"));
+        assertThat("Result did not contain C.class", files, hasKey("C.class"));
+        assertThat("Result did not contain D.class", files, hasKey("D.class"));
     }
 
     /**
@@ -79,21 +70,12 @@
      */
     @Test
     public void testSmallSet() {
-        Project p = buildRule.getProject();
         buildRule.executeTarget("testsmallset");
-        FileSet resultFileSet = p.getReference(RESULT_FILESET);
-        DirectoryScanner scanner = resultFileSet.getDirectoryScanner(p);
-        String[] scannedFiles = scanner.getIncludedFiles();
-        Hashtable files = new Hashtable();
-        for (String scannedFile : scannedFiles) {
-            files.put(scannedFile, scannedFile);
-        }
-        assertEquals("Classfileset did not pick up expected number of "
-            + "class files", 2, files.size());
-        assertTrue("Result did not contain B.class",
-            files.containsKey("B.class"));
-        assertTrue("Result did not contain C.class",
-            files.containsKey("C.class"));
+        Hashtable<String, String> files = getFiles();
+        assertEquals("Classfileset did not pick up expected number of class files",
+                2, files.size());
+        assertThat("Result did not contain B.class", files, hasKey("B.class"));
+        assertThat("Result did not contain C.class", files, hasKey("C.class"));
     }
 
     /**
@@ -101,19 +83,11 @@
      */
     @Test
     public void testComboSet() {
-        Project p = buildRule.getProject();
         buildRule.executeTarget("testcomboset");
-        FileSet resultFileSet = p.getReference(RESULT_FILESET);
-        DirectoryScanner scanner = resultFileSet.getDirectoryScanner(p);
-        String[] scannedFiles = scanner.getIncludedFiles();
-        Hashtable files = new Hashtable();
-        for (String scannedFile : scannedFiles) {
-            files.put(scannedFile, scannedFile);
-        }
-        assertEquals("Classfileset did not pick up expected number of "
-            + "class files", 1, files.size());
-        assertTrue("Result did not contain C.class",
-            files.containsKey("C.class"));
+        Hashtable<String, String> files = getFiles();
+        assertEquals("Classfileset did not pick up expected number of class files",
+                1, files.size());
+        assertThat("Result did not contain C.class", files, hasKey("C.class"));
     }
 
     /**
@@ -129,27 +103,15 @@
      */
     @Test
     public void testMethodParam() {
-        Project p = buildRule.getProject();
         buildRule.executeTarget("testmethodparam");
-        FileSet resultFileSet = p.getReference(RESULT_FILESET);
-        DirectoryScanner scanner = resultFileSet.getDirectoryScanner(p);
-        String[] scannedFiles = scanner.getIncludedFiles();
-        Hashtable files = new Hashtable();
-        for (String scannedFile : scannedFiles) {
-            files.put(scannedFile, scannedFile);
-        }
-        assertEquals("Classfileset did not pick up expected number of "
-            + "class files", 5, files.size());
-        assertTrue("Result did not contain A.class",
-            files.containsKey("A.class"));
-        assertTrue("Result did not contain B.class",
-            files.containsKey("B.class"));
-        assertTrue("Result did not contain C.class",
-            files.containsKey("C.class"));
-        assertTrue("Result did not contain D.class",
-            files.containsKey("D.class"));
-        assertTrue("Result did not contain E.class",
-            files.containsKey("E.class"));
+        Hashtable<String, String> files = getFiles();
+        assertEquals("Classfileset did not pick up expected number of class files",
+                5, files.size());
+        assertThat("Result did not contain A.class", files, hasKey("A.class"));
+        assertThat("Result did not contain B.class", files, hasKey("B.class"));
+        assertThat("Result did not contain C.class", files, hasKey("C.class"));
+        assertThat("Result did not contain D.class", files, hasKey("D.class"));
+        assertThat("Result did not contain E.class", files, hasKey("E.class"));
     }
 
     /**
@@ -157,25 +119,18 @@
      */
     @Test
     public void testMethodParamInner() {
-        Project p = buildRule.getProject();
         buildRule.executeTarget("testmethodparaminner");
-        FileSet resultFileSet = p.getReference(RESULT_FILESET);
-        DirectoryScanner scanner = resultFileSet.getDirectoryScanner(p);
-        String[] scannedFiles = scanner.getIncludedFiles();
-        Hashtable files = new Hashtable();
-        for (String scannedFile : scannedFiles) {
-            files.put(scannedFile, scannedFile);
-        }
-        assertEquals("Classfileset did not pick up expected number of "
-            + "class files", 4, files.size());
-        assertTrue("Result did not contain test" + File.separator + "Outer$Inner.class",
-            files.containsKey("test" + File.separator + "Outer$Inner.class"));
-        assertTrue("Result did not contain test" + File.separator + "Outer.class",
-            files.containsKey("test" + File.separator + "Outer.class"));
-        assertTrue("Result did not contain test" + File.separator + "ContainsOnlyInner.class",
-            files.containsKey("test" + File.separator + "ContainsOnlyInner.class"));
-        assertTrue("Result did not contain test" + File.separator + "ContainsOnlyInner.class",
-            files.containsKey("test" + File.separator + "MethodParam.class"));
+        Hashtable<String, String> files = getFiles();
+        assertEquals("Classfileset did not pick up expected number of class files",
+                4, files.size());
+        assertThat("Result did not contain test" + File.separator + "Outer$Inner.class",
+            files, hasKey("test" + File.separator + "Outer$Inner.class"));
+        assertThat("Result did not contain test" + File.separator + "Outer.class",
+            files, hasKey("test" + File.separator + "Outer.class"));
+        assertThat("Result did not contain test" + File.separator + "ContainsOnlyInner.class",
+            files, hasKey("test" + File.separator + "ContainsOnlyInner.class"));
+        assertThat("Result did not contain test" + File.separator + "ContainsOnlyInner.class",
+            files, hasKey("test" + File.separator + "MethodParam.class"));
     }
 
     @Test
@@ -183,4 +138,11 @@
         buildRule.executeTarget("testresourcecollection");
     }
 
+    private Hashtable<String, String> getFiles() {
+        FileSet resultFileSet = buildRule.getProject().getReference(RESULT_FILESET);
+        DirectoryScanner scanner = resultFileSet.getDirectoryScanner(buildRule.getProject());
+        String[] scannedFiles = scanner.getIncludedFiles();
+        return Arrays.stream(scannedFiles)
+                .collect(Collectors.toMap(file -> file, file -> file, (a, b) -> b, Hashtable::new));
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/FileResourceTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/FileResourceTest.java
index 690ace6..c34d86e 100644
--- a/src/tests/junit/org/apache/tools/ant/types/resources/FileResourceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/resources/FileResourceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,9 @@
 package org.apache.tools.ant.types.resources;
 
 import java.io.File;
+import java.io.IOException;
 
+import org.apache.tools.ant.MagicTestNames;
 import org.apache.tools.ant.Project;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,8 +36,10 @@
     private File root;
 
     @Before
-    public void setUp() {
-        root = new File(System.getProperty("root"));
+    public void setUp() throws IOException {
+        root = (System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY) == null)
+                ? new File(".").getCanonicalFile()
+                : new File(System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java
index a67db39..050509b 100644
--- a/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/resources/JavaResourceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,9 +22,10 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
 
 public class JavaResourceTest {
 
@@ -43,8 +44,8 @@
 
         // this actually relies on the first manifest being found on
         // the classpath (probably rt.jar's) being valid
-        assertTrue(buildRule.getProject().getProperty("manifest")
-                   .startsWith("Manifest-Version:"));
+        assertThat(buildRule.getProject().getProperty("manifest"),
+                   startsWith("Manifest-Version:"));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/LazyResourceCollectionTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/LazyResourceCollectionTest.java
index 3a2a7ec..e8be47e 100644
--- a/src/tests/junit/org/apache/tools/ant/types/resources/LazyResourceCollectionTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/resources/LazyResourceCollectionTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,7 +18,6 @@
 package org.apache.tools.ant.types.resources;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -29,38 +28,40 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 public class LazyResourceCollectionTest {
 
     private class StringResourceCollection implements ResourceCollection {
-        List resources = Arrays.<Resource>asList();
+        List<StringResourceIterator> createdIterators = new ArrayList<>();
 
-        List createdIterators = new ArrayList();
-
+        @Override
         public int size() {
-            return resources.size();
+            return 3;
         }
 
+        @Override
         public Iterator<Resource> iterator() {
             StringResourceIterator it = new StringResourceIterator();
             createdIterators.add(it);
             return it;
         }
 
+        @Override
         public boolean isFilesystemOnly() {
             return false;
         }
     }
 
-    private class StringResourceIterator implements Iterator {
+    private class StringResourceIterator implements Iterator<Resource> {
         int cursor = 0;
 
+        @Override
         public void remove() {
             throw new UnsupportedOperationException();
         }
 
-        public Object next() {
+        @Override
+        public StringResource next() {
             if (cursor < 3) {
                 cursor++;
                 return new StringResource("r" + cursor);
@@ -68,47 +69,51 @@
             return null;
         }
 
+        @Override
         public boolean hasNext() {
             return cursor < 3;
         }
     }
 
     @Test
-    public void testLazyLoading() throws Exception {
+    public void testLazyLoading() {
         StringResourceCollection collectionTest = new StringResourceCollection();
         LazyResourceCollectionWrapper lazyCollection = new LazyResourceCollectionWrapper();
         lazyCollection.add(collectionTest);
 
         Iterator<Resource> it = lazyCollection.iterator();
         assertOneCreatedIterator(collectionTest);
-        StringResourceIterator stringResourceIterator = (StringResourceIterator) collectionTest.createdIterators.get(0);
+        StringResourceIterator stringResourceIterator = collectionTest.createdIterators.get(0);
         assertEquals("A resource was loaded without iterating", 1,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        StringResource r = (StringResource) it.next();
+        assertStringValue("r1", it.next());
         assertOneCreatedIterator(collectionTest);
-        assertEquals("r1", r.getValue());
         assertEquals("Iterating once load more than 1 resource", 2,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it.next();
+        assertStringValue("r2", it.next());
         assertOneCreatedIterator(collectionTest);
-        assertEquals("r2", r.getValue());
         assertEquals("Iterating twice load more than 2 resources", 3,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it.next();
+        assertStringValue("r3", it.next());
         assertOneCreatedIterator(collectionTest);
-        assertEquals("r3", r.getValue());
         assertEquals("Iterating 3 times load more than 3 resources", 3,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
+    }
 
-        try {
-            it.next();
-            fail("NoSuchElementException should have been raised");
-        } catch (NoSuchElementException e) {
-            // ok
-        }
+    @Test(expected = NoSuchElementException.class)
+    public void testLazyLoadingFailsOnceWrappedCollectionIsExhausted() {
+        StringResourceCollection collectionTest = new StringResourceCollection();
+        LazyResourceCollectionWrapper lazyCollection = new LazyResourceCollectionWrapper();
+        lazyCollection.add(collectionTest);
+
+        Iterator<Resource> it = lazyCollection.iterator();
+        it.next();
+        it.next();
+        it.next();
+        it.next();
     }
 
     private void assertOneCreatedIterator(
@@ -118,7 +123,7 @@
     }
 
     @Test
-    public void testCaching() throws Exception {
+    public void testCaching() {
         StringResourceCollection collectionTest = new StringResourceCollection();
         LazyResourceCollectionWrapper lazyCollection = new LazyResourceCollectionWrapper();
         lazyCollection.add(collectionTest);
@@ -129,52 +134,66 @@
         Iterator<Resource> it2 = lazyCollection.iterator();
         assertOneCreatedIterator(collectionTest);
 
-        StringResourceIterator stringResourceIterator = (StringResourceIterator) collectionTest.createdIterators.get(0);
+        StringResourceIterator stringResourceIterator = collectionTest.createdIterators.get(0);
         assertEquals("A resource was loaded without iterating", 1,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        StringResource r = (StringResource) it1.next();
-        assertEquals("r1", r.getValue());
+        assertStringValue("r1", it1.next());
         assertEquals("Iterating once load more than 1 resource", 2,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it2.next();
-        assertEquals("r1", r.getValue());
-        assertEquals("The second iterator did not lookup in the cache for a resource",
-                2, stringResourceIterator.cursor);
+        assertStringValue("r1", it2.next());
+        assertEquals(
+            "The second iterator did not lookup in the cache for a resource", 2,
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it2.next();
-        assertEquals("r2", r.getValue());
+        assertStringValue("r2", it2.next());
         assertEquals("Iterating twice load more than 2 resources", 3,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it1.next();
-        assertEquals("r2", r.getValue());
-        assertEquals("The first iterator did not lookup in the cache for a resource",
-                3, stringResourceIterator.cursor);
+        assertStringValue("r2", it1.next());
+        assertEquals(
+            "The first iterator did not lookup in the cache for a resource", 3,
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it2.next();
-        assertEquals("r3", r.getValue());
+        assertStringValue("r3", it2.next());
         assertEquals("Iterating 3 times load more than 3 resources", 3,
-                stringResourceIterator.cursor);
+            stringResourceIterator.cursor);
 
-        r = (StringResource) it1.next();
-        assertEquals("r3", r.getValue());
-        assertEquals("The first iterator did not lookup in the cache for a resource",
-                3, stringResourceIterator.cursor);
+        assertStringValue("r3", it1.next());
+        assertEquals(
+            "The first iterator did not lookup in the cache for a resource", 3,
+            stringResourceIterator.cursor);
+    }
 
+    @Test(expected = NoSuchElementException.class)
+    public void testCachingFailsOnceWrappedCollectionIsExhausted() {
+        StringResourceCollection collectionTest = new StringResourceCollection();
+        LazyResourceCollectionWrapper lazyCollection = new LazyResourceCollectionWrapper();
+        lazyCollection.add(collectionTest);
+
+        Iterator<Resource> it1 = lazyCollection.iterator();
+        Iterator<Resource> it2 = lazyCollection.iterator();
+
+        it1.next();
+        it2.next();
+        it2.next();
+        it1.next();
+        it2.next();
+        it1.next();
+
+        // next() must throw the expected NoSuchElementException;
+        // if that does not happen, assertions throw the unexpected Assertion error
         try {
             it1.next();
-            fail("NoSuchElementException should have been raised");
-        } catch (NoSuchElementException e) {
-            // ok
-        }
-
-        try {
+            assertTrue(it1.hasNext());
+        } finally {
             it2.next();
-            fail("NoSuchElementException should have been raised");
-        } catch (NoSuchElementException e) {
-            // ok
+            assertTrue(it2.hasNext());
         }
     }
+
+    private void assertStringValue(String expected, Resource r) {
+        assertEquals(expected, r.as(StringResource.class).getValue());
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/MultiRootFileSetTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/MultiRootFileSetTest.java
index 2676632..841d0d1 100644
--- a/src/tests/junit/org/apache/tools/ant/types/resources/MultiRootFileSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/resources/MultiRootFileSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,17 +25,24 @@
 import org.apache.tools.ant.types.AbstractFileSet;
 import org.apache.tools.ant.types.AbstractFileSetTest;
 import org.apache.tools.ant.types.Reference;
+import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.endsWith;
 
 /**
  * This doesn't actually test much, mainly reference handling.
  */
 public class MultiRootFileSetTest extends AbstractFileSetTest {
 
+    private MultiRootFileSet multiRootFileSet;
+
+    @Before
+    public void setUp() {
+        super.setUp();
+        multiRootFileSet = new MultiRootFileSet();
+    }
+
     protected AbstractFileSet getInstance() {
         return new MultiRootFileSet() {
             // overriding so set/getDir works as expected by the base test class
@@ -58,73 +65,58 @@
     }
 
     @Test
-    public void testEmptyElementIfIsReferenceAdditionalAttributes() {
-        MultiRootFileSet f = new MultiRootFileSet();
-        f.setProject(getProject());
-        f.setBaseDirs("a");
-        try {
-            f.setRefid(new Reference(getProject(), "dummyref"));
-            fail("Can add reference to multirootfileset "
-                 + " with elements from setBasedirs");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        f = new MultiRootFileSet();
-        f.addConfiguredBaseDir(new FileResource(new File(".")));
-        try {
-            f.setRefid(new Reference(getProject(), "dummyref"));
-            fail("Can add reference to multirootfileset"
-                 + " with elements from addConfiguredBaseDir");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-
-        f = new MultiRootFileSet();
-        f.setRefid(new Reference(getProject(), "dummyref"));
-        try {
-            f.setBaseDirs("a");
-            fail("Can set basedirs in multirootfileset"
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.setCache(true);
-            fail("Can set cache in multirootfileset"
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.setType(MultiRootFileSet.SetType.file);
-            fail("Can set type in multirootfileset"
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute "
-                         + "when using refid", be.getMessage());
-        }
-        try {
-            f.addConfiguredBaseDir(new FileResource(new File(".")));
-            fail("Can add nested basedir in multirootfileset "
-                 + " that is a reference.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using "
-                         + "refid", be.getMessage());
-        }
+    public void testCannotSetBaseDirsThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        multiRootFileSet.setProject(getProject());
+        multiRootFileSet.setBaseDirs("a");
+        multiRootFileSet.setRefid(new Reference(getProject(), "dummyref"));
     }
 
     @Test
-    public void testDirCannotBeSet() {
-        try {
-            new MultiRootFileSet().setDir(new File("."));
-            fail("Can set dir in a multirootfileset");
-        } catch (BuildException e) {
-            assertTrue(e.getMessage()
-                       .endsWith(" doesn't support the dir attribute"));
-        }
+    public void testCannotSetConfiguredBaseDirThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        multiRootFileSet.addConfiguredBaseDir(new FileResource(new File(".")));
+        multiRootFileSet.setRefid(new Reference(getProject(), "dummyref"));
+    }
+
+    @Test
+    public void testCannotSetRefidThenBaseDirs() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        multiRootFileSet.setRefid(new Reference(getProject(), "dummyref"));
+        multiRootFileSet.setBaseDirs("a");
+    }
+
+    @Test
+    public void testCannotSetRefidThenCache() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        multiRootFileSet.setRefid(new Reference(getProject(), "dummyref"));
+        multiRootFileSet.setCache(true);
+    }
+
+    @Test
+    public void testCannotSetRefidThenType() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        multiRootFileSet.setRefid(new Reference(getProject(), "dummyref"));
+        multiRootFileSet.setType(MultiRootFileSet.SetType.file);
+    }
+
+    @Test
+    public void testCannotSetRefidThenConfiguredBaseDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        multiRootFileSet.setRefid(new Reference(getProject(), "dummyref"));
+        multiRootFileSet.addConfiguredBaseDir(new FileResource(new File(".")));
+    }
+
+    @Test
+    public void testCannotSetDir() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(endsWith(" doesn't support the dir attribute"));
+        multiRootFileSet.setDir(new File("."));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/ResourceListTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/ResourceListTest.java
index f020178..4b88433 100644
--- a/src/tests/junit/org/apache/tools/ant/types/resources/ResourceListTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/resources/ResourceListTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,110 +25,93 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 public class ResourceListTest {
 
     @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
     public BuildFileRule buildRule = new BuildFileRule();
 
+    private ResourceList rl;
+
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         buildRule.configureProject("src/etc/testcases/types/resources/resourcelist.xml");
+        rl = new ResourceList();
     }
 
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
         buildRule.executeTarget("tearDown");
     }
 
     @Test
-    public void testEmptyElementWithReference() {
-        ResourceList rl = new ResourceList();
+    public void testEmptyElementSetEncodingThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
         rl.setEncoding("foo");
-        try {
-            rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-            fail("Can add reference to ResourceList with encoding attribute set.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-
-        rl = new ResourceList();
         rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-        try {
-            rl.setEncoding("foo");
-            fail("Can set encoding in ResourceList that is a reference");
-        } catch (BuildException be) {
-            assertEquals("You must not specify more than one attribute when using refid",
-                         be.getMessage());
-        }
-
-        rl = new ResourceList();
-        rl.add(new FileResource(buildRule.getProject(), "."));
-        try {
-            rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-            fail("Can add reference to ResourceList with nested resource collection.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
-
-        rl = new ResourceList();
-        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-        try {
-            rl.add(new FileResource(buildRule.getProject(), "."));
-            fail("Can add reference to ResourceList with nested resource collection.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
-
-        rl = new ResourceList();
-        rl.addFilterChain(new FilterChain());
-        try {
-            rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-            fail("Can add reference to ResourceList with nested filter chain.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
-
-        rl = new ResourceList();
-        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
-        try {
-            rl.addFilterChain(new FilterChain());
-            fail("Can add reference to ResourceList with nested filter chain.");
-        } catch (BuildException be) {
-            assertEquals("You must not specify nested elements when using refid",
-                         be.getMessage());
-        }
     }
 
     @Test
-    public void testCircularReference() throws Exception {
-        ResourceList rl1 = new ResourceList();
-        rl1.setProject(buildRule.getProject());
-        rl1.setRefid(new Reference(buildRule.getProject(), "foo"));
+    public void testEmptyElementSetRefidThenEncoding() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify more than one attribute when using refid");
+        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+        rl.setEncoding("foo");
+    }
 
-        ResourceList rl2 = new ResourceList();
-        rl2.setProject(buildRule.getProject());
-        buildRule.getProject().addReference("foo", rl2);
+    @Test
+    public void testEmptyElementAddFileResourceThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        rl.add(new FileResource(buildRule.getProject(), "."));
+        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+    }
+
+    @Test
+    public void testEmptyElementAddRefidThenFileResource() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+        rl.add(new FileResource(buildRule.getProject(), "."));
+    }
+
+    @Test
+    public void testEmptyElementAddFilterChainThenRefid() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        rl.addFilterChain(new FilterChain());
+        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+    }
+
+    @Test
+    public void testEmptyElementAddRefidThenFilterChain() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must not specify nested elements when using refid");
+        rl.setRefid(new Reference(buildRule.getProject(), "dummyref"));
+        rl.addFilterChain(new FilterChain());
+    }
+
+    @Test
+    public void testCircularReference() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("This data type contains a circular reference.");
+        rl.setProject(buildRule.getProject());
+        rl.setRefid(new Reference(buildRule.getProject(), "foo"));
+
+        ResourceList resourceList = new ResourceList();
+        resourceList.setProject(buildRule.getProject());
+        buildRule.getProject().addReference("foo", resourceList);
 
         Union u = new Union();
-        u.add(rl1);
+        u.add(rl);
         u.setProject(buildRule.getProject());
 
-        rl2.add(u);
-
-        try {
-            rl2.size();
-            fail("Can make ResourceList a Reference to itself.");
-        } catch (BuildException be) {
-            assertEquals("This data type contains a circular reference.",
-                         be.getMessage());
-        }
+        resourceList.add(u);
+        resourceList.size();
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/resources/TarResourceTest.java b/src/tests/junit/org/apache/tools/ant/types/resources/TarResourceTest.java
index f848f7d..31a7d52 100644
--- a/src/tests/junit/org/apache/tools/ant/types/resources/TarResourceTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/resources/TarResourceTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -36,13 +36,13 @@
     public BuildFileRule buildRule = new BuildFileRule();
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         buildRule.configureProject("src/etc/testcases/types/resources/tarentry.xml");
     }
 
 
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
         buildRule.executeTarget("tearDown");
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorRule.java b/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorRule.java
index 735a4dd..4028c53 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorRule.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorRule.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorTest.java
index 8133308..795deb8 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/BaseSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsRegexpTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsRegexpTest.java
index 4928e76..1b5e967 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsRegexpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsRegexpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -41,15 +41,10 @@
     @Test
     public void testContainsRegexp() {
         buildRule.executeTarget("containsregexp");
-        File dir = new File(buildRule.getOutputDir(), "regexpseltestdest");
-        File[] files = dir.listFiles();
-        int filecount = files.length;
+        File[] files = new File(buildRule.getOutputDir(), "regexpseltestdest").listFiles();
 
-        if (filecount != 1)  {
-            assertEquals("ContainsRegexp test should have copied 1 file",
-                         1, files.length);
-
-        }
+        assertEquals("ContainsRegexp test should have copied 1 file",
+                1, files.length);
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsSelectorTest.java
index 1b19c05..fc4eca0 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/ContainsSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,14 @@
 
 package org.apache.tools.ant.types.selectors;
 
+import static org.junit.Assert.assertEquals;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Parameter;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests Contains Selectors.
@@ -35,76 +36,81 @@
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private ContainsSelector s;
+
+    @Before
+    public void setUp() {
+        s = new ContainsSelector();
+    }
 
     /**
      * Test the code that validates the selector.
      */
     @Test
-    public void testValidate() {
-        ContainsSelector s = new ContainsSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("ContainsSelector did not check for required field 'text'");
-        } catch (BuildException be1) {
-            assertEquals("The text attribute is required", be1.getMessage());
-        }
+    public void testValidateMissingParameter() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The text attribute is required");
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new ContainsSelector();
+    @Test
+    public void testValidateInvalidParameter() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid parameter garbage in");
         Parameter param = new Parameter();
         param.setName("garbage in");
         param.setValue("garbage out");
         Parameter[] params = {param};
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("ContainsSelector did not check for valid parameter element");
-        } catch (BuildException be2) {
-            assertEquals("Invalid parameter garbage in", be2.getMessage());
-        }
-
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
     }
 
     /**
      * Tests to make sure that the selector is selecting files correctly.
      */
     @Test
-    public void testSelectionBehaviour() {
-        ContainsSelector s;
-        String results;
-
-        s = new ContainsSelector();
+    public void testSelectionBehaviourNoSuch() {
         s.setText("no such string in test files");
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFFFFFT", results);
+        assertEquals("TFFFFFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new ContainsSelector();
+    @Test
+    public void testSelectionBehaviourCase() {
         s.setText("Apache Ant");
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFTFFFFFFT", results);
+        assertEquals("TFFFTFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new ContainsSelector();
+    @Test
+    public void testSelectionBehaviourCaseSensitive() {
         s.setText("apache ant");
         s.setCasesensitive(true);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFFFFFT", results);
+        assertEquals("TFFFFFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new ContainsSelector();
+    @Test
+    public void testSelectionBehaviourCaseInsensitive() {
         s.setText("apache ant");
         s.setCasesensitive(false);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFTFFFFFFT", results);
+        assertEquals("TFFFTFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new ContainsSelector();
+    @Test
+    public void testSelectionBehaviourNoWhitespace() {
         s.setText("ApacheAnt");
         s.setIgnorewhitespace(true);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFTFFFFFFT", results);
+        assertEquals("TFFFTFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new ContainsSelector();
+    @Test
+    public void testSelectionBehaviourIgnoreWhitespace() {
         s.setText("A p a c h e    A n t");
         s.setIgnorewhitespace(true);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFTFFFFFFT", results);
+        assertEquals("TFFFTFFFFFFT", selectorRule.selectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/DateSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/DateSelectorTest.java
index ec3ea89..68e0ede 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/DateSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/DateSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,13 +20,13 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Parameter;
-import org.junit.Assume;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Tests Date Selectors.
@@ -37,160 +37,160 @@
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private DateSelector s;
+
+    private DateSelector.TimeComparisons before;
+
+    private DateSelector.TimeComparisons equal;
+
+    private DateSelector.TimeComparisons after;
+
+    @Before
+    public void setUp() {
+        s = new DateSelector();
+
+        before = new DateSelector.TimeComparisons();
+        before.setValue("before");
+
+        equal = new DateSelector.TimeComparisons();
+        equal.setValue("equal");
+
+        after = new DateSelector.TimeComparisons();
+        after.setValue("after");
+    }
 
     /**
      * Test the code that validates the selector.
      */
     @Test
-    public void testValidate() {
-        DateSelector s = new DateSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DateSelector did not check for required fields");
-        } catch (BuildException be1) {
-            assertEquals("You must provide a datetime or the number of "
-                    + "milliseconds.", be1.getMessage());
-        }
+    public void testValidateFields() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must provide a datetime or the number of milliseconds.");
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testValidateRange() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Date of 01/01/1969 01:01 AM results in negative milliseconds value"
+                + " relative to epoch (January 1, 1970, 00:00:00 GMT).");
         s.setDatetime("01/01/1969 01:01 AM");
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DateSelector did not check for Datetime being in the "
-                    + "allowable range");
-        } catch (BuildException be2) {
-            assertEquals("Date of 01/01/1969 01:01 AM results in negative "
-                    + "milliseconds value relative to epoch (January 1, "
-                    + "1970, 00:00:00 GMT).", be2.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testValidateFormat() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Date of this is not a date Cannot be parsed correctly."
+                + " It should be in 'MM/dd/yyyy hh:mm a' format.");
         s.setDatetime("this is not a date");
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DateSelector did not check for Datetime being in a "
-                    + "valid format");
-        } catch (BuildException be3) {
-            assertEquals("Date of this is not a date"
-                        + " Cannot be parsed correctly. It should be in"
-                        + " 'MM/dd/yyyy hh:mm a' format.", be3.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testValidateParameterIn() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid parameter garbage in");
         Parameter param = new Parameter();
         param.setName("garbage in");
         param.setValue("garbage out");
         Parameter[] params = new Parameter[1];
         params[0] = param;
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DateSelector did not check for valid parameter element");
-        } catch (BuildException be4) {
-            assertEquals("Invalid parameter garbage in", be4.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
+    }
 
-        s = new DateSelector();
-        param = new Parameter();
+    @Test
+    public void testValidateParameterMillis() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid millisecond setting garbage out");
+        Parameter param = new Parameter();
         param.setName("millis");
         param.setValue("garbage out");
+        Parameter[] params = new Parameter[1];
         params[0] = param;
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DateSelector did not check for valid millis parameter");
-        } catch (BuildException be5) {
-            assertEquals("Invalid millisecond setting garbage out",
-                    be5.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
+    }
 
-        s = new DateSelector();
-        param = new Parameter();
+    @Test
+    public void testValidateParameterGranularity() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid granularity setting garbage out");
+        Parameter param = new Parameter();
         param.setName("granularity");
         param.setValue("garbage out");
+        Parameter[] params = new Parameter[1];
         params[0] = param;
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DateSelector did not check for valid granularity parameter");
-        } catch (BuildException be6) {
-            assertEquals("Invalid granularity setting garbage out",
-                    be6.getMessage());
-        }
-
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
     }
 
     /**
      * Tests to make sure that the selector is selecting files correctly.
      */
     @Test
-    public void testSelectionBehaviour() {
-        DateSelector s;
-        String results;
-
-        DateSelector.TimeComparisons before = new
-                DateSelector.TimeComparisons();
-        before.setValue("before");
-        DateSelector.TimeComparisons equal = new
-                DateSelector.TimeComparisons();
-        equal.setValue("equal");
-        DateSelector.TimeComparisons after = new
-                DateSelector.TimeComparisons();
-        after.setValue("after");
-
-
-        s = new DateSelector();
+    public void testSelectionBehaviourBefore() {
         s.setDatetime("10/10/1999 1:45 PM");
         s.setWhen(before);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFFFFFT", results);
+        assertEquals("TFFFFFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourBeforeCheckdirs() {
         s.setDatetime("10/10/1999 1:45 PM");
         s.setWhen(before);
         s.setCheckdirs(true);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFFFF", results);
+        assertEquals("FFFFFFFFFFFF", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourAfter() {
         s.setDatetime("10/10/1999 1:45 PM");
         s.setWhen(after);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTT", results);
+        assertEquals("TTTTTTTTTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourBefore2K() {
         s.setDatetime("11/21/2001 4:54 AM");
         s.setWhen(before);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFTFFFFFFFFT", results);
+        assertEquals("TFTFFFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourEqual() {
         s.setDatetime("11/21/2001 4:55 AM");
-
-        long milliseconds = s.getMillis();
         s.setWhen(equal);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTFFTFFFTTTT", results);
+        assertEquals("TTFFTFFFTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
-        s.setMillis(milliseconds);
+    @Test
+    public void testSelectionBehaviourEqualMillis() {
+        s.setDatetime("11/21/2001 4:55 AM");
+        s.setMillis(s.getMillis());
         s.setWhen(equal);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTFFTFFFTTTT", results);
+        assertEquals("TTFFTFFFTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourAfter2K() {
         s.setDatetime("11/21/2001 4:56 AM");
         s.setWhen(after);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFTFTTTFFFT", results);
+        assertEquals("TFFTFTTTFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourAfterNamed() {
         Parameter param1 = new Parameter();
         Parameter param2 = new Parameter();
         param1.setName("datetime");
@@ -199,39 +199,38 @@
         param2.setValue("after");
         Parameter[] params = {param1, param2};
         s.setParameters(params);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFTFTTTFFFT", results);
+        assertEquals("TFFTFTTTFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new DateSelector();
+    @Test
+    public void testSelectionBehaviourAfterWithGranularity() {
         long testtime = selectorRule.getMirrorFiles()[5].lastModified();
         s.setMillis(testtime);
         s.setWhen(after);
         s.setGranularity(2);
 
-        // setup the modified timestamp to match what the test needs, although be aware that the 3rd and 4th
-        // files don't exist so can't be changed, so don't try and loop over them
+        // setup the modified timestamp to match what the test needs, although be aware that
+        // the 3rd and 4th files don't exist so can't be changed, so don't try and loop over them
         for (int i = 1; i <= 2; i++) {
-            Assume.assumeTrue("Cannot setup file times for test",
+            assumeTrue("Cannot setup file times for test",
                     selectorRule.getMirrorFiles()[i].setLastModified(testtime - (3 * 60 * 60 * 100)));
         }
 
+        assertEquals("TFFFFTTTTTTT", selectorRule.mirrorSelectionString(s));
+    }
 
-        results = selectorRule.mirrorSelectionString(s);
-        assertEquals("TFFFFTTTTTTT", results);
-
-        s = new DateSelector();
-        testtime = selectorRule.getMirrorFiles()[6].lastModified();
+    @Test
+    public void testSelectionBehaviourBeforeWithGranularity() {
+        long testtime = selectorRule.getMirrorFiles()[6].lastModified();
         s.setMillis(testtime);
         s.setWhen(before);
         s.setGranularity(2);
         for (int i = 7; i <= 10; i++) {
-            Assume.assumeTrue("Cannot setup file times for test",
+            assumeTrue("Cannot setup file times for test",
                     selectorRule.getMirrorFiles()[i].setLastModified(testtime + (3 * 60 * 60 * 100)));
         }
 
-        results = selectorRule.mirrorSelectionString(s);
-        assertEquals("TTTTTTTFFFFT", results);
-
+        assertEquals("TTTTTTTFFFFT", selectorRule.mirrorSelectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/DependSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/DependSelectorTest.java
index ec95878..bd7069f 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/DependSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/DependSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,16 @@
 
 package org.apache.tools.ant.types.selectors;
 
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.Mapper;
-import org.junit.Rule;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
 
 import java.io.File;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Mapper;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 
 /**
@@ -35,48 +36,44 @@
  */
 public class DependSelectorTest {
 
+    private DependSelector s;
+
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        s = new DependSelector();
+    }
+
     @Test
     public void testValidateSingleMapper() {
-        try {
-            DependSelector s = new DependSelector();
-            s.createMapper();
-            s.createMapper();
-            fail("DependSelector allowed more than one nested mapper.");
-        } catch (BuildException be1) {
-            assertEquals("Cannot define more than one mapper",
-                    be1.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot define more than one mapper");
+        s.createMapper();
+        s.createMapper();
     }
 
 
     @Test
      public void testValidateRequiredFields() {
-        try {
-            DependSelector s = new DependSelector();
-            s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("DependSelector did not check for required fields");
-        } catch (BuildException be2) {
-            assertEquals("The targetdir attribute is required.",
-                    be2.getMessage());
-        }
-
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The targetdir attribute is required.");
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
     }
 
     @Test
     public void testNoMapper() {
-        DependSelector s = new DependSelector();
         s.setTargetdir(selectorRule.getBeddir());
-
-        String results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFFFF", results);
+        assertEquals("FFFFFFFFFFFF", selectorRule.selectionString(s));
     }
 
     @Test
     public void testIdentityMapper() {
-        DependSelector s = new DependSelector();
         s.setTargetdir(selectorRule.getBeddir());
 
         Mapper.MapperType identity = new Mapper.MapperType();
@@ -85,13 +82,11 @@
         Mapper m = s.createMapper();
         m.setType(identity);
 
-        String results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFFFF", results);
+        assertEquals("FFFFFFFFFFFF", selectorRule.selectionString(s));
     }
 
     @Test
     public void testMergeMapper() {
-        DependSelector s = new DependSelector();
         s.setTargetdir(selectorRule.getBeddir());
 
         Mapper.MapperType merge = new Mapper.MapperType();
@@ -101,13 +96,11 @@
         m.setType(merge);
         m.setTo("asf-logo.gif.gz");
 
-        String results = selectorRule.selectionString(s);
-        assertEquals("TFFFFTTTFFF", results.substring(0,11));
+        assertEquals("TFFFFTTTFFF", selectorRule.selectionString(s).substring(0, 11));
     }
 
     @Test
     public void testMergeMapper2() {
-        DependSelector s = new DependSelector();
         s.setTargetdir(selectorRule.getBeddir());
 
         Mapper.MapperType merge = new Mapper.MapperType();
@@ -116,13 +109,12 @@
         Mapper m = s.createMapper();
         m.setType(merge);
         m.setTo("asf-logo.gif.bz2");
-        String results = selectorRule.selectionString(s);
-        assertEquals("TTFTTTTTTTTT", results);
+
+        assertEquals("TTFTTTTTTTTT", selectorRule.selectionString(s));
     }
 
     @Test
     public void testGlobMapperRelativePath() {
-        DependSelector s = new DependSelector();
         File subdir = new File("selectortest/tar/bz2");
         s.setTargetdir(subdir);
 
@@ -134,13 +126,11 @@
         m.setFrom("*.bz2");
         m.setTo("*.tar.bz2");
 
-        String results = selectorRule.selectionString(s);
-        assertEquals("FFTFFFFFFTTF", results);
+        assertEquals("FFTFFFFFFTTF", selectorRule.selectionString(s));
     }
 
     @Test
     public void testRestrictedGlobMapper() {
-        DependSelector s = new DependSelector();
         File subdir = new File(selectorRule.getBeddir(), "tar/bz2");
         s.setTargetdir(subdir);
 
@@ -151,22 +141,19 @@
         m.setType(glob);
         m.setFrom("*.bz2");
         m.setTo("*.tar.bz2");
-        String results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFTTF", results);
+
+        assertEquals("FFFFFFFFFTTF", selectorRule.selectionString(s));
     }
 
     @Test
     public void testSelectionNoMapper() {
-        DependSelector s = new DependSelector();
         s.setTargetdir(new File(selectorRule.getOutputDir(), "selectortest2"));
-        String results = selectorRule.selectionString(s);
-        assertEquals("FFFTTFFFFFFF", results);
+        assertEquals("FFFTTFFFFFFF", selectorRule.selectionString(s));
     }
 
 
     @Test
     public void testMirroredSelection() {
-        DependSelector s = new DependSelector();
         s.setTargetdir(new File(selectorRule.getOutputDir(), "selectortest2/tar/bz2"));
 
         Mapper.MapperType glob = new Mapper.MapperType();
@@ -176,10 +163,9 @@
         m.setType(glob);
         m.setFrom("*.bz2");
         m.setTo("*.tar.bz2");
-        String results = selectorRule.mirrorSelectionString(s);
-        assertEquals("FFFFFFFFFTTF", results);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFTTF", results);
+
+        assertEquals("FFFFFFFFFTTF", selectorRule.mirrorSelectionString(s));
+        assertEquals("FFFFFFFFFTTF", selectorRule.selectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/DepthSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/DepthSelectorTest.java
index 3c7e429..1367e87 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/DepthSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/DepthSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,14 @@
 
 package org.apache.tools.ant.types.selectors;
 
+import static org.junit.Assert.assertEquals;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Parameter;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests Depth Selectors
@@ -35,111 +36,112 @@
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private DepthSelector s;
+
+    @Before
+    public void setUp() {
+        s = new DepthSelector();
+    }
 
     /**
      * Test the code that validates the selector.
      */
     @Test
-    public void testValidate() {
-        DepthSelector s = new DepthSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("DepthSelector did not check for required fields");
-        } catch (BuildException be1) {
-            assertEquals("You must set at least one of the min or the " +
-                    "max levels.", be1.getMessage());
-        }
+    public void testValidateRequiredFields() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("You must set at least one of the min or the max levels.");
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new DepthSelector();
+    @Test
+    public void testValidateDepth() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The maximum depth is lower than the minimum.");
         s.setMin(5);
         s.setMax(2);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("DepthSelector did not check for maximum being higher "
-                    + "than minimum");
-        } catch (BuildException be2) {
-            assertEquals("The maximum depth is lower than the minimum.",
-                    be2.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new DepthSelector();
+    @Test
+    public void testValidateParameterName() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid parameter garbage in");
         Parameter param = new Parameter();
         param.setName("garbage in");
         param.setValue("garbage out");
         Parameter[] params = new Parameter[1];
         params[0] = param;
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("DepthSelector did not check for valid parameter element");
-        } catch (BuildException be3) {
-            assertEquals("Invalid parameter garbage in", be3.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new DepthSelector();
-        param = new Parameter();
+    @Test
+    public void testValidateMinValue() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid minimum value garbage out");
+        Parameter param = new Parameter();
         param.setName("min");
         param.setValue("garbage out");
+        Parameter[] params = new Parameter[1];
         params[0] = param;
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("DepthSelector accepted bad minimum as parameter");
-        } catch (BuildException be4) {
-            assertEquals("Invalid minimum value garbage out",
-                    be4.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new DepthSelector();
-        param = new Parameter();
+    @Test
+    public void testValidateMaxValue() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid maximum value garbage out");
+        Parameter param = new Parameter();
         param.setName("max");
         param.setValue("garbage out");
+        Parameter[] params = new Parameter[1];
         params[0] = param;
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("DepthSelector accepted bad maximum as parameter");
-        } catch (BuildException be5) {
-            assertEquals("Invalid maximum value garbage out",
-                    be5.getMessage());
-        }
-
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
     }
 
     /**
      * Tests to make sure that the selector is selecting files correctly.
      */
     @Test
-    public void testSelectionBehaviour() {
-        DepthSelector s;
-        String results;
-
-        s = new DepthSelector();
+    public void testSelectionBehaviourMinMax() {
         s.setMin(20);
         s.setMax(25);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFFFF", results);
+        assertEquals("FFFFFFFFFFFF", selectorRule.selectionString(s));
+    }
 
-        s = new DepthSelector();
+    @Test
+    public void testSelectionBehaviourMin0() {
         s.setMin(0);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTT", results);
+        assertEquals("TTTTTTTTTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new DepthSelector();
+    @Test
+    public void testSelectionBehaviourMin1() {
         s.setMin(1);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFFFTTTTTTT", results);
+        assertEquals("FFFFFTTTTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new DepthSelector();
+    @Test
+    public void testSelectionBehaviourMax0() {
         s.setMax(0);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTFFFFFFF", results);
+        assertEquals("TTTTTFFFFFFF", selectorRule.selectionString(s));
+    }
 
-        s = new DepthSelector();
+    @Test
+    public void testSelectionBehaviourMin1Max1() {
         s.setMin(1);
         s.setMax(1);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFFFTTTFFFT", results);
+        assertEquals("FFFFFTTTFFFT", selectorRule.selectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/FilenameSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/FilenameSelectorTest.java
index 09483bf..0c508b4 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/FilenameSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/FilenameSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,13 +18,15 @@
 
 package org.apache.tools.ant.types.selectors;
 
+import static org.junit.Assert.assertEquals;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Parameter;
+import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests Filename Selectors
@@ -35,32 +37,41 @@
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private FilenameSelector s;
+
+    @Before
+    public void setUp() {
+        s = new FilenameSelector();
+    }
+
     /**
-     * Test the code that validates the selector.
+     * Test the code that validates the selector: required attribute.
+     */
+    @Test
+    public void testRequired() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The name or regex attribute is required");
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
+
+    /**
+     * Test the code that validates the selector: invalid parameter.
      */
     @Test
     public void testValidate() {
-        FilenameSelector s = new FilenameSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("FilenameSelector did not check for required fields");
-        } catch (BuildException be1) {
-            assertEquals("The name or regex attribute is required", be1.getMessage());
-        }
-
-        s = new FilenameSelector();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid parameter garbage in");
         Parameter param = new Parameter();
         param.setName("garbage in");
         param.setValue("garbage out");
         Parameter[] params = {param};
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("FilenameSelector did not check for valid parameter element");
-        } catch (BuildException be2) {
-            assertEquals("Invalid parameter garbage in", be2.getMessage());
-        }
-
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
     }
 
     /**
@@ -68,44 +79,40 @@
      */
     @Test
     public void testSelectionBehaviour() {
-        FilenameSelector s;
-        String results;
-
-        s = new FilenameSelector();
         s.setName("no match possible");
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFFFFFFFFFF", results);
+        assertEquals("FFFFFFFFFFFF", selectorRule.selectionString(s));
+    }
 
-        s = new FilenameSelector();
+    @Ignore("Turned off due to a bug: SelectorUtils.matchPattern() is recursive without '**' on Windows")
+    @Test
+    public void testSelectionBehaviourWildcard() {
         s.setName("*.gz");
-        results = selectorRule.selectionString(s);
-        // This is turned off temporarily. There appears to be a bug
-        // in SelectorUtils.matchPattern() where it is recursive on
-        // Windows even if no ** is in pattern.
-        //assertEquals("FFFTFFFFFFFF", results); // Unix
-        // vs
-        //assertEquals("FFFTFFFFTFFF", results); // Windows
+        assertEquals("FFFTFFFFFFFF", selectorRule.selectionString(s)); // Unix
+        assertEquals("FFFTFFFFTFFF", selectorRule.selectionString(s)); // Windows
+    }
 
-        s = new FilenameSelector();
+    @Test
+    public void testSelectionBehaviourNegate() {
         s.setName("**/*.gz");
         s.setNegate(true);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTFTTTFFTTT", results);
+        assertEquals("TTTFTTTFFTTT", selectorRule.selectionString(s));
+    }
 
-        s = new FilenameSelector();
+    @Test
+    public void testSelectionBehaviourCaseInsensitive() {
         s.setName("**/*.GZ");
         s.setCasesensitive(false);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFFTFFFTTFFF", results);
+        assertEquals("FFFTFFFTTFFF", selectorRule.selectionString(s));
+    }
 
-        s = new FilenameSelector();
+    @Test
+    public void testSelectionBehaviourNamedParameter() {
         Parameter param1 = new Parameter();
         param1.setName("name");
         param1.setValue("**/*.bz2");
         Parameter[] params = {param1};
         s.setParameters(params);
-        results = selectorRule.selectionString(s);
-        assertEquals("FFTFFFFFFTTF", results);
+        assertEquals("FFTFFFFFFTTF", selectorRule.selectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/MockAlgorithm.java b/src/tests/junit/org/apache/tools/ant/types/selectors/MockAlgorithm.java
index 458c83f..2d24b0d 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/MockAlgorithm.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/MockAlgorithm.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/MockCache.java b/src/tests/junit/org/apache/tools/ant/types/selectors/MockCache.java
index 81e379a..b8efe68 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/MockCache.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/MockCache.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/MockComparator.java b/src/tests/junit/org/apache/tools/ant/types/selectors/MockComparator.java
index 180aa46..ef58944 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/MockComparator.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/MockComparator.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,7 +20,7 @@
 
 import java.util.Comparator;
 
-public class MockComparator implements Comparator {
+public class MockComparator implements Comparator<Object> {
 
     public int compare(Object o1, Object o2) {
         return 0;
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/ModifiedSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/ModifiedSelectorTest.java
index 0b940ad..1e84bb7 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/ModifiedSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/ModifiedSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,16 +18,17 @@
 
 package org.apache.tools.ant.types.selectors;
 
-
 import java.io.File;
 import java.io.FileWriter;
+import java.io.IOException;
 import java.text.RuleBasedCollator;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Iterator;
 
-import org.apache.tools.ant.AntAssert;
 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.Target;
 import org.apache.tools.ant.Task;
@@ -41,20 +42,21 @@
 import org.apache.tools.ant.types.selectors.modifiedselector.HashvalueAlgorithm;
 import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
 import org.apache.tools.ant.types.selectors.modifiedselector.PropertiesfileCache;
-import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.StringUtils;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 
 /**
  * Unit tests for ModifiedSelector.
@@ -66,17 +68,19 @@
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
-    /** Utilities used for file operations */
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
-    //  =====================  attributes  =====================
+    @Rule
+    public TemporaryFolder testFolder = new TemporaryFolder();
+
+    //  =====================  fixtures  =====================
 
     /** Path where the testclasses are. */
-    private Path testclasses = null;
+    private Path testclasses;
 
     //  =====================  JUnit stuff  =====================
 
-
     @Before
     public void setUp() {
         // init the testclasses path object
@@ -90,89 +94,63 @@
     @Test
     public void testValidateWrongCache() {
         String name = "this-is-not-a-valid-cache-name";
-        try {
-            ModifiedSelector.CacheName cacheName = new ModifiedSelector.CacheName();
-            cacheName.setValue(name);
-            fail("CacheSelector.CacheName accepted invalid value.");
-        } catch (BuildException be) {
-            assertEquals(name + " is not a legal value for this attribute",
-                         be.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(name + " is not a legal value for this attribute");
+        new ModifiedSelector.CacheName().setValue(name);
     }
 
     /** Test correct use of cache names. */
     @Test
     public void testValidateWrongAlgorithm() {
         String name = "this-is-not-a-valid-algorithm-name";
-        try {
-            ModifiedSelector.AlgorithmName algoName
-                = new ModifiedSelector.AlgorithmName();
-            algoName.setValue(name);
-            fail("CacheSelector.AlgorithmName accepted invalid value.");
-        } catch (BuildException be) {
-            assertEquals(name + " is not a legal value for this attribute",
-                         be.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(name + " is not a legal value for this attribute");
+        new ModifiedSelector.AlgorithmName().setValue(name);
     }
 
     /** Test correct use of comparator names. */
     @Test
     public void testValidateWrongComparator() {
         String name = "this-is-not-a-valid-comparator-name";
-        try {
-            ModifiedSelector.ComparatorName compName
-                = new ModifiedSelector.ComparatorName();
-            compName.setValue(name);
-            fail("ModifiedSelector.ComparatorName accepted invalid value.");
-        } catch (BuildException be) {
-            assertEquals(name + " is not a legal value for this attribute",
-                         be.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage(name + " is not a legal value for this attribute");
+        new ModifiedSelector.ComparatorName().setValue(name);
     }
 
     /** Test correct use of algorithm names. */
     @Test
     public void testIllegalCustomAlgorithm() {
-        try {
-            getAlgoName("java.lang.Object");
-            fail("Illegal classname used.");
-        } catch (BuildException e) {
-            assertEquals("Wrong exception message.",
-                         "Specified class (java.lang.Object) is not an Algorithm.",
-                         e.getMessage());
-
-        }
+        String className = "java.lang.Object";
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Specified class (" + className + ") is not an Algorithm.");
+        getAlgoName(className);
     }
 
     /** Test correct use of algorithm names. */
     @Test
     public void testNonExistentCustomAlgorithm() {
-         try {
-            getAlgoName("non.existent.custom.Algorithm");
-            fail("does 'non.existent.custom.Algorithm' really exist?");
-        } catch (BuildException e) {
-            assertEquals("Wrong exception message.",
-                         "Specified class (non.existent.custom.Algorithm) not found.",
-                         e.getMessage());
-
-        }
+        String className = "non.existent.custom.Algorithm";
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Specified class (" + className + ") not found.");
+        getAlgoName(className);
     }
 
     @Test
     public void testCustomAlgorithm() {
         String algo = getAlgoName("org.apache.tools.ant.types.selectors.modifiedselector.HashvalueAlgorithm");
-        assertTrue("Wrong algorithm used: " + algo, algo.startsWith("HashvalueAlgorithm"));
+        assertThat("Wrong algorithm used: " + algo, algo, startsWith("HashvalueAlgorithm"));
     }
 
     @Test
     public void testCustomAlgorithm2() {
         String algo = getAlgoName("org.apache.tools.ant.types.selectors.MockAlgorithm");
-        assertTrue("Wrong algorithm used: " + algo, algo.startsWith("MockAlgorithm"));
+        assertThat("Wrong algorithm used: " + algo, algo, startsWith("MockAlgorithm"));
     }
 
     @Test
     public void testCustomClasses() {
-        Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home"));
+        assertNotNull("Ant home not set",
+                selectorRule.getProject().getProperty(MagicNames.ANT_HOME));
         BFT bft = new BFT();
         bft.setUp();
         // don't catch the JUnit exceptions
@@ -184,12 +162,13 @@
             String fsModValue  = bft.getProperty("fs.mod.value");
 
             assertNotNull("'fs.full.value' must be set.", fsFullValue);
-            assertTrue("'fs.full.value' must not be null.", !"".equals(fsFullValue));
-            assertTrue("'fs.full.value' must contain ant.bat.", fsFullValue.contains("ant.bat"));
+            assertNotEquals("'fs.full.value' must not be null.", "", fsFullValue);
+            assertThat("'fs.full.value' must contain ant.bat.", fsFullValue,
+                    containsString("ant.bat"));
 
             assertNotNull("'fs.mod.value' must be set.", fsModValue);
             // must be empty according to the Mock* implementations
-            assertTrue("'fs.mod.value' must be empty.", "".equals(fsModValue));
+            assertEquals("'fs.mod.value' must be empty.", "", fsModValue);
         } finally {
             bft.doTarget("modifiedselectortest-scenario-clean");
             bft.deletePropertiesfile();
@@ -302,8 +281,7 @@
     @Test
     public void testPropcacheInvalid() {
         Cache cache = new PropertiesfileCache();
-        if (cache.isValid())
-            fail("PropertyfilesCache does not check its configuration.");
+        assertFalse("PropertyfilesCache does not check its configuration.", cache.isValid());
     }
 
     @Test
@@ -367,11 +345,10 @@
      * configure() method of ModifiedSelector. This testcase tests that.
      */
     @Test
-    public void testCreatePropertiesCacheViaCustomSelector() {
-        File cachefile = FILE_UTILS.createTempFile("tmp-cache-", ".properties", null, false, false);
+    public void testCreatePropertiesCacheViaCustomSelector() throws IOException {
+        File cachefile = testFolder.newFile("tmp-cache.properties");
 
         // Configure the selector
-
         ExtendSelector s = new ExtendSelector();
         s.setClassname("org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector");
         s.addParam(createParam("update", "true"));
@@ -382,7 +359,6 @@
 
         // evaluate correctness
         assertTrue("Cache file is not created.", cachefile.exists());
-        cachefile.delete();
     }
 
     @Test
@@ -408,7 +384,7 @@
         String value2 = "value2";
 
         // given cache must be empty
-        Iterator it1 = cache.iterator();
+        Iterator<String> it1 = cache.iterator();
         assertFalse("Cache is not empty", it1.hasNext());
 
         // cache must return a stored value
@@ -418,9 +394,9 @@
         assertEquals("cache returned wrong value", value2, cache.get(key2));
 
         // test the iterator
-        Iterator it2 = cache.iterator();
-        Object   returned = it2.next();
-        boolean ok = (key1.equals(returned) || key2.equals(returned));
+        Iterator<String> it2 = cache.iterator();
+        String returned = it2.next();
+        boolean ok = key1.equals(returned) || key2.equals(returned);
         String msg = "Iterator returned unexpected value."
                    + "  key1.equals(returned)=" + key1.equals(returned)
                    + "  key2.equals(returned)=" + key2.equals(returned)
@@ -430,7 +406,7 @@
 
         // clear the cache
         cache.delete();
-        Iterator it3 = cache.iterator();
+        Iterator<String> it3 = cache.iterator();
         assertFalse("Cache is not empty", it3.hasNext());
     }
 
@@ -485,30 +461,26 @@
      * @param algo   configured test object
      */
     protected void doTest(Algorithm algo) {
-         assertTrue("Algorithm not proper configured.", algo.isValid());
-         for (int i=0; i<selectorRule.getFiles().length; i++) {
-            File file = selectorRule.getFiles()[i];  // must not be a directory
-            if (file.isFile()) {
-                // get the Hashvalues
-                String hash1 = algo.getValue(file);
-                String hash2 = algo.getValue(file);
-                String hash3 = algo.getValue(file);
-                String hash4 = algo.getValue(file);
-                String hash5 = algo.getValue(new File(file.getAbsolutePath()));
-
-                // Assert !=null and equality
-                assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash1);
-                assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash2);
-                assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash3);
-                assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash4);
-                assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash5);
-                assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash2);
-                assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash3);
-                assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash4);
-                assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash5);
-            }//if-isFile
-        }//for
-
+        assertTrue("Algorithm not proper configured.", algo.isValid());
+        // must not be a directory
+        Arrays.stream(selectorRule.getFiles()).filter(File::isFile).forEach(file -> {
+            // get the Hashvalues
+            String hash1 = algo.getValue(file);
+            String hash2 = algo.getValue(file);
+            String hash3 = algo.getValue(file);
+            String hash4 = algo.getValue(file);
+            String hash5 = algo.getValue(new File(file.getAbsolutePath()));
+            // Assert !=null and equality
+            assertNotNull("Hashvalue was null for " + file.getAbsolutePath(), hash1);
+            assertNotNull("Hashvalue was null for " + file.getAbsolutePath(), hash2);
+            assertNotNull("Hashvalue was null for " + file.getAbsolutePath(), hash3);
+            assertNotNull("Hashvalue was null for " + file.getAbsolutePath(), hash4);
+            assertNotNull("Hashvalue was null for " + file.getAbsolutePath(), hash5);
+            assertEquals("getHashvalue() returned different value for " + file.getAbsolutePath(), hash1, hash2);
+            assertEquals("getHashvalue() returned different value for " + file.getAbsolutePath(), hash1, hash3);
+            assertEquals("getHashvalue() returned different value for " + file.getAbsolutePath(), hash1, hash4);
+            assertEquals("getHashvalue() returned different value for " + file.getAbsolutePath(), hash1, hash5);
+        });
     }
 
     // ==============  testcases for the comparator implementations  ==============
@@ -570,7 +542,7 @@
     public void testResourceSelectorSelresTrue() {
         BFT bft = new BFT();
         bft.doTarget("modifiedselectortest-ResourceSelresTrue");
-        AntAssert.assertContains("does not provide an InputStream", bft.getLog());
+        assertThat(bft.getLog(), containsString("does not provide an InputStream"));
         bft.deleteCachefile();
     }
 
@@ -583,8 +555,8 @@
 
     @Test
     public void testResourceSelectorScenarioSimple() {
-
-        Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home"));
+        assertNotNull("Ant home not set",
+                selectorRule.getProject().getProperty(MagicNames.ANT_HOME));
         BFT bft = new BFT();
         bft.doTarget("modifiedselectortest-scenario-resourceSimple");
         bft.doTarget("modifiedselectortest-scenario-clean");
@@ -597,14 +569,14 @@
      *
      * @param comp   configured test object
      */
-    protected void doTest(Comparator comp) {
-        Object o1 = new String("string1");
-        Object o2 = new String("string2");
-        Object o3 = new String("string2"); // really "2"
+    protected void doTest(Comparator<Object> comp) {
+        Object o1 = "string1";
+        Object o2 = "string2";
+        Object o3 = "string2"; // really "2"
 
-        assertTrue("Comparator gave wrong value.", comp.compare(o1, o2) != 0);
-        assertTrue("Comparator gave wrong value.", comp.compare(o1, o3) != 0);
-        assertTrue("Comparator gave wrong value.", comp.compare(o2, o3) == 0);
+        assertNotEquals("Comparator gave wrong value.", 0, comp.compare(o1, o2));
+        assertNotEquals("Comparator gave wrong value.", 0, comp.compare(o1, o3));
+        assertEquals("Comparator gave wrong value.", 0, comp.compare(o2, o3));
     }
 
     // =====================  scenario tests  =====================
@@ -804,19 +776,22 @@
 
     @Test
     public void testScenarioCoreSelectorDefaults() {
-        Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home"));
+        assertNotNull("Ant home not set",
+                selectorRule.getProject().getProperty(MagicNames.ANT_HOME));
         doScenarioTest("modifiedselectortest-scenario-coreselector-defaults", "cache.properties");
     }
 
     @Test
     public void testScenarioCoreSelectorSettings() {
-        Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home"));
+        assertNotNull("Ant home not set",
+                selectorRule.getProject().getProperty(MagicNames.ANT_HOME));
         doScenarioTest("modifiedselectortest-scenario-coreselector-settings", "core.cache.properties");
     }
 
     @Test
     public void testScenarioCustomSelectorSettings() {
-        Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home"));
+        assertNotNull("Ant home not set",
+                selectorRule.getProject().getProperty(MagicNames.ANT_HOME));
         doScenarioTest("modifiedselectortest-scenario-customselector-settings", "core.cache.properties");
     }
 
@@ -837,8 +812,8 @@
             // do the checks
             assertTrue("Cache file not created.", cachefile.exists());
             assertTrue("Not enough files copied on first time.", to1.list().length > 5);
-            assertTrue("Too much files copied on second time.", to2.list().length == 0);
-            assertTrue("Too much files copied on third time.", to3.list().length == 2);
+            assertEquals("Too much files copied on second time.", 0, to2.list().length);
+            assertEquals("Too much files copied on third time.", 2, to3.list().length);
         // don't catch the JUnit exceptions
         } finally {
             bft.doTarget("modifiedselectortest-scenario-clean");
@@ -908,7 +883,7 @@
             try {
                 FileWriter out = new FileWriter(file.getAbsolutePath(), true);
                 out.write(line);
-                out.write(StringUtils.LINE_SEP);
+                out.write(System.lineSeparator());
                 out.flush();
                 out.close();
             } catch (Exception e) {
@@ -932,7 +907,7 @@
     }
 
     /**
-     * MockProject wrappes a very small ant project (one target, one task)
+     * MockProject wraps a very small ant project (one target, one task)
      * but provides public methods to fire the build events.
      */
     private class MockProject extends Project {
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..daf1006
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
@@ -0,0 +1,86 @@
+/*
+ *  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
+ *
+ *      https://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.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.UserPrincipal;
+
+import org.apache.tools.ant.taskdefs.condition.Os;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class OwnedBySelectorTest {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private final File TEST_FILE = new File("/etc/passwd");
+
+    private final String SELF = System.getProperty("user.name");
+
+    private final String ROOT_USER = "root";
+
+    private OwnedBySelector s;
+
+    @Before
+    public void setUp() {
+        // at least on Jenkins the file is owned by "BUILTIN\Administrators"
+        assumeFalse(Os.isFamily("windows"));
+
+        s = new OwnedBySelector();
+    }
+
+    @Test
+    public void ownedByIsTrueForSelf() throws Exception {
+        File file = folder.newFile("f.txt");
+        UserPrincipal user = Files.getOwner(file.toPath());
+        assertEquals(SELF, user.getName());
+
+        s.setOwner(SELF);
+        assertTrue(s.isSelected(null, null, file));
+    }
+
+    @Test
+    public void ownedByFollowSymlinks() throws IOException {
+        File target = new File(folder.getRoot(), "link");
+        Path symbolicLink = Files.createSymbolicLink(target.toPath(), TEST_FILE.toPath());
+
+        UserPrincipal root = Files.getOwner(symbolicLink);
+        assertEquals(ROOT_USER, root.getName());
+
+        UserPrincipal user = Files.getOwner(symbolicLink, LinkOption.NOFOLLOW_LINKS);
+        assertEquals(SELF, user.getName());
+
+        s.setOwner(SELF);
+        assertFalse(s.isSelected(null, null, symbolicLink.toFile()));
+        s.setFollowSymlinks(false);
+        assertTrue(s.isSelected(null, null, symbolicLink.toFile()));
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java
new file mode 100644
index 0000000..9c05f7e
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java
@@ -0,0 +1,110 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.taskdefs.condition.Os;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+public class PosixGroupSelectorTest {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private final String GROUP_GETTER = "getGid";
+
+    private final File TEST_FILE = new File("/etc/passwd");
+
+    private Class<?> jaasProviderClass;
+
+    private PosixGroupSelector s;
+
+    @Before
+    public void setUp() {
+        assumeTrue("Not POSIX", Os.isFamily("unix"));
+        String osName = System.getProperty("os.name", "unknown").toLowerCase();
+        String jaasProviderClassName = osName.contains("sunos")
+           ? "com.sun.security.auth.module.SolarisSystem"
+           : "com.sun.security.auth.module.UnixSystem";
+
+        try {
+            jaasProviderClass = Class.forName(jaasProviderClassName);
+        } catch (Throwable e) {
+            assumeNoException("Cannot obtain OS-specific JAAS information", e);
+        }
+
+        s = new PosixGroupSelector();
+    }
+
+    @Test
+    public void posixGroupIsTrueForSelf() throws Exception {
+        long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER)
+                .invoke(jaasProviderClass.getDeclaredConstructor().newInstance());
+
+        File file = folder.newFile("f.txt");
+        Map<String, Object> fileAttributes = Files.readAttributes(file.toPath(),
+                "unix:group,gid", LinkOption.NOFOLLOW_LINKS);
+        long actualGid = (int) fileAttributes.get("gid");
+        assertEquals("Different GIDs", gid, actualGid);
+
+        GroupPrincipal actualGroup = (GroupPrincipal) fileAttributes.get("group");
+        s.setGroup(actualGroup.getName());
+        assertTrue(s.isSelected(null, null, file));
+    }
+
+    @Test
+    public void posixGroupFollowSymlinks() throws Exception {
+        long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER)
+                .invoke(jaasProviderClass.getDeclaredConstructor().newInstance());
+
+        File target = new File(folder.getRoot(), "link");
+        Path symbolicLink = Files.createSymbolicLink(target.toPath(), TEST_FILE.toPath());
+        Map<String, Object> linkAttributes = Files.readAttributes(target.toPath(),
+                "unix:group,gid", LinkOption.NOFOLLOW_LINKS);
+        long linkGid = (int) linkAttributes.get("gid");
+        assertEquals("Different GIDs", gid, linkGid);
+
+        GroupPrincipal targetGroup = Files.readAttributes(target.toPath(),
+                PosixFileAttributes.class).group();
+        GroupPrincipal linkGroup = (GroupPrincipal) linkAttributes.get("group");
+        assertNotEquals("Same group name", linkGroup.getName(),
+                targetGroup.getName());
+
+        s.setGroup(linkGroup.getName());
+        assertFalse(s.isSelected(null, null, symbolicLink.toFile()));
+        s.setFollowSymlinks(false);
+        assertTrue(s.isSelected(null, null, symbolicLink.toFile()));
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java
new file mode 100644
index 0000000..c39ef4b
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java
@@ -0,0 +1,150 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.condition.Os;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+@RunWith(Enclosed.class)
+public class PosixPermissionsSelectorTest {
+
+    @RunWith(Parameterized.class)
+    public static class IllegalArgumentTest {
+
+        private PosixPermissionsSelector s;
+
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "illegal argument: |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("855", "4555", "-rwxr-xr-x", "xrwr-xr-x");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Before
+        public void setUp() {
+            assumeTrue("Not POSIX", Os.isFamily("unix"));
+            s = new PosixPermissionsSelector();
+        }
+
+        @Test(expected = BuildException.class)
+        public void test() {
+            s.setPermissions(argument);
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class LegalArgumentTest {
+
+        private PosixPermissionsSelector s;
+
+        @Rule
+        public TemporaryFolder folder = new TemporaryFolder();
+
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "legal argument (self): |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("750", "rwxr-x---");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Before
+        public void setUp() {
+            assumeTrue("Not POSIX", Os.isFamily("unix"));
+            s = new PosixPermissionsSelector();
+        }
+
+        @Test
+        public void test() throws Exception {
+            // do not depend on default umask
+            File subFolder = folder.newFolder();
+            Set<PosixFilePermission> permissions = new HashSet<>();
+            permissions.add(PosixFilePermission.OWNER_READ);
+            permissions.add(PosixFilePermission.OWNER_WRITE);
+            permissions.add(PosixFilePermission.OWNER_EXECUTE);
+            permissions.add(PosixFilePermission.GROUP_READ);
+            permissions.add(PosixFilePermission.GROUP_EXECUTE);
+            Files.setPosixFilePermissions(subFolder.toPath(), permissions);
+
+            s.setPermissions(argument);
+            assertTrue(s.isSelected(null, null, subFolder));
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class LegalSymbolicLinkArgumentTest {
+
+        private final File TEST_FILE = new File("/etc/passwd");
+
+        private PosixPermissionsSelector s;
+
+        @Rule
+        public TemporaryFolder folder = new TemporaryFolder();
+
+        // requires JUnit 4.12
+        @Parameterized.Parameters(name = "legal argument (link): |{0}|")
+        public static Collection<String> data() {
+            return Arrays.asList("644", "rw-r--r--");
+        }
+
+        @Parameterized.Parameter
+        public String argument;
+
+        @Before
+        public void setUp() {
+            assumeTrue("Not POSIX", Os.isFamily("unix"));
+            s = new PosixPermissionsSelector();
+        }
+
+        @Test
+        public void test() throws Exception {
+            // symlinks have execute bit set by default
+            File target = new File(folder.getRoot(), "link");
+            Path symbolicLink = Files.createSymbolicLink(target.toPath(), TEST_FILE.toPath());
+
+            s.setPermissions(argument);
+            assertTrue(s.isSelected(null, null, symbolicLink.toFile()));
+            s.setFollowSymlinks(false);
+            assertFalse(s.isSelected(null, null, symbolicLink.toFile()));
+        }
+    }
+
+}
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/PresentSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/PresentSelectorTest.java
index 07b664d..b43de46 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/PresentSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/PresentSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,16 +18,16 @@
 
 package org.apache.tools.ant.types.selectors;
 
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.Mapper;
-import org.junit.Rule;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
 
 import java.io.File;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Mapper;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests Present Selectors
@@ -35,34 +35,39 @@
  */
 public class PresentSelectorTest {
 
+    private PresentSelector s;
+
+    private File beddir;
 
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        s = new PresentSelector();
+        beddir = selectorRule.getBeddir();
+    }
+
     /**
      * Test the code that validates the selector.
      */
     @Test
     public void testValidate() {
-        PresentSelector s = new PresentSelector();
-        try {
-            s.createMapper();
-            s.createMapper();
-            fail("PresentSelector allowed more than one nested mapper.");
-        } catch (BuildException be1) {
-            assertEquals("Cannot define more than one mapper",
-                    be1.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Cannot define more than one mapper");
+        s.createMapper();
+        s.createMapper();
+    }
 
-        s = new PresentSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("PresentSelector did not check for required fields");
-        } catch (BuildException be2) {
-            assertEquals("The targetdir attribute is required.",
-                    be2.getMessage());
-        }
-
+    @Test
+    public void testValidateAttributes() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The targetdir attribute is required.");
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
     }
 
     /**
@@ -70,65 +75,61 @@
      */
     @Test
     public void testSelectionBehaviour() {
-        PresentSelector s;
-        String results;
-        Mapper m;
+        s.setTargetdir(beddir);
+        assertEquals("TTTTTTTTTTTT", selectorRule.selectionString(s));
+    }
+
+    @Test
+    public void testSelectionBehaviour1() {
+        s.setTargetdir(beddir);
+        Mapper m = s.createMapper();
         Mapper.MapperType identity = new Mapper.MapperType();
         identity.setValue("identity");
-        Mapper.MapperType glob = new Mapper.MapperType();
-        glob.setValue("glob");
-        Mapper.MapperType merge = new Mapper.MapperType();
-        merge.setValue("merge");
+        m.setType(identity);
+        assertEquals("TTTTTTTTTTTT", selectorRule.selectionString(s));
+    }
+
+    @Test
+    public void testSelectionBehaviour2() {
+        File subdir = selectorRule.getProject().resolveFile("../taskdefs/expected");
+        s.setTargetdir(subdir);
+        Mapper m = s.createMapper();
         Mapper.MapperType flatten = new Mapper.MapperType();
         flatten.setValue("flatten");
-
-        File beddir = selectorRule.getBeddir();
-
-        s = new PresentSelector();
-        s.setTargetdir(beddir);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTT", results);
-
-        s = new PresentSelector();
-        s.setTargetdir(beddir);
-        m = s.createMapper();
-        m.setType(identity);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTT", results);
-
-        s = new PresentSelector();
-        File subdir = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/expected");
-        s.setTargetdir(subdir);
-        m = s.createMapper();
         m.setType(flatten);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTF", results);
+        assertEquals("TTTTTTTTTTTF", selectorRule.selectionString(s));
+    }
 
-        s = new PresentSelector();
+    @Test
+    public void testSelectionBehaviour3() {
         s.setTargetdir(beddir);
-        m = s.createMapper();
+        Mapper m = s.createMapper();
+        Mapper.MapperType merge = new Mapper.MapperType();
+        merge.setValue("merge");
         m.setType(merge);
         m.setTo("asf-logo.gif.gz");
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTT", results);
+        assertEquals("TTTTTTTTTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new PresentSelector();
-        subdir = new File(beddir, "tar/bz2");
+    @Test
+    public void testSelectionBehaviour4() {
+        File subdir = new File(beddir, "tar/bz2");
         s.setTargetdir(subdir);
-        m = s.createMapper();
+        Mapper m = s.createMapper();
+        Mapper.MapperType glob = new Mapper.MapperType();
+        glob.setValue("glob");
         m.setType(glob);
         m.setFrom("*.bz2");
         m.setTo("*.tar.bz2");
-        results = selectorRule.selectionString(s);
-        assertEquals("FFTFFFFFFFFF", results);
+        assertEquals("FFTFFFFFFFFF", selectorRule.selectionString(s));
+    }
 
-        s = new PresentSelector();
-        subdir = new File(selectorRule.getOutputDir(), "selectortest2");
+    @Test
+    public void testSelectionBehaviour5() {
+        File subdir = new File(selectorRule.getOutputDir(), "selectortest2");
         s.setTargetdir(subdir);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTFFTTTTTTT", results);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTFFTTTTTTT", results);
+        assertEquals("TTTFFTTTTTTT", selectorRule.selectionString(s));
+        assertEquals("TTTFFTTTTTTT", selectorRule.selectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/SignedSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/SignedSelectorTest.java
index 1eb40dc..37a5528 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/SignedSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/SignedSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/SizeSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/SizeSelectorTest.java
index 38179c3..757b9ad 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/SizeSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/SizeSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,15 +18,16 @@
 
 package org.apache.tools.ant.types.selectors;
 
+import static org.junit.Assert.assertEquals;
+
 import java.util.Locale;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Parameter;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.rules.ExpectedException;
 
 /**
  * Tests Size Selectors
@@ -37,140 +38,151 @@
     @Rule
     public final BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private SizeSelector s;
+
+    private SizeSelector.SizeComparisons less;
+
+    private SizeSelector.SizeComparisons equal;
+
+    private SizeSelector.SizeComparisons more;
+
+    @Before
+    public void setUp() {
+        s = new SizeSelector();
+
+        less = new SizeSelector.SizeComparisons();
+        less.setValue("less");
+
+        equal = new SizeSelector.SizeComparisons();
+        equal.setValue("equal");
+
+        more = new SizeSelector.SizeComparisons();
+        more.setValue("more");
+    }
+
     /**
      * Test the code that validates the selector.
      */
     @Test
-    public void testValidate() {
-        SizeSelector s = new SizeSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("SizeSelector did not check for required fields");
-        } catch (BuildException be1) {
-            assertEquals("The value attribute is required, and must "
-                    + "be positive", be1.getMessage());
-        }
+    public void testValidateAttribute() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The value attribute is required, and must be positive");
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testValidateValue() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The value attribute is required, and must be positive");
         s.setValue(-10);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("SizeSelector did not check for value being in the "
-                    + "allowable range");
-        } catch (BuildException be2) {
-            assertEquals("The value attribute is required, and must "
-                    + "be positive", be2.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testValidateAttributeName() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid parameter garbage in");
         Parameter param = new Parameter();
         param.setName("garbage in");
         param.setValue("garbage out");
         Parameter[] params = {param};
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("SizeSelector did not check for valid parameter element");
-        } catch (BuildException be3) {
-            assertEquals("Invalid parameter garbage in", be3.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new SizeSelector();
-        param = new Parameter();
+    @Test
+    public void testValidateAttributeValue() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("Invalid size setting garbage out");
+        Parameter param = new Parameter();
         param.setName("value");
         param.setValue("garbage out");
-        params[0] = param;
+        Parameter[] params = {param};
         s.setParameters(params);
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("SizeSelector accepted bad value as parameter");
-        } catch (BuildException be4) {
-            assertEquals("Invalid size setting garbage out",
-                    be4.getMessage());
-        }
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testValidateAttributeUnits() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("garbage out is not a legal value for this attribute");
         Parameter param1 = new Parameter();
         Parameter param2 = new Parameter();
         param1.setName("value");
         param1.setValue("5");
         param2.setName("units");
         param2.setValue("garbage out");
-        params = new Parameter[2];
+        Parameter[] params = new Parameter[2];
         params[0] = param1;
         params[1] = param2;
-        try {
-            s.setParameters(params);
-            s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],selectorRule.getFiles()[0]);
-            fail("SizeSelector accepted bad units as parameter");
-        } catch (BuildException be5) {
-            assertEquals("garbage out is not a legal value for this attribute",
-                    be5.getMessage());
-        }
-
+        s.setParameters(params);
+        s.isSelected(selectorRule.getProject().getBaseDir(), selectorRule.getFilenames()[0],
+                selectorRule.getFiles()[0]);
     }
 
     /**
      * Tests to make sure that the selector is selecting files correctly.
      */
     @Test
-    public void testSelectionBehaviour() {
-        SizeSelector s;
-        String results;
-
-        SizeSelector.ByteUnits kilo = new SizeSelector.ByteUnits();
-        kilo.setValue("K");
-        SizeSelector.ByteUnits kibi = new SizeSelector.ByteUnits();
-        kibi.setValue("Ki");
-        SizeSelector.ByteUnits tibi = new SizeSelector.ByteUnits();
-        tibi.setValue("Ti");
-        SizeSelector.SizeComparisons less = new SizeSelector.SizeComparisons();
-        less.setValue("less");
-        SizeSelector.SizeComparisons equal = new SizeSelector.SizeComparisons();
-        equal.setValue("equal");
-        SizeSelector.SizeComparisons more = new SizeSelector.SizeComparisons();
-        more.setValue("more");
-
-        s = new SizeSelector();
+    public void testSelectionBehaviourLess() {
         s.setValue(10);
         s.setWhen(less);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFFFFFT", results);
+        assertEquals("TFFFFFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testSelectionBehaviourMore() {
         s.setValue(10);
         s.setWhen(more);
-        results = selectorRule.selectionString(s);
-        assertEquals("TTTTTTTTTTTT", results);
+        assertEquals("TTTTTTTTTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testSelectionBehaviourEqual() {
         s.setValue(32);
         s.setWhen(equal);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFTFFFFFFT", results);
+        assertEquals("TFFFTFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testSelectionBehaviourKilo() {
+        SizeSelector.ByteUnits kilo = new SizeSelector.ByteUnits();
+        kilo.setValue("K");
         s.setValue(7);
         s.setWhen(more);
         s.setUnits(kilo);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFTFFTTTTTTT", results);
+        assertEquals("TFTFFTTTTTTT", selectorRule.selectionString(s));
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testSelectionBehaviourKibi() {
+        SizeSelector.ByteUnits kibi = new SizeSelector.ByteUnits();
+        kibi.setValue("Ki");
         s.setValue(7);
         s.setWhen(more);
         s.setUnits(kibi);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFTFFFTTFTTT", results);
+        assertEquals("TFTFFFTTFTTT", selectorRule.selectionString(s));
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testSelectionBehaviourTibi() {
+        SizeSelector.ByteUnits tibi = new SizeSelector.ByteUnits();
+        tibi.setValue("Ti");
         s.setValue(99999);
         s.setWhen(more);
         s.setUnits(tibi);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFFFFFT", results);
+        assertEquals("TFFFFFFFFFFT", selectorRule.selectionString(s));
+    }
 
-        s = new SizeSelector();
+    @Test
+    public void testSelectionBehaviour() {
         Parameter param1 = new Parameter();
         Parameter param2 = new Parameter();
         Parameter param3 = new Parameter();
@@ -182,8 +194,7 @@
         param3.setValue("more");
         Parameter[] params = {param1, param2, param3};
         s.setParameters(params);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFTFFTT", results);
+        assertEquals("TFFFFFFTFFTT", selectorRule.selectionString(s));
     }
 
     @Test
@@ -219,16 +230,11 @@
     }
 
     private void testCaseInsensitiveParameterParsing(String name) {
-        SizeSelector s = new SizeSelector();
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("foo is not a legal value for this attribute");
         Parameter p = new Parameter();
         p.setName(name);
         p.setValue("foo");
-        try {
-            s.setParameters(new Parameter[] {p});
-            fail("should have caused an exception");
-        } catch (BuildException be) {
-            assertEquals("foo is not a legal value for this attribute",
-                         be.getMessage());
-        }
+        s.setParameters(p);
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/TokenizedPatternTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/TokenizedPatternTest.java
index 4e95c2c..1f16f93 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/TokenizedPatternTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/TokenizedPatternTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -62,12 +62,12 @@
                    .withoutLastToken().matchPath(p, true));
     }
 
-    @Test
     /**
      * this test illustrates the behavior described in bugzilla 59114
      * meaning that the pattern "**" matches the empty path
      * but the pattern "*" does not
      */
+    @Test
     public void testEmptyFolderWithStarStar() {
         TokenizedPath p = TokenizedPath.EMPTY_PATH;
         assertTrue(new TokenizedPattern(SelectorUtils.DEEP_TREE_MATCH).matchPath(p, true));
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/TypeSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/TypeSelectorTest.java
index f6be240..cde4800 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/TypeSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/TypeSelectorTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,11 +19,12 @@
 package org.apache.tools.ant.types.selectors;
 
 import org.apache.tools.ant.BuildException;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 /**
  * Tests Type Selectors.
@@ -34,43 +35,46 @@
     @Rule
     public BaseSelectorRule selectorRule = new BaseSelectorRule();
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    private TypeSelector s;
+
+    @Before
+    public void setUp() {
+        s = new TypeSelector();
+    }
+
     /**
      * Test the code that validates the selector.
      */
     @Test
     public void testValidate() {
-        TypeSelector s = new TypeSelector();
-        try {
-            s.isSelected(selectorRule.getProject().getBaseDir(),
-                    selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
-            fail("TypeSelector did not check for required fields");
-        } catch (BuildException be1) {
-            assertEquals("The type attribute is required", be1.getMessage());
-        }
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("The type attribute is required");
+        s.isSelected(selectorRule.getProject().getBaseDir(),
+                selectorRule.getFilenames()[0], selectorRule.getFiles()[0]);
     }
 
     /**
      * Tests to make sure that the selector is selecting files correctly.
      */
     @Test
-    public void testSelectionBehaviour() {
-        TypeSelector s;
-        String results;
-
+    public void testSelectionBehaviourDir() {
         TypeSelector.FileType directory = new TypeSelector.FileType();
         directory.setValue("dir");
+
+        s.setType(directory);
+        assertEquals("TFFFFFFFFFFT", selectorRule.selectionString(s));
+    }
+
+    @Test
+    public void testSelectionBehaviourFile() {
         TypeSelector.FileType file = new TypeSelector.FileType();
         file.setValue("file");
 
-        s = new TypeSelector();
-        s.setType(directory);
-        results = selectorRule.selectionString(s);
-        assertEquals("TFFFFFFFFFFT", results);
-
-        s = new TypeSelector();
         s.setType(file);
-        results = selectorRule.selectionString(s);
-        assertEquals("FTTTTTTTTTTF", results);
+        assertEquals("FTTTTTTTTTTF", selectorRule.selectionString(s));
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/Base64ConverterTest.java b/src/tests/junit/org/apache/tools/ant/util/Base64ConverterTest.java
index 61fdfba..7b2be1e 100644
--- a/src/tests/junit/org/apache/tools/ant/util/Base64ConverterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/Base64ConverterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,6 +17,7 @@
  */
 package org.apache.tools.ant.util;
 
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -27,17 +28,22 @@
  */
 public class Base64ConverterTest {
 
+    private Base64Converter base64Converter;
+
+    @Before
+    public void setUp() {
+        base64Converter = new Base64Converter();
+    }
+
     @Test
     public void testOneValue() {
-        byte[] mybytes = {0, 0, (byte) 0xFF};
-        Base64Converter base64Converter = new Base64Converter();
-        assertEquals("AAD/", base64Converter.encode(mybytes));
+        assertEquals("AAD/",
+                base64Converter.encode(new byte[]{0, 0, (byte) 0xFF}));
     }
 
     @Test
     public void testHelloWorld() {
-        byte[] mybytes = "Hello World".getBytes();
-        Base64Converter base64Converter = new Base64Converter();
-        assertEquals("SGVsbG8gV29ybGQ=", base64Converter.encode(mybytes));
+        assertEquals("SGVsbG8gV29ybGQ=",
+                base64Converter.encode("Hello World".getBytes()));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/ClasspathUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/ClasspathUtilsTest.java
index 3cffa10..3ea9dc1 100644
--- a/src/tests/junit/org/apache/tools/ant/util/ClasspathUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/ClasspathUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,15 +19,15 @@
 package org.apache.tools.ant.util;
 
 import java.io.IOException;
+import java.net.URL;
 import java.util.Enumeration;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
-import org.apache.tools.ant.types.Path;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 
 
 /**
@@ -47,9 +47,8 @@
 
     @Test
     public void testOnlyOneInstance() {
-        Enumeration enumeration;
-        String list = "";
-        ClassLoader c = ClasspathUtils.getUniqueClassLoaderForPath(p, (Path) null, false);
+        Enumeration<URL> enumeration;
+        ClassLoader c = ClasspathUtils.getUniqueClassLoaderForPath(p, null, false);
         try {
             enumeration = c.getResources(
                 "org/apache/tools/ant/taskdefs/defaults.properties");
@@ -58,10 +57,11 @@
                 "Could not get the defaults.properties resource", e);
         }
         int count = 0;
+        StringBuilder list = new StringBuilder();
         while (enumeration.hasMoreElements()) {
-            list = list + " " + enumeration.nextElement();
+            list.append(" ").append(enumeration.nextElement());
             count++;
         }
-        assertTrue("Should be only one and not " + count + " " + list, count == 1);
+        assertEquals("Should be only one and not " + count + " " + list, 1, count);
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/CollectionUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/CollectionUtilsTest.java
index 425dc47..9fbb515 100644
--- a/src/tests/junit/org/apache/tools/ant/util/CollectionUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/CollectionUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -25,6 +25,7 @@
 
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -36,67 +37,67 @@
 
     @Test
     public void testVectorEquals() {
-        assertTrue(!CollectionUtils.equals(null, new Vector()));
-        assertTrue(!CollectionUtils.equals(new Vector(), null));
+        assertFalse(CollectionUtils.equals(null, new Vector()));
+        assertFalse(CollectionUtils.equals(new Vector(), null));
         assertTrue(CollectionUtils.equals(new Vector(), new Vector()));
-        Vector v1 = new Vector();
-        Stack s2 = new Stack();
+        Vector<String> v1 = new Vector<>();
+        Stack<String> s2 = new Stack<>();
         v1.addElement("foo");
         s2.push("foo");
         assertTrue(CollectionUtils.equals(v1, s2));
         assertTrue(CollectionUtils.equals(s2, v1));
         v1.addElement("bar");
-        assertTrue(!CollectionUtils.equals(v1, s2));
-        assertTrue(!CollectionUtils.equals(s2, v1));
+        assertFalse(CollectionUtils.equals(v1, s2));
+        assertFalse(CollectionUtils.equals(s2, v1));
         s2.push("bar");
         assertTrue(CollectionUtils.equals(v1, s2));
         assertTrue(CollectionUtils.equals(s2, v1));
         s2.push("baz");
-        assertTrue(!CollectionUtils.equals(v1, s2));
-        assertTrue(!CollectionUtils.equals(s2, v1));
+        assertFalse(CollectionUtils.equals(v1, s2));
+        assertFalse(CollectionUtils.equals(s2, v1));
         v1.addElement("baz");
         assertTrue(CollectionUtils.equals(v1, s2));
         assertTrue(CollectionUtils.equals(s2, v1));
         v1.addElement("zyzzy");
         s2.push("zyzzy2");
-        assertTrue(!CollectionUtils.equals(v1, s2));
-        assertTrue(!CollectionUtils.equals(s2, v1));
+        assertFalse(CollectionUtils.equals(v1, s2));
+        assertFalse(CollectionUtils.equals(s2, v1));
     }
 
     @Test
     public void testDictionaryEquals() {
-        assertTrue(!CollectionUtils.equals(null, new Hashtable()));
-        assertTrue(!CollectionUtils.equals(new Hashtable(), null));
+        assertFalse(CollectionUtils.equals(null, new Hashtable()));
+        assertFalse(CollectionUtils.equals(new Hashtable(), null));
         assertTrue(CollectionUtils.equals(new Hashtable(), new Properties()));
-        Hashtable h1 = new Hashtable();
+        Hashtable<String, String> h1 = new Hashtable<>();
         Properties p2 = new Properties();
         h1.put("foo", "");
         p2.put("foo", "");
         assertTrue(CollectionUtils.equals(h1, p2));
         assertTrue(CollectionUtils.equals(p2, h1));
         h1.put("bar", "");
-        assertTrue(!CollectionUtils.equals(h1, p2));
-        assertTrue(!CollectionUtils.equals(p2, h1));
+        assertFalse(CollectionUtils.equals(h1, p2));
+        assertFalse(CollectionUtils.equals(p2, h1));
         p2.put("bar", "");
         assertTrue(CollectionUtils.equals(h1, p2));
         assertTrue(CollectionUtils.equals(p2, h1));
         p2.put("baz", "");
-        assertTrue(!CollectionUtils.equals(h1, p2));
-        assertTrue(!CollectionUtils.equals(p2, h1));
+        assertFalse(CollectionUtils.equals(h1, p2));
+        assertFalse(CollectionUtils.equals(p2, h1));
         h1.put("baz", "");
         assertTrue(CollectionUtils.equals(h1, p2));
         assertTrue(CollectionUtils.equals(p2, h1));
         h1.put("zyzzy", "");
         p2.put("zyzzy2", "");
-        assertTrue(!CollectionUtils.equals(h1, p2));
-        assertTrue(!CollectionUtils.equals(p2, h1));
+        assertFalse(CollectionUtils.equals(h1, p2));
+        assertFalse(CollectionUtils.equals(p2, h1));
         p2.put("zyzzy", "");
         h1.put("zyzzy2", "");
         assertTrue(CollectionUtils.equals(h1, p2));
         assertTrue(CollectionUtils.equals(p2, h1));
         h1.put("dada", "1");
         p2.put("dada", "2");
-        assertTrue(!CollectionUtils.equals(h1, p2));
-        assertTrue(!CollectionUtils.equals(p2, h1));
+        assertFalse(CollectionUtils.equals(h1, p2));
+        assertFalse(CollectionUtils.equals(p2, h1));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/DOMElementWriterTest.java b/src/tests/junit/org/apache/tools/ant/util/DOMElementWriterTest.java
index f9bf08b..292b4f3 100644
--- a/src/tests/junit/org/apache/tools/ant/util/DOMElementWriterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/DOMElementWriterTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -26,6 +26,7 @@
 import java.io.StringWriter;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -41,9 +42,9 @@
         assertTrue("&#20;", w.isReference("&#20;"));
         assertTrue("&#x20;", w.isReference("&#x20;"));
         assertTrue("&#xA0;", w.isReference("&#xA0;"));
-        assertTrue("&#A0;", !w.isReference("&#A0;"));
-        assertTrue("20;", !w.isReference("20;"));
-        assertTrue("&#20", !w.isReference("&#20"));
+        assertFalse("&#A0;", w.isReference("&#A0;"));
+        assertFalse("20;", w.isReference("20;"));
+        assertFalse("&#20", w.isReference("&#20"));
         assertTrue("&quot;", w.isReference("&quot;"));
         assertTrue("&apos;", w.isReference("&apos;"));
         assertTrue("&gt;", w.isReference("&gt;"));
@@ -99,8 +100,7 @@
         StringWriter sw = new StringWriter();
         DOMElementWriter w = new DOMElementWriter();
         w.write(root, sw, 0, "  ");
-        assertEquals("<root foo=\"bar&#xa;baz\" />" + StringUtils.LINE_SEP,
-                     sw.toString());
+        assertEquals(String.format("<root foo=\"bar&#xa;baz\" />%n"), sw.toString());
     }
 
     @Test
@@ -111,18 +111,18 @@
 
     @Test
     public void testIsLegalCharacter() {
-        assertTrue("0x00", !w.isLegalCharacter('\u0000'));
+        assertFalse("0x00", w.isLegalCharacter('\u0000'));
         assertTrue("0x09", w.isLegalCharacter('\t'));
         assertTrue("0x0A", w.isLegalCharacter('\n'));
         assertTrue("0x0C", w.isLegalCharacter('\r'));
-        assertTrue("0x1F", !w.isLegalCharacter('\u001F'));
+        assertFalse("0x1F", w.isLegalCharacter('\u001F'));
         assertTrue("0x20", w.isLegalCharacter('\u0020'));
         assertTrue("0xD7FF", w.isLegalCharacter('\uD7FF'));
-        assertTrue("0xD800", !w.isLegalCharacter('\uD800'));
-        assertTrue("0xDFFF", !w.isLegalCharacter('\uDFFF'));
+        assertFalse("0xD800", w.isLegalCharacter('\uD800'));
+        assertFalse("0xDFFF", w.isLegalCharacter('\uDFFF'));
         assertTrue("0xE000", w.isLegalCharacter('\uE000'));
         assertTrue("0xFFFD", w.isLegalCharacter('\uFFFD'));
-        assertTrue("0xFFFE", !w.isLegalCharacter('\uFFFE'));
+        assertFalse("0xFFFE", w.isLegalCharacter('\uFFFE'));
     }
 
     @Test
@@ -146,11 +146,8 @@
         StringWriter sw = new StringWriter();
         DOMElementWriter w = new DOMElementWriter();
         w.write(root, sw, 0, "  ");
-        assertEquals("<root>" + StringUtils.LINE_SEP
-                     + "  <textElement>content</textElement>"
-                     + StringUtils.LINE_SEP
-                     + "</root>" + StringUtils.LINE_SEP,
-                     sw.toString());
+        assertEquals(String.format("<root>%n  <textElement>content</textElement>%n</root>%n"),
+                sw.toString());
     }
 
     @Test
@@ -162,11 +159,8 @@
         StringWriter sw = new StringWriter();
         DOMElementWriter w = new DOMElementWriter();
         w.write(root, sw, 0, "  ");
-        assertEquals("<root>" + StringUtils.LINE_SEP
-                     + "  <cdataElement><![CDATA[content]]></cdataElement>"
-                     + StringUtils.LINE_SEP
-                     + "</root>" + StringUtils.LINE_SEP,
-                     sw.toString());
+        assertEquals(String.format("<root>%n  <cdataElement><![CDATA[content]]></cdataElement>%n"
+                        + "</root>%n"), sw.toString());
     }
 
     @Test
@@ -178,12 +172,7 @@
         StringWriter sw = new StringWriter();
         DOMElementWriter w = new DOMElementWriter();
         w.write(root, sw, 0, "  ");
-        assertEquals("<root>" + StringUtils.LINE_SEP
-                     //                     + "  <emptyElement></emptyElement>"
-                     + "  <emptyElement />"
-                     + StringUtils.LINE_SEP
-                     + "</root>" + StringUtils.LINE_SEP,
-                     sw.toString());
+        assertEquals(String.format("<root>%n  <emptyElement />%n</root>%n"), sw.toString());
     }
 
     @Test
@@ -195,8 +184,7 @@
         StringWriter sw = new StringWriter();
         DOMElementWriter w = new DOMElementWriter();
         w.write(root, sw, 0, "  ");
-        assertEquals("<root bar=\"baz\" />"
-                     + StringUtils.LINE_SEP, sw.toString());
+        assertEquals(String.format("<root bar=\"baz\" />%n"), sw.toString());
     }
 
     @Test
@@ -206,13 +194,10 @@
         root.setAttributeNS("urn:foo2", "bar", "baz");
 
         StringWriter sw = new StringWriter();
-        DOMElementWriter w =
-            new DOMElementWriter(false,
-                                 DOMElementWriter.XmlNamespacePolicy
-                                 .ONLY_QUALIFY_ELEMENTS);
+        DOMElementWriter w = new DOMElementWriter(false,
+                DOMElementWriter.XmlNamespacePolicy.ONLY_QUALIFY_ELEMENTS);
         w.write(root, sw, 0, "  ");
-        assertEquals("<root bar=\"baz\" xmlns=\"urn:foo\" />"
-                     + StringUtils.LINE_SEP, sw.toString());
+        assertEquals(String.format("<root bar=\"baz\" xmlns=\"urn:foo\" />%n"), sw.toString());
     }
 
     @Test
@@ -222,14 +207,11 @@
         root.setAttributeNS("urn:foo2", "bar", "baz");
 
         StringWriter sw = new StringWriter();
-        DOMElementWriter w =
-            new DOMElementWriter(false,
-                                 DOMElementWriter.XmlNamespacePolicy
-                                 .QUALIFY_ALL);
+        DOMElementWriter w = new DOMElementWriter(false,
+                DOMElementWriter.XmlNamespacePolicy.QUALIFY_ALL);
         w.write(root, sw, 0, "  ");
-        assertEquals("<root ns0:bar=\"baz\" xmlns=\"urn:foo\""
-                     + " xmlns:ns0=\"urn:foo2\" />"
-                     + StringUtils.LINE_SEP, sw.toString());
+        assertEquals(String.format("<root ns0:bar=\"baz\" xmlns=\"urn:foo\""
+                     + " xmlns:ns0=\"urn:foo2\" />%n"), sw.toString());
     }
 
     @Test
@@ -239,11 +221,11 @@
         root.setAttributeNS("urn:foo2", "bar", "baz");
 
         StringWriter sw = new StringWriter();
-        DOMElementWriter w =
-            new DOMElementWriter(false, new DOMElementWriter.XmlNamespacePolicy(false, true));
+        DOMElementWriter w = new DOMElementWriter(false,
+                new DOMElementWriter.XmlNamespacePolicy(false, true));
         w.write(root, sw, 0, "  ");
-        assertEquals("<root ns0:bar=\"baz\" xmlns:ns0=\"urn:foo2\" />"
-                     + StringUtils.LINE_SEP, sw.toString());
+        assertEquals(String.format("<root ns0:bar=\"baz\" xmlns:ns0=\"urn:foo2\" />%n"),
+                sw.toString());
     }
 
     @Test
@@ -253,17 +235,11 @@
         Element child = d.createElementNS("urn:foo", "child");
         root.appendChild(child);
         StringWriter sw = new StringWriter();
-        DOMElementWriter w =
-            new DOMElementWriter(false,
-                                 DOMElementWriter.XmlNamespacePolicy
-                                 .ONLY_QUALIFY_ELEMENTS);
+        DOMElementWriter w = new DOMElementWriter(false,
+                DOMElementWriter.XmlNamespacePolicy.ONLY_QUALIFY_ELEMENTS);
         w.write(root, sw, 0, "  ");
-        assertEquals("<root xmlns=\"urn:foo\">"
-                     + StringUtils.LINE_SEP
-                     + "  <child />"
-                     + StringUtils.LINE_SEP
-                     + "</root>"
-                     + StringUtils.LINE_SEP, sw.toString());
+        assertEquals(String.format("<root xmlns=\"urn:foo\">%n  <child />%n</root>%n"),
+                sw.toString());
     }
 
     @Test
@@ -279,24 +255,15 @@
         Element child3 = d.createElementNS("urn:foo2", "child");
         root.appendChild(child3);
         StringWriter sw = new StringWriter();
-        DOMElementWriter w =
-            new DOMElementWriter(false,
-                                 DOMElementWriter.XmlNamespacePolicy
-                                 .ONLY_QUALIFY_ELEMENTS);
+        DOMElementWriter w = new DOMElementWriter(false,
+                DOMElementWriter.XmlNamespacePolicy.ONLY_QUALIFY_ELEMENTS);
         w.write(root, sw, 0, "  ");
-        assertEquals("<root xmlns=\"urn:foo\">"
-                     + StringUtils.LINE_SEP
-                     + "  <ns0:child xmlns:ns0=\"urn:foo2\" />"
-                     + StringUtils.LINE_SEP
-                     + "  <ns1:child xmlns:ns1=\"urn:foo2\">"
-                     + StringUtils.LINE_SEP
-                     + "    <ns1:grandchild />"
-                     + StringUtils.LINE_SEP
-                     + "  </ns1:child>"
-                     + StringUtils.LINE_SEP
-                     + "  <ns2:child xmlns:ns2=\"urn:foo2\" />"
-                     + StringUtils.LINE_SEP
-                      + "</root>"
-                     + StringUtils.LINE_SEP, sw.toString());
+        assertEquals(String.format("<root xmlns=\"urn:foo\">%n"
+                + "  <ns0:child xmlns:ns0=\"urn:foo2\" />%n"
+                + "  <ns1:child xmlns:ns1=\"urn:foo2\">%n"
+                + "    <ns1:grandchild />%n"
+                + "  </ns1:child>%n"
+                + "  <ns2:child xmlns:ns2=\"urn:foo2\" />%n"
+                + "</root>%n"), sw.toString());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/DateUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/DateUtilsTest.java
index ca223d9..9c8e995 100644
--- a/src/tests/junit/org/apache/tools/ant/util/DateUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/DateUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -43,7 +43,9 @@
         assertEquals("2 minutes 1 second", text);
     }
 
-    // https://issues.apache.org/bugzilla/show_bug.cgi?id=44659
+    /**
+     * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=44659">bug 44659</a>
+     */
     @Test
     public void testLongElapsedTime() {
         assertEquals("2926 minutes 13 seconds",
diff --git a/src/tests/junit/org/apache/tools/ant/util/DeweyDecimalTest.java b/src/tests/junit/org/apache/tools/ant/util/DeweyDecimalTest.java
index e8e8cbd..9dc9613 100644
--- a/src/tests/junit/org/apache/tools/ant/util/DeweyDecimalTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/DeweyDecimalTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,14 @@
 
 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 org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
 public class DeweyDecimalTest {
 
     @Test
@@ -55,23 +57,76 @@
 
     @Test
     public void testEquals() {
-        assertTrue(new DeweyDecimal("1.2.3").equals(new DeweyDecimal("1.2.3")));
-        assertFalse(new DeweyDecimal("1.2.3").equals(new DeweyDecimal("1.2.4")));
-        assertTrue(new DeweyDecimal("1.2.0").equals(new DeweyDecimal("1.2")));
-        assertTrue(new DeweyDecimal("1.2").equals(new DeweyDecimal("1.2.0")));
+        assertEquals(new DeweyDecimal("1.2.3"), new DeweyDecimal("1.2.3"));
+        assertNotEquals(new DeweyDecimal("1.2.3"), new DeweyDecimal("1.2.4"));
+        assertEquals(new DeweyDecimal("1.2.0"), new DeweyDecimal("1.2"));
+        assertEquals(new DeweyDecimal("1.2"), new DeweyDecimal("1.2.0"));
     }
 
     @Test
     public void compareTo() {
         assertTrue(new DeweyDecimal("1.2.3").compareTo(new DeweyDecimal("1.2")) > 0);
         assertTrue(new DeweyDecimal("1.2").compareTo(new DeweyDecimal("1.2.3")) < 0);
-        assertTrue(new DeweyDecimal("1.2.3").compareTo(new DeweyDecimal("1.2.3")) == 0);
+        assertEquals(0, new DeweyDecimal("1.2.3").compareTo(new DeweyDecimal("1.2.3")));
         assertTrue(new DeweyDecimal("1.2.3").compareTo(new DeweyDecimal("1.1.4")) > 0);
         assertTrue(new DeweyDecimal("1.2.3").compareTo(new DeweyDecimal("1.2.2.9")) > 0);
-        assertTrue(new DeweyDecimal("1.2.0").compareTo(new DeweyDecimal("1.2")) == 0);
-        assertTrue(new DeweyDecimal("1.2").compareTo(new DeweyDecimal("1.2.0")) == 0);
+        assertEquals(0, new DeweyDecimal("1.2.0").compareTo(new DeweyDecimal("1.2")));
+        assertEquals(0, new DeweyDecimal("1.2").compareTo(new DeweyDecimal("1.2.0")));
     }
 
-    // TODO isGreaterThan, ...
+    @Test
+    public void intConstructor() {
+        int[] args = {1,2,3};
+        assertEquals("1.2.3", new DeweyDecimal(args).toString());
+    }
 
+    @Test
+    public void intConstructorNegativeValues() {
+        int[] args = {-1,-2,-3};
+        assertEquals("-1.-2.-3", new DeweyDecimal(args).toString());
+    }
+
+    @Test
+    public void details() {
+         DeweyDecimal dd = new DeweyDecimal("1.2.3");
+         assertEquals(3, dd.getSize());
+         assertEquals(2, dd.get(1));
+    }
+
+    @Test
+    public void isGreaterThanOrEqual() {
+         DeweyDecimal first = new DeweyDecimal("1.2.3");
+         assertTrue(first.isGreaterThanOrEqual(new DeweyDecimal("1")));
+         assertTrue(first.isGreaterThanOrEqual(new DeweyDecimal("1.2")));
+         assertTrue(first.isGreaterThanOrEqual(new DeweyDecimal("1.2.3")));
+         assertTrue(first.isGreaterThanOrEqual(new DeweyDecimal("1.2.3.0")));
+         assertFalse(first.isGreaterThanOrEqual(new DeweyDecimal("1.2.4")));
+         assertFalse(first.isGreaterThanOrEqual(new DeweyDecimal("1.3")));
+         assertFalse(first.isGreaterThanOrEqual(new DeweyDecimal("2")));
+    }
+
+    @Test
+    public void equals() {
+         DeweyDecimal dd = new DeweyDecimal("1.2.3");
+        assertNotEquals("other", dd);
+        assertNotNull(dd);
+        assertEquals(dd, new DeweyDecimal("1.2.3"));
+        assertEquals(dd, new DeweyDecimal("1.2.3.0"));
+    }
+
+    @Test
+    public void isLessThan() {
+         DeweyDecimal dd = new DeweyDecimal("1.2.3");
+         assertTrue(dd.isLessThan(new DeweyDecimal("2")));
+         assertFalse(dd.isLessThan(new DeweyDecimal("1")));
+         assertFalse(dd.isLessThan(new DeweyDecimal("1.2.3")));
+    }
+
+    @Test
+    public void isLessThanOrEqual() {
+         DeweyDecimal dd = new DeweyDecimal("1.2.3");
+         assertTrue(dd.isLessThanOrEqual(new DeweyDecimal("2")));
+         assertFalse(dd.isLessThanOrEqual(new DeweyDecimal("1")));
+         assertTrue(dd.isLessThanOrEqual(new DeweyDecimal("1.2.3")));
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java
index 9877e71..555916c 100644
--- a/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,18 +21,39 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.Set;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.MagicTestNames;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.condition.Os;
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
 
+import static org.apache.tools.ant.util.FileUtils.getFileUtils;
+import static org.apache.tools.ant.util.FileUtils.isCaseSensitiveFileSystem;
+import static org.apache.tools.ant.util.FileUtils.isContextRelativePath;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
@@ -42,8 +63,13 @@
  */
 public class FileUtilsTest {
 
-    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-    private File removeThis;
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private static final String ROOT = System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY);
     private String root;
 
     @Before
@@ -52,15 +78,6 @@
         root = new File(File.separator).getAbsolutePath().toUpperCase();
     }
 
-    @After
-    public void tearDown() {
-        if (removeThis != null && removeThis.exists()) {
-            if (!removeThis.delete()) {
-                removeThis.deleteOnExit();
-            }
-        }
-    }
-
     /**
      * test modification.
      * Since Ant1.7, the method being tested no longer uses
@@ -73,16 +90,16 @@
      */
     @Test
     public void testSetLastModified() throws IOException {
-        removeThis = new File("dummy");
-        FileOutputStream fos = new FileOutputStream(removeThis);
-        fos.write(new byte[0]);
-        fos.close();
-        assumeTrue("Could not change file modified time", removeThis.setLastModified(removeThis.lastModified() - 2000));
+        File removeThis = folder.newFile("dummy");
+        try (FileOutputStream fos = new FileOutputStream(removeThis)) {
+            fos.write(new byte[0]);
+        }
+        assumeTrue("Could not change file modified time",
+                removeThis.setLastModified(removeThis.lastModified() - 2000));
         long modTime = removeThis.lastModified();
-        assertTrue(modTime != 0);
+        assertNotEquals(0, modTime);
 
-
-        FILE_UTILS.setFileLastModified(removeThis, -1);
+        getFileUtils().setFileLastModified(removeThis, -1);
         long secondModTime = removeThis.lastModified();
         assertTrue(secondModTime > modTime);
 
@@ -91,7 +108,7 @@
         // in a previous version, the date of the file was set to 123456
         // milliseconds since 01.01.1970
         // it did not work on a computer running JDK 1.4.1_02 + Windows 2000
-        FILE_UTILS.setFileLastModified(removeThis, secondModTime + millisperday);
+        getFileUtils().setFileLastModified(removeThis, secondModTime + millisperday);
         long thirdModTime = removeThis.lastModified();
         /*
          * I would love to compare this with 123456, but depending on
@@ -99,226 +116,233 @@
          *
          * Just assert the time has changed.
          */
-        assertTrue(thirdModTime != secondModTime);
+        assertNotEquals(thirdModTime, secondModTime);
     }
 
     @Test
-    public void testResolveFile() {
-        if (!(Os.isFamily("dos") || Os.isFamily("netware"))) {
-            /*
-             * Start with simple absolute file names.
-             */
-            assertEquals(File.separator,
-                         FILE_UTILS.resolveFile(null, "/").getPath());
-            assertEquals(File.separator,
-                         FILE_UTILS.resolveFile(null, "\\").getPath());
-        } else {
-            assertEqualsIgnoreDriveCase(localize(File.separator),
-                FILE_UTILS.resolveFile(null, "/").getPath());
-            assertEqualsIgnoreDriveCase(localize(File.separator),
-                FILE_UTILS.resolveFile(null, "\\").getPath());
-            /*
-             * throw in drive letters
-             */
-            String driveSpec = "C:";
-            assertEquals(driveSpec + "\\",
-                         FILE_UTILS.resolveFile(null, driveSpec + "/").getPath());
-            assertEquals(driveSpec + "\\",
-                         FILE_UTILS.resolveFile(null, driveSpec + "\\").getPath());
-            String driveSpecLower = "c:";
-            assertEquals(driveSpecLower + "\\",
-                         FILE_UTILS.resolveFile(null, driveSpecLower + "/").getPath());
-            assertEquals(driveSpecLower + "\\",
-                         FILE_UTILS.resolveFile(null, driveSpecLower + "\\").getPath());
-            /*
-             * promised to eliminate consecutive slashes after drive letter.
-             */
-            assertEquals(driveSpec + "\\",
-                         FILE_UTILS.resolveFile(null, driveSpec + "/////").getPath());
-            assertEquals(driveSpec + "\\",
-                         FILE_UTILS.resolveFile(null, driveSpec + "\\\\\\\\\\\\").getPath());
-        }
+    public void testResolveFilePosix() {
+        assumeTrue("DOS or NetWare", !Os.isFamily("dos") && !Os.isFamily("netware"));
+        /*
+         * Start with simple absolute file names.
+         */
+        assertEquals(File.separator, getFileUtils().resolveFile(null, "/").getPath());
+        assertEquals(File.separator, getFileUtils().resolveFile(null, "\\").getPath());
+    }
+
+    @Test
+    public void testResolveFileDosOrNetware() {
+        assumeTrue("Not DOS or Netware", Os.isFamily("dos") || Os.isFamily("netware"));
+        assertEqualsIgnoreDriveCase(localize(File.separator),
+                getFileUtils().resolveFile(null, "/").getPath());
+        assertEqualsIgnoreDriveCase(localize(File.separator),
+                getFileUtils().resolveFile(null, "\\").getPath());
+        /*
+         * throw in drive letters
+         */
+        String driveSpec = "C:";
+        assertEquals(driveSpec + "\\",
+                getFileUtils().resolveFile(null, driveSpec + "/").getPath());
+        assertEquals(driveSpec + "\\",
+                getFileUtils().resolveFile(null, driveSpec + "\\").getPath());
+        String driveSpecLower = "c:";
+        assertEquals(driveSpecLower + "\\",
+                getFileUtils().resolveFile(null, driveSpecLower + "/").getPath());
+        assertEquals(driveSpecLower + "\\",
+                getFileUtils().resolveFile(null, driveSpecLower + "\\").getPath());
+        /*
+         * promised to eliminate consecutive slashes after drive letter.
+         */
+        assertEquals(driveSpec + "\\",
+                getFileUtils().resolveFile(null, driveSpec + "/////").getPath());
+        assertEquals(driveSpec + "\\",
+                getFileUtils().resolveFile(null, driveSpec + "\\\\\\\\\\\\").getPath());
+
         if (Os.isFamily("netware")) {
             /*
              * throw in NetWare volume names
              */
-            String driveSpec = "SYS:";
+            driveSpec = "SYS:";
             assertEquals(driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpec + "/").getPath());
+                    getFileUtils().resolveFile(null, driveSpec + "/").getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpec + "\\").getPath());
-            String driveSpecLower = "sys:";
+                    getFileUtils().resolveFile(null, driveSpec + "\\").getPath());
+            driveSpecLower = "sys:";
             assertEquals(driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpecLower + "/").getPath());
+                    getFileUtils().resolveFile(null, driveSpecLower + "/").getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpecLower + "\\").getPath());
+                    getFileUtils().resolveFile(null, driveSpecLower + "\\").getPath());
             /*
              * promised to eliminate consecutive slashes after drive letter.
              */
             assertEquals(driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpec + "/////").getPath());
+                    getFileUtils().resolveFile(null, driveSpec + "/////").getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpec + "\\\\\\\\\\\\").getPath());
-        } else if (!(Os.isFamily("dos"))) {
-            /*
-             * drive letters must be considered just normal filenames.
-             */
-            String driveSpec = "C:";
-            String udir = System.getProperty("user.dir");
-            assertEquals(udir + File.separator + driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpec + "/").getPath());
-            assertEquals(udir + File.separator + driveSpec,
-                         FILE_UTILS.resolveFile(null, driveSpec + "\\").getPath());
-            String driveSpecLower = "c:";
-            assertEquals(udir + File.separator + driveSpecLower,
-                         FILE_UTILS.resolveFile(null, driveSpecLower + "/").getPath());
-            assertEquals(udir + File.separator + driveSpecLower,
-                         FILE_UTILS.resolveFile(null, driveSpecLower + "\\").getPath());
+                    getFileUtils().resolveFile(null, driveSpec + "\\\\\\\\\\\\").getPath());
         }
-
+    }
+    @Test
+    public void testResolveFileNotDos() {
+        assumeFalse("is DOS", Os.isFamily("dos"));
         /*
-         * Now test some relative file name magic.
+         * drive letters must be considered just normal filenames.
          */
+        String driveSpec = "C:";
+        String udir = System.getProperty("user.dir");
+        assertEquals(udir + File.separator + driveSpec,
+                getFileUtils().resolveFile(null, driveSpec + "/").getPath());
+        assertEquals(udir + File.separator + driveSpec,
+                getFileUtils().resolveFile(null, driveSpec + "\\").getPath());
+        String driveSpecLower = "c:";
+        assertEquals(udir + File.separator + driveSpecLower,
+                getFileUtils().resolveFile(null, driveSpecLower + "/").getPath());
+        assertEquals(udir + File.separator + driveSpecLower,
+                getFileUtils().resolveFile(null, driveSpecLower + "\\").getPath());
+    }
+
+    /*
+     * Test some relative file name magic.
+     */
+    @Test
+    public void testResolveRelativeFile() {
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "./4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "./4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), ".\\4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), ".\\4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "./.\\4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "./.\\4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "../3/4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "../3/4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "..\\3\\4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "..\\3\\4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "../../5/.././2/./3/6/../4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "../../5/.././2/./3/6/../4").getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.resolveFile(new File(localize("/1/2/3")), "..\\../5/..\\./2/./3/6\\../4").getPath());
+                     getFileUtils().resolveFile(new File(localize("/1/2/3")), "..\\../5/..\\./2/./3/6\\../4").getPath());
 
         assertEquals("meaningless result but no exception",
                 new File(localize("/1/../../b")),
-                FILE_UTILS.resolveFile(new File(localize("/1")), "../../b"));
+                getFileUtils().resolveFile(new File(localize("/1")), "../../b"));
 
     }
 
     @Test
-    public void testNormalize() {
-        if (!(Os.isFamily("dos") || Os.isFamily("netware"))) {
-            /*
-             * Start with simple absolute file names.
-             */
-            assertEquals(File.separator,
-                         FILE_UTILS.normalize("/").getPath());
-            assertEquals(File.separator,
-                         FILE_UTILS.normalize("\\").getPath());
-        } else {
-            try {
-                 FILE_UTILS.normalize("/").getPath();
-                 fail("normalized \"/\" on dos or netware");
-            } catch (Exception e) {
-            }
-            try {
-                 FILE_UTILS.normalize("\\").getPath();
-                 fail("normalized \"\\\" on dos or netware");
-            } catch (Exception e) {
-            }
-        }
+    public void testNormalizePosix() {
+        assumeTrue("DOS or NetWare", !Os.isFamily("dos") && !Os.isFamily("netware"));
+        /*
+         * Start with simple absolute file names.
+         */
+        assertEquals(File.separator, getFileUtils().normalize("/").getPath());
+        assertEquals(File.separator, getFileUtils().normalize("\\").getPath());
 
+        // Expected exception caught
+        thrown.expect(BuildException.class);
+        String driveSpec = "C:";
+        assertEquals(driveSpec, getFileUtils().normalize(driveSpec).getPath());
+    }
+
+    @Test
+    public void testNormalizeSlashDosOrNetware() {
+        assumeTrue("Not DOS or Netware", Os.isFamily("dos") || Os.isFamily("netware"));
+        thrown.expect(BuildException.class);
+        getFileUtils().normalize("/").getPath();
+    }
+
+    @Test
+    public void testNormalizeBackSlashDosOrNetware() {
+        assumeTrue("Not DOS or Netware", Os.isFamily("dos") || Os.isFamily("netware"));
+        thrown.expect(BuildException.class);
+        getFileUtils().normalize("\\").getPath();
+    }
+
+    @Test
+    public void testNormalizeDosOrNetware() {
+        assumeTrue("Not DOS or Netware", Os.isFamily("dos") || Os.isFamily("netware"));
         if (Os.isFamily("dos")) {
             /*
              * throw in drive letters
              */
             String driveSpec = "C:";
-            try {
-                 FILE_UTILS.normalize(driveSpec).getPath();
-                 fail(driveSpec + " is not an absolute path");
-            } catch (Exception e) {
-            }
             assertEquals(driveSpec + "\\",
-                         FILE_UTILS.normalize(driveSpec + "/").getPath());
+                    getFileUtils().normalize(driveSpec + "/").getPath());
             assertEquals(driveSpec + "\\",
-                         FILE_UTILS.normalize(driveSpec + "\\").getPath());
+                    getFileUtils().normalize(driveSpec + "\\").getPath());
             String driveSpecLower = "c:";
             assertEquals(driveSpecLower + "\\",
-                         FILE_UTILS.normalize(driveSpecLower + "/").getPath());
+                    getFileUtils().normalize(driveSpecLower + "/").getPath());
             assertEquals(driveSpecLower + "\\",
-                         FILE_UTILS.normalize(driveSpecLower + "\\").getPath());
+                    getFileUtils().normalize(driveSpecLower + "\\").getPath());
             /*
              * promised to eliminate consecutive slashes after drive letter.
              */
             assertEquals(driveSpec + "\\",
-                         FILE_UTILS.normalize(driveSpec + "/////").getPath());
+                    getFileUtils().normalize(driveSpec + "/////").getPath());
             assertEquals(driveSpec + "\\",
-                         FILE_UTILS.normalize(driveSpec + "\\\\\\\\\\\\").getPath());
+                    getFileUtils().normalize(driveSpec + "\\\\\\\\\\\\").getPath());
+
+            // Expected exception caught
+            thrown.expect(BuildException.class);
+            getFileUtils().normalize(driveSpec).getPath();
         } else if (Os.isFamily("netware")) {
             /*
              * throw in NetWare volume names
              */
             String driveSpec = "SYS:";
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpec).getPath());
+                    getFileUtils().normalize(driveSpec).getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpec + "/").getPath());
+                    getFileUtils().normalize(driveSpec + "/").getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpec + "\\").getPath());
+                    getFileUtils().normalize(driveSpec + "\\").getPath());
             String driveSpecLower = "sys:";
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpecLower).getPath());
+                    getFileUtils().normalize(driveSpecLower).getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpecLower + "/").getPath());
+                    getFileUtils().normalize(driveSpecLower + "/").getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpecLower + "\\").getPath());
+                    getFileUtils().normalize(driveSpecLower + "\\").getPath());
             assertEquals(driveSpec + "\\junk",
-                         FILE_UTILS.normalize(driveSpecLower + "\\junk").getPath());
+                    getFileUtils().normalize(driveSpecLower + "\\junk").getPath());
             /*
              * promised to eliminate consecutive slashes after drive letter.
              */
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpec + "/////").getPath());
+                    getFileUtils().normalize(driveSpec + "/////").getPath());
             assertEquals(driveSpec,
-                         FILE_UTILS.normalize(driveSpec + "\\\\\\\\\\\\").getPath());
-        } else {
-            try {
-                String driveSpec = "C:";
-                assertEquals(driveSpec,
-                             FILE_UTILS.normalize(driveSpec).getPath());
-                fail("Expected failure, C: isn't an absolute path on other os's");
-            } catch (BuildException e) {
-                // Passed test
-            }
+                    getFileUtils().normalize(driveSpec + "\\\\\\\\\\\\").getPath());
         }
+    }
 
-        /*
-         * Now test some relative file name magic.
-         */
+    /**
+     * Test some relative file name magic.
+     */
+    @Test
+    public void testNormalizeRelativeFile() {
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/./4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/./4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/.\\4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/.\\4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/./.\\4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/./.\\4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/../3/4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/../3/4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/..\\3\\4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/..\\3\\4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/../../5/.././2/./3/6/../4")).getPath());
+                     getFileUtils().normalize(localize("/1/2/3/../../5/.././2/./3/6/../4")).getPath());
         assertEquals(localize("/1/2/3/4"),
-                     FILE_UTILS.normalize(localize("/1/2/3/..\\../5/..\\./2/./3/6\\../4")).getPath());
-
-        try {
-            FILE_UTILS.normalize("foo");
-            fail("foo is not an absolute path");
-        } catch (BuildException e) {
-            // Expected exception caught
-        }
+                     getFileUtils().normalize(localize("/1/2/3/..\\../5/..\\./2/./3/6\\../4")).getPath());
 
         assertEquals("will not go outside FS root (but will not throw an exception either)",
                 new File(localize("/1/../../b")),
-                FILE_UTILS.normalize(localize("/1/../../b")));
+                getFileUtils().normalize(localize("/1/../../b")));
+
+        // Expected exception caught
+        thrown.expect(BuildException.class);
+        getFileUtils().normalize("foo");
     }
 
     /**
@@ -326,43 +350,45 @@
      */
     @Test
     public void testNullArgs() {
-        try {
-            FILE_UTILS.normalize(null);
-            fail("successfully normalized a null-file");
-        } catch (NullPointerException npe) {
-            // Expected exception caught
-        }
-
-        File f = FILE_UTILS.resolveFile(null, "a");
+        File f = getFileUtils().resolveFile(null, "a");
         assertEquals(f, new File("a").getAbsoluteFile());
-    }
 
+        // Expected exception caught
+        thrown.expect(NullPointerException.class);
+        getFileUtils().normalize(null);
+    }
 
     /**
      * Test createTempFile
      */
     @Test
-    public void testCreateTempFile() {
+    public void testCreateTempFile() throws IOException {
         final String tmploc = System.getProperty("java.io.tmpdir");
         final Project projectWithoutTempDir = new Project();
         final Project projectWithTempDir = new Project();
-        final File projectTmpDir = new File(tmploc, "subdir");
-        projectTmpDir.mkdir();
-        removeThis = projectTmpDir;
+        final File projectTmpDir = folder.newFolder("subdir");
         projectWithTempDir.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath());
 
         // null parent dir, null project
-        File tmp1 = FILE_UTILS.createTempFile(null, "pre", ".suf", null, false, true);
+        File tmp1 = getFileUtils().createTempFile(null, "pre", ".suf", null, false, true);
         String name = tmp1.getName();
-        assertTrue("starts with pre", name.startsWith("pre"));
-        assertTrue("ends with .suf", name.endsWith(".suf"));
+        assertThat("starts with pre", name, startsWith("pre"));
+        assertThat("ends with .suf", name, endsWith(".suf"));
         assertTrue("File was created", tmp1.exists());
-        assertEquals((new File(tmploc, tmp1.getName())).getAbsolutePath(), tmp1
-                .getAbsolutePath());
+        assertEquals((new File(tmploc, tmp1.getName())).getAbsolutePath(),
+                tmp1.getAbsolutePath());
+        final PosixFileAttributeView attributes =
+            Files.getFileAttributeView(tmp1.toPath(), PosixFileAttributeView.class);
+        if (attributes != null) {
+            final Set<PosixFilePermission> perm = attributes.readAttributes().permissions();
+            assertThat(perm,
+                containsInAnyOrder(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE));
+            assertThat(perm, hasSize(2));
+        }
         tmp1.delete();
 
         // null parent dir, project without magic property
-        tmp1 = FILE_UTILS.createTempFile(projectWithoutTempDir, "pre", ".suf", null, false, true);
+        tmp1 = getFileUtils().createTempFile(projectWithoutTempDir, "pre", ".suf", null, false, true);
         name = tmp1.getName();
         assertTrue("starts with pre", name.startsWith("pre"));
         assertTrue("ends with .suf", name.endsWith(".suf"));
@@ -372,7 +398,7 @@
         tmp1.delete();
 
         // null parent dir, project with magic property
-        tmp1 = FILE_UTILS.createTempFile(projectWithTempDir, "pre", ".suf", null, false, true);
+        tmp1 = getFileUtils().createTempFile(projectWithTempDir, "pre", ".suf", null, false, true);
         name = tmp1.getName();
         assertTrue("starts with pre", name.startsWith("pre"));
         assertTrue("ends with .suf", name.endsWith(".suf"));
@@ -381,19 +407,18 @@
                 .getAbsolutePath());
         tmp1.delete();
 
-        File dir2 = new File(tmploc + "/ant-test");
-        dir2.mkdir();
+        File dir2 = folder.newFolder("ant-test");
 
-        File tmp2 = FILE_UTILS.createTempFile(null, "pre", ".suf", dir2, true, true);
+        File tmp2 = getFileUtils().createTempFile(null, "pre", ".suf", dir2, true, true);
         String name2 = tmp2.getName();
-        assertTrue("starts with pre", name2.startsWith("pre"));
-        assertTrue("ends with .suf", name2.endsWith(".suf"));
+        assertThat("starts with pre", name2, startsWith("pre"));
+        assertThat("ends with .suf", name2, endsWith(".suf"));
         assertTrue("File was created", tmp2.exists());
-        assertEquals((new File(dir2, tmp2.getName())).getAbsolutePath(), tmp2
-                .getAbsolutePath());
+        assertEquals((new File(dir2, tmp2.getName())).getAbsolutePath(),
+                tmp2.getAbsolutePath());
         tmp2.delete();
 
-        tmp2 = FILE_UTILS.createTempFile(projectWithoutTempDir, "pre", ".suf", dir2, true, true);
+        tmp2 = getFileUtils().createTempFile(projectWithoutTempDir, "pre", ".suf", dir2, true, true);
         name2 = tmp2.getName();
         assertTrue("starts with pre", name2.startsWith("pre"));
         assertTrue("ends with .suf", name2.endsWith(".suf"));
@@ -402,7 +427,7 @@
                 .getAbsolutePath());
         tmp2.delete();
 
-        tmp2 = FILE_UTILS.createTempFile(projectWithTempDir, "pre", ".suf", dir2, true, true);
+        tmp2 = getFileUtils().createTempFile(projectWithTempDir, "pre", ".suf", dir2, true, true);
         name2 = tmp2.getName();
         assertTrue("starts with pre", name2.startsWith("pre"));
         assertTrue("ends with .suf", name2.endsWith(".suf"));
@@ -413,18 +438,79 @@
         dir2.delete();
 
         File parent = new File((new File("/tmp")).getAbsolutePath());
-        tmp1 = FILE_UTILS.createTempFile("pre", ".suf", parent, false);
-        assertTrue("new file", !tmp1.exists());
+        tmp1 = getFileUtils().createTempFile("pre", ".suf", parent, false);
+        assertFalse("new file", tmp1.exists());
 
         name = tmp1.getName();
-        assertTrue("starts with pre", name.startsWith("pre"));
-        assertTrue("ends with .suf", name.endsWith(".suf"));
+        assertThat("starts with pre", name, startsWith("pre"));
+        assertThat("ends with .suf", name, endsWith(".suf"));
         assertEquals("is inside parent dir", parent.getAbsolutePath(), tmp1
                 .getParent());
 
-        tmp2 = FILE_UTILS.createTempFile("pre", ".suf", parent, false);
-        assertTrue("files are different", !tmp1.getAbsolutePath().equals(
-                tmp2.getAbsolutePath()));
+        tmp2 = getFileUtils().createTempFile("pre", ".suf", parent, false);
+        assertNotEquals("files are different", tmp1.getAbsolutePath(), tmp2.getAbsolutePath());
+    }
+
+    @Test
+    public void createTempFileUsesAntTmpDirIfSetAndDeleteOnExitIsTrue() throws IOException {
+        final Project project = new Project();
+        final File projectTmpDir = folder.newFolder("subdir");
+        project.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath());
+        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
+        assertTrue(tmpFile + " must be child of " + projectTmpDir,
+                   tmpFile.getAbsolutePath().startsWith(projectTmpDir.getAbsolutePath()));
+    }
+
+    @Test
+    public void createTempFileUsesAntTmpDirIfSetAndDeleteOnExitIsFalse() throws IOException {
+        final Project project = new Project();
+        final File projectTmpDir = folder.newFolder("subdir");
+        project.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath());
+        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, false, true);
+        assertTrue(tmpFile + " must be child of " + projectTmpDir,
+                   tmpFile.getAbsolutePath().startsWith(projectTmpDir.getAbsolutePath()));
+    }
+
+    @Test
+    public void createTempFileCreatesAutoTmpDirIfDeleteOnExitIsTrueOnUnix() throws IOException {
+        assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
+        final Project project = new Project();
+        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
+        final String autoTempDir = project.getProperty("ant.auto.tmpdir");
+        assertNotNull(autoTempDir);
+        assertTrue(tmpFile + " must be child of " + autoTempDir,
+                   tmpFile.getAbsolutePath().startsWith(autoTempDir));
+    }
+
+    @Test
+    public void createTempFileDoesntCreateAutoTmpDirIfDeleteOnExitIsFalse() throws IOException {
+        final Project project = new Project();
+        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, false, true);
+        assertNull(project.getProperty("ant.auto.tmpdir"));
+    }
+
+    @Test
+    public void createTempFileReusesAutoTmpDirIfDeleteOnExitIsTrueOnUnix() throws IOException {
+        assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
+        final Project project = new Project();
+        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
+        final String autoTempDir = project.getProperty("ant.auto.tmpdir");
+        assertNotNull(autoTempDir);
+        final File tmpFile2 = getFileUtils().createTempFile(project, null, null, null, true, true);
+        assertTrue(tmpFile2 + " must be child of " + autoTempDir,
+                   tmpFile2.getAbsolutePath().startsWith(autoTempDir));
+    }
+
+    @Test
+    public void createTempFileDoesntReusesAutoTmpDirIfDeleteOnExitIsFalse() throws IOException {
+        assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
+        final Project project = new Project();
+        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
+        final String autoTempDir = project.getProperty("ant.auto.tmpdir");
+        assertNotNull(autoTempDir);
+        final File tmpFile2 = getFileUtils().createTempFile(project, null, null, null, false, true);
+        assertFalse(tmpFile2 + " must not be child of " + autoTempDir,
+                    tmpFile2.getAbsolutePath().startsWith(autoTempDir));
     }
 
     /**
@@ -432,18 +518,21 @@
      */
     @Test
     public void testContentEquals() throws IOException {
-        assertTrue("Non existing files", FILE_UTILS.contentEquals(new File(System.getProperty("root"), "foo"),
-                                                          new File(System.getProperty("root"), "bar")));
-        assertTrue("One exists, the other one doesn\'t",
-                   !FILE_UTILS.contentEquals(new File(System.getProperty("root"), "foo"), new File(System.getProperty("root"), "build.xml")));
-        assertTrue("Don\'t compare directories",
-                   !FILE_UTILS.contentEquals(new File(System.getProperty("root"), "src"), new File(System.getProperty("root"), "src")));
+        assertTrue("Non existing files",
+                getFileUtils().contentEquals(new File(ROOT, "foo"),
+                        new File(ROOT, "bar")));
+        assertFalse("One exists, the other one doesn't",
+                getFileUtils().contentEquals(new File(ROOT, "foo"),
+                        new File(ROOT, "build.xml")));
+        assertFalse("Don't compare directories",
+                getFileUtils().contentEquals(new File(ROOT, "src"),
+                        new File(ROOT, "src")));
         assertTrue("File equals itself",
-                   FILE_UTILS.contentEquals(new File(System.getProperty("root"), "build.xml"),
-                                    new File(System.getProperty("root"), "build.xml")));
-        assertTrue("Files are different",
-                   !FILE_UTILS.contentEquals(new File(System.getProperty("root"), "build.xml"),
-                                     new File(System.getProperty("root"), "docs.xml")));
+                getFileUtils().contentEquals(new File(ROOT, "build.xml"),
+                        new File(ROOT, "build.xml")));
+        assertFalse("Files are different",
+                getFileUtils().contentEquals(new File(ROOT, "build.xml"),
+                        new File(ROOT, "docs.xml")));
     }
 
     /**
@@ -451,9 +540,10 @@
      */
     @Test
     public void testCreateNewFile() throws IOException {
-        removeThis = new File("dummy");
-        assertTrue(!removeThis.exists());
-        FILE_UTILS.createNewFile(removeThis);
+        File removeThis = new File("dummy");
+        removeThis.deleteOnExit();
+        assertFalse(removeThis.exists());
+        getFileUtils().createNewFile(removeThis);
         assertTrue(removeThis.exists());
     }
 
@@ -462,45 +552,45 @@
      */
     @Test
     public void testRemoveLeadingPath() {
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("/foo"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("/foo"),
                                                  new File("/foo/bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("/foo/"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("/foo/"),
                                                  new File("/foo/bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("\\foo"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("\\foo"),
                                                  new File("\\foo\\bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("\\foo\\"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("\\foo\\"),
                                                  new File("\\foo\\bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("c:/foo"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("c:/foo"),
                                                  new File("c:/foo/bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("c:/foo/"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("c:/foo/"),
                                                  new File("c:/foo/bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("c:\\foo"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("c:\\foo"),
                                                  new File("c:\\foo\\bar")));
-        assertEquals("bar", FILE_UTILS.removeLeadingPath(new File("c:\\foo\\"),
+        assertEquals("bar", getFileUtils().removeLeadingPath(new File("c:\\foo\\"),
                                                  new File("c:\\foo\\bar")));
-        if (!(Os.isFamily("dos") || Os.isFamily("netware"))) {
-            assertEquals(FILE_UTILS.normalize("/bar").getAbsolutePath(),
-                         FILE_UTILS.removeLeadingPath(new File("/foo"), new File("/bar")));
-            assertEquals(FILE_UTILS.normalize("/foobar").getAbsolutePath(),
-                         FILE_UTILS.removeLeadingPath(new File("/foo"), new File("/foobar")));
+        if (!Os.isFamily("dos") && !Os.isFamily("netware")) {
+            assertEquals(getFileUtils().normalize("/bar").getAbsolutePath(),
+                         getFileUtils().removeLeadingPath(new File("/foo"), new File("/bar")));
+            assertEquals(getFileUtils().normalize("/foobar").getAbsolutePath(),
+                         getFileUtils().removeLeadingPath(new File("/foo"), new File("/foobar")));
         }
         // bugzilla report 19979
-        assertEquals("", FILE_UTILS.removeLeadingPath(new File("/foo/bar"),
+        assertEquals("", getFileUtils().removeLeadingPath(new File("/foo/bar"),
                                               new File("/foo/bar")));
-        assertEquals("", FILE_UTILS.removeLeadingPath(new File("/foo/bar"),
+        assertEquals("", getFileUtils().removeLeadingPath(new File("/foo/bar"),
                                               new File("/foo/bar/")));
-        assertEquals("", FILE_UTILS.removeLeadingPath(new File("/foo/bar/"),
+        assertEquals("", getFileUtils().removeLeadingPath(new File("/foo/bar/"),
                                               new File("/foo/bar/")));
-        assertEquals("", FILE_UTILS.removeLeadingPath(new File("/foo/bar/"),
+        assertEquals("", getFileUtils().removeLeadingPath(new File("/foo/bar/"),
                                               new File("/foo/bar")));
 
         String expected = "foo/bar".replace('\\', File.separatorChar)
             .replace('/', File.separatorChar);
-        assertEquals(expected, FILE_UTILS.removeLeadingPath(new File("/"),
+        assertEquals(expected, getFileUtils().removeLeadingPath(new File("/"),
                                                     new File("/foo/bar")));
-        assertEquals(expected, FILE_UTILS.removeLeadingPath(new File("c:/"),
+        assertEquals(expected, getFileUtils().removeLeadingPath(new File("c:/"),
                                                     new File("c:/foo/bar")));
-        assertEquals(expected, FILE_UTILS.removeLeadingPath(new File("c:\\"),
+        assertEquals(expected, getFileUtils().removeLeadingPath(new File("c:\\"),
                                                     new File("c:\\foo\\bar")));
     }
 
@@ -517,28 +607,28 @@
             dosRoot = "";
         }
         if (Os.isFamily("dos")) {
-            assertEquals("file:/c:/foo", removeExtraneousAuthority(FILE_UTILS.toURI("c:\\foo")));
+            assertEquals("file:/c:/foo", removeExtraneousAuthority(getFileUtils().toURI("c:\\foo")));
         }
         if (Os.isFamily("netware")) {
-            assertEquals("file:/SYS:/foo", removeExtraneousAuthority(FILE_UTILS.toURI("sys:\\foo")));
+            assertEquals("file:/SYS:/foo", removeExtraneousAuthority(getFileUtils().toURI("sys:\\foo")));
         }
         if (File.pathSeparatorChar == '/') {
-            assertEquals("file:/foo", removeExtraneousAuthority(FILE_UTILS.toURI("/foo")));
-            assertTrue("file: URIs must name absolute paths", FILE_UTILS.toURI("./foo").startsWith("file:/"));
-            assertTrue(FILE_UTILS.toURI("./foo").endsWith("/foo"));
-            assertEquals("file:/" + dosRoot + "foo%20bar", removeExtraneousAuthority(FILE_UTILS.toURI("/foo bar")));
-            assertEquals("file:/" + dosRoot + "foo%23bar", removeExtraneousAuthority(FILE_UTILS.toURI("/foo#bar")));
+            assertEquals("file:/foo", removeExtraneousAuthority(getFileUtils().toURI("/foo")));
+            assertThat("file: URIs must name absolute paths", getFileUtils().toURI("./foo"), startsWith("file:/"));
+            assertThat(getFileUtils().toURI("./foo"), endsWith("/foo"));
+            assertEquals("file:/" + dosRoot + "foo%20bar", removeExtraneousAuthority(getFileUtils().toURI("/foo bar")));
+            assertEquals("file:/" + dosRoot + "foo%23bar", removeExtraneousAuthority(getFileUtils().toURI("/foo#bar")));
         } else if (File.pathSeparatorChar == '\\') {
-            assertEquals("file:/" + dosRoot + "foo", removeExtraneousAuthority(FILE_UTILS.toURI("\\foo")));
-            assertTrue("file: URIs must name absolute paths", FILE_UTILS.toURI(".\\foo").startsWith("file:/"));
-            assertTrue(FILE_UTILS.toURI(".\\foo").endsWith("/foo"));
-            assertEquals("file:/" + dosRoot + "foo%20bar", removeExtraneousAuthority(FILE_UTILS.toURI("\\foo bar")));
-            assertEquals("file:/" + dosRoot + "foo%23bar", removeExtraneousAuthority(FILE_UTILS.toURI("\\foo#bar")));
+            assertEquals("file:/" + dosRoot + "foo", removeExtraneousAuthority(getFileUtils().toURI("\\foo")));
+            assertThat("file: URIs must name absolute paths", getFileUtils().toURI(".\\foo"), startsWith("file:/"));
+            assertThat(getFileUtils().toURI(".\\foo"), endsWith("/foo"));
+            assertEquals("file:/" + dosRoot + "foo%20bar", removeExtraneousAuthority(getFileUtils().toURI("\\foo bar")));
+            assertEquals("file:/" + dosRoot + "foo%23bar", removeExtraneousAuthority(getFileUtils().toURI("\\foo#bar")));
         }
         // a test with ant for germans
         // the escaped character used for the test is the "a umlaut"
         // this is the fix for the bug 37348
-        assertEquals("file:/" + dosRoot + "%C3%A4nt", removeExtraneousAuthority(FILE_UTILS.toURI("/\u00E4nt")));
+        assertEquals("file:/" + dosRoot + "%C3%A4nt", removeExtraneousAuthority(getFileUtils().toURI("/\u00E4nt")));
     }
 
     /**
@@ -557,8 +647,8 @@
     @Test
     public void testIsContextRelativePath() {
         assumeTrue("Test only runs on DOS", Os.isFamily("dos"));
-        assertTrue(FileUtils.isContextRelativePath("/\u00E4nt"));
-        assertTrue(FileUtils.isContextRelativePath("\\foo"));
+        assertTrue(isContextRelativePath("/\u00E4nt"));
+        assertTrue(isContextRelativePath("\\foo"));
     }
 
     /**
@@ -573,16 +663,16 @@
             dosRoot = "";
         }
         if (Os.isFamily("netware")) {
-            assertEqualsIgnoreDriveCase("SYS:\\foo", FILE_UTILS.fromURI("file:///sys:/foo"));
+            assertEqualsIgnoreDriveCase("SYS:\\foo", getFileUtils().fromURI("file:///sys:/foo"));
         }
         if (Os.isFamily("dos")) {
-            assertEqualsIgnoreDriveCase("C:\\foo", FILE_UTILS.fromURI("file:///c:/foo"));
+            assertEqualsIgnoreDriveCase("C:\\foo", getFileUtils().fromURI("file:///c:/foo"));
         }
-        assertEqualsIgnoreDriveCase(dosRoot + File.separator + "foo", FILE_UTILS.fromURI("file:///foo"));
+        assertEqualsIgnoreDriveCase(dosRoot + File.separator + "foo", getFileUtils().fromURI("file:///foo"));
         assertEquals("." + File.separator + "foo",
-                     FILE_UTILS.fromURI("file:./foo"));
-        assertEquals(dosRoot + File.separator + "foo bar", FILE_UTILS.fromURI("file:///foo%20bar"));
-        assertEquals(dosRoot + File.separator + "foo#bar", FILE_UTILS.fromURI("file:///foo%23bar"));
+                     getFileUtils().fromURI("file:./foo"));
+        assertEquals(dosRoot + File.separator + "foo bar", getFileUtils().fromURI("file:///foo%20bar"));
+        assertEquals(dosRoot + File.separator + "foo#bar", getFileUtils().fromURI("file:///foo%23bar"));
     }
 
     @Test
@@ -599,30 +689,30 @@
 
         //check that older is up to date with a newer dest
         assertTrue("older source files are up to date",
-                FILE_UTILS.isUpToDate(firstTime,secondTime));
+                getFileUtils().isUpToDate(firstTime,secondTime));
         //check that older is up to date with a newer dest
         assertFalse("newer source files are no up to date",
-                FILE_UTILS.isUpToDate(secondTime, firstTime));
+                getFileUtils().isUpToDate(secondTime, firstTime));
 
-        assertTrue("-1 dest timestamp implies nonexistence",
-                !FILE_UTILS.isUpToDate(firstTime,-1L));
+        assertFalse("-1 dest timestamp implies nonexistence",
+                getFileUtils().isUpToDate(firstTime, -1L));
     }
 
     @Test
     public void testHasErrorInCase() {
         File tempFolder = new File(System.getProperty("java.io.tmpdir"));
-        File wellcased = FILE_UTILS.createTempFile("alpha", "beta", tempFolder,
+        File wellcased = getFileUtils().createTempFile("alpha", "beta", tempFolder,
                                                    true, true);
         String s = wellcased.getName().toUpperCase();
         File wrongcased = new File(tempFolder, s);
         if (Os.isFamily("mac") && Os.isFamily("unix")) {
             //no guarantees on filesystem case-sensitivity
         } else if (Os.isFamily("dos")) {
-            assertTrue(FILE_UTILS.hasErrorInCase(wrongcased));
-            assertFalse(FILE_UTILS.hasErrorInCase(wellcased));
+            assertTrue(getFileUtils().hasErrorInCase(wrongcased));
+            assertFalse(getFileUtils().hasErrorInCase(wellcased));
         } else {
-            assertFalse(FILE_UTILS.hasErrorInCase(wrongcased));
-            assertFalse(FILE_UTILS.hasErrorInCase(wellcased));
+            assertFalse(getFileUtils().hasErrorInCase(wrongcased));
+            assertFalse(getFileUtils().hasErrorInCase(wellcased));
         }
 
     }
@@ -630,7 +720,7 @@
     @Test
     public void testGetDefaultEncoding() {
         // This just tests that the function does not blow up
-        FILE_UTILS.getDefaultEncoding();
+        getFileUtils().getDefaultEncoding();
     }
 
     /**
@@ -638,9 +728,9 @@
      */
     @Test
     public void isLeadingPathCannotBeFooledByTooManyDoubleDots() {
-        assertFalse(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/../../bar")));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\..\\..\\bar")));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/../..")));
+        assertFalse(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/../../bar")));
+        assertFalse(getFileUtils().isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\..\\..\\bar")));
+        assertFalse(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/../..")));
     }
 
     /**
@@ -648,61 +738,93 @@
      */
     @Test
     public void isLeadingPathCanonicalVersionCannotBeFooledByTooManyDoubleDots() throws IOException {
-        assertFalse(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/../../bar"), true));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\..\\..\\bar"), true));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/../.."), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/../../bar"), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\..\\..\\bar"), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/../.."), true));
     }
 
     @Test
     public void isLeadingPathCanonicalVersionWorksAsExpectedOnUnix() throws IOException {
         assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/bar"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/baz/../bar"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/../foo/bar"), true));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foobar"), true));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/baz/../bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/../foo/bar"), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("/foo"), new File("/foobar"), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("/foo"), new File("/bar"), true));
     }
 
     @Test
     public void isLeadingPathAndTrailingSlashesOnUnix() throws IOException {
         assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo/bar"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo/bar/"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo/"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo/bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo/bar/"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo/"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/"), true));
 
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo/bar"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo/bar/"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo/"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo/"), new File("/foo"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("/foo"), new File("/foo/"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo/bar"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo/bar/"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo/"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo/"), new File("/foo"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("/foo"), new File("/foo/"), false));
     }
 
     @Test
     public void isLeadingPathCanonicalVersionWorksAsExpectedOnDos() throws IOException {
         assumeTrue("Test only runs on DOS", Os.isFamily("dos"));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("C:\\foo"), new File("C:\\foo\\bar"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("C:\\foo"), new File("C:\\foo\\baz\\..\\bar"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("C:\\foo"), new File("C:\\foo\\..\\foo\\bar"), true));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("C:\\foo"), new File("C:\\foobar"), true));
-        assertFalse(FILE_UTILS.isLeadingPath(new File("C:\\foo"), new File("C:\\bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("C:\\foo"), new File("C:\\foo\\bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("C:\\foo"), new File("C:\\foo\\baz\\..\\bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("C:\\foo"), new File("C:\\foo\\..\\foo\\bar"), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("C:\\foo"), new File("C:\\foobar"), true));
+        assertFalse(getFileUtils().isLeadingPath(new File("C:\\foo"), new File("C:\\bar"), true));
     }
 
     @Test
     public void isLeadingPathAndTrailingSlashesOnDos() throws IOException {
         assumeTrue("Test only runs on DOS", Os.isFamily("dos"));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar\\"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo"), true));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar\\"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo"), true));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\"), true));
 
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar\\"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo"), false));
-        assertTrue(FILE_UTILS.isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\bar\\"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo\\"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo\\"), new File("c:\\foo"), false));
+        assertTrue(getFileUtils().isLeadingPath(new File("c:\\foo"), new File("c:\\foo\\"), false));
+    }
+
+    /**
+     * Tests {@link FileUtils#isCaseSensitiveFileSystem(Path)} method
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testCaseSensitiveFileSystem() throws Exception {
+        // create a temp file in a fresh directory
+        final Path tmpDir = Files.createTempDirectory(null);
+        final Path tmpFile = Files.createTempFile(tmpDir, null, null);
+        tmpFile.toFile().deleteOnExit();
+        tmpDir.toFile().deleteOnExit();
+        // now check if a file with that same name but different case is considered to exist
+        final boolean existsAsLowerCase = Files.exists(Paths.get(tmpDir.toString(), tmpFile.getFileName().toString().toLowerCase(Locale.US)));
+        final boolean existsAsUpperCase = Files.exists(Paths.get(tmpDir.toString(), tmpFile.getFileName().toString().toUpperCase(Locale.US)));
+        // if the temp file that we created is found to not exist in a particular "case", then
+        // the filesystem is case sensitive
+        final Boolean expectedCaseSensitivity = !existsAsLowerCase || !existsAsUpperCase;
+
+        // call the method and pass it a directory
+        Optional<Boolean> actualCaseSensitivity = isCaseSensitiveFileSystem(tmpDir);
+        assertTrue("Filesystem case sensitivity was expected to be determined", actualCaseSensitivity.isPresent());
+        assertEquals("Filesystem was expected to be case " + (expectedCaseSensitivity
+                ? "sensitive" : "insensitive"), expectedCaseSensitivity, actualCaseSensitivity.get());
+
+        // now test it out by passing it a file
+        actualCaseSensitivity = isCaseSensitiveFileSystem(tmpFile);
+        assertTrue("Filesystem case sensitivity was expected to be determined", actualCaseSensitivity.isPresent());
+        assertEquals("Filesystem was expected to be case " + (expectedCaseSensitivity
+                ? "sensitive" : "insensitive"), expectedCaseSensitivity, actualCaseSensitivity.get());
     }
 
     /**
@@ -720,8 +842,8 @@
      * calling this method allows tests where normalize is called to pass under cygwin
      */
     private void assertEqualsIgnoreDriveCase(String s1, String s2) {
-        if ((Os.isFamily("dos") || Os.isFamily("netware"))
-            && s1.length() > 0 && s2.length() > 0) {
+        assumeTrue("Not DOS or Netware", Os.isFamily("dos") || Os.isFamily("netware"));
+        if (!s1.isEmpty() && !s2.isEmpty()) {
             StringBuilder sb1 = new StringBuilder(s1);
             StringBuilder sb2 = new StringBuilder(s2);
             sb1.setCharAt(0, Character.toUpperCase(s1.charAt(0)));
diff --git a/src/tests/junit/org/apache/tools/ant/util/GlobPatternMapperTest.java b/src/tests/junit/org/apache/tools/ant/util/GlobPatternMapperTest.java
index 5bd7db6..eb9dc3a 100644
--- a/src/tests/junit/org/apache/tools/ant/util/GlobPatternMapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/GlobPatternMapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,7 @@
 
 package org.apache.tools.ant.util;
 
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -25,17 +26,23 @@
 import static org.junit.Assert.assertNull;
 
 /**
- * Tests for org.apache.tools.ant.util;GlobPatternMapper.
+ * Tests for org.apache.tools.ant.util.GlobPatternMapper.
  *
  */
 public class GlobPatternMapperTest {
 
+    private GlobPatternMapper m;
+
+    @Before
+    public void setUp() {
+        m = new GlobPatternMapper();
+    }
+
     @Test
     public void testNoPatternAtAll() {
-        GlobPatternMapper m = new GlobPatternMapper();
         m.setFrom("foobar");
         m.setTo("baz");
-        assertNull("Shouldn\'t match foobar", m.mapFileName("plonk"));
+        assertNull("Shouldn't match foobar", m.mapFileName("plonk"));
         String[] result = m.mapFileName("foobar");
         assertNotNull("Should match foobar", result);
         assertEquals("only one result for foobar", 1, result.length);
@@ -44,10 +51,9 @@
 
     @Test
     public void testPostfixOnly() {
-        GlobPatternMapper m = new GlobPatternMapper();
         m.setFrom("*foo");
         m.setTo("*plonk");
-        assertNull("Shouldn\'t match *foo", m.mapFileName("bar.baz"));
+        assertNull("Shouldn't match *foo", m.mapFileName("bar.baz"));
         String[] result = m.mapFileName("bar.foo");
         assertNotNull("Should match *.foo", result);
         assertEquals("only one result for bar.foo", 1, result.length);
@@ -61,10 +67,9 @@
 
     @Test
     public void testPrefixOnly() {
-        GlobPatternMapper m = new GlobPatternMapper();
         m.setFrom("foo*");
         m.setTo("plonk*");
-        assertNull("Shouldn\'t match foo*", m.mapFileName("bar.baz"));
+        assertNull("Shouldn't match foo*", m.mapFileName("bar.baz"));
         String[] result = m.mapFileName("foo.bar");
         assertNotNull("Should match foo*", result);
         assertEquals("only one result for foo.bar", 1, result.length);
@@ -78,10 +83,9 @@
 
     @Test
     public void testPreAndPostfix() {
-        GlobPatternMapper m = new GlobPatternMapper();
         m.setFrom("foo*bar");
         m.setTo("plonk*pling");
-        assertNull("Shouldn\'t match foo*bar", m.mapFileName("bar.baz"));
+        assertNull("Shouldn't match foo*bar", m.mapFileName("bar.baz"));
         String[] result = m.mapFileName("foo.bar");
         assertNotNull("Should match foo*bar", result);
         assertEquals("only one result for foo.bar", 1, result.length);
diff --git a/src/tests/junit/org/apache/tools/ant/util/JAXPUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/JAXPUtilsTest.java
index 7950771..840546b 100644
--- a/src/tests/junit/org/apache/tools/ant/util/JAXPUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/JAXPUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,7 +21,9 @@
 
 import java.io.File;
 
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
 
 /**
  * JAXPUtils test case
@@ -37,7 +39,7 @@
             file = new File("/user/local/bin");
         }
         String systemid = JAXPUtils.getSystemId(file);
-        assertTrue("SystemIDs should start by file:/", systemid.startsWith("file:/"));
-        assertTrue("SystemIDs should not start with file:////", !systemid.startsWith("file:////"));
+        assertThat("SystemIDs should start by file:/", systemid, startsWith("file:/"));
+        assertThat("SystemIDs should not start with file:////", systemid, not(startsWith("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 aa71b0b..65631d5 100644
--- a/src/tests/junit/org/apache/tools/ant/util/JavaEnvUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/JavaEnvUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -20,11 +20,15 @@
 import java.io.File;
 
 import org.apache.tools.ant.taskdefs.condition.Os;
-import org.junit.Assume;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
 /**
@@ -37,7 +41,7 @@
 
     @Test
     public void testGetExecutableNetware() {
-        Assume.assumeTrue("Test only runs on netware", Os.isName("netware"));
+        assumeTrue("Test only runs on netware", Os.isName("netware"));
         assertEquals("java", JavaEnvUtils.getJreExecutable("java"));
         assertEquals("javac", JavaEnvUtils.getJdkExecutable("javac"));
         assertEquals("foo", JavaEnvUtils.getJreExecutable("foo"));
@@ -46,31 +50,31 @@
 
     @Test
     public void testGetExecutableWindows() {
-        Assume.assumeTrue("Test only runs on windows", Os.isFamily("windows"));
-        String javaHome = FILE_UTILS.normalize(System.getProperty("java.home"))
+        assumeTrue("Test only runs on windows", Os.isFamily("windows"));
+        String javaHome = FILE_UTILS.normalize(JavaEnvUtils.getJavaHome())
             .getAbsolutePath();
 
         String j = JavaEnvUtils.getJreExecutable("java");
-        assertTrue(j.endsWith(".exe"));
+        assertThat(j, endsWith(".exe"));
         assertTrue(j + " is absolute", (new File(j)).isAbsolute());
         try {
-            assertTrue(j + " is normalized and in the JRE dir", j.startsWith(javaHome));
+            assertThat(j + " is normalized and in the JRE dir", j, startsWith(javaHome));
         } catch (AssertionError e) {
             // java.home is bogus
             assertEquals("java.exe", j);
         }
 
         j = JavaEnvUtils.getJdkExecutable("javac");
-        assertTrue(j.endsWith(".exe"));
+        assertThat(j, endsWith(".exe"));
 
         try {
             assertTrue(j + " is absolute", (new File(j)).isAbsolute());
             String javaHomeParent = FILE_UTILS.normalize(javaHome + "/..").getAbsolutePath();
-            assertTrue(j + " is normalized and in the JDK dir", j.startsWith(javaHomeParent));
+            assertThat(j + " is normalized and in the JDK dir", j, startsWith(javaHomeParent));
             if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
-                assertTrue(j + " is normalized and not in the JRE dir", j.startsWith(javaHome));
+                assertThat(j + " is normalized and not in the JRE dir", j, startsWith(javaHome));
             } else {
-                assertTrue(j + " is normalized and not in the JRE dir", !j.startsWith(javaHome));
+                assertThat(j + " is normalized and not in the JRE dir", j, not(startsWith(javaHome)));
             }
         } catch (AssertionError e) {
             // java.home is bogus
@@ -83,34 +87,33 @@
 
     @Test
     public void testGetExecutableMostPlatforms() {
-        Assume.assumeTrue("Test only runs on non Netware and non Windows systems",
-                !Os.isName("netware") && !Os.isFamily("windows"));
-        String javaHome = FILE_UTILS.normalize(System.getProperty("java.home")).getAbsolutePath();
+        assumeFalse("Test only runs on non Netware and non Windows systems",
+                Os.isName("netware") || Os.isFamily("windows"));
+        String javaHome = FILE_UTILS.normalize(JavaEnvUtils.getJavaHome()).getAbsolutePath();
 
         // could still be OS/2
         String extension = Os.isFamily("dos") ? ".exe" : "";
 
         String j = JavaEnvUtils.getJreExecutable("java");
-        if (!extension.equals("")) {
-            assertTrue(j.endsWith(extension));
+        if (!extension.isEmpty()) {
+            assertThat(j, endsWith(extension));
         }
         assertTrue(j + " is absolute", (new File(j)).isAbsolute());
-        assertTrue(j + " is normalized and in the JRE dir", j.startsWith(javaHome));
+        assertThat(j + " is normalized and in the JRE dir", j, startsWith(javaHome));
 
         j = JavaEnvUtils.getJdkExecutable("javac");
-        if (!extension.equals("")) {
-            assertTrue(j.endsWith(extension));
+        if (!extension.isEmpty()) {
+            assertThat(j, endsWith(extension));
         }
         assertTrue(j + " is absolute", (new File(j)).isAbsolute());
 
         String javaHomeParent = FILE_UTILS.normalize(javaHome + "/..").getAbsolutePath();
-        assertTrue(j + " is normalized and in the JDK dir", j.startsWith(javaHomeParent));
+        assertThat(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", j.startsWith(javaHome));
+        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
+            assertThat(j + " is normalized and in the JRE dir", j, startsWith(javaHome));
         } else {
-            assertTrue(j + " is normalized and not in the JRE dir", !j.startsWith(javaHome));
+            assertThat(j + " is normalized and not in the JRE dir", j, not(startsWith(javaHome)));
         }
 
         assertEquals("foo" + extension, JavaEnvUtils.getJreExecutable("foo"));
@@ -124,6 +127,7 @@
     }
 
     @Test
+    @SuppressWarnings("deprecation")
     public void isJavaVersionSupportsBothVersionsOfJava9() {
         assumeTrue(JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_9));
         assertTrue("JAVA_1_9 is not considered equal to JAVA_9",
@@ -131,6 +135,7 @@
     }
 
     @Test
+    @SuppressWarnings("deprecation")
     public void java10IsDetectedProperly() {
         assumeTrue("10".equals(System.getProperty("java.specification.version")));
         assertEquals("10", JavaEnvUtils.getJavaVersion());
@@ -139,4 +144,28 @@
         assertTrue(JavaEnvUtils.isJavaVersion("10"));
         assertTrue(JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
     }
+    
+    @Test
+    @SuppressWarnings("deprecation")
+    public void java11IsDetectedProperly() {
+        assumeTrue("11".equals(System.getProperty("java.specification.version")));
+        assertEquals("11", JavaEnvUtils.getJavaVersion());
+        assertEquals(110, JavaEnvUtils.getJavaVersionNumber());
+        assertEquals(new DeweyDecimal("11"), JavaEnvUtils.getParsedJavaVersion());
+        assertTrue(JavaEnvUtils.isJavaVersion("11"));
+        assertTrue(JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+    }
+    
+    @Test
+    @SuppressWarnings("deprecation")
+    public void java12IsDetectedProperly() {
+        assumeTrue("12".equals(System.getProperty("java.specification.version")));
+        assertEquals("12", JavaEnvUtils.getJavaVersion());
+        assertEquals(120, JavaEnvUtils.getJavaVersionNumber());
+        assertEquals(new DeweyDecimal("12"), JavaEnvUtils.getParsedJavaVersion());
+        assertTrue(JavaEnvUtils.isJavaVersion("12"));
+        assertTrue(JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9));
+    }
+
+
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/LayoutPreservingPropertiesTest.java b/src/tests/junit/org/apache/tools/ant/util/LayoutPreservingPropertiesTest.java
index 1e0bdfb..9fe1492 100644
--- a/src/tests/junit/org/apache/tools/ant/util/LayoutPreservingPropertiesTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/LayoutPreservingPropertiesTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -24,13 +24,35 @@
 import java.io.InputStreamReader;
 import java.util.Properties;
 
+import org.apache.tools.ant.MagicTestNames;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
+import static org.apache.tools.ant.util.FileUtils.readFully;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
 
 public class LayoutPreservingPropertiesTest {
 
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private static final String ROOT = System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY);
+
+    private LayoutPreservingProperties lpf;
+
+    private File tmp;
+
+    @Before
+    public void setUp() throws IOException {
+        lpf = new LayoutPreservingProperties();
+        tmp = folder.newFile("tmp.properties");
+    }
     /**
      * Tests that a properties file read by the
      * LayoutPreservingPropertiesFile and then saves the properties in
@@ -38,14 +60,10 @@
      */
     @Test
     public void testPreserve() throws Exception {
-        File simple = new File(System.getProperty("root"),
-                               "src/etc/testcases/util/simple.properties");
+        File simple = new File(ROOT, "src/etc/testcases/util/simple.properties");
         FileInputStream fis = new FileInputStream(simple);
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
         lpf.load(fis);
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // now compare original and tmp for property equivalence
@@ -59,8 +77,8 @@
 
         // and now make sure that the comments made it into the new file
         String s = readFile(tmp);
-        assertTrue("missing comment", s.contains("# a comment"));
-        assertTrue("missing comment", s.contains("! more comment"));
+        assertThat("missing comment", s, containsString(("# a comment")));
+        assertThat("missing comment", s, containsString(("! more comment")));
     }
 
     /**
@@ -69,8 +87,6 @@
      */
     @Test
     public void testEscaping() throws Exception {
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
-
         lpf.setProperty(" prop one ", "  leading and trailing spaces ");
         lpf.setProperty("prop\ttwo", "contains\ttab");
         lpf.setProperty("prop\nthree", "contains\nnewline");
@@ -82,22 +98,20 @@
         lpf.setProperty("prop#nine", "contains#hash");
         lpf.setProperty("prop!ten", "contains!exclamation");
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // and check that the resulting file looks okay
         String s = readFile(tmp);
 
-        assertTrue(s.contains("\\ prop\\ one\\ =\\ \\ leading and trailing spaces "));
-        assertTrue(s.contains("prop\\ttwo=contains\\ttab"));
-        assertTrue(s.contains("prop\\nthree=contains\\nnewline"));
-        assertTrue(s.contains("prop\\rfour=contains\\rcarriage return"));
-        assertTrue(s.contains("prop\\\\six=contains\\\\backslash"));
-        assertTrue(s.contains("prop\\:seven=contains\\:colon"));
-        assertTrue(s.contains("prop\\=eight=contains\\=equals"));
-        assertTrue(s.contains("prop\\#nine=contains\\#hash"));
-        assertTrue(s.contains("prop\\!ten=contains\\!exclamation"));
+        assertThat(s, containsString("\\ prop\\ one\\ =\\ \\ leading and trailing spaces "));
+        assertThat(s, containsString("prop\\ttwo=contains\\ttab"));
+        assertThat(s, containsString("prop\\nthree=contains\\nnewline"));
+        assertThat(s, containsString("prop\\rfour=contains\\rcarriage return"));
+        assertThat(s, containsString("prop\\\\six=contains\\\\backslash"));
+        assertThat(s, containsString("prop\\:seven=contains\\:colon"));
+        assertThat(s, containsString("prop\\=eight=contains\\=equals"));
+        assertThat(s, containsString("prop\\#nine=contains\\#hash"));
+        assertThat(s, containsString("prop\\!ten=contains\\!exclamation"));
     }
 
     /**
@@ -107,163 +121,132 @@
      */
     @Test
     public void testOverwrite() throws Exception {
-        File unusual = new File(System.getProperty("root"),
-                                "src/etc/testcases/util/unusual.properties");
+        File unusual = new File(ROOT, "src/etc/testcases/util/unusual.properties");
         FileInputStream fis = new FileInputStream(unusual);
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
         lpf.load(fis);
 
         lpf.setProperty(" prop one ", "new one");
         lpf.setProperty("prop\ttwo", "new two");
         lpf.setProperty("prop\nthree", "new three");
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // and check that the resulting file looks okay
         String s = readFile(tmp);
 
-        assertTrue(!s.contains("\\ prop\\ one\\ =\\ \\ leading and trailing spaces "));
-        assertTrue(s.contains("\\ prop\\ one\\ =new one"));
-        assertTrue(!s.contains("prop\\ttwo=contains\\ttab"));
-        assertTrue(s.contains("prop\\ttwo=new two"));
-        assertTrue(!s.contains("prop\\nthree=contains\\nnewline"));
-        assertTrue(s.contains("prop\\nthree=new three"));
+        assertThat(s, not(containsString("\\ prop\\ one\\ =\\ \\ leading and trailing spaces ")));
+        assertThat(s, containsString("\\ prop\\ one\\ =new one"));
+        assertThat(s, not(containsString("prop\\ttwo=contains\\ttab")));
+        assertThat(s, containsString("prop\\ttwo=new two"));
+        assertThat(s, not(containsString("prop\\nthree=contains\\nnewline")));
+        assertThat(s, containsString("prop\\nthree=new three"));
     }
 
     @Test
     public void testStoreWithHeader() throws Exception {
-        File simple = new File(System.getProperty("root"),
-                               "src/etc/testcases/util/simple.properties");
+        File simple = new File(ROOT, "src/etc/testcases/util/simple.properties");
         FileInputStream fis = new FileInputStream(simple);
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
         lpf.load(fis);
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
-        FileOutputStream fos = new FileOutputStream(tmp);
-        lpf.store(fos, "file-header");
-        fos.close();
+        try (FileOutputStream fos = new FileOutputStream(tmp)) {
+            lpf.store(fos, "file-header");
+        }
 
         // and check that the resulting file looks okay
-        String s = readFile(tmp);
-
-        assertTrue("should have had header ", s.startsWith("#file-header"));
+        assertThat("should have had header ", readFile(tmp), startsWith("#file-header"));
     }
 
     @Test
     public void testClear() throws Exception {
-        File simple = new File(System.getProperty("root"),
-                               "src/etc/testcases/util/simple.properties");
+        File simple = new File(ROOT, "src/etc/testcases/util/simple.properties");
         FileInputStream fis = new FileInputStream(simple);
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
         lpf.load(fis);
 
         lpf.clear();
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // and check that the resulting file looks okay
         String s = readFile(tmp);
 
-        assertTrue("should have had no properties ", !s.contains("prop.alpha"));
-        assertTrue("should have had no properties ", !s.contains("prop.beta"));
-        assertTrue("should have had no properties ", !s.contains("prop.gamma"));
+        assertThat("should have had no properties ", s, not(containsString(("prop.alpha"))));
+        assertThat("should have had no properties ", s, not(containsString(("prop.beta"))));
+        assertThat("should have had no properties ", s, not(containsString(("prop.gamma"))));
 
-        assertTrue("should have had no comments", !s.contains("# a comment"));
-        assertTrue("should have had no comments", !s.contains("! more comment"));
-        assertTrue("should have had no comments", !s.contains("# now a line wrapping one"));
+        assertThat("should have had no comments", s, not(containsString(("# a comment"))));
+        assertThat("should have had no comments", s, not(containsString(("! more comment"))));
+        assertThat("should have had no comments", s, not(containsString(("# now a line wrapping one"))));
     }
 
     @Test
     public void testRemove() throws Exception {
-        File simple = new File(System.getProperty("root"),
-                               "src/etc/testcases/util/simple.properties");
+        File simple = new File(ROOT, "src/etc/testcases/util/simple.properties");
         FileInputStream fis = new FileInputStream(simple);
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
         lpf.load(fis);
 
         lpf.remove("prop.beta");
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // and check that the resulting file looks okay
         String s = readFile(tmp);
 
-        assertTrue("should not have had prop.beta", !s.contains("prop.beta"));
-        assertTrue("should have had prop.beta's comment", s.contains("! more comment"));
+        assertThat("should not have had prop.beta", s, not(containsString(("prop.beta"))));
+        assertThat("should have had prop.beta's comment", s, containsString("! more comment"));
     }
 
     @Test
     public void testRemoveWithComment() throws Exception {
-        File simple = new File(System.getProperty("root"),
-                               "src/etc/testcases/util/simple.properties");
+        File simple = new File(ROOT, "src/etc/testcases/util/simple.properties");
         FileInputStream fis = new FileInputStream(simple);
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
         lpf.load(fis);
 
         lpf.setRemoveComments(true);
 
         lpf.remove("prop.beta");
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // and check that the resulting file looks okay
         String s = readFile(tmp);
 
-        assertTrue("should not have had prop.beta", !s.contains("prop.beta"));
-        assertTrue("should not have had prop.beta's comment", !s.contains("! more comment"));
+        assertThat("should not have had prop.beta", s, not(containsString(("prop.beta"))));
+        assertThat("should not have had prop.beta's comment", s, not(containsString(("! more comment"))));
     }
 
     @Test
     public void testClone() throws Exception {
-        File simple = new File(System.getProperty("root"),
-                               "src/etc/testcases/util/simple.properties");
+        File simple = new File(ROOT, "src/etc/testcases/util/simple.properties");
         FileInputStream fis = new FileInputStream(simple);
-        LayoutPreservingProperties lpf1 = new LayoutPreservingProperties();
-        lpf1.load(fis);
+        lpf.load(fis);
 
-        LayoutPreservingProperties lpf2 =
-            (LayoutPreservingProperties) lpf1.clone();
+        LayoutPreservingProperties lpfClone = (LayoutPreservingProperties) lpf.clone();
 
-        lpf2.setProperty("prop.new", "a new property");
-        lpf2.setProperty("prop.beta", "a new value for beta");
+        lpfClone.setProperty("prop.new", "a new property");
+        lpfClone.setProperty("prop.beta", "a new value for beta");
 
-        assertEquals("size of original is wrong", 3, lpf1.size());
-        assertEquals("size of clone is wrong", 4, lpf2.size());
+        assertEquals("size of original is wrong", 3, lpf.size());
+        assertEquals("size of clone is wrong", 4, lpfClone.size());
 
-        File tmp1 = File.createTempFile("tmp", "props");
-        tmp1.deleteOnExit();
-        lpf1.saveAs(tmp1);
-        String s1 = readFile(tmp1);
+        lpf.saveAs(tmp);
+        String s1 = readFile(tmp);
 
-        File tmp2 = File.createTempFile("tmp", "props");
-        tmp2.deleteOnExit();
-        lpf2.saveAs(tmp2);
-        String s2 = readFile(tmp2);
+        File tmpClone = folder.newFile("tmp-clone.properties");
+        lpfClone.saveAs(tmpClone);
+        String s2 = readFile(tmpClone);
 
         // check original is untouched
-        assertTrue("should have had 'simple'", s1.contains("simple"));
-        assertTrue("should not have had prop.new", !s1.contains("prop.new"));
+        assertThat("should have had 'simple'", s1, containsString(("simple")));
+        assertThat("should not have had prop.new", s1, not(containsString(("prop.new"))));
 
         // check clone has the changes
-        assertTrue("should have had 'a new value for beta'",
-                s2.contains("a new value for beta"));
-        assertTrue("should have had prop.new", s2.contains("prop.new"));
+        assertThat("should have had 'a new value for beta'", s2, containsString(("a new value for beta")));
+        assertThat("should have had prop.new", s2, containsString(("prop.new")));
     }
 
     @Test
     public void testPreserveEscapeName() throws Exception {
-        LayoutPreservingProperties lpf = new LayoutPreservingProperties();
-        File unusual = new File(System.getProperty("root"),
-                                "src/etc/testcases/util/unusual.properties");
+        File unusual = new File(ROOT, "src/etc/testcases/util/unusual.properties");
         FileInputStream fis = new FileInputStream(unusual);
         lpf.load(fis);
 
@@ -274,31 +257,26 @@
         lpf.setProperty("alpha", "new value for alpha");
         lpf.setProperty("beta", "new value for beta");
 
-        File tmp = File.createTempFile("tmp", "props");
-        tmp.deleteOnExit();
         lpf.saveAs(tmp);
 
         // and check that the resulting file looks okay
         String s = readFile(tmp);
 
-        assertTrue(s.contains("prop\\:seven=new value for seven"));
-        assertTrue(s.contains("prop\\=eight=new value for eight"));
-        assertTrue(s.contains("prop\\ eleven=new value for eleven"));
-        assertTrue(s.contains("alpha=new value for alpha"));
-        assertTrue(s.contains("beta=new value for beta"));
+        assertThat(s, containsString("prop\\:seven=new value for seven"));
+        assertThat(s, containsString("prop\\=eight=new value for eight"));
+        assertThat(s, containsString("prop\\ eleven=new value for eleven"));
+        assertThat(s, containsString("alpha=new value for alpha"));
+        assertThat(s, containsString("beta=new value for beta"));
 
-        assertTrue(!s.contains("prop\\:seven=contains\\:colon"));
-        assertTrue(!s.contains("prop\\=eight=contains\\=equals"));
-        assertTrue(!s.contains("alpha:set with a colon"));
-        assertTrue(!s.contains("beta set with a space"));
+        assertThat(s, not(containsString("prop\\:seven=contains\\:colon")));
+        assertThat(s, not(containsString("prop\\=eight=contains\\=equals")));
+        assertThat(s, not(containsString("alpha:set with a colon")));
+        assertThat(s, not(containsString("beta set with a space")));
     }
 
     private static String readFile(File f) throws IOException {
-        FileInputStream fis = new FileInputStream(f);
-        InputStreamReader isr = new InputStreamReader(fis);
-        String s = FileUtils.readFully(isr);
-        isr.close();
-        fis.close();
-        return s;
+        try (InputStreamReader isr = new InputStreamReader(new FileInputStream(f))) {
+            return readFully(isr);
+        }
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/LazyFileOutputStreamTest.java b/src/tests/junit/org/apache/tools/ant/util/LazyFileOutputStreamTest.java
index 82c3634..28b0a68 100644
--- a/src/tests/junit/org/apache/tools/ant/util/LazyFileOutputStreamTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/LazyFileOutputStreamTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,6 +23,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -30,7 +31,7 @@
  */
 public class LazyFileOutputStreamTest {
     private LazyFileOutputStream los;
-    private final static File f = new File("test.txt");
+    private static final File f = new File("test.txt");
 
     @Before
     public void setUp() {
@@ -49,7 +50,7 @@
     @Test
     public void testNoFileWithoutWrite() throws IOException {
         los.close();
-        assertTrue(f + " has not been written.", !f.exists());
+        assertFalse(f + " has not been written.", f.exists());
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/ant/util/LineOrientedOutputStreamTest.java b/src/tests/junit/org/apache/tools/ant/util/LineOrientedOutputStreamTest.java
index 68a8164..6ebb951 100644
--- a/src/tests/junit/org/apache/tools/ant/util/LineOrientedOutputStreamTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/LineOrientedOutputStreamTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -147,7 +147,7 @@
         }
 
         private void assertNotInvoked() {
-            assertTrue("No output", !invoked);
+            assertFalse("No output", invoked);
         }
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/LinkedHashtableTest.java b/src/tests/junit/org/apache/tools/ant/util/LinkedHashtableTest.java
index bfd2cda..c350e1e 100644
--- a/src/tests/junit/org/apache/tools/ant/util/LinkedHashtableTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/LinkedHashtableTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,17 +18,23 @@
 
 package org.apache.tools.ant.util;
 
+import java.util.Collections;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Map;
 
 import org.junit.Test;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNull;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.hasValue;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 public class LinkedHashtableTest {
 
@@ -36,28 +42,31 @@
     private static final Object K2 = new Object();
     private static final Object V1 = new Object();
     private static final Object V2 = new Object();
-    private Hashtable h = new LinkedHashtable();
+    private Hashtable<Object, Object> h = new LinkedHashtable<>();
 
+    @Test
     public void testClear() {
         h.put(K1, V1);
         h.clear();
         assertTrue(h.isEmpty());
     }
 
+    @SuppressWarnings("unchecked")
+    @Test
     public void testClone() {
         h.put(K1, V1);
-        Hashtable h2 = (Hashtable) h.clone();
-        assertTrue(h2 instanceof LinkedHashtable);
-        assertTrue(h2.containsKey(K1));
+        Hashtable<Object, Object> h2 = (Hashtable<Object, Object>) h.clone();
+        assertThat(h2, instanceOf(LinkedHashtable.class));
+        assertThat(h2, hasKey(K1));
     }
 
     @Test
     public void testContainsAndPut() {
         h.put(K1, V1);
         assertTrue(h.contains(K1));
-        assertTrue(h.containsKey(K1));
-        assertTrue(h.containsValue(V1));
-        assertFalse(h.containsKey(K2));
+        assertThat(h, hasKey(K1));
+        assertThat(h, hasValue(V1));
+        assertThat(h, not(hasKey(K2)));
     }
 
     @Test
@@ -82,10 +91,10 @@
 
     @Test
     public void testPutAll() {
-        LinkedHashtable h2 = new LinkedHashtable();
+        LinkedHashtable<Object, Object> h2 = new LinkedHashtable<>();
         h.put(K1, V1);
         h2.putAll(h);
-        assertTrue(h2.containsKey(K1));
+        assertThat(h2, hasKey(K1));
     }
 
     @Test
@@ -106,7 +115,7 @@
     @Test
     public void testKeys() {
         multiSetup();
-        assertKeys(CollectionUtils.asIterator(h.keys()));
+        assertKeys(Collections.list(h.keys()).iterator());
     }
 
     @Test
@@ -118,7 +127,7 @@
     @Test
     public void testElements() {
         multiSetup();
-        assertValues(CollectionUtils.asIterator(h.elements()));
+        assertValues(Collections.list(h.elements()).iterator());
     }
 
     @Test
@@ -130,13 +139,13 @@
     @Test
     public void testEntrySet() {
         multiSetup();
-        Iterator i = h.entrySet().iterator();
+        Iterator<Map.Entry<Object, Object>> i = h.entrySet().iterator();
         assertTrue(i.hasNext());
-        Map.Entry e = (Map.Entry) i.next();
+        Map.Entry<Object, Object> e = i.next();
         assertSame(K1, e.getKey());
         assertSame(V1, e.getValue());
         assertTrue(i.hasNext());
-        e = (Map.Entry) i.next();
+        e = i.next();
         assertSame(K2, e.getKey());
         assertSame(V2, e.getValue());
         assertFalse(i.hasNext());
@@ -147,7 +156,7 @@
         h.put(K2, V2);
     }
 
-    private static void assertKeys(Iterator i) {
+    private static void assertKeys(Iterator<Object> i) {
         assertTrue(i.hasNext());
         assertSame(K1, i.next());
         assertTrue(i.hasNext());
@@ -155,7 +164,7 @@
         assertFalse(i.hasNext());
     }
 
-    private static void assertValues(Iterator i) {
+    private static void assertValues(Iterator<Object> i) {
         assertTrue(i.hasNext());
         assertSame(V1, i.next());
         assertTrue(i.hasNext());
diff --git a/src/tests/junit/org/apache/tools/ant/util/LoaderUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/LoaderUtilsTest.java
index 9935edd..196dd11 100644
--- a/src/tests/junit/org/apache/tools/ant/util/LoaderUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/LoaderUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java
index f3b54e6..081e915 100644
--- a/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/util/PackageNameMapperTest.java b/src/tests/junit/org/apache/tools/ant/util/PackageNameMapperTest.java
index fdf7393..24e7e19 100644
--- a/src/tests/junit/org/apache/tools/ant/util/PackageNameMapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/PackageNameMapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -31,10 +31,9 @@
         mapper.setFrom("*.java");
         mapper.setTo("TEST-*.xml");
         String file = fixupPath("org/apache/tools/ant/util/PackageNameMapperTest.java");
-        String result = mapper.mapFileName(file)[0];
 
         assertEquals("TEST-org.apache.tools.ant.util.PackageNameMapperTest.xml",
-          result);
+                mapper.mapFileName(file)[0]);
     }
 
     private String fixupPath(String file) {
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..2cfa6ba
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java
@@ -0,0 +1,150 @@
+/*
+ *  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
+ *
+ *      https://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.Assume.assumeNotNull;
+
+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.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class PermissionUtilsTest {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    @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 {
+        assertEquals(PermissionUtils.FileType.REGULAR_FILE,
+                     PermissionUtils.FileType.of(folder.newFile("ant.tst").toPath()));
+    }
+
+    @Test
+    public void detectsFileTypeOfRegularFileFromResource() throws IOException {
+        assertEquals(PermissionUtils.FileType.REGULAR_FILE,
+                     PermissionUtils.FileType.of(new FileResource(folder.newFile("ant.tst"))));
+    }
+
+    @Test
+    public void detectsFileTypeOfDirectoryFromPath() throws IOException {
+        assertEquals(PermissionUtils.FileType.DIR,
+                     PermissionUtils.FileType.of(folder.newFolder("ant.tst").toPath()));
+    }
+
+    @Test
+    public void detectsFileTypeOfDirectoryFromResource() throws IOException {
+        assertEquals(PermissionUtils.FileType.DIR,
+                     PermissionUtils.FileType.of(new FileResource(folder.newFolder("ant.tst"))));
+    }
+
+    @Test
+    public void getSetPermissionsWorksForFiles() throws IOException {
+        File f = folder.newFile("ant.tst");
+        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 = folder.newFile("ant.zip");
+        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 = folder.newFile("ant.tar");
+        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/ReaderInputStreamTest.java b/src/tests/junit/org/apache/tools/ant/util/ReaderInputStreamTest.java
index 1951a8a..09e80eb 100644
--- a/src/tests/junit/org/apache/tools/ant/util/ReaderInputStreamTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/ReaderInputStreamTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,22 +17,30 @@
  */
 package org.apache.tools.ant.util;
 
+import org.apache.tools.ant.MagicTestNames;
 import org.junit.Test;
 
 import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Test for ReaderInputStream
  */
 public class ReaderInputStreamTest {
 
+    private static final String ROOT = System.getProperty(MagicTestNames.TEST_ROOT_DIRECTORY);
+
     @Test
     public void testSimple() throws Exception {
         compareBytes("abc", "utf-8");
@@ -59,9 +67,9 @@
             }
             bytes[pos++] = (byte) res;
         }
-        bytes = "abc".getBytes("utf-16");
+        bytes = "abc".getBytes(StandardCharsets.UTF_16);
         //        String n = new String(bytes, 0, pos, "utf-16");
-        new String(bytes, 0, bytes.length, "utf-16");
+        new String(bytes, 0, bytes.length, StandardCharsets.UTF_16);
     }
 
     @SuppressWarnings("resource")
@@ -79,69 +87,171 @@
     }
 
     @Test
-    public void testPreample() throws Exception {
-        byte[] bytes = "".getBytes("utf-16");
+    public void testPreample() {
+        byte[] bytes = "".getBytes(StandardCharsets.UTF_16);
         System.out.println("Preample len is " + bytes.length);
     }
 
     @Test
     public void testIso88591ToUtf8() throws Exception {
-        InputStreamReader fin = null;
-        ReaderInputStream r = null;
-        FileInputStream utf8 = null;
-        try {
-            fin = new InputStreamReader(new FileInputStream(new File(System.getProperty("root"),
-                    "src/tests/antunit/taskdefs/exec/input/iso8859-1")),
-                                        "ISO8859_1");
-            r = new ReaderInputStream(fin, "UTF8");
-
-            ByteArrayOutputStream actualOS = new ByteArrayOutputStream();
+        ByteArrayOutputStream actualOS = new ByteArrayOutputStream();
+        try (ReaderInputStream r = new ReaderInputStream(new InputStreamReader(new FileInputStream(new File(ROOT,
+                "src/tests/antunit/taskdefs/exec/input/iso8859-1")), StandardCharsets.ISO_8859_1),
+                StandardCharsets.UTF_8)) {
             int b = r.read();
             while (b > -1) {
                 actualOS.write((byte) b);
                 b = r.read();
             }
+        }
 
-            utf8 = new FileInputStream(new File(System.getProperty("root"),
-                    "src/tests/antunit/taskdefs/exec/expected/utf-8"));
-            ByteArrayOutputStream expectedOS = new ByteArrayOutputStream();
-            b = utf8.read();
+        ByteArrayOutputStream expectedOS = new ByteArrayOutputStream();
+        try (FileInputStream utf8 = new FileInputStream(new File(ROOT,
+                "src/tests/antunit/taskdefs/exec/expected/utf-8"))) {
+            int b = utf8.read();
             while (b > -1) {
                 expectedOS.write((byte) b);
                 b = utf8.read();
             }
+        }
 
-            byte[] expected = expectedOS.toByteArray();
-            byte[] actual = actualOS.toByteArray();
-            assertEquals("length", expected.length, actual.length);
-            for (int i = 0; i < actual.length; i++) {
-                assertEquals("byte " + i, expected[i], actual[i]);
-            }
-        } finally {
-            FileUtils.close(fin);
-            FileUtils.close(r);
-            FileUtils.close(utf8);
+        byte[] expected = expectedOS.toByteArray();
+        byte[] actual = actualOS.toByteArray();
+        assertEquals("length", expected.length, actual.length);
+        for (int i = 0; i < actual.length; i++) {
+            assertEquals("byte " + i, expected[i], actual[i]);
         }
     }
 
     @SuppressWarnings("resource")
     private void compareBytes(String s, String encoding) throws Exception {
         byte[] expected = s.getBytes(encoding);
-
-        ReaderInputStream r = new ReaderInputStream(
-            new StringReader(s), encoding);
+        ReaderInputStream r = new ReaderInputStream(new StringReader(s), encoding);
         for (int i = 0; i < expected.length; ++i) {
             int expect = expected[i] & 0xFF;
             int read = r.read();
-            if (expect != read) {
-                fail("Mismatch in ReaderInputStream at index " + i
-                     + " expecting " + expect + " got " + read + " for string "
-                     + s + " with encoding " + encoding);
+            assertEquals("Mismatch in ReaderInputStream at index " + i
+                    + " expecting " + expect + " got " + read + " for string "
+                    + s + " with encoding " + encoding, expect, read);
+        }
+        assertEquals("Mismatch in ReaderInputStream - EOF not seen for string "
+                + s + " with encoding " + encoding, -1, r.read());
+    }
+
+    private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre";
+    private static final String LARGE_TEST_STRING;
+
+    static {
+        final StringBuilder buffer = new StringBuilder();
+        for (int i=0; i<100; i++) {
+            buffer.append(TEST_STRING);
+        }
+        LARGE_TEST_STRING = buffer.toString();
+    }
+
+    private final Random random = new Random();
+
+    private void testWithSingleByteRead(final String testString, final String charsetName) throws IOException {
+        final byte[] bytes = testString.getBytes(charsetName);
+        final ReaderInputStream in = new ReaderInputStream(new StringReader(testString), charsetName);
+        for (final byte b : bytes) {
+            final int read = in.read();
+            assertTrue(read >= 0);
+            assertTrue(read <= 255);
+            assertEquals(b, (byte)read);
+        }
+        assertEquals(-1, in.read());
+        in.close();
+    }
+
+    private void testWithBufferedRead(final String testString, final String charsetName) throws IOException {
+        final byte[] expected = testString.getBytes(charsetName);
+        final ReaderInputStream in = new ReaderInputStream(new StringReader(testString), charsetName);
+        final byte[] buffer = new byte[128];
+        int offset = 0;
+        while (true) {
+            int bufferOffset = random.nextInt(64);
+            final int bufferLength = random.nextInt(64);
+            int read = in.read(buffer, bufferOffset, bufferLength);
+            if (read == -1) {
+                assertEquals(offset, expected.length);
+                break;
+            }
+            assertTrue(read <= bufferLength);
+            while (read > 0) {
+                assertTrue(offset < expected.length);
+                assertEquals(expected[offset], buffer[bufferOffset]);
+                offset++;
+                bufferOffset++;
+                read--;
             }
         }
-        if (r.read() != -1) {
-            fail("Mismatch in ReaderInputStream - EOF not seen for string "
-                 + s + " with encoding " + encoding);
+        in.close();
+    }
+
+    @Test
+    public void testUTF8WithSingleByteRead() throws IOException {
+        testWithSingleByteRead(TEST_STRING, "UTF-8");
+    }
+
+    @Test
+    public void testLargeUTF8WithSingleByteRead() throws IOException {
+        testWithSingleByteRead(LARGE_TEST_STRING, "UTF-8");
+    }
+
+    @Test
+    public void testUTF8WithBufferedRead() throws IOException {
+        testWithBufferedRead(TEST_STRING, "UTF-8");
+    }
+
+    @Test
+    public void testLargeUTF8WithBufferedRead() throws IOException {
+        testWithBufferedRead(LARGE_TEST_STRING, "UTF-8");
+    }
+
+    @Test
+    public void testUTF16WithSingleByteRead() throws IOException {
+        testWithSingleByteRead(TEST_STRING, "UTF-16");
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testReadZeroCommonsIo() throws Exception {
+        final String inStr = "test";
+        final ReaderInputStream r = new ReaderInputStream(new StringReader(inStr));
+        final byte[] bytes = new byte[30];
+        assertEquals(0, r.read(bytes, 0, 0));
+        assertEquals(inStr.length(), r.read(bytes, 0, inStr.length()+1));
+        // Should always return 0 for length == 0
+        assertEquals(0, r.read(bytes, 0, 0));
+        r.close();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testReadZeroEmptyString() throws Exception {
+        final ReaderInputStream r = new ReaderInputStream(new StringReader(""));
+        final byte[] bytes = new byte[30];
+        // Should always return 0 for length == 0
+        assertEquals(0, r.read(bytes, 0, 0));
+        assertEquals(-1, r.read(bytes, 0, 1));
+        assertEquals(0, r.read(bytes, 0, 0));
+        assertEquals(-1, r.read(bytes, 0, 1));
+        r.close();
+    }
+
+    /*
+     * Tests https://issues.apache.org/jira/browse/IO-277
+     */
+    @Test
+    public void testCharsetMismatchInfiniteLoop() throws IOException {
+        // Input is UTF-8 bytes: 0xE0 0xB2 0xA0
+        final char[] inputChars = new char[] { (char) 0xE0, (char) 0xB2, (char) 0xA0 };
+        // Charset charset = Charset.forName("UTF-8"); // works
+        final Charset charset = Charset.forName("ASCII"); // infinite loop
+        try (ReaderInputStream stream = new ReaderInputStream(new CharArrayReader(inputChars), charset)) {
+            while (stream.read() != -1) {
+            }
         }
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/ResourceUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/ResourceUtilsTest.java
index 50247b1..686da69 100644
--- a/src/tests/junit/org/apache/tools/ant/util/ResourceUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/ResourceUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
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 59d3ec6..6d17d47 100644
--- a/src/tests/junit/org/apache/tools/ant/util/StringUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/StringUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -17,12 +17,17 @@
  */
 package org.apache.tools.ant.util;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Vector;
 
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.endsWith;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -33,7 +38,7 @@
     @Test
     public void testSplit() {
         final String data = "a,b,,";
-        Vector res = StringUtils.split(data, ',');
+        Vector<String> res = StringUtils.split(data, ',');
         assertEquals(4, res.size());
         assertEquals("a", res.elementAt(0));
         assertEquals("b", res.elementAt(1));
@@ -44,7 +49,7 @@
     @Test
     public void testSplitLines() {
         final String data = "a\r\nb\nc\nd\ne";
-        Vector res = StringUtils.lineSplit(data);
+        Vector<String> res = StringUtils.lineSplit(data);
         assertEquals(5, res.size());
         assertEquals("a\r", res.elementAt(0));
         assertEquals("b", res.elementAt(1));
@@ -53,6 +58,7 @@
         assertEquals("e", res.elementAt(4));
     }
 
+    @SuppressWarnings("deprecation")
     @Test
     public void testReplace() {
         final String data = "abcabcabca";
@@ -92,14 +98,14 @@
 
     @Test
     public void testEndsWithEmptyBuffer() {
-        assertFalse(StringUtils.endsWith(new StringBuffer(""), "12345667"));
+        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"));
+            assertThat(buf.toString(), endsWith("aa"));
         }
     }
 
@@ -143,13 +149,11 @@
         assertEquals(
             "Does not remove the suffix right.",
             prefix + name,
-            StringUtils.removeSuffix(input, suffix)
-        );
+            StringUtils.removeSuffix(input, suffix));
         assertEquals(
             "Should leave the string unattended.",
             prefix + name + suffix,
-            StringUtils.removeSuffix(input, "bla")
-        );
+            StringUtils.removeSuffix(input, "bla"));
     }
 
     @Test
@@ -158,15 +162,56 @@
         String name = "Name";
         String suffix = "Suffix";
         String input = prefix + name + suffix;
-        assertEquals(
-            "Does not remove the prefix right.",
+        assertEquals("Does not remove the prefix right.",
             name + suffix,
-            StringUtils.removePrefix(input, prefix)
-        );
-        assertEquals(
-            "Should leave the string unattended.",
+            StringUtils.removePrefix(input, prefix));
+        assertEquals("Should leave the string unattended.",
             prefix + name + suffix,
-            StringUtils.removePrefix(input, "bla")
-        );
+            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));
+    }
+
+    @Test
+    public void testTrimToNullWithNullInput() {
+        assertNull(StringUtils.trimToNull(null));
+    }
+
+    @Test
+    public void testTrimToNullWithEmptyInput() {
+        assertNull(StringUtils.trimToNull(""));
+    }
+
+    @Test
+    public void testTrimToNullWithBlankSpaceInput() {
+        assertNull(StringUtils.trimToNull("   "));
+    }
+
+    @Test
+    public void testTrimToNullWithInputPaddedWithSpace() {
+        assertEquals("aaBcDeF", StringUtils.trimToNull(" aaBcDeF  "));
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/SymlinkUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/SymlinkUtilsTest.java
index d1de1b1..119a339 100644
--- a/src/tests/junit/org/apache/tools/ant/util/SymlinkUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/SymlinkUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -19,11 +19,11 @@
 package org.apache.tools.ant.util;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeFalse;
 
 import java.io.IOException;
 
 import org.apache.tools.ant.taskdefs.condition.Os;
-import org.junit.Assume;
 import org.junit.Test;
 
 public class SymlinkUtilsTest {
@@ -33,7 +33,7 @@
 
     @Test
     public void testRootIsNoSymlink() throws IOException {
-        Assume.assumeFalse("Symlink doesn't work on Windows", Os.isFamily("windows"));
+        assumeFalse("Symlink doesn't work on Windows", Os.isFamily("windows"));
         assertFalse(SYMLINK_UTILS.isSymbolicLink("/"));
     }
 
diff --git a/src/tests/junit/org/apache/tools/ant/util/UnPackageNameMapperTest.java b/src/tests/junit/org/apache/tools/ant/util/UnPackageNameMapperTest.java
index c59154d..9f17f4e 100644
--- a/src/tests/junit/org/apache/tools/ant/util/UnPackageNameMapperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/UnPackageNameMapperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -30,10 +30,9 @@
         mapper.setFrom("TEST-*.xml");
         mapper.setTo("*.java");
         String file = "TEST-org.apache.tools.ant.util.UnPackageNameMapperTest.xml";
-        String result = mapper.mapFileName(file)[0];
         String expected = fixupPath("org/apache/tools/ant/util/UnPackageNameMapperTest.java");
 
-        assertEquals(expected, result);
+        assertEquals(expected, mapper.mapFileName(file)[0]);
     }
 
     private String fixupPath(String file) {
diff --git a/src/tests/junit/org/apache/tools/ant/util/UnicodeUtilTest.java b/src/tests/junit/org/apache/tools/ant/util/UnicodeUtilTest.java
index 090da56..59b9136 100644
--- a/src/tests/junit/org/apache/tools/ant/util/UnicodeUtilTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/UnicodeUtilTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java b/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java
index 11491e3..5b86c23 100644
--- a/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,16 +23,17 @@
 
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
 
 public class VectorSetTest {
 
     private static final Object O = new Object();
-    private VectorSet v = new VectorSet();
+    private VectorSet<Object> v = new VectorSet<>();
 
     @Test
     public void testAdd() {
@@ -57,13 +58,13 @@
 
     @Test
     public void testAddAll() {
-        assertTrue(v.addAll(Arrays.asList(new Object[] {O, O})));
+        assertTrue(v.addAll(Arrays.asList(O, O)));
         assertEquals(1, v.size());
     }
 
     @Test
     public void testAddAll2() {
-        assertTrue(v.addAll(0, Arrays.asList(new Object[] {O, O})));
+        assertTrue(v.addAll(0, Arrays.asList(O, O)));
         assertEquals(1, v.size());
     }
 
@@ -75,11 +76,12 @@
     }
 
     @Test
+    @SuppressWarnings("unchecked")
     public void testClone() {
         v.add(O);
         Object o = v.clone();
-        assertTrue(o instanceof VectorSet);
-        VectorSet vs = (VectorSet) o;
+        assertThat(o, instanceOf(VectorSet.class));
+        VectorSet<Object> vs = (VectorSet<Object>) o;
         assertEquals(1, vs.size());
         assertTrue(vs.contains(O));
     }
@@ -94,10 +96,10 @@
 
     @Test
     public void testContainsAll() {
-        assertFalse(v.containsAll(Arrays.asList(new Object[] {O, O})));
+        assertFalse(v.containsAll(Arrays.asList(O, O)));
         v.add(O);
-        assertTrue(v.containsAll(Arrays.asList(new Object[] {O, O})));
-        assertFalse(v.containsAll(Arrays.asList(new Object[] {O, null})));
+        assertTrue(v.containsAll(Arrays.asList(O, O)));
+        assertFalse(v.containsAll(Arrays.asList(O, null)));
     }
 
     @Test
@@ -112,13 +114,11 @@
         v.add(O);
         assertSame(O, v.remove(0));
         assertEquals(0, v.size());
-        try {
-            v.remove(0);
-            fail("expected an AIOBE");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            //TODO assert exception values
-            // expected
-        }
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void testCantRemoveByIndexFromEmptySet() {
+        v.remove(0);
     }
 
     @Test
@@ -131,7 +131,7 @@
 
     @Test
     public void testRemoveAtEndWhenSizeEqualsCapacity() {
-        v = new VectorSet(3, 1);
+        v = new VectorSet<>(3, 1);
         Object a = new Object();
         v.add(a);
         Object b = new Object();
@@ -148,7 +148,7 @@
 
     @Test
     public void testRemoveAtFrontWhenSizeEqualsCapacity() {
-        v = new VectorSet(3, 1);
+        v = new VectorSet<>(3, 1);
         v.add(O);
         Object a = new Object();
         v.add(a);
@@ -165,7 +165,7 @@
 
     @Test
     public void testRemoveInMiddleWhenSizeEqualsCapacity() {
-        v = new VectorSet(3, 1);
+        v = new VectorSet<>(3, 1);
         Object a = new Object();
         v.add(a);
         v.add(O);
@@ -183,9 +183,9 @@
     @Test
     public void testRemoveAll() {
         v.add(O);
-        assertTrue(v.removeAll(Arrays.asList(new Object[] {O, O})));
+        assertTrue(v.removeAll(Arrays.asList(O, O)));
         assertEquals(0, v.size());
-        assertFalse(v.removeAll(Arrays.asList(new Object[] {O, O})));
+        assertFalse(v.removeAll(Arrays.asList(O, O)));
     }
 
     @Test
@@ -208,13 +208,11 @@
         v.add(O);
         v.removeElementAt(0);
         assertEquals(0, v.size());
-        try {
-            v.removeElementAt(0);
-            fail("expected an AIOBE");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            //TODO assert exception values
-            // expected
-        }
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void testCantRemoveAtFromEmptySet() {
+        v.removeElementAt(0);
     }
 
     @Test
@@ -222,7 +220,7 @@
         Object a = new Object();
         Object b = new Object();
         Object c = new Object();
-        v.addAll(Arrays.asList(new Object[] {O, a, b, c}));
+        v.addAll(Arrays.asList(O, a, b, c));
         v.removeRange(1, 3);
         assertEquals(2, v.size());
         assertTrue(v.contains(O));
@@ -234,9 +232,9 @@
         Object a = new Object();
         Object b = new Object();
         Object c = new Object();
-        v.addAll(Arrays.asList(new Object[] {O, a, b, c}));
+        v.addAll(Arrays.asList(O, a, b, c));
         assertEquals(0, v.indexOf(O));
-        assertTrue(v.retainAll(Arrays.asList(new Object[] {c, O})));
+        assertTrue(v.retainAll(Arrays.asList(c, O)));
         assertEquals(2, v.size());
         assertTrue(v.contains(O));
         assertTrue(v.contains(c));
@@ -283,7 +281,7 @@
             v.add(i);
         }
         assertEquals(size, v.size());
-        ArrayList<Integer> list = new ArrayList<Integer>();
+        ArrayList<Integer> list = new ArrayList<>();
         for (int i = size - 4; i < 2 * size; i++) {
             list.add(i);
             v.add(i);
diff --git a/src/tests/junit/org/apache/tools/ant/util/XMLFragmentTest.java b/src/tests/junit/org/apache/tools/ant/util/XMLFragmentTest.java
index 0ac938f..051ccd0 100644
--- a/src/tests/junit/org/apache/tools/ant/util/XMLFragmentTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/XMLFragmentTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -27,6 +27,7 @@
 import org.w3c.dom.NodeList;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -42,10 +43,10 @@
 
     @Test
     public void testNestedText() {
-        XMLFragment x = (XMLFragment) buildRule.getProject().getReference("nested-text");
+        XMLFragment x = buildRule.getProject().getReference("nested-text");
         assertNotNull(x);
         Node n = x.getFragment();
-        assertTrue("No attributes", !n.hasAttributes());
+        assertFalse("No attributes", n.hasAttributes());
         NodeList nl = n.getChildNodes();
         assertEquals(1, nl.getLength());
         assertEquals(Node.TEXT_NODE, nl.item(0).getNodeType());
@@ -55,17 +56,17 @@
     @Test
     public void testNestedChildren() {
         XMLFragment x =
-            (XMLFragment) buildRule.getProject().getReference("with-children");
+                buildRule.getProject().getReference("with-children");
         assertNotNull(x);
         Node n = x.getFragment();
-        assertTrue("No attributes", !n.hasAttributes());
+        assertFalse("No attributes", n.hasAttributes());
         NodeList nl = n.getChildNodes();
         assertEquals(3, nl.getLength());
 
         assertEquals(Node.ELEMENT_NODE, nl.item(0).getNodeType());
         Element child1 = (Element) nl.item(0);
         assertEquals("child1", child1.getTagName());
-        assertTrue(!child1.hasAttributes());
+        assertFalse(child1.hasAttributes());
         NodeList nl2 = child1.getChildNodes();
         assertEquals(1, nl2.getLength());
         assertEquals(Node.TEXT_NODE, nl2.item(0).getNodeType());
@@ -82,7 +83,7 @@
         assertEquals(Node.ELEMENT_NODE, nl.item(2).getNodeType());
         Element child3 = (Element) nl.item(2);
         assertEquals("child3", child3.getTagName());
-        assertTrue(!child3.hasAttributes());
+        assertFalse(child3.hasAttributes());
         nl2 = child3.getChildNodes();
         assertEquals(1, nl2.getLength());
         assertEquals(Node.ELEMENT_NODE, nl2.item(0).getNodeType());
diff --git a/src/tests/junit/org/apache/tools/ant/util/facade/FacadeTaskHelperTest.java b/src/tests/junit/org/apache/tools/ant/util/facade/FacadeTaskHelperTest.java
index df2d43b..245958f 100644
--- a/src/tests/junit/org/apache/tools/ant/util/facade/FacadeTaskHelperTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/facade/FacadeTaskHelperTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,6 +21,7 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -51,13 +52,13 @@
     @Test
     public void testHasBeenSet() {
         FacadeTaskHelper fth = new FacadeTaskHelper("foo");
-        assertTrue("nothing set", !fth.hasBeenSet());
+        assertFalse("nothing set", fth.hasBeenSet());
         fth.setMagicValue(null);
-        assertTrue("magic has not been set", !fth.hasBeenSet());
+        assertFalse("magic has not been set", fth.hasBeenSet());
         fth.setMagicValue("foo");
         assertTrue("magic has been set", fth.hasBeenSet());
         fth.setMagicValue(null);
-        assertTrue(!fth.hasBeenSet());
+        assertFalse(fth.hasBeenSet());
         fth.setImplementation("baz");
         assertTrue("set explicitly", fth.hasBeenSet());
     }
diff --git a/src/tests/junit/org/apache/tools/ant/util/facade/ImplementationSpecificArgumentTest.java b/src/tests/junit/org/apache/tools/ant/util/facade/ImplementationSpecificArgumentTest.java
index a1b97d1..f4a6e29 100644
--- a/src/tests/junit/org/apache/tools/ant/util/facade/ImplementationSpecificArgumentTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/facade/ImplementationSpecificArgumentTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroMatcherTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroMatcherTest.java
index c05ea22..6b234aa 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroMatcherTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroMatcherTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroRegexpTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroRegexpTest.java
index ae82f75..a98cca4 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroRegexpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaOroRegexpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpMatcherTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpMatcherTest.java
index ce42c8c..adcdfb3 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpMatcherTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpMatcherTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,8 @@
 
 package org.apache.tools.ant.util.regexp;
 
-import java.io.IOException;
-
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 /**
  * Tests for the jakarta-regexp implementation of the RegexpMatcher interface.
  *
@@ -34,25 +30,21 @@
         return new JakartaRegexpMatcher();
     }
 
-    @Test
-    public void testWindowsLineSeparator2() throws IOException {
-        try {
-            super.testWindowsLineSeparator2();
-            fail("Should trigger when this bug is fixed. {@since 1.2}");
-        } catch (AssertionError e) {
-        }
+    /**
+     * Should trigger once fixed. {@since 1.2}
+     */
+    @Test(expected = AssertionError.class)
+    public void testWindowsLineSeparator2() {
+        super.testWindowsLineSeparator2();
     }
 
     /**
      * Fails for the same reason as "default" mode in doEndTest2.
+     * Should trigger once fixed. {@since 1.2}
      */
-    @Test
-    public void testUnixLineSeparator() throws IOException {
-        try {
-            super.testUnixLineSeparator();
-            fail("Should trigger once this bug is fixed. {@since 1.2}");
-        } catch (AssertionError e) {
-        }
+    @Test(expected = AssertionError.class)
+    public void testUnixLineSeparator() {
+        super.testUnixLineSeparator();
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpRegexpTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpRegexpTest.java
index 4937ff4..4f1d077 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpRegexpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/JakartaRegexpRegexpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,8 @@
 
 package org.apache.tools.ant.util.regexp;
 
-import java.io.IOException;
-
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 /**
  * Tests for the jakarta-regexp implementation of the Regexp interface.
  *
@@ -34,25 +30,21 @@
         return new JakartaRegexpRegexp();
     }
 
-    @Test
-    public void testWindowsLineSeparator2() throws IOException {
-        try {
-            super.testWindowsLineSeparator2();
-            fail("Should trigger when this bug is fixed. {@since 1.2}");
-        } catch (AssertionError e) {
-        }
+    /**
+     * Should trigger once fixed. {@since 1.2}
+     */
+    @Test(expected = AssertionError.class)
+    public void testWindowsLineSeparator2() {
+        super.testWindowsLineSeparator2();
     }
 
     /**
      * Fails for the same reason as "default" mode in doEndTest2.
+     * Should trigger once fixed. {@since 1.2}
      */
-    @Test
-    public void testUnixLineSeparator() throws IOException {
-        try {
-            super.testUnixLineSeparator();
-            fail("Should trigger once this bug is fixed. {@since 1.2}");
-        } catch (AssertionError e) {
-        }
+    @Test(expected = AssertionError.class)
+    public void testUnixLineSeparator() {
+        super.testUnixLineSeparator();
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcherTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcherTest.java
index 5a5f1d2..f6c058d 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcherTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpMatcherTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,8 @@
 
 package org.apache.tools.ant.util.regexp;
 
-import java.io.IOException;
-
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 /**
  * Tests for the JDK 1.4 implementation of the RegexpMatcher interface.
  *
@@ -34,39 +30,35 @@
         return new Jdk14RegexpMatcher();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testParagraphCharacter() throws IOException {
-        try {
-            super.testParagraphCharacter();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testParagraphCharacter() {
+        super.testParagraphCharacter();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testLineSeparatorCharacter() throws IOException {
-        try {
-            super.testLineSeparatorCharacter();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testLineSeparatorCharacter() {
+        super.testLineSeparatorCharacter();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testStandaloneCR() throws IOException {
-        try {
-            super.testStandaloneCR();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testStandaloneCR() {
+        super.testStandaloneCR();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testWindowsLineSeparator() throws IOException {
-        try {
-            super.testWindowsLineSeparator();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testWindowsLineSeparator() {
+        super.testWindowsLineSeparator();
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexpTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexpTest.java
index 67b69aa..8fa9891 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,8 @@
 
 package org.apache.tools.ant.util.regexp;
 
-import java.io.IOException;
-
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 /**
  * Tests for the JDK 1.4 implementation of the Regexp interface.
  *
@@ -34,40 +30,36 @@
         return new Jdk14RegexpRegexp();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testParagraphCharacter() throws IOException {
-        try {
-            super.testParagraphCharacter();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testParagraphCharacter() {
+        super.testParagraphCharacter();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testLineSeparatorCharacter() throws IOException {
-        try {
-            super.testLineSeparatorCharacter();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testLineSeparatorCharacter() {
+        super.testLineSeparatorCharacter();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testStandaloneCR() throws IOException {
-        try {
-            super.testStandaloneCR();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testStandaloneCR() {
+        super.testStandaloneCR();
     }
 
+    /**
+     * Should trigger once fixed. {@since JDK 1.4RC1}
+     */
     @Test
-    public void testWindowsLineSeparator() throws IOException {
-        try {
-            super.testWindowsLineSeparator();
-            fail("Should trigger once fixed. {@since JDK 1.4RC1}");
-        } catch (AssertionError e) {
-        }
+    public void testWindowsLineSeparator() {
+        super.testWindowsLineSeparator();
     }
 
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpMatcherTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpMatcherTest.java
index 5edaf57..c7b4a08 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpMatcherTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpMatcherTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,10 +21,10 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import java.io.IOException;
 import java.util.Vector;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -53,56 +53,56 @@
         reg.setPattern("aaaa");
         assertTrue("aaaa should match itself", reg.matches("aaaa"));
         assertTrue("aaaa should match xaaaa", reg.matches("xaaaa"));
-        assertTrue("aaaa shouldn\'t match xaaa", !reg.matches("xaaa"));
+        assertFalse("aaaa shouldn't match xaaa", reg.matches("xaaa"));
         reg.setPattern("^aaaa");
-        assertTrue("^aaaa shouldn\'t match xaaaa", !reg.matches("xaaaa"));
+        assertFalse("^aaaa shouldn't match xaaaa", reg.matches("xaaaa"));
         assertTrue("^aaaa should match aaaax", reg.matches("aaaax"));
         reg.setPattern("aaaa$");
-        assertTrue("aaaa$ shouldn\'t match aaaax", !reg.matches("aaaax"));
+        assertFalse("aaaa$ shouldn't match aaaax", reg.matches("aaaax"));
         assertTrue("aaaa$ should match xaaaa", reg.matches("xaaaa"));
         reg.setPattern("[0-9]+");
         assertTrue("[0-9]+ should match 123", reg.matches("123"));
         assertTrue("[0-9]+ should match 1", reg.matches("1"));
-        assertTrue("[0-9]+ shouldn\'t match \'\'", !reg.matches(""));
-        assertTrue("[0-9]+ shouldn\'t match a", !reg.matches("a"));
+        assertFalse("[0-9]+ shouldn't match ''", reg.matches(""));
+        assertFalse("[0-9]+ shouldn't match a", reg.matches("a"));
         reg.setPattern("[0-9]*");
         assertTrue("[0-9]* should match 123", reg.matches("123"));
         assertTrue("[0-9]* should match 1", reg.matches("1"));
-        assertTrue("[0-9]* should match \'\'", reg.matches(""));
+        assertTrue("[0-9]* should match ''", reg.matches(""));
         assertTrue("[0-9]* should match a", reg.matches("a"));
         reg.setPattern("([0-9]+)=\\1");
         assertTrue("([0-9]+)=\\1 should match 1=1", reg.matches("1=1"));
-        assertTrue("([0-9]+)=\\1 shouldn\'t match 1=2", !reg.matches("1=2"));
+        assertFalse("([0-9]+)=\\1 shouldn't match 1=2", reg.matches("1=2"));
     }
 
     @Test
     public void testGroups() {
         reg.setPattern("aaaa");
-        Vector v = reg.getGroups("xaaaa");
+        Vector<String> v = reg.getGroups("xaaaa");
         assertEquals("No parens -> no extra groups", 1, v.size());
         assertEquals("Trivial match with no parens", "aaaa",
-                     (String) v.elementAt(0));
+                v.elementAt(0));
 
         reg.setPattern("(aaaa)");
         v = reg.getGroups("xaaaa");
         assertEquals("Trivial match with single paren", 2, v.size());
         assertEquals("Trivial match with single paren, full match", "aaaa",
-                     (String) v.elementAt(0));
+                v.elementAt(0));
         assertEquals("Trivial match with single paren, matched paren", "aaaa",
-                     (String) v.elementAt(0));
+                v.elementAt(0));
 
         reg.setPattern("(a+)b(b+)");
         v = reg.getGroups("xaabb");
         assertEquals(3, v.size());
-        assertEquals("aabb", (String) v.elementAt(0));
-        assertEquals("aa", (String) v.elementAt(1));
-        assertEquals("b", (String) v.elementAt(2));
+        assertEquals("aabb", v.elementAt(0));
+        assertEquals("aa", v.elementAt(1));
+        assertEquals("b", v.elementAt(2));
     }
 
     @Test
     public void testBugzillaReport14619() {
         reg.setPattern("^(.*)/src/((.*/)*)([a-zA-Z0-9_\\.]+)\\.java$");
-        Vector v = reg.getGroups("de/tom/src/Google.java");
+        Vector<String> v = reg.getGroups("de/tom/src/Google.java");
         assertEquals(5, v.size());
         assertEquals("de/tom", v.elementAt(1));
         assertEquals("", v.elementAt(2));
@@ -113,7 +113,7 @@
     @Test
     public void testCaseInsensitiveMatch() {
         reg.setPattern("aaaa");
-        assertTrue("aaaa doesn't match AAaa", !reg.matches("AAaa"));
+        assertFalse("aaaa doesn't match AAaa", reg.matches("AAaa"));
         assertTrue("aaaa matches AAaa ignoring case",
                    reg.matches("AAaa", RegexpMatcher.MATCH_CASE_INSENSITIVE));
     }
@@ -122,55 +122,53 @@
     // a line separator for regex (perl) is always a unix line (ie \n)
 
     @Test
-    public void testParagraphCharacter() throws IOException {
+    public void testParagraphCharacter() {
         reg.setPattern("end of text$");
-        assertTrue("paragraph character", !reg.matches("end of text\u2029"));
+        assertFalse("paragraph character", reg.matches("end of text\u2029"));
     }
 
     @Test
-    public void testLineSeparatorCharacter() throws IOException {
+    public void testLineSeparatorCharacter() {
         reg.setPattern("end of text$");
-        assertTrue("line-separator character", !reg.matches("end of text\u2028"));
+        assertFalse("line-separator character", reg.matches("end of text\u2028"));
     }
 
     @Test
-    public void testNextLineCharacter() throws IOException {
+    public void testNextLineCharacter() {
         reg.setPattern("end of text$");
-        assertTrue("next-line character", !reg.matches("end of text\u0085"));
+        assertFalse("next-line character", reg.matches("end of text\u0085"));
     }
 
     @Test
-    public void testStandaloneCR() throws IOException {
+    public void testStandaloneCR() {
         reg.setPattern("end of text$");
-        assertTrue("standalone CR", !reg.matches("end of text\r"));
+        assertFalse("standalone CR", reg.matches("end of text\r"));
     }
 
     @Test
-    public void testWindowsLineSeparator() throws IOException {
+    public void testWindowsLineSeparator() {
         reg.setPattern("end of text$");
-        assertTrue("Windows line separator", !reg.matches("end of text\r\n"));
+        assertFalse("Windows line separator", reg.matches("end of text\r\n"));
     }
 
     @Test
-    public void testWindowsLineSeparator2() throws IOException {
+    public void testWindowsLineSeparator2() {
         reg.setPattern("end of text\r$");
         assertTrue("Windows line separator", reg.matches("end of text\r\n"));
     }
 
     @Test
-    public void testUnixLineSeparator() throws IOException {
+    public void testUnixLineSeparator() {
         reg.setPattern("end of text$");
         assertTrue("Unix line separator", reg.matches("end of text\n"));
     }
 
     @Test
-    public void testMultiVersusSingleLine() throws IOException {
-        StringBuilder buf = new StringBuilder();
-        buf.append("Line1").append(UNIX_LINE);
-        buf.append("starttest Line2").append(UNIX_LINE);
-        buf.append("Line3 endtest").append(UNIX_LINE);
-        buf.append("Line4").append(UNIX_LINE);
-        String text = buf.toString();
+    public void testMultiVersusSingleLine() {
+        String text = "Line1" + UNIX_LINE +
+                "starttest Line2" + UNIX_LINE +
+                "Line3 endtest" + UNIX_LINE +
+                "Line4" + UNIX_LINE;
 
         doStartTest1(text);
         doStartTest2(text);
@@ -180,9 +178,9 @@
 
     protected void doStartTest1(String text) {
         reg.setPattern("^starttest");
-        assertTrue("^starttest in default mode", !reg.matches(text));
-        assertTrue("^starttest in single line mode",
-               !reg.matches(text, RegexpMatcher.MATCH_SINGLELINE));
+        assertFalse("^starttest in default mode", reg.matches(text));
+        assertFalse("^starttest in single line mode",
+                reg.matches(text, RegexpMatcher.MATCH_SINGLELINE));
         assertTrue("^starttest in multi line mode",
                reg.matches(text, RegexpMatcher.MATCH_MULTILINE));
     }
@@ -198,11 +196,11 @@
 
     protected void doEndTest1(String text) {
         reg.setPattern("endtest$");
-        assertTrue("endtest$ in default mode", !reg.matches(text));
-        assertTrue("endtest$ in single line mode",
-               !reg.matches(text, RegexpMatcher.MATCH_SINGLELINE));
+        assertFalse("endtest$ in default mode", reg.matches(text));
+        assertFalse("endtest$ in single line mode",
+                reg.matches(text, RegexpMatcher.MATCH_SINGLELINE));
         assertTrue("endtest$ in multi line mode",
-               reg.matches(text, RegexpMatcher.MATCH_MULTILINE));
+                reg.matches(text, RegexpMatcher.MATCH_MULTILINE));
     }
 
     protected void doEndTest2(String text) {
diff --git a/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpTest.java b/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpTest.java
index 08a8416..1f7a777 100644
--- a/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/regexp/RegexpTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/bzip2/BlockSortTest.java b/src/tests/junit/org/apache/tools/bzip2/BlockSortTest.java
index ed0269e..56c36c2 100644
--- a/src/tests/junit/org/apache/tools/bzip2/BlockSortTest.java
+++ b/src/tests/junit/org/apache/tools/bzip2/BlockSortTest.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
diff --git a/src/tests/junit/org/apache/tools/bzip2/CBZip2StreamTest.java b/src/tests/junit/org/apache/tools/bzip2/CBZip2StreamTest.java
index 88b500a..5b8ea97 100644
--- a/src/tests/junit/org/apache/tools/bzip2/CBZip2StreamTest.java
+++ b/src/tests/junit/org/apache/tools/bzip2/CBZip2StreamTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -23,20 +23,12 @@
 
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
-
 public class CBZip2StreamTest {
 
     @SuppressWarnings("resource")
-    @Test
+    @Test(expected = IOException.class)
     public void testNullPointer() throws IOException {
-        try {
-            new CBZip2InputStream(new ByteArrayInputStream(new byte[0]));
-            fail("expected an exception");
-        } catch (IOException e) {
-            // expected
-            //TODO assert exception values
-        }
+        new CBZip2InputStream(new ByteArrayInputStream(new byte[0]));
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/mail/MailMessageTest.java b/src/tests/junit/org/apache/tools/mail/MailMessageTest.java
index ee7a05c..72ee1fa 100644
--- a/src/tests/junit/org/apache/tools/mail/MailMessageTest.java
+++ b/src/tests/junit/org/apache/tools/mail/MailMessageTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,6 +18,9 @@
 
 package org.apache.tools.mail;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
 import org.apache.tools.ant.DummyMailServer;
 import org.junit.AssumptionViolatedException;
 import org.junit.Before;
@@ -27,12 +30,8 @@
 import java.io.IOException;
 import java.io.PrintStream;
 import java.net.InetAddress;
-import java.util.Enumeration;
 import java.util.Vector;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
 /**
  * JUnit testcases for org.apache.tools.mail.MailMessage.
  *
@@ -45,7 +44,7 @@
     @Before
     public void setUp() {
         try {
-            local = InetAddress.getLocalHost().getHostName();
+            local = InetAddress.getLocalHost().getCanonicalHostName();
         } catch (java.net.UnknownHostException uhe) {
             // ignore
         }
@@ -430,10 +429,10 @@
         protected String subject = null;
         protected String message = null;
 
-        protected Vector replyToList = new Vector();
-        protected Vector toList = new Vector();
-        protected Vector ccList = new Vector();
-        protected Vector bccList = new Vector();
+        protected Vector<String> replyToList = new Vector<>();
+        protected Vector<String> toList = new Vector<>();
+        protected Vector<String> ccList = new Vector<>();
+        protected Vector<String> bccList = new Vector<>();
 
         ClientThread(int port) {
             this.port = port;
@@ -468,26 +467,18 @@
             try {
                 msg.from(from);
 
-                Enumeration e;
+                replyToList.forEach(e -> msg.replyto(e));
 
-                e = replyToList.elements();
-                while (e.hasMoreElements()) {
-                    msg.replyto(e.nextElement().toString());
+                for (String e : toList) {
+                    msg.to(e);
                 }
 
-                e = toList.elements();
-                while (e.hasMoreElements()) {
-                    msg.to(e.nextElement().toString());
+                for (String e : ccList) {
+                    msg.cc(e);
                 }
 
-                e = ccList.elements();
-                while (e.hasMoreElements()) {
-                    msg.cc(e.nextElement().toString());
-                }
-
-                e = bccList.elements();
-                while (e.hasMoreElements()) {
-                    msg.bcc(e.nextElement().toString());
+                for (String e : bccList) {
+                    msg.bcc(e);
                 }
 
                 if (subject != null) {
diff --git a/src/tests/junit/org/apache/tools/tar/TarEntryTest.java b/src/tests/junit/org/apache/tools/tar/TarEntryTest.java
index f5c2020..13d9f99 100644
--- a/src/tests/junit/org/apache/tools/tar/TarEntryTest.java
+++ b/src/tests/junit/org/apache/tools/tar/TarEntryTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/tar/TarOutputStreamTest.java b/src/tests/junit/org/apache/tools/tar/TarOutputStreamTest.java
index cb65e2d..46b10de 100644
--- a/src/tests/junit/org/apache/tools/tar/TarOutputStreamTest.java
+++ b/src/tests/junit/org/apache/tools/tar/TarOutputStreamTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/tar/TarRoundTripTest.java b/src/tests/junit/org/apache/tools/tar/TarRoundTripTest.java
index 3caba34..884ad76 100644
--- a/src/tests/junit/org/apache/tools/tar/TarRoundTripTest.java
+++ b/src/tests/junit/org/apache/tools/tar/TarRoundTripTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/apache/tools/zip/AsiExtraFieldTest.java b/src/tests/junit/org/apache/tools/zip/AsiExtraFieldTest.java
index af44e7d..8469f45 100644
--- a/src/tests/junit/org/apache/tools/zip/AsiExtraFieldTest.java
+++ b/src/tests/junit/org/apache/tools/zip/AsiExtraFieldTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,17 @@
 
 package org.apache.tools.zip;
 
-import org.junit.Test;
-
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.zip.ZipException;
 
 /**
  * JUnit testcases for org.apache.tools.zip.AsiExtraField.
@@ -31,12 +36,21 @@
  */
 public class AsiExtraFieldTest implements UnixStat {
 
+    private  AsiExtraField a;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        a = new AsiExtraField();
+    }
+
     /**
      * Test file mode magic.
      */
     @Test
     public void testModes() {
-        AsiExtraField a = new AsiExtraField();
         a.setMode(0123);
         assertEquals("plain file", 0100123, a.getMode());
         a.setDirectory(true);
@@ -50,7 +64,6 @@
      */
     @Test
     public void testContent() {
-        AsiExtraField a = new AsiExtraField();
         a.setMode(0123);
         a.setUserId(5);
         a.setGroupId(6);
@@ -81,83 +94,96 @@
     }
 
     /**
-     * Test reparse
+     * Test reparse file
      */
     @Test
-    public void testReparse() throws Exception {
-        AsiExtraField a = new AsiExtraField();
+    public void testReparseFile() throws Exception {
         // CRC manually calculated, sorry
         byte[] data = {(byte) 0xC6, 0x02, 0x78, (byte) 0xB6, // CRC
-                        0123, (byte) 0x80,                   // mode
-                        0, 0, 0, 0,                          // link length
-                        5, 0, 6, 0};                         // uid, gid
+                       0123, (byte) 0x80,                    // mode
+                       0, 0, 0, 0,                           // link length
+                       5, 0, 6, 0};                          // uid, gid
+
         a.parseFromLocalFileData(data, 0, data.length);
         assertEquals("length plain file", data.length,
-                     a.getLocalFileDataLength().getValue());
-        assertTrue("plain file, no link", !a.isLink());
-        assertTrue("plain file, no dir", !a.isDirectory());
+                a.getLocalFileDataLength().getValue());
+        assertFalse("plain file, no link", a.isLink());
+        assertFalse("plain file, no dir", a.isDirectory());
         assertEquals("mode plain file", FILE_FLAG | 0123, a.getMode());
         assertEquals("uid plain file", 5, a.getUserId());
         assertEquals("gid plain file", 6, a.getGroupId());
+    }
 
-        data = new byte[] {0x75, (byte) 0x8E, 0x41, (byte) 0xFD, // CRC
-                           0123, (byte) 0xA0,                    // mode
-                           4, 0, 0, 0,                           // link length
-                           5, 0, 6, 0,                           // uid, gid
-                           (byte) 't', (byte) 'e', (byte) 's', (byte) 't'};
-        a = new AsiExtraField();
+    /**
+     * Test reparse link
+     */
+    @Test
+    public void testReparseLink() throws Exception {
+        byte[] data = {0x75, (byte) 0x8E, 0x41, (byte) 0xFD, // CRC
+                       0123, (byte) 0xA0,                    // mode
+                       4, 0, 0, 0,                           // link length
+                       5, 0, 6, 0,                           // uid, gid
+                       (byte) 't', (byte) 'e', (byte) 's', (byte) 't'};
+
         a.parseFromLocalFileData(data, 0, data.length);
         assertEquals("length link", data.length,
-                     a.getLocalFileDataLength().getValue());
+                a.getLocalFileDataLength().getValue());
         assertTrue("link, is link", a.isLink());
-        assertTrue("link, no dir", !a.isDirectory());
+        assertFalse("link, no dir", a.isDirectory());
         assertEquals("mode link", LINK_FLAG | 0123, a.getMode());
         assertEquals("uid link", 5, a.getUserId());
         assertEquals("gid link", 6, a.getGroupId());
         assertEquals("test", a.getLinkedFile());
+    }
 
-        data = new byte[] {(byte) 0x8E, 0x01, (byte) 0xBF, (byte) 0x0E, // CRC
-                           0123, (byte) 0x40,                           // mode
-                           0, 0, 0, 0,                                  // link
-                           5, 0, 6, 0};                                 // uid, gid
-        a = new AsiExtraField();
+    /**
+     * Test reparse directory
+     */
+    @Test
+    public void testReparseDirectory() throws Exception {
+        byte[] data ={(byte)0x8E, 0x01, (byte)0xBF, (byte)0x0E, // CRC
+                      0123, (byte)0x40,                         // mode
+                      0, 0, 0, 0,                               // link
+                      5, 0, 6, 0};                              // uid, gid
+
         a.parseFromLocalFileData(data, 0, data.length);
         assertEquals("length dir", data.length,
-                     a.getLocalFileDataLength().getValue());
-        assertTrue("dir, no link", !a.isLink());
+                a.getLocalFileDataLength().getValue());
+        assertFalse("dir, no link", a.isLink());
         assertTrue("dir, is dir", a.isDirectory());
         assertEquals("mode dir", DIR_FLAG | 0123, a.getMode());
         assertEquals("uid dir", 5, a.getUserId());
         assertEquals("gid dir", 6, a.getGroupId());
+    }
 
-        data = new byte[] {0, 0, 0, 0,                           // bad CRC
-                           0123, (byte) 0x40,                    // mode
-                           0, 0, 0, 0,                           // link
-                           5, 0, 6, 0};                          // uid, gid
-        a = new AsiExtraField();
-        try {
-            a.parseFromLocalFileData(data, 0, data.length);
-            fail("should raise bad CRC exception");
-        } catch (Exception e) {
-            assertEquals("bad CRC checksum 0 instead of ebf018e",
-                         e.getMessage());
-        }
+    /**
+     * Test reparse bad CRC
+     */
+    @Test
+    public void testReparseBadCRC() throws Exception {
+        thrown.expect(ZipException.class);
+        thrown.expectMessage("bad CRC checksum 0 instead of ebf018e");
+        byte[] data = {0, 0, 0, 0,                           // bad CRC
+                       0123, (byte)0x40,                     // mode
+                       0, 0, 0, 0,                           // link
+                       5, 0, 6, 0};                          // uid, gid
+
+        a.parseFromLocalFileData(data, 0, data.length);
     }
 
     @Test
     public void testClone() {
-        AsiExtraField s1 = new AsiExtraField();
-        s1.setUserId(42);
-        s1.setGroupId(12);
-        s1.setLinkedFile("foo");
-        s1.setMode(0644);
-        s1.setDirectory(true);
-        AsiExtraField s2 = (AsiExtraField) s1.clone();
-        assertNotSame(s1, s2);
-        assertEquals(s1.getUserId(), s2.getUserId());
-        assertEquals(s1.getGroupId(), s2.getGroupId());
-        assertEquals(s1.getLinkedFile(), s2.getLinkedFile());
-        assertEquals(s1.getMode(), s2.getMode());
-        assertEquals(s1.isDirectory(), s2.isDirectory());
+        a.setUserId(42);
+        a.setGroupId(12);
+        a.setLinkedFile("foo");
+        a.setMode(0644);
+        a.setDirectory(true);
+        AsiExtraField s2 = (AsiExtraField) a.clone();
+        assertNotSame(a, s2);
+        assertEquals(a.getUserId(), s2.getUserId());
+        assertEquals(a.getGroupId(), s2.getGroupId());
+        assertEquals(a.getLinkedFile(), s2.getLinkedFile());
+        assertEquals(a.getMode(), s2.getMode());
+        assertEquals(a.isDirectory(), s2.isDirectory());
     }
 }
diff --git a/src/tests/junit/org/apache/tools/zip/ExtraFieldUtilsTest.java b/src/tests/junit/org/apache/tools/zip/ExtraFieldUtilsTest.java
index 841a2fc..baf3e2b 100644
--- a/src/tests/junit/org/apache/tools/zip/ExtraFieldUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/zip/ExtraFieldUtilsTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,16 @@
 
 package org.apache.tools.zip;
 
-import org.junit.Before;
-import org.junit.Test;
-
+import static org.hamcrest.Matchers.instanceOf;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.zip.ZipException;
 
 /**
  * JUnit 4 testcases for org.apache.tools.zip.ExtraFieldUtils.
@@ -43,6 +47,9 @@
     private byte[] data;
     private byte[] aLocal;
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
     @Before
     public void setUp() {
         a = new AsiExtraField();
@@ -73,26 +80,22 @@
      */
     @Test
     public void testParse() throws Exception {
+        thrown.expect(ZipException.class);
+        thrown.expectMessage("bad extra field starting at " + (4 + aLocal.length)
+                        + ".  Block length of 1 bytes exceeds remaining data of 0 bytes.");
+
         ZipExtraField[] ze = ExtraFieldUtils.parse(data);
         assertEquals("number of fields", 2, ze.length);
-        assertTrue("type field 1", ze[0] instanceof AsiExtraField);
+        assertThat("type field 1", ze[0], instanceOf(AsiExtraField.class));
         assertEquals("mode field 1", 040755,
                      ((AsiExtraField) ze[0]).getMode());
-        assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
+        assertThat("type field 2", ze[1], instanceOf(UnrecognizedExtraField.class));
         assertEquals("data length field 2", 1,
                      ze[1].getLocalFileDataLength().getValue());
 
         byte[] data2 = new byte[data.length - 1];
         System.arraycopy(data, 0, data2, 0, data2.length);
-        try {
-            ExtraFieldUtils.parse(data2);
-            fail("data should be invalid");
-        } catch (Exception e) {
-            assertEquals("message",
-                         "bad extra field starting at " + (4 + aLocal.length)
-                         + ".  Block length of 1 bytes exceeds remaining data of 0 bytes.",
-                         e.getMessage());
-        }
+        ExtraFieldUtils.parse(data2);
     }
 
     @Test
@@ -101,10 +104,10 @@
             ExtraFieldUtils.parse(data, true,
                                   ExtraFieldUtils.UnparseableExtraField.READ);
         assertEquals("number of fields", 2, ze.length);
-        assertTrue("type field 1", ze[0] instanceof AsiExtraField);
+        assertThat("type field 1", ze[0], instanceOf(AsiExtraField.class));
         assertEquals("mode field 1", 040755,
                      ((AsiExtraField) ze[0]).getMode());
-        assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
+        assertThat("type field 2", ze[1], instanceOf(UnrecognizedExtraField.class));
         assertEquals("data length field 2", 1,
                      ze[1].getLocalFileDataLength().getValue());
 
@@ -113,10 +116,10 @@
         ze = ExtraFieldUtils.parse(data2, true,
                                    ExtraFieldUtils.UnparseableExtraField.READ);
         assertEquals("number of fields", 2, ze.length);
-        assertTrue("type field 1", ze[0] instanceof AsiExtraField);
+        assertThat("type field 1", ze[0], instanceOf(AsiExtraField.class));
         assertEquals("mode field 1", 040755,
                      ((AsiExtraField) ze[0]).getMode());
-        assertTrue("type field 2", ze[1] instanceof UnparseableExtraFieldData);
+        assertThat("type field 2", ze[1], instanceOf(UnparseableExtraFieldData.class));
         assertEquals("data length field 2", 4,
                      ze[1].getLocalFileDataLength().getValue());
         for (int i = 0; i < 4; i++) {
@@ -132,10 +135,10 @@
             ExtraFieldUtils.parse(data, true,
                                   ExtraFieldUtils.UnparseableExtraField.SKIP);
         assertEquals("number of fields", 2, ze.length);
-        assertTrue("type field 1", ze[0] instanceof AsiExtraField);
+        assertThat("type field 1", ze[0], instanceOf(AsiExtraField.class));
         assertEquals("mode field 1", 040755,
                      ((AsiExtraField) ze[0]).getMode());
-        assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
+        assertThat("type field 2", ze[1], instanceOf(UnrecognizedExtraField.class));
         assertEquals("data length field 2", 1,
                      ze[1].getLocalFileDataLength().getValue());
 
@@ -144,7 +147,7 @@
         ze = ExtraFieldUtils.parse(data2, true,
                                    ExtraFieldUtils.UnparseableExtraField.SKIP);
         assertEquals("number of fields", 1, ze.length);
-        assertTrue("type field 1", ze[0] instanceof AsiExtraField);
+        assertThat("type field 1", ze[0], instanceOf(AsiExtraField.class));
         assertEquals("mode field 1", 040755,
                      ((AsiExtraField) ze[0]).getMode());
     }
diff --git a/src/tests/junit/org/apache/tools/zip/UTF8ZipFilesTest.java b/src/tests/junit/org/apache/tools/zip/UTF8ZipFilesTest.java
index 6f21ca8..fe5eccd 100644
--- a/src/tests/junit/org/apache/tools/zip/UTF8ZipFilesTest.java
+++ b/src/tests/junit/org/apache/tools/zip/UTF8ZipFilesTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
-import java.util.Enumeration;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
 import java.util.zip.CRC32;
 import org.junit.Test;
 
@@ -126,71 +127,61 @@
 
         ZipEncoding zipEncoding = ZipEncodingHelper.getZipEncoding(encoding);
 
-        ZipOutputStream zos = null;
-        try {
-            zos = new ZipOutputStream(file);
+        try (ZipOutputStream zos = new ZipOutputStream(file)) {
             zos.setEncoding(encoding);
             zos.setUseLanguageEncodingFlag(withEFS);
             zos.setCreateUnicodeExtraFields(withExplicitUnicodeExtra
-                                            ? ZipOutputStream.UnicodeExtraFieldPolicy.NEVER
-                                            : ZipOutputStream.UnicodeExtraFieldPolicy.ALWAYS);
+                    ? ZipOutputStream.UnicodeExtraFieldPolicy.NEVER
+                    : ZipOutputStream.UnicodeExtraFieldPolicy.ALWAYS);
 
             ZipEntry ze = new ZipEntry(OIL_BARREL_TXT);
             if (withExplicitUnicodeExtra
-                && !zipEncoding.canEncode(ze.getName())) {
+                    && !zipEncoding.canEncode(ze.getName())) {
 
                 ByteBuffer en = zipEncoding.encode(ze.getName());
 
                 ze.addExtraField(new UnicodePathExtraField(ze.getName(),
-                                                           en.array(),
-                                                           en.arrayOffset(),
-                                                           en.limit()));
+                        en.array(),
+                        en.arrayOffset(),
+                        en.limit()));
             }
 
             zos.putNextEntry(ze);
-            zos.write("Hello, world!".getBytes("US-ASCII"));
+            zos.write("Hello, world!".getBytes(StandardCharsets.US_ASCII));
             zos.closeEntry();
 
             ze = new ZipEntry(EURO_FOR_DOLLAR_TXT);
             if (withExplicitUnicodeExtra
-                && !zipEncoding.canEncode(ze.getName())) {
+                    && !zipEncoding.canEncode(ze.getName())) {
 
                 ByteBuffer en = zipEncoding.encode(ze.getName());
 
                 ze.addExtraField(new UnicodePathExtraField(ze.getName(),
-                                                           en.array(),
-                                                           en.arrayOffset(),
-                                                           en.limit()));
+                        en.array(),
+                        en.arrayOffset(),
+                        en.limit()));
             }
 
             zos.putNextEntry(ze);
-            zos.write("Give me your money!".getBytes("US-ASCII"));
+            zos.write("Give me your money!".getBytes(StandardCharsets.US_ASCII));
             zos.closeEntry();
 
             ze = new ZipEntry(ASCII_TXT);
 
             if (withExplicitUnicodeExtra
-                && !zipEncoding.canEncode(ze.getName())) {
+                    && !zipEncoding.canEncode(ze.getName())) {
 
                 ByteBuffer en = zipEncoding.encode(ze.getName());
 
                 ze.addExtraField(new UnicodePathExtraField(ze.getName(),
-                                                           en.array(),
-                                                           en.arrayOffset(),
-                                                           en.limit()));
+                        en.array(),
+                        en.arrayOffset(),
+                        en.limit()));
             }
 
             zos.putNextEntry(ze);
-            zos.write("ascii".getBytes("US-ASCII"));
+            zos.write("ascii".getBytes(StandardCharsets.US_ASCII));
             zos.closeEntry();
-        } finally {
-            if (zos != null) {
-                try {
-                    zos.close();
-                } catch (IOException e) {
-                    /* swallow */
-                }
-            }
         }
     }
 
@@ -199,11 +190,7 @@
         ZipFile zf = null;
         try {
             zf = new ZipFile(file, encoding, false);
-
-            Enumeration e = zf.getEntries();
-            while (e.hasMoreElements()) {
-                ZipEntry ze = (ZipEntry) e.nextElement();
-
+            for (ZipEntry ze : Collections.list(zf.getEntries())) {
                 if (ze.getName().endsWith("sser.txt")) {
                     assertUnicodeName(ze, OIL_BARREL_TXT, encoding);
 
@@ -239,20 +226,16 @@
             crc.update(ne.array(), ne.arrayOffset(), ne.limit());
 
             assertEquals(crc.getValue(), ucpf.getNameCRC32());
-            assertEquals(expectedName, new String(ucpf.getUnicodeName(),
-                                                  UTF_8));
+            assertEquals(expectedName, new String(ucpf.getUnicodeName(), StandardCharsets.UTF_8));
         }
     }
 
     private static void assertCanRead(ZipFile zf, String fileName) throws IOException {
         ZipEntry entry = zf.getEntry(fileName);
         assertNotNull("Entry " + fileName + " doesn't exist", entry);
-        InputStream is = zf.getInputStream(entry);
-        assertNotNull("InputStream is null", is);
-        try {
+        try (InputStream is = zf.getInputStream(entry)) {
+            assertNotNull("InputStream is null", is);
             is.read();
-        } finally {
-            is.close();
         }
     }
 
diff --git a/src/tests/junit/org/apache/tools/zip/ZipEncodingTest.java b/src/tests/junit/org/apache/tools/zip/ZipEncodingTest.java
index f05d553..a16ac83 100644
--- a/src/tests/junit/org/apache/tools/zip/ZipEncodingTest.java
+++ b/src/tests/junit/org/apache/tools/zip/ZipEncodingTest.java
@@ -7,7 +7,7 @@
  * "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
+ * https://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
@@ -21,10 +21,13 @@
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Test zip encodings.
@@ -133,16 +136,16 @@
 
         String decoded = enc.decode(testBytes);
 
-        assertEquals(true, enc.canEncode(decoded));
+        assertTrue(enc.canEncode(decoded));
 
         ByteBuffer encoded = enc.encode(decoded);
 
         assertByteEquals(testBytes, encoded);
 
-        assertEquals(false, enc.canEncode(UNENC_STRING));
-        assertByteEquals("%U2016".getBytes("US-ASCII"), enc.encode(UNENC_STRING));
-        assertEquals(false, enc.canEncode(BAD_STRING));
-        assertByteEquals(BAD_STRING_ENC.getBytes("US-ASCII"),
+        assertFalse(enc.canEncode(UNENC_STRING));
+        assertByteEquals("%U2016".getBytes(StandardCharsets.US_ASCII), enc.encode(UNENC_STRING));
+        assertFalse(enc.canEncode(BAD_STRING));
+        assertByteEquals(BAD_STRING_ENC.getBytes(StandardCharsets.US_ASCII),
                 enc.encode(BAD_STRING));
     }
 
diff --git a/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java b/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java
index fc30eca..d79b0e6 100644
--- a/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java
+++ b/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,20 +18,23 @@
 
 package org.apache.tools.zip;
 
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.util.NoSuchElementException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.fail;
 
 /**
  * JUnit 4 testcases for org.apache.tools.zip.ZipEntry.
  */
 public class ZipEntryTest {
 
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     /**
      * test handling of extra fields
@@ -80,12 +83,9 @@
         assertSame(u3, result[1]);
         assertEquals("length fourth pass", data2.length, data3.length);
 
-        try {
-            ze.removeExtraField(ExtraFieldUtilsTest.UNRECOGNIZED_HEADER);
-            fail("should be no such element");
-        } catch (NoSuchElementException nse) {
-            //TODO assert exception values
-        }
+        thrown.expect(NoSuchElementException.class);
+        //TODO assert exception values
+        ze.removeExtraField(ExtraFieldUtilsTest.UNRECOGNIZED_HEADER);
     }
 
     /**
@@ -203,14 +203,13 @@
 
     /**
      * Test case for
-     * <a href="https://issues.apache.org/jira/browse/COMPRESS-94"
-     * >COMPRESS-94</a>.
+     * <a href="https://issues.apache.org/jira/browse/COMPRESS-94">COMPRESS-94</a>
      */
     @Test
     public void testNotEquals() {
         ZipEntry entry1 = new ZipEntry("foo");
         ZipEntry entry2 = new ZipEntry("bar");
-        assertFalse(entry1.equals(entry2));
+        assertNotEquals(entry1, entry2);
     }
 
     @Test
diff --git a/src/tests/junit/org/apache/tools/zip/ZipLongTest.java b/src/tests/junit/org/apache/tools/zip/ZipLongTest.java
index 65ee505..6bbe184 100644
--- a/src/tests/junit/org/apache/tools/zip/ZipLongTest.java
+++ b/src/tests/junit/org/apache/tools/zip/ZipLongTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -22,7 +22,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotEquals;
 
 /**
  * JUnit testcases for org.apache.tools.zip.ZipLong.
@@ -63,15 +63,15 @@
         ZipLong zl2 = new ZipLong(0x12345678);
         ZipLong zl3 = new ZipLong(0x87654321);
 
-        assertTrue("reflexive", zl.equals(zl));
+        assertEquals("reflexive", zl, zl);
 
-        assertTrue("works", zl.equals(zl2));
-        assertTrue("works, part two", !zl.equals(zl3));
+        assertEquals("works", zl, zl2);
+        assertNotEquals("works, part two", zl, zl3);
 
-        assertTrue("symmetric", zl2.equals(zl));
+        assertEquals("symmetric", zl2, zl);
 
-        assertTrue("null handling", !zl.equals(null));
-        assertTrue("non ZipLong handling", !zl.equals(Integer.valueOf(0x1234)));
+        assertNotEquals("null handling", null, zl);
+        assertNotEquals("non ZipLong handling", 0x1234, zl);
     }
 
     /**
diff --git a/src/tests/junit/org/apache/tools/zip/ZipOutputStreamTest.java b/src/tests/junit/org/apache/tools/zip/ZipOutputStreamTest.java
index f41b246..0777630 100644
--- a/src/tests/junit/org/apache/tools/zip/ZipOutputStreamTest.java
+++ b/src/tests/junit/org/apache/tools/zip/ZipOutputStreamTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,8 +21,14 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.zip.ZipInputStream;
 
 import static org.junit.Assert.assertEquals;
 
@@ -32,7 +38,7 @@
     private ZipLong zl;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         time = new Date();
         Calendar cal = Calendar.getInstance();
         cal.setTime(time);
@@ -55,19 +61,33 @@
 
 
     @Test
-    public void testZipLong() throws Exception {
-        ZipLong test = ZipOutputStream.toDosTime(time);
+    public void testZipLong() {
+        ZipLong test = ZipUtil.toDosTime(time);
         assertEquals(test.getValue(), zl.getValue());
     }
 
     @Test
     public void testAdjustToLong() {
         assertEquals((long) Integer.MAX_VALUE,
-                     ZipOutputStream.adjustToLong(Integer.MAX_VALUE));
+                     ZipUtil.adjustToLong(Integer.MAX_VALUE));
         assertEquals(((long) Integer.MAX_VALUE) + 1,
-                     ZipOutputStream.adjustToLong(Integer.MAX_VALUE + 1));
+                     ZipUtil.adjustToLong(Integer.MAX_VALUE + 1));
         assertEquals(2 * ((long) Integer.MAX_VALUE),
-                     ZipOutputStream.adjustToLong(2 * Integer.MAX_VALUE));
+                     ZipUtil.adjustToLong(2 * Integer.MAX_VALUE));
     }
 
+    @Test
+    public void testWriteAndReadManifest() throws IOException {
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            try (ZipOutputStream zos = new ZipOutputStream(baos)) {
+                zos.putNextEntry(new ZipEntry(JarFile.MANIFEST_NAME));
+                new Manifest().write(zos);
+            }
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+                 ZipInputStream zis = new ZipInputStream(bais)) {
+                zis.getNextEntry();
+                zis.closeEntry();
+            }
+        }
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/zip/ZipShortTest.java b/src/tests/junit/org/apache/tools/zip/ZipShortTest.java
index 7efca58..e2ecea6 100644
--- a/src/tests/junit/org/apache/tools/zip/ZipShortTest.java
+++ b/src/tests/junit/org/apache/tools/zip/ZipShortTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,8 +21,8 @@
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
 
 /**
  * JUnit 4 testcases for org.apache.tools.zip.ZipShort.
@@ -60,15 +60,15 @@
         ZipShort zs2 = new ZipShort(0x1234);
         ZipShort zs3 = new ZipShort(0x5678);
 
-        assertTrue("reflexive", zs.equals(zs));
+        assertEquals("reflexive", zs, zs);
 
-        assertTrue("works", zs.equals(zs2));
-        assertTrue("works, part two", !zs.equals(zs3));
+        assertEquals("works", zs, zs2);
+        assertNotEquals("works, part two", zs, zs3);
 
-        assertTrue("symmetric", zs2.equals(zs));
+        assertEquals("symmetric", zs2, zs);
 
-        assertTrue("null handling", !zs.equals(null));
-        assertTrue("non ZipShort handling", !zs.equals(Integer.valueOf(0x1234)));
+        assertNotEquals("null handling", null, zs);
+        assertNotEquals("non ZipShort handling", 0x1234, zs);
     }
 
     /**
diff --git a/src/tests/junit/org/example/junit/AbstractJUnit3TestMissed.java b/src/tests/junit/org/example/junit/AbstractJUnit3TestMissed.java
index fd261f5..93de8c5 100644
--- a/src/tests/junit/org/example/junit/AbstractJUnit3TestMissed.java
+++ b/src/tests/junit/org/example/junit/AbstractJUnit3TestMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/AbstractJUnit3TestNotMissed.java b/src/tests/junit/org/example/junit/AbstractJUnit3TestNotMissed.java
index e1d1c0b..20fd9d5 100644
--- a/src/tests/junit/org/example/junit/AbstractJUnit3TestNotMissed.java
+++ b/src/tests/junit/org/example/junit/AbstractJUnit3TestNotMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/AbstractTestMissed.java b/src/tests/junit/org/example/junit/AbstractTestMissed.java
index 6724d5b..7ded913 100644
--- a/src/tests/junit/org/example/junit/AbstractTestMissed.java
+++ b/src/tests/junit/org/example/junit/AbstractTestMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/AbstractTestNotMissed.java b/src/tests/junit/org/example/junit/AbstractTestNotMissed.java
index 9a77d1b..ac9b299 100644
--- a/src/tests/junit/org/example/junit/AbstractTestNotMissed.java
+++ b/src/tests/junit/org/example/junit/AbstractTestNotMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/JUnit3NonTestMissed.java b/src/tests/junit/org/example/junit/JUnit3NonTestMissed.java
index 76cead6..405ea0e 100644
--- a/src/tests/junit/org/example/junit/JUnit3NonTestMissed.java
+++ b/src/tests/junit/org/example/junit/JUnit3NonTestMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/JUnit3TestNotMissed.java b/src/tests/junit/org/example/junit/JUnit3TestNotMissed.java
index 1e5ac2d..0d4dc18 100644
--- a/src/tests/junit/org/example/junit/JUnit3TestNotMissed.java
+++ b/src/tests/junit/org/example/junit/JUnit3TestNotMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/JUnit4Skippable.java b/src/tests/junit/org/example/junit/JUnit4Skippable.java
index aa89ab7..0e66492 100644
--- a/src/tests/junit/org/example/junit/JUnit4Skippable.java
+++ b/src/tests/junit/org/example/junit/JUnit4Skippable.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -18,12 +18,12 @@
 
 package org.example.junit;
 
-import org.junit.Assume;
 import org.junit.Ignore;
 import org.junit.Test;
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 
 public class JUnit4Skippable {
 
@@ -40,7 +40,7 @@
 
     @Test
     public void implicitlyIgnoreTest() {
-        Assume.assumeFalse("This test will be ignored", true);
+        assumeFalse("This test will be ignored", true);
         fail("I told you, this test should have been ignored!");
     }
 
@@ -52,7 +52,7 @@
 
     @Test
     public void implicitlyIgnoreTestNoMessage() {
-        Assume.assumeFalse(true);
+        assumeFalse(true);
         fail("I told you, this test should have been ignored!");
     }
 
diff --git a/src/tests/junit/org/example/junit/MultilineAsserts.java b/src/tests/junit/org/example/junit/MultilineAsserts.java
index be68ec6..75e307f 100644
--- a/src/tests/junit/org/example/junit/MultilineAsserts.java
+++ b/src/tests/junit/org/example/junit/MultilineAsserts.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -21,13 +21,13 @@
 
 public class MultilineAsserts extends TestCase {
     public void testFoo() {
-        assertTrue("testFoo \nmessed up", false);
+        fail("testFoo \nmessed up");
     }
     public void testBar() {
         assertTrue("testBar \ndidn't work", true);
     }
     public void testFee() {
-        assertTrue("testFee \ncrashed", false);
+        fail("testFee \ncrashed");
     }
     public void testFie() {
         assertTrue("testFie \nbroke", true);
diff --git a/src/tests/junit/org/example/junit/NonTestMissed.java b/src/tests/junit/org/example/junit/NonTestMissed.java
index 0a020ec..9be0f2c 100644
--- a/src/tests/junit/org/example/junit/NonTestMissed.java
+++ b/src/tests/junit/org/example/junit/NonTestMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/Output.java b/src/tests/junit/org/example/junit/Output.java
index a7135f7..416b67e 100644
--- a/src/tests/junit/org/example/junit/Output.java
+++ b/src/tests/junit/org/example/junit/Output.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/TestNotMissed.java b/src/tests/junit/org/example/junit/TestNotMissed.java
index 41b722f..942e2c3 100644
--- a/src/tests/junit/org/example/junit/TestNotMissed.java
+++ b/src/tests/junit/org/example/junit/TestNotMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/TestWithSuiteNotMissed.java b/src/tests/junit/org/example/junit/TestWithSuiteNotMissed.java
index 80b722c..40632c5 100644
--- a/src/tests/junit/org/example/junit/TestWithSuiteNotMissed.java
+++ b/src/tests/junit/org/example/junit/TestWithSuiteNotMissed.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/ThreadedOutput.java b/src/tests/junit/org/example/junit/ThreadedOutput.java
index 91f462a..21f7507 100644
--- a/src/tests/junit/org/example/junit/ThreadedOutput.java
+++ b/src/tests/junit/org/example/junit/ThreadedOutput.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -32,11 +32,7 @@
     }
 
     public void testOutput() throws InterruptedException {
-        Thread t = new Thread(new Runnable() {
-                public void run() {
-                    System.out.println("foo");
-                }
-            });
+        Thread t = new Thread(() -> System.out.println("foo"));
         t.start();
         t.join();
     }
diff --git a/src/tests/junit/org/example/junit/Timeout.java b/src/tests/junit/org/example/junit/Timeout.java
index 6a42ee7..1c0ec51 100644
--- a/src/tests/junit/org/example/junit/Timeout.java
+++ b/src/tests/junit/org/example/junit/Timeout.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junit/XmlParserTest.java b/src/tests/junit/org/example/junit/XmlParserTest.java
index e5fae55..4475c26 100644
--- a/src/tests/junit/org/example/junit/XmlParserTest.java
+++ b/src/tests/junit/org/example/junit/XmlParserTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/junitlauncher/Tracker.java b/src/tests/junit/org/example/junitlauncher/Tracker.java
new file mode 100644
index 0000000..807da05
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/Tracker.java
@@ -0,0 +1,171 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher;
+
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.TestExecutionContext;
+import org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter;
+import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.engine.support.descriptor.MethodSource;
+import org.junit.platform.launcher.TestIdentifier;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.List;
+
+/**
+ * Utility listener used in {@link org.apache.tools.ant.taskdefs.optional.junitlauncher.JUnitLauncherTaskTest}
+ * to verify that tests launched through junitlauncher task are executed as expected
+ */
+public class Tracker implements TestResultFormatter {
+
+    private static final String PREFIX_TEST_CLASS_STARTED = "started:test-class:";
+    private static final String PREFIX_TEST_METHOD_STARTED = "started:test-method:";
+    private static final String PREFIX_TEST_CLASS_SKIPPED = "skipped:test-class:";
+    private static final String PREFIX_TEST_METHOD_SKIPPED = "skipped:test-method:";
+
+    private PrintWriter writer;
+    private TestExecutionContext context;
+    private OutputStream appendModeFile;
+
+    @Override
+    public void setDestination(final OutputStream os) {
+        final String propVal = this.context.getProperties().getProperty("junitlauncher.test.tracker.append.file");
+        if (propVal == null) {
+            this.writer = new PrintWriter(os, true);
+            return;
+        }
+        // ignore the passed outputstream and instead create our own, in append mode
+        final Path appendModeFilePath = Paths.get(propVal);
+        try {
+            this.appendModeFile = Files.newOutputStream(appendModeFilePath, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
+            this.writer = new PrintWriter(this.appendModeFile, true);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void setContext(final TestExecutionContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public void setUseLegacyReportingName(final boolean useLegacyReportingName) {
+        // do nothing
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.writer.flush();
+        if (this.appendModeFile != null) {
+            this.appendModeFile.close();
+        }
+    }
+
+    @Override
+    public void executionStarted(final TestIdentifier testIdentifier) {
+        testIdentifier.getSource().ifPresent((s) -> {
+            if (s instanceof MethodSource) {
+                writer.println(PREFIX_TEST_METHOD_STARTED + ((MethodSource) s).getClassName()
+                        + "#" + ((MethodSource) s).getMethodName());
+                return;
+            }
+            if (s instanceof ClassSource) {
+                writer.println(PREFIX_TEST_CLASS_STARTED + ((ClassSource) s).getClassName());
+                return;
+            }
+
+        });
+    }
+
+    @Override
+    public void executionFinished(final TestIdentifier testIdentifier, final TestExecutionResult testExecutionResult) {
+        testIdentifier.getSource().ifPresent((s) -> {
+            if (s instanceof MethodSource) {
+                writer.println(testExecutionResult.getStatus().name() + ":test-method:" + ((MethodSource) s).getClassName()
+                        + "#" + ((MethodSource) s).getMethodName());
+                return;
+            }
+            if (s instanceof ClassSource) {
+                writer.println(testExecutionResult.getStatus().name() + ":test-class:" + ((ClassSource) s).getClassName());
+                return;
+            }
+
+        });
+    }
+
+    @Override
+    public void executionSkipped(final TestIdentifier testIdentifier, final String reason) {
+        testIdentifier.getSource().ifPresent((s) -> {
+            if (s instanceof MethodSource) {
+                writer.println(PREFIX_TEST_METHOD_SKIPPED + ((MethodSource) s).getClassName() + "#"
+                        + ((MethodSource) s).getMethodName());
+                return;
+            }
+            if (s instanceof ClassSource) {
+                writer.println(PREFIX_TEST_CLASS_SKIPPED + ((ClassSource) s).getClassName());
+                return;
+            }
+
+        });
+    }
+
+    public static boolean wasTestRun(final Path trackerFile, final String className) throws IOException {
+        final List<String> lines = readTrackerFile(trackerFile);
+        return lines.contains(PREFIX_TEST_CLASS_STARTED + className);
+    }
+
+    public static boolean wasTestRun(final Path trackerFile, final String className, final String methodName) throws IOException {
+        final List<String> lines = readTrackerFile(trackerFile);
+        return lines.contains(PREFIX_TEST_METHOD_STARTED + className + "#" + methodName);
+    }
+
+    public static boolean verifyFailed(final Path trackerFile, final String className, final String methodName) throws IOException {
+        final List<String> lines = readTrackerFile(trackerFile);
+        return lines.contains(TestExecutionResult.Status.FAILED + ":test-method:" + className + "#" + methodName);
+    }
+    
+    public static boolean verifySetupFailed(final Path trackerFile, final String className) throws IOException {
+        final List<String> lines = readTrackerFile(trackerFile);
+        return lines.contains(TestExecutionResult.Status.FAILED + ":test-class:" + className);
+    }
+
+    public static boolean verifySuccess(final Path trackerFile, final String className, final String methodName) throws IOException {
+        final List<String> lines = readTrackerFile(trackerFile);
+        return lines.contains(TestExecutionResult.Status.SUCCESSFUL + ":test-method:" + className + "#" + methodName);
+    }
+
+    public static boolean verifySkipped(final Path trackerFile, final String className, final String methodName) throws IOException {
+        final List<String> lines = readTrackerFile(trackerFile);
+        return lines.contains(PREFIX_TEST_METHOD_SKIPPED + className + "#" + methodName);
+    }
+
+    private static List<String> readTrackerFile(final Path trackerFile) throws IOException {
+        if (!Files.isRegularFile(trackerFile)) {
+            throw new RuntimeException(trackerFile + " is either missing or not a file");
+        }
+        return Files.readAllLines(trackerFile);
+    }
+}
diff --git a/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTest.java b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTest.java
new file mode 100644
index 0000000..7803512
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher.jupiter;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ *
+ */
+public class JupiterSampleTest {
+
+    private static final String message = "The quick brown fox jumps over the lazy dog";
+
+    @BeforeAll
+    static void beforeAll() {
+    }
+
+    @BeforeEach
+    void beforeEach() {
+    }
+
+    @Test
+    void testSucceeds() {
+        System.out.println(message);
+        System.out.print("<some-other-message>Hello world! <!-- some comment --></some-other-message>");
+    }
+
+    @Test
+    void testFails() {
+        fail("intentionally failing");
+    }
+
+    @Test
+    @Disabled("intentionally skipped")
+    void testSkipped() {
+    }
+
+    @Test
+    @Tag("fast")
+    void testMethodIncludeTagisExecuted() {
+    }
+
+    @Test
+    @Tag("fast")
+    void testMethodIncludeTagisExecuted2() {
+    }
+
+    @Test
+    @Tag("slow")
+    void testMethodIncludeTagisNotExecuted() {
+    }
+
+    @AfterEach
+    void afterEach() {
+    }
+
+    @AfterAll
+    static void afterAll() {
+    }
+}
diff --git a/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTestFailingBeforeAll.java b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTestFailingBeforeAll.java
new file mode 100644
index 0000000..d42e703
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTestFailingBeforeAll.java
@@ -0,0 +1,55 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher.jupiter;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ */
+public class JupiterSampleTestFailingBeforeAll {
+
+    private static final String message = "The quick brown fox jumps over the lazy dog";
+
+    @BeforeAll
+    static void beforeAll() {
+    	throw new RuntimeException("Intentional failure");
+    }
+
+    @BeforeEach
+    void beforeEach() {
+    }
+
+    @Test
+    void testSucceeds() {
+        System.out.println(message);
+        System.out.print("<some-other-message>Hello world! <!-- some comment --></some-other-message>");
+    }
+
+    @AfterEach
+    void afterEach() {
+    }
+
+    @AfterAll
+    static void afterAll() {
+    }
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTestFailingStatic.java
similarity index 65%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTestFailingStatic.java
index 9d6fcba..2c88d66 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterSampleTestFailingStatic.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,25 @@
  *  limitations under the License.
  *
  */
+package org.example.junitlauncher.jupiter;
+
+import org.junit.jupiter.api.Test;
+
 /**
+ *
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+public class JupiterSampleTestFailingStatic {
+
+    static {
+        if (true) {
+            throw new RuntimeException("Intentional exception from static init block");
+        }
+    }
+
+
+    @Test
+    void testSucceeds() {
+        System.out.println("hello");
+    }
+
 }
diff --git a/src/tests/junit/org/example/junitlauncher/jupiter/JupiterTagSampleTest.java b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterTagSampleTest.java
new file mode 100644
index 0000000..0f1916a
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterTagSampleTest.java
@@ -0,0 +1,63 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher.jupiter;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ */
+public class JupiterTagSampleTest {
+
+    @BeforeAll
+    static void beforeAll() {
+    }
+
+    @BeforeEach
+    void beforeEach() {
+    }
+
+    @Test
+    @Tag("fast")
+    void testMethodIncludeTagisExecutedTagSampleTest() {
+    }
+
+    @Test
+    @Tag("slow")
+    void testMethodIncludeTagisNotExecutedTagSampleTest() {
+    }
+
+    @Test
+    @Tag("extraSlow")
+    void testMethodIncludeTagisNotExecuted2TagSampleTest() {
+    }
+
+
+    @AfterEach
+    void afterEach() {
+    }
+
+    @AfterAll
+    static void afterAll() {
+    }
+}
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tests/junit/org/example/junitlauncher/vintage/AlwaysFailingJUnit4Test.java
similarity index 70%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tests/junit/org/example/junitlauncher/vintage/AlwaysFailingJUnit4Test.java
index 9d6fcba..1887eb8 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tests/junit/org/example/junitlauncher/vintage/AlwaysFailingJUnit4Test.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,19 @@
  *  limitations under the License.
  *
  */
+package org.example.junitlauncher.vintage;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
 /**
+ *
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+public class AlwaysFailingJUnit4Test {
+
+    @Test
+    public void testWillFail() {
+        assertEquals("Values weren't equal", 3, 4);
+    }
 }
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tests/junit/org/example/junitlauncher/vintage/ForkedTest.java
similarity index 63%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tests/junit/org/example/junitlauncher/vintage/ForkedTest.java
index 9d6fcba..2f432e5 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tests/junit/org/example/junitlauncher/vintage/ForkedTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,23 @@
  *  limitations under the License.
  *
  */
+
+package org.example.junitlauncher.vintage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
 /**
+ *
  */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+public class ForkedTest {
+
+    public static String SYS_PROP_ONE = "junitlauncher.test.sysprop.one";
+
+
+    @Test
+    public void testSysProp() {
+        Assert.assertEquals("Unexpected value for system property",
+                "forked", System.getProperty(SYS_PROP_ONE));
+    }
 }
diff --git a/src/tests/junit/org/example/junitlauncher/vintage/JUnit4SampleTest.java b/src/tests/junit/org/example/junitlauncher/vintage/JUnit4SampleTest.java
new file mode 100644
index 0000000..bdd6291
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/vintage/JUnit4SampleTest.java
@@ -0,0 +1,45 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher.vintage;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class JUnit4SampleTest {
+
+    @Test
+    public void testFoo() {
+        assertEquals(1, 1);
+    }
+
+    @Test
+    public void testBar() {
+        assertTrue(true);
+    }
+
+    @Test
+    public void testFooBar() {
+        assertFalse(false);
+    }
+}
diff --git a/src/tests/junit/org/example/tasks/TaskdefTestContainerTask.java b/src/tests/junit/org/example/tasks/TaskdefTestContainerTask.java
index 960ad72..cfd98b9 100644
--- a/src/tests/junit/org/example/tasks/TaskdefTestContainerTask.java
+++ b/src/tests/junit/org/example/tasks/TaskdefTestContainerTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/tasks/TaskdefTestSimpleTask.java b/src/tests/junit/org/example/tasks/TaskdefTestSimpleTask.java
index 4adad93..11fde79 100644
--- a/src/tests/junit/org/example/tasks/TaskdefTestSimpleTask.java
+++ b/src/tests/junit/org/example/tasks/TaskdefTestSimpleTask.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tests/junit/org/example/tasks/antlib.xml b/src/tests/junit/org/example/tasks/antlib.xml
index b920da7..47bb6a4 100644
--- a/src/tests/junit/org/example/tasks/antlib.xml
+++ b/src/tests/junit/org/example/tasks/antlib.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/junit/org/example/tasks/antlib2.xml b/src/tests/junit/org/example/tasks/antlib2.xml
index b920da7..47bb6a4 100644
--- a/src/tests/junit/org/example/tasks/antlib2.xml
+++ b/src/tests/junit/org/example/tasks/antlib2.xml
@@ -7,7 +7,7 @@
   (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
+      https://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,
diff --git a/src/tests/junit/org/example/types/TypedefTestType.java b/src/tests/junit/org/example/types/TypedefTestType.java
index c031422..3660b15 100644
--- a/src/tests/junit/org/example/types/TypedefTestType.java
+++ b/src/tests/junit/org/example/types/TypedefTestType.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
diff --git a/src/tutorial/hello-world/01-simple/build.xml b/src/tutorial/hello-world/01-simple/build.xml
new file mode 100644
index 0000000..ff896c1
--- /dev/null
+++ b/src/tutorial/hello-world/01-simple/build.xml
@@ -0,0 +1,55 @@
+<?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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="HelloWorld" basedir="." default="main">
+
+    <property name="src.dir"     value="src"/>
+
+    <property name="build.dir"   value="build"/>
+    <property name="classes.dir" value="${build.dir}/classes"/>
+    <property name="jar.dir"     value="${build.dir}/jar"/>
+
+    <property name="main-class"  value="oata.HelloWorld"/>
+
+    <target name="clean">
+        <delete dir="${build.dir}"/>
+    </target>
+
+    <target name="compile">
+        <mkdir dir="${classes.dir}"/>
+        <javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}"/>
+    </target>
+
+    <target name="jar" depends="compile">
+        <mkdir dir="${jar.dir}"/>
+        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
+            <manifest>
+                <attribute name="Main-Class" value="${main-class}"/>
+            </manifest>
+        </jar>
+    </target>
+
+    <target name="run" depends="jar">
+        <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/>
+    </target>
+
+    <target name="clean-build" depends="clean,jar"/>
+
+    <target name="main" depends="clean,run"/>
+
+</project>
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tutorial/hello-world/01-simple/src/oata/HelloWorld.java
similarity index 79%
rename from src/tests/antunit/taskdefs/apt/AptExample.java
rename to src/tutorial/hello-world/01-simple/src/oata/HelloWorld.java
index 9d6fcba..17f2d9f 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tutorial/hello-world/01-simple/src/oata/HelloWorld.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,10 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package oata;
+
+public class HelloWorld {
+    public static void main(String[] args) {
+        System.out.println("Hello World");
+    }
 }
diff --git a/src/tutorial/hello-world/02-logging/build.xml b/src/tutorial/hello-world/02-logging/build.xml
new file mode 100644
index 0000000..3544aa6
--- /dev/null
+++ b/src/tutorial/hello-world/02-logging/build.xml
@@ -0,0 +1,65 @@
+<?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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="HelloWorld" basedir="." default="main">
+
+    <property name="src.dir"     value="src"/>
+
+    <property name="build.dir"   value="build"/>
+    <property name="classes.dir" value="${build.dir}/classes"/>
+    <property name="jar.dir"     value="${build.dir}/jar"/>
+    <property name="lib.dir"     value="lib"/>
+
+    <path id="classpath">
+        <fileset dir="${lib.dir}" includes="**/*.jar"/>
+    </path>
+
+    <property name="main-class"  value="oata.HelloWorld"/>
+
+    <target name="clean">
+        <delete dir="${build.dir}"/>
+    </target>
+
+    <target name="compile">
+        <mkdir dir="${classes.dir}"/>
+        <javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
+    </target>
+
+    <target name="jar" depends="compile">
+        <mkdir dir="${jar.dir}"/>
+        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
+            <manifest>
+                <attribute name="Main-Class" value="${main-class}"/>
+            </manifest>
+        </jar>
+    </target>
+
+    <target name="run" depends="jar">
+        <java classname="${main-class}" fork="true">
+            <classpath>
+                <path refid="classpath"/>
+                <path location="${jar.dir}/${ant.project.name}.jar"/>
+            </classpath>
+        </java>
+    </target>
+
+    <target name="clean-build" depends="clean,jar"/>
+
+    <target name="main" depends="clean,run"/>
+
+</project>
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tutorial/hello-world/02-logging/src/oata/HelloWorld.java
similarity index 65%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tutorial/hello-world/02-logging/src/oata/HelloWorld.java
index 9d6fcba..b14f999 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tutorial/hello-world/02-logging/src/oata/HelloWorld.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,16 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package oata;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.BasicConfigurator;
+
+public class HelloWorld {
+    static Logger logger = Logger.getLogger(HelloWorld.class);
+
+    public static void main(String[] args) {
+        BasicConfigurator.configure();
+        logger.info("Hello World");          // the old System.out-statement
+    }
 }
diff --git a/src/tutorial/hello-world/03-testing/build.xml b/src/tutorial/hello-world/03-testing/build.xml
new file mode 100644
index 0000000..a77a725
--- /dev/null
+++ b/src/tutorial/hello-world/03-testing/build.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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="HelloWorld" basedir="." default="main">
+
+    <property name="src.dir"     value="src"/>
+
+    <property name="build.dir"   value="build"/>
+    <property name="classes.dir" value="${build.dir}/classes"/>
+    <property name="jar.dir"     value="${build.dir}/jar"/>
+    <property name="lib.dir"     value="lib"/>
+
+    <path id="application" location="${jar.dir}/${ant.project.name}.jar"/>
+    <path id="classpath">
+        <fileset dir="${lib.dir}" includes="**/*.jar"/>
+    </path>
+
+    <property name="main-class"  value="oata.HelloWorld"/>
+
+    <target name="clean">
+        <delete dir="${build.dir}"/>
+    </target>
+
+    <target name="compile">
+        <mkdir dir="${classes.dir}"/>
+        <javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
+        <copy todir="${classes.dir}">
+            <fileset dir="${src.dir}" excludes="**/*.java"/>
+        </copy>
+    </target>
+
+    <target name="jar" depends="compile">
+        <mkdir dir="${jar.dir}"/>
+        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
+            <manifest>
+                <attribute name="Main-Class" value="${main-class}"/>
+            </manifest>
+        </jar>
+    </target>
+
+    <target name="run" depends="jar">
+        <java classname="${main-class}" fork="true">
+            <classpath>
+                <path refid="classpath"/>
+                <path refid="application"/>
+            </classpath>
+        </java>
+    </target>
+
+    <target name="junit" depends="jar">
+        <junit printsummary="yes">
+            <classpath>
+                <path refid="classpath"/>
+                <path refid="application"/>
+            </classpath>
+
+            <batchtest fork="yes">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="clean-build" depends="clean,jar"/>
+
+    <target name="main" depends="clean,run"/>
+
+</project>
diff --git a/src/tutorial/hello-world/03-testing/src/log4j.properties b/src/tutorial/hello-world/03-testing/src/log4j.properties
new file mode 100644
index 0000000..4fb02a9
--- /dev/null
+++ b/src/tutorial/hello-world/03-testing/src/log4j.properties
@@ -0,0 +1,20 @@
+# 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
+#
+#     https://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.
+log4j.rootLogger=DEBUG, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%m%n
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tutorial/hello-world/03-testing/src/oata/HelloWorld.java
similarity index 70%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tutorial/hello-world/03-testing/src/oata/HelloWorld.java
index 9d6fcba..3c34f15 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tutorial/hello-world/03-testing/src/oata/HelloWorld.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,14 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package oata;
+
+import org.apache.log4j.Logger;
+
+public class HelloWorld {
+    static Logger logger = Logger.getLogger(HelloWorld.class);
+
+    public static void main(String[] args) {
+        logger.info("Hello World");          // the old System.out-statement
+    }
 }
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tutorial/hello-world/03-testing/src/oata/HelloWorldTest.java
similarity index 71%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tutorial/hello-world/03-testing/src/oata/HelloWorldTest.java
index 9d6fcba..fc8a100 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tutorial/hello-world/03-testing/src/oata/HelloWorldTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,21 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package oata;
+
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest {
+
+    @Test
+    public void testNothing() {
+    }
+
+    @Test
+    public void testWillAlwaysFail() {
+        fail("An error message");
+    }
+
 }
diff --git a/src/tutorial/hello-world/final/build.xml b/src/tutorial/hello-world/final/build.xml
new file mode 100644
index 0000000..87eb9a8
--- /dev/null
+++ b/src/tutorial/hello-world/final/build.xml
@@ -0,0 +1,93 @@
+<?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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="HelloWorld" basedir="." default="main">
+
+    <property name="src.dir"     value="src"/>
+
+    <property name="build.dir"   value="build"/>
+    <property name="classes.dir" value="${build.dir}/classes"/>
+    <property name="jar.dir"     value="${build.dir}/jar"/>
+    <property name="lib.dir"     value="lib"/>
+    <property name="report.dir"  value="${build.dir}/junitreport"/>
+
+    <path id="application" location="${jar.dir}/${ant.project.name}.jar"/>
+    <path id="classpath">
+        <fileset dir="${lib.dir}" includes="**/*.jar"/>
+    </path>
+
+    <property name="main-class"  value="oata.HelloWorld"/>
+
+    <target name="clean">
+        <delete dir="${build.dir}"/>
+    </target>
+
+    <target name="compile">
+        <mkdir dir="${classes.dir}"/>
+        <javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
+        <copy todir="${classes.dir}">
+            <fileset dir="${src.dir}" excludes="**/*.java"/>
+        </copy>
+    </target>
+
+    <target name="jar" depends="compile">
+        <mkdir dir="${jar.dir}"/>
+        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
+            <manifest>
+                <attribute name="Main-Class" value="${main-class}"/>
+            </manifest>
+        </jar>
+    </target>
+
+    <target name="run" depends="jar">
+        <java classname="${main-class}" fork="true">
+            <classpath>
+                <path refid="classpath"/>
+                <path refid="application"/>
+            </classpath>
+        </java>
+    </target>
+
+    <target name="junit" depends="jar">
+        <mkdir dir="${report.dir}"/>
+        <junit printsummary="yes" tempdir="${build.dir}">
+            <classpath>
+                <path refid="classpath"/>
+                <path refid="application"/>
+            </classpath>
+
+            <formatter type="xml"/>
+
+            <batchtest fork="yes" todir="${report.dir}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport">
+        <junitreport todir="${report.dir}">
+            <fileset dir="${report.dir}" includes="TEST-*.xml"/>
+            <report todir="${report.dir}"/>
+        </junitreport>
+    </target>
+
+    <target name="clean-build" depends="clean,jar"/>
+
+    <target name="main" depends="clean,run"/>
+
+</project>
diff --git a/src/tutorial/hello-world/final/src/log4j.properties b/src/tutorial/hello-world/final/src/log4j.properties
new file mode 100644
index 0000000..4fb02a9
--- /dev/null
+++ b/src/tutorial/hello-world/final/src/log4j.properties
@@ -0,0 +1,20 @@
+# 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
+#
+#     https://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.
+log4j.rootLogger=DEBUG, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%m%n
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tutorial/hello-world/final/src/oata/HelloWorld.java
similarity index 70%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tutorial/hello-world/final/src/oata/HelloWorld.java
index 9d6fcba..3c34f15 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tutorial/hello-world/final/src/oata/HelloWorld.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,14 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package oata;
+
+import org.apache.log4j.Logger;
+
+public class HelloWorld {
+    static Logger logger = Logger.getLogger(HelloWorld.class);
+
+    public static void main(String[] args) {
+        logger.info("Hello World");          // the old System.out-statement
+    }
 }
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tutorial/hello-world/final/src/oata/HelloWorldTest.java
similarity index 71%
copy from src/tests/antunit/taskdefs/apt/AptExample.java
copy to src/tutorial/hello-world/final/src/oata/HelloWorldTest.java
index 9d6fcba..fc8a100 100644
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ b/src/tutorial/hello-world/final/src/oata/HelloWorldTest.java
@@ -6,7 +6,7 @@
  *  (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
+ *      https://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,
@@ -15,11 +15,21 @@
  *  limitations under the License.
  *
  */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
+package oata;
+
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest {
+
+    @Test
+    public void testNothing() {
+    }
+
+    @Test
+    public void testWillAlwaysFail() {
+        fail("An error message");
+    }
+
 }
diff --git a/src/tutorial/tasks-filesets-properties/01-propertyaccess/build.xml b/src/tutorial/tasks-filesets-properties/01-propertyaccess/build.xml
new file mode 100644
index 0000000..ec18137
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/01-propertyaccess/build.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="FindTask" basedir="." default="test">
+
+    <property name="src.dir"     value="src"/>
+    <property name="classes.dir" value="classes"/>
+
+    <property name="ant.test.lib" value="ant-testutil.jar"/>
+    <property name="report.dir"   value="report"/>
+    <property name="junit.out.dir.xml"  value="${report.dir}/junit/xml"/>
+    <property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
+
+    <path id="classpath.run">
+        <path path="${java.class.path}"/>
+        <path location="${ant.project.name}.jar"/>
+    </path>
+
+    <path id="classpath.test">
+        <path refid="classpath.run"/>
+        <path location="${ant.test.lib}"/>
+    </path>
+
+    <target name="clean" description="Delete all generated files">
+        <delete failonerror="false" includeEmptyDirs="true">
+            <fileset dir="." includes="${ant.project.name}.jar"/>
+            <fileset dir="${classes.dir}"/>
+            <fileset dir="${report.dir}"/>
+        </delete>
+    </target>
+
+    <target name="compile" description="Compiles the Task">
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpath="${ant.test.lib}"/>
+    </target>
+
+    <target name="jar" description="JARs the Task" depends="compile">
+        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
+    </target>
+
+    <target name="use.init" description="Taskdef the Find-Task" depends="jar">
+        <taskdef name="find" classname="Find" classpath="${ant.project.name}.jar"/>
+    </target>
+
+    <target name="use.simple" depends="use.init">
+        <find property="test" value="test-value"/>
+        <find print="test"/>
+    </target>
+
+    <target name="junit" description="Runs the unit tests" depends="jar">
+        <delete dir="${junit.out.dir.xml}" />
+        <mkdir  dir="${junit.out.dir.xml}" />
+        <junit printsummary="yes" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <formatter type="xml"/>
+            <batchtest fork="yes" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport" description="Create a report for the rest result">
+        <mkdir dir="${junit.out.dir.html}" />
+        <junitreport todir="${junit.out.dir.html}">
+            <fileset dir="${junit.out.dir.xml}">
+                <include name="*.xml"/>
+            </fileset>
+            <report format="frames" todir="${junit.out.dir.html}"/>
+        </junitreport>
+    </target>
+
+    <target name="test"
+            depends="junit,junitreport"
+            description="Runs unit tests and creates a report"/>
+
+</project>
diff --git a/src/tutorial/tasks-filesets-properties/01-propertyaccess/src/Find.java b/src/tutorial/tasks-filesets-properties/01-propertyaccess/src/Find.java
new file mode 100644
index 0000000..15c766d
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/01-propertyaccess/src/Find.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
+ *
+ *      https://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 org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+
+public class Find extends Task {
+
+    private String property;
+    private String value;
+    private String print;
+
+    public void setProperty(String property) {
+        this.property = property;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public void setPrint(String print) {
+        this.print = print;
+    }
+
+    public void execute() {
+        if (print != null) {
+            String propValue = getProject().getProperty(print);
+            log(propValue);
+        } else {
+            if (property == null) throw new BuildException("property not set");
+            if (value    == null) throw new BuildException("value not set");
+            getProject().setNewProperty(property, value);
+        }
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/01-propertyaccess/src/FindTest.java b/src/tutorial/tasks-filesets-properties/01-propertyaccess/src/FindTest.java
new file mode 100644
index 0000000..e3a53f2
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/01-propertyaccess/src/FindTest.java
@@ -0,0 +1,40 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class FindTest {
+
+    @Rule
+    public BuildFileRule rule = new BuildFileRule();
+
+    @Before
+    public void setUp() {
+        rule.configureProject("build.xml");
+    }
+
+    @Test
+    public void testSimple() {
+        rule.executeTarget("use.simple");
+        assertEquals("test-value", rule.getLog());
+    }
+}
diff --git a/src/tutorial/tasks-filesets-properties/02-fileset/build.xml b/src/tutorial/tasks-filesets-properties/02-fileset/build.xml
new file mode 100644
index 0000000..0a575d7
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/02-fileset/build.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="FindTask" basedir="." default="test">
+
+    <property name="src.dir"     value="src"/>
+    <property name="classes.dir" value="classes"/>
+
+    <property name="ant.test.lib" value="ant-testutil.jar"/>
+    <property name="report.dir"   value="report"/>
+    <property name="junit.out.dir.xml"  value="${report.dir}/junit/xml"/>
+    <property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
+
+    <path id="classpath.run">
+        <path path="${java.class.path}"/>
+        <path location="${ant.project.name}.jar"/>
+    </path>
+
+    <path id="classpath.test">
+        <path refid="classpath.run"/>
+        <path location="${ant.test.lib}"/>
+    </path>
+
+    <target name="clean" description="Delete all generated files">
+        <delete failonerror="false" includeEmptyDirs="true">
+            <fileset dir="." includes="${ant.project.name}.jar"/>
+            <fileset dir="${classes.dir}"/>
+            <fileset dir="${report.dir}"/>
+        </delete>
+    </target>
+
+    <target name="compile" description="Compiles the Task">
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpath="${ant.test.lib}"/>
+    </target>
+
+    <target name="jar" description="JARs the Task" depends="compile">
+        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
+    </target>
+
+    <target name="use.init" description="Taskdef the Find-Task" depends="jar">
+        <taskdef name="find" classname="Find" classpath="${ant.project.name}.jar"/>
+    </target>
+
+    <target name="use.simple" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <fileset dir="${ant.home}" includes="**/*.jar"/>
+        </find>
+    </target>
+
+    <target name="testFileNotPresent" depends="use.init">
+        <find file="a-not-existing-file.jar" location="location.ant-jar">
+            <fileset dir="${ant.home}" includes="**/*.jar"/>
+        </find>
+    </target>
+
+    <target name="testFilePresent" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <fileset dir="${ant.home}" includes="**/*.jar"/>
+        </find>
+    </target>
+
+    <target name="junit" description="Runs the unit tests" depends="jar">
+        <delete dir="${junit.out.dir.xml}" />
+        <mkdir  dir="${junit.out.dir.xml}" />
+        <junit printsummary="yes" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="xml"/>
+            <batchtest fork="yes" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport" description="Create a report for the rest result">
+        <mkdir dir="${junit.out.dir.html}" />
+        <junitreport todir="${junit.out.dir.html}">
+            <fileset dir="${junit.out.dir.xml}">
+                <include name="*.xml"/>
+            </fileset>
+            <report format="frames" todir="${junit.out.dir.html}"/>
+        </junitreport>
+    </target>
+
+    <target name="test" depends="jar">
+        <junit printsummary="no" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="brief" usefile="false"/>
+            <batchtest fork="true" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test2"
+            depends="junit,junitreport"
+            description="Runs unit tests and creates a report"/>
+
+</project>
diff --git a/src/tutorial/tasks-filesets-properties/02-fileset/src/Find.java b/src/tutorial/tasks-filesets-properties/02-fileset/src/Find.java
new file mode 100644
index 0000000..922aec2
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/02-fileset/src/Find.java
@@ -0,0 +1,70 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.DirectoryScanner;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+
+public class Find extends Task {
+
+    private String file;
+    private String location;
+    private List<FileSet> filesets = new ArrayList<>();
+
+    public void setFile(String file) {
+        this.file = file;
+    }
+
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    public void addFileset(FileSet fileset) {
+        filesets.add(fileset);
+    }
+
+    protected void validate() {
+        if (file == null) throw new BuildException("file not set");
+        if (location == null) throw new BuildException("location not set");
+        if (filesets.size() < 1) throw new BuildException("fileset not set");
+    }
+
+    public void execute2() {
+        validate();
+        String foundLocation = null;
+        for (FileSet fs : filesets) {
+            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+            File base  = ds.getBasedir();
+            for (String includedFile : ds.getIncludedFiles()) {
+                String filename = includedFile.replace('\\','/');
+                filename = filename.substring(filename.lastIndexOf("/") + 1);
+                if (foundLocation == null && file.equals(filename)) {
+                    File found = new File(base, includedFile);
+                    foundLocation = found.getAbsolutePath();
+                }
+            }
+        }
+        if (foundLocation != null)
+            getProject().setNewProperty(location, foundLocation);
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/02-fileset/src/FindTest.java b/src/tutorial/tasks-filesets-properties/02-fileset/src/FindTest.java
new file mode 100644
index 0000000..f85a787
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/02-fileset/src/FindTest.java
@@ -0,0 +1,84 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class FindTest {
+
+    @Rule
+    public BuildFileRule rule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException tried = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        rule.configureProject("build.xml");
+    }
+
+    @Test
+    public void testMissingFile() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("file not set");
+        Find find = new Find();
+        find.execute();
+    }
+
+    @Test
+    public void testMissingLocation() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("location not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.execute();
+    }
+
+    @Test
+    public void testMissingFileset() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("fileset not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.setLocation("location.ant-jar");
+        find.execute();
+    }
+
+    @Test
+    public void testFileNotPresent() {
+        rule.executeTarget("testFileNotPresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNull("Property set to wrong value.", result);
+    }
+
+    @Test
+    public void testFilePresent() {
+        rule.executeTarget("testFilePresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNotNull("Property not set.", result);
+        assertTrue("Wrong file found.", result.endsWith("ant.jar"));
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/03-paths/build.xml b/src/tutorial/tasks-filesets-properties/03-paths/build.xml
new file mode 100644
index 0000000..b602c19
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/03-paths/build.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="FindTask" basedir="." default="test">
+
+    <property name="src.dir"     value="src"/>
+    <property name="classes.dir" value="classes"/>
+
+    <property name="ant.test.lib" value="ant-testutil.jar"/>
+    <property name="report.dir"   value="report"/>
+    <property name="junit.out.dir.xml"  value="${report.dir}/junit/xml"/>
+    <property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
+
+    <path id="classpath.run">
+        <path path="${java.class.path}"/>
+        <path location="${ant.project.name}.jar"/>
+    </path>
+
+    <path id="classpath.test">
+        <path refid="classpath.run"/>
+        <path location="${ant.test.lib}"/>
+    </path>
+
+    <target name="clean" description="Delete all generated files">
+        <delete failonerror="false" includeEmptyDirs="true">
+            <fileset dir="." includes="${ant.project.name}.jar"/>
+            <fileset dir="${classes.dir}"/>
+            <fileset dir="${report.dir}"/>
+        </delete>
+    </target>
+
+    <target name="compile" description="Compiles the Task">
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpath="${ant.test.lib}"/>
+    </target>
+
+    <target name="jar" description="JARs the Task" depends="compile">
+        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
+    </target>
+
+    <target name="use.init" description="Taskdef the Find-Task" depends="jar">
+        <taskdef name="find" classname="Find" classpath="${ant.project.name}.jar"/>
+    </target>
+
+    <target name="use.simple" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+        <echo>ant.jar found on ${location.ant-jar}</echo>
+    </target>
+
+    <target name="testFileNotPresent" depends="use.init">
+        <find file="a-not-existing-file.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+    </target>
+
+    <target name="testFilePresent" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+    </target>
+
+    <target name="junit" description="Runs the unit tests" depends="jar">
+        <delete dir="${junit.out.dir.xml}" />
+        <mkdir  dir="${junit.out.dir.xml}" />
+        <junit printsummary="yes" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="xml"/>
+            <batchtest fork="yes" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport" description="Create a report for the rest result">
+        <mkdir dir="${junit.out.dir.html}" />
+        <junitreport todir="${junit.out.dir.html}">
+            <fileset dir="${junit.out.dir.xml}">
+                <include name="*.xml"/>
+            </fileset>
+            <report format="frames" todir="${junit.out.dir.html}"/>
+        </junitreport>
+    </target>
+
+    <target name="test" depends="jar">
+        <junit printsummary="no" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="brief" usefile="false"/>
+            <batchtest fork="true" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test2"
+            depends="junit,junitreport"
+            description="Runs unit tests and creates a report"/>
+
+</project>
diff --git a/src/tutorial/tasks-filesets-properties/03-paths/src/Find.java b/src/tutorial/tasks-filesets-properties/03-paths/src/Find.java
new file mode 100644
index 0000000..c41a39c
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/03-paths/src/Find.java
@@ -0,0 +1,65 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Path;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Find extends Task {
+
+    private String file;
+    private String location;
+    private List<Path> paths = new ArrayList<>();
+
+    public void setFile(String file) {
+        this.file = file;
+    }
+
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    public void addPath(Path path) {
+        paths.add(path);
+    }
+
+    protected void validate() {
+        if (file == null) throw new BuildException("file not set");
+        if (location == null) throw new BuildException("location not set");
+        if (paths.size() < 1) throw new BuildException("path not set");
+    }
+
+    public void execute() {
+        validate();
+        String foundLocation = null;
+        for (Path path : paths) {
+            for (String includedFile : path.list()) {
+                String filename = includedFile.replace('\\','/');
+                filename = filename.substring(filename.lastIndexOf("/") + 1);
+                if (foundLocation == null && file.equals(filename)) {
+                    foundLocation = includedFiles[i];
+                }
+            }
+        }
+        if (foundLocation != null)
+            getProject().setNewProperty(location, foundLocation);
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/03-paths/src/FindTest.java b/src/tutorial/tasks-filesets-properties/03-paths/src/FindTest.java
new file mode 100644
index 0000000..21518b8
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/03-paths/src/FindTest.java
@@ -0,0 +1,84 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class FindTest {
+
+    @Rule
+    public BuildFileRule rule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException tried = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        rule.configureProject("build.xml");
+    }
+
+    @Test
+    public void testMissingFile() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("file not set");
+        Find find = new Find();
+        find.execute();
+    }
+
+    @Test
+    public void testMissingLocation() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("location not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.execute();
+    }
+
+    @Test
+    public void testMissingPath() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("path not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.setLocation("location.ant-jar");
+        find.execute();
+    }
+
+    @Test
+    public void testFileNotPresent() {
+        rule.executeTarget("testFileNotPresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNull("Property set to wrong value.", result);
+    }
+
+    @Test
+    public void testFilePresent() {
+        rule.executeTarget("testFilePresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNotNull("Property not set.", result);
+        assertTrue("Wrong file found.", result.endsWith("ant.jar"));
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/04-lists/build.xml b/src/tutorial/tasks-filesets-properties/04-lists/build.xml
new file mode 100644
index 0000000..a3fb038
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/04-lists/build.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="FindTask" basedir="." default="test">
+
+    <property name="src.dir"     value="src"/>
+    <property name="classes.dir" value="classes"/>
+
+    <property name="ant.test.lib" value="ant-testutil.jar"/>
+    <property name="report.dir"   value="report"/>
+    <property name="junit.out.dir.xml"  value="${report.dir}/junit/xml"/>
+    <property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
+
+    <path id="classpath.run">
+        <path path="${java.class.path}"/>
+        <path location="${ant.project.name}.jar"/>
+    </path>
+
+    <path id="classpath.test">
+        <path refid="classpath.run"/>
+        <path location="${ant.test.lib}"/>
+    </path>
+
+    <target name="clean" description="Delete all generated files">
+        <delete failonerror="false" includeEmptyDirs="true">
+            <fileset dir="." includes="${ant.project.name}.jar"/>
+            <fileset dir="${classes.dir}"/>
+            <fileset dir="${report.dir}"/>
+        </delete>
+    </target>
+
+    <target name="compile" description="Compiles the Task">
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpath="${ant.test.lib}"/>
+    </target>
+
+    <target name="jar" description="JARs the Task" depends="compile">
+        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
+    </target>
+
+    <target name="use.init" description="Taskdef the Find-Task" depends="jar">
+        <taskdef name="find" classname="Find" classpath="${ant.project.name}.jar"/>
+    </target>
+
+    <target name="use.simple" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+                <fileset dir="c:/seu" includes="ant*/**/*.jar"/>
+            </path>
+        </find>
+        <echo>ant.jar found on ${location.ant-jar}</echo>
+    </target>
+
+    <target name="use.simple2" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar" delimiter=";">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+                <fileset dir="c:/seu" includes="ant*/**/*.jar"/>
+            </path>
+        </find>
+        <echo>ant.jar found on ${location.ant-jar}</echo>
+    </target>
+
+    <target name="testFileNotPresent" depends="use.init">
+        <find file="a-not-existing-file.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+    </target>
+
+    <target name="testFilePresent" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+    </target>
+
+    <target name="test.init">
+        <mkdir dir="test1/dir11/dir111"/>
+        <mkdir dir="test1/dir11/dir112"/>
+        <mkdir dir="test1/dir12/"/>
+        <mkdir dir="test1/dir13/dir131"/>
+        <mkdir dir="test1/dir13/dir132"/>
+        <touch file="test1/dir11/dir111/test"/>
+        <touch file="test1/dir11/dir111/not"/>
+        <touch file="test1/dir11/dir111/not2"/>
+        <touch file="test1/dir11/dir112/test"/>
+        <touch file="test1/dir11/dir112/not"/>
+        <touch file="test1/dir11/dir112/not2"/>
+        <touch file="test1/dir12/test"/>
+        <touch file="test1/dir12/not"/>
+        <touch file="test1/dir12/not2"/>
+        <touch file="test1/dir13/dir131/test"/>
+        <touch file="test1/dir13/dir131/not"/>
+        <touch file="test1/dir13/dir131/not2"/>
+        <touch file="test1/dir13/dir132/test"/>
+        <touch file="test1/dir13/dir132/not"/>
+        <touch file="test1/dir13/dir132/not2"/>
+        <mkdir dir="test2"/>
+        <copy todir="test2">
+            <fileset dir="test1"/>
+        </copy>
+    </target>
+
+    <target name="testMultipleFiles" depends="use.init,test.init">
+        <touch file="test1/dir11/dir111/test"/>
+        <find file="test" location="location.test" delimiter=";">
+            <path>
+                <fileset dir="test1"/>
+                <fileset dir="test2"/>
+            </path>
+        </find>
+        <delete>
+            <fileset dir="test1"/>
+            <fileset dir="test2"/>
+        </delete>
+    </target>
+
+    <target name="junit" description="Runs the unit tests" depends="jar">
+        <delete dir="${junit.out.dir.xml}" />
+        <mkdir  dir="${junit.out.dir.xml}" />
+        <junit printsummary="yes" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="xml"/>
+            <batchtest fork="yes" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport" description="Create a report for the rest result">
+        <mkdir dir="${junit.out.dir.html}" />
+        <junitreport todir="${junit.out.dir.html}">
+            <fileset dir="${junit.out.dir.xml}">
+                <include name="*.xml"/>
+            </fileset>
+            <report format="frames" todir="${junit.out.dir.html}"/>
+        </junitreport>
+    </target>
+
+    <target name="test" depends="jar">
+        <junit printsummary="no" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="brief" usefile="false"/>
+            <batchtest fork="true" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test2"
+            depends="junit,junitreport"
+            description="Runs unit tests and creates a report"/>
+
+</project>
diff --git a/src/tutorial/tasks-filesets-properties/04-lists/src/Find.java b/src/tutorial/tasks-filesets-properties/04-lists/src/Find.java
new file mode 100644
index 0000000..0689e98
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/04-lists/src/Find.java
@@ -0,0 +1,96 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Path;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Find extends Task {
+
+    // =====  internal attributes  =====
+
+    private List<String> foundFiles = new ArrayList<>();
+
+    // =====  attribute support  =====
+
+    private String file;
+    private String location;
+    private List<Path> paths = new ArrayList<>();
+    private String delimiter = null;
+
+    public void setFile(String file) {
+        this.file = file;
+    }
+
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    public void addPath(Path path) {
+        paths.add(path);
+    }
+
+    public void setDelimiter(String delim) {
+        delimiter = delim;
+    }
+
+    // =====  the tasks work  =====
+
+    protected void validate() {
+        if (file == null) throw new BuildException("file not set");
+        if (location == null) throw new BuildException("location not set");
+        if (paths.isEmpty()) throw new BuildException("path not set");
+    }
+
+    public void execute() {
+        validate();
+        for (Path path : paths) {
+            for (String includedFile : path.list()) {
+                String filename = includedFile.replace('\\','/');
+                filename = filename.substring(filename.lastIndexOf("/") + 1);
+                if (file.equals(filename) && !foundFiles.contains(includedFile)) {
+                    foundFiles.add(includedFile);
+                }
+            }
+        }
+        String rv = null;
+        if (!foundFiles.isEmpty()) {
+            if (delimiter == null) {
+                // only the first
+                rv = foundFiles.get(0);
+            } else {
+                // create list
+                StringBuilder list = new StringBuilder();
+                for (String file : foundFiles) {
+                    if (list.length() > 0) {
+                        list.append(delimiter);
+                    }
+                    list.append(file);
+                }
+                rv = list.toString();
+            }
+        }
+
+
+        if (rv != null)
+            getProject().setNewProperty(location, rv);
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/04-lists/src/FindTest.java b/src/tutorial/tasks-filesets-properties/04-lists/src/FindTest.java
new file mode 100644
index 0000000..a149490
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/04-lists/src/FindTest.java
@@ -0,0 +1,92 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class FindTest {
+
+    @Rule
+    public BuildFileRule rule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException tried = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        rule.configureProject("build.xml");
+    }
+
+    @Test
+    public void testMissingFile() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("file not set");
+        Find find = new Find();
+        find.execute();
+    }
+
+    @Test
+    public void testMissingLocation() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("location not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.execute();
+    }
+
+    @Test
+    public void testMissingPath() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("path not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.setLocation("location.ant-jar");
+        find.execute();
+    }
+
+    @Test
+    public void testFileNotPresent() {
+        rule.executeTarget("testFileNotPresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNull("Property set to wrong value.", result);
+    }
+
+    public void testFilePresent() {
+        rule.executeTarget("testFilePresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNotNull("Property not set.", result);
+        assertTrue("Wrong file found.", result.endsWith("ant.jar"));
+    }
+
+
+    public void testMultipleFiles() {
+        rule.executeTarget("testMultipleFiles");
+        String result = rule.getProject().getProperty("location.test");
+        assertNotNull("Property not set.", result);
+        assertTrue("Only one file found.", result.contains(";"));
+        //assertTrue("Wrong file found.", result.endsWith("ant.jar"));
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/final/build.xml b/src/tutorial/tasks-filesets-properties/final/build.xml
new file mode 100644
index 0000000..8e6d795
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/final/build.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="FindTask" basedir="." default="test">
+
+    <property name="src.dir"     value="src"/>
+    <property name="classes.dir" value="classes"/>
+
+    <property name="ant.test.lib" value="ant-testutil.jar"/>
+    <property name="report.dir"   value="report"/>
+    <property name="junit.out.dir.xml"  value="${report.dir}/junit/xml"/>
+    <property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
+
+    <path id="classpath.run">
+        <path path="${java.class.path}"/>
+        <path location="${ant.project.name}.jar"/>
+    </path>
+
+    <path id="classpath.test">
+        <path refid="classpath.run"/>
+        <path location="${ant.test.lib}"/>
+    </path>
+
+    <target name="clean" description="Delete all generated files">
+        <delete failonerror="false" includeEmptyDirs="true">
+            <fileset dir="." includes="${ant.project.name}.jar"/>
+            <fileset dir="${classes.dir}"/>
+            <fileset dir="${report.dir}"/>
+        </delete>
+    </target>
+
+    <target name="compile" description="Compiles the Task">
+        <mkdir dir="${classes.dir}"/>
+        <javac includeantruntime="true" srcdir="${src.dir}" destdir="${classes.dir}" classpath="${ant.test.lib}"/>
+    </target>
+
+    <target name="jar" description="JARs the Task" depends="compile">
+        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
+    </target>
+
+    <target name="use.init" description="Taskdef the Find-Task" depends="jar">
+        <taskdef name="find" classname="Find" classpath="${ant.project.name}.jar"/>
+    </target>
+
+    <target name="use.simple" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+                <fileset dir="c:/seu" includes="ant*/**/*.jar"/>
+            </path>
+        </find>
+        <echo>ant.jar found on ${location.ant-jar}</echo>
+    </target>
+
+    <target name="use.simple2" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar" delimiter=";">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+                <fileset dir="c:/seu" includes="ant*/**/*.jar"/>
+            </path>
+        </find>
+        <echo>ant.jar found on ${location.ant-jar}</echo>
+    </target>
+
+    <target name="testFileNotPresent" depends="use.init">
+        <find file="a-not-existing-file.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+    </target>
+
+    <target name="testFilePresent" depends="use.init">
+        <find file="ant.jar" location="location.ant-jar">
+            <path>
+                <fileset dir="${ant.home}" includes="**/*.jar"/>
+            </path>
+        </find>
+    </target>
+
+    <target name="test.init">
+        <mkdir dir="test1/dir11/dir111"/>
+        <mkdir dir="test1/dir11/dir112"/>
+        <mkdir dir="test1/dir12/"/>
+        <mkdir dir="test1/dir13/dir131"/>
+        <mkdir dir="test1/dir13/dir132"/>
+        <touch file="test1/dir11/dir111/test"/>
+        <touch file="test1/dir11/dir111/not"/>
+        <touch file="test1/dir11/dir111/not2"/>
+        <touch file="test1/dir11/dir112/test"/>
+        <touch file="test1/dir11/dir112/not"/>
+        <touch file="test1/dir11/dir112/not2"/>
+        <touch file="test1/dir12/test"/>
+        <touch file="test1/dir12/not"/>
+        <touch file="test1/dir12/not2"/>
+        <touch file="test1/dir13/dir131/test"/>
+        <touch file="test1/dir13/dir131/not"/>
+        <touch file="test1/dir13/dir131/not2"/>
+        <touch file="test1/dir13/dir132/test"/>
+        <touch file="test1/dir13/dir132/not"/>
+        <touch file="test1/dir13/dir132/not2"/>
+        <mkdir dir="test2"/>
+        <copy todir="test2">
+            <fileset dir="test1"/>
+        </copy>
+    </target>
+
+    <target name="testMultipleFiles" depends="use.init,test.init">
+        <touch file="test1/dir11/dir111/test"/>
+        <find file="test" location="location.test" delimiter=";">
+            <path>
+                <fileset dir="test1"/>
+                <fileset dir="test2"/>
+            </path>
+        </find>
+        <delete>
+            <fileset dir="test1"/>
+            <fileset dir="test2"/>
+        </delete>
+    </target>
+
+    <target name="junit" description="Runs the unit tests" depends="jar">
+        <delete dir="${junit.out.dir.xml}" />
+        <mkdir  dir="${junit.out.dir.xml}" />
+        <junit printsummary="yes" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="xml"/>
+            <batchtest fork="yes" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport" description="Create a report for the rest result">
+        <mkdir dir="${junit.out.dir.html}" />
+        <junitreport todir="${junit.out.dir.html}">
+            <fileset dir="${junit.out.dir.xml}">
+                <include name="*.xml"/>
+            </fileset>
+            <report format="frames" todir="${junit.out.dir.html}"/>
+        </junitreport>
+    </target>
+
+    <target name="test" depends="jar">
+        <junit printsummary="no" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <sysproperty key="ant.home" value="${ant.home}"/>
+            <formatter type="brief" usefile="false"/>
+            <batchtest fork="true" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="test2"
+            depends="junit,junitreport"
+            description="Runs unit tests and creates a report"/>
+
+</project>
diff --git a/src/tutorial/tasks-filesets-properties/final/find.html b/src/tutorial/tasks-filesets-properties/final/find.html
new file mode 100644
index 0000000..607123a
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/final/find.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+   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
+
+       https://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">
+
+<head>
+<title> Find Task</title>
+</head>
+
+<body>
+
+<h2 id="find">Find</h2>
+<h3>Description</h3>
+<p>Searches in a given path for a file and returns the absolute to it as property.
+If delimiter is set this task returns all found locations.</p>
+
+<h3>Parameters</h3>
+<table class="attr">
+  <tr>
+    <th scope="col">Attribute</th>
+    <th scope="col">Description</th>
+    <th scope="col">Required</th>
+  </tr>
+  <tr>
+    <td>file</td>
+    <td>The name of the file to search.</td>
+    <td>yes</td>
+  </tr>
+  <tr>
+    <td>location</td>
+    <td>The name of the property where to store the location</td>
+    <td>yes</td>
+  </tr>
+  <tr>
+    <td>delimiter</td>
+    <td>A delimiter to use when returning the list</td>
+    <td>only if the list is required</td>
+  </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+
+<h4>path</h4>
+<p>The path where to search the file.</p>
+
+<h3>Examples</h3>
+<pre>
+    &lt;find file="ant.jar" location="loc">
+        &lt;path>
+            &lt;fileset dir="${ant.home}"/>
+        &lt;path>
+    &lt;/find>
+</pre>
+Searches in Ant home directory for a file <samp>ant.jar</samp> and stores its location in
+property <samp>loc</samp> (should be <samp>ANT_HOME/bin/ant.jar</samp>).
+
+<pre>
+    &lt;find file="ant.jar" location="loc" delimiter=";">
+        &lt;path>
+            &lt;fileset dir="C:/"/>
+        &lt;path>
+    &lt;/find>
+    &lt;echo>ant.jar found in: ${loc}&lt;/echo>
+</pre>
+Searches in Windows <samp>C:</samp> drive for all <samp>ant.jar</samp> and stores their locations in
+property <samp>loc</samp> delimited with <q>;</q>. (should need a long time :-)
+After that it prints out the result (e.g. <samp>C:/ant-1.5.4/bin/ant.jar;C:/ant-1.6/bin/ant.jar</samp>).
+
+</body>
+</html>
diff --git a/src/tutorial/tasks-filesets-properties/final/src/Find.java b/src/tutorial/tasks-filesets-properties/final/src/Find.java
new file mode 100644
index 0000000..c1f1cf7
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/final/src/Find.java
@@ -0,0 +1,101 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Find extends Task {
+
+    // =====  internal attributes  =====
+
+    private List<String> foundFiles = new ArrayList<>();
+
+    // =====  attribute support  =====
+
+    private String file;
+    private String location;
+    private List<Path> paths = new ArrayList<>();
+    private String delimiter = null;
+
+    public void setFile(String file) {
+        this.file = file;
+    }
+
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    public void addPath(Path path) {
+        paths.add(path);
+    }
+
+    public void setDelimiter(String delim) {
+        delimiter = delim;
+    }
+
+    // =====  the tasks work  =====
+
+    protected void validate() {
+        if (file == null) throw new BuildException("file not set");
+        if (location == null) throw new BuildException("location not set");
+        if (paths.isEmpty()) throw new BuildException("path not set");
+    }
+
+    public void execute() {
+        validate();
+        // find all files
+        for (Path path : paths) {
+            for (String includedFile : path.list()) {
+                String filename = includedFile.replace('\\', '/');
+                filename = filename.substring(filename.lastIndexOf("/") + 1);
+                if (file.equals(filename) && !foundFiles.contains(includedFile)) {
+                    foundFiles.add(includedFile);
+                }
+            }
+        }
+
+        // create the return value (list/single)
+        String rv = null;
+        if (!foundFiles.isEmpty()) {
+            if (delimiter == null) {
+                // only the first
+                rv = foundFiles.get(0);
+            } else {
+                // create list
+                StringBuilder list = new StringBuilder();
+                for (String file : foundFiles) {
+                    if (list.length() > 0) {
+                        list.append(delimiter);
+                    }
+                    list.append(file);
+                }
+                rv = list.toString();
+            }
+        }
+
+        // create the property
+        if (rv != null)
+            getProject().setNewProperty(location, rv);
+    }
+
+}
diff --git a/src/tutorial/tasks-filesets-properties/final/src/FindTest.java b/src/tutorial/tasks-filesets-properties/final/src/FindTest.java
new file mode 100644
index 0000000..d9e2e9c
--- /dev/null
+++ b/src/tutorial/tasks-filesets-properties/final/src/FindTest.java
@@ -0,0 +1,95 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class FindTest {
+
+    @Rule
+    public BuildFileRule rule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException tried = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        rule.configureProject("build.xml");
+    }
+
+    @Test
+    public void testMissingFile() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("file not set");
+        Find find = new Find();
+        find.execute();
+    }
+
+    @Test
+    public void testMissingLocation() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("location not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.execute();
+    }
+
+    @Test
+    public void testMissingPath() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("path not set");
+        Find find = new Find();
+        find.setFile("ant.jar");
+        find.setLocation("location.ant-jar");
+        find.execute();
+    }
+
+    @Test
+    public void testFileNotPresent() {
+        rule.executeTarget("testFileNotPresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNull("Property set to wrong value.", result);
+    }
+
+    @Test
+    public void testFilePresent() {
+        rule.executeTarget("testFilePresent");
+        String result = rule.getProject().getProperty("location.ant-jar");
+        assertNotNull("Property not set.", result);
+        assertTrue("Wrong file found.", result.endsWith("ant.jar"));
+    }
+
+    @Test
+    public void testMultipleFiles() {
+        rule.executeTarget("testMultipleFiles");
+        String result = rule.getProject().getProperty("location.test");
+        assertNotNull("Property not set.", result);
+        assertTrue("Only one file found.", result.contains(";"));
+    }
+
+}
diff --git a/src/tutorial/tasks-start-writing/build.xml b/src/tutorial/tasks-start-writing/build.xml
new file mode 100644
index 0000000..b068b02
--- /dev/null
+++ b/src/tutorial/tasks-start-writing/build.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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
+
+       https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project name="MyTask" basedir="." default="test">
+
+    <property name="src.dir"     value="src"/>
+    <property name="classes.dir" value="classes"/>
+
+    <property name="ant.test.lib" value="ant-testutil.jar"/>
+    <property name="report.dir"   value="report"/>
+    <property name="junit.out.dir.xml"  value="${report.dir}/junit/xml"/>
+    <property name="junit.out.dir.html" value="${report.dir}/junit/html"/>
+
+    <path id="classpath.run">
+        <path path="${java.class.path}"/>
+        <path location="${ant.project.name}.jar"/>
+    </path>
+
+    <path id="classpath.test">
+        <path refid="classpath.run"/>
+        <path location="${ant.test.lib}"/>
+    </path>
+
+    <target name="clean" description="Delete all generated files">
+        <delete failonerror="false" includeEmptyDirs="true">
+            <fileset dir="." includes="${ant.project.name}.jar"/>
+            <fileset dir="${classes.dir}"/>
+            <fileset dir="${report.dir}"/>
+        </delete>
+    </target>
+
+    <target name="compile" description="Compiles the Task">
+        <mkdir dir="${classes.dir}"/>
+        <javac includeantruntime="true" srcdir="${src.dir}" destdir="${classes.dir}" classpath="${ant.test.lib}"/>
+    </target>
+
+    <target name="jar" description="JARs the Task" depends="compile">
+        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
+    </target>
+
+
+    <target name="use.init" description="Taskdef the HelloWorld-Task" depends="jar">
+        <taskdef name="helloworld" classname="HelloWorld" classpath="${ant.project.name}.jar"/>
+    </target>
+
+
+    <target name="use.without" description="Use without any" depends="use.init">
+        <helloworld/>
+    </target>
+
+    <target name="use.message" description="Use with attribute 'message'" depends="use.init">
+        <helloworld message="attribute-text"/>
+    </target>
+
+    <target name="use.fail" description="Use with attribute 'fail'" depends="use.init">
+        <helloworld fail="true"/>
+    </target>
+
+    <target name="use.nestedText" description="Use with nested text" depends="use.init">
+        <helloworld>nested-text</helloworld>
+    </target>
+
+    <target name="use.nestedElement" description="Use with nested 'message'" depends="use.init">
+        <helloworld>
+            <message msg="Nested Element 1"/>
+            <message msg="Nested Element 2"/>
+        </helloworld>
+    </target>
+
+
+    <target name="use"
+            description="Try all (w/out use.fail)"
+            depends="use.without,use.message,use.nestedText,use.nestedElement"/>
+
+
+    <target name="junit" description="Runs the unit tests" depends="jar">
+        <delete dir="${junit.out.dir.xml}" />
+        <mkdir  dir="${junit.out.dir.xml}" />
+        <junit printsummary="yes" haltonfailure="no">
+            <classpath refid="classpath.test"/>
+            <formatter type="xml"/>
+            <batchtest fork="yes" todir="${junit.out.dir.xml}">
+                <fileset dir="${src.dir}" includes="**/*Test.java"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junitreport" description="Create a report for the rest result">
+        <mkdir dir="${junit.out.dir.html}" />
+        <junitreport todir="${junit.out.dir.html}">
+            <fileset dir="${junit.out.dir.xml}">
+                <include name="*.xml"/>
+            </fileset>
+            <report format="frames" todir="${junit.out.dir.html}"/>
+        </junitreport>
+    </target>
+
+    <target name="test"
+            depends="junit,junitreport"
+            description="Runs unit tests and creates a report"/>
+
+</project>
diff --git a/src/tutorial/tasks-start-writing/src/HelloWorld.java b/src/tutorial/tasks-start-writing/src/HelloWorld.java
new file mode 100644
index 0000000..1b7df5d
--- /dev/null
+++ b/src/tutorial/tasks-start-writing/src/HelloWorld.java
@@ -0,0 +1,87 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The task of the tutorial.
+ * Prints a message or lets the build fail.
+ * @author Jan Matérne
+ * @since 2003-08-19
+ */
+public class HelloWorld extends Task {
+
+
+    /** The message to print. As attribute. */
+    String message;
+    public void setMessage(String msg) {
+        message = msg;
+    }
+
+    /** Should the build fail? Defaults to <i>false</i>. As attribute. */
+    boolean fail = false;
+    public void setFail(boolean b) {
+        fail = b;
+    }
+
+    /** Support for nested text. */
+    public void addText(String text) {
+        message = text;
+    }
+
+
+    /** Do the work. */
+    public void execute() {
+        // handle attribute 'fail'
+        if (fail) throw new BuildException("Fail requested.");
+
+        // handle attribute 'message' and nested text
+        if (message != null) log(message);
+
+        // handle nested elements
+        for (Message msg : messages) {
+            log(msg.getMsg());
+        }
+    }
+
+
+    /** Store nested 'message's. */
+    List<Message> messages = new ArrayList<>();
+
+    /** Factory method for creating nested 'message's. */
+    public Message createMessage() {
+        Message msg = new Message();
+        messages.add(msg);
+        return msg;
+    }
+
+    /** A nested 'message'. */
+    public class Message {
+        // Bean constructor
+        public Message() {}
+
+        /** Message to print. */
+        String msg;
+        public void setMsg(String msg) { this.msg = msg; }
+        public String getMsg() { return msg; }
+    }
+
+}
diff --git a/src/tutorial/tasks-start-writing/src/HelloWorldTest.java b/src/tutorial/tasks-start-writing/src/HelloWorldTest.java
new file mode 100644
index 0000000..1ddbb22
--- /dev/null
+++ b/src/tutorial/tasks-start-writing/src/HelloWorldTest.java
@@ -0,0 +1,77 @@
+/*
+ *  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
+ *
+ *      https://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 org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class HelloWorldTest {
+
+    @Rule
+    public BuildFileRule rule = new BuildFileRule();
+
+    @Rule
+    public ExpectedException tried = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        // initialize Ant
+        rule.configureProject("build.xml");
+    }
+
+    @Test
+    public void testWithout() {
+        rule.executeTarget("use.without");
+        assertEquals("Message was logged but should not.", "", rule.getLog());
+    }
+
+    @Test
+    public void testMessage() {
+        // execute target 'use.nestedText' and expect a message
+        // 'attribute-text' in the log
+        rule.executeTarget("use.message");
+        assertEquals(rule.getLog(), "attribute-text");
+    }
+
+    @Test
+    public void testFail() {
+        tried.expect(BuildException.class);
+        tried.expectMessage("Fail requested.");
+        // execute target 'use.fail' and expect a BuildException
+        // with text 'Fail requested.'
+        rule.executeTarget("use.fail");
+    }
+
+    @Test
+    public void testNestedText() {
+        rule.executeTarget("use.nestedText");
+        assertEquals("nested-text", rule.getLog());
+    }
+
+    @Test
+    public void testNestedElement() {
+        rule.executeTarget("use.nestedElement");
+        assertTrue(rule.getLog().contains("Nested Element 1"));
+        assertTrue(rule.getLog().contains("Nested Element 2"));
+    }
+}
diff --git a/test-compatibility.sh b/test-compatibility.sh
new file mode 100755
index 0000000..79d4eec
--- /dev/null
+++ b/test-compatibility.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# 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
+#
+#     https://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.
+
+# Compiles and builds Ant with various different recent versions of Java and
+# then runs (only the) tests with the minimal supported version of Java runtime
+# (which as of Aug 2019, is Java 8).
+# This ensures/verifies that various Ant functionality works as expected
+# when Ant is built with a higher version of Java and is run against the minimal
+# supported version.
+# This script is ideal for using in a CI environment where it can be invoked
+# through a job which is configured to use various different JDK versions.
+
+# Fail the script on error
+set -e
+
+# Build (compile and generate the dist) the project using the Java version
+# that's already set in the environment
+echo "Using  \"${JAVA_HOME}\" to build Ant"
+java -version
+
+# Fetch all the necessary thirdparty libs, before boostraping Ant
+ant -f fetch.xml -Ddest=optional
+
+# Now bootstrap Ant with all necessary thirdparty libs already fetched
+./build.sh allclean dist
+
+# Switch the JDK to Java 8 to run *only* the tests.
+# This will ensure that Ant built with different (higher) version of Ant
+# can be used by Java 8 runtime and can function properly for all Ant
+# functionality
+mkdir -p build/java-8-latest
+cd build/java-8-latest
+# Download latest Java 8 (we use Adopt OpenJDK binaries)
+wget https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u232-b09/OpenJDK8U-jdk_x64_linux_hotspot_8u232b09.tar.gz
+tar -zxf ./*.tar.gz
+# set JAVA_HOME to point to the newly extracted tar's content
+export JAVA_HOME="`echo \`pwd\`/\`echo */\``"
+export PATH="${JAVA_HOME}"/bin:"${PATH}"
+cd ../..
+
+echo "Using \"${JAVA_HOME}\" to run Ant tests"
+java -version
+
+# Set ANT_HOME to the boostraped version - the one which was built, using a different Java version, a few steps
+# earlier in this script
+export ANT_HOME="`pwd`/bootstrap"
+# Run the tests. We intentionally skip the build (compilation etc) to avoid compiling the project
+# with the newly set Java version.
+ant -nouserlib -lib lib/optional test -Dskip.build=true -Dignore.tests.failed=true -Doptional.jars.whenmanifestonly=skip -Djenkins=t
+